FA-83441 / Card game rule engines / Open access
Bag penalty discards bags beyond ten · case 01
Twelve bags reset to zero instead of two.
ROOT CAUSE
The penalty branch zeroes the bag count.
VERIFIED REPAIR
Subtract ten bags per penalty and keep the remainder.
Unsuccessful approach: Penalising only above ten lets a team sit at exactly ten bags.
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
if bags >= 10:
score -= 100
bags = 0
return [score, bags]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[[6, 1], [11, 1], 8], [-25, 3]], [[[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, 1], [12, 1], 3], [-33, 0]]], [[[[0, 2], [12, 1], 4], [-220, 6]], [[[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]], [[[6, 0], [0, 10], 0], [-260, 0]]], [[[[4, 0], [1, 8], 8], [-240, 6]], [[[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]], [[[2, 5], [13, 0], 1], [76, 7]], [[[1, 1], [7, 4], 1], [-71, 0]]], [[[[1, 4], [6, 4], 5], [-45, 0]], [[[6, 0], [8, 3], 7], [-138, 2]], [[[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]], [[[3, 5], [7, 3], 2], [82, 4]], [[[5, 3], [7, 2], 7], [81, 8]]], [[[[3, 4], [7, 2], 9], [-28, 1]], [[[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]], [[[6, 4], [1, 10], 5], [101, 6]], [[[5, 1], [12, 1], 3], [-33, 0]]]]
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 | [-25, 0] | [-25, 3] | Failed |
| team score case 1 | [-220, 0] | [-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, 0] | [-154, 4] | Failed |
| team score case 5 | [-8, 0] | [-8, 1] | Failed |
| team score case 6 | [102, 7] | [102, 7] | Passed |
| team score case 7 | [-33, 0] | [-33, 0] | Passed |
SHA-256 / ccf12418676c32f7c2b020b877762f76446b5dfc615b9f973f26a5a480d9bcc4
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 * 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 = [[[[[6, 1], [11, 1], 8], [-25, 3]], [[[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, 1], [12, 1], 3], [-33, 0]]], [[[[0, 2], [12, 1], 4], [-220, 6]], [[[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]], [[[6, 0], [0, 10], 0], [-260, 0]]], [[[[4, 0], [1, 8], 8], [-240, 6]], [[[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]], [[[2, 5], [13, 0], 1], [76, 7]], [[[1, 1], [7, 4], 1], [-71, 0]]], [[[[1, 4], [6, 4], 5], [-45, 0]], [[[6, 0], [8, 3], 7], [-138, 2]], [[[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]], [[[3, 5], [7, 3], 2], [82, 4]], [[[5, 3], [7, 2], 7], [81, 8]]], [[[[3, 4], [7, 2], 9], [-28, 1]], [[[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]], [[[6, 4], [1, 10], 5], [101, 6]], [[[5, 1], [12, 1], 3], [-33, 0]]]]
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 | [-25, 3] | [-25, 3] | 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 | [67, 10] | [-33, 0] | Failed |
SHA-256 / 5977eb90dddfec4042ca23a8b440076ae5a94abeaf7fac5b01a33458626939fc
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 = [[[[[6, 1], [11, 1], 8], [-25, 3]], [[[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, 1], [12, 1], 3], [-33, 0]]], [[[[0, 2], [12, 1], 4], [-220, 6]], [[[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]], [[[6, 0], [0, 10], 0], [-260, 0]]], [[[[4, 0], [1, 8], 8], [-240, 6]], [[[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]], [[[2, 5], [13, 0], 1], [76, 7]], [[[1, 1], [7, 4], 1], [-71, 0]]], [[[[1, 4], [6, 4], 5], [-45, 0]], [[[6, 0], [8, 3], 7], [-138, 2]], [[[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]], [[[3, 5], [7, 3], 2], [82, 4]], [[[5, 3], [7, 2], 7], [81, 8]]], [[[[3, 4], [7, 2], 9], [-28, 1]], [[[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]], [[[6, 4], [1, 10], 5], [101, 6]], [[[5, 1], [12, 1], 3], [-33, 0]]]]
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 | [-25, 3] | [-25, 3] | 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 | [-33, 0] | [-33, 0] | Passed |
SHA-256 / 43892ac272b7825df13ce4cdee6a01292a5ca72239f3a739359a5ea0de72a4e7
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.565259+00:00.
Case digest / bca9c09f3c829c85187b4935fa711b3e9f2717f4a61e6ca8a5834f4b52a5d8bc