FAILURE MAP
← Case archive

FA-82276 / Poker hand evaluation / Open access

Four-card run treated as a made straight · case 01

Open-ended draws report zero outs because the draw is already counted as a straight.

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

ROOT CAUSE

The straight window checks four consecutive ranks.

VERIFIED REPAIR

Require all five ranks of the window.

Unsuccessful approach: Accepting four of five window ranks is still a draw, not a straight.

Case contract

Input: {"cards": known hole and board cards (4 to 6, no straight yet), "dead": other seen cards}. Return how many unseen cards would give the player a five-card straight (ace plays high or low): for every rank that completes a straight, count its four cards minus those already seen in cards or dead.

Why this case matters

Out counts feed pot-odds displays and all-in equity shortcuts.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    R='23456789TJQKA'
    known=x['cards']+x.get('dead',[])
    ranks={R.index(c[0])+2 for c in x['cards']}
    def has(rs):
        rs=set(rs)
        if 14 in rs: rs.add(1)
        return any(all(t-i in rs for i in range(4)) for t in range(5,15))
    if has(ranks): return 0
    outs=0
    for r in range(2,15):
        if has(ranks|{r}):
            outs+=4-sum(1 for c in known if R.index(c[0])+2==r)
    return outs
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('open ended', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': []}, 8),
  ('gutshot', {'cards': ['8h', '9d', 'Jc', 'Qs', '2h'], 'dead': []}, 4),
  ('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
  ('ace-high draw', {'cards': ['Ah', 'Kd', 'Qc', 'Js', '2h'], 'dead': []}, 4),
  ('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
   5),
  ('paired board seen out', {'cards': ['8h', '9d', 'Tc', 'Js', 'Qh'], 'dead': []}, 0),
  ('no draw', {'cards': ['2h', '7d', 'Tc', 'Ks', '4h'], 'dead': []}, 0),
  ('double gutshot', {'cards': ['7h', '9d', 'Tc', 'Js', 'Kh', '2c'], 'dead': []}, 8)],
 [('gutshot', {'cards': ['8h', '9d', 'Jc', 'Qs', '2h'], 'dead': []}, 4),
  ('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
  ('ace-high draw', {'cards': ['Ah', 'Kd', 'Qc', 'Js', '2h'], 'dead': []}, 4),
  ('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
   5),
  ('double gutshot', {'cards': ['7h', '9d', 'Tc', 'Js', 'Kh', '2c'], 'dead': []}, 8),
  ('wheel gutshot with dead', {'cards': ['Ah', '2d', '4c', '5s', 'Jh'], 'dead': ['3h']}, 3),
  ('three to straight only', {'cards': ['8h', '9d', 'Tc', '2s', '3h'], 'dead': []}, 0),
  ('two dead copies of an out',
   {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', '7d', 'Qd']}, 5)],
 [('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
  ('ace-high draw', {'cards': ['Ah', 'Kd', 'Qc', 'Js', '2h'], 'dead': []}, 4),
  ('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
   5),
  ('double gutshot', {'cards': ['7h', '9d', 'Tc', 'Js', 'Kh', '2c'], 'dead': []}, 8),
  ('wheel gutshot with dead', {'cards': ['Ah', '2d', '4c', '5s', 'Jh'], 'dead': ['3h']}, 3),
  ('three to straight only', {'cards': ['8h', '9d', 'Tc', '2s', '3h'], 'dead': []}, 0),
  ('two dead copies of an out',
   {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', '7d', 'Qd']}, 5),
  ('open ender with seen nine', {'cards': ['5h', '6d', '7c', '8s', '8h'], 'dead': ['9c', '4d']},
   6)],
 [('open ended', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': []}, 8),
  ('ace-high draw', {'cards': ['Ah', 'Kd', 'Qc', 'Js', '2h'], 'dead': []}, 4),
  ('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
   5),
  ('paired board seen out', {'cards': ['8h', '9d', 'Tc', 'Js', 'Qh'], 'dead': []}, 0),
  ('no draw', {'cards': ['2h', '7d', 'Tc', 'Ks', '4h'], 'dead': []}, 0),
  ('three to straight only', {'cards': ['8h', '9d', 'Tc', '2s', '3h'], 'dead': []}, 0),
  ('two dead copies of an out',
   {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', '7d', 'Qd']}, 5),
  ('open ender with seen nine', {'cards': ['5h', '6d', '7c', '8s', '8h'], 'dead': ['9c', '4d']},
   6)],
 [('open ended', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': []}, 8),
  ('gutshot', {'cards': ['8h', '9d', 'Jc', 'Qs', '2h'], 'dead': []}, 4),
  ('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
   5),
  ('paired board seen out', {'cards': ['8h', '9d', 'Tc', 'Js', 'Qh'], 'dead': []}, 0),
  ('no draw', {'cards': ['2h', '7d', 'Tc', 'Ks', '4h'], 'dead': []}, 0),
  ('double gutshot', {'cards': ['7h', '9d', 'Tc', 'Js', 'Kh', '2c'], 'dead': []}, 8),
  ('two dead copies of an out',
   {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', '7d', 'Qd']}, 5),
  ('open ender with seen nine', {'cards': ['5h', '6d', '7c', '8s', '8h'], 'dead': ['9c', '4d']},
   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 fixtureActualExpectedOutcome
open ended08Failed
gutshot44Passed
ace-low draw44Passed
ace-high draw04Failed
open ended with dead05Failed
paired board seen out00Passed
no draw00Passed
double gutshot88Passed

SHA-256 / 7e143ace53b339bbeb7b0bc3a5dc4e08192fa2b900b640f59c0e73b00b16223d

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    R='23456789TJQKA'
    known=x['cards']+x.get('dead',[])
    ranks={R.index(c[0])+2 for c in x['cards']}
    def has(rs):
        rs=set(rs)
        if 14 in rs: rs.add(1)
        return any(sum(t-i in rs for i in range(5))>=4 for t in range(5,15))
    if has(ranks): return 0
    outs=0
    for r in range(2,15):
        if has(ranks|{r}):
            outs+=4-sum(1 for c in known if R.index(c[0])+2==r)
    return outs
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('open ended', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': []}, 8),
  ('gutshot', {'cards': ['8h', '9d', 'Jc', 'Qs', '2h'], 'dead': []}, 4),
  ('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
  ('ace-high draw', {'cards': ['Ah', 'Kd', 'Qc', 'Js', '2h'], 'dead': []}, 4),
  ('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
   5),
  ('paired board seen out', {'cards': ['8h', '9d', 'Tc', 'Js', 'Qh'], 'dead': []}, 0),
  ('no draw', {'cards': ['2h', '7d', 'Tc', 'Ks', '4h'], 'dead': []}, 0),
  ('double gutshot', {'cards': ['7h', '9d', 'Tc', 'Js', 'Kh', '2c'], 'dead': []}, 8)],
 [('gutshot', {'cards': ['8h', '9d', 'Jc', 'Qs', '2h'], 'dead': []}, 4),
  ('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
  ('ace-high draw', {'cards': ['Ah', 'Kd', 'Qc', 'Js', '2h'], 'dead': []}, 4),
  ('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
   5),
  ('double gutshot', {'cards': ['7h', '9d', 'Tc', 'Js', 'Kh', '2c'], 'dead': []}, 8),
  ('wheel gutshot with dead', {'cards': ['Ah', '2d', '4c', '5s', 'Jh'], 'dead': ['3h']}, 3),
  ('three to straight only', {'cards': ['8h', '9d', 'Tc', '2s', '3h'], 'dead': []}, 0),
  ('two dead copies of an out',
   {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', '7d', 'Qd']}, 5)],
 [('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
  ('ace-high draw', {'cards': ['Ah', 'Kd', 'Qc', 'Js', '2h'], 'dead': []}, 4),
  ('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
   5),
  ('double gutshot', {'cards': ['7h', '9d', 'Tc', 'Js', 'Kh', '2c'], 'dead': []}, 8),
  ('wheel gutshot with dead', {'cards': ['Ah', '2d', '4c', '5s', 'Jh'], 'dead': ['3h']}, 3),
  ('three to straight only', {'cards': ['8h', '9d', 'Tc', '2s', '3h'], 'dead': []}, 0),
  ('two dead copies of an out',
   {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', '7d', 'Qd']}, 5),
  ('open ender with seen nine', {'cards': ['5h', '6d', '7c', '8s', '8h'], 'dead': ['9c', '4d']},
   6)],
 [('open ended', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': []}, 8),
  ('ace-high draw', {'cards': ['Ah', 'Kd', 'Qc', 'Js', '2h'], 'dead': []}, 4),
  ('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
   5),
  ('paired board seen out', {'cards': ['8h', '9d', 'Tc', 'Js', 'Qh'], 'dead': []}, 0),
  ('no draw', {'cards': ['2h', '7d', 'Tc', 'Ks', '4h'], 'dead': []}, 0),
  ('three to straight only', {'cards': ['8h', '9d', 'Tc', '2s', '3h'], 'dead': []}, 0),
  ('two dead copies of an out',
   {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', '7d', 'Qd']}, 5),
  ('open ender with seen nine', {'cards': ['5h', '6d', '7c', '8s', '8h'], 'dead': ['9c', '4d']},
   6)],
 [('open ended', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': []}, 8),
  ('gutshot', {'cards': ['8h', '9d', 'Jc', 'Qs', '2h'], 'dead': []}, 4),
  ('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
   5),
  ('paired board seen out', {'cards': ['8h', '9d', 'Tc', 'Js', 'Qh'], 'dead': []}, 0),
  ('no draw', {'cards': ['2h', '7d', 'Tc', 'Ks', '4h'], 'dead': []}, 0),
  ('double gutshot', {'cards': ['7h', '9d', 'Tc', 'Js', 'Kh', '2c'], 'dead': []}, 8),
  ('two dead copies of an out',
   {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', '7d', 'Qd']}, 5),
  ('open ender with seen nine', {'cards': ['5h', '6d', '7c', '8s', '8h'], 'dead': ['9c', '4d']},
   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 fixtureActualExpectedOutcome
open ended08Failed
gutshot04Failed
ace-low draw04Failed
ace-high draw04Failed
open ended with dead05Failed
paired board seen out00Passed
no draw00Passed
double gutshot08Failed

SHA-256 / b70b7c4eb75e0f190da599170dde7319155a729393c1188d7b706e470b9a8324

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    R='23456789TJQKA'
    known=x['cards']+x.get('dead',[])
    ranks={R.index(c[0])+2 for c in x['cards']}
    def has(rs):
        rs=set(rs)
        if 14 in rs: rs.add(1)
        return any(all(t-i in rs for i in range(5)) for t in range(5,15))
    if has(ranks): return 0
    outs=0
    for r in range(2,15):
        if has(ranks|{r}):
            outs+=4-sum(1 for c in known if R.index(c[0])+2==r)
    return outs
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('open ended', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': []}, 8),
  ('gutshot', {'cards': ['8h', '9d', 'Jc', 'Qs', '2h'], 'dead': []}, 4),
  ('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
  ('ace-high draw', {'cards': ['Ah', 'Kd', 'Qc', 'Js', '2h'], 'dead': []}, 4),
  ('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
   5),
  ('paired board seen out', {'cards': ['8h', '9d', 'Tc', 'Js', 'Qh'], 'dead': []}, 0),
  ('no draw', {'cards': ['2h', '7d', 'Tc', 'Ks', '4h'], 'dead': []}, 0),
  ('double gutshot', {'cards': ['7h', '9d', 'Tc', 'Js', 'Kh', '2c'], 'dead': []}, 8)],
 [('gutshot', {'cards': ['8h', '9d', 'Jc', 'Qs', '2h'], 'dead': []}, 4),
  ('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
  ('ace-high draw', {'cards': ['Ah', 'Kd', 'Qc', 'Js', '2h'], 'dead': []}, 4),
  ('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
   5),
  ('double gutshot', {'cards': ['7h', '9d', 'Tc', 'Js', 'Kh', '2c'], 'dead': []}, 8),
  ('wheel gutshot with dead', {'cards': ['Ah', '2d', '4c', '5s', 'Jh'], 'dead': ['3h']}, 3),
  ('three to straight only', {'cards': ['8h', '9d', 'Tc', '2s', '3h'], 'dead': []}, 0),
  ('two dead copies of an out',
   {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', '7d', 'Qd']}, 5)],
 [('ace-low draw', {'cards': ['Ah', '2d', '3c', '4s', 'Kh'], 'dead': []}, 4),
  ('ace-high draw', {'cards': ['Ah', 'Kd', 'Qc', 'Js', '2h'], 'dead': []}, 4),
  ('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
   5),
  ('double gutshot', {'cards': ['7h', '9d', 'Tc', 'Js', 'Kh', '2c'], 'dead': []}, 8),
  ('wheel gutshot with dead', {'cards': ['Ah', '2d', '4c', '5s', 'Jh'], 'dead': ['3h']}, 3),
  ('three to straight only', {'cards': ['8h', '9d', 'Tc', '2s', '3h'], 'dead': []}, 0),
  ('two dead copies of an out',
   {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', '7d', 'Qd']}, 5),
  ('open ender with seen nine', {'cards': ['5h', '6d', '7c', '8s', '8h'], 'dead': ['9c', '4d']},
   6)],
 [('open ended', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': []}, 8),
  ('ace-high draw', {'cards': ['Ah', 'Kd', 'Qc', 'Js', '2h'], 'dead': []}, 4),
  ('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
   5),
  ('paired board seen out', {'cards': ['8h', '9d', 'Tc', 'Js', 'Qh'], 'dead': []}, 0),
  ('no draw', {'cards': ['2h', '7d', 'Tc', 'Ks', '4h'], 'dead': []}, 0),
  ('three to straight only', {'cards': ['8h', '9d', 'Tc', '2s', '3h'], 'dead': []}, 0),
  ('two dead copies of an out',
   {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', '7d', 'Qd']}, 5),
  ('open ender with seen nine', {'cards': ['5h', '6d', '7c', '8s', '8h'], 'dead': ['9c', '4d']},
   6)],
 [('open ended', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': []}, 8),
  ('gutshot', {'cards': ['8h', '9d', 'Jc', 'Qs', '2h'], 'dead': []}, 4),
  ('open ended with dead', {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', 'Qd', 'Qs']},
   5),
  ('paired board seen out', {'cards': ['8h', '9d', 'Tc', 'Js', 'Qh'], 'dead': []}, 0),
  ('no draw', {'cards': ['2h', '7d', 'Tc', 'Ks', '4h'], 'dead': []}, 0),
  ('double gutshot', {'cards': ['7h', '9d', 'Tc', 'Js', 'Kh', '2c'], 'dead': []}, 8),
  ('two dead copies of an out',
   {'cards': ['8h', '9d', 'Tc', 'Js', '2h'], 'dead': ['7c', '7d', 'Qd']}, 5),
  ('open ender with seen nine', {'cards': ['5h', '6d', '7c', '8s', '8h'], 'dead': ['9c', '4d']},
   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 fixtureActualExpectedOutcome
open ended88Passed
gutshot44Passed
ace-low draw44Passed
ace-high draw44Passed
open ended with dead55Passed
paired board seen out00Passed
no draw00Passed
double gutshot88Passed

SHA-256 / a7e0edc497747e66c097a5468b2f0888cc346ddc76a67ea2bdc2a76800e3f66c

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

Case digest / 35bf25eef2f3617f24ee420d803c3f5007a92c65a1c2816639560a5eff57d766