FAILURE MAP
← Case archive

FA-82291 / Poker hand evaluation / Open access

Small pairs score below the pair floor · case 01

Pocket deuces score 2 instead of 5.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The doubled pair score is not raised to the minimum of 5.

THE FAILURE

The doubled pair score is not raised to the minimum of 5.

Unsuccessful approach: Applying the minimum before doubling makes every small pair worth 10.

Case contract

Input: two hole cards. Chen score: highest card points A=10, K=8, Q=7, J=6, else half its rank (2..10). Pairs double the points with a minimum of 5. Suited adds 2. Gap between ranks (cards strictly between) subtracts 0, 1, 2, 4 for gaps 0-3 and 5 for 4+. Add 1 for gap 0 or 1 when both cards are below a queen. Round the final score up.

Why this case matters

Starting-hand heuristics in training tools and bots use this scoring.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    R='23456789TJQKA'
    pts={14:10,13:8,12:7,11:6}
    a,b=sorted((R.index(c[0])+2 for c in x), reverse=True)
    s=pts.get(a, a/2)
    if a==b:
        s=s*2
    else:
        if x[0][1]==x[1][1]: s+=2
        gap=a-b-1
        s-={0:0,1:1,2:2,3:4}.get(gap,5)
        if gap<=1 and a<12: s+=1
    return math.ceil(s)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('pocket aces', ['Ah', 'Ad'], 20), ('pocket deuces', ['2h', '2d'], 5),
  ('pocket fives', ['5h', '5d'], 5), ('ace king suited', ['Ah', 'Kh'], 12),
  ('seven six suited', ['7h', '6h'], 7), ('nine seven offsuit', ['9h', '7d'], 5),
  ('queen jack suited', ['Qs', 'Js'], 9), ('ace five offsuit', ['Ah', '5d'], 5)],
 [('pocket deuces', ['2h', '2d'], 5), ('pocket fives', ['5h', '5d'], 5),
  ('nine seven offsuit', ['9h', '7d'], 5), ('queen jack suited', ['Qs', 'Js'], 9),
  ('ace five offsuit', ['Ah', '5d'], 5), ('king nine suited', ['Kc', '9c'], 6),
  ('ten nine offsuit', ['Th', '9d'], 6), ('pocket sevens', ['7h', '7s'], 7)],
 [('pocket deuces', ['2h', '2d'], 5), ('king nine suited', ['Kc', '9c'], 6),
  ('ten nine offsuit', ['Th', '9d'], 6), ('jack ten suited', ['Js', 'Ts'], 9),
  ('nine five offsuit', ['9c', '5d'], 1), ('pocket sevens', ['7h', '7s'], 7),
  ('eight six suited', ['8d', '6d'], 6), ('jack nine offsuit', ['Jh', '9c'], 6)],
 [('pocket aces', ['Ah', 'Ad'], 20), ('pocket deuces', ['2h', '2d'], 5),
  ('pocket fives', ['5h', '5d'], 5), ('ace king suited', ['Ah', 'Kh'], 12),
  ('nine five offsuit', ['9c', '5d'], 1), ('pocket sevens', ['7h', '7s'], 7),
  ('eight six suited', ['8d', '6d'], 6), ('jack nine offsuit', ['Jh', '9c'], 6)],
 [('pocket aces', ['Ah', 'Ad'], 20), ('pocket deuces', ['2h', '2d'], 5),
  ('pocket fives', ['5h', '5d'], 5), ('ace king suited', ['Ah', 'Kh'], 12),
  ('seven six suited', ['7h', '6h'], 7), ('nine seven offsuit', ['9h', '7d'], 5),
  ('queen jack suited', ['Qs', 'Js'], 9), ('pocket sevens', ['7h', '7s'], 7)]]
