FAILURE MAP
← Case archive

FA-82326 / Poker hand evaluation / Open access

Badugi search settles for one-card subsets · case 01

Every hand evaluates as a one-card hand, so comparisons depend only on the lowest card.

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

ROOT CAUSE

Subset sizes are searched from smallest to largest and the first hit is returned.

VERIFIED REPAIR

Search from four cards down to one and return the first size that has a valid subset.

Unsuccessful approach: Starting from three never recognizes a complete four-card badugi.

Case contract

Input: [hand_a, hand_b], four distinct cards each. A hand's value is its best subset with all ranks distinct and all suits distinct: more cards beat fewer; among equal sizes the lower subset (compared from its highest card down, ace low = 1) wins. Return 1, -1 or 0.

Why this case matters

Badugi uses a unique subset-based evaluator that is easy to get subtly wrong.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import itertools
N = 1
observations = []
def solve(x):
    R='A23456789TJQK'
    def best(h):
        for n in range(1,5):
            cands=[]
            for sub in itertools.combinations(h,n):
                if len({c[0] for c in sub})==n and len({c[1] for c in sub})==n:
                    cands.append(sorted((R.index(c[0])+1 for c in sub), reverse=True))
            if cands: return (n, min(cands))
    a,b=best(x[0]),best(x[1])
    if a[0]!=b[0]: return 1 if a[0]>b[0] else -1
    if a[1]==b[1]: return 0
    return 1 if a[1]<b[1] else -1
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('four-card badugi vs three', [['Ac', '2d', '3h', '4s'], ['Ac', '2c', '3h', '4s']], 1),
  ('paired rank different suits', [['Ac', 'Ad', '3h', '4s'], ['5c', '6d', '7h', 'Ks']], -1),
  ('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('one-card hands', [['Ac', '2c', '3c', '4c'], ['5d', '6d', '7d', '8d']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 1)],
 [('four-card badugi vs three', [['Ac', '2d', '3h', '4s'], ['Ac', '2c', '3h', '4s']], 1),
  ('paired rank different suits', [['Ac', 'Ad', '3h', '4s'], ['5c', '6d', '7h', 'Ks']], -1),
  ('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 1)],
 [('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1),
  ('one-card hands', [['Ac', '2c', '3c', '4c'], ['5d', '6d', '7d', '8d']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 1)],
 [('paired rank different suits', [['Ac', 'Ad', '3h', '4s'], ['5c', '6d', '7h', 'Ks']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1),
  ('one-card hands', [['Ac', '2c', '3c', '4c'], ['5d', '6d', '7d', '8d']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 1)],
 [('four-card badugi vs three', [['Ac', '2d', '3h', '4s'], ['Ac', '2c', '3h', '4s']], 1),
  ('paired rank different suits', [['Ac', 'Ad', '3h', '4s'], ['5c', '6d', '7h', 'Ks']], -1),
  ('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1),
  ('one-card hands', [['Ac', '2c', '3c', '4c'], ['5d', '6d', '7d', '8d']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 1)]]
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
four-card badugi vs three01Failed
paired rank different suits1-1Failed
lower badugi wins0-1Failed
equal badugis00Passed
best three-card subset11Passed
two-card hands1-1Failed
one-card hands11Passed
suit pair plus rank pair11Passed

SHA-256 / 8758a076b36a1622f64ca3130c30af547c1fc324fbb7ff38905d704b3da35968

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import itertools
N = 1
observations = []
def solve(x):
    R='A23456789TJQK'
    def best(h):
        for n in range(3,0,-1):
            cands=[]
            for sub in itertools.combinations(h,n):
                if len({c[0] for c in sub})==n and len({c[1] for c in sub})==n:
                    cands.append(sorted((R.index(c[0])+1 for c in sub), reverse=True))
            if cands: return (n, min(cands))
    a,b=best(x[0]),best(x[1])
    if a[0]!=b[0]: return 1 if a[0]>b[0] else -1
    if a[1]==b[1]: return 0
    return 1 if a[1]<b[1] else -1
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('four-card badugi vs three', [['Ac', '2d', '3h', '4s'], ['Ac', '2c', '3h', '4s']], 1),
  ('paired rank different suits', [['Ac', 'Ad', '3h', '4s'], ['5c', '6d', '7h', 'Ks']], -1),
  ('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('one-card hands', [['Ac', '2c', '3c', '4c'], ['5d', '6d', '7d', '8d']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 1)],
 [('four-card badugi vs three', [['Ac', '2d', '3h', '4s'], ['Ac', '2c', '3h', '4s']], 1),
  ('paired rank different suits', [['Ac', 'Ad', '3h', '4s'], ['5c', '6d', '7h', 'Ks']], -1),
  ('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 1)],
 [('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1),
  ('one-card hands', [['Ac', '2c', '3c', '4c'], ['5d', '6d', '7d', '8d']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 1)],
 [('paired rank different suits', [['Ac', 'Ad', '3h', '4s'], ['5c', '6d', '7h', 'Ks']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1),
  ('one-card hands', [['Ac', '2c', '3c', '4c'], ['5d', '6d', '7d', '8d']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 1)],
 [('four-card badugi vs three', [['Ac', '2d', '3h', '4s'], ['Ac', '2c', '3h', '4s']], 1),
  ('paired rank different suits', [['Ac', 'Ad', '3h', '4s'], ['5c', '6d', '7h', 'Ks']], -1),
  ('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1),
  ('one-card hands', [['Ac', '2c', '3c', '4c'], ['5d', '6d', '7d', '8d']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 1)]]
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
four-card badugi vs three11Passed
paired rank different suits1-1Failed
lower badugi wins1-1Failed
equal badugis00Passed
best three-card subset11Passed
two-card hands-1-1Passed
one-card hands11Passed
suit pair plus rank pair11Passed

SHA-256 / 43d19bbe2ac223e776c996c4360a7a8273fbd4936e4e845b40ab31fc674a7374

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import itertools
N = 1
observations = []
def solve(x):
    R='A23456789TJQK'
    def best(h):
        for n in range(4,0,-1):
            cands=[]
            for sub in itertools.combinations(h,n):
                if len({c[0] for c in sub})==n and len({c[1] for c in sub})==n:
                    cands.append(sorted((R.index(c[0])+1 for c in sub), reverse=True))
            if cands: return (n, min(cands))
    a,b=best(x[0]),best(x[1])
    if a[0]!=b[0]: return 1 if a[0]>b[0] else -1
    if a[1]==b[1]: return 0
    return 1 if a[1]<b[1] else -1
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('four-card badugi vs three', [['Ac', '2d', '3h', '4s'], ['Ac', '2c', '3h', '4s']], 1),
  ('paired rank different suits', [['Ac', 'Ad', '3h', '4s'], ['5c', '6d', '7h', 'Ks']], -1),
  ('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('one-card hands', [['Ac', '2c', '3c', '4c'], ['5d', '6d', '7d', '8d']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 1)],
 [('four-card badugi vs three', [['Ac', '2d', '3h', '4s'], ['Ac', '2c', '3h', '4s']], 1),
  ('paired rank different suits', [['Ac', 'Ad', '3h', '4s'], ['5c', '6d', '7h', 'Ks']], -1),
  ('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 1)],
 [('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1),
  ('one-card hands', [['Ac', '2c', '3c', '4c'], ['5d', '6d', '7d', '8d']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 1)],
 [('paired rank different suits', [['Ac', 'Ad', '3h', '4s'], ['5c', '6d', '7h', 'Ks']], -1),
  ('equal badugis', [['Ac', '2d', '3h', '4s'], ['Ad', '2c', '3s', '4h']], 0),
  ('best three-card subset', [['Kc', '2c', '3h', '4s'], ['5c', '6c', '7h', '8s']], 1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1),
  ('one-card hands', [['Ac', '2c', '3c', '4c'], ['5d', '6d', '7d', '8d']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 1)],
 [('four-card badugi vs three', [['Ac', '2d', '3h', '4s'], ['Ac', '2c', '3h', '4s']], 1),
  ('paired rank different suits', [['Ac', 'Ad', '3h', '4s'], ['5c', '6d', '7h', 'Ks']], -1),
  ('lower badugi wins', [['Ac', '2d', '3h', '8s'], ['Ac', '2d', '4h', '7s']], -1),
  ('two-card hands', [['Ac', '2c', '3c', 'Kd'], ['4h', '5h', '6h', '7s']], -1),
  ('king high badugi vs three', [['Kc', 'Qd', 'Jh', 'Ts'], ['Ac', '2c', '3d', '4h']], 1),
  ('lowest card trap', [['Ac', '5d', '6h', '7s'], ['2c', '3d', '4h', '8s']], 1),
  ('one-card hands', [['Ac', '2c', '3c', '4c'], ['5d', '6d', '7d', '8d']], 1),
  ('suit pair plus rank pair', [['2c', '2d', '5c', '9h'], ['3c', '4c', '6d', 'Th']], 1)]]
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
four-card badugi vs three11Passed
paired rank different suits-1-1Passed
lower badugi wins-1-1Passed
equal badugis00Passed
best three-card subset11Passed
two-card hands-1-1Passed
one-card hands11Passed
suit pair plus rank pair11Passed

SHA-256 / 34587914b1571de09826b47869050b2a58baf9e1dac9b6c433268283ae3443e1

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:11.120119+00:00.

Case digest / dda3961aa0093f3d11beb1cb9b7ce8cd61c785d5205c27060e0da17e89cca9cc