FAILURE MAP
← Case archive

FA-82591 / Chess move legality / Open access

Exhausted castling rights rendered as an empty field · case 01

After the last right is lost, the rights field is "" instead of "-".

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

ROOT CAUSE

The empty string is returned as-is.

VERIFIED REPAIR

Render an empty rights set as "-".

Unsuccessful approach: Checking the incoming rights string misses rights emptied by this move.

Case contract

Input: {"board" (before the move), "rights": castling rights string or "-", "move": [from, to], "halfmove"}. Return the next {"rights", "ep", "halfmove"}: a king move removes both of its side's rights; any move from or onto h1/a1/h8/a8 removes the matching right; a pawn double step sets ep to the skipped square only when an enemy pawn stands beside the destination; the halfmove clock resets on pawn moves and captures, else increments. Empty rights render as "-".

Why this case matters

These updates decide whether castling and en passant are legal on later moves.

1 / The failure

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

N = 1
observations = []
def solve(x):
    b=x['board']; fr,to=x['move']; p=b[fr]; cap=b.get(to)
    rights=x['rights'].replace('-','')
    if p=='K': rights=rights.replace('K','').replace('Q','')
    if p=='k': rights=rights.replace('k','').replace('q','')
    for sq,r in (('h1','K'),('a1','Q'),('h8','k'),('a8','q')):
        if fr==sq or to==sq: rights=rights.replace(r,'')
    ep=None
    if p in ('P','p') and abs(int(to[1])-int(fr[1]))==2:
        enemy='p' if p=='P' else 'P'
        f=ord(to[0])-97
        if any(b.get(chr(97+f+d)+to[1])==enemy for d in (-1,1)):
            ep=fr[0]+str((int(fr[1])+int(to[1]))//2)
    pawn_or_capture=p in ('P','p') or cap is not None
    hm=0 if pawn_or_capture else x['halfmove']+1
    return {'rights':rights,'ep':ep,'halfmove':hm}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('king move clears both',
   {'board': {'a1': 'R', 'e1': 'K', 'e8': 'k', 'h1': 'R'},
    'halfmove': 3,
    'move': ['e1', 'f1'],
    'rights': 'KQkq'},
   {'ep': None, 'halfmove': 4, 'rights': 'kq'}),
  ('black king move',
   {'board': {'e1': 'K', 'e8': 'k'}, 'halfmove': 0, 'move': ['e8', 'd8'], 'rights': 'KQkq'},
   {'ep': None, 'halfmove': 1, 'rights': 'KQ'}),
  ('rook captured on a8',
   {'board': {'a8': 'r', 'b7': 'B', 'e1': 'K', 'e8': 'k'},
    'halfmove': 5,
    'move': ['b7', 'a8'],
    'rights': 'Kkq'},
   {'ep': None, 'halfmove': 0, 'rights': 'Kk'}),
  ('bishop takes h8 rook',
   {'board': {'a1': 'B', 'e1': 'K', 'e8': 'k', 'h8': 'r'},
    'halfmove': 5,
    'move': ['a1', 'h8'],
    'rights': 'KQk'},
   {'ep': None, 'halfmove': 0, 'rights': 'K'}),
  ('rook leaves corner',
   {'board': {'a1': 'R', 'e1': 'K', 'e8': 'k'},
    'halfmove': 9,
    'move': ['a1', 'a5'],
    'rights': 'KQ'},
   {'ep': None, 'halfmove': 10, 'rights': 'K'}),
  ('double step with adjacent enemy',
   {'board': {'d4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': 'e3', 'halfmove': 0, 'rights': '-'}),
  ('double step no enemy beside',
   {'board': {'a4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('black double step',
   {'board': {'b5': 'P', 'c7': 'p', 'e1': 'K', 'e8': 'k'},
    'halfmove': 2,
    'move': ['c7', 'c5'],
    'rights': 'kq'},
   {'ep': 'c6', 'halfmove': 0, 'rights': 'kq'})],
 [('bishop takes h8 rook',
   {'board': {'a1': 'B', 'e1': 'K', 'e8': 'k', 'h8': 'r'},
    'halfmove': 5,
    'move': ['a1', 'h8'],
    'rights': 'KQk'},
   {'ep': None, 'halfmove': 0, 'rights': 'K'}),
  ('rook leaves corner',
   {'board': {'a1': 'R', 'e1': 'K', 'e8': 'k'},
    'halfmove': 9,
    'move': ['a1', 'a5'],
    'rights': 'KQ'},
   {'ep': None, 'halfmove': 10, 'rights': 'K'}),
  ('double step no enemy beside',
   {'board': {'a4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('double step beside own pawn',
   {'board': {'e1': 'K', 'e2': 'P', 'e8': 'k', 'f4': 'P'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('black double step',
   {'board': {'b5': 'P', 'c7': 'p', 'e1': 'K', 'e8': 'k'},
    'halfmove': 2,
    'move': ['c7', 'c5'],
    'rights': 'kq'},
   {'ep': 'c6', 'halfmove': 0, 'rights': 'kq'}),
  ('black double step beside black pawn',
   {'board': {'c7': 'p', 'd5': 'p', 'e1': 'K', 'e8': 'k'},
    'halfmove': 2,
    'move': ['c7', 'c5'],
    'rights': 'kq'},
   {'ep': None, 'halfmove': 0, 'rights': 'kq'}),
  ('quiet knight move',
   {'board': {'e1': 'K', 'e8': 'k', 'g1': 'N'}, 'halfmove': 7, 'move': ['g1', 'f3'], 'rights': 'K'},
   {'ep': None, 'halfmove': 8, 'rights': 'K'}),
  ('knight capture resets',
   {'board': {'e1': 'K', 'e8': 'k', 'f3': 'p', 'g1': 'N'},
    'halfmove': 7,
    'move': ['g1', 'f3'],
    'rights': 'K'},
   {'ep': None, 'halfmove': 0, 'rights': 'K'})],
 [('double step with adjacent enemy',
   {'board': {'d4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': 'e3', 'halfmove': 0, 'rights': '-'}),
  ('double step no enemy beside',
   {'board': {'a4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('double step beside own pawn',
   {'board': {'e1': 'K', 'e2': 'P', 'e8': 'k', 'f4': 'P'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('black double step beside black pawn',
   {'board': {'c7': 'p', 'd5': 'p', 'e1': 'K', 'e8': 'k'},
    'halfmove': 2,
    'move': ['c7', 'c5'],
    'rights': 'kq'},
   {'ep': None, 'halfmove': 0, 'rights': 'kq'}),
  ('quiet knight move',
   {'board': {'e1': 'K', 'e8': 'k', 'g1': 'N'}, 'halfmove': 7, 'move': ['g1', 'f3'], 'rights': 'K'},
   {'ep': None, 'halfmove': 8, 'rights': 'K'}),
  ('knight capture resets',
   {'board': {'e1': 'K', 'e8': 'k', 'f3': 'p', 'g1': 'N'},
    'halfmove': 7,
    'move': ['g1', 'f3'],
    'rights': 'K'},
   {'ep': None, 'halfmove': 0, 'rights': 'K'}),
  ('single pawn step',
   {'board': {'a2': 'P', 'e1': 'K', 'e8': 'k'},
    'halfmove': 11,
    'move': ['a2', 'a3'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('queen two-rank move',
   {'board': {'c4': 'P', 'd6': 'q', 'e1': 'K', 'e8': 'k'},
    'halfmove': 6,
    'move': ['d6', 'd4'],
    'rights': 'k'},
   {'ep': None, 'halfmove': 7, 'rights': 'k'})],
 [('king move clears both',
   {'board': {'a1': 'R', 'e1': 'K', 'e8': 'k', 'h1': 'R'},
    'halfmove': 3,
    'move': ['e1', 'f1'],
    'rights': 'KQkq'},
   {'ep': None, 'halfmove': 4, 'rights': 'kq'}),
  ('black king move',
   {'board': {'e1': 'K', 'e8': 'k'}, 'halfmove': 0, 'move': ['e8', 'd8'], 'rights': 'KQkq'},
   {'ep': None, 'halfmove': 1, 'rights': 'KQ'}),
  ('double step with adjacent enemy',
   {'board': {'d4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': 'e3', 'halfmove': 0, 'rights': '-'}),
  ('double step no enemy beside',
   {'board': {'a4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('double step beside own pawn',
   {'board': {'e1': 'K', 'e2': 'P', 'e8': 'k', 'f4': 'P'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('single pawn step',
   {'board': {'a2': 'P', 'e1': 'K', 'e8': 'k'},
    'halfmove': 11,
    'move': ['a2', 'a3'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('rook two-rank move',
   {'board': {'c3': 'p', 'd1': 'R', 'e1': 'K', 'e8': 'k'},
    'halfmove': 1,
    'move': ['d1', 'd3'],
    'rights': '-'},
   {'ep': None, 'halfmove': 2, 'rights': '-'}),
  ('queen two-rank move',
   {'board': {'c4': 'P', 'd6': 'q', 'e1': 'K', 'e8': 'k'},
    'halfmove': 6,
    'move': ['d6', 'd4'],
    'rights': 'k'},
   {'ep': None, 'halfmove': 7, 'rights': 'k'})],
 [('king move clears both',
   {'board': {'a1': 'R', 'e1': 'K', 'e8': 'k', 'h1': 'R'},
    'halfmove': 3,
    'move': ['e1', 'f1'],
    'rights': 'KQkq'},
   {'ep': None, 'halfmove': 4, 'rights': 'kq'}),
  ('black king move',
   {'board': {'e1': 'K', 'e8': 'k'}, 'halfmove': 0, 'move': ['e8', 'd8'], 'rights': 'KQkq'},
   {'ep': None, 'halfmove': 1, 'rights': 'KQ'}),
  ('rook captured on a8',
   {'board': {'a8': 'r', 'b7': 'B', 'e1': 'K', 'e8': 'k'},
    'halfmove': 5,
    'move': ['b7', 'a8'],
    'rights': 'Kkq'},
   {'ep': None, 'halfmove': 0, 'rights': 'Kk'}),
  ('bishop takes h8 rook',
   {'board': {'a1': 'B', 'e1': 'K', 'e8': 'k', 'h8': 'r'},
    'halfmove': 5,
    'move': ['a1', 'h8'],
    'rights': 'KQk'},
   {'ep': None, 'halfmove': 0, 'rights': 'K'}),
  ('double step with adjacent enemy',
   {'board': {'d4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': 'e3', 'halfmove': 0, 'rights': '-'}),
  ('double step beside own pawn',
   {'board': {'e1': 'K', 'e2': 'P', 'e8': 'k', 'f4': 'P'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('single pawn step',
   {'board': {'a2': 'P', 'e1': 'K', 'e8': 'k'},
    'halfmove': 11,
    'move': ['a2', 'a3'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('rook two-rank move',
   {'board': {'c3': 'p', 'd1': 'R', 'e1': 'K', 'e8': 'k'},
    'halfmove': 1,
    'move': ['d1', 'd3'],
    'rights': '-'},
   {'ep': None, 'halfmove': 2, 'rights': '-'})]]
for label, args, expected in fixtures[N-1]:
    try:
        actual = solve(args)
    except Exception as exc:
        actual = 'error:' + type(exc).__name__
    check(label, actual, 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
king move clears both{'ep': None, 'halfmove': 4, 'rights': 'kq'}{'ep': None, 'halfmove': 4, 'rights': 'kq'}Passed
black king move{'ep': None, 'halfmove': 1, 'rights': 'KQ'}{'ep': None, 'halfmove': 1, 'rights': 'KQ'}Passed
rook captured on a8{'ep': None, 'halfmove': 0, 'rights': 'Kk'}{'ep': None, 'halfmove': 0, 'rights': 'Kk'}Passed
bishop takes h8 rook{'ep': None, 'halfmove': 0, 'rights': 'K'}{'ep': None, 'halfmove': 0, 'rights': 'K'}Passed
rook leaves corner{'ep': None, 'halfmove': 10, 'rights': 'K'}{'ep': None, 'halfmove': 10, 'rights': 'K'}Passed
double step with adjacent enemy{'ep': 'e3', 'halfmove': 0, 'rights': ''}{'ep': 'e3', 'halfmove': 0, 'rights': '-'}Failed
double step no enemy beside{'ep': None, 'halfmove': 0, 'rights': ''}{'ep': None, 'halfmove': 0, 'rights': '-'}Failed
black double step{'ep': 'c6', 'halfmove': 0, 'rights': 'kq'}{'ep': 'c6', 'halfmove': 0, 'rights': 'kq'}Passed

SHA-256 / 9139a77423327ac1e85e6cd9bae2060bb45a8a9566e10be6a24c957b6af6853d

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(x):
    b=x['board']; fr,to=x['move']; p=b[fr]; cap=b.get(to)
    rights=x['rights'].replace('-','')
    if p=='K': rights=rights.replace('K','').replace('Q','')
    if p=='k': rights=rights.replace('k','').replace('q','')
    for sq,r in (('h1','K'),('a1','Q'),('h8','k'),('a8','q')):
        if fr==sq or to==sq: rights=rights.replace(r,'')
    ep=None
    if p in ('P','p') and abs(int(to[1])-int(fr[1]))==2:
        enemy='p' if p=='P' else 'P'
        f=ord(to[0])-97
        if any(b.get(chr(97+f+d)+to[1])==enemy for d in (-1,1)):
            ep=fr[0]+str((int(fr[1])+int(to[1]))//2)
    pawn_or_capture=p in ('P','p') or cap is not None
    hm=0 if pawn_or_capture else x['halfmove']+1
    return {'rights':'-' if not x['rights'] else rights,'ep':ep,'halfmove':hm}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('king move clears both',
   {'board': {'a1': 'R', 'e1': 'K', 'e8': 'k', 'h1': 'R'},
    'halfmove': 3,
    'move': ['e1', 'f1'],
    'rights': 'KQkq'},
   {'ep': None, 'halfmove': 4, 'rights': 'kq'}),
  ('black king move',
   {'board': {'e1': 'K', 'e8': 'k'}, 'halfmove': 0, 'move': ['e8', 'd8'], 'rights': 'KQkq'},
   {'ep': None, 'halfmove': 1, 'rights': 'KQ'}),
  ('rook captured on a8',
   {'board': {'a8': 'r', 'b7': 'B', 'e1': 'K', 'e8': 'k'},
    'halfmove': 5,
    'move': ['b7', 'a8'],
    'rights': 'Kkq'},
   {'ep': None, 'halfmove': 0, 'rights': 'Kk'}),
  ('bishop takes h8 rook',
   {'board': {'a1': 'B', 'e1': 'K', 'e8': 'k', 'h8': 'r'},
    'halfmove': 5,
    'move': ['a1', 'h8'],
    'rights': 'KQk'},
   {'ep': None, 'halfmove': 0, 'rights': 'K'}),
  ('rook leaves corner',
   {'board': {'a1': 'R', 'e1': 'K', 'e8': 'k'},
    'halfmove': 9,
    'move': ['a1', 'a5'],
    'rights': 'KQ'},
   {'ep': None, 'halfmove': 10, 'rights': 'K'}),
  ('double step with adjacent enemy',
   {'board': {'d4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': 'e3', 'halfmove': 0, 'rights': '-'}),
  ('double step no enemy beside',
   {'board': {'a4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('black double step',
   {'board': {'b5': 'P', 'c7': 'p', 'e1': 'K', 'e8': 'k'},
    'halfmove': 2,
    'move': ['c7', 'c5'],
    'rights': 'kq'},
   {'ep': 'c6', 'halfmove': 0, 'rights': 'kq'})],
 [('bishop takes h8 rook',
   {'board': {'a1': 'B', 'e1': 'K', 'e8': 'k', 'h8': 'r'},
    'halfmove': 5,
    'move': ['a1', 'h8'],
    'rights': 'KQk'},
   {'ep': None, 'halfmove': 0, 'rights': 'K'}),
  ('rook leaves corner',
   {'board': {'a1': 'R', 'e1': 'K', 'e8': 'k'},
    'halfmove': 9,
    'move': ['a1', 'a5'],
    'rights': 'KQ'},
   {'ep': None, 'halfmove': 10, 'rights': 'K'}),
  ('double step no enemy beside',
   {'board': {'a4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('double step beside own pawn',
   {'board': {'e1': 'K', 'e2': 'P', 'e8': 'k', 'f4': 'P'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('black double step',
   {'board': {'b5': 'P', 'c7': 'p', 'e1': 'K', 'e8': 'k'},
    'halfmove': 2,
    'move': ['c7', 'c5'],
    'rights': 'kq'},
   {'ep': 'c6', 'halfmove': 0, 'rights': 'kq'}),
  ('black double step beside black pawn',
   {'board': {'c7': 'p', 'd5': 'p', 'e1': 'K', 'e8': 'k'},
    'halfmove': 2,
    'move': ['c7', 'c5'],
    'rights': 'kq'},
   {'ep': None, 'halfmove': 0, 'rights': 'kq'}),
  ('quiet knight move',
   {'board': {'e1': 'K', 'e8': 'k', 'g1': 'N'}, 'halfmove': 7, 'move': ['g1', 'f3'], 'rights': 'K'},
   {'ep': None, 'halfmove': 8, 'rights': 'K'}),
  ('knight capture resets',
   {'board': {'e1': 'K', 'e8': 'k', 'f3': 'p', 'g1': 'N'},
    'halfmove': 7,
    'move': ['g1', 'f3'],
    'rights': 'K'},
   {'ep': None, 'halfmove': 0, 'rights': 'K'})],
 [('double step with adjacent enemy',
   {'board': {'d4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': 'e3', 'halfmove': 0, 'rights': '-'}),
  ('double step no enemy beside',
   {'board': {'a4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('double step beside own pawn',
   {'board': {'e1': 'K', 'e2': 'P', 'e8': 'k', 'f4': 'P'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('black double step beside black pawn',
   {'board': {'c7': 'p', 'd5': 'p', 'e1': 'K', 'e8': 'k'},
    'halfmove': 2,
    'move': ['c7', 'c5'],
    'rights': 'kq'},
   {'ep': None, 'halfmove': 0, 'rights': 'kq'}),
  ('quiet knight move',
   {'board': {'e1': 'K', 'e8': 'k', 'g1': 'N'}, 'halfmove': 7, 'move': ['g1', 'f3'], 'rights': 'K'},
   {'ep': None, 'halfmove': 8, 'rights': 'K'}),
  ('knight capture resets',
   {'board': {'e1': 'K', 'e8': 'k', 'f3': 'p', 'g1': 'N'},
    'halfmove': 7,
    'move': ['g1', 'f3'],
    'rights': 'K'},
   {'ep': None, 'halfmove': 0, 'rights': 'K'}),
  ('single pawn step',
   {'board': {'a2': 'P', 'e1': 'K', 'e8': 'k'},
    'halfmove': 11,
    'move': ['a2', 'a3'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('queen two-rank move',
   {'board': {'c4': 'P', 'd6': 'q', 'e1': 'K', 'e8': 'k'},
    'halfmove': 6,
    'move': ['d6', 'd4'],
    'rights': 'k'},
   {'ep': None, 'halfmove': 7, 'rights': 'k'})],
 [('king move clears both',
   {'board': {'a1': 'R', 'e1': 'K', 'e8': 'k', 'h1': 'R'},
    'halfmove': 3,
    'move': ['e1', 'f1'],
    'rights': 'KQkq'},
   {'ep': None, 'halfmove': 4, 'rights': 'kq'}),
  ('black king move',
   {'board': {'e1': 'K', 'e8': 'k'}, 'halfmove': 0, 'move': ['e8', 'd8'], 'rights': 'KQkq'},
   {'ep': None, 'halfmove': 1, 'rights': 'KQ'}),
  ('double step with adjacent enemy',
   {'board': {'d4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': 'e3', 'halfmove': 0, 'rights': '-'}),
  ('double step no enemy beside',
   {'board': {'a4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('double step beside own pawn',
   {'board': {'e1': 'K', 'e2': 'P', 'e8': 'k', 'f4': 'P'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('single pawn step',
   {'board': {'a2': 'P', 'e1': 'K', 'e8': 'k'},
    'halfmove': 11,
    'move': ['a2', 'a3'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('rook two-rank move',
   {'board': {'c3': 'p', 'd1': 'R', 'e1': 'K', 'e8': 'k'},
    'halfmove': 1,
    'move': ['d1', 'd3'],
    'rights': '-'},
   {'ep': None, 'halfmove': 2, 'rights': '-'}),
  ('queen two-rank move',
   {'board': {'c4': 'P', 'd6': 'q', 'e1': 'K', 'e8': 'k'},
    'halfmove': 6,
    'move': ['d6', 'd4'],
    'rights': 'k'},
   {'ep': None, 'halfmove': 7, 'rights': 'k'})],
 [('king move clears both',
   {'board': {'a1': 'R', 'e1': 'K', 'e8': 'k', 'h1': 'R'},
    'halfmove': 3,
    'move': ['e1', 'f1'],
    'rights': 'KQkq'},
   {'ep': None, 'halfmove': 4, 'rights': 'kq'}),
  ('black king move',
   {'board': {'e1': 'K', 'e8': 'k'}, 'halfmove': 0, 'move': ['e8', 'd8'], 'rights': 'KQkq'},
   {'ep': None, 'halfmove': 1, 'rights': 'KQ'}),
  ('rook captured on a8',
   {'board': {'a8': 'r', 'b7': 'B', 'e1': 'K', 'e8': 'k'},
    'halfmove': 5,
    'move': ['b7', 'a8'],
    'rights': 'Kkq'},
   {'ep': None, 'halfmove': 0, 'rights': 'Kk'}),
  ('bishop takes h8 rook',
   {'board': {'a1': 'B', 'e1': 'K', 'e8': 'k', 'h8': 'r'},
    'halfmove': 5,
    'move': ['a1', 'h8'],
    'rights': 'KQk'},
   {'ep': None, 'halfmove': 0, 'rights': 'K'}),
  ('double step with adjacent enemy',
   {'board': {'d4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': 'e3', 'halfmove': 0, 'rights': '-'}),
  ('double step beside own pawn',
   {'board': {'e1': 'K', 'e2': 'P', 'e8': 'k', 'f4': 'P'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('single pawn step',
   {'board': {'a2': 'P', 'e1': 'K', 'e8': 'k'},
    'halfmove': 11,
    'move': ['a2', 'a3'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('rook two-rank move',
   {'board': {'c3': 'p', 'd1': 'R', 'e1': 'K', 'e8': 'k'},
    'halfmove': 1,
    'move': ['d1', 'd3'],
    'rights': '-'},
   {'ep': None, 'halfmove': 2, 'rights': '-'})]]
for label, args, expected in fixtures[N-1]:
    try:
        actual = solve(args)
    except Exception as exc:
        actual = 'error:' + type(exc).__name__
    check(label, actual, 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
king move clears both{'ep': None, 'halfmove': 4, 'rights': 'kq'}{'ep': None, 'halfmove': 4, 'rights': 'kq'}Passed
black king move{'ep': None, 'halfmove': 1, 'rights': 'KQ'}{'ep': None, 'halfmove': 1, 'rights': 'KQ'}Passed
rook captured on a8{'ep': None, 'halfmove': 0, 'rights': 'Kk'}{'ep': None, 'halfmove': 0, 'rights': 'Kk'}Passed
bishop takes h8 rook{'ep': None, 'halfmove': 0, 'rights': 'K'}{'ep': None, 'halfmove': 0, 'rights': 'K'}Passed
rook leaves corner{'ep': None, 'halfmove': 10, 'rights': 'K'}{'ep': None, 'halfmove': 10, 'rights': 'K'}Passed
double step with adjacent enemy{'ep': 'e3', 'halfmove': 0, 'rights': ''}{'ep': 'e3', 'halfmove': 0, 'rights': '-'}Failed
double step no enemy beside{'ep': None, 'halfmove': 0, 'rights': ''}{'ep': None, 'halfmove': 0, 'rights': '-'}Failed
black double step{'ep': 'c6', 'halfmove': 0, 'rights': 'kq'}{'ep': 'c6', 'halfmove': 0, 'rights': 'kq'}Passed

SHA-256 / 2523ed62020609355e601f8d82c1ccf4557886304777c1cfb06008945240c2b2

3 / The verified repair

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

N = 1
observations = []
def solve(x):
    b=x['board']; fr,to=x['move']; p=b[fr]; cap=b.get(to)
    rights=x['rights'].replace('-','')
    if p=='K': rights=rights.replace('K','').replace('Q','')
    if p=='k': rights=rights.replace('k','').replace('q','')
    for sq,r in (('h1','K'),('a1','Q'),('h8','k'),('a8','q')):
        if fr==sq or to==sq: rights=rights.replace(r,'')
    ep=None
    if p in ('P','p') and abs(int(to[1])-int(fr[1]))==2:
        enemy='p' if p=='P' else 'P'
        f=ord(to[0])-97
        if any(b.get(chr(97+f+d)+to[1])==enemy for d in (-1,1)):
            ep=fr[0]+str((int(fr[1])+int(to[1]))//2)
    pawn_or_capture=p in ('P','p') or cap is not None
    hm=0 if pawn_or_capture else x['halfmove']+1
    return {'rights':rights or '-','ep':ep,'halfmove':hm}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('king move clears both',
   {'board': {'a1': 'R', 'e1': 'K', 'e8': 'k', 'h1': 'R'},
    'halfmove': 3,
    'move': ['e1', 'f1'],
    'rights': 'KQkq'},
   {'ep': None, 'halfmove': 4, 'rights': 'kq'}),
  ('black king move',
   {'board': {'e1': 'K', 'e8': 'k'}, 'halfmove': 0, 'move': ['e8', 'd8'], 'rights': 'KQkq'},
   {'ep': None, 'halfmove': 1, 'rights': 'KQ'}),
  ('rook captured on a8',
   {'board': {'a8': 'r', 'b7': 'B', 'e1': 'K', 'e8': 'k'},
    'halfmove': 5,
    'move': ['b7', 'a8'],
    'rights': 'Kkq'},
   {'ep': None, 'halfmove': 0, 'rights': 'Kk'}),
  ('bishop takes h8 rook',
   {'board': {'a1': 'B', 'e1': 'K', 'e8': 'k', 'h8': 'r'},
    'halfmove': 5,
    'move': ['a1', 'h8'],
    'rights': 'KQk'},
   {'ep': None, 'halfmove': 0, 'rights': 'K'}),
  ('rook leaves corner',
   {'board': {'a1': 'R', 'e1': 'K', 'e8': 'k'},
    'halfmove': 9,
    'move': ['a1', 'a5'],
    'rights': 'KQ'},
   {'ep': None, 'halfmove': 10, 'rights': 'K'}),
  ('double step with adjacent enemy',
   {'board': {'d4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': 'e3', 'halfmove': 0, 'rights': '-'}),
  ('double step no enemy beside',
   {'board': {'a4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('black double step',
   {'board': {'b5': 'P', 'c7': 'p', 'e1': 'K', 'e8': 'k'},
    'halfmove': 2,
    'move': ['c7', 'c5'],
    'rights': 'kq'},
   {'ep': 'c6', 'halfmove': 0, 'rights': 'kq'})],
 [('bishop takes h8 rook',
   {'board': {'a1': 'B', 'e1': 'K', 'e8': 'k', 'h8': 'r'},
    'halfmove': 5,
    'move': ['a1', 'h8'],
    'rights': 'KQk'},
   {'ep': None, 'halfmove': 0, 'rights': 'K'}),
  ('rook leaves corner',
   {'board': {'a1': 'R', 'e1': 'K', 'e8': 'k'},
    'halfmove': 9,
    'move': ['a1', 'a5'],
    'rights': 'KQ'},
   {'ep': None, 'halfmove': 10, 'rights': 'K'}),
  ('double step no enemy beside',
   {'board': {'a4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('double step beside own pawn',
   {'board': {'e1': 'K', 'e2': 'P', 'e8': 'k', 'f4': 'P'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('black double step',
   {'board': {'b5': 'P', 'c7': 'p', 'e1': 'K', 'e8': 'k'},
    'halfmove': 2,
    'move': ['c7', 'c5'],
    'rights': 'kq'},
   {'ep': 'c6', 'halfmove': 0, 'rights': 'kq'}),
  ('black double step beside black pawn',
   {'board': {'c7': 'p', 'd5': 'p', 'e1': 'K', 'e8': 'k'},
    'halfmove': 2,
    'move': ['c7', 'c5'],
    'rights': 'kq'},
   {'ep': None, 'halfmove': 0, 'rights': 'kq'}),
  ('quiet knight move',
   {'board': {'e1': 'K', 'e8': 'k', 'g1': 'N'}, 'halfmove': 7, 'move': ['g1', 'f3'], 'rights': 'K'},
   {'ep': None, 'halfmove': 8, 'rights': 'K'}),
  ('knight capture resets',
   {'board': {'e1': 'K', 'e8': 'k', 'f3': 'p', 'g1': 'N'},
    'halfmove': 7,
    'move': ['g1', 'f3'],
    'rights': 'K'},
   {'ep': None, 'halfmove': 0, 'rights': 'K'})],
 [('double step with adjacent enemy',
   {'board': {'d4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': 'e3', 'halfmove': 0, 'rights': '-'}),
  ('double step no enemy beside',
   {'board': {'a4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('double step beside own pawn',
   {'board': {'e1': 'K', 'e2': 'P', 'e8': 'k', 'f4': 'P'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('black double step beside black pawn',
   {'board': {'c7': 'p', 'd5': 'p', 'e1': 'K', 'e8': 'k'},
    'halfmove': 2,
    'move': ['c7', 'c5'],
    'rights': 'kq'},
   {'ep': None, 'halfmove': 0, 'rights': 'kq'}),
  ('quiet knight move',
   {'board': {'e1': 'K', 'e8': 'k', 'g1': 'N'}, 'halfmove': 7, 'move': ['g1', 'f3'], 'rights': 'K'},
   {'ep': None, 'halfmove': 8, 'rights': 'K'}),
  ('knight capture resets',
   {'board': {'e1': 'K', 'e8': 'k', 'f3': 'p', 'g1': 'N'},
    'halfmove': 7,
    'move': ['g1', 'f3'],
    'rights': 'K'},
   {'ep': None, 'halfmove': 0, 'rights': 'K'}),
  ('single pawn step',
   {'board': {'a2': 'P', 'e1': 'K', 'e8': 'k'},
    'halfmove': 11,
    'move': ['a2', 'a3'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('queen two-rank move',
   {'board': {'c4': 'P', 'd6': 'q', 'e1': 'K', 'e8': 'k'},
    'halfmove': 6,
    'move': ['d6', 'd4'],
    'rights': 'k'},
   {'ep': None, 'halfmove': 7, 'rights': 'k'})],
 [('king move clears both',
   {'board': {'a1': 'R', 'e1': 'K', 'e8': 'k', 'h1': 'R'},
    'halfmove': 3,
    'move': ['e1', 'f1'],
    'rights': 'KQkq'},
   {'ep': None, 'halfmove': 4, 'rights': 'kq'}),
  ('black king move',
   {'board': {'e1': 'K', 'e8': 'k'}, 'halfmove': 0, 'move': ['e8', 'd8'], 'rights': 'KQkq'},
   {'ep': None, 'halfmove': 1, 'rights': 'KQ'}),
  ('double step with adjacent enemy',
   {'board': {'d4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': 'e3', 'halfmove': 0, 'rights': '-'}),
  ('double step no enemy beside',
   {'board': {'a4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('double step beside own pawn',
   {'board': {'e1': 'K', 'e2': 'P', 'e8': 'k', 'f4': 'P'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('single pawn step',
   {'board': {'a2': 'P', 'e1': 'K', 'e8': 'k'},
    'halfmove': 11,
    'move': ['a2', 'a3'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('rook two-rank move',
   {'board': {'c3': 'p', 'd1': 'R', 'e1': 'K', 'e8': 'k'},
    'halfmove': 1,
    'move': ['d1', 'd3'],
    'rights': '-'},
   {'ep': None, 'halfmove': 2, 'rights': '-'}),
  ('queen two-rank move',
   {'board': {'c4': 'P', 'd6': 'q', 'e1': 'K', 'e8': 'k'},
    'halfmove': 6,
    'move': ['d6', 'd4'],
    'rights': 'k'},
   {'ep': None, 'halfmove': 7, 'rights': 'k'})],
 [('king move clears both',
   {'board': {'a1': 'R', 'e1': 'K', 'e8': 'k', 'h1': 'R'},
    'halfmove': 3,
    'move': ['e1', 'f1'],
    'rights': 'KQkq'},
   {'ep': None, 'halfmove': 4, 'rights': 'kq'}),
  ('black king move',
   {'board': {'e1': 'K', 'e8': 'k'}, 'halfmove': 0, 'move': ['e8', 'd8'], 'rights': 'KQkq'},
   {'ep': None, 'halfmove': 1, 'rights': 'KQ'}),
  ('rook captured on a8',
   {'board': {'a8': 'r', 'b7': 'B', 'e1': 'K', 'e8': 'k'},
    'halfmove': 5,
    'move': ['b7', 'a8'],
    'rights': 'Kkq'},
   {'ep': None, 'halfmove': 0, 'rights': 'Kk'}),
  ('bishop takes h8 rook',
   {'board': {'a1': 'B', 'e1': 'K', 'e8': 'k', 'h8': 'r'},
    'halfmove': 5,
    'move': ['a1', 'h8'],
    'rights': 'KQk'},
   {'ep': None, 'halfmove': 0, 'rights': 'K'}),
  ('double step with adjacent enemy',
   {'board': {'d4': 'p', 'e1': 'K', 'e2': 'P', 'e8': 'k'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': 'e3', 'halfmove': 0, 'rights': '-'}),
  ('double step beside own pawn',
   {'board': {'e1': 'K', 'e2': 'P', 'e8': 'k', 'f4': 'P'},
    'halfmove': 4,
    'move': ['e2', 'e4'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('single pawn step',
   {'board': {'a2': 'P', 'e1': 'K', 'e8': 'k'},
    'halfmove': 11,
    'move': ['a2', 'a3'],
    'rights': '-'},
   {'ep': None, 'halfmove': 0, 'rights': '-'}),
  ('rook two-rank move',
   {'board': {'c3': 'p', 'd1': 'R', 'e1': 'K', 'e8': 'k'},
    'halfmove': 1,
    'move': ['d1', 'd3'],
    'rights': '-'},
   {'ep': None, 'halfmove': 2, 'rights': '-'})]]
for label, args, expected in fixtures[N-1]:
    try:
        actual = solve(args)
    except Exception as exc:
        actual = 'error:' + type(exc).__name__
    check(label, actual, 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
king move clears both{'ep': None, 'halfmove': 4, 'rights': 'kq'}{'ep': None, 'halfmove': 4, 'rights': 'kq'}Passed
black king move{'ep': None, 'halfmove': 1, 'rights': 'KQ'}{'ep': None, 'halfmove': 1, 'rights': 'KQ'}Passed
rook captured on a8{'ep': None, 'halfmove': 0, 'rights': 'Kk'}{'ep': None, 'halfmove': 0, 'rights': 'Kk'}Passed
bishop takes h8 rook{'ep': None, 'halfmove': 0, 'rights': 'K'}{'ep': None, 'halfmove': 0, 'rights': 'K'}Passed
rook leaves corner{'ep': None, 'halfmove': 10, 'rights': 'K'}{'ep': None, 'halfmove': 10, 'rights': 'K'}Passed
double step with adjacent enemy{'ep': 'e3', 'halfmove': 0, 'rights': '-'}{'ep': 'e3', 'halfmove': 0, 'rights': '-'}Passed
double step no enemy beside{'ep': None, 'halfmove': 0, 'rights': '-'}{'ep': None, 'halfmove': 0, 'rights': '-'}Passed
black double step{'ep': 'c6', 'halfmove': 0, 'rights': 'kq'}{'ep': 'c6', 'halfmove': 0, 'rights': 'kq'}Passed

SHA-256 / 2c922d8899807b8b1d7c86f2d04db20513ecf8f093269cf9a0210a220b938688

Verification & scope

A deterministic toy model with an explicitly stated contract; boards are {square: piece} with white upper-case and black lower-case pieces; no claim of full FIDE Laws conformance. 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:13.466936+00:00.

Case digest / 537ac280457fa1a623cc07da666419decc4b4df564c961352352d84c52388f50