FAILURE MAP
← Case archive

FA-83191 / Go territory scoring / Open access

Territory is rendered with live-stone letters · case 01

Territory points look like stones in the map.

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

ROOT CAUSE

The owner colour is used without lower-casing.

VERIFIED REPAIR

Render territory as lower-case b/w.

Unsuccessful approach: Rendering dame as "." instead of "?" makes neutral points look unscored.

Case contract

Input [board, dead_points]. Remove dead stones, then render each point: live stones as B/W, territory (region bordered by one colour) as lower-case b/w, other empty points as "?". Return 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):
    board, dead = x
    n = len(board)
    m = len(board[0])
    dd = {tuple(p) for p in dead}
    g = [[('.' if (r, c) in dd else board[r][c]) for c in range(m)] for r in range(n)]
    out = [[g[r][c] for c in range(m)] for r in range(n)]
    seen = set()
    for r in range(n):
        for c in range(m):
            if g[r][c] != '.' or (r, c) in seen:
                continue
            seen.add((r, c))
            region = [(r, c)]
            k = 0
            cols = set()
            while k < len(region):
                i, j = region[k]
                k += 1
                for p, q in ((i - 1, j), (i, j - 1), (i + 1, j), (i, j + 1)):
                    if 0 <= p < n and 0 <= q < m:
                        if g[p][q] == '.':
                            if (p, q) not in seen:
                                seen.add((p, q))
                                region.append((p, q))
                        else:
                            cols.add(g[p][q])
            mark = cols.pop() if len(cols) == 1 else '?'
            for i, j in region:
                out[i][j] = mark
    return [''.join(row) for row in out]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['...BW..', '...BW..', '...BW..', '...BWB.', '...BW.B'], [[4, 6], [4, 4]]], ['bbbBW??', 'bbbBW??', 'bbbBW??', 'bbbBWB?', 'bbbB???']], [[['.BW.', '.BW.', 'WBW.', '.BW.', '.BW.', 'WBW.'], [[0, 1], [2, 0]]], ['??Ww', '?BWw', '?BWw', '?BWw', '?BWw', 'WBWw']], [[['.BWB.', '.BW..', '.BW..', '.BWB.'], [[2, 2], [0, 2]]], ['bB?B?', 'bBW??', 'bB???', 'bBWB?']], [[['WBW...', '.BW...', '.BW..B', '.BW...', '.BW...'], [[0, 2]]], ['WB????', '?BW???', '?BW??B', '?BW???', '?BW???']], [[['.BW.B..', 'WBW....', '.BW....', '.BW....', '.BW....'], [[2, 2]]], ['?BW?B??', 'WBW????', '?B?????', '?BW????', '?BW????']], [[['....BW', '....BW', '....BW', '....BW', '....BW', '....BW'], [[2, 5], [2, 4]]], ['????BW', '????BW', '??????', '????BW', '????BW', '????BW']], [[['..BW', '..BW', '..BW', '..BW', '..BW', '..BW', '..BW'], [[3, 2]]], ['??BW', '??BW', '??BW', '???W', '??BW', '??BW', '??BW']], [[['W.BW.', '..BW.', '.WBW.', '.WBW.', '..BW.', '..BW.', '..BW.'], []], ['W?BWw', '??BWw', '?WBWw', '?WBWw', '??BWw', '??BWw', '??BWw']]], [[[['...WBW.', '....BW.', '....BW.', '.W..BW.'], []], ['???WBWw', '????BWw', '????BWw', '?W??BWw']], [[['.BW.B..', 'WBW....', '.BW....', '.BW....', '.BW....'], [[2, 2]]], ['?BW?B??', 'WBW????', '?B?????', '?BW????', '?BW????']], [[['.BWB', '.BW.', 'WBW.', '.BW.', '.BW.', 'WBW.'], [[4, 1]]], ['?BWB', '?BW?', 'WBW?', '?BW?', '??W?', 'WBW?']], [[['.BW.', '.BW.', 'WBW.', '.BW.', '.BW.'], [[0, 1], [3, 1]]], ['??Ww', '?BWw', 'WBWw', '??Ww', '?BWw']], [[['.W..BW', '....BW', 'W...BW', '....BW'], [[1, 4]]], ['?W??BW', '?????W', 'W???BW', '????BW']], [[['..BW', '..BW', 'W.BW', '..BW', '..BW'], [[4, 2], [3, 2]]], ['??BW', '??BW', 'W?BW', '???W', '???W']], [[['.BW...', '.BW...', '.BW...', 'WBW..B', '.BW..B', '.BW..B'], []], ['?BW???', '?BW???', '?BW???', 'WBW??B', '?BW??B', '?BW??B']], [[['.BW..', 'WBW..', 'WBWB.', '.BW..', '.BW..'], []], ['?BW??', 'WBW??', 'WBWB?', '?BW??', '?BW??']]], [[[['.BWB', '.BW.', 'WBW.', '.BW.', '.BW.', 'WBW.'], [[4, 1]]], ['?BWB', '?BW?', 'WBW?', '?BW?', '??W?', 'WBW?']], [[['.BW.', '.BW.', 'WBW.', '.BW.', '.BW.'], [[0, 1], [3, 1]]], ['??Ww', '?BWw', 'WBWw', '??Ww', '?BWw']], [[['...BW', '..WBW', '...BW', '...BW', '...BW'], []], ['???BW', '??WBW', '???BW', '???BW', '???BW']], [[['...BW', '...BW', '...BW', 'W..BW'], []], ['???BW', '???BW', '???BW', 'W??BW']], [[['..BW.', '..BW.', '..BWB', '..BW.', '..BW.', '..BW.', '..BW.'], [[2, 2], [3, 3]]], ['??BW?', '??BW?', '???WB', '??B??', '??BW?', '??BW?', '??BW?']], [[['.BW..', '.BW.B', '.BWB.', '.BW..', '.BW.B', '.BW..', 'WBW..'], [[4, 1]]], ['?BW??', '?BW?B', '?BWB?', '?BW??', '??W?B', '?BW??', 'WBW??']], [[['..BW', 'W.BW', '..BW', '..BW', '..BW', 'W.BW'], [[0, 2], [5, 3]]], ['???W', 'W?BW', '??BW', '??BW', '??BW', 'W?B?']], [[['...BW.', '...BW.', '...BW.', '...BW.', '...BW.', '...BW.'], [[2, 4]]], ['bbbBW?', 'bbbBW?', 'bbbB??', 'bbbBW?', 'bbbBW?', 'bbbBW?']]], [[[['.BW..', 'WBW..', 'WBWB.', '.BW..', '.BW..'], []], ['?BW??', 'WBW??', 'WBWB?', '?BW??', '?BW??']], [[['...BW', '...BW', 'W..BW', 'W.WBW', '...BW', '...BW'], []], ['???BW', '???BW', 'W??BW', 'W?WBW', '???BW', '???BW']], [[['....', '....', '....', '....'], []], ['????', '????', '????', '????']], [[['...', '...', '...'], []], ['???', '???', '???']], [[['.B.', 'B.B', '.B.'], [[1, 2], [2, 1]]], ['bBb', 'Bbb', 'bbb']], [[['B..W', 'B..W', 'B..W', 'B..W'], [[2, 3]]], ['B??W', 'B??W', 'B???', 'B??W']], [[['.BW.', '.BW.', '.BW.', '.BW.'], [[0, 2]]], ['bB??', 'bBW?', 'bBW?', 'bBW?']], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], [[0, 2]]], ['bbbbb', 'bbBbb', 'BBBBB', 'WWWWW', 'wwWww']]], [[[['.BW..', '.BW.B', '.BWB.', '.BW..', '.BW.B', '.BW..', 'WBW..'], [[4, 1]]], ['?BW??', '?BW?B', '?BWB?', '?BW??', '??W?B', '?BW??', 'WBW??']], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], []], ['BbB?W', 'bB?Ww', 'BbBWw', 'BBWwW', '??Www']], [[['W....', '.....', '.....', '.....', '....B'], [[4, 4]]], ['Wwwww', 'wwwww', 'wwwww', 'wwwww', 'wwwww']], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], [[3, 1], [3, 0]]], ['wW?B?', 'WwWB?', '?WB??', '?????', 'B????']], [[['BBBB', 'B..B', 'B..B', 'BBBB'], [[0, 2]]], ['BBbB', 'BbbB', 'BbbB', 'BBBB']], [[['WWW', 'W.W', 'WWW'], []], ['WWW', 'WwW', 'WWW']], [[['B.W', '...', 'W.B'], [[2, 2], [0, 0]]], ['wwW', 'www', 'Www']], [[['.B...', 'B....', '.....', '....W', '...W.'], [[1, 0]]], ['?B???', '?????', '?????', '????W', '???Ww']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("ownership map 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
ownership map case 0['BBBBW??', 'BBBBW??', 'BBBBW??', 'BBBBWB?', 'BBBB???']['bbbBW??', 'bbbBW??', 'bbbBW??', 'bbbBWB?', 'bbbB???']Failed
ownership map case 1['??WW', '?BWW', '?BWW', '?BWW', '?BWW', 'WBWW']['??Ww', '?BWw', '?BWw', '?BWw', '?BWw', 'WBWw']Failed
ownership map case 2['BB?B?', 'BBW??', 'BB???', 'BBWB?']['bB?B?', 'bBW??', 'bB???', 'bBWB?']Failed
ownership map case 3['WB????', '?BW???', '?BW??B', '?BW???', '?BW???']['WB????', '?BW???', '?BW??B', '?BW???', '?BW???']Passed
ownership map case 4['?BW?B??', 'WBW????', '?B?????', '?BW????', '?BW????']['?BW?B??', 'WBW????', '?B?????', '?BW????', '?BW????']Passed
ownership map case 5['????BW', '????BW', '??????', '????BW', '????BW', '????BW']['????BW', '????BW', '??????', '????BW', '????BW', '????BW']Passed
ownership map case 6['??BW', '??BW', '??BW', '???W', '??BW', '??BW', '??BW']['??BW', '??BW', '??BW', '???W', '??BW', '??BW', '??BW']Passed
ownership map case 7['W?BWW', '??BWW', '?WBWW', '?WBWW', '??BWW', '??BWW', '??BWW']['W?BWw', '??BWw', '?WBWw', '?WBWw', '??BWw', '??BWw', '??BWw']Failed

SHA-256 / 82cd385c5c3ad8e93770f44a0fe2eb3c46c61baa468bf7be1f6b4ce3ef020b68

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(x):
    board, dead = x
    n = len(board)
    m = len(board[0])
    dd = {tuple(p) for p in dead}
    g = [[('.' if (r, c) in dd else board[r][c]) for c in range(m)] for r in range(n)]
    out = [[g[r][c] for c in range(m)] for r in range(n)]
    seen = set()
    for r in range(n):
        for c in range(m):
            if g[r][c] != '.' or (r, c) in seen:
                continue
            seen.add((r, c))
            region = [(r, c)]
            k = 0
            cols = set()
            while k < len(region):
                i, j = region[k]
                k += 1
                for p, q in ((i - 1, j), (i, j - 1), (i + 1, j), (i, j + 1)):
                    if 0 <= p < n and 0 <= q < m:
                        if g[p][q] == '.':
                            if (p, q) not in seen:
                                seen.add((p, q))
                                region.append((p, q))
                        else:
                            cols.add(g[p][q])
            mark = cols.pop().lower() if len(cols) == 1 else '.'
            for i, j in region:
                out[i][j] = mark
    return [''.join(row) for row in out]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['...BW..', '...BW..', '...BW..', '...BWB.', '...BW.B'], [[4, 6], [4, 4]]], ['bbbBW??', 'bbbBW??', 'bbbBW??', 'bbbBWB?', 'bbbB???']], [[['.BW.', '.BW.', 'WBW.', '.BW.', '.BW.', 'WBW.'], [[0, 1], [2, 0]]], ['??Ww', '?BWw', '?BWw', '?BWw', '?BWw', 'WBWw']], [[['.BWB.', '.BW..', '.BW..', '.BWB.'], [[2, 2], [0, 2]]], ['bB?B?', 'bBW??', 'bB???', 'bBWB?']], [[['WBW...', '.BW...', '.BW..B', '.BW...', '.BW...'], [[0, 2]]], ['WB????', '?BW???', '?BW??B', '?BW???', '?BW???']], [[['.BW.B..', 'WBW....', '.BW....', '.BW....', '.BW....'], [[2, 2]]], ['?BW?B??', 'WBW????', '?B?????', '?BW????', '?BW????']], [[['....BW', '....BW', '....BW', '....BW', '....BW', '....BW'], [[2, 5], [2, 4]]], ['????BW', '????BW', '??????', '????BW', '????BW', '????BW']], [[['..BW', '..BW', '..BW', '..BW', '..BW', '..BW', '..BW'], [[3, 2]]], ['??BW', '??BW', '??BW', '???W', '??BW', '??BW', '??BW']], [[['W.BW.', '..BW.', '.WBW.', '.WBW.', '..BW.', '..BW.', '..BW.'], []], ['W?BWw', '??BWw', '?WBWw', '?WBWw', '??BWw', '??BWw', '??BWw']]], [[[['...WBW.', '....BW.', '....BW.', '.W..BW.'], []], ['???WBWw', '????BWw', '????BWw', '?W??BWw']], [[['.BW.B..', 'WBW....', '.BW....', '.BW....', '.BW....'], [[2, 2]]], ['?BW?B??', 'WBW????', '?B?????', '?BW????', '?BW????']], [[['.BWB', '.BW.', 'WBW.', '.BW.', '.BW.', 'WBW.'], [[4, 1]]], ['?BWB', '?BW?', 'WBW?', '?BW?', '??W?', 'WBW?']], [[['.BW.', '.BW.', 'WBW.', '.BW.', '.BW.'], [[0, 1], [3, 1]]], ['??Ww', '?BWw', 'WBWw', '??Ww', '?BWw']], [[['.W..BW', '....BW', 'W...BW', '....BW'], [[1, 4]]], ['?W??BW', '?????W', 'W???BW', '????BW']], [[['..BW', '..BW', 'W.BW', '..BW', '..BW'], [[4, 2], [3, 2]]], ['??BW', '??BW', 'W?BW', '???W', '???W']], [[['.BW...', '.BW...', '.BW...', 'WBW..B', '.BW..B', '.BW..B'], []], ['?BW???', '?BW???', '?BW???', 'WBW??B', '?BW??B', '?BW??B']], [[['.BW..', 'WBW..', 'WBWB.', '.BW..', '.BW..'], []], ['?BW??', 'WBW??', 'WBWB?', '?BW??', '?BW??']]], [[[['.BWB', '.BW.', 'WBW.', '.BW.', '.BW.', 'WBW.'], [[4, 1]]], ['?BWB', '?BW?', 'WBW?', '?BW?', '??W?', 'WBW?']], [[['.BW.', '.BW.', 'WBW.', '.BW.', '.BW.'], [[0, 1], [3, 1]]], ['??Ww', '?BWw', 'WBWw', '??Ww', '?BWw']], [[['...BW', '..WBW', '...BW', '...BW', '...BW'], []], ['???BW', '??WBW', '???BW', '???BW', '???BW']], [[['...BW', '...BW', '...BW', 'W..BW'], []], ['???BW', '???BW', '???BW', 'W??BW']], [[['..BW.', '..BW.', '..BWB', '..BW.', '..BW.', '..BW.', '..BW.'], [[2, 2], [3, 3]]], ['??BW?', '??BW?', '???WB', '??B??', '??BW?', '??BW?', '??BW?']], [[['.BW..', '.BW.B', '.BWB.', '.BW..', '.BW.B', '.BW..', 'WBW..'], [[4, 1]]], ['?BW??', '?BW?B', '?BWB?', '?BW??', '??W?B', '?BW??', 'WBW??']], [[['..BW', 'W.BW', '..BW', '..BW', '..BW', 'W.BW'], [[0, 2], [5, 3]]], ['???W', 'W?BW', '??BW', '??BW', '??BW', 'W?B?']], [[['...BW.', '...BW.', '...BW.', '...BW.', '...BW.', '...BW.'], [[2, 4]]], ['bbbBW?', 'bbbBW?', 'bbbB??', 'bbbBW?', 'bbbBW?', 'bbbBW?']]], [[[['.BW..', 'WBW..', 'WBWB.', '.BW..', '.BW..'], []], ['?BW??', 'WBW??', 'WBWB?', '?BW??', '?BW??']], [[['...BW', '...BW', 'W..BW', 'W.WBW', '...BW', '...BW'], []], ['???BW', '???BW', 'W??BW', 'W?WBW', '???BW', '???BW']], [[['....', '....', '....', '....'], []], ['????', '????', '????', '????']], [[['...', '...', '...'], []], ['???', '???', '???']], [[['.B.', 'B.B', '.B.'], [[1, 2], [2, 1]]], ['bBb', 'Bbb', 'bbb']], [[['B..W', 'B..W', 'B..W', 'B..W'], [[2, 3]]], ['B??W', 'B??W', 'B???', 'B??W']], [[['.BW.', '.BW.', '.BW.', '.BW.'], [[0, 2]]], ['bB??', 'bBW?', 'bBW?', 'bBW?']], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], [[0, 2]]], ['bbbbb', 'bbBbb', 'BBBBB', 'WWWWW', 'wwWww']]], [[[['.BW..', '.BW.B', '.BWB.', '.BW..', '.BW.B', '.BW..', 'WBW..'], [[4, 1]]], ['?BW??', '?BW?B', '?BWB?', '?BW??', '??W?B', '?BW??', 'WBW??']], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], []], ['BbB?W', 'bB?Ww', 'BbBWw', 'BBWwW', '??Www']], [[['W....', '.....', '.....', '.....', '....B'], [[4, 4]]], ['Wwwww', 'wwwww', 'wwwww', 'wwwww', 'wwwww']], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], [[3, 1], [3, 0]]], ['wW?B?', 'WwWB?', '?WB??', '?????', 'B????']], [[['BBBB', 'B..B', 'B..B', 'BBBB'], [[0, 2]]], ['BBbB', 'BbbB', 'BbbB', 'BBBB']], [[['WWW', 'W.W', 'WWW'], []], ['WWW', 'WwW', 'WWW']], [[['B.W', '...', 'W.B'], [[2, 2], [0, 0]]], ['wwW', 'www', 'Www']], [[['.B...', 'B....', '.....', '....W', '...W.'], [[1, 0]]], ['?B???', '?????', '?????', '????W', '???Ww']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("ownership map 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
ownership map case 0['bbbBW..', 'bbbBW..', 'bbbBW..', 'bbbBWB.', 'bbbB...']['bbbBW??', 'bbbBW??', 'bbbBW??', 'bbbBWB?', 'bbbB???']Failed
ownership map case 1['..Ww', '.BWw', '.BWw', '.BWw', '.BWw', 'WBWw']['??Ww', '?BWw', '?BWw', '?BWw', '?BWw', 'WBWw']Failed
ownership map case 2['bB.B.', 'bBW..', 'bB...', 'bBWB.']['bB?B?', 'bBW??', 'bB???', 'bBWB?']Failed
ownership map case 3['WB....', '.BW...', '.BW..B', '.BW...', '.BW...']['WB????', '?BW???', '?BW??B', '?BW???', '?BW???']Failed
ownership map case 4['.BW.B..', 'WBW....', '.B.....', '.BW....', '.BW....']['?BW?B??', 'WBW????', '?B?????', '?BW????', '?BW????']Failed
ownership map case 5['....BW', '....BW', '......', '....BW', '....BW', '....BW']['????BW', '????BW', '??????', '????BW', '????BW', '????BW']Failed
ownership map case 6['..BW', '..BW', '..BW', '...W', '..BW', '..BW', '..BW']['??BW', '??BW', '??BW', '???W', '??BW', '??BW', '??BW']Failed
ownership map case 7['W.BWw', '..BWw', '.WBWw', '.WBWw', '..BWw', '..BWw', '..BWw']['W?BWw', '??BWw', '?WBWw', '?WBWw', '??BWw', '??BWw', '??BWw']Failed

SHA-256 / 5e50c5b6a5b8984077a3be226fc637c0ace50112bd6ec75c9aa30526f78825bf

3 / The verified repair

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

N = 1
observations = []
def solve(x):
    board, dead = x
    n = len(board)
    m = len(board[0])
    dd = {tuple(p) for p in dead}
    g = [[('.' if (r, c) in dd else board[r][c]) for c in range(m)] for r in range(n)]
    out = [[g[r][c] for c in range(m)] for r in range(n)]
    seen = set()
    for r in range(n):
        for c in range(m):
            if g[r][c] != '.' or (r, c) in seen:
                continue
            seen.add((r, c))
            region = [(r, c)]
            k = 0
            cols = set()
            while k < len(region):
                i, j = region[k]
                k += 1
                for p, q in ((i - 1, j), (i, j - 1), (i + 1, j), (i, j + 1)):
                    if 0 <= p < n and 0 <= q < m:
                        if g[p][q] == '.':
                            if (p, q) not in seen:
                                seen.add((p, q))
                                region.append((p, q))
                        else:
                            cols.add(g[p][q])
            mark = cols.pop().lower() if len(cols) == 1 else '?'
            for i, j in region:
                out[i][j] = mark
    return [''.join(row) for row in out]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['...BW..', '...BW..', '...BW..', '...BWB.', '...BW.B'], [[4, 6], [4, 4]]], ['bbbBW??', 'bbbBW??', 'bbbBW??', 'bbbBWB?', 'bbbB???']], [[['.BW.', '.BW.', 'WBW.', '.BW.', '.BW.', 'WBW.'], [[0, 1], [2, 0]]], ['??Ww', '?BWw', '?BWw', '?BWw', '?BWw', 'WBWw']], [[['.BWB.', '.BW..', '.BW..', '.BWB.'], [[2, 2], [0, 2]]], ['bB?B?', 'bBW??', 'bB???', 'bBWB?']], [[['WBW...', '.BW...', '.BW..B', '.BW...', '.BW...'], [[0, 2]]], ['WB????', '?BW???', '?BW??B', '?BW???', '?BW???']], [[['.BW.B..', 'WBW....', '.BW....', '.BW....', '.BW....'], [[2, 2]]], ['?BW?B??', 'WBW????', '?B?????', '?BW????', '?BW????']], [[['....BW', '....BW', '....BW', '....BW', '....BW', '....BW'], [[2, 5], [2, 4]]], ['????BW', '????BW', '??????', '????BW', '????BW', '????BW']], [[['..BW', '..BW', '..BW', '..BW', '..BW', '..BW', '..BW'], [[3, 2]]], ['??BW', '??BW', '??BW', '???W', '??BW', '??BW', '??BW']], [[['W.BW.', '..BW.', '.WBW.', '.WBW.', '..BW.', '..BW.', '..BW.'], []], ['W?BWw', '??BWw', '?WBWw', '?WBWw', '??BWw', '??BWw', '??BWw']]], [[[['...WBW.', '....BW.', '....BW.', '.W..BW.'], []], ['???WBWw', '????BWw', '????BWw', '?W??BWw']], [[['.BW.B..', 'WBW....', '.BW....', '.BW....', '.BW....'], [[2, 2]]], ['?BW?B??', 'WBW????', '?B?????', '?BW????', '?BW????']], [[['.BWB', '.BW.', 'WBW.', '.BW.', '.BW.', 'WBW.'], [[4, 1]]], ['?BWB', '?BW?', 'WBW?', '?BW?', '??W?', 'WBW?']], [[['.BW.', '.BW.', 'WBW.', '.BW.', '.BW.'], [[0, 1], [3, 1]]], ['??Ww', '?BWw', 'WBWw', '??Ww', '?BWw']], [[['.W..BW', '....BW', 'W...BW', '....BW'], [[1, 4]]], ['?W??BW', '?????W', 'W???BW', '????BW']], [[['..BW', '..BW', 'W.BW', '..BW', '..BW'], [[4, 2], [3, 2]]], ['??BW', '??BW', 'W?BW', '???W', '???W']], [[['.BW...', '.BW...', '.BW...', 'WBW..B', '.BW..B', '.BW..B'], []], ['?BW???', '?BW???', '?BW???', 'WBW??B', '?BW??B', '?BW??B']], [[['.BW..', 'WBW..', 'WBWB.', '.BW..', '.BW..'], []], ['?BW??', 'WBW??', 'WBWB?', '?BW??', '?BW??']]], [[[['.BWB', '.BW.', 'WBW.', '.BW.', '.BW.', 'WBW.'], [[4, 1]]], ['?BWB', '?BW?', 'WBW?', '?BW?', '??W?', 'WBW?']], [[['.BW.', '.BW.', 'WBW.', '.BW.', '.BW.'], [[0, 1], [3, 1]]], ['??Ww', '?BWw', 'WBWw', '??Ww', '?BWw']], [[['...BW', '..WBW', '...BW', '...BW', '...BW'], []], ['???BW', '??WBW', '???BW', '???BW', '???BW']], [[['...BW', '...BW', '...BW', 'W..BW'], []], ['???BW', '???BW', '???BW', 'W??BW']], [[['..BW.', '..BW.', '..BWB', '..BW.', '..BW.', '..BW.', '..BW.'], [[2, 2], [3, 3]]], ['??BW?', '??BW?', '???WB', '??B??', '??BW?', '??BW?', '??BW?']], [[['.BW..', '.BW.B', '.BWB.', '.BW..', '.BW.B', '.BW..', 'WBW..'], [[4, 1]]], ['?BW??', '?BW?B', '?BWB?', '?BW??', '??W?B', '?BW??', 'WBW??']], [[['..BW', 'W.BW', '..BW', '..BW', '..BW', 'W.BW'], [[0, 2], [5, 3]]], ['???W', 'W?BW', '??BW', '??BW', '??BW', 'W?B?']], [[['...BW.', '...BW.', '...BW.', '...BW.', '...BW.', '...BW.'], [[2, 4]]], ['bbbBW?', 'bbbBW?', 'bbbB??', 'bbbBW?', 'bbbBW?', 'bbbBW?']]], [[[['.BW..', 'WBW..', 'WBWB.', '.BW..', '.BW..'], []], ['?BW??', 'WBW??', 'WBWB?', '?BW??', '?BW??']], [[['...BW', '...BW', 'W..BW', 'W.WBW', '...BW', '...BW'], []], ['???BW', '???BW', 'W??BW', 'W?WBW', '???BW', '???BW']], [[['....', '....', '....', '....'], []], ['????', '????', '????', '????']], [[['...', '...', '...'], []], ['???', '???', '???']], [[['.B.', 'B.B', '.B.'], [[1, 2], [2, 1]]], ['bBb', 'Bbb', 'bbb']], [[['B..W', 'B..W', 'B..W', 'B..W'], [[2, 3]]], ['B??W', 'B??W', 'B???', 'B??W']], [[['.BW.', '.BW.', '.BW.', '.BW.'], [[0, 2]]], ['bB??', 'bBW?', 'bBW?', 'bBW?']], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], [[0, 2]]], ['bbbbb', 'bbBbb', 'BBBBB', 'WWWWW', 'wwWww']]], [[[['.BW..', '.BW.B', '.BWB.', '.BW..', '.BW.B', '.BW..', 'WBW..'], [[4, 1]]], ['?BW??', '?BW?B', '?BWB?', '?BW??', '??W?B', '?BW??', 'WBW??']], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], []], ['BbB?W', 'bB?Ww', 'BbBWw', 'BBWwW', '??Www']], [[['W....', '.....', '.....', '.....', '....B'], [[4, 4]]], ['Wwwww', 'wwwww', 'wwwww', 'wwwww', 'wwwww']], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], [[3, 1], [3, 0]]], ['wW?B?', 'WwWB?', '?WB??', '?????', 'B????']], [[['BBBB', 'B..B', 'B..B', 'BBBB'], [[0, 2]]], ['BBbB', 'BbbB', 'BbbB', 'BBBB']], [[['WWW', 'W.W', 'WWW'], []], ['WWW', 'WwW', 'WWW']], [[['B.W', '...', 'W.B'], [[2, 2], [0, 0]]], ['wwW', 'www', 'Www']], [[['.B...', 'B....', '.....', '....W', '...W.'], [[1, 0]]], ['?B???', '?????', '?????', '????W', '???Ww']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("ownership map 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
ownership map case 0['bbbBW??', 'bbbBW??', 'bbbBW??', 'bbbBWB?', 'bbbB???']['bbbBW??', 'bbbBW??', 'bbbBW??', 'bbbBWB?', 'bbbB???']Passed
ownership map case 1['??Ww', '?BWw', '?BWw', '?BWw', '?BWw', 'WBWw']['??Ww', '?BWw', '?BWw', '?BWw', '?BWw', 'WBWw']Passed
ownership map case 2['bB?B?', 'bBW??', 'bB???', 'bBWB?']['bB?B?', 'bBW??', 'bB???', 'bBWB?']Passed
ownership map case 3['WB????', '?BW???', '?BW??B', '?BW???', '?BW???']['WB????', '?BW???', '?BW??B', '?BW???', '?BW???']Passed
ownership map case 4['?BW?B??', 'WBW????', '?B?????', '?BW????', '?BW????']['?BW?B??', 'WBW????', '?B?????', '?BW????', '?BW????']Passed
ownership map case 5['????BW', '????BW', '??????', '????BW', '????BW', '????BW']['????BW', '????BW', '??????', '????BW', '????BW', '????BW']Passed
ownership map case 6['??BW', '??BW', '??BW', '???W', '??BW', '??BW', '??BW']['??BW', '??BW', '??BW', '???W', '??BW', '??BW', '??BW']Passed
ownership map case 7['W?BWw', '??BWw', '?WBWw', '?WBWw', '??BWw', '??BWw', '??BWw']['W?BWw', '??BWw', '?WBWw', '?WBWw', '??BWw', '??BWw', '??BWw']Passed

SHA-256 / d8324dad261c78577042b9d1261751a76b352756b60d6a3d09401956d1f7b6c8

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

Case digest / 56e8bef0fe2e427cd6506cc669dc3f259e340a32189c6e3099f4e29f87201254