FA-83561 / Card game rule engines / Open access
Non-adjacent equal ranks score as pegging pairs · case 01
A five played after 5-6 pegs a pair.
ROOT CAUSE
The backward scan does not stop at the first different rank.
VERIFIED REPAIR
Count only the unbroken run of equal ranks ending at the new card.
Unsuccessful approach: Scanning from the oldest card instead of the newest measures the wrong run.
Case contract
Input [cards_in_current_count, new_card]. Values A=1, T/J/Q/K=10; a count above 31 is "illegal". Points: count 15 -> 2, count 31 -> 2; the new card with the immediately preceding same-rank run scores 2/6/12; the longest trailing sequence of 3+ cards whose ranks are consecutive in any order scores its length. Return [points, count].
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):
pile, card = x
order = 'A23456789TJQK'
def val(c):
return min(order.index(c[0]) + 1, 10)
count = sum(val(c) for c in pile) + val(card)
if count > 31:
return 'illegal'
seq = pile + [card]
pts = 0
if count == 15:
pts += 2
if count == 31:
pts += 2
same = 1
for c in reversed(seq[:-1]):
if c[0] == card[0]:
same += 1
pts += {1: 0, 2: 2, 3: 6, 4: 12}[same]
best = 0
for L in range(3, len(seq) + 1):
tail = sorted(order.index(c[0]) for c in seq[-L:])
if all(tail[i + 1] == tail[i] + 1 for i in range(L - 1)):
best = L
pts += best
return [pts, count]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['TD'], 'JC'], [0, 20]], [[['4D', 'KS', '2C', 'TC'], 'TS'], 'illegal'], [[['JD', '8D', 'QD'], '9D'], 'illegal'], [[['8S', 'TD', '2H', 'QH'], '5S'], 'illegal'], [[['6S', '7D', '7C', 'KS'], '3C'], 'illegal'], [[['5C', '7H'], 'TS'], [0, 22]], [[['JC', 'JC', '3C'], '3C'], [2, 26]], [[['5S', 'KS'], '5D'], [0, 20]]], [[[[], '5D'], [0, 5]], [[['8C', '2D', '8S', '5H', 'AH'], 'AS'], [2, 25]], [[['5D', '4C', '3S', 'KS'], 'KC'], 'illegal'], [[['9C', '7D'], 'KD'], [0, 26]], [[[], '7C'], [0, 7]], [[['7H'], '7C'], [2, 14]], [[['QS', '6C'], '6C'], [2, 22]], [[['AH', '8S', '9C'], '8H'], [0, 26]]], [[[['5D', 'JD', '2S', '6H', 'AH'], '4C'], [0, 28]], [[['AD'], 'AS'], [2, 2]], [[['JC'], 'JD'], [2, 20]], [[['TS', '4H', '2H', '7S'], 'QD'], 'illegal'], [[['QS', '3C'], '3C'], [2, 16]], [[['QS', '7D', '6S'], '9S'], 'illegal'], [[['5C', '4D'], '4C'], [2, 13]], [[['7C', 'AD', '5S', '4S'], 'AS'], [0, 18]]], [[[['AD', '5H', 'KD', '6D'], '6S'], [2, 28]], [[['2H', '4S', 'TC', '6H', '8D'], '8H'], 'illegal'], [[['9D', '2C', 'TC'], 'KD'], [2, 31]], [[['AS', '2D'], 'JH'], [0, 13]], [[[], 'AD'], [0, 1]], [[['JH'], '7C'], [0, 17]], [[['7D', '7D', '6D', '3D'], '7C'], [0, 30]], [[['7D', '7D', '6D', '3D'], '7C'], [0, 30]]], [[[[], '3S'], [0, 3]], [[['TD', '5S', 'AD'], 'AD'], [2, 17]], [[[], '5S'], [0, 5]], [[['6H', 'AD'], 'TD'], [0, 17]], [[['JC', 'JC', '3C'], '3C'], [2, 26]], [[['5C', '3S', '8D', '7D'], 'QC'], 'illegal'], [[['9D', '7H', '2S'], '2C'], [2, 20]], [[['5C', '6H', '5S'], '5H'], [2, 21]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("pegging 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 |
|---|---|---|---|
| pegging case 0 | [0, 20] | [0, 20] | Passed |
| pegging case 1 | illegal | illegal | Passed |
| pegging case 2 | illegal | illegal | Passed |
| pegging case 3 | illegal | illegal | Passed |
| pegging case 4 | illegal | illegal | Passed |
| pegging case 5 | [0, 22] | [0, 22] | Passed |
| pegging case 6 | [2, 26] | [2, 26] | Passed |
| pegging case 7 | [2, 20] | [0, 20] | Failed |
SHA-256 / e552536ba7f67bcc6accddfe1e45a5ce2f25fd2692a8944b3d7e04bbcf614614
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
pile, card = x
order = 'A23456789TJQK'
def val(c):
return min(order.index(c[0]) + 1, 10)
count = sum(val(c) for c in pile) + val(card)
if count > 31:
return 'illegal'
seq = pile + [card]
pts = 0
if count == 15:
pts += 2
if count == 31:
pts += 2
same = 1
for c in seq[:-1]:
if c[0] == card[0]:
same += 1
else:
break
pts += {1: 0, 2: 2, 3: 6, 4: 12}[same]
best = 0
for L in range(3, len(seq) + 1):
tail = sorted(order.index(c[0]) for c in seq[-L:])
if all(tail[i + 1] == tail[i] + 1 for i in range(L - 1)):
best = L
pts += best
return [pts, count]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['TD'], 'JC'], [0, 20]], [[['4D', 'KS', '2C', 'TC'], 'TS'], 'illegal'], [[['JD', '8D', 'QD'], '9D'], 'illegal'], [[['8S', 'TD', '2H', 'QH'], '5S'], 'illegal'], [[['6S', '7D', '7C', 'KS'], '3C'], 'illegal'], [[['5C', '7H'], 'TS'], [0, 22]], [[['JC', 'JC', '3C'], '3C'], [2, 26]], [[['5S', 'KS'], '5D'], [0, 20]]], [[[[], '5D'], [0, 5]], [[['8C', '2D', '8S', '5H', 'AH'], 'AS'], [2, 25]], [[['5D', '4C', '3S', 'KS'], 'KC'], 'illegal'], [[['9C', '7D'], 'KD'], [0, 26]], [[[], '7C'], [0, 7]], [[['7H'], '7C'], [2, 14]], [[['QS', '6C'], '6C'], [2, 22]], [[['AH', '8S', '9C'], '8H'], [0, 26]]], [[[['5D', 'JD', '2S', '6H', 'AH'], '4C'], [0, 28]], [[['AD'], 'AS'], [2, 2]], [[['JC'], 'JD'], [2, 20]], [[['TS', '4H', '2H', '7S'], 'QD'], 'illegal'], [[['QS', '3C'], '3C'], [2, 16]], [[['QS', '7D', '6S'], '9S'], 'illegal'], [[['5C', '4D'], '4C'], [2, 13]], [[['7C', 'AD', '5S', '4S'], 'AS'], [0, 18]]], [[[['AD', '5H', 'KD', '6D'], '6S'], [2, 28]], [[['2H', '4S', 'TC', '6H', '8D'], '8H'], 'illegal'], [[['9D', '2C', 'TC'], 'KD'], [2, 31]], [[['AS', '2D'], 'JH'], [0, 13]], [[[], 'AD'], [0, 1]], [[['JH'], '7C'], [0, 17]], [[['7D', '7D', '6D', '3D'], '7C'], [0, 30]], [[['7D', '7D', '6D', '3D'], '7C'], [0, 30]]], [[[[], '3S'], [0, 3]], [[['TD', '5S', 'AD'], 'AD'], [2, 17]], [[[], '5S'], [0, 5]], [[['6H', 'AD'], 'TD'], [0, 17]], [[['JC', 'JC', '3C'], '3C'], [2, 26]], [[['5C', '3S', '8D', '7D'], 'QC'], 'illegal'], [[['9D', '7H', '2S'], '2C'], [2, 20]], [[['5C', '6H', '5S'], '5H'], [2, 21]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("pegging 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 |
|---|---|---|---|
| pegging case 0 | [0, 20] | [0, 20] | Passed |
| pegging case 1 | illegal | illegal | Passed |
| pegging case 2 | illegal | illegal | Passed |
| pegging case 3 | illegal | illegal | Passed |
| pegging case 4 | illegal | illegal | Passed |
| pegging case 5 | [0, 22] | [0, 22] | Passed |
| pegging case 6 | [0, 26] | [2, 26] | Failed |
| pegging case 7 | [2, 20] | [0, 20] | Failed |
SHA-256 / de7bf264a4c89ceedaac2c0ba595e656fef7abf235e5e4da81158f8e2c723711
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
pile, card = x
order = 'A23456789TJQK'
def val(c):
return min(order.index(c[0]) + 1, 10)
count = sum(val(c) for c in pile) + val(card)
if count > 31:
return 'illegal'
seq = pile + [card]
pts = 0
if count == 15:
pts += 2
if count == 31:
pts += 2
same = 1
for c in reversed(seq[:-1]):
if c[0] == card[0]:
same += 1
else:
break
pts += {1: 0, 2: 2, 3: 6, 4: 12}[same]
best = 0
for L in range(3, len(seq) + 1):
tail = sorted(order.index(c[0]) for c in seq[-L:])
if all(tail[i + 1] == tail[i] + 1 for i in range(L - 1)):
best = L
pts += best
return [pts, count]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['TD'], 'JC'], [0, 20]], [[['4D', 'KS', '2C', 'TC'], 'TS'], 'illegal'], [[['JD', '8D', 'QD'], '9D'], 'illegal'], [[['8S', 'TD', '2H', 'QH'], '5S'], 'illegal'], [[['6S', '7D', '7C', 'KS'], '3C'], 'illegal'], [[['5C', '7H'], 'TS'], [0, 22]], [[['JC', 'JC', '3C'], '3C'], [2, 26]], [[['5S', 'KS'], '5D'], [0, 20]]], [[[[], '5D'], [0, 5]], [[['8C', '2D', '8S', '5H', 'AH'], 'AS'], [2, 25]], [[['5D', '4C', '3S', 'KS'], 'KC'], 'illegal'], [[['9C', '7D'], 'KD'], [0, 26]], [[[], '7C'], [0, 7]], [[['7H'], '7C'], [2, 14]], [[['QS', '6C'], '6C'], [2, 22]], [[['AH', '8S', '9C'], '8H'], [0, 26]]], [[[['5D', 'JD', '2S', '6H', 'AH'], '4C'], [0, 28]], [[['AD'], 'AS'], [2, 2]], [[['JC'], 'JD'], [2, 20]], [[['TS', '4H', '2H', '7S'], 'QD'], 'illegal'], [[['QS', '3C'], '3C'], [2, 16]], [[['QS', '7D', '6S'], '9S'], 'illegal'], [[['5C', '4D'], '4C'], [2, 13]], [[['7C', 'AD', '5S', '4S'], 'AS'], [0, 18]]], [[[['AD', '5H', 'KD', '6D'], '6S'], [2, 28]], [[['2H', '4S', 'TC', '6H', '8D'], '8H'], 'illegal'], [[['9D', '2C', 'TC'], 'KD'], [2, 31]], [[['AS', '2D'], 'JH'], [0, 13]], [[[], 'AD'], [0, 1]], [[['JH'], '7C'], [0, 17]], [[['7D', '7D', '6D', '3D'], '7C'], [0, 30]], [[['7D', '7D', '6D', '3D'], '7C'], [0, 30]]], [[[[], '3S'], [0, 3]], [[['TD', '5S', 'AD'], 'AD'], [2, 17]], [[[], '5S'], [0, 5]], [[['6H', 'AD'], 'TD'], [0, 17]], [[['JC', 'JC', '3C'], '3C'], [2, 26]], [[['5C', '3S', '8D', '7D'], 'QC'], 'illegal'], [[['9D', '7H', '2S'], '2C'], [2, 20]], [[['5C', '6H', '5S'], '5H'], [2, 21]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("pegging 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 |
|---|---|---|---|
| pegging case 0 | [0, 20] | [0, 20] | Passed |
| pegging case 1 | illegal | illegal | Passed |
| pegging case 2 | illegal | illegal | Passed |
| pegging case 3 | illegal | illegal | Passed |
| pegging case 4 | illegal | illegal | Passed |
| pegging case 5 | [0, 22] | [0, 22] | Passed |
| pegging case 6 | [2, 26] | [2, 26] | Passed |
| pegging case 7 | [0, 20] | [0, 20] | Passed |
SHA-256 / 0d761cee2f3d650bf18cfb148bff186734bf662c4f25698e1a929755c2070d0f
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:22.637986+00:00.
Case digest / 2e28e97abee8784dac461d45deb8bbaa03d9dc76eca68c744122605b144de7bf