broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    board, color, r, c = x
    g = [list(row) for row in board]
    n = len(g)
    m = len(g[0])
    if g[r][c] != '.':
        return ['illegal', 'occupied']
    opp = 'W' if color == 'B' else 'B'
    g[r][c] = color
    def group(i, j):
        col = g[i][j]
        stones = {(i, j)}
        libs = set()
        stack = [(i, j)]
        while stack:
            a, b = stack.pop()
            for p, q in ((a, b + 1), (a + 1, b), (a, b - 1), (a - 1, b)):
                if 0 <= p < n and 0 <= q < m:
                    if g[p][q] == '.':
                        libs.add((p, q))
                    elif g[p][q] == col and (p, q) not in stones:
                        stones.add((p, q))
                        stack.append((p, q))
        return stones, libs
    captured = 0
    for p, q in ((r + 1, c), (r - 1, c), (r, c + 1), (r, c - 1)):
        if 0 <= p < n and 0 <= q < m and g[p][q] == opp:
            stones, libs = group(p, q)
            if not libs:
                for s, t in stones:
                    g[s][t] = '.'
                captured += len(stones)
                break
    stones, libs = group(r, c)
    if not libs:
        return ['illegal', 'suicide']
    return [[''.join(row) for row in g], captured]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['...', '...', '...'], 'W', 2, 0], [['...', '...', 'W..'], 0]], [[['.B.', 'B.B', '.B.'], 'W', 2, 2], ['illegal', 'suicide']], [[['.B.', 'B.B', '.B.'], 'W', 2, 0], ['illegal', 'suicide']], [[['.B.', 'B.B', '.B.'], 'B', 0, 0], [['BB.', 'B.B', '.B.'], 0]], [[['.B.', 'B.B', '.B.'], 'B', 0, 2], [['.BB', 'B.B', '.B.'], 0]], [[['.B.', 'B.B', '.B.'], 'B', 0, 1], ['illegal', 'occupied']], [[['WB.BB', 'B.B.W', 'B.WBB', 'BWBW.'], 'B', 2, 1], [['WB.BB', 'B.B.W', 'BB.BB', 'B.BW.'], 2]], [[['WB.BB', 'B.B.W', 'B.WBB', 'BWBW.'], 'B', 2, 1], [['WB.BB', 'B.B.W', 'BB.BB', 'B.BW.'], 2]]], [[[['B..W', 'B..W', 'B..W', 'B..W'], 'B', 1, 1], [['B..W', 'BB.W', 'B..W', 'B..W'], 0]], [[['B..W', 'B..W', 'B..W', 'B..W'], 'W', 0, 2], [['B.WW', 'B..W', 'B..W', 'B..W'], 0]], [[['B..W', 'B..W', 'B..W', 'B..W'], 'B', 0, 1], [['BB.W', 'B..W', 'B..W', 'B..W'], 0]], [[['B..W', 'B..W', 'B..W', 'B..W'], 'B', 2, 0], ['illegal', 'occupied']], [[['.BW.', '.BW.', '.BW.', '.BW.'], 'W', 2, 3], [['.BW.', '.BW.', '.BWW', '.BW.'], 0]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 'W', 0, 0], [['WBW.', '.BW.', '.BW.', '.BW.'], 0]], [[['WB.BB', 'B.B.W', 'B.WBB', 'BWBW.'], 'B', 2, 1], [['WB.BB', 'B.B.W', 'BB.BB', 'B.BW.'], 2]], [[['BWB', 'W.W', 'BWB'], 'B', 1, 1], [['B.B', '.B.', 'B.B'], 4]]], [[[['.BW.', '.BW.', '.BW.', '.BW.'], 'B', 2, 0], [['.BW.', '.BW.', 'BBW.', '.BW.'], 0]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 'B', 0, 2], ['illegal', 'occupied']], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 0, 0], [['B.B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 1, 1], [['..B..', '.BB..', 'BBBBB', 'WWWWW', '..W..'], 0]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 4, 0], [['..B..', '..B..', 'BBBBB', 'WWWWW', 'B.W..'], 0]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 0, 1], [['.BB..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0]], [[['WB.BB', 'B.B.W', 'B.WBB', 'BWBW.'], 'B', 2, 1], [['WB.BB', 'B.B.W', 'BB.BB', 'B.BW.'], 2]], [[['.WB.', 'B.WB', 'W.BW'], 'W', 0, 3], [['.W.W', 'B.W.', 'W.BW'], 2]]], [[[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'W', 2, 1], ['illegal', 'suicide']], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'W', 0, 1], ['illegal', 'suicide']], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'B', 4, 3], [['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..WB.'], 0]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'B', 2, 4], [['B.B.W', '.B.W.', 'B.BWB', 'BBW.W', '..W..'], 0]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'B', 3, 2], ['illegal', 'occupied']], [[['W....', '.....', '.....', '.....', '....B'], 'W', 4, 1], [['W....', '.....', '.....', '.....', '.W..B'], 0]], [[['WB.BB', 'B.B.W', 'B.WBB', 'BWBW.'], 'B', 2, 1], [['WB.BB', 'B.B.W', 'BB.BB', 'B.BW.'], 2]], [[['WB.BB', 'B.B.W', 'B.WBB', 'BWBW.'], 'B', 2, 1], [['WB.BB', 'B.B.W', 'BB.BB', 'B.BW.'], 2]]], [[[['W....', '.....', '.....', '.....', '....B'], 'W', 3, 0], [['W....', '.....', '.....', 'W....', '....B'], 0]], [[['W....', '.....', '.....', '.....', '....B'], 'W', 4, 0], [['W....', '.....', '.....', '.....', 'W...B'], 0]], [[['W....', '.....', '.....', '.....', '....B'], 'B', 4, 4], ['illegal', 'occupied']], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 'W', 0, 2], [['.WWB.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 'W', 0, 0], [['WW.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 'B', 2, 4], [['.W.B.', 'W.WB.', '.WB.B', 'WB...', 'B....'], 0]], [[['WB.BB', 'B.B.W', 'B.WBB', 'BWBW.'], 'B', 2, 1], [['WB.BB', 'B.B.W', 'BB.BB', 'B.BW.'], 2]], [[['BWB', 'W.W', 'BWB'], 'B', 1, 1], [['B.B', '.B.', 'B.B'], 4]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("move result 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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    board, color, r, c = x
    g = [list(row) for row in board]
    n = len(g)
    m = len(g[0])
    if g[r][c] != '.':
        return ['illegal', 'occupied']
    opp = 'W' if color == 'B' else 'B'
    g[r][c] = color
    def group(i, j):
        col = g[i][j]
        stones = {(i, j)}
        libs = set()
        stack = [(i, j)]
        while stack:
            a, b = stack.pop()
            for p, q in ((a, b + 1), (a + 1, b), (a, b - 1), (a - 1, b)):
                if 0 <= p < n and 0 <= q < m:
                    if g[p][q] == '.':
                        libs.add((p, q))
                    elif g[p][q] == col and (p, q) not in stones:
                        stones.add((p, q))
                        stack.append((p, q))
        return stones, libs
    captured = 0
    for p, q in ((r + 1, c), (r - 1, c), (r, c + 1), (r, c - 1)):
        if 0 <= p < n and 0 <= q < m and g[p][q] == opp:
            stones, libs = group(p, q)
            if not libs:
                for s, t in stones:
                    g[s][t] = '.'
                captured = len(stones)
    stones, libs = group(r, c)
    if not libs:
        return ['illegal', 'suicide']
    return [[''.join(row) for row in g], captured]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['...', '...', '...'], 'W', 2, 0], [['...', '...', 'W..'], 0]], [[['.B.', 'B.B', '.B.'], 'W', 2, 2], ['illegal', 'suicide']], [[['.B.', 'B.B', '.B.'], 'W', 2, 0], ['illegal', 'suicide']], [[['.B.', 'B.B', '.B.'], 'B', 0, 0], [['BB.', 'B.B', '.B.'], 0]], [[['.B.', 'B.B', '.B.'], 'B', 0, 2], [['.BB', 'B.B', '.B.'], 0]], [[['.B.', 'B.B', '.B.'], 'B', 0, 1], ['illegal', 'occupied']], [[['WB.BB', 'B.B.W', 'B.WBB', 'BWBW.'], 'B', 2, 1], [['WB.BB', 'B.B.W', 'BB.BB', 'B.BW.'], 2]], [[['WB.BB', 'B.B.W', 'B.WBB', 'BWBW.'], 'B', 2, 1], [['WB.BB', 'B.B.W', 'BB.BB', 'B.BW.'], 2]]], [[[['B..W', 'B..W', 'B..W', 'B..W'], 'B', 1, 1], [['B..W', 'BB.W', 'B..W', 'B..W'], 0]], [[['B..W', 'B..W', 'B..W', 'B..W'], 'W', 0, 2], [['B.WW', 'B..W', 'B..W', 'B..W'], 0]], [[['B..W', 'B..W', 'B..W', 'B..W'], 'B', 0, 1], [['BB.W', 'B..W', 'B..W', 'B..W'], 0]], [[['B..W', 'B..W', 'B..W', 'B..W'], 'B', 2, 0], ['illegal', 'occupied']], [[['.BW.', '.BW.', '.BW.', '.BW.'], 'W', 2, 3], [['.BW.', '.BW.', '.BWW', '.BW.'], 0]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 'W', 0, 0], [['WBW.', '.BW.', '.BW.', '.BW.'], 0]], [[['WB.BB', 'B.B.W', 'B.WBB', 'BWBW.'], 'B', 2, 1], [['WB.BB', 'B.B.W', 'BB.BB', 'B.BW.'], 2]], [[['BWB', 'W.W', 'BWB'], 'B', 1, 1], [['B.B', '.B.', 'B.B'], 4]]], [[[['.BW.', '.BW.', '.BW.', '.BW.'], 'B', 2, 0], [['.BW.', '.BW.', 'BBW.', '.BW.'], 0]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 'B', 0, 2], ['illegal', 'occupied']], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 0, 0], [['B.B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 1, 1], [['..B..', '.BB..', 'BBBBB', 'WWWWW', '..W..'], 0]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 4, 0], [['..B..', '..B..', 'BBBBB', 'WWWWW', 'B.W..'], 0]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 0, 1], [['.BB..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0]], [[['WB.BB', 'B.B.W', 'B.WBB', 'BWBW.'], 'B', 2, 1], [['WB.BB', 'B.B.W', 'BB.BB', 'B.BW.'], 2]], [[['.WB.', 'B.WB', 'W.BW'], 'W', 0, 3], [['.W.W', 'B.W.', 'W.BW'], 2]]], [[[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'W', 2, 1], ['illegal', 'suicide']], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'W', 0, 1], ['illegal', 'suicide']], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'B', 4, 3], [['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..WB.'], 0]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'B', 2, 4], [['B.B.W', '.B.W.', 'B.BWB', 'BBW.W', '..W..'], 0]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'B', 3, 2], ['illegal', 'occupied']], [[['W....', '.....', '.....', '.....', '....B'], 'W', 4, 1], [['W....', '.....', '.....', '.....', '.W..B'], 0]], [[['WB.BB', 'B.B.W', 'B.WBB', 'BWBW.'], 'B', 2, 1], [['WB.BB', 'B.B.W', 'BB.BB', 'B.BW.'], 2]], [[['WB.BB', 'B.B.W', 'B.WBB', 'BWBW.'], 'B', 2, 1], [['WB.BB', 'B.B.W', 'BB.BB', 'B.BW.'], 2]]], [[[['W....', '.....', '.....', '.....', '....B'], 'W', 3, 0], [['W....', '.....', '.....', 'W....', '....B'], 0]], [[['W....', '.....', '.....', '.....', '....B'], 'W', 4, 0], [['W....', '.....', '.....', '.....', 'W...B'], 0]], [[['W....', '.....', '.....', '.....', '....B'], 'B', 4, 4], ['illegal', 'occupied']], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 'W', 0, 2], [['.WWB.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 'W', 0, 0], [['WW.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 'B', 2, 4], [['.W.B.', 'W.WB.', '.WB.B', 'WB...', 'B....'], 0]], [[['WB.BB', 'B.B.W', 'B.WBB', 'BWBW.'], 'B', 2, 1], [['WB.BB', 'B.B.W', 'BB.BB', 'B.BW.'], 2]], [[['BWB', 'W.W', 'BWB'], 'B', 1, 1], [['B.B', '.B.', 'B.B'], 4]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("move result 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)

prompt:
A move that removes the last liberty of two opponent chains leaves one of them on the board.

Input [board, colour, row, col]. Occupied point -> ["illegal", "occupied"]. Otherwise place the stone, remove every adjacent opponent chain left without liberties, then reject the move as ["illegal", "suicide"] only if the placed chain still has no liberty. Return [new_board, captured_stone_count].

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    board, color, r, c = x
    g = [list(row) for row in board]
    n = len(g)
    m = len(g[0])
    if g[r][c] != '.':
        return ['illegal', 'occupied']
    opp = 'W' if color == 'B' else 'B'
    g[r][c] = color
    def group(i, j):
        col = g[i][j]
        stones = {(i, j)}
        libs = set()
        stack = [(i, j)]
        while stack:
            a, b = stack.pop()
            for p, q in ((a, b + 1), (a + 1, b), (a, b - 1), (a - 1, b)):
                if 0 <= p < n and 0 <= q < m:
                    if g[p][q] != col:
                        libs.add((p, q))
                    elif g[p][q] == col and (p, q) not in stones:
                        stones.add((p, q))
                        stack.append((p, q))
        return stones, libs
    captured = 0
    for p, q in ((r + 1, c), (r - 1, c), (r, c + 1), (r, c - 1)):
        if 0 <= p < n and 0 <= q < m and g[p][q] == opp:
            stones, libs = group(p, q)
            if not libs:
                for s, t in stones:
                    g[s][t] = '.'
                captured += len(stones)
    stones, libs = group(r, c)
    if not libs:
        return ['illegal', 'suicide']
    return [[''.join(row) for row in g], captured]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['...', '...', '...'], 'W', 2, 0], [['...', '...', 'W..'], 0]], [[['.B.', 'B.B', '.B.'], 'W', 2, 2], ['illegal', 'suicide']], [[['.B.', 'B.B', '.B.'], 'W', 2, 0], ['illegal', 'suicide']], [[['.B.', 'B.B', '.B.'], 'B', 0, 0], [['BB.', 'B.B', '.B.'], 0]], [[['.B.', 'B.B', '.B.'], 'B', 0, 2], [['.BB', 'B.B', '.B.'], 0]], [[['.B.', 'B.B', '.B.'], 'B', 0, 1], ['illegal', 'occupied']], [[['B..W', 'B..W', 'B..W', 'B..W'], 'W', 2, 2], [['B..W', 'B..W', 'B.WW', 'B..W'], 0]], [[['WBW.', '..W.', 'WB.W', '..BW'], 'B', 1, 0], [['.BW.', 'B.W.', 'WB.W', '..BW'], 1]]], [[[['B..W', 'B..W', 'B..W', 'B..W'], 'B', 1, 1], [['B..W', 'BB.W', 'B..W', 'B..W'], 0]], [[['B..W', 'B..W', 'B..W', 'B..W'], 'W', 0, 2], [['B.WW', 'B..W', 'B..W', 'B..W'], 0]], [[['B..W', 'B..W', 'B..W', 'B..W'], 'B', 0, 1], [['BB.W', 'B..W', 'B..W', 'B..W'], 0]], [[['B..W', 'B..W', 'B..W', 'B..W'], 'B', 2, 0], ['illegal', 'occupied']], [[['.BW.', '.BW.', '.BW.', '.BW.'], 'W', 2, 3], [['.BW.', '.BW.', '.BWW', '.BW.'], 0]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 'W', 0, 0], [['WBW.', '.BW.', '.BW.', '.BW.'], 0]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'W', 0, 1], ['illegal', 'suicide']], [[['.WB.', 'B.WB', 'W.BW'], 'B', 1, 1], [['.WB.', 'BB.B', 'W.BW'], 1]]], [[[['.BW.', '.BW.', '.BW.', '.BW.'], 'B', 2, 0], [['.BW.', '.BW.', 'BBW.', '.BW.'], 0]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 'B', 0, 2], ['illegal', 'occupied']], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 0, 0], [['B.B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 1, 1], [['..B..', '.BB..', 'BBBBB', 'WWWWW', '..W..'], 0]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 4, 0], [['..B..', '..B..', 'BBBBB', 'WWWWW', 'B.W..'], 0]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 0, 1], [['.BB..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0]], [[['...', '.BW', '..B', '.BW', 'BB.'], 'W', 4, 2], ['illegal', 'suicide']], [[['B.BW', 'WWBB', 'BB.W', '.BBB'], 'W', 0, 1], [['.WBW', 'WWBB', 'BB.W', '.BBB'], 1]]], [[[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'W', 2, 1], ['illegal', 'suicide']], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'W', 0, 1], ['illegal', 'suicide']], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'B', 4, 3], [['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..WB.'], 0]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'B', 2, 4], [['B.B.W', '.B.W.', 'B.BWB', 'BBW.W', '..W..'], 0]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'B', 3, 2], ['illegal', 'occupied']], [[['W....', '.....', '.....', '.....', '....B'], 'W', 4, 1], [['W....', '.....', '.....', '.....', '.W..B'], 0]], [[['WB.BB', 'B.B.W', 'B.WBB', 'BWBW.'], 'W', 1, 3], ['illegal', 'suicide']], [[['.BW', 'BW.', 'W..'], 'B', 2, 1], [['.BW', 'BW.', '.B.'], 1]]], [[[['W....', '.....', '.....', '.....', '....B'], 'W', 3, 0], [['W....', '.....', '.....', 'W....', '....B'], 0]], [[['W....', '.....', '.....', '.....', '....B'], 'W', 4, 0], [['W....', '.....', '.....', '.....', 'W...B'], 0]], [[['W....', '.....', '.....', '.....', '....B'], 'B', 4, 4], ['illegal', 'occupied']], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 'W', 0, 2], [['.WWB.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 'W', 0, 0], [['WW.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 'B', 2, 4], [['.W.B.', 'W.WB.', '.WB.B', 'WB...', 'B....'], 0]], [[['.B...', 'WWWBW', 'WW..B', '.W.WW', '..B..'], 'W', 2, 3], [['.B...', 'WWWBW', 'WW.W.', '.W.WW', '..B..'], 1]], [[['.W.', 'WBW', 'BWB'], 'B', 0, 2], [['.WB', 'WB.', 'BWB'], 1]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("move result 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)

meaning: Fixture-count band, not measured model difficulty

deps: stdlib

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    board, color, r, c = x
    g = [list(row) for row in board]
    n = len(g)
    m = len(g[0])
    if g[r][c] != '.':
        return ['illegal', 'occupied']
    opp = 'W' if color == 'B' else 'B'
    g[r][c] = color
    def group(i, j):
        col = g[i][j]
        stones = {(i, j)}
        libs = set()
        stack = [(i, j)]
        while stack:
            a, b = stack.pop()
            for p, q in ((a, b + 1), (a + 1, b), (a, b - 1), (a - 1, b)):
                if 0 <= p < n and 0 <= q < m:
                    if g[p][q] == '.' or (p, q) == (r, c):
                        libs.add((p, q))
                    elif g[p][q] == col and (p, q) not in stones:
                        stones.add((p, q))
                        stack.append((p, q))
        return stones, libs
    captured = 0
    for p, q in ((r + 1, c), (r - 1, c), (r, c + 1), (r, c - 1)):
        if 0 <= p < n and 0 <= q < m and g[p][q] == opp:
            stones, libs = group(p, q)
            if not libs:
                for s, t in stones:
                    g[s][t] = '.'
                captured += len(stones)
    stones, libs = group(r, c)
    if not libs:
        return ['illegal', 'suicide']
    return [[''.join(row) for row in g], captured]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[['...', '...', '...'], 'W', 2, 0], [['...', '...', 'W..'], 0]], [[['.B.', 'B.B', '.B.'], 'W', 2, 2], ['illegal', 'suicide']], [[['.B.', 'B.B', '.B.'], 'W', 2, 0], ['illegal', 'suicide']], [[['.B.', 'B.B', '.B.'], 'B', 0, 0], [['BB.', 'B.B', '.B.'], 0]], [[['.B.', 'B.B', '.B.'], 'B', 0, 2], [['.BB', 'B.B', '.B.'], 0]], [[['.B.', 'B.B', '.B.'], 'B', 0, 1], ['illegal', 'occupied']], [[['B..W', 'B..W', 'B..W', 'B..W'], 'W', 2, 2], [['B..W', 'B..W', 'B.WW', 'B..W'], 0]], [[['WBW.', '..W.', 'WB.W', '..BW'], 'B', 1, 0], [['.BW.', 'B.W.', 'WB.W', '..BW'], 1]]], [[[['B..W', 'B..W', 'B..W', 'B..W'], 'B', 1, 1], [['B..W', 'BB.W', 'B..W', 'B..W'], 0]], [[['B..W', 'B..W', 'B..W', 'B..W'], 'W', 0, 2], [['B.WW', 'B..W', 'B..W', 'B..W'], 0]], [[['B..W', 'B..W', 'B..W', 'B..W'], 'B', 0, 1], [['BB.W', 'B..W', 'B..W', 'B..W'], 0]], [[['B..W', 'B..W', 'B..W', 'B..W'], 'B', 2, 0], ['illegal', 'occupied']], [[['.BW.', '.BW.', '.BW.', '.BW.'], 'W', 2, 3], [['.BW.', '.BW.', '.BWW', '.BW.'], 0]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 'W', 0, 0], [['WBW.', '.BW.', '.BW.', '.BW.'], 0]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'W', 0, 1], ['illegal', 'suicide']], [[['.WB.', 'B.WB', 'W.BW'], 'B', 1, 1], [['.WB.', 'BB.B', 'W.BW'], 1]]], [[[['.BW.', '.BW.', '.BW.', '.BW.'], 'B', 2, 0], [['.BW.', '.BW.', 'BBW.', '.BW.'], 0]], [[['.BW.', '.BW.', '.BW.', '.BW.'], 'B', 0, 2], ['illegal', 'occupied']], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 0, 0], [['B.B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 1, 1], [['..B..', '.BB..', 'BBBBB', 'WWWWW', '..W..'], 0]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 4, 0], [['..B..', '..B..', 'BBBBB', 'WWWWW', 'B.W..'], 0]], [[['..B..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 'B', 0, 1], [['.BB..', '..B..', 'BBBBB', 'WWWWW', '..W..'], 0]], [[['...', '.BW', '..B', '.BW', 'BB.'], 'W', 4, 2], ['illegal', 'suicide']], [[['B.BW', 'WWBB', 'BB.W', '.BBB'], 'W', 0, 1], [['.WBW', 'WWBB', 'BB.W', '.BBB'], 1]]], [[[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'W', 2, 1], ['illegal', 'suicide']], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'W', 0, 1], ['illegal', 'suicide']], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'B', 4, 3], [['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..WB.'], 0]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'B', 2, 4], [['B.B.W', '.B.W.', 'B.BWB', 'BBW.W', '..W..'], 0]], [[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 'B', 3, 2], ['illegal', 'occupied']], [[['W....', '.....', '.....', '.....', '....B'], 'W', 4, 1], [['W....', '.....', '.....', '.....', '.W..B'], 0]], [[['WB.BB', 'B.B.W', 'B.WBB', 'BWBW.'], 'W', 1, 3], ['illegal', 'suicide']], [[['.BW', 'BW.', 'W..'], 'B', 2, 1], [['.BW', 'BW.', '.B.'], 1]]], [[[['W....', '.....', '.....', '.....', '....B'], 'W', 3, 0], [['W....', '.....', '.....', 'W....', '....B'], 0]], [[['W....', '.....', '.....', '.....', '....B'], 'W', 4, 0], [['W....', '.....', '.....', '.....', 'W...B'], 0]], [[['W....', '.....', '.....', '.....', '....B'], 'B', 4, 4], ['illegal', 'occupied']], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 'W', 0, 2], [['.WWB.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 'W', 0, 0], [['WW.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 0]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 'B', 2, 4], [['.W.B.', 'W.WB.', '.WB.B', 'WB...', 'B....'], 0]], [[['.B...', 'WWWBW', 'WW..B', '.W.WW', '..B..'], 'W', 2, 3], [['.B...', 'WWWBW', 'WW.W.', '.W.WW', '..B..'], 1]], [[['.W.', 'WBW', 'BWB'], 'B', 0, 2], [['.WB', 'WB.', 'BWB'], 1]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("move result 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)

prompt:
Surrounded chains are never captured and some suicides are accepted.

Input [board, colour, row, col]. Occupied point -> ["illegal", "occupied"]. Otherwise place the stone, remove every adjacent opponent chain left without liberties, then reject the move as ["illegal", "suicide"] only if the placed chain still has no liberty. Return [new_board, captured_stone_count].

split: open-access


prompt:
A single-stone capture by a connected stone forbids an immediate recapture that is actually legal.

Input [board_after_move, row, col, captured_points]. A ko ban point exists only when exactly one stone was captured, the played stone has no friendly orthogonal neighbour, and it has exactly one liberty. Return the captured point or None.

split: open-access


prompt:
Snapback-style single captures with open points around are flagged as ko.

Input [board_after_move, row, col, captured_points]. A ko ban point exists only when exactly one stone was captured, the played stone has no friendly orthogonal neighbour, and it has exactly one liberty. Return the captured point or None.

split: open-access


prompt:
Capturing two stones marks the first captured point as a ko point.

Input [board_after_move, row, col, captured_points]. A ko ban point exists only when exactly one stone was captured, the played stone has no friendly orthogonal neighbour, and it has exactly one liberty. Return the captured point or None.

split: open-access


prompt:
Triple ko and longer cycles are accepted as legal.

Input [history, candidate_board, player_to_move_after, mode]; history is a list of [board, player_to_move]. Positional mode forbids any earlier board equal to the candidate; situational mode additionally requires the same player to move. Return the earliest matching history index or "legal".

split: open-access


prompt:
Repeating a position with a different player to move is rejected in situational mode.

Input [history, candidate_board, player_to_move_after, mode]; history is a list of [board, player_to_move]. Positional mode forbids any earlier board equal to the candidate; situational mode additionally requires the same player to move. Return the earliest matching history index or "legal".

split: open-access


prompt:
The reported conflicting move number points at a later repetition.

Input [history, candidate_board, player_to_move_after, mode]; history is a list of [board, player_to_move]. Positional mode forbids any earlier board equal to the candidate; situational mode additionally requires the same player to move. Return the earliest matching history index or "legal".

split: open-access


prompt:
Every move is reported as repeating itself.

Input [history, candidate_board, player_to_move_after, mode]; history is a list of [board, player_to_move]. Positional mode forbids any earlier board equal to the candidate; situational mode additionally requires the same player to move. Return the earliest matching history index or "legal".

split: open-access


prompt:
Handicap on 13x13 uses 3-3 points instead of 4-4 points.

Input [size, count]. Star line e = 2 (0-based) below 13x13 else 3; f = size-1-e; mid = size//2. Counts outside 2..9 give []. Even boards allow at most 4. Order: [e,f],[f,e],[f,f],[e,e]; counts 6-9 add [mid,e],[mid,f]; 8-9 add [e,mid],[f,mid]; odd counts from 5 add the centre last.

split: open-access


prompt:
Handicap 1 (no komi, black first) puts a black stone on the board.

Input [size, count]. Star line e = 2 (0-based) below 13x13 else 3; f = size-1-e; mid = size//2. Counts outside 2..9 give []. Even boards allow at most 4. Order: [e,f],[f,e],[f,f],[e,e]; counts 6-9 add [mid,e],[mid,f]; 8-9 add [e,mid],[f,mid]; odd counts from 5 add the centre last.

split: open-access


prompt:
The fifth and sixth stones sit on the top/bottom edges instead of left/right.

Input [size, count]. Star line e = 2 (0-based) below 13x13 else 3; f = size-1-e; mid = size//2. Counts outside 2..9 give []. Even boards allow at most 4. Order: [e,f],[f,e],[f,f],[e,e]; counts 6-9 add [mid,e],[mid,f]; 8-9 add [e,mid],[f,mid]; odd counts from 5 add the centre last.

split: open-access


prompt:
Six- and eight-stone handicaps receive tengen as an extra stone.

Input [size, count]. Star line e = 2 (0-based) below 13x13 else 3; f = size-1-e; mid = size//2. Counts outside 2..9 give []. Even boards allow at most 4. Order: [e,f],[f,e],[f,f],[e,e]; counts 6-9 add [mid,e],[mid,f]; 8-9 add [e,mid],[f,mid]; odd counts from 5 add the centre last.

split: open-access


prompt:
A 10x10 board with 5+ handicap gets off-centre "tengen" stones.

Input [size, count]. Star line e = 2 (0-based) below 13x13 else 3; f = size-1-e; mid = size//2. Counts outside 2..9 give []. Even boards allow at most 4. Order: [e,f],[f,e],[f,f],[e,e]; counts 6-9 add [mid,e],[mid,f]; 8-9 add [e,mid],[f,mid]; odd counts from 5 add the centre last.

split: open-access


prompt:
The first two stones go to upper-left and lower-right.

Input [size, count]. Star line e = 2 (0-based) below 13x13 else 3; f = size-1-e; mid = size//2. Counts outside 2..9 give []. Even boards allow at most 4. Order: [e,f],[f,e],[f,f],[e,e]; counts 6-9 add [mid,e],[mid,f]; 8-9 add [e,mid],[f,mid]; odd counts from 5 add the centre last.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    size, text = x
    t = text.strip().upper()
    if t == 'PASS':
        return 'pass'
    if len(t) < 2 or not t[1:].isdigit():
        return 'invalid'
    letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    if t[0] not in letters:
        return 'invalid'
    col = letters.index(t[0])
    num = int(t[1:])
    if col >= size or num < 1 or num > size:
        return 'invalid'
    return [size - num, col]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[9, 'I5'], 'invalid'], [[9, 'pass'], 'pass'], [[9, 'PASS'], 'pass'], [[9, ' Pass'], 'pass'], [[9, 'Z1'], 'invalid'], [[9, 'A0'], 'invalid'], [[9, 'A9'], [0, 0]], [[19, 'I5'], 'invalid']], [[[9, 'A10'], 'invalid'], [[9, 'K1'], 'invalid'], [[9, 'O3'], 'invalid'], [[9, 'Q16'], 'invalid'], [[9, 'X'], 'invalid'], [[9, ''], 'invalid'], [[13, 'I5'], 'invalid'], [[25, 'I5'], 'invalid']], [[[9, 'I5'], 'invalid'], [[9, 'Y25'], 'invalid'], [[9, 'N13'], 'invalid'], [[9, 'M9'], 'invalid'], [[13, 'D4'], [9, 3]], [[13, 'd4'], [9, 3]], [[13, ' D4 '], [9, 3]], [[13, 'N13'], [0, 12]]], [[[13, 'A1'], [12, 0]], [[13, 'T19'], 'invalid'], [[13, 'J10'], [3, 8]], [[13, 'I5'], 'invalid'], [[13, 'H8'], [5, 7]], [[13, 'pass'], 'pass'], [[13, 'PASS'], 'pass'], [[19, 'J10'], [9, 8]]], [[[13, ' Pass'], 'pass'], [[13, 'Z1'], 'invalid'], [[13, 'A0'], 'invalid'], [[13, 'A13'], [0, 0]], [[13, 'A14'], 'invalid'], [[13, 'K1'], [12, 9]], [[19, 'I5'], 'invalid'], [[19, 'O3'], [16, 13]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("vertex 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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    size, text = x
    t = text.strip().upper()
    if t == 'PASS':
        return 'pass'
    if len(t) < 2 or not t[1:].isdigit():
        return 'invalid'
    letters = 'ABCDEFGHJKLMNOPQRSTUVWXYZ'
    if t[0] == 'I':
        t = 'J' + t[1:]
    if t[0] not in letters:
        return 'invalid'
    col = letters.index(t[0])
    num = int(t[1:])
    if col >= size or num < 1 or num > size:
        return 'invalid'
    return [size - num, col]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[9, 'I5'], 'invalid'], [[9, 'pass'], 'pass'], [[9, 'PASS'], 'pass'], [[9, ' Pass'], 'pass'], [[9, 'Z1'], 'invalid'], [[9, 'A0'], 'invalid'], [[9, 'A9'], [0, 0]], [[19, 'I5'], 'invalid']], [[[9, 'A10'], 'invalid'], [[9, 'K1'], 'invalid'], [[9, 'O3'], 'invalid'], [[9, 'Q16'], 'invalid'], [[9, 'X'], 'invalid'], [[9, ''], 'invalid'], [[13, 'I5'], 'invalid'], [[25, 'I5'], 'invalid']], [[[9, 'I5'], 'invalid'], [[9, 'Y25'], 'invalid'], [[9, 'N13'], 'invalid'], [[9, 'M9'], 'invalid'], [[13, 'D4'], [9, 3]], [[13, 'd4'], [9, 3]], [[13, ' D4 '], [9, 3]], [[13, 'N13'], [0, 12]]], [[[13, 'A1'], [12, 0]], [[13, 'T19'], 'invalid'], [[13, 'J10'], [3, 8]], [[13, 'I5'], 'invalid'], [[13, 'H8'], [5, 7]], [[13, 'pass'], 'pass'], [[13, 'PASS'], 'pass'], [[19, 'J10'], [9, 8]]], [[[13, ' Pass'], 'pass'], [[13, 'Z1'], 'invalid'], [[13, 'A0'], 'invalid'], [[13, 'A13'], [0, 0]], [[13, 'A14'], 'invalid'], [[13, 'K1'], [12, 9]], [[19, 'I5'], 'invalid'], [[19, 'O3'], [16, 13]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("vertex 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)

prompt:
J10 is parsed one column too far right and I5 is accepted.

Input [size, text]. Case-insensitive, surrounding blanks ignored; "pass" -> "pass". Column letters A..Z skipping I; row numbers count from 1 at the bottom. Return [row_from_top, col] or "invalid".

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    size, text = x
    t = text.strip().upper()
    if t == 'PASS':
        return 'pass'
    if len(t) < 2 or not t[1:].isdigit():
        return 'invalid'
    letters = 'ABCDEFGHJKLMNOPQRSTUVWXYZ'
    if t[0] not in letters:
        return 'invalid'
    col = letters.index(t[0])
    num = int(t[1:])
    if col >= size or num < 1 or num > size:
        return 'invalid'
    return [num - 1, col]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[9, 'D4'], [5, 3]], [[9, 'pass'], 'pass'], [[9, 'PASS'], 'pass'], [[9, ' Pass'], 'pass'], [[9, 'Z1'], 'invalid'], [[9, 'A0'], 'invalid'], [[9, 'A9'], [0, 0]], [[9, 'j9'], [0, 8]]], [[[9, 'A1'], [8, 0]], [[9, 'K1'], 'invalid'], [[9, 'O3'], 'invalid'], [[9, 'Q16'], 'invalid'], [[9, 'X'], 'invalid'], [[9, ''], 'invalid'], [[9, 'E'], 'invalid'], [[13, 'J10'], [3, 8]]], [[[9, 'j9'], [0, 8]], [[9, 'Y25'], 'invalid'], [[9, 'N13'], 'invalid'], [[9, 'M9'], 'invalid'], [[13, 'D4'], [9, 3]], [[13, 'd4'], [9, 3]], [[13, ' D4 '], [9, 3]], [[13, 'N13'], [0, 12]]], [[[13, ' D4 '], [9, 3]], [[13, 'T19'], 'invalid'], [[13, 'J10'], [3, 8]], [[13, 'I5'], 'invalid'], [[13, 'H8'], [5, 7]], [[13, 'pass'], 'pass'], [[13, 'PASS'], 'pass'], [[19, 'A1'], [18, 0]]], [[[13, 'H8'], [5, 7]], [[13, 'Z1'], 'invalid'], [[13, 'A0'], 'invalid'], [[13, 'A13'], [0, 0]], [[13, 'A14'], 'invalid'], [[13, 'K1'], [12, 9]], [[13, 'O3'], 'invalid'], [[19, 'K1'], [18, 9]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("vertex 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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    size, text = x
    t = text.strip().upper()
    if t == 'PASS':
        return 'pass'
    if len(t) < 2 or not t[1:].isdigit():
        return 'invalid'
    letters = 'ABCDEFGHJKLMNOPQRSTUVWXYZ'
    if t[0] not in letters:
        return 'invalid'
    col = letters.index(t[0])
    num = int(t[1:])
    if col >= size or num < 1 or num > size:
        return 'invalid'
    return [size - num - 1, col]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[9, 'D4'], [5, 3]], [[9, 'pass'], 'pass'], [[9, 'PASS'], 'pass'], [[9, ' Pass'], 'pass'], [[9, 'Z1'], 'invalid'], [[9, 'A0'], 'invalid'], [[9, 'A9'], [0, 0]], [[9, 'j9'], [0, 8]]], [[[9, 'A1'], [8, 0]], [[9, 'K1'], 'invalid'], [[9, 'O3'], 'invalid'], [[9, 'Q16'], 'invalid'], [[9, 'X'], 'invalid'], [[9, ''], 'invalid'], [[9, 'E'], 'invalid'], [[13, 'J10'], [3, 8]]], [[[9, 'j9'], [0, 8]], [[9, 'Y25'], 'invalid'], [[9, 'N13'], 'invalid'], [[9, 'M9'], 'invalid'], [[13, 'D4'], [9, 3]], [[13, 'd4'], [9, 3]], [[13, ' D4 '], [9, 3]], [[13, 'N13'], [0, 12]]], [[[13, ' D4 '], [9, 3]], [[13, 'T19'], 'invalid'], [[13, 'J10'], [3, 8]], [[13, 'I5'], 'invalid'], [[13, 'H8'], [5, 7]], [[13, 'pass'], 'pass'], [[13, 'PASS'], 'pass'], [[19, 'A1'], [18, 0]]], [[[13, 'H8'], [5, 7]], [[13, 'Z1'], 'invalid'], [[13, 'A0'], 'invalid'], [[13, 'A13'], [0, 0]], [[13, 'A14'], 'invalid'], [[13, 'K1'], [12, 9]], [[13, 'O3'], 'invalid'], [[19, 'K1'], [18, 9]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("vertex 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)

prompt:
D4 lands on the fourth row from the top instead of the bottom.

Input [size, text]. Case-insensitive, surrounding blanks ignored; "pass" -> "pass". Column letters A..Z skipping I; row numbers count from 1 at the bottom. Return [row_from_top, col] or "invalid".

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    size, text = x
    t = text.strip()
    if t == 'PASS':
        return 'pass'
    if len(t) < 2 or not t[1:].isdigit():
        return 'invalid'
    letters = 'ABCDEFGHJKLMNOPQRSTUVWXYZ'
    if t[0] not in letters:
        return 'invalid'
    col = letters.index(t[0])
    num = int(t[1:])
    if col >= size or num < 1 or num > size:
        return 'invalid'
    return [size - num, col]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[9, 'd4'], [5, 3]], [[9, 'pass'], 'pass'], [[9, 'PASS'], 'pass'], [[9, ' Pass'], 'pass'], [[9, 'Z1'], 'invalid'], [[9, 'A0'], 'invalid'], [[9, 'A9'], [0, 0]], [[25, ' D4 '], [21, 3]]], [[[9, 'A10'], 'invalid'], [[9, 'K1'], 'invalid'], [[9, 'O3'], 'invalid'], [[9, 'Q16'], 'invalid'], [[9, 'X'], 'invalid'], [[9, ''], 'invalid'], [[9, 'j9'], [0, 8]], [[13, ' Pass'], 'pass']], [[[9, ' D4 '], [5, 3]], [[9, 'Y25'], 'invalid'], [[9, 'N13'], 'invalid'], [[9, 'M9'], 'invalid'], [[13, 'D4'], [9, 3]], [[13, 'd4'], [9, 3]], [[13, ' D4 '], [9, 3]], [[13, ' Pass'], 'pass']], [[[13, 'A1'], [12, 0]], [[13, 'T19'], 'invalid'], [[13, 'J10'], [3, 8]], [[13, 'I5'], 'invalid'], [[13, 'H8'], [5, 7]], [[13, 'pass'], 'pass'], [[19, 'pass'], 'pass'], [[19, ' Pass'], 'pass']], [[[13, ' D4 '], [9, 3]], [[13, 'Z1'], 'invalid'], [[13, 'A0'], 'invalid'], [[13, 'A13'], [0, 0]], [[13, 'A14'], 'invalid'], [[13, 'K1'], [12, 9]], [[13, 'O3'], 'invalid'], [[25, 'd4'], [21, 3]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("vertex 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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    size, text = x
    t = text.upper()
    if t == 'PASS':
        return 'pass'
    if len(t) < 2 or not t[1:].isdigit():
        return 'invalid'
    letters = 'ABCDEFGHJKLMNOPQRSTUVWXYZ'
    if t[0] not in letters:
        return 'invalid'
    col = letters.index(t[0])
    num = int(t[1:])
    if col >= size or num < 1 or num > size:
        return 'invalid'
    return [size - num, col]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[9, 'd4'], [5, 3]], [[9, 'pass'], 'pass'], [[9, 'PASS'], 'pass'], [[9, ' Pass'], 'pass'], [[9, 'Z1'], 'invalid'], [[9, 'A0'], 'invalid'], [[9, 'A9'], [0, 0]], [[25, ' D4 '], [21, 3]]], [[[9, 'A10'], 'invalid'], [[9, 'K1'], 'invalid'], [[9, 'O3'], 'invalid'], [[9, 'Q16'], 'invalid'], [[9, 'X'], 'invalid'], [[9, ''], 'invalid'], [[9, 'j9'], [0, 8]], [[13, ' Pass'], 'pass']], [[[9, ' D4 '], [5, 3]], [[9, 'Y25'], 'invalid'], [[9, 'N13'], 'invalid'], [[9, 'M9'], 'invalid'], [[13, 'D4'], [9, 3]], [[13, 'd4'], [9, 3]], [[13, ' D4 '], [9, 3]], [[13, ' Pass'], 'pass']], [[[13, 'A1'], [12, 0]], [[13, 'T19'], 'invalid'], [[13, 'J10'], [3, 8]], [[13, 'I5'], 'invalid'], [[13, 'H8'], [5, 7]], [[13, 'pass'], 'pass'], [[19, 'pass'], 'pass'], [[19, ' Pass'], 'pass']], [[[13, ' D4 '], [9, 3]], [[13, 'Z1'], 'invalid'], [[13, 'A0'], 'invalid'], [[13, 'A13'], [0, 0]], [[13, 'A14'], 'invalid'], [[13, 'K1'], [12, 9]], [[13, 'O3'], 'invalid'], [[25, 'd4'], [21, 3]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("vertex 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)

prompt:
Engines sending d4 or pass get "invalid".

Input [size, text]. Case-insensitive, surrounding blanks ignored; "pass" -> "pass". Column letters A..Z skipping I; row numbers count from 1 at the bottom. Return [row_from_top, col] or "invalid".

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    size, text = x
    t = text.strip().upper()
    if t == 'PASS':
        return 'pass'
    if len(t) < 2 or not t[1:].isdigit():
        return 'invalid'
    letters = 'ABCDEFGHJKLMNOPQRSTUVWXYZ'
    if t[0] not in letters:
        return 'invalid'
    col = letters.index(t[0])
    num = int(t[1:])
    if col > size or num < 1 or num > size:
        return 'invalid'
    return [size - num, col]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[9, 'H8'], [1, 7]], [[9, 'pass'], 'pass'], [[9, 'PASS'], 'pass'], [[9, ' Pass'], 'pass'], [[9, 'Z1'], 'invalid'], [[9, 'A0'], 'invalid'], [[9, 'K1'], 'invalid'], [[19, 'A0'], 'invalid']], [[[9, 'A10'], 'invalid'], [[9, 'K1'], 'invalid'], [[9, 'O3'], 'invalid'], [[9, 'Q16'], 'invalid'], [[9, 'X'], 'invalid'], [[9, ''], 'invalid'], [[13, 'O3'], 'invalid'], [[25, 'A0'], 'invalid']], [[[9, 'A0'], 'invalid'], [[9, 'K1'], 'invalid'], [[9, 'N13'], 'invalid'], [[9, 'M9'], 'invalid'], [[13, 'D4'], [9, 3]], [[13, 'd4'], [9, 3]], [[13, ' D4 '], [9, 3]], [[13, 'A1'], [12, 0]]], [[[13, 'A1'], [12, 0]], [[13, 'T19'], 'invalid'], [[13, 'J10'], [3, 8]], [[13, 'I5'], 'invalid'], [[13, 'H8'], [5, 7]], [[13, 'pass'], 'pass'], [[13, 'A0'], 'invalid'], [[13, 'O3'], 'invalid']], [[[9, 'K1'], 'invalid'], [[13, 'Z1'], 'invalid'], [[13, 'A0'], 'invalid'], [[13, 'A13'], [0, 0]], [[13, 'A14'], 'invalid'], [[13, 'K1'], [12, 9]], [[13, 'O3'], 'invalid'], [[19, 'A0'], 'invalid']]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("vertex 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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    size, text = x
    t = text.strip().upper()
    if t == 'PASS':
        return 'pass'
    if len(t) < 2 or not t[1:].isdigit():
        return 'invalid'
    letters = 'ABCDEFGHJKLMNOPQRSTUVWXYZ'
    if t[0] not in letters:
        return 'invalid'
    col = letters.index(t[0])
    num = int(t[1:])
    if col >= size or num > size:
        return 'invalid'
    return [size - num, col]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[9, 'H8'], [1, 7]], [[9, 'pass'], 'pass'], [[9, 'PASS'], 'pass'], [[9, ' Pass'], 'pass'], [[9, 'Z1'], 'invalid'], [[9, 'A0'], 'invalid'], [[9, 'K1'], 'invalid'], [[19, 'A0'], 'invalid']], [[[9, 'A10'], 'invalid'], [[9, 'K1'], 'invalid'], [[9, 'O3'], 'invalid'], [[9, 'Q16'], 'invalid'], [[9, 'X'], 'invalid'], [[9, ''], 'invalid'], [[13, 'O3'], 'invalid'], [[25, 'A0'], 'invalid']], [[[9, 'A0'], 'invalid'], [[9, 'K1'], 'invalid'], [[9, 'N13'], 'invalid'], [[9, 'M9'], 'invalid'], [[13, 'D4'], [9, 3]], [[13, 'd4'], [9, 3]], [[13, ' D4 '], [9, 3]], [[13, 'A1'], [12, 0]]], [[[13, 'A1'], [12, 0]], [[13, 'T19'], 'invalid'], [[13, 'J10'], [3, 8]], [[13, 'I5'], 'invalid'], [[13, 'H8'], [5, 7]], [[13, 'pass'], 'pass'], [[13, 'A0'], 'invalid'], [[13, 'O3'], 'invalid']], [[[9, 'K1'], 'invalid'], [[13, 'Z1'], 'invalid'], [[13, 'A0'], 'invalid'], [[13, 'A13'], [0, 0]], [[13, 'A14'], 'invalid'], [[13, 'K1'], [12, 9]], [[13, 'O3'], 'invalid'], [[19, 'A0'], 'invalid']]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("vertex 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)

prompt:
Vertices outside the board are converted to coordinates.

Input [size, text]. Case-insensitive, surrounding blanks ignored; "pass" -> "pass". Column letters A..Z skipping I; row numbers count from 1 at the bottom. Return [row_from_top, col] or "invalid".

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    size, text = x
    if text == '':
        return 'pass'
    if text == 'tt':
        return 'pass'
    if len(text) != 2:
        return 'invalid'
    col = ord(text[0]) - ord('a')
    row = ord(text[1]) - ord('a')
    if not (0 <= col < size and 0 <= row < size):
        return 'invalid'
    return [row, col]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[9, 'jj'], 'invalid'], [[9, 'Aa'], 'invalid'], [[9, 'aA'], 'invalid'], [[9, 'u'], 'invalid'], [[9, 'abc'], 'invalid'], [[9, 'ia'], [0, 8]], [[19, 'tt'], 'pass'], [[21, 'tt'], [19, 19]]], [[[9, 'ta'], 'invalid'], [[9, 'at'], 'invalid'], [[9, 'pd'], 'invalid'], [[9, 'dp'], 'invalid'], [[9, 'ia'], [0, 8]], [[9, 'ja'], 'invalid'], [[19, 'tt'], 'pass'], [[25, 'tt'], [19, 19]]], [[[13, 'dd'], [3, 3]], [[13, 'aa'], [0, 0]], [[13, 'ss'], 'invalid'], [[13, 'tt'], 'pass'], [[13, ''], 'pass'], [[13, 'ab'], [1, 0]], [[19, 'tt'], 'pass'], [[21, 'tt'], [19, 19]]], [[[13, 'jj'], [9, 9]], [[13, 'Aa'], 'invalid'], [[13, 'aA'], 'invalid'], [[13, 'u'], 'invalid'], [[13, 'abc'], 'invalid'], [[13, 'ia'], [0, 8]], [[19, 'tt'], 'pass'], [[25, 'tt'], [19, 19]]], [[[13, 'ta'], 'invalid'], [[13, 'at'], 'invalid'], [[13, 'pd'], 'invalid'], [[13, 'dp'], 'invalid'], [[13, 'ma'], [0, 12]], [[13, 'na'], 'invalid'], [[19, 'tt'], 'pass'], [[21, 'tt'], [19, 19]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("sgf point 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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    size, text = x
    if text == '':
        return 'pass'
    if text == 'tt' and size < 19:
        return 'pass'
    if len(text) != 2:
        return 'invalid'
    col = ord(text[0]) - ord('a')
    row = ord(text[1]) - ord('a')
    if not (0 <= col < size and 0 <= row < size):
        return 'invalid'
    return [row, col]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[9, 'jj'], 'invalid'], [[9, 'Aa'], 'invalid'], [[9, 'aA'], 'invalid'], [[9, 'u'], 'invalid'], [[9, 'abc'], 'invalid'], [[9, 'ia'], [0, 8]], [[19, 'tt'], 'pass'], [[21, 'tt'], [19, 19]]], [[[9, 'ta'], 'invalid'], [[9, 'at'], 'invalid'], [[9, 'pd'], 'invalid'], [[9, 'dp'], 'invalid'], [[9, 'ia'], [0, 8]], [[9, 'ja'], 'invalid'], [[19, 'tt'], 'pass'], [[25, 'tt'], [19, 19]]], [[[13, 'dd'], [3, 3]], [[13, 'aa'], [0, 0]], [[13, 'ss'], 'invalid'], [[13, 'tt'], 'pass'], [[13, ''], 'pass'], [[13, 'ab'], [1, 0]], [[19, 'tt'], 'pass'], [[21, 'tt'], [19, 19]]], [[[13, 'jj'], [9, 9]], [[13, 'Aa'], 'invalid'], [[13, 'aA'], 'invalid'], [[13, 'u'], 'invalid'], [[13, 'abc'], 'invalid'], [[13, 'ia'], [0, 8]], [[19, 'tt'], 'pass'], [[25, 'tt'], [19, 19]]], [[[13, 'ta'], 'invalid'], [[13, 'at'], 'invalid'], [[13, 'pd'], 'invalid'], [[13, 'dp'], 'invalid'], [[13, 'ma'], [0, 12]], [[13, 'na'], 'invalid'], [[19, 'tt'], 'pass'], [[21, 'tt'], [19, 19]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("sgf point 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)

prompt:
A real move at column 20 row 20 on a 21x21 board is dropped as a pass.

Input [size, text]. "" is a pass; "tt" is also a pass on boards up to 19x19. Otherwise exactly two lower-case letters: first = column, second = row, both from the top-left. Return [row, col], "pass" or "invalid".

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    size, text = x
    if text == '':
        return 'pass'
    if text == 'tt' and size <= 19:
        return 'pass'
    if len(text) != 2:
        return 'invalid'
    col = ord(text[0]) - ord('a')
    row = ord(text[1]) - ord('a')
    if not (0 <= col < size and 0 <= row < size):
        return 'invalid'
    return [col, row]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[9, 'ab'], [1, 0]], [[9, 'Aa'], 'invalid'], [[9, 'aA'], 'invalid'], [[9, 'u'], 'invalid'], [[9, 'abc'], 'invalid'], [[9, 'ia'], [0, 8]], [[9, 'ai'], [8, 0]], [[9, 'ia'], [0, 8]]], [[[9, 'ai'], [8, 0]], [[9, 'at'], 'invalid'], [[9, 'pd'], 'invalid'], [[9, 'dp'], 'invalid'], [[9, 'ia'], [0, 8]], [[9, 'ja'], 'invalid'], [[9, 'ai'], [8, 0]], [[13, 'ba'], [0, 1]]], [[[13, 'dd'], [3, 3]], [[13, 'aa'], [0, 0]], [[13, 'ss'], 'invalid'], [[13, 'tt'], 'pass'], [[13, ''], 'pass'], [[13, 'ab'], [1, 0]], [[13, 'ba'], [0, 1]], [[13, 'am'], [12, 0]]], [[[13, 'jj'], [9, 9]], [[13, 'Aa'], 'invalid'], [[13, 'aA'], 'invalid'], [[13, 'u'], 'invalid'], [[13, 'abc'], 'invalid'], [[13, 'ia'], [0, 8]], [[13, 'ai'], [8, 0]], [[19, 'ba'], [0, 1]]], [[[13, 'ta'], 'invalid'], [[13, 'at'], 'invalid'], [[13, 'pd'], 'invalid'], [[13, 'dp'], 'invalid'], [[13, 'ma'], [0, 12]], [[13, 'na'], 'invalid'], [[19, 'ab'], [1, 0]], [[19, 'sa'], [0, 18]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("sgf point 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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    size, text = x
    if text == '':
        return 'pass'
    if text == 'tt' and size <= 19:
        return 'pass'
    if len(text) != 2:
        return 'invalid'
    col = ord(text[0]) - ord('a')
    row = ord(text[1]) - ord('a')
    if not (0 <= col < size and 0 <= row < size):
        return 'invalid'
    return [size - 1 - row, col]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[9, 'ab'], [1, 0]], [[9, 'Aa'], 'invalid'], [[9, 'aA'], 'invalid'], [[9, 'u'], 'invalid'], [[9, 'abc'], 'invalid'], [[9, 'ia'], [0, 8]], [[9, 'ai'], [8, 0]], [[9, 'ia'], [0, 8]]], [[[9, 'ai'], [8, 0]], [[9, 'at'], 'invalid'], [[9, 'pd'], 'invalid'], [[9, 'dp'], 'invalid'], [[9, 'ia'], [0, 8]], [[9, 'ja'], 'invalid'], [[9, 'ai'], [8, 0]], [[13, 'ba'], [0, 1]]], [[[13, 'dd'], [3, 3]], [[13, 'aa'], [0, 0]], [[13, 'ss'], 'invalid'], [[13, 'tt'], 'pass'], [[13, ''], 'pass'], [[13, 'ab'], [1, 0]], [[13, 'ba'], [0, 1]], [[13, 'am'], [12, 0]]], [[[13, 'jj'], [9, 9]], [[13, 'Aa'], 'invalid'], [[13, 'aA'], 'invalid'], [[13, 'u'], 'invalid'], [[13, 'abc'], 'invalid'], [[13, 'ia'], [0, 8]], [[13, 'ai'], [8, 0]], [[19, 'ba'], [0, 1]]], [[[13, 'ta'], 'invalid'], [[13, 'at'], 'invalid'], [[13, 'pd'], 'invalid'], [[13, 'dp'], 'invalid'], [[13, 'ma'], [0, 12]], [[13, 'na'], 'invalid'], [[19, 'ab'], [1, 0]], [[19, 'sa'], [0, 18]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("sgf point 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)

prompt:
Moves are mirrored across the main diagonal.

Input [size, text]. "" is a pass; "tt" is also a pass on boards up to 19x19. Otherwise exactly two lower-case letters: first = column, second = row, both from the top-left. Return [row, col], "pass" or "invalid".

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    size, text = x
    if text == '':
        return 'pass'
    if text == 'tt' and size <= 19:
        return 'pass'
    if len(text) != 2:
        return 'invalid'
    col = ord(text[0]) - ord('a')
    row = ord(text[1]) - ord('a')
    if not (col < size and row < size):
        return 'invalid'
    return [row, col]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[9, 'jj'], 'invalid'], [[9, 'Aa'], 'invalid'], [[9, 'aA'], 'invalid'], [[9, 'u'], 'invalid'], [[9, 'abc'], 'invalid'], [[9, 'ia'], [0, 8]], [[9, 'ai'], [8, 0]], [[21, 'va'], 'invalid']], [[[9, 'ta'], 'invalid'], [[9, 'at'], 'invalid'], [[9, 'pd'], 'invalid'], [[9, 'dp'], 'invalid'], [[9, 'ia'], [0, 8]], [[9, 'ja'], 'invalid'], [[13, 'aA'], 'invalid'], [[19, 'ta'], 'invalid']], [[[9, 'jj'], 'invalid'], [[13, 'aa'], [0, 0]], [[13, 'ss'], 'invalid'], [[13, 'tt'], 'pass'], [[13, ''], 'pass'], [[13, 'ab'], [1, 0]], [[13, 'ba'], [0, 1]], [[21, 'Aa'], 'invalid']], [[[13, 'jj'], [9, 9]], [[13, 'Aa'], 'invalid'], [[13, 'aA'], 'invalid'], [[13, 'u'], 'invalid'], [[13, 'abc'], 'invalid'], [[13, 'ia'], [0, 8]], [[19, 'ta'], 'invalid'], [[25, 'aA'], 'invalid']], [[[13, 'Aa'], 'invalid'], [[13, 'at'], 'invalid'], [[13, 'pd'], 'invalid'], [[13, 'dp'], 'invalid'], [[13, 'ma'], [0, 12]], [[13, 'na'], 'invalid'], [[13, 'am'], [12, 0]], [[19, 'dd'], [3, 3]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("sgf point 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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    size, text = x
    if text == '':
        return 'pass'
    if text == 'tt' and size <= 19:
        return 'pass'
    if len(text) != 2:
        return 'invalid'
    col = ord(text[0]) - ord('a')
    row = ord(text[1]) - ord('a')
    if not (0 <= col <= size and 0 <= row <= size):
        return 'invalid'
    return [row, col]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[9, 'jj'], 'invalid'], [[9, 'Aa'], 'invalid'], [[9, 'aA'], 'invalid'], [[9, 'u'], 'invalid'], [[9, 'abc'], 'invalid'], [[9, 'ia'], [0, 8]], [[9, 'ai'], [8, 0]], [[21, 'va'], 'invalid']], [[[9, 'ta'], 'invalid'], [[9, 'at'], 'invalid'], [[9, 'pd'], 'invalid'], [[9, 'dp'], 'invalid'], [[9, 'ia'], [0, 8]], [[9, 'ja'], 'invalid'], [[13, 'aA'], 'invalid'], [[19, 'ta'], 'invalid']], [[[9, 'jj'], 'invalid'], [[13, 'aa'], [0, 0]], [[13, 'ss'], 'invalid'], [[13, 'tt'], 'pass'], [[13, ''], 'pass'], [[13, 'ab'], [1, 0]], [[13, 'ba'], [0, 1]], [[21, 'Aa'], 'invalid']], [[[13, 'jj'], [9, 9]], [[13, 'Aa'], 'invalid'], [[13, 'aA'], 'invalid'], [[13, 'u'], 'invalid'], [[13, 'abc'], 'invalid'], [[13, 'ia'], [0, 8]], [[19, 'ta'], 'invalid'], [[25, 'aA'], 'invalid']], [[[13, 'Aa'], 'invalid'], [[13, 'at'], 'invalid'], [[13, 'pd'], 'invalid'], [[13, 'dp'], 'invalid'], [[13, 'ma'], [0, 12]], [[13, 'na'], 'invalid'], [[13, 'am'], [12, 0]], [[19, 'dd'], [3, 3]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("sgf point 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)

prompt:
Points like "Aa" produce negative rows or columns.

Input [size, text]. "" is a pass; "tt" is also a pass on boards up to 19x19. Otherwise exactly two lower-case letters: first = column, second = row, both from the top-left. Return [row, col], "pass" or "invalid".

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    size, text = x
    if text == 'tt' and size <= 19:
        return 'pass'
    if len(text) != 2:
        return 'invalid'
    col = ord(text[0]) - ord('a')
    row = ord(text[1]) - ord('a')
    if not (0 <= col < size and 0 <= row < size):
        return 'invalid'
    return [row, col]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[9, ''], 'pass'], [[9, 'Aa'], 'invalid'], [[9, 'aA'], 'invalid'], [[9, 'u'], 'invalid'], [[9, 'abc'], 'invalid'], [[9, 'ia'], [0, 8]], [[9, 'ai'], [8, 0]], [[21, ''], 'pass']], [[[9, 'ta'], 'invalid'], [[9, 'at'], 'invalid'], [[9, 'pd'], 'invalid'], [[9, 'dp'], 'invalid'], [[9, 'ia'], [0, 8]], [[9, 'ja'], 'invalid'], [[21, ''], 'pass'], [[25, ''], 'pass']], [[[13, 'dd'], [3, 3]], [[13, 'aa'], [0, 0]], [[13, 'ss'], 'invalid'], [[13, 'tt'], 'pass'], [[13, ''], 'pass'], [[13, 'ab'], [1, 0]], [[13, 'ba'], [0, 1]], [[21, ''], 'pass']], [[[13, 'jj'], [9, 9]], [[13, 'Aa'], 'invalid'], [[13, 'aA'], 'invalid'], [[13, 'u'], 'invalid'], [[13, 'abc'], 'invalid'], [[13, 'ia'], [0, 8]], [[25, ''], 'pass'], [[25, ''], 'pass']], [[[13, 'ta'], 'invalid'], [[13, 'at'], 'invalid'], [[13, 'pd'], 'invalid'], [[13, 'dp'], 'invalid'], [[13, 'ma'], [0, 12]], [[13, 'na'], 'invalid'], [[19, ''], 'pass'], [[21, ''], 'pass']]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("sgf point 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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    size, text = x
    if text == '' and size <= 19:
        return 'pass'
    if text == 'tt' and size <= 19:
        return 'pass'
    if len(text) != 2:
        return 'invalid'
    col = ord(text[0]) - ord('a')
    row = ord(text[1]) - ord('a')
    if not (0 <= col < size and 0 <= row < size):
        return 'invalid'
    return [row, col]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[9, ''], 'pass'], [[9, 'Aa'], 'invalid'], [[9, 'aA'], 'invalid'], [[9, 'u'], 'invalid'], [[9, 'abc'], 'invalid'], [[9, 'ia'], [0, 8]], [[9, 'ai'], [8, 0]], [[21, ''], 'pass']], [[[9, 'ta'], 'invalid'], [[9, 'at'], 'invalid'], [[9, 'pd'], 'invalid'], [[9, 'dp'], 'invalid'], [[9, 'ia'], [0, 8]], [[9, 'ja'], 'invalid'], [[21, ''], 'pass'], [[25, ''], 'pass']], [[[13, 'dd'], [3, 3]], [[13, 'aa'], [0, 0]], [[13, 'ss'], 'invalid'], [[13, 'tt'], 'pass'], [[13, ''], 'pass'], [[13, 'ab'], [1, 0]], [[13, 'ba'], [0, 1]], [[21, ''], 'pass']], [[[13, 'jj'], [9, 9]], [[13, 'Aa'], 'invalid'], [[13, 'aA'], 'invalid'], [[13, 'u'], 'invalid'], [[13, 'abc'], 'invalid'], [[13, 'ia'], [0, 8]], [[25, ''], 'pass'], [[25, ''], 'pass']], [[[13, 'ta'], 'invalid'], [[13, 'at'], 'invalid'], [[13, 'pd'], 'invalid'], [[13, 'dp'], 'invalid'], [[13, 'ma'], [0, 12]], [[13, 'na'], 'invalid'], [[19, ''], 'pass'], [[21, ''], 'pass']]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("sgf point 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)

prompt:
B[] passes become invalid moves.

Input [size, text]. "" is a pass; "tt" is also a pass on boards up to 19x19. Otherwise exactly two lower-case letters: first = column, second = row, both from the top-left. Return [row, col], "pass" or "invalid".

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    s = x.strip()
    if s in ('0', 'Draw', 'Jigo'):
        return ['draw', 0, 'score']
    if s == 'Void':
        return ['void', None, 'none']
    if len(s) < 2 or s[0] not in 'BW' or s[1] != '+':
        return ['unknown', None, 'none']
    who = s[0]
    rest = s[2:]
    if rest == '':
        return [who, None, 'unknown']
    word = rest.lower()
    for key, reason in (('r', 'resign'), ('t', 'time'), ('f', 'forfeit')):
        if word in (key, reason):
            return [who, None, reason]
    if '.' in rest:
        whole, _, frac = rest.partition('.')
    else:
        whole, frac = rest, '0'
    if not whole.isdigit() or not frac.isdigit() or len(frac) != 1:
        return ['unknown', None, 'none']
    return [who, int(whole) * 10, 'score']
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['B+3.5', ['B', 35, 'score']], ['W+0.5', ['W', 5, 'score']], ['W+12', ['W', 120, 'score']], ['B+2.3', ['B', 23, 'score']], ['W+8.2', ['W', 82, 'score']], ['B+1.1', ['B', 11, 'score']], ['B+', ['B', None, 'unknown']], ['W+', ['W', None, 'unknown']]], [['W+8.2', ['W', 82, 'score']], ['0', ['draw', 0, 'score']], ['Draw', ['draw', 0, 'score']], ['Jigo', ['draw', 0, 'score']], ['Void', ['void', None, 'none']], ['?', ['unknown', None, 'none']], [' B+R ', ['B', None, 'resign']], ['W+4.1', ['W', 41, 'score']]], [['B+3.5 ', ['B', 35, 'score']], [' W+7', ['W', 70, 'score']], ['X+3', ['unknown', None, 'none']], ['B-3', ['unknown', None, 'none']], ['B+3.25', ['unknown', None, 'none']], ['W+3.0', ['W', 30, 'score']], ['B+6.0', ['B', 60, 'score']], ['B+100.5', ['B', 1005, 'score']]], [['W+0.5', ['W', 5, 'score']], ['W+3.0', ['W', 30, 'score']], ['W+Timeout', ['unknown', None, 'none']], ['B+r', ['B', None, 'resign']], ['W+t', ['W', None, 'time']], ['B+100.5', ['B', 1005, 'score']], ['W+4.1', ['W', 41, 'score']], ['W+.5', ['unknown', None, 'none']]], [['B+R', ['B', None, 'resign']], ['W+Resign', ['W', None, 'resign']], ['B+resign', ['B', None, 'resign']], ['W+T', ['W', None, 'time']], ['B+Time', ['B', None, 'time']], ['B+1.1', ['B', 11, 'score']], ['B+1.1', ['B', 11, 'score']], ['B+7.', ['unknown', None, 'none']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("result 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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    s = x.strip()
    if s in ('0', 'Draw', 'Jigo'):
        return ['draw', 0, 'score']
    if s == 'Void':
        return ['void', None, 'none']
    if len(s) < 2 or s[0] not in 'BW' or s[1] != '+':
        return ['unknown', None, 'none']
    who = s[0]
    rest = s[2:]
    if rest == '':
        return [who, None, 'unknown']
    word = rest.lower()
    for key, reason in (('r', 'resign'), ('t', 'time'), ('f', 'forfeit')):
        if word in (key, reason):
            return [who, None, reason]
    if '.' in rest:
        whole, _, frac = rest.partition('.')
    else:
        whole, frac = rest, '0'
    if not whole.isdigit() or not frac.isdigit() or len(frac) != 1:
        return ['unknown', None, 'none']
    return [who, int(whole) * 10 + 5 * ('.' in rest), 'score']
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['B+3.5', ['B', 35, 'score']], ['W+0.5', ['W', 5, 'score']], ['W+12', ['W', 120, 'score']], ['B+2.3', ['B', 23, 'score']], ['W+8.2', ['W', 82, 'score']], ['B+1.1', ['B', 11, 'score']], ['B+', ['B', None, 'unknown']], ['W+', ['W', None, 'unknown']]], [['W+8.2', ['W', 82, 'score']], ['0', ['draw', 0, 'score']], ['Draw', ['draw', 0, 'score']], ['Jigo', ['draw', 0, 'score']], ['Void', ['void', None, 'none']], ['?', ['unknown', None, 'none']], [' B+R ', ['B', None, 'resign']], ['W+4.1', ['W', 41, 'score']]], [['B+3.5 ', ['B', 35, 'score']], [' W+7', ['W', 70, 'score']], ['X+3', ['unknown', None, 'none']], ['B-3', ['unknown', None, 'none']], ['B+3.25', ['unknown', None, 'none']], ['W+3.0', ['W', 30, 'score']], ['B+6.0', ['B', 60, 'score']], ['B+100.5', ['B', 1005, 'score']]], [['W+0.5', ['W', 5, 'score']], ['W+3.0', ['W', 30, 'score']], ['W+Timeout', ['unknown', None, 'none']], ['B+r', ['B', None, 'resign']], ['W+t', ['W', None, 'time']], ['B+100.5', ['B', 1005, 'score']], ['W+4.1', ['W', 41, 'score']], ['W+.5', ['unknown', None, 'none']]], [['B+R', ['B', None, 'resign']], ['W+Resign', ['W', None, 'resign']], ['B+resign', ['B', None, 'resign']], ['W+T', ['W', None, 'time']], ['B+Time', ['B', None, 'time']], ['B+1.1', ['B', 11, 'score']], ['B+1.1', ['B', 11, 'score']], ['B+7.', ['unknown', None, 'none']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("result 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)

prompt:
W+0.5 is stored as a zero margin win.

Input an SGF RE string. "0", "Draw", "Jigo" -> ["draw", 0, "score"]; "Void" -> ["void", None, "none"]; C+R/Resign, C+T/Time, C+F/Forfeit (case-insensitive) -> [C, None, reason]; "C+" -> [C, None, "unknown"]; C+digits with optional one-digit fraction -> [C, tenths, "score"]; else unknown.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    s = x.strip()
    if s in ('0', 'Draw', 'Jigo'):
        return ['draw', 0, 'score']
    if s == 'Void':
        return ['void', None, 'none']
    if len(s) < 2 or s[0] not in 'BW' or s[1] != '+':
        return ['unknown', None, 'none']
    who = s[0]
    rest = s[2:]
    if rest == '':
        return [who, None, 'unknown']
    word = rest
    for key, reason in (('r', 'resign'), ('t', 'time'), ('f', 'forfeit')):
        if word in (key, reason):
            return [who, None, reason]
    if '.' in rest:
        whole, _, frac = rest.partition('.')
    else:
        whole, frac = rest, '0'
    if not whole.isdigit() or not frac.isdigit() or len(frac) != 1:
        return ['unknown', None, 'none']
    return [who, int(whole) * 10 + int(frac), 'score']
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['B+R', ['B', None, 'resign']], ['W+0.5', ['W', 5, 'score']], ['W+12', ['W', 120, 'score']], ['B+2.3', ['B', 23, 'score']], ['W+8.2', ['W', 82, 'score']], ['B+1.1', ['B', 11, 'score']], ['B+', ['B', None, 'unknown']], ['B+Rough', ['unknown', None, 'none']]], [['B+Time', ['B', None, 'time']], ['0', ['draw', 0, 'score']], ['Draw', ['draw', 0, 'score']], ['Jigo', ['draw', 0, 'score']], ['Void', ['void', None, 'none']], ['?', ['unknown', None, 'none']], [' B+R ', ['B', None, 'resign']], ['W+Timeout', ['unknown', None, 'none']]], [[' B+R ', ['B', None, 'resign']], [' W+7', ['W', 70, 'score']], ['X+3', ['unknown', None, 'none']], ['B-3', ['unknown', None, 'none']], ['B+3.25', ['unknown', None, 'none']], ['W+3.0', ['W', 30, 'score']], ['B+6.0', ['B', 60, 'score']], ['B+Rough', ['unknown', None, 'none']]], [['W+T', ['W', None, 'time']], ['B+Rough', ['unknown', None, 'none']], ['W+Timeout', ['unknown', None, 'none']], ['B+r', ['B', None, 'resign']], ['W+t', ['W', None, 'time']], ['B+100.5', ['B', 1005, 'score']], ['W+4.1', ['W', 41, 'score']], ['W+.5', ['unknown', None, 'none']]], [['B+R', ['B', None, 'resign']], ['W+Resign', ['W', None, 'resign']], ['B+resign', ['B', None, 'resign']], ['W+T', ['W', None, 'time']], ['B+Time', ['B', None, 'time']], ['W+F', ['W', None, 'forfeit']], ['B+Forfeit', ['B', None, 'forfeit']], ['B+Rough', ['unknown', None, 'none']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("result 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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    s = x.strip()
    if s in ('0', 'Draw', 'Jigo'):
        return ['draw', 0, 'score']
    if s == 'Void':
        return ['void', None, 'none']
    if len(s) < 2 or s[0] not in 'BW' or s[1] != '+':
        return ['unknown', None, 'none']
    who = s[0]
    rest = s[2:]
    if rest == '':
        return [who, None, 'unknown']
    word = rest.lower()[:1]
    for key, reason in (('r', 'resign'), ('t', 'time'), ('f', 'forfeit')):
        if word in (key, reason):
            return [who, None, reason]
    if '.' in rest:
        whole, _, frac = rest.partition('.')
    else:
        whole, frac = rest, '0'
    if not whole.isdigit() or not frac.isdigit() or len(frac) != 1:
        return ['unknown', None, 'none']
    return [who, int(whole) * 10 + int(frac), 'score']
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['B+R', ['B', None, 'resign']], ['W+0.5', ['W', 5, 'score']], ['W+12', ['W', 120, 'score']], ['B+2.3', ['B', 23, 'score']], ['W+8.2', ['W', 82, 'score']], ['B+1.1', ['B', 11, 'score']], ['B+', ['B', None, 'unknown']], ['B+Rough', ['unknown', None, 'none']]], [['B+Time', ['B', None, 'time']], ['0', ['draw', 0, 'score']], ['Draw', ['draw', 0, 'score']], ['Jigo', ['draw', 0, 'score']], ['Void', ['void', None, 'none']], ['?', ['unknown', None, 'none']], [' B+R ', ['B', None, 'resign']], ['W+Timeout', ['unknown', None, 'none']]], [[' B+R ', ['B', None, 'resign']], [' W+7', ['W', 70, 'score']], ['X+3', ['unknown', None, 'none']], ['B-3', ['unknown', None, 'none']], ['B+3.25', ['unknown', None, 'none']], ['W+3.0', ['W', 30, 'score']], ['B+6.0', ['B', 60, 'score']], ['B+Rough', ['unknown', None, 'none']]], [['W+T', ['W', None, 'time']], ['B+Rough', ['unknown', None, 'none']], ['W+Timeout', ['unknown', None, 'none']], ['B+r', ['B', None, 'resign']], ['W+t', ['W', None, 'time']], ['B+100.5', ['B', 1005, 'score']], ['W+4.1', ['W', 41, 'score']], ['W+.5', ['unknown', None, 'none']]], [['B+R', ['B', None, 'resign']], ['W+Resign', ['W', None, 'resign']], ['B+resign', ['B', None, 'resign']], ['W+T', ['W', None, 'time']], ['B+Time', ['B', None, 'time']], ['W+F', ['W', None, 'forfeit']], ['B+Forfeit', ['B', None, 'forfeit']], ['B+Rough', ['unknown', None, 'none']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("result 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)

prompt:
B+R and W+Resign are reported as unknown results.

Input an SGF RE string. "0", "Draw", "Jigo" -> ["draw", 0, "score"]; "Void" -> ["void", None, "none"]; C+R/Resign, C+T/Time, C+F/Forfeit (case-insensitive) -> [C, None, reason]; "C+" -> [C, None, "unknown"]; C+digits with optional one-digit fraction -> [C, tenths, "score"]; else unknown.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    s = x.strip()
    if s == 'Draw':
        return ['draw', 0, 'score']
    if s == 'Void':
        return ['void', None, 'none']
    if len(s) < 2 or s[0] not in 'BW' or s[1] != '+':
        return ['unknown', None, 'none']
    who = s[0]
    rest = s[2:]
    if rest == '':
        return [who, None, 'unknown']
    word = rest.lower()
    for key, reason in (('r', 'resign'), ('t', 'time'), ('f', 'forfeit')):
        if word in (key, reason):
            return [who, None, reason]
    if '.' in rest:
        whole, _, frac = rest.partition('.')
    else:
        whole, frac = rest, '0'
    if not whole.isdigit() or not frac.isdigit() or len(frac) != 1:
        return ['unknown', None, 'none']
    return [who, int(whole) * 10 + int(frac), 'score']
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['B+3.5', ['B', 35, 'score']], ['W+0.5', ['W', 5, 'score']], ['W+12', ['W', 120, 'score']], ['B+2.3', ['B', 23, 'score']], ['W+8.2', ['W', 82, 'score']], ['B+1.1', ['B', 11, 'score']], ['0', ['draw', 0, 'score']], ['0', ['draw', 0, 'score']]], [['W+', ['W', None, 'unknown']], ['0', ['draw', 0, 'score']], ['Draw', ['draw', 0, 'score']], ['Jigo', ['draw', 0, 'score']], ['Void', ['void', None, 'none']], ['?', ['unknown', None, 'none']], [' B+R ', ['B', None, 'resign']], ['B+3.5 ', ['B', 35, 'score']]], [['0', ['draw', 0, 'score']], ['0', ['draw', 0, 'score']], [' W+7', ['W', 70, 'score']], ['X+3', ['unknown', None, 'none']], ['B-3', ['unknown', None, 'none']], ['B+3.25', ['unknown', None, 'none']], ['W+3.0', ['W', 30, 'score']], ['B+6.0', ['B', 60, 'score']]], [['0', ['draw', 0, 'score']], ['Jigo', ['draw', 0, 'score']], ['W+Timeout', ['unknown', None, 'none']], ['B+r', ['B', None, 'resign']], ['W+t', ['W', None, 'time']], ['B+100.5', ['B', 1005, 'score']], ['W+4.1', ['W', 41, 'score']], ['W+.5', ['unknown', None, 'none']]], [['B+R', ['B', None, 'resign']], ['W+Resign', ['W', None, 'resign']], ['B+resign', ['B', None, 'resign']], ['W+T', ['W', None, 'time']], ['B+Time', ['B', None, 'time']], ['0', ['draw', 0, 'score']], ['0', ['draw', 0, 'score']], ['B+7.', ['unknown', None, 'none']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("result 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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    s = x.strip()
    if s in ('Draw', 'Jigo'):
        return ['draw', 0, 'score']
    if s == 'Void':
        return ['void', None, 'none']
    if len(s) < 2 or s[0] not in 'BW' or s[1] != '+':
        return ['unknown', None, 'none']
    who = s[0]
    rest = s[2:]
    if rest == '':
        return [who, None, 'unknown']
    word = rest.lower()
    for key, reason in (('r', 'resign'), ('t', 'time'), ('f', 'forfeit')):
        if word in (key, reason):
            return [who, None, reason]
    if '.' in rest:
        whole, _, frac = rest.partition('.')
    else:
        whole, frac = rest, '0'
    if not whole.isdigit() or not frac.isdigit() or len(frac) != 1:
        return ['unknown', None, 'none']
    return [who, int(whole) * 10 + int(frac), 'score']
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['B+3.5', ['B', 35, 'score']], ['W+0.5', ['W', 5, 'score']], ['W+12', ['W', 120, 'score']], ['B+2.3', ['B', 23, 'score']], ['W+8.2', ['W', 82, 'score']], ['B+1.1', ['B', 11, 'score']], ['0', ['draw', 0, 'score']], ['0', ['draw', 0, 'score']]], [['W+', ['W', None, 'unknown']], ['0', ['draw', 0, 'score']], ['Draw', ['draw', 0, 'score']], ['Jigo', ['draw', 0, 'score']], ['Void', ['void', None, 'none']], ['?', ['unknown', None, 'none']], [' B+R ', ['B', None, 'resign']], ['B+3.5 ', ['B', 35, 'score']]], [['0', ['draw', 0, 'score']], ['0', ['draw', 0, 'score']], [' W+7', ['W', 70, 'score']], ['X+3', ['unknown', None, 'none']], ['B-3', ['unknown', None, 'none']], ['B+3.25', ['unknown', None, 'none']], ['W+3.0', ['W', 30, 'score']], ['B+6.0', ['B', 60, 'score']]], [['0', ['draw', 0, 'score']], ['Jigo', ['draw', 0, 'score']], ['W+Timeout', ['unknown', None, 'none']], ['B+r', ['B', None, 'resign']], ['W+t', ['W', None, 'time']], ['B+100.5', ['B', 1005, 'score']], ['W+4.1', ['W', 41, 'score']], ['W+.5', ['unknown', None, 'none']]], [['B+R', ['B', None, 'resign']], ['W+Resign', ['W', None, 'resign']], ['B+resign', ['B', None, 'resign']], ['W+T', ['W', None, 'time']], ['B+Time', ['B', None, 'time']], ['0', ['draw', 0, 'score']], ['0', ['draw', 0, 'score']], ['B+7.', ['unknown', None, 'none']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("result 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)

prompt:
Records with RE[0] or RE[Jigo] are classified as unknown.

Input an SGF RE string. "0", "Draw", "Jigo" -> ["draw", 0, "score"]; "Void" -> ["void", None, "none"]; C+R/Resign, C+T/Time, C+F/Forfeit (case-insensitive) -> [C, None, reason]; "C+" -> [C, None, "unknown"]; C+digits with optional one-digit fraction -> [C, tenths, "score"]; else unknown.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    s = x.strip()
    if s in ('0', 'Draw', 'Jigo'):
        return ['draw', 0, 'score']
    if len(s) < 2 or s[0] not in 'BW' or s[1] != '+':
        return ['unknown', None, 'none']
    who = s[0]
    rest = s[2:]
    if rest == '':
        return [who, None, 'unknown']
    word = rest.lower()
    for key, reason in (('r', 'resign'), ('t', 'time'), ('f', 'forfeit')):
        if word in (key, reason):
            return [who, None, reason]
    if '.' in rest:
        whole, _, frac = rest.partition('.')
    else:
        whole, frac = rest, '0'
    if not whole.isdigit() or not frac.isdigit() or len(frac) != 1:
        return ['unknown', None, 'none']
    return [who, int(whole) * 10 + int(frac), 'score']
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['B+3.5', ['B', 35, 'score']], ['W+0.5', ['W', 5, 'score']], ['W+12', ['W', 120, 'score']], ['B+2.3', ['B', 23, 'score']], ['W+8.2', ['W', 82, 'score']], ['B+1.1', ['B', 11, 'score']], ['Void', ['void', None, 'none']], ['Void', ['void', None, 'none']]], [['W+', ['W', None, 'unknown']], ['0', ['draw', 0, 'score']], ['Draw', ['draw', 0, 'score']], ['Jigo', ['draw', 0, 'score']], ['Void', ['void', None, 'none']], ['Void', ['void', None, 'none']], ['?', ['unknown', None, 'none']], [' B+R ', ['B', None, 'resign']]], [['Void', ['void', None, 'none']], ['Void', ['void', None, 'none']], [' W+7', ['W', 70, 'score']], ['X+3', ['unknown', None, 'none']], ['B-3', ['unknown', None, 'none']], ['B+3.25', ['unknown', None, 'none']], ['W+3.0', ['W', 30, 'score']], ['B+6.0', ['B', 60, 'score']]], [['Void', ['void', None, 'none']], ['Void', ['void', None, 'none']], ['B+Rough', ['unknown', None, 'none']], ['W+Timeout', ['unknown', None, 'none']], ['B+r', ['B', None, 'resign']], ['W+t', ['W', None, 'time']], ['B+100.5', ['B', 1005, 'score']], ['W+4.1', ['W', 41, 'score']]], [['B+R', ['B', None, 'resign']], ['W+Resign', ['W', None, 'resign']], ['B+resign', ['B', None, 'resign']], ['W+T', ['W', None, 'time']], ['B+Time', ['B', None, 'time']], ['Void', ['void', None, 'none']], ['Void', ['void', None, 'none']], ['B+7.', ['unknown', None, 'none']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("result 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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    s = x.strip()
    if s in ('0', 'Draw', 'Jigo'):
        return ['draw', 0, 'score']
    if s == 'Void':
        return ['draw', 0, 'score']
    if len(s) < 2 or s[0] not in 'BW' or s[1] != '+':
        return ['unknown', None, 'none']
    who = s[0]
    rest = s[2:]
    if rest == '':
        return [who, None, 'unknown']
    word = rest.lower()
    for key, reason in (('r', 'resign'), ('t', 'time'), ('f', 'forfeit')):
        if word in (key, reason):
            return [who, None, reason]
    if '.' in rest:
        whole, _, frac = rest.partition('.')
    else:
        whole, frac = rest, '0'
    if not whole.isdigit() or not frac.isdigit() or len(frac) != 1:
        return ['unknown', None, 'none']
    return [who, int(whole) * 10 + int(frac), 'score']
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['B+3.5', ['B', 35, 'score']], ['W+0.5', ['W', 5, 'score']], ['W+12', ['W', 120, 'score']], ['B+2.3', ['B', 23, 'score']], ['W+8.2', ['W', 82, 'score']], ['B+1.1', ['B', 11, 'score']], ['Void', ['void', None, 'none']], ['Void', ['void', None, 'none']]], [['W+', ['W', None, 'unknown']], ['0', ['draw', 0, 'score']], ['Draw', ['draw', 0, 'score']], ['Jigo', ['draw', 0, 'score']], ['Void', ['void', None, 'none']], ['Void', ['void', None, 'none']], ['?', ['unknown', None, 'none']], [' B+R ', ['B', None, 'resign']]], [['Void', ['void', None, 'none']], ['Void', ['void', None, 'none']], [' W+7', ['W', 70, 'score']], ['X+3', ['unknown', None, 'none']], ['B-3', ['unknown', None, 'none']], ['B+3.25', ['unknown', None, 'none']], ['W+3.0', ['W', 30, 'score']], ['B+6.0', ['B', 60, 'score']]], [['Void', ['void', None, 'none']], ['Void', ['void', None, 'none']], ['B+Rough', ['unknown', None, 'none']], ['W+Timeout', ['unknown', None, 'none']], ['B+r', ['B', None, 'resign']], ['W+t', ['W', None, 'time']], ['B+100.5', ['B', 1005, 'score']], ['W+4.1', ['W', 41, 'score']]], [['B+R', ['B', None, 'resign']], ['W+Resign', ['W', None, 'resign']], ['B+resign', ['B', None, 'resign']], ['W+T', ['W', None, 'time']], ['B+Time', ['B', None, 'time']], ['Void', ['void', None, 'none']], ['Void', ['void', None, 'none']], ['B+7.', ['unknown', None, 'none']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("result 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)

prompt:
RE[Void] (no result, e.g. an annulled game) is reported as unknown.

Input an SGF RE string. "0", "Draw", "Jigo" -> ["draw", 0, "score"]; "Void" -> ["void", None, "none"]; C+R/Resign, C+T/Time, C+F/Forfeit (case-insensitive) -> [C, None, reason]; "C+" -> [C, None, "unknown"]; C+digits with optional one-digit fraction -> [C, tenths, "score"]; else unknown.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    s = x.strip()
    if s in ('0', 'Draw', 'Jigo'):
        return ['draw', 0, 'score']
    if s == 'Void':
        return ['void', None, 'none']
    if len(s) < 2 or s[0] not in 'BW' or s[1] != '+':
        return ['unknown', None, 'none']
    who = s[0]
    rest = s[2:]
    word = rest.lower()
    for key, reason in (('r', 'resign'), ('t', 'time'), ('f', 'forfeit')):
        if word in (key, reason):
            return [who, None, reason]
    if '.' in rest:
        whole, _, frac = rest.partition('.')
    else:
        whole, frac = rest, '0'
    if not whole.isdigit() or not frac.isdigit() or len(frac) != 1:
        return ['unknown', None, 'none']
    return [who, int(whole) * 10 + int(frac), 'score']
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['B+3.5', ['B', 35, 'score']], ['W+0.5', ['W', 5, 'score']], ['W+12', ['W', 120, 'score']], ['B+2.3', ['B', 23, 'score']], ['W+8.2', ['W', 82, 'score']], ['B+1.1', ['B', 11, 'score']], ['B+', ['B', None, 'unknown']], ['B+', ['B', None, 'unknown']]], [['W+', ['W', None, 'unknown']], ['W+', ['W', None, 'unknown']], ['0', ['draw', 0, 'score']], ['Draw', ['draw', 0, 'score']], ['Jigo', ['draw', 0, 'score']], ['Void', ['void', None, 'none']], ['?', ['unknown', None, 'none']], [' B+R ', ['B', None, 'resign']]], [['B+', ['B', None, 'unknown']], ['B+', ['B', None, 'unknown']], [' W+7', ['W', 70, 'score']], ['X+3', ['unknown', None, 'none']], ['B-3', ['unknown', None, 'none']], ['B+3.25', ['unknown', None, 'none']], ['W+3.0', ['W', 30, 'score']], ['B+6.0', ['B', 60, 'score']]], [['W+', ['W', None, 'unknown']], ['W+', ['W', None, 'unknown']], ['B+Rough', ['unknown', None, 'none']], ['W+Timeout', ['unknown', None, 'none']], ['B+r', ['B', None, 'resign']], ['W+t', ['W', None, 'time']], ['B+100.5', ['B', 1005, 'score']], ['W+4.1', ['W', 41, 'score']]], [['B+R', ['B', None, 'resign']], ['W+Resign', ['W', None, 'resign']], ['B+resign', ['B', None, 'resign']], ['W+T', ['W', None, 'time']], ['B+Time', ['B', None, 'time']], ['B+', ['B', None, 'unknown']], ['B+', ['B', None, 'unknown']], ['B+7.', ['unknown', None, 'none']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("result 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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    s = x.strip()
    if s in ('0', 'Draw', 'Jigo'):
        return ['draw', 0, 'score']
    if s == 'Void':
        return ['void', None, 'none']
    if len(s) < 2 or s[0] not in 'BW' or s[1] != '+':
        return ['unknown', None, 'none']
    who = s[0]
    rest = s[2:]
    if rest == '':
        return [who, 0, 'score']
    word = rest.lower()
    for key, reason in (('r', 'resign'), ('t', 'time'), ('f', 'forfeit')):
        if word in (key, reason):
            return [who, None, reason]
    if '.' in rest:
        whole, _, frac = rest.partition('.')
    else:
        whole, frac = rest, '0'
    if not whole.isdigit() or not frac.isdigit() or len(frac) != 1:
        return ['unknown', None, 'none']
    return [who, int(whole) * 10 + int(frac), 'score']
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['B+3.5', ['B', 35, 'score']], ['W+0.5', ['W', 5, 'score']], ['W+12', ['W', 120, 'score']], ['B+2.3', ['B', 23, 'score']], ['W+8.2', ['W', 82, 'score']], ['B+1.1', ['B', 11, 'score']], ['B+', ['B', None, 'unknown']], ['B+', ['B', None, 'unknown']]], [['W+', ['W', None, 'unknown']], ['W+', ['W', None, 'unknown']], ['0', ['draw', 0, 'score']], ['Draw', ['draw', 0, 'score']], ['Jigo', ['draw', 0, 'score']], ['Void', ['void', None, 'none']], ['?', ['unknown', None, 'none']], [' B+R ', ['B', None, 'resign']]], [['B+', ['B', None, 'unknown']], ['B+', ['B', None, 'unknown']], [' W+7', ['W', 70, 'score']], ['X+3', ['unknown', None, 'none']], ['B-3', ['unknown', None, 'none']], ['B+3.25', ['unknown', None, 'none']], ['W+3.0', ['W', 30, 'score']], ['B+6.0', ['B', 60, 'score']]], [['W+', ['W', None, 'unknown']], ['W+', ['W', None, 'unknown']], ['B+Rough', ['unknown', None, 'none']], ['W+Timeout', ['unknown', None, 'none']], ['B+r', ['B', None, 'resign']], ['W+t', ['W', None, 'time']], ['B+100.5', ['B', 1005, 'score']], ['W+4.1', ['W', 41, 'score']]], [['B+R', ['B', None, 'resign']], ['W+Resign', ['W', None, 'resign']], ['B+resign', ['B', None, 'resign']], ['W+T', ['W', None, 'time']], ['B+Time', ['B', None, 'time']], ['B+', ['B', None, 'unknown']], ['B+', ['B', None, 'unknown']], ['B+7.', ['unknown', None, 'none']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("result 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)

prompt:
RE[B+] loses the winner.

Input an SGF RE string. "0", "Draw", "Jigo" -> ["draw", 0, "score"]; "Void" -> ["void", None, "none"]; C+R/Resign, C+T/Time, C+F/Forfeit (case-insensitive) -> [C, None, reason]; "C+" -> [C, None, "unknown"]; C+digits with optional one-digit fraction -> [C, tenths, "score"]; else unknown.

split: open-access


source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(x):
    board, komi = x
    n = len(board)
    m = len(board[0])
    score = {'B': 0, 'W': 0}
    groups = {'B': 0, 'W': 0}
    seen = set()
    for r in range(n):
        for c in range(m):
            if (r, c) in seen:
                continue
            col = board[r][c]
            seen.add((r, c))
            stack = [(r, c)]
            size = 0
            touch = set()
            while stack:
                i, j = stack.pop()
                size += 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:
                        v = board[p][q]
                        if v == col and (p, q) not in seen:
                            seen.add((p, q))
                            stack.append((p, q))
                        elif v != col:
                            touch.add(v)
            if col == '.':
                if len(touch) == 1:
                    score[touch.pop()] += size
            else:
                score[col] += size
                groups[col] += 1 if size > 1 else 0
    b = score['B'] - 2 * groups['B']
    w = score['W'] - 2 * groups['W']
    return [b, w, b * 10 - w * 10 - komi]
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'], 75], [2, 2, -75]], [[['.W.B.', 'W.WB.', '.WB..', 'WB...', 'B....'], 75], [8, -2, 25]], [[['BBBB', 'B..B', 'B..B', 'BBBB'], 20], [14, 0, 120]], [[['WWW', 'W.W', 'WWW'], 0], [0, 7, -70]], [[['B.W', '...', 'W.B'], 5], [-2, -2, -5]], [[['.B...', 'B....', '.....', '....W', '...W.'], 65], [-1, -1, -65]], [[['BW.', 'BW.', 'BW.'], 75], [1, 4, -105]], [[['WB.B', 'B.B.', '.B..', 'B...'], 0], [3, -1, 40]]], [[[['B.B.W', '.B.W.', 'B.BW.', 'BBW.W', '..W..'], 5], [0, 3, -35]], [[['WB.B', 'B.B.', '.B..', 'B...'], 0], [3, -1, 40]], [[['..W', '.W.', 'W..'], 5], [0, 3, -35]], [[['B....B', '......', '..WW..', '..WW..', '......', 'B....B'], 65], [-4, 2, -125]], [[['..WW', '.W..', 'B...'], 75], [-1, -1, -75]], [[['..WW', '.W.B', '.WWW', 'B..B'], 20], [-3, 2, -70]], [[['W..B', 'W...', '.W.W', '.W..', 'W.W.'], 0], [-1, 0, -10]], [[['.W...', 'W....', '.....', '....W', 'W....'], 5], [0, 17, -175]]], [[[['WWW', 'W.W', 'WWW'], 0], [0, 7, -70]], [[['..B', '..B', '...', '...', '..B'], 65], [11, 0, 45]], [[['B..', 'B.W', '.W.'], 75], [0, -1, -65]], [[['W..BW.', '.W....', '......'], 20], [-1, -3, 0]], [[['BBBB', '....', '.W.B', 'BBB.', '.BBB', 'BB.B'], 0], [11, -1, 120]], [[['...', '.BW', '.B.', '...', 'B.B', 'BB.'], 5], [1, -1, 15]], [[['B.B', 'WWB', 'BWB', 'BWB', 'WBB'], 65], [3, 1, -45]], [[['B.WBB', 'W.B..', 'W.WWB', '.WB.B', '.WWWW', '..W.B'], 75], [-4, 7, -185]]], [[[['B....B', '......', '..WW..', '..WW..', '......', 'B....B'], 65], [-4, 2, -125]], [[['.WWB', '.BB.', '.BBB', '..B.'], 20], [5, 0, 30]], [[['B.B...', '......', '..WWB.', '.WB.W.', 'WWB.B.'], 0], [-4, 0, -40]], [[['.WWBBB', 'WBWB.W', 'BBB.W.', 'BB..BB', 'BWB.B.', 'WWW.WW'], 5], [7, 1, 55]], [[['BBBB', 'B..B', 'W..B', '.WBB', 'WB..', '.B..'], 65], [11, -2, 65]], [[['WWWB.W', 'WB....', 'W.WB..', 'W.BB.W', 'BBW...', '.BB.WW'], 75], [2, 0, -55]], [[['BWB', 'W.W', 'WBW', 'BWB', '.W.', 'BWW'], 20], [-6, 1, -90]], [[['.BBW', '.WB.', 'W...', '....', '....'], 0], [1, -3, 40]]], [[[['W..B', 'W...', '.W.W', '.W..', 'W.W.'], 0], [-1, 0, -10]], [[['.BBW', '.WB.', 'W...', '....', '....'], 0], [1, -3, 40]], [[['B..', 'B..', '.B.', '..B', '..B'], 65], [9, 0, 25]], [[['....W.', '...B.B', 'BBBB..', '..B.W.', '.B.B.W'], 75], [5, -3, 5]], [[['..B', '.BW', 'B.B'], 20], [0, -1, -10]], [[['.BB..B', '......', 'B.B.BB', '.BBB..', '.B....'], 0], [20, 0, 200]], [[['W..', '.B.', '.W.', '...'], 5], [-1, -2, 5]], [[['..WW', 'B.WW', 'WBBW', '.WBW', 'WWBW', 'B..W'], 65], [0, 7, -135]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("group tax 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)

prompt:
Large living groups are penalised by their size.

Input [board, komi_tenths]. Each colour scores stones + empty regions bordered only by it, minus two points per orthogonally connected chain. Return [black, white, margin_tenths] with margin = 10*(black-white) - komi.

split: open-access


prompt:
Players are under-taxed for diagonal shapes and regions leak diagonally.

Input [board, komi_tenths]. Each colour scores stones + empty regions bordered only by it, minus two points per orthogonally connected chain. Return [black, white, margin_tenths] with margin = 10*(black-white) - komi.

split: open-access


prompt:
Fragmented positions lose only half the intended penalty.

Input [board, komi_tenths]. Each colour scores stones + empty regions bordered only by it, minus two points per orthogonally connected chain. Return [black, white, margin_tenths] with margin = 10*(black-white) - komi.

split: open-access


prompt:
Passing earns the passer a prisoner.

Input [terr_b, terr_w, prisoners_b, prisoners_w, passes, komi_tenths]; passes lists passing colours in order. Each pass gives one prisoner to the opponent; if the final pass was black, white hands one extra stone to black. Return [black_tenths, white_tenths, winner] with winner B, W or tie.

split: open-access


prompt:
White is charged or excused the equalising stone based on who passed first.

Input [terr_b, terr_w, prisoners_b, prisoners_w, passes, komi_tenths]; passes lists passing colours in order. Each pass gives one prisoner to the opponent; if the final pass was black, white hands one extra stone to black. Return [black_tenths, white_tenths, winner] with winner B, W or tie.

split: open-access


prompt:
Black-last games give white an extra prisoner.

Input [terr_b, terr_w, prisoners_b, prisoners_w, passes, komi_tenths]; passes lists passing colours in order. Each pass gives one prisoner to the opponent; if the final pass was black, white hands one extra stone to black. Return [black_tenths, white_tenths, winner] with winner B, W or tie.

split: open-access


prompt:
Handicap 1 games give white an extra point.

Input [rules, handicap, area_b, area_w, komi_tenths]. With handicap >= 2, white receives handicap points under chinese and handicap-1 under aga; other rules none. Return black margin in tenths.

split: open-access


prompt:
AGA games are scored like Chinese games.

Input [rules, handicap, area_b, area_w, komi_tenths]. With handicap >= 2, white receives handicap points under chinese and handicap-1 under aga; other rules none. Return black margin in tenths.

split: open-access


prompt:
Black margin grows with the handicap.

Input [rules, handicap, area_b, area_w, komi_tenths]. With handicap >= 2, white receives handicap points under chinese and handicap-1 under aga; other rules none. Return black margin in tenths.

split: open-access


prompt:
Chains whose only liberty touches two of their stones are not reported.

Input a board. Report every chain with exactly one distinct liberty as [colour, lib_row, lib_col, chain_size], sorted ascending.

split: open-access


prompt:
Reports are emitted in row-major discovery order instead of sorted order.

Input a board. Report every chain with exactly one distinct liberty as [colour, lib_row, lib_col, chain_size], sorted ascending.

split: open-access


prompt:
Chains in atari appear to have several liberties.

Input [board, row, col]. Return [colour, chain_size, distinct_orthogonal_empty_liberties]; an empty point gives [".", 0, 0].

split: open-access


prompt:
Edge and corner chains report extra liberties.

Input [board, row, col]. Return [colour, chain_size, distinct_orthogonal_empty_liberties]; an empty point gives [".", 0, 0].

split: open-access


prompt:
A contact fight reports one merged chain with the liberties of both sides.

Input [board, row, col]. Return [colour, chain_size, distinct_orthogonal_empty_liberties]; an empty point gives [".", 0, 0].

split: open-access


prompt:
An edge eye with one opponent diagonal is reported as real.

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".

split: open-access


prompt:
Every corner eye is reported false.

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".

split: open-access


prompt:
Points on the first line are classified as none.

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".

split: open-access


prompt:
Centre points with exactly two opponent diagonals are called real eyes.

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".

split: open-access


prompt:
A stone surrounded by its own colour is reported as an eye.

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".

split: open-access


prompt:
Half of a dead group stays alive after a click.

Input [board, dead_points, row, col]. Clicking a stone toggles its whole orthogonally connected chain: if the clicked stone is currently marked, unmark the chain, otherwise mark it. Clicking an empty point changes nothing. Return the sorted distinct dead points.

split: open-access


prompt:
Clicking a marked stone in a partially marked chain marks everything.

Input [board, dead_points, row, col]. Clicking a stone toggles its whole orthogonally connected chain: if the clicked stone is currently marked, unmark the chain, otherwise mark it. Clicking an empty point changes nothing. Return the sorted distinct dead points.

split: open-access