FAILURE MAP
← Case archive

FA-83246 / Go territory scoring / Open access

Captured stones are credited to the captured side · case 01

Replay prisoner totals are swapped for every capture.

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

ROOT CAUSE

The capture counter indexes the opponent colour.

VERIFIED REPAIR

Credit captures to the moving colour.

Unsuccessful approach: Counting one prisoner per captured chain undercounts multi-stone captures.

Case contract

Input [size, moves]; each move is [colour, row, col] or [colour, "pass"]. Replay with captures; captured stones are prisoners of the mover; occupied or suicidal moves stop replay with ["illegal", index]. Return [prisoners_B, prisoners_W, final_board_rows].

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):
    size, moves = x
    g = [['.'] * size for _ in range(size)]
    pris = {'B': 0, 'W': 0}
    def chain(i, j):
        col = g[i][j]
        seen = {(i, j)}
        todo = [(i, j)]
        libs = 0
        while todo:
            a, b = todo.pop()
            for p, q in ((a - 1, b), (a, b + 1), (a + 1, b), (a, b - 1)):
                if 0 <= p < size and 0 <= q < size:
                    if g[p][q] == '.':
                        libs += 1
                    elif g[p][q] == col and (p, q) not in seen:
                        seen.add((p, q))
                        todo.append((p, q))
        return seen, libs
    for idx, mv in enumerate(moves):
        if mv[1] == 'pass':
            continue
        col, r, c = mv
        if g[r][c] != '.':
            return ['illegal', idx]
        g[r][c] = col
        opp = 'B' if col == 'W' else 'W'
        for p, q in ((r - 1, c), (r, c + 1), (r + 1, c), (r, c - 1)):
            if 0 <= p < size and 0 <= q < size and g[p][q] == opp:
                dead, libs = chain(p, q)
                if libs == 0:
                    for s, t in dead:
                        g[s][t] = '.'
                    pris[opp] += len(dead)
        own, libs = chain(r, c)
        if libs == 0:
            return ['illegal', idx]
    return [pris['B'], pris['W'], [''.join(row) for row in g]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[4, [['B', 3, 0], ['W', 2, 3], ['B', 'pass']]], [0, 0, ['....', '....', '...W', 'B...']]], [[4, [['B', 2, 0], ['W', 3, 1], ['B', 2, 0], ['W', 0, 1], ['B', 2, 0], ['W', 1, 3], ['B', 'pass'], ['W', 0, 1], ['B', 2, 3], ['W', 1, 2], ['B', 1, 1], ['W', 1, 0]]], ['illegal', 2]], [[3, [['B', 1, 1], ['W', 0, 1], ['B', 1, 1], ['W', 1, 1], ['B', 'pass'], ['W', 1, 1], ['B', 2, 0], ['W', 2, 2], ['B', 2, 0], ['W', 1, 1], ['B', 2, 2], ['W', 0, 0], ['B', 'pass'], ['W', 0, 2], ['B', 2, 1]]], ['illegal', 2]], [[3, [['B', 0, 1], ['W', 1, 0], ['B', 2, 1], ['W', 1, 0], ['B', 'pass'], ['W', 0, 0], ['B', 1, 1], ['W', 1, 1], ['B', 1, 1], ['W', 1, 2], ['B', 2, 0], ['W', 1, 1], ['B', 2, 2], ['W', 2, 1], ['B', 0, 0]]], ['illegal', 3]], [[4, [['B', 3, 0], ['W', 2, 1], ['B', 3, 1], ['W', 3, 0], ['B', 0, 0], ['W', 1, 0], ['B', 'pass']]], ['illegal', 3]], [[4, [['B', 0, 3], ['W', 0, 2], ['B', 2, 0], ['W', 1, 3], ['B', 2, 3], ['W', 'pass'], ['B', 0, 1], ['W', 1, 0], ['B', 0, 2], ['W', 1, 0], ['B', 2, 1], ['W', 3, 0]]], ['illegal', 8]], [[3, [['B', 'pass'], ['W', 1, 2], ['B', 0, 0], ['W', 1, 1], ['B', 0, 2], ['W', 0, 1], ['B', 'pass'], ['W', 'pass']]], [0, 1, ['BW.', '.WW', '...']]], [[3, [['B', 1, 0], ['W', 0, 0], ['B', 1, 1], ['W', 0, 1], ['B', 0, 2]]], [2, 0, ['..B', 'BB.', '...']]]], [[[3, [['B', 0, 1], ['W', 2, 0], ['B', 1, 1], ['W', 1, 2], ['B', 0, 0], ['W', 2, 1], ['B', 2, 1], ['W', 'pass'], ['B', 0, 2], ['W', 1, 1], ['B', 1, 2], ['W', 0, 0], ['B', 'pass']]], ['illegal', 6]], [[4, [['B', 2, 0], ['W', 0, 2], ['B', 1, 1], ['W', 3, 0], ['B', 3, 2]]], [0, 0, ['..W.', '.B..', 'B...', 'W.B.']]], [[3, [['B', 2, 1], ['W', 2, 1], ['B', 1, 2], ['W', 2, 2], ['B', 0, 2], ['W', 0, 0], ['B', 1, 1], ['W', 0, 1], ['B', 0, 2]]], ['illegal', 1]], [[4, [['B', 0, 1], ['W', 'pass'], ['B', 1, 3], ['W', 2, 3], ['B', 0, 2], ['W', 2, 0], ['B', 2, 0], ['W', 1, 1], ['B', 'pass'], ['W', 1, 2], ['B', 1, 0], ['W', 3, 2]]], ['illegal', 6]], [[3, [['B', 1, 0], ['W', 2, 2], ['B', 'pass'], ['W', 1, 0], ['B', 1, 2]]], ['illegal', 3]], [[4, [['B', 1, 0], ['W', 2, 0], ['B', 1, 3], ['W', 0, 0], ['B', 1, 1], ['W', 2, 2], ['B', 3, 1], ['W', 1, 2], ['B', 0, 0], ['W', 0, 2], ['B', 1, 0], ['W', 0, 0]]], ['illegal', 8]], [[4, [['B', 1, 0], ['W', 0, 0], ['B', 1, 1], ['W', 0, 1], ['B', 1, 2], ['W', 0, 2], ['B', 0, 3]]], [3, 0, ['...B', 'BBB.', '....', '....']]], [[3, [['W', 1, 0], ['B', 0, 0], ['W', 1, 1], ['B', 0, 1], ['W', 0, 2], ['B', 2, 2]]], [0, 2, ['..W', 'WW.', '..B']]]], [[[3, [['B', 2, 0], ['W', 1, 1], ['B', 'pass'], ['W', 2, 1], ['B', 0, 1], ['W', 1, 1]]], ['illegal', 5]], [[4, [['B', 3, 1], ['W', 1, 3], ['B', 2, 3], ['W', 2, 0], ['B', 0, 1], ['W', 1, 3], ['B', 'pass'], ['W', 0, 0], ['B', 3, 0], ['W', 'pass'], ['B', 'pass'], ['W', 1, 1], ['B', 0, 2], ['W', 'pass'], ['B', 0, 0]]], ['illegal', 5]], [[4, [['B', 1, 1], ['W', 0, 2], ['B', 2, 3], ['W', 'pass'], ['B', 1, 1], ['W', 0, 2], ['B', 0, 3], ['W', 2, 0], ['B', 2, 2], ['W', 3, 0], ['B', 3, 0]]], ['illegal', 4]], [[3, [['B', 0, 0], ['W', 2, 2], ['B', 2, 1], ['W', 2, 2], ['B', 1, 2], ['W', 2, 2], ['B', 1, 0]]], ['illegal', 3]], [[3, [['B', 1, 2], ['W', 2, 0], ['B', 1, 0], ['W', 0, 1], ['B', 2, 2], ['W', 2, 2], ['B', 1, 2], ['W', 2, 0], ['B', 'pass'], ['W', 2, 0], ['B', 2, 1], ['W', 2, 0], ['B', 0, 2], ['W', 0, 1], ['B', 2, 2]]], ['illegal', 5]], [[3, [['B', 'pass'], ['W', 1, 2], ['B', 0, 0], ['W', 1, 1], ['B', 0, 2], ['W', 0, 1], ['B', 'pass'], ['W', 'pass']]], [0, 1, ['BW.', '.WW', '...']]], [[4, [['B', 1, 0], ['W', 0, 0], ['B', 1, 1], ['W', 0, 1], ['B', 1, 2], ['W', 0, 2], ['B', 0, 3]]], [3, 0, ['...B', 'BBB.', '....', '....']]], [[3, [['W', 0, 1], ['B', 0, 0], ['W', 1, 0], ['B', 'pass'], ['W', 2, 2]]], [0, 1, ['.W.', 'W..', '..W']]]], [[[4, [['B', 'pass'], ['W', 1, 0], ['B', 2, 3], ['W', 3, 2], ['B', 1, 3]]], [0, 0, ['....', 'W..B', '...B', '..W.']]], [[4, [['B', 0, 3], ['W', 'pass'], ['B', 3, 1], ['W', 3, 3], ['B', 3, 1], ['W', 0, 3], ['B', 1, 3], ['W', 'pass'], ['B', 3, 2], ['W', 'pass'], ['B', 3, 1], ['W', 0, 2], ['B', 3, 0]]], ['illegal', 4]], [[3, [['B', 1, 1], ['W', 2, 1], ['B', 2, 0], ['W', 0, 2], ['B', 0, 2], ['W', 0, 0], ['B', 2, 2], ['W', 2, 0], ['B', 2, 2], ['W', 0, 2], ['B', 2, 2], ['W', 2, 0]]], ['illegal', 4]], [[3, [['B', 1, 0], ['W', 0, 1], ['B', 0, 1], ['W', 0, 2], ['B', 2, 0], ['W', 1, 0], ['B', 0, 0], ['W', 2, 1], ['B', 2, 2], ['W', 2, 0], ['B', 1, 1], ['W', 0, 2], ['B', 1, 1], ['W', 0, 2]]], ['illegal', 2]], [[4, [['B', 0, 3], ['W', 3, 3], ['B', 1, 2], ['W', 0, 1], ['B', 3, 0]]], [0, 0, ['.W.B', '..B.', '....', 'B..W']]], [[4, [['B', 3, 0], ['W', 0, 3], ['B', 0, 2]]], [0, 0, ['..BW', '....', '....', 'B...']]], [[3, [['B', 1, 0], ['W', 0, 0], ['B', 1, 1], ['W', 0, 1], ['B', 0, 2]]], [2, 0, ['..B', 'BB.', '...']]], [[3, [['B', 1, 0], ['W', 0, 0], ['B', 1, 1], ['W', 0, 1], ['B', 0, 2]]], [2, 0, ['..B', 'BB.', '...']]]], [[[3, [['B', 2, 2], ['W', 1, 1], ['B', 1, 0], ['W', 2, 1], ['B', 0, 2]]], [0, 0, ['..B', 'BW.', '.WB']]], [[3, [['B', 0, 2], ['W', 0, 1], ['B', 1, 1], ['W', 2, 2], ['B', 0, 2], ['W', 'pass'], ['B', 1, 1], ['W', 'pass'], ['B', 0, 2], ['W', 2, 1], ['B', 'pass'], ['W', 0, 0], ['B', 'pass']]], ['illegal', 4]], [[3, [['B', 1, 1], ['W', 1, 2], ['B', 0, 2]]], [0, 0, ['..B', '.BW', '...']]], [[3, [['B', 2, 1], ['W', 'pass'], ['B', 'pass'], ['W', 0, 0], ['B', 1, 1], ['W', 0, 2], ['B', 0, 2], ['W', 2, 2], ['B', 0, 1]]], ['illegal', 6]], [[3, [['B', 2, 0], ['W', 0, 1], ['B', 1, 0], ['W', 1, 1], ['B', 2, 0], ['W', 1, 0], ['B', 0, 0], ['W', 'pass']]], ['illegal', 4]], [[4, [['B', 2, 3], ['W', 0, 2], ['B', 1, 3], ['W', 'pass'], ['B', 1, 0], ['W', 2, 1], ['B', 3, 0], ['W', 1, 1]]], [0, 0, ['..W.', 'BW.B', '.W.B', 'B...']]], [[3, [['W', 1, 0], ['B', 0, 0], ['W', 1, 1], ['B', 0, 1], ['W', 0, 2], ['B', 2, 2]]], [0, 2, ['..W', 'WW.', '..B']]], [[3, [['B', 0, 1], ['W', 0, 0], ['B', 1, 0]]], [1, 0, ['.B.', 'B..', '...']]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("replay 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
replay case 0[0, 0, ['....', '....', '...W', 'B...']][0, 0, ['....', '....', '...W', 'B...']]Passed
replay case 1['illegal', 2]['illegal', 2]Passed
replay case 2['illegal', 2]['illegal', 2]Passed
replay case 3['illegal', 3]['illegal', 3]Passed
replay case 4['illegal', 3]['illegal', 3]Passed
replay case 5['illegal', 8]['illegal', 8]Passed
replay case 6[1, 0, ['BW.', '.WW', '...']][0, 1, ['BW.', '.WW', '...']]Failed
replay case 7[0, 2, ['..B', 'BB.', '...']][2, 0, ['..B', 'BB.', '...']]Failed

SHA-256 / 03fe28edb3a8d1c1c97cd060bf6af9b3c95da59bed9edcda64ece327e7253101

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    size, moves = x
    g = [['.'] * size for _ in range(size)]
    pris = {'B': 0, 'W': 0}
    def chain(i, j):
        col = g[i][j]
        seen = {(i, j)}
        todo = [(i, j)]
        libs = 0
        while todo:
            a, b = todo.pop()
            for p, q in ((a - 1, b), (a, b + 1), (a + 1, b), (a, b - 1)):
                if 0 <= p < size and 0 <= q < size:
                    if g[p][q] == '.':
                        libs += 1
                    elif g[p][q] == col and (p, q) not in seen:
                        seen.add((p, q))
                        todo.append((p, q))
        return seen, libs
    for idx, mv in enumerate(moves):
        if mv[1] == 'pass':
            continue
        col, r, c = mv
        if g[r][c] != '.':
            return ['illegal', idx]
        g[r][c] = col
        opp = 'B' if col == 'W' else 'W'
        for p, q in ((r - 1, c), (r, c + 1), (r + 1, c), (r, c - 1)):
            if 0 <= p < size and 0 <= q < size and g[p][q] == opp:
                dead, libs = chain(p, q)
                if libs == 0:
                    for s, t in dead:
                        g[s][t] = '.'
                    pris[col] += 1
        own, libs = chain(r, c)
        if libs == 0:
            return ['illegal', idx]
    return [pris['B'], pris['W'], [''.join(row) for row in g]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[4, [['B', 3, 0], ['W', 2, 3], ['B', 'pass']]], [0, 0, ['....', '....', '...W', 'B...']]], [[4, [['B', 2, 0], ['W', 3, 1], ['B', 2, 0], ['W', 0, 1], ['B', 2, 0], ['W', 1, 3], ['B', 'pass'], ['W', 0, 1], ['B', 2, 3], ['W', 1, 2], ['B', 1, 1], ['W', 1, 0]]], ['illegal', 2]], [[3, [['B', 1, 1], ['W', 0, 1], ['B', 1, 1], ['W', 1, 1], ['B', 'pass'], ['W', 1, 1], ['B', 2, 0], ['W', 2, 2], ['B', 2, 0], ['W', 1, 1], ['B', 2, 2], ['W', 0, 0], ['B', 'pass'], ['W', 0, 2], ['B', 2, 1]]], ['illegal', 2]], [[3, [['B', 0, 1], ['W', 1, 0], ['B', 2, 1], ['W', 1, 0], ['B', 'pass'], ['W', 0, 0], ['B', 1, 1], ['W', 1, 1], ['B', 1, 1], ['W', 1, 2], ['B', 2, 0], ['W', 1, 1], ['B', 2, 2], ['W', 2, 1], ['B', 0, 0]]], ['illegal', 3]], [[4, [['B', 3, 0], ['W', 2, 1], ['B', 3, 1], ['W', 3, 0], ['B', 0, 0], ['W', 1, 0], ['B', 'pass']]], ['illegal', 3]], [[4, [['B', 0, 3], ['W', 0, 2], ['B', 2, 0], ['W', 1, 3], ['B', 2, 3], ['W', 'pass'], ['B', 0, 1], ['W', 1, 0], ['B', 0, 2], ['W', 1, 0], ['B', 2, 1], ['W', 3, 0]]], ['illegal', 8]], [[3, [['B', 'pass'], ['W', 1, 2], ['B', 0, 0], ['W', 1, 1], ['B', 0, 2], ['W', 0, 1], ['B', 'pass'], ['W', 'pass']]], [0, 1, ['BW.', '.WW', '...']]], [[3, [['B', 1, 0], ['W', 0, 0], ['B', 1, 1], ['W', 0, 1], ['B', 0, 2]]], [2, 0, ['..B', 'BB.', '...']]]], [[[3, [['B', 0, 1], ['W', 2, 0], ['B', 1, 1], ['W', 1, 2], ['B', 0, 0], ['W', 2, 1], ['B', 2, 1], ['W', 'pass'], ['B', 0, 2], ['W', 1, 1], ['B', 1, 2], ['W', 0, 0], ['B', 'pass']]], ['illegal', 6]], [[4, [['B', 2, 0], ['W', 0, 2], ['B', 1, 1], ['W', 3, 0], ['B', 3, 2]]], [0, 0, ['..W.', '.B..', 'B...', 'W.B.']]], [[3, [['B', 2, 1], ['W', 2, 1], ['B', 1, 2], ['W', 2, 2], ['B', 0, 2], ['W', 0, 0], ['B', 1, 1], ['W', 0, 1], ['B', 0, 2]]], ['illegal', 1]], [[4, [['B', 0, 1], ['W', 'pass'], ['B', 1, 3], ['W', 2, 3], ['B', 0, 2], ['W', 2, 0], ['B', 2, 0], ['W', 1, 1], ['B', 'pass'], ['W', 1, 2], ['B', 1, 0], ['W', 3, 2]]], ['illegal', 6]], [[3, [['B', 1, 0], ['W', 2, 2], ['B', 'pass'], ['W', 1, 0], ['B', 1, 2]]], ['illegal', 3]], [[4, [['B', 1, 0], ['W', 2, 0], ['B', 1, 3], ['W', 0, 0], ['B', 1, 1], ['W', 2, 2], ['B', 3, 1], ['W', 1, 2], ['B', 0, 0], ['W', 0, 2], ['B', 1, 0], ['W', 0, 0]]], ['illegal', 8]], [[4, [['B', 1, 0], ['W', 0, 0], ['B', 1, 1], ['W', 0, 1], ['B', 1, 2], ['W', 0, 2], ['B', 0, 3]]], [3, 0, ['...B', 'BBB.', '....', '....']]], [[3, [['W', 1, 0], ['B', 0, 0], ['W', 1, 1], ['B', 0, 1], ['W', 0, 2], ['B', 2, 2]]], [0, 2, ['..W', 'WW.', '..B']]]], [[[3, [['B', 2, 0], ['W', 1, 1], ['B', 'pass'], ['W', 2, 1], ['B', 0, 1], ['W', 1, 1]]], ['illegal', 5]], [[4, [['B', 3, 1], ['W', 1, 3], ['B', 2, 3], ['W', 2, 0], ['B', 0, 1], ['W', 1, 3], ['B', 'pass'], ['W', 0, 0], ['B', 3, 0], ['W', 'pass'], ['B', 'pass'], ['W', 1, 1], ['B', 0, 2], ['W', 'pass'], ['B', 0, 0]]], ['illegal', 5]], [[4, [['B', 1, 1], ['W', 0, 2], ['B', 2, 3], ['W', 'pass'], ['B', 1, 1], ['W', 0, 2], ['B', 0, 3], ['W', 2, 0], ['B', 2, 2], ['W', 3, 0], ['B', 3, 0]]], ['illegal', 4]], [[3, [['B', 0, 0], ['W', 2, 2], ['B', 2, 1], ['W', 2, 2], ['B', 1, 2], ['W', 2, 2], ['B', 1, 0]]], ['illegal', 3]], [[3, [['B', 1, 2], ['W', 2, 0], ['B', 1, 0], ['W', 0, 1], ['B', 2, 2], ['W', 2, 2], ['B', 1, 2], ['W', 2, 0], ['B', 'pass'], ['W', 2, 0], ['B', 2, 1], ['W', 2, 0], ['B', 0, 2], ['W', 0, 1], ['B', 2, 2]]], ['illegal', 5]], [[3, [['B', 'pass'], ['W', 1, 2], ['B', 0, 0], ['W', 1, 1], ['B', 0, 2], ['W', 0, 1], ['B', 'pass'], ['W', 'pass']]], [0, 1, ['BW.', '.WW', '...']]], [[4, [['B', 1, 0], ['W', 0, 0], ['B', 1, 1], ['W', 0, 1], ['B', 1, 2], ['W', 0, 2], ['B', 0, 3]]], [3, 0, ['...B', 'BBB.', '....', '....']]], [[3, [['W', 0, 1], ['B', 0, 0], ['W', 1, 0], ['B', 'pass'], ['W', 2, 2]]], [0, 1, ['.W.', 'W..', '..W']]]], [[[4, [['B', 'pass'], ['W', 1, 0], ['B', 2, 3], ['W', 3, 2], ['B', 1, 3]]], [0, 0, ['....', 'W..B', '...B', '..W.']]], [[4, [['B', 0, 3], ['W', 'pass'], ['B', 3, 1], ['W', 3, 3], ['B', 3, 1], ['W', 0, 3], ['B', 1, 3], ['W', 'pass'], ['B', 3, 2], ['W', 'pass'], ['B', 3, 1], ['W', 0, 2], ['B', 3, 0]]], ['illegal', 4]], [[3, [['B', 1, 1], ['W', 2, 1], ['B', 2, 0], ['W', 0, 2], ['B', 0, 2], ['W', 0, 0], ['B', 2, 2], ['W', 2, 0], ['B', 2, 2], ['W', 0, 2], ['B', 2, 2], ['W', 2, 0]]], ['illegal', 4]], [[3, [['B', 1, 0], ['W', 0, 1], ['B', 0, 1], ['W', 0, 2], ['B', 2, 0], ['W', 1, 0], ['B', 0, 0], ['W', 2, 1], ['B', 2, 2], ['W', 2, 0], ['B', 1, 1], ['W', 0, 2], ['B', 1, 1], ['W', 0, 2]]], ['illegal', 2]], [[4, [['B', 0, 3], ['W', 3, 3], ['B', 1, 2], ['W', 0, 1], ['B', 3, 0]]], [0, 0, ['.W.B', '..B.', '....', 'B..W']]], [[4, [['B', 3, 0], ['W', 0, 3], ['B', 0, 2]]], [0, 0, ['..BW', '....', '....', 'B...']]], [[3, [['B', 1, 0], ['W', 0, 0], ['B', 1, 1], ['W', 0, 1], ['B', 0, 2]]], [2, 0, ['..B', 'BB.', '...']]], [[3, [['B', 1, 0], ['W', 0, 0], ['B', 1, 1], ['W', 0, 1], ['B', 0, 2]]], [2, 0, ['..B', 'BB.', '...']]]], [[[3, [['B', 2, 2], ['W', 1, 1], ['B', 1, 0], ['W', 2, 1], ['B', 0, 2]]], [0, 0, ['..B', 'BW.', '.WB']]], [[3, [['B', 0, 2], ['W', 0, 1], ['B', 1, 1], ['W', 2, 2], ['B', 0, 2], ['W', 'pass'], ['B', 1, 1], ['W', 'pass'], ['B', 0, 2], ['W', 2, 1], ['B', 'pass'], ['W', 0, 0], ['B', 'pass']]], ['illegal', 4]], [[3, [['B', 1, 1], ['W', 1, 2], ['B', 0, 2]]], [0, 0, ['..B', '.BW', '...']]], [[3, [['B', 2, 1], ['W', 'pass'], ['B', 'pass'], ['W', 0, 0], ['B', 1, 1], ['W', 0, 2], ['B', 0, 2], ['W', 2, 2], ['B', 0, 1]]], ['illegal', 6]], [[3, [['B', 2, 0], ['W', 0, 1], ['B', 1, 0], ['W', 1, 1], ['B', 2, 0], ['W', 1, 0], ['B', 0, 0], ['W', 'pass']]], ['illegal', 4]], [[4, [['B', 2, 3], ['W', 0, 2], ['B', 1, 3], ['W', 'pass'], ['B', 1, 0], ['W', 2, 1], ['B', 3, 0], ['W', 1, 1]]], [0, 0, ['..W.', 'BW.B', '.W.B', 'B...']]], [[3, [['W', 1, 0], ['B', 0, 0], ['W', 1, 1], ['B', 0, 1], ['W', 0, 2], ['B', 2, 2]]], [0, 2, ['..W', 'WW.', '..B']]], [[3, [['B', 0, 1], ['W', 0, 0], ['B', 1, 0]]], [1, 0, ['.B.', 'B..', '...']]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("replay 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
replay case 0[0, 0, ['....', '....', '...W', 'B...']][0, 0, ['....', '....', '...W', 'B...']]Passed
replay case 1['illegal', 2]['illegal', 2]Passed
replay case 2['illegal', 2]['illegal', 2]Passed
replay case 3['illegal', 3]['illegal', 3]Passed
replay case 4['illegal', 3]['illegal', 3]Passed
replay case 5['illegal', 8]['illegal', 8]Passed
replay case 6[0, 1, ['BW.', '.WW', '...']][0, 1, ['BW.', '.WW', '...']]Passed
replay case 7[1, 0, ['..B', 'BB.', '...']][2, 0, ['..B', 'BB.', '...']]Failed

SHA-256 / 25f7124db4526ad6c3bb636655d4bbf4eb8edcffa91e8d01b5063c6b8a00c9f0

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    size, moves = x
    g = [['.'] * size for _ in range(size)]
    pris = {'B': 0, 'W': 0}
    def chain(i, j):
        col = g[i][j]
        seen = {(i, j)}
        todo = [(i, j)]
        libs = 0
        while todo:
            a, b = todo.pop()
            for p, q in ((a - 1, b), (a, b + 1), (a + 1, b), (a, b - 1)):
                if 0 <= p < size and 0 <= q < size:
                    if g[p][q] == '.':
                        libs += 1
                    elif g[p][q] == col and (p, q) not in seen:
                        seen.add((p, q))
                        todo.append((p, q))
        return seen, libs
    for idx, mv in enumerate(moves):
        if mv[1] == 'pass':
            continue
        col, r, c = mv
        if g[r][c] != '.':
            return ['illegal', idx]
        g[r][c] = col
        opp = 'B' if col == 'W' else 'W'
        for p, q in ((r - 1, c), (r, c + 1), (r + 1, c), (r, c - 1)):
            if 0 <= p < size and 0 <= q < size and g[p][q] == opp:
                dead, libs = chain(p, q)
                if libs == 0:
                    for s, t in dead:
                        g[s][t] = '.'
                    pris[col] += len(dead)
        own, libs = chain(r, c)
        if libs == 0:
            return ['illegal', idx]
    return [pris['B'], pris['W'], [''.join(row) for row in g]]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[4, [['B', 3, 0], ['W', 2, 3], ['B', 'pass']]], [0, 0, ['....', '....', '...W', 'B...']]], [[4, [['B', 2, 0], ['W', 3, 1], ['B', 2, 0], ['W', 0, 1], ['B', 2, 0], ['W', 1, 3], ['B', 'pass'], ['W', 0, 1], ['B', 2, 3], ['W', 1, 2], ['B', 1, 1], ['W', 1, 0]]], ['illegal', 2]], [[3, [['B', 1, 1], ['W', 0, 1], ['B', 1, 1], ['W', 1, 1], ['B', 'pass'], ['W', 1, 1], ['B', 2, 0], ['W', 2, 2], ['B', 2, 0], ['W', 1, 1], ['B', 2, 2], ['W', 0, 0], ['B', 'pass'], ['W', 0, 2], ['B', 2, 1]]], ['illegal', 2]], [[3, [['B', 0, 1], ['W', 1, 0], ['B', 2, 1], ['W', 1, 0], ['B', 'pass'], ['W', 0, 0], ['B', 1, 1], ['W', 1, 1], ['B', 1, 1], ['W', 1, 2], ['B', 2, 0], ['W', 1, 1], ['B', 2, 2], ['W', 2, 1], ['B', 0, 0]]], ['illegal', 3]], [[4, [['B', 3, 0], ['W', 2, 1], ['B', 3, 1], ['W', 3, 0], ['B', 0, 0], ['W', 1, 0], ['B', 'pass']]], ['illegal', 3]], [[4, [['B', 0, 3], ['W', 0, 2], ['B', 2, 0], ['W', 1, 3], ['B', 2, 3], ['W', 'pass'], ['B', 0, 1], ['W', 1, 0], ['B', 0, 2], ['W', 1, 0], ['B', 2, 1], ['W', 3, 0]]], ['illegal', 8]], [[3, [['B', 'pass'], ['W', 1, 2], ['B', 0, 0], ['W', 1, 1], ['B', 0, 2], ['W', 0, 1], ['B', 'pass'], ['W', 'pass']]], [0, 1, ['BW.', '.WW', '...']]], [[3, [['B', 1, 0], ['W', 0, 0], ['B', 1, 1], ['W', 0, 1], ['B', 0, 2]]], [2, 0, ['..B', 'BB.', '...']]]], [[[3, [['B', 0, 1], ['W', 2, 0], ['B', 1, 1], ['W', 1, 2], ['B', 0, 0], ['W', 2, 1], ['B', 2, 1], ['W', 'pass'], ['B', 0, 2], ['W', 1, 1], ['B', 1, 2], ['W', 0, 0], ['B', 'pass']]], ['illegal', 6]], [[4, [['B', 2, 0], ['W', 0, 2], ['B', 1, 1], ['W', 3, 0], ['B', 3, 2]]], [0, 0, ['..W.', '.B..', 'B...', 'W.B.']]], [[3, [['B', 2, 1], ['W', 2, 1], ['B', 1, 2], ['W', 2, 2], ['B', 0, 2], ['W', 0, 0], ['B', 1, 1], ['W', 0, 1], ['B', 0, 2]]], ['illegal', 1]], [[4, [['B', 0, 1], ['W', 'pass'], ['B', 1, 3], ['W', 2, 3], ['B', 0, 2], ['W', 2, 0], ['B', 2, 0], ['W', 1, 1], ['B', 'pass'], ['W', 1, 2], ['B', 1, 0], ['W', 3, 2]]], ['illegal', 6]], [[3, [['B', 1, 0], ['W', 2, 2], ['B', 'pass'], ['W', 1, 0], ['B', 1, 2]]], ['illegal', 3]], [[4, [['B', 1, 0], ['W', 2, 0], ['B', 1, 3], ['W', 0, 0], ['B', 1, 1], ['W', 2, 2], ['B', 3, 1], ['W', 1, 2], ['B', 0, 0], ['W', 0, 2], ['B', 1, 0], ['W', 0, 0]]], ['illegal', 8]], [[4, [['B', 1, 0], ['W', 0, 0], ['B', 1, 1], ['W', 0, 1], ['B', 1, 2], ['W', 0, 2], ['B', 0, 3]]], [3, 0, ['...B', 'BBB.', '....', '....']]], [[3, [['W', 1, 0], ['B', 0, 0], ['W', 1, 1], ['B', 0, 1], ['W', 0, 2], ['B', 2, 2]]], [0, 2, ['..W', 'WW.', '..B']]]], [[[3, [['B', 2, 0], ['W', 1, 1], ['B', 'pass'], ['W', 2, 1], ['B', 0, 1], ['W', 1, 1]]], ['illegal', 5]], [[4, [['B', 3, 1], ['W', 1, 3], ['B', 2, 3], ['W', 2, 0], ['B', 0, 1], ['W', 1, 3], ['B', 'pass'], ['W', 0, 0], ['B', 3, 0], ['W', 'pass'], ['B', 'pass'], ['W', 1, 1], ['B', 0, 2], ['W', 'pass'], ['B', 0, 0]]], ['illegal', 5]], [[4, [['B', 1, 1], ['W', 0, 2], ['B', 2, 3], ['W', 'pass'], ['B', 1, 1], ['W', 0, 2], ['B', 0, 3], ['W', 2, 0], ['B', 2, 2], ['W', 3, 0], ['B', 3, 0]]], ['illegal', 4]], [[3, [['B', 0, 0], ['W', 2, 2], ['B', 2, 1], ['W', 2, 2], ['B', 1, 2], ['W', 2, 2], ['B', 1, 0]]], ['illegal', 3]], [[3, [['B', 1, 2], ['W', 2, 0], ['B', 1, 0], ['W', 0, 1], ['B', 2, 2], ['W', 2, 2], ['B', 1, 2], ['W', 2, 0], ['B', 'pass'], ['W', 2, 0], ['B', 2, 1], ['W', 2, 0], ['B', 0, 2], ['W', 0, 1], ['B', 2, 2]]], ['illegal', 5]], [[3, [['B', 'pass'], ['W', 1, 2], ['B', 0, 0], ['W', 1, 1], ['B', 0, 2], ['W', 0, 1], ['B', 'pass'], ['W', 'pass']]], [0, 1, ['BW.', '.WW', '...']]], [[4, [['B', 1, 0], ['W', 0, 0], ['B', 1, 1], ['W', 0, 1], ['B', 1, 2], ['W', 0, 2], ['B', 0, 3]]], [3, 0, ['...B', 'BBB.', '....', '....']]], [[3, [['W', 0, 1], ['B', 0, 0], ['W', 1, 0], ['B', 'pass'], ['W', 2, 2]]], [0, 1, ['.W.', 'W..', '..W']]]], [[[4, [['B', 'pass'], ['W', 1, 0], ['B', 2, 3], ['W', 3, 2], ['B', 1, 3]]], [0, 0, ['....', 'W..B', '...B', '..W.']]], [[4, [['B', 0, 3], ['W', 'pass'], ['B', 3, 1], ['W', 3, 3], ['B', 3, 1], ['W', 0, 3], ['B', 1, 3], ['W', 'pass'], ['B', 3, 2], ['W', 'pass'], ['B', 3, 1], ['W', 0, 2], ['B', 3, 0]]], ['illegal', 4]], [[3, [['B', 1, 1], ['W', 2, 1], ['B', 2, 0], ['W', 0, 2], ['B', 0, 2], ['W', 0, 0], ['B', 2, 2], ['W', 2, 0], ['B', 2, 2], ['W', 0, 2], ['B', 2, 2], ['W', 2, 0]]], ['illegal', 4]], [[3, [['B', 1, 0], ['W', 0, 1], ['B', 0, 1], ['W', 0, 2], ['B', 2, 0], ['W', 1, 0], ['B', 0, 0], ['W', 2, 1], ['B', 2, 2], ['W', 2, 0], ['B', 1, 1], ['W', 0, 2], ['B', 1, 1], ['W', 0, 2]]], ['illegal', 2]], [[4, [['B', 0, 3], ['W', 3, 3], ['B', 1, 2], ['W', 0, 1], ['B', 3, 0]]], [0, 0, ['.W.B', '..B.', '....', 'B..W']]], [[4, [['B', 3, 0], ['W', 0, 3], ['B', 0, 2]]], [0, 0, ['..BW', '....', '....', 'B...']]], [[3, [['B', 1, 0], ['W', 0, 0], ['B', 1, 1], ['W', 0, 1], ['B', 0, 2]]], [2, 0, ['..B', 'BB.', '...']]], [[3, [['B', 1, 0], ['W', 0, 0], ['B', 1, 1], ['W', 0, 1], ['B', 0, 2]]], [2, 0, ['..B', 'BB.', '...']]]], [[[3, [['B', 2, 2], ['W', 1, 1], ['B', 1, 0], ['W', 2, 1], ['B', 0, 2]]], [0, 0, ['..B', 'BW.', '.WB']]], [[3, [['B', 0, 2], ['W', 0, 1], ['B', 1, 1], ['W', 2, 2], ['B', 0, 2], ['W', 'pass'], ['B', 1, 1], ['W', 'pass'], ['B', 0, 2], ['W', 2, 1], ['B', 'pass'], ['W', 0, 0], ['B', 'pass']]], ['illegal', 4]], [[3, [['B', 1, 1], ['W', 1, 2], ['B', 0, 2]]], [0, 0, ['..B', '.BW', '...']]], [[3, [['B', 2, 1], ['W', 'pass'], ['B', 'pass'], ['W', 0, 0], ['B', 1, 1], ['W', 0, 2], ['B', 0, 2], ['W', 2, 2], ['B', 0, 1]]], ['illegal', 6]], [[3, [['B', 2, 0], ['W', 0, 1], ['B', 1, 0], ['W', 1, 1], ['B', 2, 0], ['W', 1, 0], ['B', 0, 0], ['W', 'pass']]], ['illegal', 4]], [[4, [['B', 2, 3], ['W', 0, 2], ['B', 1, 3], ['W', 'pass'], ['B', 1, 0], ['W', 2, 1], ['B', 3, 0], ['W', 1, 1]]], [0, 0, ['..W.', 'BW.B', '.W.B', 'B...']]], [[3, [['W', 1, 0], ['B', 0, 0], ['W', 1, 1], ['B', 0, 1], ['W', 0, 2], ['B', 2, 2]]], [0, 2, ['..W', 'WW.', '..B']]], [[3, [['B', 0, 1], ['W', 0, 0], ['B', 1, 0]]], [1, 0, ['.B.', 'B..', '...']]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("replay 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
replay case 0[0, 0, ['....', '....', '...W', 'B...']][0, 0, ['....', '....', '...W', 'B...']]Passed
replay case 1['illegal', 2]['illegal', 2]Passed
replay case 2['illegal', 2]['illegal', 2]Passed
replay case 3['illegal', 3]['illegal', 3]Passed
replay case 4['illegal', 3]['illegal', 3]Passed
replay case 5['illegal', 8]['illegal', 8]Passed
replay case 6[0, 1, ['BW.', '.WW', '...']][0, 1, ['BW.', '.WW', '...']]Passed
replay case 7[2, 0, ['..B', 'BB.', '...']][2, 0, ['..B', 'BB.', '...']]Passed

SHA-256 / f1496f36a097c6d95009d0a6cf3ea56860b88ff4d6de09138791ecaf35771a9d

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.873170+00:00.

Case digest / ef4d8f2cd97ad46bf858ced864dd7f229389113e2a49c49037741ba4b238a99a