FAILURE MAP
← Case archive

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.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

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 fixtureActualExpectedOutcome
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 fixtureActualExpectedOutcome
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 fixtureActualExpectedOutcome
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