FAILURE MAP
← Case archive

FA-82701 / Chess move legality / Open access

King may castle into an attacked destination · case 01

Castling to g1 is allowed while a rook on g8 attacks it.

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

ROOT CAUSE

The attack loop is half-open and stops before the king's destination.

VERIFIED REPAIR

Test every square from the king's start to its destination, both inclusive.

Unsuccessful approach: Starting after the origin allows castling out of check.

Case contract

Input: {"board", "side", "wing", "king_from", "rook_from"}; rights are assumed held. Chess960 castling: the king ends on g (kingside) or c (queenside) and the rook on f or d; the kingside rook must be on the king's h-side and the queenside rook on its a-side. Every square from the leftmost to the rightmost of king start, king end, rook start and rook end must be empty apart from the castling king and rook, and no square the king stands on or passes through (start to end inclusive) may be attacked.

Why this case matters

Chess960 castling generalizes standard rules; standard-chess shortcuts break it.

1 / The failure

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

N = 1
observations = []
def solve(x):
    def attacked(bd, sq, by_white):
        f,r=ord(sq[0])-97,int(sq[1])-1
        def at(ff,rr):
            return bd.get(chr(97+ff)+str(rr+1)) if 0<=ff<8 and 0<=rr<8 else None
        P,N,B,R,Q,K=('PNBRQK' if by_white else 'pnbrqk')
        pr=r-1 if by_white else r+1
        if at(f-1,pr)==P or at(f+1,pr)==P: return True
        for df,dr in ((1,2),(2,1),(-1,2),(-2,1),(1,-2),(2,-1),(-1,-2),(-2,-1)):
            if at(f+df,r+dr)==N: return True
        for df in (-1,0,1):
            for dr in (-1,0,1):
                if (df or dr) and at(f+df,r+dr)==K: return True
        for df,dr,kinds in ((1,0,(R,Q)),(-1,0,(R,Q)),(0,1,(R,Q)),(0,-1,(R,Q)),(1,1,(B,Q)),(1,-1,(B,Q)),(-1,1,(B,Q)),(-1,-1,(B,Q))):
            ff,rr=f+df,r+dr
            while 0<=ff<8 and 0<=rr<8:
                v=at(ff,rr)
                if v:
                    if v in kinds: return True
                    break
                ff+=df; rr+=dr
        return False
    
    b=x['board']; white=x['side']=='w'; rank='1' if white else '8'
    kf=ord(x['king_from'][0])-97; rf=ord(x['rook_from'][0])-97
    if b.get(x['king_from'])!=('K' if white else 'k') or b.get(x['rook_from'])!=('R' if white else 'r'): return False
    if x['wing']=='K':
        if rf<kf: return False
        kd,rd=6,5
    else:
        if rf>kf: return False
        kd,rd=2,3
    lo=min(kf,kd,rf,rd); hi=max(kf,kd,rf,rd)
    for f in range(lo,hi+1):
        q=chr(97+f)+rank
        if q in b and f not in (kf,rf): return False
    step=1 if kd>=kf else -1
    for f in range(kf,kd,step):
        if attacked(b, chr(97+f)+rank, not white): return False
    return True
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('king b1 rook a1 queenside',
   {'board': {'a1': 'R', 'b1': 'K', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   True),
  ('king b1 rook c1 kingside',
   {'board': {'b1': 'K', 'c1': 'R', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king f1 rook h1',
   {'board': {'e8': 'k', 'f1': 'K', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king g1 rook h1 stays',
   {'board': {'e8': 'k', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('rook destination occupied',
   {'board': {'e8': 'k', 'f1': 'B', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king destination attacked',
   {'board': {'a8': 'k', 'e1': 'K', 'g8': 'r', 'h1': 'R'},
    'king_from': 'e1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king in check',
   {'board': {'a8': 'k', 'f1': 'K', 'f8': 'r', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king b1 rook a1 c1 attacked',
   {'board': {'a1': 'R', 'b1': 'K', 'c8': 'r', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False)],
 [('king g1 rook h1 stays',
   {'board': {'e8': 'k', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('rook destination occupied',
   {'board': {'e8': 'k', 'f1': 'B', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('queenside d1 occupied',
   {'board': {'a1': 'R', 'b1': 'K', 'd1': 'N', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('rook on wrong side',
   {'board': {'b1': 'R', 'd1': 'K', 'e8': 'k'},
    'king_from': 'd1',
    'rook_from': 'b1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king destination attacked',
   {'board': {'a8': 'k', 'e1': 'K', 'g8': 'r', 'h1': 'R'},
    'king_from': 'e1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king in check',
   {'board': {'a8': 'k', 'f1': 'K', 'f8': 'r', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('black queenside c8 d8',
   {'board': {'a8': 'r', 'd8': 'k', 'e1': 'K'},
    'king_from': 'd8',
    'rook_from': 'a8',
    'side': 'b',
    'wing': 'Q'},
   True),
  ('king b1 rook a1 c1 attacked',
   {'board': {'a1': 'R', 'b1': 'K', 'c8': 'r', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False)],
 [('rook on wrong side',
   {'board': {'b1': 'R', 'd1': 'K', 'e8': 'k'},
    'king_from': 'd1',
    'rook_from': 'b1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king destination attacked',
   {'board': {'a8': 'k', 'e1': 'K', 'g8': 'r', 'h1': 'R'},
    'king_from': 'e1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king in check',
   {'board': {'a8': 'k', 'f1': 'K', 'f8': 'r', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('black queenside c8 d8',
   {'board': {'a8': 'r', 'd8': 'k', 'e1': 'K'},
    'king_from': 'd8',
    'rook_from': 'a8',
    'side': 'b',
    'wing': 'Q'},
   True),
  ('king c1 rook a1 queenside',
   {'board': {'a1': 'R', 'b1': 'N', 'c1': 'K', 'e8': 'k'},
    'king_from': 'c1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('rook f1 king e1 kingside',
   {'board': {'e1': 'K', 'e8': 'k', 'f1': 'R'},
    'king_from': 'e1',
    'rook_from': 'f1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king b1 rook c1 f1 attacked',
   {'board': {'a8': 'k', 'b1': 'K', 'c1': 'R', 'f8': 'r'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king b1 rook a1 c1 attacked',
   {'board': {'a1': 'R', 'b1': 'K', 'c8': 'r', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False)],
 [('king b1 rook a1 queenside',
   {'board': {'a1': 'R', 'b1': 'K', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   True),
  ('king b1 rook c1 kingside',
   {'board': {'b1': 'K', 'c1': 'R', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king destination attacked',
   {'board': {'a8': 'k', 'e1': 'K', 'g8': 'r', 'h1': 'R'},
    'king_from': 'e1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king in check',
   {'board': {'a8': 'k', 'f1': 'K', 'f8': 'r', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('rook f1 king e1 kingside',
   {'board': {'e1': 'K', 'e8': 'k', 'f1': 'R'},
    'king_from': 'e1',
    'rook_from': 'f1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king b1 rook c1 f1 attacked',
   {'board': {'a8': 'k', 'b1': 'K', 'c1': 'R', 'f8': 'r'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('rook adjacent on a-side kingside',
   {'board': {'c1': 'R', 'd1': 'K', 'e8': 'k'},
    'king_from': 'd1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king b1 rook a1 c1 attacked',
   {'board': {'a1': 'R', 'b1': 'K', 'c8': 'r', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False)],
 [('king b1 rook a1 queenside',
   {'board': {'a1': 'R', 'b1': 'K', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   True),
  ('king b1 rook c1 kingside',
   {'board': {'b1': 'K', 'c1': 'R', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king f1 rook h1',
   {'board': {'e8': 'k', 'f1': 'K', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king g1 rook h1 stays',
   {'board': {'e8': 'k', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('rook destination occupied',
   {'board': {'e8': 'k', 'f1': 'B', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king destination attacked',
   {'board': {'a8': 'k', 'e1': 'K', 'g8': 'r', 'h1': 'R'},
    'king_from': 'e1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king in check',
   {'board': {'a8': 'k', 'f1': 'K', 'f8': 'r', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king b1 rook a1 c1 attacked',
   {'board': {'a1': 'R', 'b1': 'K', 'c8': 'r', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False)]]
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 b1 rook a1 queensideTrueTruePassed
king b1 rook c1 kingsideTrueTruePassed
king f1 rook h1TrueTruePassed
king g1 rook h1 staysTrueTruePassed
rook destination occupiedFalseFalsePassed
king destination attackedTrueFalseFailed
king in checkFalseFalsePassed
king b1 rook a1 c1 attackedTrueFalseFailed

SHA-256 / 9c326f80013ab7a53ea7e6499c4a36cb06576ca7f551c6ae096b3371f0e703cc

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(x):
    def attacked(bd, sq, by_white):
        f,r=ord(sq[0])-97,int(sq[1])-1
        def at(ff,rr):
            return bd.get(chr(97+ff)+str(rr+1)) if 0<=ff<8 and 0<=rr<8 else None
        P,N,B,R,Q,K=('PNBRQK' if by_white else 'pnbrqk')
        pr=r-1 if by_white else r+1
        if at(f-1,pr)==P or at(f+1,pr)==P: return True
        for df,dr in ((1,2),(2,1),(-1,2),(-2,1),(1,-2),(2,-1),(-1,-2),(-2,-1)):
            if at(f+df,r+dr)==N: return True
        for df in (-1,0,1):
            for dr in (-1,0,1):
                if (df or dr) and at(f+df,r+dr)==K: return True
        for df,dr,kinds in ((1,0,(R,Q)),(-1,0,(R,Q)),(0,1,(R,Q)),(0,-1,(R,Q)),(1,1,(B,Q)),(1,-1,(B,Q)),(-1,1,(B,Q)),(-1,-1,(B,Q))):
            ff,rr=f+df,r+dr
            while 0<=ff<8 and 0<=rr<8:
                v=at(ff,rr)
                if v:
                    if v in kinds: return True
                    break
                ff+=df; rr+=dr
        return False
    
    b=x['board']; white=x['side']=='w'; rank='1' if white else '8'
    kf=ord(x['king_from'][0])-97; rf=ord(x['rook_from'][0])-97
    if b.get(x['king_from'])!=('K' if white else 'k') or b.get(x['rook_from'])!=('R' if white else 'r'): return False
    if x['wing']=='K':
        if rf<kf: return False
        kd,rd=6,5
    else:
        if rf>kf: return False
        kd,rd=2,3
    lo=min(kf,kd,rf,rd); hi=max(kf,kd,rf,rd)
    for f in range(lo,hi+1):
        q=chr(97+f)+rank
        if q in b and f not in (kf,rf): return False
    step=1 if kd>=kf else -1
    for f in range(kf+step,kd+step,step):
        if attacked(b, chr(97+f)+rank, not white): return False
    return True
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('king b1 rook a1 queenside',
   {'board': {'a1': 'R', 'b1': 'K', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   True),
  ('king b1 rook c1 kingside',
   {'board': {'b1': 'K', 'c1': 'R', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king f1 rook h1',
   {'board': {'e8': 'k', 'f1': 'K', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king g1 rook h1 stays',
   {'board': {'e8': 'k', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('rook destination occupied',
   {'board': {'e8': 'k', 'f1': 'B', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king destination attacked',
   {'board': {'a8': 'k', 'e1': 'K', 'g8': 'r', 'h1': 'R'},
    'king_from': 'e1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king in check',
   {'board': {'a8': 'k', 'f1': 'K', 'f8': 'r', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king b1 rook a1 c1 attacked',
   {'board': {'a1': 'R', 'b1': 'K', 'c8': 'r', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False)],
 [('king g1 rook h1 stays',
   {'board': {'e8': 'k', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('rook destination occupied',
   {'board': {'e8': 'k', 'f1': 'B', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('queenside d1 occupied',
   {'board': {'a1': 'R', 'b1': 'K', 'd1': 'N', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('rook on wrong side',
   {'board': {'b1': 'R', 'd1': 'K', 'e8': 'k'},
    'king_from': 'd1',
    'rook_from': 'b1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king destination attacked',
   {'board': {'a8': 'k', 'e1': 'K', 'g8': 'r', 'h1': 'R'},
    'king_from': 'e1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king in check',
   {'board': {'a8': 'k', 'f1': 'K', 'f8': 'r', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('black queenside c8 d8',
   {'board': {'a8': 'r', 'd8': 'k', 'e1': 'K'},
    'king_from': 'd8',
    'rook_from': 'a8',
    'side': 'b',
    'wing': 'Q'},
   True),
  ('king b1 rook a1 c1 attacked',
   {'board': {'a1': 'R', 'b1': 'K', 'c8': 'r', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False)],
 [('rook on wrong side',
   {'board': {'b1': 'R', 'd1': 'K', 'e8': 'k'},
    'king_from': 'd1',
    'rook_from': 'b1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king destination attacked',
   {'board': {'a8': 'k', 'e1': 'K', 'g8': 'r', 'h1': 'R'},
    'king_from': 'e1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king in check',
   {'board': {'a8': 'k', 'f1': 'K', 'f8': 'r', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('black queenside c8 d8',
   {'board': {'a8': 'r', 'd8': 'k', 'e1': 'K'},
    'king_from': 'd8',
    'rook_from': 'a8',
    'side': 'b',
    'wing': 'Q'},
   True),
  ('king c1 rook a1 queenside',
   {'board': {'a1': 'R', 'b1': 'N', 'c1': 'K', 'e8': 'k'},
    'king_from': 'c1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('rook f1 king e1 kingside',
   {'board': {'e1': 'K', 'e8': 'k', 'f1': 'R'},
    'king_from': 'e1',
    'rook_from': 'f1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king b1 rook c1 f1 attacked',
   {'board': {'a8': 'k', 'b1': 'K', 'c1': 'R', 'f8': 'r'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king b1 rook a1 c1 attacked',
   {'board': {'a1': 'R', 'b1': 'K', 'c8': 'r', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False)],
 [('king b1 rook a1 queenside',
   {'board': {'a1': 'R', 'b1': 'K', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   True),
  ('king b1 rook c1 kingside',
   {'board': {'b1': 'K', 'c1': 'R', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king destination attacked',
   {'board': {'a8': 'k', 'e1': 'K', 'g8': 'r', 'h1': 'R'},
    'king_from': 'e1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king in check',
   {'board': {'a8': 'k', 'f1': 'K', 'f8': 'r', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('rook f1 king e1 kingside',
   {'board': {'e1': 'K', 'e8': 'k', 'f1': 'R'},
    'king_from': 'e1',
    'rook_from': 'f1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king b1 rook c1 f1 attacked',
   {'board': {'a8': 'k', 'b1': 'K', 'c1': 'R', 'f8': 'r'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('rook adjacent on a-side kingside',
   {'board': {'c1': 'R', 'd1': 'K', 'e8': 'k'},
    'king_from': 'd1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king b1 rook a1 c1 attacked',
   {'board': {'a1': 'R', 'b1': 'K', 'c8': 'r', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False)],
 [('king b1 rook a1 queenside',
   {'board': {'a1': 'R', 'b1': 'K', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   True),
  ('king b1 rook c1 kingside',
   {'board': {'b1': 'K', 'c1': 'R', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king f1 rook h1',
   {'board': {'e8': 'k', 'f1': 'K', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king g1 rook h1 stays',
   {'board': {'e8': 'k', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('rook destination occupied',
   {'board': {'e8': 'k', 'f1': 'B', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king destination attacked',
   {'board': {'a8': 'k', 'e1': 'K', 'g8': 'r', 'h1': 'R'},
    'king_from': 'e1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king in check',
   {'board': {'a8': 'k', 'f1': 'K', 'f8': 'r', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king b1 rook a1 c1 attacked',
   {'board': {'a1': 'R', 'b1': 'K', 'c8': 'r', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False)]]
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 b1 rook a1 queensideTrueTruePassed
king b1 rook c1 kingsideTrueTruePassed
king f1 rook h1TrueTruePassed
king g1 rook h1 staysTrueTruePassed
rook destination occupiedFalseFalsePassed
king destination attackedFalseFalsePassed
king in checkTrueFalseFailed
king b1 rook a1 c1 attackedFalseFalsePassed

SHA-256 / e759ce2ef9f58235fb1c81f6a03f95da46250c2c99bcf2ed186d873fc807fa81

3 / The verified repair

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

N = 1
observations = []
def solve(x):
    def attacked(bd, sq, by_white):
        f,r=ord(sq[0])-97,int(sq[1])-1
        def at(ff,rr):
            return bd.get(chr(97+ff)+str(rr+1)) if 0<=ff<8 and 0<=rr<8 else None
        P,N,B,R,Q,K=('PNBRQK' if by_white else 'pnbrqk')
        pr=r-1 if by_white else r+1
        if at(f-1,pr)==P or at(f+1,pr)==P: return True
        for df,dr in ((1,2),(2,1),(-1,2),(-2,1),(1,-2),(2,-1),(-1,-2),(-2,-1)):
            if at(f+df,r+dr)==N: return True
        for df in (-1,0,1):
            for dr in (-1,0,1):
                if (df or dr) and at(f+df,r+dr)==K: return True
        for df,dr,kinds in ((1,0,(R,Q)),(-1,0,(R,Q)),(0,1,(R,Q)),(0,-1,(R,Q)),(1,1,(B,Q)),(1,-1,(B,Q)),(-1,1,(B,Q)),(-1,-1,(B,Q))):
            ff,rr=f+df,r+dr
            while 0<=ff<8 and 0<=rr<8:
                v=at(ff,rr)
                if v:
                    if v in kinds: return True
                    break
                ff+=df; rr+=dr
        return False
    
    b=x['board']; white=x['side']=='w'; rank='1' if white else '8'
    kf=ord(x['king_from'][0])-97; rf=ord(x['rook_from'][0])-97
    if b.get(x['king_from'])!=('K' if white else 'k') or b.get(x['rook_from'])!=('R' if white else 'r'): return False
    if x['wing']=='K':
        if rf<kf: return False
        kd,rd=6,5
    else:
        if rf>kf: return False
        kd,rd=2,3
    lo=min(kf,kd,rf,rd); hi=max(kf,kd,rf,rd)
    for f in range(lo,hi+1):
        q=chr(97+f)+rank
        if q in b and f not in (kf,rf): return False
    step=1 if kd>=kf else -1
    for f in range(kf,kd+step,step):
        if attacked(b, chr(97+f)+rank, not white): return False
    return True
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('king b1 rook a1 queenside',
   {'board': {'a1': 'R', 'b1': 'K', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   True),
  ('king b1 rook c1 kingside',
   {'board': {'b1': 'K', 'c1': 'R', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king f1 rook h1',
   {'board': {'e8': 'k', 'f1': 'K', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king g1 rook h1 stays',
   {'board': {'e8': 'k', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('rook destination occupied',
   {'board': {'e8': 'k', 'f1': 'B', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king destination attacked',
   {'board': {'a8': 'k', 'e1': 'K', 'g8': 'r', 'h1': 'R'},
    'king_from': 'e1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king in check',
   {'board': {'a8': 'k', 'f1': 'K', 'f8': 'r', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king b1 rook a1 c1 attacked',
   {'board': {'a1': 'R', 'b1': 'K', 'c8': 'r', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False)],
 [('king g1 rook h1 stays',
   {'board': {'e8': 'k', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('rook destination occupied',
   {'board': {'e8': 'k', 'f1': 'B', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('queenside d1 occupied',
   {'board': {'a1': 'R', 'b1': 'K', 'd1': 'N', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('rook on wrong side',
   {'board': {'b1': 'R', 'd1': 'K', 'e8': 'k'},
    'king_from': 'd1',
    'rook_from': 'b1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king destination attacked',
   {'board': {'a8': 'k', 'e1': 'K', 'g8': 'r', 'h1': 'R'},
    'king_from': 'e1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king in check',
   {'board': {'a8': 'k', 'f1': 'K', 'f8': 'r', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('black queenside c8 d8',
   {'board': {'a8': 'r', 'd8': 'k', 'e1': 'K'},
    'king_from': 'd8',
    'rook_from': 'a8',
    'side': 'b',
    'wing': 'Q'},
   True),
  ('king b1 rook a1 c1 attacked',
   {'board': {'a1': 'R', 'b1': 'K', 'c8': 'r', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False)],
 [('rook on wrong side',
   {'board': {'b1': 'R', 'd1': 'K', 'e8': 'k'},
    'king_from': 'd1',
    'rook_from': 'b1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king destination attacked',
   {'board': {'a8': 'k', 'e1': 'K', 'g8': 'r', 'h1': 'R'},
    'king_from': 'e1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king in check',
   {'board': {'a8': 'k', 'f1': 'K', 'f8': 'r', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('black queenside c8 d8',
   {'board': {'a8': 'r', 'd8': 'k', 'e1': 'K'},
    'king_from': 'd8',
    'rook_from': 'a8',
    'side': 'b',
    'wing': 'Q'},
   True),
  ('king c1 rook a1 queenside',
   {'board': {'a1': 'R', 'b1': 'N', 'c1': 'K', 'e8': 'k'},
    'king_from': 'c1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('rook f1 king e1 kingside',
   {'board': {'e1': 'K', 'e8': 'k', 'f1': 'R'},
    'king_from': 'e1',
    'rook_from': 'f1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king b1 rook c1 f1 attacked',
   {'board': {'a8': 'k', 'b1': 'K', 'c1': 'R', 'f8': 'r'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king b1 rook a1 c1 attacked',
   {'board': {'a1': 'R', 'b1': 'K', 'c8': 'r', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False)],
 [('king b1 rook a1 queenside',
   {'board': {'a1': 'R', 'b1': 'K', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   True),
  ('king b1 rook c1 kingside',
   {'board': {'b1': 'K', 'c1': 'R', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king destination attacked',
   {'board': {'a8': 'k', 'e1': 'K', 'g8': 'r', 'h1': 'R'},
    'king_from': 'e1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king in check',
   {'board': {'a8': 'k', 'f1': 'K', 'f8': 'r', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('rook f1 king e1 kingside',
   {'board': {'e1': 'K', 'e8': 'k', 'f1': 'R'},
    'king_from': 'e1',
    'rook_from': 'f1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king b1 rook c1 f1 attacked',
   {'board': {'a8': 'k', 'b1': 'K', 'c1': 'R', 'f8': 'r'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('rook adjacent on a-side kingside',
   {'board': {'c1': 'R', 'd1': 'K', 'e8': 'k'},
    'king_from': 'd1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king b1 rook a1 c1 attacked',
   {'board': {'a1': 'R', 'b1': 'K', 'c8': 'r', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False)],
 [('king b1 rook a1 queenside',
   {'board': {'a1': 'R', 'b1': 'K', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   True),
  ('king b1 rook c1 kingside',
   {'board': {'b1': 'K', 'c1': 'R', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king f1 rook h1',
   {'board': {'e8': 'k', 'f1': 'K', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king g1 rook h1 stays',
   {'board': {'e8': 'k', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('rook destination occupied',
   {'board': {'e8': 'k', 'f1': 'B', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king destination attacked',
   {'board': {'a8': 'k', 'e1': 'K', 'g8': 'r', 'h1': 'R'},
    'king_from': 'e1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king in check',
   {'board': {'a8': 'k', 'f1': 'K', 'f8': 'r', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king b1 rook a1 c1 attacked',
   {'board': {'a1': 'R', 'b1': 'K', 'c8': 'r', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False)]]
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 b1 rook a1 queensideTrueTruePassed
king b1 rook c1 kingsideTrueTruePassed
king f1 rook h1TrueTruePassed
king g1 rook h1 staysTrueTruePassed
rook destination occupiedFalseFalsePassed
king destination attackedFalseFalsePassed
king in checkFalseFalsePassed
king b1 rook a1 c1 attackedFalseFalsePassed

SHA-256 / 32a064441289717052151645bfd0865d0766a33e4e7f1bb7ea7fa56686a1bfb8

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

Case digest / 28e5029e6da7a579018b5cb2f8638d74adb167baad2786ac5d6345d39cdf4a63