FA-83361 / Card game rule engines / Open access
The two of clubs is forced on every lead · case 01
After the first trick a player holding 2C can only lead it.
ROOT CAUSE
The forced-lead rule ignores the first-trick flag.
THE FAILURE
The forced-lead rule ignores the first-trick flag.
Unsuccessful approach: Forcing 2C on every first-trick lead returns a card the leader does not hold.
Case contract
Input [hand, trick_so_far, hearts_broken, first_trick]. Leading: on the first trick the holder of 2C must lead it; hearts may not be led before they are broken unless the hand is all hearts (QS may be led). Following: follow the led suit if possible; on the first trick a void player may not discard hearts or QS unless nothing else is held. Return legal cards in hand order.
Why this case matters
Card-game engines, scoring apps and online tables apply this rule automatically on every hand.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
hand, trick, broken, first = x
def penalty(c):
return c[1] == 'H' or c == 'QS'
if not trick:
if '2C' in hand:
return ['2C']
if not broken:
safe = [c for c in hand if c[1] != 'H']
if safe:
return safe
return list(hand)
suit = trick[0][1]
follow = [c for c in hand if c[1] == suit]
if follow:
return follow
if first:
clean = [c for c in hand if not penalty(c)]
if clean:
return clean
return list(hand)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['6H', 'AH', 'JC'], ['7S', 'KC'], False, False], ['6H', 'AH', 'JC']], [[['5H', '6C', '7C', '9C', 'KD', 'QC', 'TS'], ['3S', '8S', '2S'], False, True], ['TS']], [[['2C', 'JS'], [], True, True], ['2C']], [[['AS', 'TH'], [], False, True], ['AS']], [[['2C', '8C', 'AS', 'KH'], [], True, False], ['2C', '8C', 'AS', 'KH']], [[['2H', '3C', '3H', 'QC'], [], True, False], ['2H', '3C', '3H', 'QC']], [[['7C'], ['4S'], False, True], ['7C']], [[['3S', '7D'], [], False, True], ['3S', '7D']]], [[[['2S', 'KS', 'TH'], ['JC', '2C'], False, True], ['2S', 'KS']], [[['2S'], ['QS'], False, False], ['2S']], [[['2H', '6C', '7H', '9C', '9S'], ['QC', '2C', '6H'], False, False], ['6C', '9C']], [[['3H', '5D', '9D'], ['3C'], True, False], ['3H', '5D', '9D']], [[['AH', 'JH', 'TH'], ['9C', 'TS'], True, False], ['AH', 'JH', 'TH']], [[['2H', '6S', '8D', 'AC', 'JD', 'QH'], ['4H', 'KC', '3S'], True, True], ['2H', 'QH']], [[['2S', '7C', '9C'], [], False, True], ['2S', '7C', '9C']], [[['2C', '3D', '5D', '7D', '7S', '8H', '9H', 'QC'], [], True, False], ['2C', '3D', '5D', '7D', '7S', '8H', '9H', 'QC']]], [[[['2C', '8C', 'AS', 'KH'], [], True, False], ['2C', '8C', 'AS', 'KH']], [[['5D', 'JH'], ['QH', 'KC', '8S'], True, False], ['JH']], [[['4H'], [], True, True], ['4H']], [[['3D', '5C'], [], True, False], ['3D', '5C']], [[['2H', '5H'], ['KS', '9C', '7H'], False, False], ['2H', '5H']], [[['8C', 'AC', 'KD', 'TS'], [], False, True], ['8C', 'AC', 'KD', 'TS']], [[['3D', '4C', '7C', '9D', 'JH', 'QD', 'TH'], [], False, False], ['3D', '4C', '7C', '9D', 'QD']], [[['6C', '6S', '7S', 'KC', 'KH', 'QD', 'QH'], [], True, True], ['6C', '6S', '7S', 'KC', 'KH', 'QD', 'QH']]], [[[['2H', '6C', '6D', '7C', 'KS', 'QC'], ['3C', '7D'], True, False], ['6C', '7C', 'QC']], [[['AC'], ['2C', '8D'], False, False], ['AC']], [[['2S', '6D'], [], True, False], ['2S', '6D']], [[['5D', 'AS'], ['5S', '3C'], False, False], ['AS']], [[['3C', '4S', '6S', '7D', '8H', 'AS', 'KC', 'KH'], [], False, False], ['3C', '4S', '6S', '7D', 'AS', 'KC']], [[['2H', '3D', '5H', '9D', 'JC', 'KS', 'QD'], [], False, False], ['3D', '9D', 'JC', 'KS', 'QD']], [[['2C', '3D', '5D', '7D', '7S', '8H', '9H', 'QC'], [], True, False], ['2C', '3D', '5D', '7D', '7S', '8H', '9H', 'QC']], [[['2S', '3C', '3D', '8C', '9H', 'AD', 'KS'], [], True, True], ['2S', '3C', '3D', '8C', '9H', 'AD', 'KS']]], [[[['2C', '8C', 'AS', 'KH'], [], True, False], ['2C', '8C', 'AS', 'KH']], [[['3S', '7D'], [], False, True], ['3S', '7D']], [[['2D', '3H', '3S', '4S', '6D', 'QC', 'QH'], ['6C', 'AH'], False, False], ['QC']], [[['3C', '6D', 'TH'], [], False, False], ['3C', '6D']], [[['3D', '5C', '6S', '7H', 'KH', 'TH', 'TS'], [], False, False], ['3D', '5C', '6S', 'TS']], [[['7D', '8H', 'AD', 'AS'], ['AH', '4H', '9C'], True, True], ['8H']], [[['2C', '4C', '6H', '8H', '9D', 'KC', 'TS'], ['6C', '9C'], False, False], ['2C', '4C', 'KC']], [[['3D', '6D', '8D'], [], True, True], ['3D', '6D', '8D']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("legal plays case %d" % i, solve(args), 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 |
|---|---|---|---|
| legal plays case 0 | ['6H', 'AH', 'JC'] | ['6H', 'AH', 'JC'] | Passed |
| legal plays case 1 | ['TS'] | ['TS'] | Passed |
| legal plays case 2 | ['2C'] | ['2C'] | Passed |
| legal plays case 3 | ['AS'] | ['AS'] | Passed |
| legal plays case 4 | ['2C'] | ['2C', '8C', 'AS', 'KH'] | Failed |
| legal plays case 5 | ['2H', '3C', '3H', 'QC'] | ['2H', '3C', '3H', 'QC'] | Passed |
| legal plays case 6 | ['7C'] | ['7C'] | Passed |
| legal plays case 7 | ['3S', '7D'] | ['3S', '7D'] | Passed |
SHA-256 / 6ec2e2e2afd2e56b6ea5d6456e648967e7f111a692218197af176674b62af74b
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
hand, trick, broken, first = x
def penalty(c):
return c[1] == 'H' or c == 'QS'
if not trick:
if first:
return ['2C']
if not broken:
safe = [c for c in hand if c[1] != 'H']
if safe:
return safe
return list(hand)
suit = trick[0][1]
follow = [c for c in hand if c[1] == suit]
if follow:
return follow
if first:
clean = [c for c in hand if not penalty(c)]
if clean:
return clean
return list(hand)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['6H', 'AH', 'JC'], ['7S', 'KC'], False, False], ['6H', 'AH', 'JC']], [[['5H', '6C', '7C', '9C', 'KD', 'QC', 'TS'], ['3S', '8S', '2S'], False, True], ['TS']], [[['2C', 'JS'], [], True, True], ['2C']], [[['AS', 'TH'], [], False, True], ['AS']], [[['2C', '8C', 'AS', 'KH'], [], True, False], ['2C', '8C', 'AS', 'KH']], [[['2H', '3C', '3H', 'QC'], [], True, False], ['2H', '3C', '3H', 'QC']], [[['7C'], ['4S'], False, True], ['7C']], [[['3S', '7D'], [], False, True], ['3S', '7D']]], [[[['2S', 'KS', 'TH'], ['JC', '2C'], False, True], ['2S', 'KS']], [[['2S'], ['QS'], False, False], ['2S']], [[['2H', '6C', '7H', '9C', '9S'], ['QC', '2C', '6H'], False, False], ['6C', '9C']], [[['3H', '5D', '9D'], ['3C'], True, False], ['3H', '5D', '9D']], [[['AH', 'JH', 'TH'], ['9C', 'TS'], True, False], ['AH', 'JH', 'TH']], [[['2H', '6S', '8D', 'AC', 'JD', 'QH'], ['4H', 'KC', '3S'], True, True], ['2H', 'QH']], [[['2S', '7C', '9C'], [], False, True], ['2S', '7C', '9C']], [[['2C', '3D', '5D', '7D', '7S', '8H', '9H', 'QC'], [], True, False], ['2C', '3D', '5D', '7D', '7S', '8H', '9H', 'QC']]], [[[['2C', '8C', 'AS', 'KH'], [], True, False], ['2C', '8C', 'AS', 'KH']], [[['5D', 'JH'], ['QH', 'KC', '8S'], True, False], ['JH']], [[['4H'], [], True, True], ['4H']], [[['3D', '5C'], [], True, False], ['3D', '5C']], [[['2H', '5H'], ['KS', '9C', '7H'], False, False], ['2H', '5H']], [[['8C', 'AC', 'KD', 'TS'], [], False, True], ['8C', 'AC', 'KD', 'TS']], [[['3D', '4C', '7C', '9D', 'JH', 'QD', 'TH'], [], False, False], ['3D', '4C', '7C', '9D', 'QD']], [[['6C', '6S', '7S', 'KC', 'KH', 'QD', 'QH'], [], True, True], ['6C', '6S', '7S', 'KC', 'KH', 'QD', 'QH']]], [[[['2H', '6C', '6D', '7C', 'KS', 'QC'], ['3C', '7D'], True, False], ['6C', '7C', 'QC']], [[['AC'], ['2C', '8D'], False, False], ['AC']], [[['2S', '6D'], [], True, False], ['2S', '6D']], [[['5D', 'AS'], ['5S', '3C'], False, False], ['AS']], [[['3C', '4S', '6S', '7D', '8H', 'AS', 'KC', 'KH'], [], False, False], ['3C', '4S', '6S', '7D', 'AS', 'KC']], [[['2H', '3D', '5H', '9D', 'JC', 'KS', 'QD'], [], False, False], ['3D', '9D', 'JC', 'KS', 'QD']], [[['2C', '3D', '5D', '7D', '7S', '8H', '9H', 'QC'], [], True, False], ['2C', '3D', '5D', '7D', '7S', '8H', '9H', 'QC']], [[['2S', '3C', '3D', '8C', '9H', 'AD', 'KS'], [], True, True], ['2S', '3C', '3D', '8C', '9H', 'AD', 'KS']]], [[[['2C', '8C', 'AS', 'KH'], [], True, False], ['2C', '8C', 'AS', 'KH']], [[['3S', '7D'], [], False, True], ['3S', '7D']], [[['2D', '3H', '3S', '4S', '6D', 'QC', 'QH'], ['6C', 'AH'], False, False], ['QC']], [[['3C', '6D', 'TH'], [], False, False], ['3C', '6D']], [[['3D', '5C', '6S', '7H', 'KH', 'TH', 'TS'], [], False, False], ['3D', '5C', '6S', 'TS']], [[['7D', '8H', 'AD', 'AS'], ['AH', '4H', '9C'], True, True], ['8H']], [[['2C', '4C', '6H', '8H', '9D', 'KC', 'TS'], ['6C', '9C'], False, False], ['2C', '4C', 'KC']], [[['3D', '6D', '8D'], [], True, True], ['3D', '6D', '8D']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("legal plays case %d" % i, solve(args), 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 |
|---|---|---|---|
| legal plays case 0 | ['6H', 'AH', 'JC'] | ['6H', 'AH', 'JC'] | Passed |
| legal plays case 1 | ['TS'] | ['TS'] | Passed |
| legal plays case 2 | ['2C'] | ['2C'] | Passed |
| legal plays case 3 | ['2C'] | ['AS'] | Failed |
| legal plays case 4 | ['2C', '8C', 'AS', 'KH'] | ['2C', '8C', 'AS', 'KH'] | Passed |
| legal plays case 5 | ['2H', '3C', '3H', 'QC'] | ['2H', '3C', '3H', 'QC'] | Passed |
| legal plays case 6 | ['7C'] | ['7C'] | Passed |
| legal plays case 7 | ['2C'] | ['3S', '7D'] | Failed |
SHA-256 / 14e0ff89d98dfda0c84882c9da662683da4ec0c9812f92e3017f005f4d7ccacc
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 bounded toy rule contract stated explicitly in the contract field; cards are two-character codes (rank, suit). Not a complete implementation of any published rulebook or casino table rules. 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:20.750443+00:00.
Case digest / ae6c571c4e5d54aad701560df0445f62a80e5976c89871530d8183b40ffa1047