FAILURE MAP
← Case archive

FA-83091 / Go territory scoring / Open access

Diagonal empty points are counted as liberties · case 01

Chains in atari appear to have several liberties.

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

ROOT CAUSE

The liberty scan uses the eight-neighbourhood.

VERIFIED REPAIR

Only orthogonal empty points are liberties.

Unsuccessful approach: Counting just one diagonal direction still inflates liberties.

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] == 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), (i - 1, j - 1), (i - 1, j + 1), (i + 1, j - 1), (i + 1, j + 1)):
            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, 1], ['B', 4, 4]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 1, 1], ['B', 4, 4]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 2, 2], ['B', 1, 2]], [[['B.W', '...', 'W.B'], 2, 2], ['B', 1, 2]]], [[[['..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]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 2, 1], ['W', 1, 2]], [[['.....', '.BBB.', '.B.B.', '.BBB.', '.....'], 3, 3], ['B', 8, 13]]], [[[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 4, 3], ['.', 0, 0]], [[['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]], [[['B.W', '...', 'W.B'], 0, 2], ['W', 1, 2]], [[['BW..W', 'W..WW', 'W..W.', '.WWW.', '.W.BW'], 4, 1], ['W', 8, 9]]], [[[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0, 2], ['.', 0, 0]], [[['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]], [[['.B...', 'B....', '.....', '....W', '...W.'], 0, 1], ['B', 1, 3]], [[['....', 'W.BW', '....'], 1, 3], ['W', 1, 2]]], [[[['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]], [[['.....', '.BBB.', '.B.B.', '.BBB.', '.....'], 3, 3], ['B', 8, 13]], [[['..B..', 'B....', 'BB.BB', 'W...W'], 1, 0], ['B', 3, 4]]]]
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['B', 4, 4]['B', 4, 4]Passed
chain case 5['B', 4, 4]['B', 4, 4]Passed
chain case 6['B', 1, 3]['B', 1, 2]Failed
chain case 7['B', 1, 3]['B', 1, 2]Failed

SHA-256 / a640ce57f934866e3f0d4b2ea40d1a06f2c049826435ddfcd7291f36e7467a80

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] == 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), (i + 1, j + 1), (i - 1, j - 1)):
            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, 1], ['B', 4, 4]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 1, 1], ['B', 4, 4]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 2, 2], ['B', 1, 2]], [[['B.W', '...', 'W.B'], 2, 2], ['B', 1, 2]]], [[[['..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]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 2, 1], ['W', 1, 2]], [[['.....', '.BBB.', '.B.B.', '.BBB.', '.....'], 3, 3], ['B', 8, 13]]], [[[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 4, 3], ['.', 0, 0]], [[['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]], [[['B.W', '...', 'W.B'], 0, 2], ['W', 1, 2]], [[['BW..W', 'W..WW', 'W..W.', '.WWW.', '.W.BW'], 4, 1], ['W', 8, 9]]], [[[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0, 2], ['.', 0, 0]], [[['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]], [[['.B...', 'B....', '.....', '....W', '...W.'], 0, 1], ['B', 1, 3]], [[['....', 'W.BW', '....'], 1, 3], ['W', 1, 2]]], [[[['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]], [[['.....', '.BBB.', '.B.B.', '.BBB.', '.....'], 3, 3], ['B', 8, 13]], [[['..B..', 'B....', 'BB.BB', 'W...W'], 1, 0], ['B', 3, 4]]]]
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['B', 4, 4]['B', 4, 4]Passed
chain case 5['B', 4, 4]['B', 4, 4]Passed
chain case 6['B', 1, 3]['B', 1, 2]Failed
chain case 7['B', 1, 3]['B', 1, 2]Failed

SHA-256 / 72e56e7ac55eb77eba181baef17c9a814cacddc5ed6c2cad1d6d96b8f7e53284

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, 1], ['B', 4, 4]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 1, 1], ['B', 4, 4]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 2, 2], ['B', 1, 2]], [[['B.W', '...', 'W.B'], 2, 2], ['B', 1, 2]]], [[[['..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]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 2, 1], ['W', 1, 2]], [[['.....', '.BBB.', '.B.B.', '.BBB.', '.....'], 3, 3], ['B', 8, 13]]], [[[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 4, 3], ['.', 0, 0]], [[['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]], [[['B.W', '...', 'W.B'], 0, 2], ['W', 1, 2]], [[['BW..W', 'W..WW', 'W..W.', '.WWW.', '.W.BW'], 4, 1], ['W', 8, 9]]], [[[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0, 2], ['.', 0, 0]], [[['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]], [[['.B...', 'B....', '.....', '....W', '...W.'], 0, 1], ['B', 1, 3]], [[['....', 'W.BW', '....'], 1, 3], ['W', 1, 2]]], [[[['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]], [[['.....', '.BBB.', '.B.B.', '.BBB.', '.....'], 3, 3], ['B', 8, 13]], [[['..B..', 'B....', 'BB.BB', 'W...W'], 1, 0], ['B', 3, 4]]]]
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['B', 4, 4]['B', 4, 4]Passed
chain case 5['B', 4, 4]['B', 4, 4]Passed
chain case 6['B', 1, 2]['B', 1, 2]Passed
chain case 7['B', 1, 2]['B', 1, 2]Passed

SHA-256 / 169313991da1eb0255a32632a6e24d5776efa8b50735a392cf590cd410169ffb

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

Case digest / c601529a5ab5d5acaedfccef72113a1d66e61d4541e012149b1e0184d03d7360