FA-83226 / Go territory scoring / Open access
Non-consecutive passes end the game · case 01
A pass, a move, then an opponent pass is treated as two consecutive passes.
ROOT CAUSE
Board moves do not clear the pending pass.
VERIFIED REPAIR
Clear the pending pass after any board move.
Unsuccessful approach: Clearing only when the passer moves again leaves the pass pending across an opponent move.
Case contract
Input list of "C:action" tokens. Two consecutive passes by different players end the game ["score", None, index]; any board move clears a pending pass; "resign"/"timeout" end it with the opponent as winner ["resign"/"time", winner, index]. Otherwise ["playing", None, len(moves)].
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):
moves = x
prev_pass = None
for idx, mv in enumerate(moves):
who, _, act = mv.partition(':')
other = 'W' if who == 'B' else 'B'
if act == 'resign':
return ['resign', other, idx]
if act == 'timeout':
return ['time', other, idx]
if act == 'pass':
if prev_pass is not None and prev_pass != who:
return ['score', None, idx]
prev_pass = who
return ['playing', None, len(moves)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[], ['playing', None, 0]], [['B:resign', 'W:pass', 'W:resign', 'B:resign', 'B:qq', 'W:cc'], ['resign', 'W', 0]], [['B:timeout', 'W:pass', 'B:cc', 'B:cc'], ['time', 'W', 0]], [['B:timeout', 'W:pass', 'W:pass', 'W:pass'], ['time', 'W', 0]], [['B:timeout', 'W:cc'], ['time', 'W', 0]], [['B:timeout', 'W:resign'], ['time', 'W', 0]], [['B:pass', 'W:cc', 'W:pass', 'B:cc'], ['playing', None, 4]], [['B:pass', 'W:cc', 'W:pass', 'B:cc'], ['playing', None, 4]]], [[['B:pass', 'W:dd'], ['playing', None, 2]], [['W:cc', 'B:pass', 'B:dd', 'W:cc', 'B:resign'], ['resign', 'W', 4]], [['B:pass'], ['playing', None, 1]], [['B:resign'], ['resign', 'W', 0]], [['B:resign', 'B:cc', 'W:timeout', 'W:pass', 'B:cc'], ['resign', 'W', 0]], [['B:cc', 'W:pass', 'B:dd', 'B:resign'], ['resign', 'W', 3]], [['B:pass', 'W:dd', 'B:cc', 'W:pass'], ['playing', None, 4]], [['B:pass', 'W:cc', 'W:pass', 'W:timeout', 'B:qq'], ['time', 'B', 3]]], [[['B:pass', 'W:qq'], ['playing', None, 2]], [['B:resign', 'W:pass'], ['resign', 'W', 0]], [['B:pass', 'W:cc', 'W:pass', 'B:cc'], ['playing', None, 4]], [['B:pass', 'W:qq'], ['playing', None, 2]], [['B:pass', 'B:dd', 'B:qq'], ['playing', None, 3]], [['W:pass'], ['playing', None, 1]], [['B:qq', 'W:cc', 'B:pass', 'B:cc'], ['playing', None, 4]], [['B:pass', 'B:dd', 'W:pass'], ['playing', None, 3]]], [[['B:resign', 'W:pass', 'B:pass', 'W:dd'], ['resign', 'W', 0]], [['B:pass', 'W:qq', 'B:resign', 'W:pass', 'B:resign'], ['resign', 'W', 2]], [['B:dd', 'W:pass', 'B:pass', 'W:cc', 'B:cc'], ['score', None, 2]], [['B:dd', 'W:resign', 'B:dd', 'W:dd'], ['resign', 'B', 1]], [['W:qq', 'W:timeout', 'B:dd', 'W:pass', 'B:cc', 'W:qq'], ['time', 'B', 1]], [['B:dd'], ['playing', None, 1]], [['B:pass', 'B:cc', 'B:cc', 'W:pass', 'W:cc', 'W:pass'], ['playing', None, 6]], [['B:pass', 'W:cc', 'W:pass', 'W:timeout', 'B:qq'], ['time', 'B', 3]]], [[['B:pass', 'W:cc', 'W:pass', 'B:cc'], ['playing', None, 4]], [['B:dd', 'B:cc', 'B:cc', 'W:resign'], ['resign', 'B', 3]], [['W:pass', 'B:timeout', 'B:cc', 'W:dd'], ['time', 'W', 1]], [['B:timeout'], ['time', 'W', 0]], [['B:pass', 'W:pass', 'B:pass', 'W:resign', 'B:pass', 'W:dd'], ['score', None, 1]], [['W:timeout', 'W:cc', 'B:cc', 'W:pass', 'B:dd', 'W:qq'], ['time', 'B', 0]], [['B:pass', 'W:resign', 'W:pass'], ['resign', 'B', 1]], [['W:pass', 'W:qq', 'B:dd', 'W:cc', 'B:pass', 'B:dd'], ['playing', None, 6]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("game end 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 |
|---|---|---|---|
| game end case 0 | ['playing', None, 0] | ['playing', None, 0] | Passed |
| game end case 1 | ['resign', 'W', 0] | ['resign', 'W', 0] | Passed |
| game end case 2 | ['time', 'W', 0] | ['time', 'W', 0] | Passed |
| game end case 3 | ['time', 'W', 0] | ['time', 'W', 0] | Passed |
| game end case 4 | ['time', 'W', 0] | ['time', 'W', 0] | Passed |
| game end case 5 | ['time', 'W', 0] | ['time', 'W', 0] | Passed |
| game end case 6 | ['score', None, 2] | ['playing', None, 4] | Failed |
| game end case 7 | ['score', None, 2] | ['playing', None, 4] | Failed |
SHA-256 / 2820741ed566aad0f0c2caa122aceade49446b6c5b56d3b49dd719350ac00544
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
moves = x
prev_pass = None
for idx, mv in enumerate(moves):
who, _, act = mv.partition(':')
other = 'W' if who == 'B' else 'B'
if act == 'resign':
return ['resign', other, idx]
if act == 'timeout':
return ['time', other, idx]
if act == 'pass':
if prev_pass is not None and prev_pass != who:
return ['score', None, idx]
prev_pass = who
else:
prev_pass = None if who == prev_pass else prev_pass
return ['playing', None, len(moves)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[], ['playing', None, 0]], [['B:resign', 'W:pass', 'W:resign', 'B:resign', 'B:qq', 'W:cc'], ['resign', 'W', 0]], [['B:timeout', 'W:pass', 'B:cc', 'B:cc'], ['time', 'W', 0]], [['B:timeout', 'W:pass', 'W:pass', 'W:pass'], ['time', 'W', 0]], [['B:timeout', 'W:cc'], ['time', 'W', 0]], [['B:timeout', 'W:resign'], ['time', 'W', 0]], [['B:pass', 'W:cc', 'W:pass', 'B:cc'], ['playing', None, 4]], [['B:pass', 'W:cc', 'W:pass', 'B:cc'], ['playing', None, 4]]], [[['B:pass', 'W:dd'], ['playing', None, 2]], [['W:cc', 'B:pass', 'B:dd', 'W:cc', 'B:resign'], ['resign', 'W', 4]], [['B:pass'], ['playing', None, 1]], [['B:resign'], ['resign', 'W', 0]], [['B:resign', 'B:cc', 'W:timeout', 'W:pass', 'B:cc'], ['resign', 'W', 0]], [['B:cc', 'W:pass', 'B:dd', 'B:resign'], ['resign', 'W', 3]], [['B:pass', 'W:dd', 'B:cc', 'W:pass'], ['playing', None, 4]], [['B:pass', 'W:cc', 'W:pass', 'W:timeout', 'B:qq'], ['time', 'B', 3]]], [[['B:pass', 'W:qq'], ['playing', None, 2]], [['B:resign', 'W:pass'], ['resign', 'W', 0]], [['B:pass', 'W:cc', 'W:pass', 'B:cc'], ['playing', None, 4]], [['B:pass', 'W:qq'], ['playing', None, 2]], [['B:pass', 'B:dd', 'B:qq'], ['playing', None, 3]], [['W:pass'], ['playing', None, 1]], [['B:qq', 'W:cc', 'B:pass', 'B:cc'], ['playing', None, 4]], [['B:pass', 'B:dd', 'W:pass'], ['playing', None, 3]]], [[['B:resign', 'W:pass', 'B:pass', 'W:dd'], ['resign', 'W', 0]], [['B:pass', 'W:qq', 'B:resign', 'W:pass', 'B:resign'], ['resign', 'W', 2]], [['B:dd', 'W:pass', 'B:pass', 'W:cc', 'B:cc'], ['score', None, 2]], [['B:dd', 'W:resign', 'B:dd', 'W:dd'], ['resign', 'B', 1]], [['W:qq', 'W:timeout', 'B:dd', 'W:pass', 'B:cc', 'W:qq'], ['time', 'B', 1]], [['B:dd'], ['playing', None, 1]], [['B:pass', 'B:cc', 'B:cc', 'W:pass', 'W:cc', 'W:pass'], ['playing', None, 6]], [['B:pass', 'W:cc', 'W:pass', 'W:timeout', 'B:qq'], ['time', 'B', 3]]], [[['B:pass', 'W:cc', 'W:pass', 'B:cc'], ['playing', None, 4]], [['B:dd', 'B:cc', 'B:cc', 'W:resign'], ['resign', 'B', 3]], [['W:pass', 'B:timeout', 'B:cc', 'W:dd'], ['time', 'W', 1]], [['B:timeout'], ['time', 'W', 0]], [['B:pass', 'W:pass', 'B:pass', 'W:resign', 'B:pass', 'W:dd'], ['score', None, 1]], [['W:timeout', 'W:cc', 'B:cc', 'W:pass', 'B:dd', 'W:qq'], ['time', 'B', 0]], [['B:pass', 'W:resign', 'W:pass'], ['resign', 'B', 1]], [['W:pass', 'W:qq', 'B:dd', 'W:cc', 'B:pass', 'B:dd'], ['playing', None, 6]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("game end 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 |
|---|---|---|---|
| game end case 0 | ['playing', None, 0] | ['playing', None, 0] | Passed |
| game end case 1 | ['resign', 'W', 0] | ['resign', 'W', 0] | Passed |
| game end case 2 | ['time', 'W', 0] | ['time', 'W', 0] | Passed |
| game end case 3 | ['time', 'W', 0] | ['time', 'W', 0] | Passed |
| game end case 4 | ['time', 'W', 0] | ['time', 'W', 0] | Passed |
| game end case 5 | ['time', 'W', 0] | ['time', 'W', 0] | Passed |
| game end case 6 | ['score', None, 2] | ['playing', None, 4] | Failed |
| game end case 7 | ['score', None, 2] | ['playing', None, 4] | Failed |
SHA-256 / 77b047769b6adf176bd173ab2586e2706c25f303120df9b6ab4e12ac4b1c7d02
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
moves = x
prev_pass = None
for idx, mv in enumerate(moves):
who, _, act = mv.partition(':')
other = 'W' if who == 'B' else 'B'
if act == 'resign':
return ['resign', other, idx]
if act == 'timeout':
return ['time', other, idx]
if act == 'pass':
if prev_pass is not None and prev_pass != who:
return ['score', None, idx]
prev_pass = who
else:
prev_pass = None
return ['playing', None, len(moves)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[], ['playing', None, 0]], [['B:resign', 'W:pass', 'W:resign', 'B:resign', 'B:qq', 'W:cc'], ['resign', 'W', 0]], [['B:timeout', 'W:pass', 'B:cc', 'B:cc'], ['time', 'W', 0]], [['B:timeout', 'W:pass', 'W:pass', 'W:pass'], ['time', 'W', 0]], [['B:timeout', 'W:cc'], ['time', 'W', 0]], [['B:timeout', 'W:resign'], ['time', 'W', 0]], [['B:pass', 'W:cc', 'W:pass', 'B:cc'], ['playing', None, 4]], [['B:pass', 'W:cc', 'W:pass', 'B:cc'], ['playing', None, 4]]], [[['B:pass', 'W:dd'], ['playing', None, 2]], [['W:cc', 'B:pass', 'B:dd', 'W:cc', 'B:resign'], ['resign', 'W', 4]], [['B:pass'], ['playing', None, 1]], [['B:resign'], ['resign', 'W', 0]], [['B:resign', 'B:cc', 'W:timeout', 'W:pass', 'B:cc'], ['resign', 'W', 0]], [['B:cc', 'W:pass', 'B:dd', 'B:resign'], ['resign', 'W', 3]], [['B:pass', 'W:dd', 'B:cc', 'W:pass'], ['playing', None, 4]], [['B:pass', 'W:cc', 'W:pass', 'W:timeout', 'B:qq'], ['time', 'B', 3]]], [[['B:pass', 'W:qq'], ['playing', None, 2]], [['B:resign', 'W:pass'], ['resign', 'W', 0]], [['B:pass', 'W:cc', 'W:pass', 'B:cc'], ['playing', None, 4]], [['B:pass', 'W:qq'], ['playing', None, 2]], [['B:pass', 'B:dd', 'B:qq'], ['playing', None, 3]], [['W:pass'], ['playing', None, 1]], [['B:qq', 'W:cc', 'B:pass', 'B:cc'], ['playing', None, 4]], [['B:pass', 'B:dd', 'W:pass'], ['playing', None, 3]]], [[['B:resign', 'W:pass', 'B:pass', 'W:dd'], ['resign', 'W', 0]], [['B:pass', 'W:qq', 'B:resign', 'W:pass', 'B:resign'], ['resign', 'W', 2]], [['B:dd', 'W:pass', 'B:pass', 'W:cc', 'B:cc'], ['score', None, 2]], [['B:dd', 'W:resign', 'B:dd', 'W:dd'], ['resign', 'B', 1]], [['W:qq', 'W:timeout', 'B:dd', 'W:pass', 'B:cc', 'W:qq'], ['time', 'B', 1]], [['B:dd'], ['playing', None, 1]], [['B:pass', 'B:cc', 'B:cc', 'W:pass', 'W:cc', 'W:pass'], ['playing', None, 6]], [['B:pass', 'W:cc', 'W:pass', 'W:timeout', 'B:qq'], ['time', 'B', 3]]], [[['B:pass', 'W:cc', 'W:pass', 'B:cc'], ['playing', None, 4]], [['B:dd', 'B:cc', 'B:cc', 'W:resign'], ['resign', 'B', 3]], [['W:pass', 'B:timeout', 'B:cc', 'W:dd'], ['time', 'W', 1]], [['B:timeout'], ['time', 'W', 0]], [['B:pass', 'W:pass', 'B:pass', 'W:resign', 'B:pass', 'W:dd'], ['score', None, 1]], [['W:timeout', 'W:cc', 'B:cc', 'W:pass', 'B:dd', 'W:qq'], ['time', 'B', 0]], [['B:pass', 'W:resign', 'W:pass'], ['resign', 'B', 1]], [['W:pass', 'W:qq', 'B:dd', 'W:cc', 'B:pass', 'B:dd'], ['playing', None, 6]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("game end 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 |
|---|---|---|---|
| game end case 0 | ['playing', None, 0] | ['playing', None, 0] | Passed |
| game end case 1 | ['resign', 'W', 0] | ['resign', 'W', 0] | Passed |
| game end case 2 | ['time', 'W', 0] | ['time', 'W', 0] | Passed |
| game end case 3 | ['time', 'W', 0] | ['time', 'W', 0] | Passed |
| game end case 4 | ['time', 'W', 0] | ['time', 'W', 0] | Passed |
| game end case 5 | ['time', 'W', 0] | ['time', 'W', 0] | Passed |
| game end case 6 | ['playing', None, 4] | ['playing', None, 4] | Passed |
| game end case 7 | ['playing', None, 4] | ['playing', None, 4] | Passed |
SHA-256 / 0e484a3fed46a42ba5bc351b36dd96c7e782b4cc24e3ae8011902d32b9fa4527
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:19.538976+00:00.
Case digest / 99c3b20a29816fcd393493a1556d870304d40e72ce2dab2903195ad329a43bec