FAILURE MAP
← Case archive

FA-83116 / Go territory scoring / Open access

Edge points can never be eyes · case 01

Points on the first line are classified as none.

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

ROOT CAUSE

Off-board orthogonal neighbours are recorded as a non-matching colour.

VERIFIED REPAIR

Consider only on-board orthogonal neighbours.

Unsuccessful approach: Wrapping the neighbour index to the opposite edge makes eye status depend on unrelated stones.

Case contract

Input [board, row, col]. A point is an eye candidate of colour X if it is empty and every on-board orthogonal neighbour is X. It is false if opponent stones occupy >= 2 diagonals in the centre, or >= 1 diagonal on the edge/corner. Return "eye-X", "false-X" or "none".

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])
    if board[r][c] != '.':
        return 'none'
    orth = []
    for p, q in ((r - 1, c), (r + 1, c), (r, c - 1), (r, c + 1)):
        orth.append(board[p][q] if 0 <= p < n and 0 <= q < m else '#')
    if not orth or orth.count(orth[0]) != len(orth) or orth[0] == '.':
        return 'none'
    col = orth[0]
    opp = 'W' if col == 'B' else 'B'
    bad = 0
    ondiag = 0
    for p, q in ((r - 1, c - 1), (r - 1, c + 1), (r + 1, c - 1), (r + 1, c + 1)):
        if 0 <= p < n and 0 <= q < m:
            ondiag += 1
            if board[p][q] == opp:
                bad += 1
    limit = 2 if ondiag == 4 else 1
    if bad >= limit:
        return 'false-' + col
    return 'eye-' + col
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['...', '...', '...'], 0, 1], 'none'], [[['...', '...', '...'], 0, 2], 'none'], [[['...', '...', '...'], 1, 0], 'none'], [[['...', '...', '...'], 1, 1], 'none'], [[['...', '...', '...'], 1, 2], 'none'], [[['.B.', 'B.B', '.B.'], 0, 0], 'eye-B'], [[['.B.', 'B.B', '.B.'], 0, 2], 'eye-B'], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0, 0], 'eye-W']], [[[['.B.', 'B.B', '.B.'], 1, 1], 'eye-B'], [[['.B.', 'B.B', '.B.'], 2, 0], 'eye-B'], [[['.B.', 'B.B', '.B.'], 2, 2], 'eye-B'], [[['.B.', 'B.B', '.B.'], 0, 1], 'none'], [[['B..W', 'B..W', 'B..W', 'B..W'], 0, 1], 'none'], [[['B..W', 'B..W', 'B..W', 'B..W'], 0, 2], 'none'], [[['B..W', 'B..W', 'B..W', 'B..W'], 1, 1], 'none'], [[['..W.', '...W', '.WB.', '...B'], 0, 3], 'eye-W']], [[[['B..W', 'B..W', 'B..W', 'B..W'], 1, 2], 'none'], [[['B..W', 'B..W', 'B..W', 'B..W'], 2, 1], 'none'], [[['B..W', 'B..W', 'B..W', 'B..W'], 2, 2], 'none'], [[['B..W', 'B..W', 'B..W', 'B..W'], 0, 0], 'none'], [[['.BW.', '.BW.', '.BW.', '.BW.'], 0, 0], 'none'], [[['.BW.', '.BW.', '.BW.', '.BW.'], 0, 3], 'none'], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0, 0], 'eye-W'], [[['WW.WW', 'WB.B.', 'WBW.W', 'W.WBB', 'BBB.B'], 4, 3], 'false-B']], [[[['.BW.', '.BW.', '.BW.', '.BW.'], 1, 3], 'none'], [[['.BW.', '.BW.', '.BW.', '.BW.'], 2, 0], 'none'], [[['.BW.', '.BW.', '.BW.', '.BW.'], 2, 3], 'none'], [[['.BW.', '.BW.', '.BW.', '.BW.'], 0, 1], 'none'], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0, 0], 'none'], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0, 1], 'none'], [[['WB.B', 'B.B.', '.B..', 'B...'], 0, 2], 'eye-B'], [[['.B.', 'B.B', '.B.'], 0, 0], 'eye-B']], [[[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0, 4], 'none'], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 1, 0], 'none'], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 1, 1], 'none'], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0, 2], 'none'], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 0, 1], 'eye-B'], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 0, 3], 'none'], [[['WBW', '..W', '.WW', '.W.'], 3, 2], 'eye-W'], [[['W.W', '.W.', 'W.W'], 0, 1], 'eye-W']]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("eye 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
eye case 0nonenonePassed
eye case 1nonenonePassed
eye case 2nonenonePassed
eye case 3nonenonePassed
eye case 4nonenonePassed
eye case 5noneeye-BFailed
eye case 6noneeye-BFailed
eye case 7noneeye-WFailed

SHA-256 / 1bbe9dbb7fbea6a9a6104185ce01877f62d9e4e420976c51c945f5383f957c69

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])
    if board[r][c] != '.':
        return 'none'
    orth = []
    for p, q in ((r - 1, c), (r + 1, c), (r, c - 1), (r, c + 1)):
        orth.append(board[p % n][q % m])
    if not orth or orth.count(orth[0]) != len(orth) or orth[0] == '.':
        return 'none'
    col = orth[0]
    opp = 'W' if col == 'B' else 'B'
    bad = 0
    ondiag = 0
    for p, q in ((r - 1, c - 1), (r - 1, c + 1), (r + 1, c - 1), (r + 1, c + 1)):
        if 0 <= p < n and 0 <= q < m:
            ondiag += 1
            if board[p][q] == opp:
                bad += 1
    limit = 2 if ondiag == 4 else 1
    if bad >= limit:
        return 'false-' + col
    return 'eye-' + col
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['...', '...', '...'], 0, 1], 'none'], [[['...', '...', '...'], 0, 2], 'none'], [[['...', '...', '...'], 1, 0], 'none'], [[['...', '...', '...'], 1, 1], 'none'], [[['...', '...', '...'], 1, 2], 'none'], [[['.B.', 'B.B', '.B.'], 0, 0], 'eye-B'], [[['.B.', 'B.B', '.B.'], 0, 2], 'eye-B'], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0, 0], 'eye-W']], [[[['.B.', 'B.B', '.B.'], 1, 1], 'eye-B'], [[['.B.', 'B.B', '.B.'], 2, 0], 'eye-B'], [[['.B.', 'B.B', '.B.'], 2, 2], 'eye-B'], [[['.B.', 'B.B', '.B.'], 0, 1], 'none'], [[['B..W', 'B..W', 'B..W', 'B..W'], 0, 1], 'none'], [[['B..W', 'B..W', 'B..W', 'B..W'], 0, 2], 'none'], [[['B..W', 'B..W', 'B..W', 'B..W'], 1, 1], 'none'], [[['..W.', '...W', '.WB.', '...B'], 0, 3], 'eye-W']], [[[['B..W', 'B..W', 'B..W', 'B..W'], 1, 2], 'none'], [[['B..W', 'B..W', 'B..W', 'B..W'], 2, 1], 'none'], [[['B..W', 'B..W', 'B..W', 'B..W'], 2, 2], 'none'], [[['B..W', 'B..W', 'B..W', 'B..W'], 0, 0], 'none'], [[['.BW.', '.BW.', '.BW.', '.BW.'], 0, 0], 'none'], [[['.BW.', '.BW.', '.BW.', '.BW.'], 0, 3], 'none'], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0, 0], 'eye-W'], [[['WW.WW', 'WB.B.', 'WBW.W', 'W.WBB', 'BBB.B'], 4, 3], 'false-B']], [[[['.BW.', '.BW.', '.BW.', '.BW.'], 1, 3], 'none'], [[['.BW.', '.BW.', '.BW.', '.BW.'], 2, 0], 'none'], [[['.BW.', '.BW.', '.BW.', '.BW.'], 2, 3], 'none'], [[['.BW.', '.BW.', '.BW.', '.BW.'], 0, 1], 'none'], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0, 0], 'none'], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0, 1], 'none'], [[['WB.B', 'B.B.', '.B..', 'B...'], 0, 2], 'eye-B'], [[['.B.', 'B.B', '.B.'], 0, 0], 'eye-B']], [[[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0, 4], 'none'], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 1, 0], 'none'], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 1, 1], 'none'], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0, 2], 'none'], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 0, 1], 'eye-B'], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 0, 3], 'none'], [[['WBW', '..W', '.WW', '.W.'], 3, 2], 'eye-W'], [[['W.W', '.W.', 'W.W'], 0, 1], 'eye-W']]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("eye 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
eye case 0nonenonePassed
eye case 1nonenonePassed
eye case 2nonenonePassed
eye case 3nonenonePassed
eye case 4nonenonePassed
eye case 5noneeye-BFailed
eye case 6noneeye-BFailed
eye case 7noneeye-WFailed

SHA-256 / 7cd1b9518906e63dcdce96a13c08319444448f3cce7be781bd05792cedcb101a

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])
    if board[r][c] != '.':
        return 'none'
    orth = []
    for p, q in ((r - 1, c), (r + 1, c), (r, c - 1), (r, c + 1)):
        if 0 <= p < n and 0 <= q < m:
            orth.append(board[p][q])
    if not orth or orth.count(orth[0]) != len(orth) or orth[0] == '.':
        return 'none'
    col = orth[0]
    opp = 'W' if col == 'B' else 'B'
    bad = 0
    ondiag = 0
    for p, q in ((r - 1, c - 1), (r - 1, c + 1), (r + 1, c - 1), (r + 1, c + 1)):
        if 0 <= p < n and 0 <= q < m:
            ondiag += 1
            if board[p][q] == opp:
                bad += 1
    limit = 2 if ondiag == 4 else 1
    if bad >= limit:
        return 'false-' + col
    return 'eye-' + col
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['...', '...', '...'], 0, 1], 'none'], [[['...', '...', '...'], 0, 2], 'none'], [[['...', '...', '...'], 1, 0], 'none'], [[['...', '...', '...'], 1, 1], 'none'], [[['...', '...', '...'], 1, 2], 'none'], [[['.B.', 'B.B', '.B.'], 0, 0], 'eye-B'], [[['.B.', 'B.B', '.B.'], 0, 2], 'eye-B'], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0, 0], 'eye-W']], [[[['.B.', 'B.B', '.B.'], 1, 1], 'eye-B'], [[['.B.', 'B.B', '.B.'], 2, 0], 'eye-B'], [[['.B.', 'B.B', '.B.'], 2, 2], 'eye-B'], [[['.B.', 'B.B', '.B.'], 0, 1], 'none'], [[['B..W', 'B..W', 'B..W', 'B..W'], 0, 1], 'none'], [[['B..W', 'B..W', 'B..W', 'B..W'], 0, 2], 'none'], [[['B..W', 'B..W', 'B..W', 'B..W'], 1, 1], 'none'], [[['..W.', '...W', '.WB.', '...B'], 0, 3], 'eye-W']], [[[['B..W', 'B..W', 'B..W', 'B..W'], 1, 2], 'none'], [[['B..W', 'B..W', 'B..W', 'B..W'], 2, 1], 'none'], [[['B..W', 'B..W', 'B..W', 'B..W'], 2, 2], 'none'], [[['B..W', 'B..W', 'B..W', 'B..W'], 0, 0], 'none'], [[['.BW.', '.BW.', '.BW.', '.BW.'], 0, 0], 'none'], [[['.BW.', '.BW.', '.BW.', '.BW.'], 0, 3], 'none'], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0, 0], 'eye-W'], [[['WW.WW', 'WB.B.', 'WBW.W', 'W.WBB', 'BBB.B'], 4, 3], 'false-B']], [[[['.BW.', '.BW.', '.BW.', '.BW.'], 1, 3], 'none'], [[['.BW.', '.BW.', '.BW.', '.BW.'], 2, 0], 'none'], [[['.BW.', '.BW.', '.BW.', '.BW.'], 2, 3], 'none'], [[['.BW.', '.BW.', '.BW.', '.BW.'], 0, 1], 'none'], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0, 0], 'none'], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0, 1], 'none'], [[['WB.B', 'B.B.', '.B..', 'B...'], 0, 2], 'eye-B'], [[['.B.', 'B.B', '.B.'], 0, 0], 'eye-B']], [[[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0, 4], 'none'], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 1, 0], 'none'], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 1, 1], 'none'], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0, 2], 'none'], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 0, 1], 'eye-B'], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 0, 3], 'none'], [[['WBW', '..W', '.WW', '.W.'], 3, 2], 'eye-W'], [[['W.W', '.W.', 'W.W'], 0, 1], 'eye-W']]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("eye 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
eye case 0nonenonePassed
eye case 1nonenonePassed
eye case 2nonenonePassed
eye case 3nonenonePassed
eye case 4nonenonePassed
eye case 5eye-Beye-BPassed
eye case 6eye-Beye-BPassed
eye case 7eye-Weye-WPassed

SHA-256 / 6e7be70552686766ea6cc78938f927406796897dc3bd81524be41371f1260fe5

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

Case digest / 683f7f6baa66ad01ae233d79f8c4a544fc06b261cc1ebc684931a915a3012d39