FAILURE MAP
← Case archive

FA-83186 / Go territory scoring / Open access

Every pass earns another half point · case 01

Players accumulate multiple buttons by passing repeatedly.

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

ROOT CAUSE

The award is inside a loop over all passes.

VERIFIED REPAIR

There is exactly one button, taken by the first passer.

Unsuccessful approach: Awarding only when exactly one pass occurred drops the button in normal two-pass endings.

Case contract

Input [area_b, area_w, passes, komi_tenths]. The first player ever to pass takes the button worth half a point. Return [black_tenths, white_tenths, winner] with winner B, W or draw.

Why this case matters

Go servers and scoring tools compute this value automatically; a wrong answer changes a game result.

1 / The failure

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

N = 1
observations = []
def solve(x):
    ab, aw, passes, komi = x
    sb = ab * 10
    sw = aw * 10 + komi
    for who in passes:
        if who == 'B':
            sb += 5
        else:
            sw += 5
    winner = 'B' if sb > sw else 'W' if sw > sb else 'draw'
    return [sb, sw, winner]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[186, 173, ['W', 'W'], 0], [1860, 1735, 'B']], [[171, 180, ['W', 'B', 'B'], 60], [1710, 1865, 'W']], [[186, 187, ['B', 'W'], 0], [1865, 1870, 'W']], [[187, 178, ['W'], 60], [1870, 1845, 'B']], [[178, 183, ['W', 'W', 'W'], 60], [1780, 1895, 'W']], [[179, 185, ['W'], 60], [1790, 1915, 'W']], [[174, 182, ['W', 'B', 'B'], 5], [1740, 1830, 'W']], [[187, 175, ['B'], 60], [1875, 1810, 'B']]], [[[180, 171, ['W', 'B', 'W'], 0], [1800, 1715, 'B']], [[186, 183, [], 60], [1860, 1890, 'W']], [[191, 181, ['B', 'W', 'W'], 0], [1915, 1810, 'B']], [[186, 178, ['W', 'B'], 5], [1860, 1790, 'B']], [[187, 185, ['W'], 70], [1870, 1925, 'W']], [[178, 182, ['B', 'B'], 5], [1785, 1825, 'W']], [[176, 188, ['W', 'W'], 5], [1760, 1890, 'W']], [[171, 181, ['W', 'W'], 60], [1710, 1875, 'W']]], [[[171, 180, ['W', 'B', 'B'], 60], [1710, 1865, 'W']], [[171, 190, ['W', 'W'], 0], [1710, 1905, 'W']], [[175, 191, [], 5], [1750, 1915, 'W']], [[186, 183, ['W', 'W', 'W'], 5], [1860, 1840, 'B']], [[170, 181, [], 0], [1700, 1810, 'W']], [[179, 175, ['W'], 60], [1790, 1815, 'W']], [[190, 180, ['B', 'W', 'W'], 70], [1905, 1870, 'B']], [[176, 182, ['W', 'W', 'W'], 70], [1760, 1895, 'W']]], [[[174, 182, ['W', 'B', 'B'], 5], [1740, 1830, 'W']], [[179, 189, [], 60], [1790, 1950, 'W']], [[172, 174, [], 5], [1720, 1745, 'W']], [[177, 171, ['W'], 70], [1770, 1785, 'W']], [[179, 182, ['B'], 0], [1795, 1820, 'W']], [[182, 174, ['B', 'B'], 70], [1825, 1810, 'B']], [[173, 172, [], 70], [1730, 1790, 'W']], [[179, 175, ['W', 'W', 'B'], 60], [1790, 1815, 'W']]], [[[178, 182, ['B', 'B'], 5], [1785, 1825, 'W']], [[177, 171, ['B'], 60], [1775, 1770, 'B']], [[175, 176, ['B'], 5], [1755, 1765, 'W']], [[182, 185, ['B', 'W'], 60], [1825, 1910, 'W']], [[179, 175, ['W', 'W', 'B'], 60], [1790, 1815, 'W']], [[181, 180, ['B', 'B'], 70], [1815, 1870, 'W']], [[171, 191, [], 70], [1710, 1980, 'W']], [[173, 177, ['W', 'W'], 70], [1730, 1845, 'W']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("button case %d" % i, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
button case 0[1860, 1740, 'B'][1860, 1735, 'B']Failed
button case 1[1720, 1865, 'W'][1710, 1865, 'W']Failed
button case 2[1865, 1875, 'W'][1865, 1870, 'W']Failed
button case 3[1870, 1845, 'B'][1870, 1845, 'B']Passed
button case 4[1780, 1905, 'W'][1780, 1895, 'W']Failed
button case 5[1790, 1915, 'W'][1790, 1915, 'W']Passed
button case 6[1750, 1830, 'W'][1740, 1830, 'W']Failed
button case 7[1875, 1810, 'B'][1875, 1810, 'B']Passed

SHA-256 / 4c15df22597d6cce5f228d79ef5b7073064dfbc3f469ccea56ac7d9b78c3feb0

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(x):
    ab, aw, passes, komi = x
    sb = ab * 10
    sw = aw * 10 + komi
    if len(passes) == 1:
        if passes[0] == 'B':
            sb += 5
        else:
            sw += 5
    winner = 'B' if sb > sw else 'W' if sw > sb else 'draw'
    return [sb, sw, winner]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[186, 173, ['W', 'W'], 0], [1860, 1735, 'B']], [[171, 180, ['W', 'B', 'B'], 60], [1710, 1865, 'W']], [[186, 187, ['B', 'W'], 0], [1865, 1870, 'W']], [[187, 178, ['W'], 60], [1870, 1845, 'B']], [[178, 183, ['W', 'W', 'W'], 60], [1780, 1895, 'W']], [[179, 185, ['W'], 60], [1790, 1915, 'W']], [[174, 182, ['W', 'B', 'B'], 5], [1740, 1830, 'W']], [[187, 175, ['B'], 60], [1875, 1810, 'B']]], [[[180, 171, ['W', 'B', 'W'], 0], [1800, 1715, 'B']], [[186, 183, [], 60], [1860, 1890, 'W']], [[191, 181, ['B', 'W', 'W'], 0], [1915, 1810, 'B']], [[186, 178, ['W', 'B'], 5], [1860, 1790, 'B']], [[187, 185, ['W'], 70], [1870, 1925, 'W']], [[178, 182, ['B', 'B'], 5], [1785, 1825, 'W']], [[176, 188, ['W', 'W'], 5], [1760, 1890, 'W']], [[171, 181, ['W', 'W'], 60], [1710, 1875, 'W']]], [[[171, 180, ['W', 'B', 'B'], 60], [1710, 1865, 'W']], [[171, 190, ['W', 'W'], 0], [1710, 1905, 'W']], [[175, 191, [], 5], [1750, 1915, 'W']], [[186, 183, ['W', 'W', 'W'], 5], [1860, 1840, 'B']], [[170, 181, [], 0], [1700, 1810, 'W']], [[179, 175, ['W'], 60], [1790, 1815, 'W']], [[190, 180, ['B', 'W', 'W'], 70], [1905, 1870, 'B']], [[176, 182, ['W', 'W', 'W'], 70], [1760, 1895, 'W']]], [[[174, 182, ['W', 'B', 'B'], 5], [1740, 1830, 'W']], [[179, 189, [], 60], [1790, 1950, 'W']], [[172, 174, [], 5], [1720, 1745, 'W']], [[177, 171, ['W'], 70], [1770, 1785, 'W']], [[179, 182, ['B'], 0], [1795, 1820, 'W']], [[182, 174, ['B', 'B'], 70], [1825, 1810, 'B']], [[173, 172, [], 70], [1730, 1790, 'W']], [[179, 175, ['W', 'W', 'B'], 60], [1790, 1815, 'W']]], [[[178, 182, ['B', 'B'], 5], [1785, 1825, 'W']], [[177, 171, ['B'], 60], [1775, 1770, 'B']], [[175, 176, ['B'], 5], [1755, 1765, 'W']], [[182, 185, ['B', 'W'], 60], [1825, 1910, 'W']], [[179, 175, ['W', 'W', 'B'], 60], [1790, 1815, 'W']], [[181, 180, ['B', 'B'], 70], [1815, 1870, 'W']], [[171, 191, [], 70], [1710, 1980, 'W']], [[173, 177, ['W', 'W'], 70], [1730, 1845, 'W']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("button case %d" % i, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
button case 0[1860, 1730, 'B'][1860, 1735, 'B']Failed
button case 1[1710, 1860, 'W'][1710, 1865, 'W']Failed
button case 2[1860, 1870, 'W'][1865, 1870, 'W']Failed
button case 3[1870, 1845, 'B'][1870, 1845, 'B']Passed
button case 4[1780, 1890, 'W'][1780, 1895, 'W']Failed
button case 5[1790, 1915, 'W'][1790, 1915, 'W']Passed
button case 6[1740, 1825, 'W'][1740, 1830, 'W']Failed
button case 7[1875, 1810, 'B'][1875, 1810, 'B']Passed

SHA-256 / b1659303ebc1e34b52bf567ce9762a6d2fd6b3a8b449735d5eb4267c8202e1a6

3 / The verified repair

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

N = 1
observations = []
def solve(x):
    ab, aw, passes, komi = x
    sb = ab * 10
    sw = aw * 10 + komi
    if passes:
        if passes[0] == 'B':
            sb += 5
        else:
            sw += 5
    winner = 'B' if sb > sw else 'W' if sw > sb else 'draw'
    return [sb, sw, winner]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[186, 173, ['W', 'W'], 0], [1860, 1735, 'B']], [[171, 180, ['W', 'B', 'B'], 60], [1710, 1865, 'W']], [[186, 187, ['B', 'W'], 0], [1865, 1870, 'W']], [[187, 178, ['W'], 60], [1870, 1845, 'B']], [[178, 183, ['W', 'W', 'W'], 60], [1780, 1895, 'W']], [[179, 185, ['W'], 60], [1790, 1915, 'W']], [[174, 182, ['W', 'B', 'B'], 5], [1740, 1830, 'W']], [[187, 175, ['B'], 60], [1875, 1810, 'B']]], [[[180, 171, ['W', 'B', 'W'], 0], [1800, 1715, 'B']], [[186, 183, [], 60], [1860, 1890, 'W']], [[191, 181, ['B', 'W', 'W'], 0], [1915, 1810, 'B']], [[186, 178, ['W', 'B'], 5], [1860, 1790, 'B']], [[187, 185, ['W'], 70], [1870, 1925, 'W']], [[178, 182, ['B', 'B'], 5], [1785, 1825, 'W']], [[176, 188, ['W', 'W'], 5], [1760, 1890, 'W']], [[171, 181, ['W', 'W'], 60], [1710, 1875, 'W']]], [[[171, 180, ['W', 'B', 'B'], 60], [1710, 1865, 'W']], [[171, 190, ['W', 'W'], 0], [1710, 1905, 'W']], [[175, 191, [], 5], [1750, 1915, 'W']], [[186, 183, ['W', 'W', 'W'], 5], [1860, 1840, 'B']], [[170, 181, [], 0], [1700, 1810, 'W']], [[179, 175, ['W'], 60], [1790, 1815, 'W']], [[190, 180, ['B', 'W', 'W'], 70], [1905, 1870, 'B']], [[176, 182, ['W', 'W', 'W'], 70], [1760, 1895, 'W']]], [[[174, 182, ['W', 'B', 'B'], 5], [1740, 1830, 'W']], [[179, 189, [], 60], [1790, 1950, 'W']], [[172, 174, [], 5], [1720, 1745, 'W']], [[177, 171, ['W'], 70], [1770, 1785, 'W']], [[179, 182, ['B'], 0], [1795, 1820, 'W']], [[182, 174, ['B', 'B'], 70], [1825, 1810, 'B']], [[173, 172, [], 70], [1730, 1790, 'W']], [[179, 175, ['W', 'W', 'B'], 60], [1790, 1815, 'W']]], [[[178, 182, ['B', 'B'], 5], [1785, 1825, 'W']], [[177, 171, ['B'], 60], [1775, 1770, 'B']], [[175, 176, ['B'], 5], [1755, 1765, 'W']], [[182, 185, ['B', 'W'], 60], [1825, 1910, 'W']], [[179, 175, ['W', 'W', 'B'], 60], [1790, 1815, 'W']], [[181, 180, ['B', 'B'], 70], [1815, 1870, 'W']], [[171, 191, [], 70], [1710, 1980, 'W']], [[173, 177, ['W', 'W'], 70], [1730, 1845, 'W']]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("button case %d" % i, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
button case 0[1860, 1735, 'B'][1860, 1735, 'B']Passed
button case 1[1710, 1865, 'W'][1710, 1865, 'W']Passed
button case 2[1865, 1870, 'W'][1865, 1870, 'W']Passed
button case 3[1870, 1845, 'B'][1870, 1845, 'B']Passed
button case 4[1780, 1895, 'W'][1780, 1895, 'W']Passed
button case 5[1790, 1915, 'W'][1790, 1915, 'W']Passed
button case 6[1740, 1830, 'W'][1740, 1830, 'W']Passed
button case 7[1875, 1810, 'B'][1875, 1810, 'B']Passed

SHA-256 / b714fc76df6e678ef844a274f15c027a87b453b0c78c8dcd59012b88743ac2fb

Verification & scope

Small rectangular toy boards given as strings of B, W and dot; a bounded teaching model of one scoring or bookkeeping rule, not a complete rules engine or server implementation. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:50:19.368114+00:00.

Case digest / 66e5785dec6d55e81331cbd2fc1108e10237bf637c51ec037263cb20b93098c0