FA-82296 / Poker hand evaluation / Open access
Connectors penalized as one-gappers · case 01
Seven-six suited loses a point and the connector bonus logic misfires.
ROOT CAUSE
The gap is the rank difference rather than the number of ranks strictly between the cards.
VERIFIED REPAIR
Gap equals the rank difference minus one.
Unsuccessful approach: Subtracting two treats one-gappers as connectors and connectors as negative gaps.
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=max(s*2,5)
else:
if x[0][1]==x[1][1]: s+=2
gap=a-b
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),
('ace five offsuit', ['Ah', '5d'], 5), ('pocket sevens', ['7h', '7s'], 7)],
[('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), ('king nine suited', ['Kc', '9c'], 6),
('ten nine offsuit', ['Th', '9d'], 6), ('pocket sevens', ['7h', '7s'], 7)],
[('seven six suited', ['7h', '6h'], 7), ('nine seven offsuit', ['9h', '7d'], 5),
('queen jack suited', ['Qs', 'Js'], 9), ('king nine suited', ['Kc', '9c'], 6),
('ten nine offsuit', ['Th', '9d'], 6), ('jack ten suited', ['Js', 'Ts'], 9),
('nine five offsuit', ['9c', '5d'], 1), ('eight six suited', ['8d', '6d'], 6)],
[('pocket aces', ['Ah', 'Ad'], 20), ('queen jack suited', ['Qs', 'Js'], 9),
('king nine suited', ['Kc', '9c'], 6), ('ten nine offsuit', ['Th', '9d'], 6),
('jack ten suited', ['Js', 'Ts'], 9), ('nine five offsuit', ['9c', '5d'], 1),
('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), ('king nine suited', ['Kc', '9c'], 6),
('ten nine offsuit', ['Th', '9d'], 6), ('nine five offsuit', ['9c', '5d'], 1),
('eight six suited', ['8d', '6d'], 6), ('jack nine offsuit', ['Jh', '9c'], 6)]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| pocket aces | 20 | 20 | Passed |
| pocket deuces | 5 | 5 | Passed |
| pocket fives | 5 | 5 | Passed |
| ace king suited | 11 | 12 | Failed |
| seven six suited | 6 | 7 | Failed |
| nine seven offsuit | 3 | 5 | Failed |
| ace five offsuit | 5 | 5 | Passed |
| pocket sevens | 7 | 7 | Passed |
SHA-256 / 191bb69b6f6c8ed4806ca529c6bff5d0692106add83166b3dae13e298d6cf604
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*2,5)
else:
if x[0][1]==x[1][1]: s+=2
gap=a-b-2
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),
('ace five offsuit', ['Ah', '5d'], 5), ('pocket sevens', ['7h', '7s'], 7)],
[('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), ('king nine suited', ['Kc', '9c'], 6),
('ten nine offsuit', ['Th', '9d'], 6), ('pocket sevens', ['7h', '7s'], 7)],
[('seven six suited', ['7h', '6h'], 7), ('nine seven offsuit', ['9h', '7d'], 5),
('queen jack suited', ['Qs', 'Js'], 9), ('king nine suited', ['Kc', '9c'], 6),
('ten nine offsuit', ['Th', '9d'], 6), ('jack ten suited', ['Js', 'Ts'], 9),
('nine five offsuit', ['9c', '5d'], 1), ('eight six suited', ['8d', '6d'], 6)],
[('pocket aces', ['Ah', 'Ad'], 20), ('queen jack suited', ['Qs', 'Js'], 9),
('king nine suited', ['Kc', '9c'], 6), ('ten nine offsuit', ['Th', '9d'], 6),
('jack ten suited', ['Js', 'Ts'], 9), ('nine five offsuit', ['9c', '5d'], 1),
('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), ('king nine suited', ['Kc', '9c'], 6),
('ten nine offsuit', ['Th', '9d'], 6), ('nine five offsuit', ['9c', '5d'], 1),
('eight six suited', ['8d', '6d'], 6), ('jack nine offsuit', ['Jh', '9c'], 6)]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| pocket aces | 20 | 20 | Passed |
| pocket deuces | 5 | 5 | Passed |
| pocket fives | 5 | 5 | Passed |
| ace king suited | 7 | 12 | Failed |
| seven six suited | 2 | 7 | Failed |
| nine seven offsuit | 6 | 5 | Failed |
| ace five offsuit | 5 | 5 | Passed |
| pocket sevens | 7 | 7 | Passed |
SHA-256 / 7113d924e40b4b0771e569362f0d858cbc6a393d1081a66296cf68ad21ed3ccf
3 / The verified repair
Exit 0"""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*2,5)
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),
('ace five offsuit', ['Ah', '5d'], 5), ('pocket sevens', ['7h', '7s'], 7)],
[('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), ('king nine suited', ['Kc', '9c'], 6),
('ten nine offsuit', ['Th', '9d'], 6), ('pocket sevens', ['7h', '7s'], 7)],
[('seven six suited', ['7h', '6h'], 7), ('nine seven offsuit', ['9h', '7d'], 5),
('queen jack suited', ['Qs', 'Js'], 9), ('king nine suited', ['Kc', '9c'], 6),
('ten nine offsuit', ['Th', '9d'], 6), ('jack ten suited', ['Js', 'Ts'], 9),
('nine five offsuit', ['9c', '5d'], 1), ('eight six suited', ['8d', '6d'], 6)],
[('pocket aces', ['Ah', 'Ad'], 20), ('queen jack suited', ['Qs', 'Js'], 9),
('king nine suited', ['Kc', '9c'], 6), ('ten nine offsuit', ['Th', '9d'], 6),
('jack ten suited', ['Js', 'Ts'], 9), ('nine five offsuit', ['9c', '5d'], 1),
('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), ('king nine suited', ['Kc', '9c'], 6),
('ten nine offsuit', ['Th', '9d'], 6), ('nine five offsuit', ['9c', '5d'], 1),
('eight six suited', ['8d', '6d'], 6), ('jack nine offsuit', ['Jh', '9c'], 6)]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| pocket aces | 20 | 20 | Passed |
| pocket deuces | 5 | 5 | Passed |
| pocket fives | 5 | 5 | Passed |
| ace king suited | 12 | 12 | Passed |
| seven six suited | 7 | 7 | Passed |
| nine seven offsuit | 5 | 5 | Passed |
| ace five offsuit | 5 | 5 | Passed |
| pocket sevens | 7 | 7 | Passed |
SHA-256 / 69e138520fa2c472417b36beef6e0c50a6c02e48b619b1db41b6b0fc103c04cc
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.779434+00:00.
Case digest / a8959ee867b56cfdafa739d062635ade780fa3be08cdfc09541fe9aea6eb158f