FA-83456 / Card game rule engines / Open access
A set contract loses only the missing tricks · case 01
Going down by one on a bid of eight costs 10 instead of 80.
ROOT CAUSE
The set penalty multiplies the shortfall.
VERIFIED REPAIR
A set costs 10 times the full bid.
Unsuccessful approach: Charging ten per trick actually taken inverts the penalty.
Case contract
Input [[bid1, bid2], [tricks1, tricks2], bags_before]. Nil (0) bids score +100 if the player took no tricks, else -100 and their tricks become bags. Other bids combine into a contract made by the non-nil players tricks: made -> 10*bid + 1 per overtrick (overtricks are bags); set -> -10*bid. Every 10 accumulated bags costs 100 and removes 10 bags. Return [score_delta, bags].
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):
bids, tricks, bags = x
score = 0
contract = 0
made = 0
for b, t in zip(bids, tricks):
if b == 0:
if t == 0:
score += 100
else:
score -= 100
bags += t
else:
contract += b
made += t
if made >= contract:
score += 10 * contract
over = made - contract
score += over
bags += over
else:
score -= 10 * (contract - made)
while bags >= 10:
score -= 100
bags -= 10
return [score, bags]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[[2, 6], [0, 4], 7], [-80, 7]], [[[0, 2], [12, 1], 4], [-220, 6]], [[[3, 5], [1, 12], 3], [85, 8]], [[[5, 5], [12, 1], 1], [103, 4]], [[[0, 4], [3, 10], 5], [-154, 4]], [[[3, 6], [3, 8], 9], [-8, 1]], [[[5, 5], [12, 0], 5], [102, 7]], [[[5, 6], [7, 3], 6], [-110, 6]]], [[[[1, 4], [6, 4], 5], [-45, 0]], [[[4, 0], [1, 8], 8], [-240, 6]], [[[1, 0], [9, 2], 4], [-182, 4]], [[[5, 1], [6, 7], 3], [-33, 0]], [[[1, 4], [3, 8], 0], [56, 6]], [[[1, 6], [2, 0], 5], [-70, 5]], [[[4, 5], [9, 4], 4], [94, 8]], [[[2, 2], [0, 1], 8], [-40, 8]]], [[[[2, 3], [8, 3], 4], [-44, 0]], [[[1, 5], [7, 0], 2], [61, 3]], [[[3, 4], [11, 1], 1], [75, 6]], [[[3, 1], [12, 0], 9], [-52, 7]], [[[5, 6], [7, 3], 6], [-110, 6]], [[[6, 0], [8, 3], 7], [-138, 2]], [[[6, 2], [3, 4], 8], [-80, 8]], [[[4, 3], [0, 6], 8], [-70, 8]]], [[[[1, 5], [10, 2], 7], [-34, 3]], [[[3, 5], [12, 0], 0], [84, 4]], [[[0, 4], [1, 4], 9], [-160, 0]], [[[6, 2], [3, 4], 8], [-80, 8]], [[[3, 2], [8, 2], 6], [-45, 1]], [[[3, 4], [7, 2], 9], [-28, 1]], [[[2, 2], [0, 1], 8], [-40, 8]], [[[6, 5], [3, 4], 9], [-110, 9]]], [[[[5, 3], [7, 2], 7], [81, 8]], [[[2, 2], [10, 1], 9], [-53, 6]], [[[3, 5], [9, 2], 5], [83, 8]], [[[5, 3], [7, 5], 2], [84, 6]], [[[6, 2], [8, 0], 9], [80, 9]], [[[3, 0], [2, 0], 9], [70, 9]], [[[5, 5], [1, 6], 8], [-100, 8]], [[[6, 6], [0, 5], 6], [-120, 6]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("team score 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 |
|---|---|---|---|
| team score case 0 | [-40, 7] | [-80, 7] | Failed |
| team score case 1 | [-210, 6] | [-220, 6] | Failed |
| team score case 2 | [85, 8] | [85, 8] | Passed |
| team score case 3 | [103, 4] | [103, 4] | Passed |
| team score case 4 | [-154, 4] | [-154, 4] | Passed |
| team score case 5 | [-8, 1] | [-8, 1] | Passed |
| team score case 6 | [102, 7] | [102, 7] | Passed |
| team score case 7 | [-10, 6] | [-110, 6] | Failed |
SHA-256 / 416e47875f7df73832d83f2d8861e555d6cd6dfb6f897a7317bf35a8b9ca9c53
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
bids, tricks, bags = x
score = 0
contract = 0
made = 0
for b, t in zip(bids, tricks):
if b == 0:
if t == 0:
score += 100
else:
score -= 100
bags += t
else:
contract += b
made += t
if made >= contract:
score += 10 * contract
over = made - contract
score += over
bags += over
else:
score -= 10 * made
while bags >= 10:
score -= 100
bags -= 10
return [score, bags]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[[2, 6], [0, 4], 7], [-80, 7]], [[[0, 2], [12, 1], 4], [-220, 6]], [[[3, 5], [1, 12], 3], [85, 8]], [[[5, 5], [12, 1], 1], [103, 4]], [[[0, 4], [3, 10], 5], [-154, 4]], [[[3, 6], [3, 8], 9], [-8, 1]], [[[5, 5], [12, 0], 5], [102, 7]], [[[5, 6], [7, 3], 6], [-110, 6]]], [[[[1, 4], [6, 4], 5], [-45, 0]], [[[4, 0], [1, 8], 8], [-240, 6]], [[[1, 0], [9, 2], 4], [-182, 4]], [[[5, 1], [6, 7], 3], [-33, 0]], [[[1, 4], [3, 8], 0], [56, 6]], [[[1, 6], [2, 0], 5], [-70, 5]], [[[4, 5], [9, 4], 4], [94, 8]], [[[2, 2], [0, 1], 8], [-40, 8]]], [[[[2, 3], [8, 3], 4], [-44, 0]], [[[1, 5], [7, 0], 2], [61, 3]], [[[3, 4], [11, 1], 1], [75, 6]], [[[3, 1], [12, 0], 9], [-52, 7]], [[[5, 6], [7, 3], 6], [-110, 6]], [[[6, 0], [8, 3], 7], [-138, 2]], [[[6, 2], [3, 4], 8], [-80, 8]], [[[4, 3], [0, 6], 8], [-70, 8]]], [[[[1, 5], [10, 2], 7], [-34, 3]], [[[3, 5], [12, 0], 0], [84, 4]], [[[0, 4], [1, 4], 9], [-160, 0]], [[[6, 2], [3, 4], 8], [-80, 8]], [[[3, 2], [8, 2], 6], [-45, 1]], [[[3, 4], [7, 2], 9], [-28, 1]], [[[2, 2], [0, 1], 8], [-40, 8]], [[[6, 5], [3, 4], 9], [-110, 9]]], [[[[5, 3], [7, 2], 7], [81, 8]], [[[2, 2], [10, 1], 9], [-53, 6]], [[[3, 5], [9, 2], 5], [83, 8]], [[[5, 3], [7, 5], 2], [84, 6]], [[[6, 2], [8, 0], 9], [80, 9]], [[[3, 0], [2, 0], 9], [70, 9]], [[[5, 5], [1, 6], 8], [-100, 8]], [[[6, 6], [0, 5], 6], [-120, 6]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("team score 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 |
|---|---|---|---|
| team score case 0 | [-40, 7] | [-80, 7] | Failed |
| team score case 1 | [-210, 6] | [-220, 6] | Failed |
| team score case 2 | [85, 8] | [85, 8] | Passed |
| team score case 3 | [103, 4] | [103, 4] | Passed |
| team score case 4 | [-154, 4] | [-154, 4] | Passed |
| team score case 5 | [-8, 1] | [-8, 1] | Passed |
| team score case 6 | [102, 7] | [102, 7] | Passed |
| team score case 7 | [-100, 6] | [-110, 6] | Failed |
SHA-256 / 30dd461b48f9bd28e5b82aa9d32a4522da85ceda9fedeb5eea54d32a04f893fc
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
bids, tricks, bags = x
score = 0
contract = 0
made = 0
for b, t in zip(bids, tricks):
if b == 0:
if t == 0:
score += 100
else:
score -= 100
bags += t
else:
contract += b
made += t
if made >= contract:
score += 10 * contract
over = made - contract
score += over
bags += over
else:
score -= 10 * contract
while bags >= 10:
score -= 100
bags -= 10
return [score, bags]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[[2, 6], [0, 4], 7], [-80, 7]], [[[0, 2], [12, 1], 4], [-220, 6]], [[[3, 5], [1, 12], 3], [85, 8]], [[[5, 5], [12, 1], 1], [103, 4]], [[[0, 4], [3, 10], 5], [-154, 4]], [[[3, 6], [3, 8], 9], [-8, 1]], [[[5, 5], [12, 0], 5], [102, 7]], [[[5, 6], [7, 3], 6], [-110, 6]]], [[[[1, 4], [6, 4], 5], [-45, 0]], [[[4, 0], [1, 8], 8], [-240, 6]], [[[1, 0], [9, 2], 4], [-182, 4]], [[[5, 1], [6, 7], 3], [-33, 0]], [[[1, 4], [3, 8], 0], [56, 6]], [[[1, 6], [2, 0], 5], [-70, 5]], [[[4, 5], [9, 4], 4], [94, 8]], [[[2, 2], [0, 1], 8], [-40, 8]]], [[[[2, 3], [8, 3], 4], [-44, 0]], [[[1, 5], [7, 0], 2], [61, 3]], [[[3, 4], [11, 1], 1], [75, 6]], [[[3, 1], [12, 0], 9], [-52, 7]], [[[5, 6], [7, 3], 6], [-110, 6]], [[[6, 0], [8, 3], 7], [-138, 2]], [[[6, 2], [3, 4], 8], [-80, 8]], [[[4, 3], [0, 6], 8], [-70, 8]]], [[[[1, 5], [10, 2], 7], [-34, 3]], [[[3, 5], [12, 0], 0], [84, 4]], [[[0, 4], [1, 4], 9], [-160, 0]], [[[6, 2], [3, 4], 8], [-80, 8]], [[[3, 2], [8, 2], 6], [-45, 1]], [[[3, 4], [7, 2], 9], [-28, 1]], [[[2, 2], [0, 1], 8], [-40, 8]], [[[6, 5], [3, 4], 9], [-110, 9]]], [[[[5, 3], [7, 2], 7], [81, 8]], [[[2, 2], [10, 1], 9], [-53, 6]], [[[3, 5], [9, 2], 5], [83, 8]], [[[5, 3], [7, 5], 2], [84, 6]], [[[6, 2], [8, 0], 9], [80, 9]], [[[3, 0], [2, 0], 9], [70, 9]], [[[5, 5], [1, 6], 8], [-100, 8]], [[[6, 6], [0, 5], 6], [-120, 6]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("team score 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 |
|---|---|---|---|
| team score case 0 | [-80, 7] | [-80, 7] | Passed |
| team score case 1 | [-220, 6] | [-220, 6] | Passed |
| team score case 2 | [85, 8] | [85, 8] | Passed |
| team score case 3 | [103, 4] | [103, 4] | Passed |
| team score case 4 | [-154, 4] | [-154, 4] | Passed |
| team score case 5 | [-8, 1] | [-8, 1] | Passed |
| team score case 6 | [102, 7] | [102, 7] | Passed |
| team score case 7 | [-110, 6] | [-110, 6] | Passed |
SHA-256 / 0c59d06e99778465912cbcbf1451c44c39d64f43026d9ef95a4a351b4eb83f54
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:21.828512+00:00.
Case digest / a61d1e198217f7456ce53c7fb71e7cb28c644a7d6ab28dd4f964529de5c534f1