FAILURE MAP
← Case archive

FA-83641 / Card game rule engines / Open access

The left bower keeps its printed suit · case 01

The jack of the same colour loses to small trumps and follows its printed suit.

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

ROOT CAUSE

Effective suit mapping for the left bower is missing.

VERIFIED REPAIR

Treat the same-colour jack as a trump.

Unsuccessful approach: Pairing suits by the wrong colour turns an off-colour jack into the left bower.

Case contract

Input [four_cards, leader, trump]. The jack of trump (right bower) is highest, the jack of the same-colour suit (left bower) is second and belongs to the trump suit; then A K Q T 9 of trump. Otherwise the highest card of the effective led suit (A K Q J T 9) wins. Return the winning seat.

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):
    cards, leader, trump = x
    partner = {'S': 'C', 'C': 'S', 'H': 'D', 'D': 'H'}[trump]
    def suit(c):
        return c[1]
    def power(c):
        if suit(c) == trump:
            if c[0] == 'J':
                return 100 if c[1] == trump else 99
            return 50 + '9TJQKA'.index(c[0])
        return '9TJQKA'.index(c[0])
    best = 0
    for i in range(1, len(cards)):
        c = cards[i]
        b = cards[best]
        if suit(c) == suit(b) and power(c) > power(b):
            best = i
        elif suit(c) == trump and suit(b) != trump:
            best = i
    return (leader + best) % 4
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['9S', 'JD', 'AC', '9H'], 0, 'H'], 1], [[['9H', 'JS', 'TH', 'QC'], 3, 'C'], 0], [[['KS', '9H', 'QC', '9D'], 3, 'S'], 3], [[['JD', 'QD', 'AD', 'AC'], 0, 'H'], 0], [[['JD', 'AS', 'JC', 'QH'], 3, 'S'], 1], [[['KH', '9S', 'JH', 'QS'], 3, 'D'], 1], [[['TS', 'JS', 'TC', 'QC'], 2, 'S'], 3], [[['JH', 'AH', 'KD', 'JD'], 2, 'D'], 1]], [[[['TH', 'KH', 'JD', 'JC'], 2, 'H'], 0], [[['JD', '9H', 'TH', 'AS'], 0, 'H'], 0], [[['JD', 'TS', '9C', 'QD'], 3, 'C'], 1], [[['QS', 'KD', '9S', '9C'], 1, 'S'], 1], [[['TH', 'AS', 'TD', 'KD'], 2, 'C'], 2], [[['QS', 'TC', 'KH', 'AS'], 0, 'D'], 3], [[['KD', 'TH', 'AD', 'AH'], 2, 'C'], 0], [[['JC', 'TH', '9H', 'QD'], 1, 'D'], 0]], [[[['JD', 'AS', 'JC', 'QH'], 3, 'S'], 1], [[['JC', 'TH', '9H', 'QD'], 1, 'D'], 0], [[['9D', 'AS', 'JS', 'TD'], 0, 'S'], 2], [[['JS', 'TH', 'TC', 'JD'], 2, 'C'], 2], [[['TC', 'JS', 'AC', 'TH'], 1, 'C'], 2], [[['QC', 'QD', 'KC', 'JS'], 2, 'C'], 1], [[['AC', 'TC', 'AH', 'JS'], 1, 'C'], 0], [[['JD', 'QD', 'KC', 'JC'], 3, 'S'], 2]], [[[['KC', 'KD', 'JS', 'QH'], 1, 'C'], 3], [[['JD', 'QD', 'KC', 'JC'], 3, 'S'], 2], [[['TH', 'AH', 'JD', 'QD'], 2, 'S'], 3], [[['KS', '9D', 'TD', 'JS'], 0, 'C'], 3], [[['9C', 'JH', 'JS', 'TC'], 2, 'C'], 0], [[['QD', 'AH', 'KS', 'TC'], 3, 'H'], 0], [[['AS', 'TC', 'TD', 'QS'], 1, 'S'], 1], [[['TS', '9C', '9H', 'JS'], 3, 'C'], 2]], [[[['QC', 'QD', 'KC', 'JS'], 2, 'C'], 1], [[['TC', 'JD', 'QS', 'JC'], 3, 'C'], 2], [[['AH', 'JH', '9C', 'TS'], 0, 'D'], 1], [[['AD', 'KS', 'JH', 'JD'], 2, 'H'], 0], [[['TH', 'JS', 'QC', 'JC'], 2, 'C'], 1], [[['KC', '9H', 'JS', 'JC'], 2, 'S'], 0], [[['KD', 'AS', 'JD', 'JH'], 0, 'D'], 2], [[['JD', 'JS', 'QC', '9H'], 3, 'C'], 0]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("trick 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 fixtureActualExpectedOutcome
trick case 031Failed
trick case 120Failed
trick case 233Passed
trick case 320Failed
trick case 401Failed
trick case 531Failed
trick case 633Passed
trick case 711Passed

SHA-256 / 9b00ccf2c04ab0920675187d559c87ed2e35edb81554c2596da3a5848c501440

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(x):
    cards, leader, trump = x
    partner = {'S': 'H', 'H': 'S', 'C': 'D', 'D': 'C'}[trump]
    def suit(c):
        if c[0] == 'J' and c[1] == partner:
            return trump
        return c[1]
    def power(c):
        if suit(c) == trump:
            if c[0] == 'J':
                return 100 if c[1] == trump else 99
            return 50 + '9TJQKA'.index(c[0])
        return '9TJQKA'.index(c[0])
    best = 0
    for i in range(1, len(cards)):
        c = cards[i]
        b = cards[best]
        if suit(c) == suit(b) and power(c) > power(b):
            best = i
        elif suit(c) == trump and suit(b) != trump:
            best = i
    return (leader + best) % 4
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['9S', 'JD', 'AC', '9H'], 0, 'H'], 1], [[['9H', 'JS', 'TH', 'QC'], 3, 'C'], 0], [[['KS', '9H', 'QC', '9D'], 3, 'S'], 3], [[['JD', 'QD', 'AD', 'AC'], 0, 'H'], 0], [[['JD', 'AS', 'JC', 'QH'], 3, 'S'], 1], [[['KH', '9S', 'JH', 'QS'], 3, 'D'], 1], [[['TS', 'JS', 'TC', 'QC'], 2, 'S'], 3], [[['JH', 'AH', 'KD', 'JD'], 2, 'D'], 1]], [[[['TH', 'KH', 'JD', 'JC'], 2, 'H'], 0], [[['JD', '9H', 'TH', 'AS'], 0, 'H'], 0], [[['JD', 'TS', '9C', 'QD'], 3, 'C'], 1], [[['QS', 'KD', '9S', '9C'], 1, 'S'], 1], [[['TH', 'AS', 'TD', 'KD'], 2, 'C'], 2], [[['QS', 'TC', 'KH', 'AS'], 0, 'D'], 3], [[['KD', 'TH', 'AD', 'AH'], 2, 'C'], 0], [[['JC', 'TH', '9H', 'QD'], 1, 'D'], 0]], [[[['JD', 'AS', 'JC', 'QH'], 3, 'S'], 1], [[['JC', 'TH', '9H', 'QD'], 1, 'D'], 0], [[['9D', 'AS', 'JS', 'TD'], 0, 'S'], 2], [[['JS', 'TH', 'TC', 'JD'], 2, 'C'], 2], [[['TC', 'JS', 'AC', 'TH'], 1, 'C'], 2], [[['QC', 'QD', 'KC', 'JS'], 2, 'C'], 1], [[['AC', 'TC', 'AH', 'JS'], 1, 'C'], 0], [[['JD', 'QD', 'KC', 'JC'], 3, 'S'], 2]], [[[['KC', 'KD', 'JS', 'QH'], 1, 'C'], 3], [[['JD', 'QD', 'KC', 'JC'], 3, 'S'], 2], [[['TH', 'AH', 'JD', 'QD'], 2, 'S'], 3], [[['KS', '9D', 'TD', 'JS'], 0, 'C'], 3], [[['9C', 'JH', 'JS', 'TC'], 2, 'C'], 0], [[['QD', 'AH', 'KS', 'TC'], 3, 'H'], 0], [[['AS', 'TC', 'TD', 'QS'], 1, 'S'], 1], [[['TS', '9C', '9H', 'JS'], 3, 'C'], 2]], [[[['QC', 'QD', 'KC', 'JS'], 2, 'C'], 1], [[['TC', 'JD', 'QS', 'JC'], 3, 'C'], 2], [[['AH', 'JH', '9C', 'TS'], 0, 'D'], 1], [[['AD', 'KS', 'JH', 'JD'], 2, 'H'], 0], [[['TH', 'JS', 'QC', 'JC'], 2, 'C'], 1], [[['KC', '9H', 'JS', 'JC'], 2, 'S'], 0], [[['KD', 'AS', 'JD', 'JH'], 0, 'D'], 2], [[['JD', 'JS', 'QC', '9H'], 3, 'C'], 0]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("trick 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 fixtureActualExpectedOutcome
trick case 031Failed
trick case 120Failed
trick case 233Passed
trick case 320Failed
trick case 401Failed
trick case 531Failed
trick case 633Passed
trick case 711Passed

SHA-256 / dc41f6a5a91f0befe12def9459cfd7a6f4e8f70bd04f55558accf2fcf972f2ae

3 / The verified repair

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

N = 1
observations = []
def solve(x):
    cards, leader, trump = x
    partner = {'S': 'C', 'C': 'S', 'H': 'D', 'D': 'H'}[trump]
    def suit(c):
        if c[0] == 'J' and c[1] == partner:
            return trump
        return c[1]
    def power(c):
        if suit(c) == trump:
            if c[0] == 'J':
                return 100 if c[1] == trump else 99
            return 50 + '9TJQKA'.index(c[0])
        return '9TJQKA'.index(c[0])
    best = 0
    for i in range(1, len(cards)):
        c = cards[i]
        b = cards[best]
        if suit(c) == suit(b) and power(c) > power(b):
            best = i
        elif suit(c) == trump and suit(b) != trump:
            best = i
    return (leader + best) % 4
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['9S', 'JD', 'AC', '9H'], 0, 'H'], 1], [[['9H', 'JS', 'TH', 'QC'], 3, 'C'], 0], [[['KS', '9H', 'QC', '9D'], 3, 'S'], 3], [[['JD', 'QD', 'AD', 'AC'], 0, 'H'], 0], [[['JD', 'AS', 'JC', 'QH'], 3, 'S'], 1], [[['KH', '9S', 'JH', 'QS'], 3, 'D'], 1], [[['TS', 'JS', 'TC', 'QC'], 2, 'S'], 3], [[['JH', 'AH', 'KD', 'JD'], 2, 'D'], 1]], [[[['TH', 'KH', 'JD', 'JC'], 2, 'H'], 0], [[['JD', '9H', 'TH', 'AS'], 0, 'H'], 0], [[['JD', 'TS', '9C', 'QD'], 3, 'C'], 1], [[['QS', 'KD', '9S', '9C'], 1, 'S'], 1], [[['TH', 'AS', 'TD', 'KD'], 2, 'C'], 2], [[['QS', 'TC', 'KH', 'AS'], 0, 'D'], 3], [[['KD', 'TH', 'AD', 'AH'], 2, 'C'], 0], [[['JC', 'TH', '9H', 'QD'], 1, 'D'], 0]], [[[['JD', 'AS', 'JC', 'QH'], 3, 'S'], 1], [[['JC', 'TH', '9H', 'QD'], 1, 'D'], 0], [[['9D', 'AS', 'JS', 'TD'], 0, 'S'], 2], [[['JS', 'TH', 'TC', 'JD'], 2, 'C'], 2], [[['TC', 'JS', 'AC', 'TH'], 1, 'C'], 2], [[['QC', 'QD', 'KC', 'JS'], 2, 'C'], 1], [[['AC', 'TC', 'AH', 'JS'], 1, 'C'], 0], [[['JD', 'QD', 'KC', 'JC'], 3, 'S'], 2]], [[[['KC', 'KD', 'JS', 'QH'], 1, 'C'], 3], [[['JD', 'QD', 'KC', 'JC'], 3, 'S'], 2], [[['TH', 'AH', 'JD', 'QD'], 2, 'S'], 3], [[['KS', '9D', 'TD', 'JS'], 0, 'C'], 3], [[['9C', 'JH', 'JS', 'TC'], 2, 'C'], 0], [[['QD', 'AH', 'KS', 'TC'], 3, 'H'], 0], [[['AS', 'TC', 'TD', 'QS'], 1, 'S'], 1], [[['TS', '9C', '9H', 'JS'], 3, 'C'], 2]], [[[['QC', 'QD', 'KC', 'JS'], 2, 'C'], 1], [[['TC', 'JD', 'QS', 'JC'], 3, 'C'], 2], [[['AH', 'JH', '9C', 'TS'], 0, 'D'], 1], [[['AD', 'KS', 'JH', 'JD'], 2, 'H'], 0], [[['TH', 'JS', 'QC', 'JC'], 2, 'C'], 1], [[['KC', '9H', 'JS', 'JC'], 2, 'S'], 0], [[['KD', 'AS', 'JD', 'JH'], 0, 'D'], 2], [[['JD', 'JS', 'QC', '9H'], 3, 'C'], 0]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("trick 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 fixtureActualExpectedOutcome
trick case 011Passed
trick case 100Passed
trick case 233Passed
trick case 300Passed
trick case 411Passed
trick case 511Passed
trick case 633Passed
trick case 711Passed

SHA-256 / b0b6c996e1759bf5b3c2f168c221d666f961ee04ea38bc740b4dc9cd3214824c

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

Case digest / 975083f0c2701bbeccf28acc85a704230063198a6df59ef7511ff25ca20e15a1