FA-83101 / Go territory scoring / Open access
Chains grow through adjacent opponent stones · case 01
A contact fight reports one merged chain with the liberties of both sides.
ROOT CAUSE
The chain expansion accepts any stone rather than stones of the clicked colour.
VERIFIED REPAIR
Expand only through stones of the same colour as the queried point.
Unsuccessful approach: Expanding through empty points as well as own stones reports whole regions instead of chains.
Case contract
Input [board, row, col]. Return [colour, chain_size, distinct_orthogonal_empty_liberties]; an empty point gives [".", 0, 0].
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):
board, r, c = x
n = len(board)
m = len(board[0])
col = board[r][c]
if col == '.':
return ['.', 0, 0]
chain = [(r, c)]
k = 0
while k < len(chain):
i, j = chain[k]
k += 1
for p, q in ((i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1)):
if 0 <= p < n and 0 <= q < m and board[p][q] != '.' and (p, q) not in chain:
chain.append((p, q))
libs = set()
for i, j in chain:
for p, q in ((i, j - 1), (i, j + 1), (i - 1, j), (i + 1, j)):
if 0 <= p < n and 0 <= q < m and board[p][q] == '.':
libs.add((p, q))
return [col, len(chain), len(libs)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['B..W', 'B..W', 'B..W', 'B..W'], 3, 0], ['B', 4, 4]], [[['B..W', 'B..W', 'B..W', 'B..W'], 3, 3], ['W', 4, 4]], [[['B..W', 'B..W', 'B..W', 'B..W'], 3, 2], ['.', 0, 0]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 3, 2], ['W', 4, 4]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 3, 2], ['W', 4, 4]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 3, 1], ['B', 4, 4]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 1, 1], ['B', 4, 4]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 2, 0], ['.', 0, 0]]], [[[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 3, 3], ['W', 6, 4]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 3, 1], ['W', 6, 4]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 1, 2], ['B', 7, 6]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 1, 1], ['.', 0, 0]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 1, 1], ['B', 1, 4]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 2, 2], ['B', 1, 2]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 3, 0], ['B', 3, 4]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 4, 3], ['.', 0, 0]]], [[[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 2, 2], ['B', 1, 2]], [[['W....', '.....', '.....', '.....', '....B'], 4, 4], ['B', 1, 2]], [[['W....', '.....', '.....', '.....', '....B'], 0, 0], ['W', 1, 2]], [[['W....', '.....', '.....', '.....', '....B'], 1, 0], ['.', 0, 0]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 2, 1], ['W', 1, 2]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 4, 0], ['B', 1, 1]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 3, 0], ['W', 1, 1]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0, 2], ['.', 0, 0]]], [[[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 4, 0], ['B', 1, 1]], [[['BBBB', 'B..B', 'B..B', 'BBBB'], 3, 0], ['B', 12, 4]], [[['BBBB', 'B..B', 'B..B', 'BBBB'], 3, 2], ['B', 12, 4]], [[['BBBB', 'B..B', 'B..B', 'BBBB'], 0, 1], ['B', 12, 4]], [[['BBBB', 'B..B', 'B..B', 'BBBB'], 2, 2], ['.', 0, 0]], [[['WWW', 'W.W', 'WWW'], 2, 1], ['W', 8, 1]], [[['WWW', 'W.W', 'WWW'], 1, 2], ['W', 8, 1]], [[['WWW', 'W.W', 'WWW'], 0, 2], ['W', 8, 1]]], [[[['WWW', 'W.W', 'WWW'], 0, 2], ['W', 8, 1]], [[['WWW', 'W.W', 'WWW'], 1, 1], ['.', 0, 0]], [[['B.W', '...', 'W.B'], 0, 0], ['B', 1, 2]], [[['B.W', '...', 'W.B'], 0, 2], ['W', 1, 2]], [[['B.W', '...', 'W.B'], 2, 2], ['B', 1, 2]], [[['B.W', '...', 'W.B'], 1, 2], ['.', 0, 0]], [[['.B...', 'B....', '.....', '....W', '...W.'], 4, 3], ['W', 1, 3]], [[['BW.', 'BW.', 'BW.'], 0, 1], ['W', 3, 3]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("chain 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 |
|---|---|---|---|
| chain case 0 | ['B', 4, 4] | ['B', 4, 4] | Passed |
| chain case 1 | ['W', 4, 4] | ['W', 4, 4] | Passed |
| chain case 2 | ['.', 0, 0] | ['.', 0, 0] | Passed |
| chain case 3 | ['W', 8, 8] | ['W', 4, 4] | Failed |
| chain case 4 | ['W', 8, 8] | ['W', 4, 4] | Failed |
| chain case 5 | ['B', 8, 8] | ['B', 4, 4] | Failed |
| chain case 6 | ['B', 8, 8] | ['B', 4, 4] | Failed |
| chain case 7 | ['.', 0, 0] | ['.', 0, 0] | Passed |
SHA-256 / 18c6b4a4759ee9220ec50179ea657e93751980915f3624d4b4aeb33a5adb7b34
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
board, r, c = x
n = len(board)
m = len(board[0])
col = board[r][c]
if col == '.':
return ['.', 0, 0]
chain = [(r, c)]
k = 0
while k < len(chain):
i, j = chain[k]
k += 1
for p, q in ((i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1)):
if 0 <= p < n and 0 <= q < m and board[p][q] in (col, '.') and (p, q) not in chain:
chain.append((p, q))
libs = set()
for i, j in chain:
for p, q in ((i, j - 1), (i, j + 1), (i - 1, j), (i + 1, j)):
if 0 <= p < n and 0 <= q < m and board[p][q] == '.':
libs.add((p, q))
return [col, len(chain), len(libs)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['B..W', 'B..W', 'B..W', 'B..W'], 3, 0], ['B', 4, 4]], [[['B..W', 'B..W', 'B..W', 'B..W'], 3, 3], ['W', 4, 4]], [[['B..W', 'B..W', 'B..W', 'B..W'], 3, 2], ['.', 0, 0]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 3, 2], ['W', 4, 4]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 3, 2], ['W', 4, 4]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 3, 1], ['B', 4, 4]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 1, 1], ['B', 4, 4]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 2, 0], ['.', 0, 0]]], [[[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 3, 3], ['W', 6, 4]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 3, 1], ['W', 6, 4]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 1, 2], ['B', 7, 6]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 1, 1], ['.', 0, 0]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 1, 1], ['B', 1, 4]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 2, 2], ['B', 1, 2]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 3, 0], ['B', 3, 4]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 4, 3], ['.', 0, 0]]], [[[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 2, 2], ['B', 1, 2]], [[['W....', '.....', '.....', '.....', '....B'], 4, 4], ['B', 1, 2]], [[['W....', '.....', '.....', '.....', '....B'], 0, 0], ['W', 1, 2]], [[['W....', '.....', '.....', '.....', '....B'], 1, 0], ['.', 0, 0]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 2, 1], ['W', 1, 2]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 4, 0], ['B', 1, 1]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 3, 0], ['W', 1, 1]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0, 2], ['.', 0, 0]]], [[[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 4, 0], ['B', 1, 1]], [[['BBBB', 'B..B', 'B..B', 'BBBB'], 3, 0], ['B', 12, 4]], [[['BBBB', 'B..B', 'B..B', 'BBBB'], 3, 2], ['B', 12, 4]], [[['BBBB', 'B..B', 'B..B', 'BBBB'], 0, 1], ['B', 12, 4]], [[['BBBB', 'B..B', 'B..B', 'BBBB'], 2, 2], ['.', 0, 0]], [[['WWW', 'W.W', 'WWW'], 2, 1], ['W', 8, 1]], [[['WWW', 'W.W', 'WWW'], 1, 2], ['W', 8, 1]], [[['WWW', 'W.W', 'WWW'], 0, 2], ['W', 8, 1]]], [[[['WWW', 'W.W', 'WWW'], 0, 2], ['W', 8, 1]], [[['WWW', 'W.W', 'WWW'], 1, 1], ['.', 0, 0]], [[['B.W', '...', 'W.B'], 0, 0], ['B', 1, 2]], [[['B.W', '...', 'W.B'], 0, 2], ['W', 1, 2]], [[['B.W', '...', 'W.B'], 2, 2], ['B', 1, 2]], [[['B.W', '...', 'W.B'], 1, 2], ['.', 0, 0]], [[['.B...', 'B....', '.....', '....W', '...W.'], 4, 3], ['W', 1, 3]], [[['BW.', 'BW.', 'BW.'], 0, 1], ['W', 3, 3]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("chain 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 |
|---|---|---|---|
| chain case 0 | ['B', 12, 8] | ['B', 4, 4] | Failed |
| chain case 1 | ['W', 12, 8] | ['W', 4, 4] | Failed |
| chain case 2 | ['.', 0, 0] | ['.', 0, 0] | Passed |
| chain case 3 | ['W', 8, 4] | ['W', 4, 4] | Failed |
| chain case 4 | ['W', 8, 4] | ['W', 4, 4] | Failed |
| chain case 5 | ['B', 8, 4] | ['B', 4, 4] | Failed |
| chain case 6 | ['B', 8, 4] | ['B', 4, 4] | Failed |
| chain case 7 | ['.', 0, 0] | ['.', 0, 0] | Passed |
SHA-256 / ca51a4724a194583825fa783bdf9bd5ed8fc15e82034ce405e67dbf050224512
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
board, r, c = x
n = len(board)
m = len(board[0])
col = board[r][c]
if col == '.':
return ['.', 0, 0]
chain = [(r, c)]
k = 0
while k < len(chain):
i, j = chain[k]
k += 1
for p, q in ((i + 1, j), (i - 1, j), (i, j + 1), (i, j - 1)):
if 0 <= p < n and 0 <= q < m and board[p][q] == col and (p, q) not in chain:
chain.append((p, q))
libs = set()
for i, j in chain:
for p, q in ((i, j - 1), (i, j + 1), (i - 1, j), (i + 1, j)):
if 0 <= p < n and 0 <= q < m and board[p][q] == '.':
libs.add((p, q))
return [col, len(chain), len(libs)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['B..W', 'B..W', 'B..W', 'B..W'], 3, 0], ['B', 4, 4]], [[['B..W', 'B..W', 'B..W', 'B..W'], 3, 3], ['W', 4, 4]], [[['B..W', 'B..W', 'B..W', 'B..W'], 3, 2], ['.', 0, 0]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 3, 2], ['W', 4, 4]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 3, 2], ['W', 4, 4]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 3, 1], ['B', 4, 4]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 1, 1], ['B', 4, 4]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 2, 0], ['.', 0, 0]]], [[[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 3, 3], ['W', 6, 4]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 3, 1], ['W', 6, 4]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 1, 2], ['B', 7, 6]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 1, 1], ['.', 0, 0]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 1, 1], ['B', 1, 4]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 2, 2], ['B', 1, 2]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 3, 0], ['B', 3, 4]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 4, 3], ['.', 0, 0]]], [[[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 2, 2], ['B', 1, 2]], [[['W....', '.....', '.....', '.....', '....B'], 4, 4], ['B', 1, 2]], [[['W....', '.....', '.....', '.....', '....B'], 0, 0], ['W', 1, 2]], [[['W....', '.....', '.....', '.....', '....B'], 1, 0], ['.', 0, 0]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 2, 1], ['W', 1, 2]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 4, 0], ['B', 1, 1]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 3, 0], ['W', 1, 1]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0, 2], ['.', 0, 0]]], [[[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 4, 0], ['B', 1, 1]], [[['BBBB', 'B..B', 'B..B', 'BBBB'], 3, 0], ['B', 12, 4]], [[['BBBB', 'B..B', 'B..B', 'BBBB'], 3, 2], ['B', 12, 4]], [[['BBBB', 'B..B', 'B..B', 'BBBB'], 0, 1], ['B', 12, 4]], [[['BBBB', 'B..B', 'B..B', 'BBBB'], 2, 2], ['.', 0, 0]], [[['WWW', 'W.W', 'WWW'], 2, 1], ['W', 8, 1]], [[['WWW', 'W.W', 'WWW'], 1, 2], ['W', 8, 1]], [[['WWW', 'W.W', 'WWW'], 0, 2], ['W', 8, 1]]], [[[['WWW', 'W.W', 'WWW'], 0, 2], ['W', 8, 1]], [[['WWW', 'W.W', 'WWW'], 1, 1], ['.', 0, 0]], [[['B.W', '...', 'W.B'], 0, 0], ['B', 1, 2]], [[['B.W', '...', 'W.B'], 0, 2], ['W', 1, 2]], [[['B.W', '...', 'W.B'], 2, 2], ['B', 1, 2]], [[['B.W', '...', 'W.B'], 1, 2], ['.', 0, 0]], [[['.B...', 'B....', '.....', '....W', '...W.'], 4, 3], ['W', 1, 3]], [[['BW.', 'BW.', 'BW.'], 0, 1], ['W', 3, 3]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
check("chain 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 |
|---|---|---|---|
| chain case 0 | ['B', 4, 4] | ['B', 4, 4] | Passed |
| chain case 1 | ['W', 4, 4] | ['W', 4, 4] | Passed |
| chain case 2 | ['.', 0, 0] | ['.', 0, 0] | Passed |
| chain case 3 | ['W', 4, 4] | ['W', 4, 4] | Passed |
| chain case 4 | ['W', 4, 4] | ['W', 4, 4] | Passed |
| chain case 5 | ['B', 4, 4] | ['B', 4, 4] | Passed |
| chain case 6 | ['B', 4, 4] | ['B', 4, 4] | Passed |
| chain case 7 | ['.', 0, 0] | ['.', 0, 0] | Passed |
SHA-256 / fd4ebccde8ec4c8e7a6afbfa9cb00028663198ac75b9002eca9da602949768b5
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.548150+00:00.
Case digest / ef6a54f4c9050c7b9c15564db3c7b0c67f71ab064b0006bf5774e7f81017a644