FA-83051 / Go territory scoring / Open access
Pass stones are credited to the passing player · case 01
Passing earns the passer a prisoner.
ROOT CAUSE
Pass counts are added to the passer rather than the opponent.
VERIFIED REPAIR
A black pass gives white a prisoner and vice versa.
Unsuccessful approach: Forgetting black passes entirely still leaves white short of prisoners.
Case contract
Input [terr_b, terr_w, prisoners_b, prisoners_w, passes, komi_tenths]; passes lists passing colours in order. Each pass gives one prisoner to the opponent; if the final pass was black, white hands one extra stone to black. Return [black_tenths, white_tenths, winner] with winner B, W or tie.
Why this case matters
Go servers and scoring tools compute this value automatically; a wrong answer changes a game result.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
tb, tw, cb, cw, passes, komi = x
pb = cb + passes.count('B')
pw = cw + passes.count('W')
if passes and passes[-1] == 'B':
pb += 1
sb = (tb + pb) * 10
sw = (tw + pw) * 10 + komi
if sb > sw:
winner = 'B'
elif sw > sb:
winner = 'W'
else:
winner = 'tie'
return [sb, sw, winner]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[11, 24, 5, 1, ['B'], 75], [170, 335, 'W']], [[12, 29, 2, 1, ['B'], 75], [150, 385, 'W']], [[9, 19, 1, 1, ['W'], 5], [110, 205, 'W']], [[19, 16, 2, 4, ['B'], 75], [220, 285, 'W']], [[28, 11, 4, 3, ['B', 'W', 'W', 'B'], 0], [350, 160, 'B']], [[5, 17, 2, 2, [], 5], [70, 195, 'W']], [[16, 18, 1, 5, ['B'], 5], [180, 245, 'W']], [[22, 11, 2, 4, ['B', 'B'], 75], [250, 245, 'B']]], [[[14, 7, 4, 0, ['B', 'B'], 0], [190, 90, 'B']], [[22, 11, 2, 4, ['B', 'B'], 75], [250, 245, 'B']], [[28, 12, 2, 1, ['B', 'W'], 75], [310, 215, 'B']], [[9, 10, 4, 5, ['W', 'W', 'B', 'W'], 70], [160, 230, 'W']], [[19, 26, 4, 1, ['W'], 0], [240, 270, 'W']], [[25, 8, 5, 0, ['W', 'W', 'W', 'B'], 70], [340, 160, 'B']], [[15, 27, 0, 4, ['B', 'W'], 0], [160, 320, 'W']], [[27, 20, 5, 1, ['B'], 70], [330, 290, 'B']]], [[[3, 12, 5, 1, ['W'], 5], [90, 135, 'W']], [[15, 27, 0, 4, ['B', 'W'], 0], [160, 320, 'W']], [[23, 20, 1, 3, ['W', 'W'], 75], [260, 305, 'W']], [[9, 14, 1, 0, ['B', 'B', 'B', 'B'], 70], [110, 250, 'W']], [[27, 17, 0, 5, ['B'], 0], [280, 230, 'B']], [[18, 4, 0, 3, [], 5], [180, 75, 'B']], [[7, 19, 2, 1, ['W', 'B'], 70], [110, 280, 'W']], [[20, 13, 2, 0, ['B', 'B', 'W', 'W'], 70], [240, 220, 'B']]], [[[16, 18, 1, 5, ['B'], 5], [180, 245, 'W']], [[20, 13, 2, 0, ['B', 'B', 'W', 'W'], 70], [240, 220, 'B']], [[20, 18, 4, 4, ['B', 'W', 'B', 'B'], 75], [260, 325, 'W']], [[26, 10, 1, 0, ['W', 'W'], 5], [290, 105, 'B']], [[1, 17, 1, 2, ['B', 'W', 'W'], 5], [40, 205, 'W']], [[12, 11, 3, 5, ['W', 'B', 'B', 'B'], 70], [170, 260, 'W']], [[12, 19, 1, 1, ['B'], 5], [140, 215, 'W']], [[18, 1, 5, 2, [], 0], [230, 30, 'B']]], [[[9, 10, 4, 5, ['W', 'W', 'B', 'W'], 70], [160, 230, 'W']], [[12, 19, 1, 1, ['B'], 5], [140, 215, 'W']], [[25, 22, 0, 4, ['B', 'B', 'B'], 70], [260, 360, 'W']], [[29, 1, 0, 1, ['B', 'W'], 5], [300, 35, 'B']], [[23, 0, 0, 3, ['W', 'W'], 70], [250, 100, 'B']], [[28, 1, 0, 2, ['B'], 5], [290, 45, 'B']], [[24, 22, 2, 4, ['W', 'B'], 70], [280, 340, 'W']], [[0, 22, 1, 3, ['B'], 75], [20, 335, 'W']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("pass stones 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 |
|---|---|---|---|
| pass stones case 0 | [180, 325, 'W'] | [170, 335, 'W'] | Failed |
| pass stones case 1 | [160, 375, 'W'] | [150, 385, 'W'] | Failed |
| pass stones case 2 | [100, 215, 'W'] | [110, 205, 'W'] | Failed |
| pass stones case 3 | [230, 275, 'W'] | [220, 285, 'W'] | Failed |
| pass stones case 4 | [350, 160, 'B'] | [350, 160, 'B'] | Passed |
| pass stones case 5 | [70, 195, 'W'] | [70, 195, 'W'] | Passed |
| pass stones case 6 | [190, 235, 'W'] | [180, 245, 'W'] | Failed |
| pass stones case 7 | [270, 225, 'B'] | [250, 245, 'B'] | Failed |
SHA-256 / 9bb5f0ab9ba2156413e3d0368017471fd44ae1dc88800ce16657a0e84ddf4e82
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
tb, tw, cb, cw, passes, komi = x
pb = cb + passes.count('W')
pw = cw
if passes and passes[-1] == 'B':
pb += 1
sb = (tb + pb) * 10
sw = (tw + pw) * 10 + komi
if sb > sw:
winner = 'B'
elif sw > sb:
winner = 'W'
else:
winner = 'tie'
return [sb, sw, winner]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[11, 24, 5, 1, ['B'], 75], [170, 335, 'W']], [[12, 29, 2, 1, ['B'], 75], [150, 385, 'W']], [[9, 19, 1, 1, ['W'], 5], [110, 205, 'W']], [[19, 16, 2, 4, ['B'], 75], [220, 285, 'W']], [[28, 11, 4, 3, ['B', 'W', 'W', 'B'], 0], [350, 160, 'B']], [[5, 17, 2, 2, [], 5], [70, 195, 'W']], [[16, 18, 1, 5, ['B'], 5], [180, 245, 'W']], [[22, 11, 2, 4, ['B', 'B'], 75], [250, 245, 'B']]], [[[14, 7, 4, 0, ['B', 'B'], 0], [190, 90, 'B']], [[22, 11, 2, 4, ['B', 'B'], 75], [250, 245, 'B']], [[28, 12, 2, 1, ['B', 'W'], 75], [310, 215, 'B']], [[9, 10, 4, 5, ['W', 'W', 'B', 'W'], 70], [160, 230, 'W']], [[19, 26, 4, 1, ['W'], 0], [240, 270, 'W']], [[25, 8, 5, 0, ['W', 'W', 'W', 'B'], 70], [340, 160, 'B']], [[15, 27, 0, 4, ['B', 'W'], 0], [160, 320, 'W']], [[27, 20, 5, 1, ['B'], 70], [330, 290, 'B']]], [[[3, 12, 5, 1, ['W'], 5], [90, 135, 'W']], [[15, 27, 0, 4, ['B', 'W'], 0], [160, 320, 'W']], [[23, 20, 1, 3, ['W', 'W'], 75], [260, 305, 'W']], [[9, 14, 1, 0, ['B', 'B', 'B', 'B'], 70], [110, 250, 'W']], [[27, 17, 0, 5, ['B'], 0], [280, 230, 'B']], [[18, 4, 0, 3, [], 5], [180, 75, 'B']], [[7, 19, 2, 1, ['W', 'B'], 70], [110, 280, 'W']], [[20, 13, 2, 0, ['B', 'B', 'W', 'W'], 70], [240, 220, 'B']]], [[[16, 18, 1, 5, ['B'], 5], [180, 245, 'W']], [[20, 13, 2, 0, ['B', 'B', 'W', 'W'], 70], [240, 220, 'B']], [[20, 18, 4, 4, ['B', 'W', 'B', 'B'], 75], [260, 325, 'W']], [[26, 10, 1, 0, ['W', 'W'], 5], [290, 105, 'B']], [[1, 17, 1, 2, ['B', 'W', 'W'], 5], [40, 205, 'W']], [[12, 11, 3, 5, ['W', 'B', 'B', 'B'], 70], [170, 260, 'W']], [[12, 19, 1, 1, ['B'], 5], [140, 215, 'W']], [[18, 1, 5, 2, [], 0], [230, 30, 'B']]], [[[9, 10, 4, 5, ['W', 'W', 'B', 'W'], 70], [160, 230, 'W']], [[12, 19, 1, 1, ['B'], 5], [140, 215, 'W']], [[25, 22, 0, 4, ['B', 'B', 'B'], 70], [260, 360, 'W']], [[29, 1, 0, 1, ['B', 'W'], 5], [300, 35, 'B']], [[23, 0, 0, 3, ['W', 'W'], 70], [250, 100, 'B']], [[28, 1, 0, 2, ['B'], 5], [290, 45, 'B']], [[24, 22, 2, 4, ['W', 'B'], 70], [280, 340, 'W']], [[0, 22, 1, 3, ['B'], 75], [20, 335, 'W']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("pass stones 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 |
|---|---|---|---|
| pass stones case 0 | [170, 325, 'W'] | [170, 335, 'W'] | Failed |
| pass stones case 1 | [150, 375, 'W'] | [150, 385, 'W'] | Failed |
| pass stones case 2 | [110, 205, 'W'] | [110, 205, 'W'] | Passed |
| pass stones case 3 | [220, 275, 'W'] | [220, 285, 'W'] | Failed |
| pass stones case 4 | [350, 140, 'B'] | [350, 160, 'B'] | Failed |
| pass stones case 5 | [70, 195, 'W'] | [70, 195, 'W'] | Passed |
| pass stones case 6 | [180, 235, 'W'] | [180, 245, 'W'] | Failed |
| pass stones case 7 | [250, 225, 'B'] | [250, 245, 'B'] | Failed |
SHA-256 / 48599cdf89b6032505ea6771df4bb0cb44d56c80426e6b1b93b85af82f24c08f
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
tb, tw, cb, cw, passes, komi = x
pb = cb + passes.count('W')
pw = cw + passes.count('B')
if passes and passes[-1] == 'B':
pb += 1
sb = (tb + pb) * 10
sw = (tw + pw) * 10 + komi
if sb > sw:
winner = 'B'
elif sw > sb:
winner = 'W'
else:
winner = 'tie'
return [sb, sw, winner]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[11, 24, 5, 1, ['B'], 75], [170, 335, 'W']], [[12, 29, 2, 1, ['B'], 75], [150, 385, 'W']], [[9, 19, 1, 1, ['W'], 5], [110, 205, 'W']], [[19, 16, 2, 4, ['B'], 75], [220, 285, 'W']], [[28, 11, 4, 3, ['B', 'W', 'W', 'B'], 0], [350, 160, 'B']], [[5, 17, 2, 2, [], 5], [70, 195, 'W']], [[16, 18, 1, 5, ['B'], 5], [180, 245, 'W']], [[22, 11, 2, 4, ['B', 'B'], 75], [250, 245, 'B']]], [[[14, 7, 4, 0, ['B', 'B'], 0], [190, 90, 'B']], [[22, 11, 2, 4, ['B', 'B'], 75], [250, 245, 'B']], [[28, 12, 2, 1, ['B', 'W'], 75], [310, 215, 'B']], [[9, 10, 4, 5, ['W', 'W', 'B', 'W'], 70], [160, 230, 'W']], [[19, 26, 4, 1, ['W'], 0], [240, 270, 'W']], [[25, 8, 5, 0, ['W', 'W', 'W', 'B'], 70], [340, 160, 'B']], [[15, 27, 0, 4, ['B', 'W'], 0], [160, 320, 'W']], [[27, 20, 5, 1, ['B'], 70], [330, 290, 'B']]], [[[3, 12, 5, 1, ['W'], 5], [90, 135, 'W']], [[15, 27, 0, 4, ['B', 'W'], 0], [160, 320, 'W']], [[23, 20, 1, 3, ['W', 'W'], 75], [260, 305, 'W']], [[9, 14, 1, 0, ['B', 'B', 'B', 'B'], 70], [110, 250, 'W']], [[27, 17, 0, 5, ['B'], 0], [280, 230, 'B']], [[18, 4, 0, 3, [], 5], [180, 75, 'B']], [[7, 19, 2, 1, ['W', 'B'], 70], [110, 280, 'W']], [[20, 13, 2, 0, ['B', 'B', 'W', 'W'], 70], [240, 220, 'B']]], [[[16, 18, 1, 5, ['B'], 5], [180, 245, 'W']], [[20, 13, 2, 0, ['B', 'B', 'W', 'W'], 70], [240, 220, 'B']], [[20, 18, 4, 4, ['B', 'W', 'B', 'B'], 75], [260, 325, 'W']], [[26, 10, 1, 0, ['W', 'W'], 5], [290, 105, 'B']], [[1, 17, 1, 2, ['B', 'W', 'W'], 5], [40, 205, 'W']], [[12, 11, 3, 5, ['W', 'B', 'B', 'B'], 70], [170, 260, 'W']], [[12, 19, 1, 1, ['B'], 5], [140, 215, 'W']], [[18, 1, 5, 2, [], 0], [230, 30, 'B']]], [[[9, 10, 4, 5, ['W', 'W', 'B', 'W'], 70], [160, 230, 'W']], [[12, 19, 1, 1, ['B'], 5], [140, 215, 'W']], [[25, 22, 0, 4, ['B', 'B', 'B'], 70], [260, 360, 'W']], [[29, 1, 0, 1, ['B', 'W'], 5], [300, 35, 'B']], [[23, 0, 0, 3, ['W', 'W'], 70], [250, 100, 'B']], [[28, 1, 0, 2, ['B'], 5], [290, 45, 'B']], [[24, 22, 2, 4, ['W', 'B'], 70], [280, 340, 'W']], [[0, 22, 1, 3, ['B'], 75], [20, 335, 'W']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("pass stones 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 |
|---|---|---|---|
| pass stones case 0 | [170, 335, 'W'] | [170, 335, 'W'] | Passed |
| pass stones case 1 | [150, 385, 'W'] | [150, 385, 'W'] | Passed |
| pass stones case 2 | [110, 205, 'W'] | [110, 205, 'W'] | Passed |
| pass stones case 3 | [220, 285, 'W'] | [220, 285, 'W'] | Passed |
| pass stones case 4 | [350, 160, 'B'] | [350, 160, 'B'] | Passed |
| pass stones case 5 | [70, 195, 'W'] | [70, 195, 'W'] | Passed |
| pass stones case 6 | [180, 245, 'W'] | [180, 245, 'W'] | Passed |
| pass stones case 7 | [250, 245, 'B'] | [250, 245, 'B'] | Passed |
SHA-256 / ef56c3c232e0b97afb7605d1b585ac0a3e41a4eabddd8a666a4166010e32e85a
Verification & scope
Small rectangular toy boards given as strings of B, W and dot; a bounded teaching model of one scoring or bookkeeping rule, not a complete rules engine or server implementation. 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:18.006847+00:00.
Case digest / 1beb1d8b89b8b8759c35ee3424318aafbf2923109575417c24b173249b4a0b06