for label, args, expected in fixtures[N-1]:
    try:
        actual = solve(args)
    except Exception as exc:
        actual = 'error:' + type(exc).__name__
    check(label, actual, expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
pocket aces2020Passed
pocket deuces25Failed
pocket fives55Passed
ace king suited1212Passed
seven six suited77Passed
nine seven offsuit55Passed
queen jack suited99Passed
ace five offsuit55Passed

SHA-256 / 1b273c31f4b2d8e730f1ba907e89a7d1282eb16e373926acade61b12bcaa3143

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    R='23456789TJQKA'
    pts={14:10,13:8,12:7,11:6}
    a,b=sorted((R.index(c[0])+2 for c in x), reverse=True)
    s=pts.get(a, a/2)
    if a==b:
        s=max(s,5)*2
    else:
        if x[0][1]==x[1][1]: s+=2
        gap=a-b-1
        s-={0:0,1:1,2:2,3:4}.get(gap,5)
        if gap<=1 and a<12: s+=1
    return math.ceil(s)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('pocket aces', ['Ah', 'Ad'], 20), ('pocket deuces', ['2h', '2d'], 5),
  ('pocket fives', ['5h', '5d'], 5), ('ace king suited', ['Ah', 'Kh'], 12),
  ('seven six suited', ['7h', '6h'], 7), ('nine seven offsuit', ['9h', '7d'], 5),
  ('queen jack suited', ['Qs', 'Js'], 9), ('ace five offsuit', ['Ah', '5d'], 5)],
 [('pocket deuces', ['2h', '2d'], 5), ('pocket fives', ['5h', '5d'], 5),
  ('nine seven offsuit', ['9h', '7d'], 5), ('queen jack suited', ['Qs', 'Js'], 9),
  ('ace five offsuit', ['Ah', '5d'], 5), ('king nine suited', ['Kc', '9c'], 6),
  ('ten nine offsuit', ['Th', '9d'], 6), ('pocket sevens', ['7h', '7s'], 7)],
 [('pocket deuces', ['2h', '2d'], 5), ('king nine suited', ['Kc', '9c'], 6),
  ('ten nine offsuit', ['Th', '9d'], 6), ('jack ten suited', ['Js', 'Ts'], 9),
  ('nine five offsuit', ['9c', '5d'], 1), ('pocket sevens', ['7h', '7s'], 7),
  ('eight six suited', ['8d', '6d'], 6), ('jack nine offsuit', ['Jh', '9c'], 6)],
 [('pocket aces', ['Ah', 'Ad'], 20), ('pocket deuces', ['2h', '2d'], 5),
  ('pocket fives', ['5h', '5d'], 5), ('ace king suited', ['Ah', 'Kh'], 12),
  ('nine five offsuit', ['9c', '5d'], 1), ('pocket sevens', ['7h', '7s'], 7),
  ('eight six suited', ['8d', '6d'], 6), ('jack nine offsuit', ['Jh', '9c'], 6)],
 [('pocket aces', ['Ah', 'Ad'], 20), ('pocket deuces', ['2h', '2d'], 5),
  ('pocket fives', ['5h', '5d'], 5), ('ace king suited', ['Ah', 'Kh'], 12),
  ('seven six suited', ['7h', '6h'], 7), ('nine seven offsuit', ['9h', '7d'], 5),
  ('queen jack suited', ['Qs', 'Js'], 9), ('pocket sevens', ['7h', '7s'], 7)]]
for label, args, expected in fixtures[N-1]:
    try:
        actual = solve(args)
    except Exception as exc:
        actual = 'error:' + type(exc).__name__
    check(label, actual, expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
pocket aces2020Passed
pocket deuces105Failed
pocket fives105Failed
ace king suited1212Passed
seven six suited77Passed
nine seven offsuit55Passed
queen jack suited99Passed
ace five offsuit55Passed

SHA-256 / 8c6787410f1fbb6b82d4459759eacf0bd8ee86c6fe956469ace2c4d0e44c7103

HELD IN THE MEMBER ARCHIVE

The verified repair and its recorded checks are member-only.

This mechanism has 8 recorded checks per implementation. The open-access tier publishes the failure and the unsuccessful fix; the repaired source that passes every check, and the observations that prove it, are available to members.

Every case sharing this mechanism uses the same contract and the same repair, so this one record is held back for all of them.

Member access is invitation-based. Sign in with your invited account to inspect the repair.

Sign in to the archive ↗

Verification & scope

A deterministic toy model with an explicitly stated contract; card strings are rank+suit (for example "As", "Td"); no claim of conformance to any casino or tournament rulebook. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:50:10.778536+00:00.

Case digest / 65448da51fd5a0cd6e2897dce8c8b8cc96a9d9ae58488da3e39cd296d2833341