FAILURE MAP
← Case archive

FA-82436 / Chess move legality / Open access

Queenside castling through a piece on b1 · case 01

White castles long with a knight still on b1.

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

ROOT CAUSE

The queenside emptiness check only covers c1 and d1, because the king never visits b1.

VERIFIED REPAIR

All squares between king and rook must be empty: b, c and d on the queenside.

Unsuccessful approach: Checking b and c but not d lets the king jump over a piece on d1.

Case contract

Input: {"board", "side": "w" or "b", "wing": "K" or "Q", "rights": subset of "KQkq"}. Standard castling is legal when the right is held, the king is on e1/e8 and the matching own rook on h- or a-file, the squares between them are empty (f,g or b,c,d), and none of the king's squares e, f, g (kingside) or e, d, c (queenside) is attacked by the opponent.

Why this case matters

Move validators gate every move in engines, servers and arbiters; accepting an illegal move or rejecting a legal one corrupts the game record.

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'; wing=x['wing']
    rank='1' if white else '8'
    right=wing if white else wing.lower()
    if right not in x['rights']: return False
    if b.get('e'+rank)!=('K' if white else 'k'): return False
    rook_sq=('h' if wing=='K' else 'a')+rank
    if b.get(rook_sq)!=('R' if white else 'r'): return False
    between='fg' if wing=='K' else 'cd'
    if any(f+rank in b for f in between): return False
    path='efg' if wing=='K' else 'edc'
    return not any(attacked(b, f+rank, not white) for f in path)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('white kingside clear',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'KQkq', 'side': 'w', 'wing': 'K'}, True),
  ('queenside b-file blocked',
   {'board': {'a1': 'R', 'b1': 'N', 'e1': 'K', 'e8': 'k'},
    'rights': 'KQ',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('queenside b-file attacked',
   {'board': {'a1': 'R', 'b8': 'r', 'e1': 'K', 'e8': 'k'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   True),
  ('in check',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('f1 attacked',
   {'board': {'c4': 'b', 'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('black uses own right',
   {'board': {'e1': 'K', 'e8': 'k', 'h8': 'r'}, 'rights': 'K', 'side': 'b', 'wing': 'K'}, False),
  ('black has right',
   {'board': {'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'rights': 'q', 'side': 'b', 'wing': 'Q'}, True),
  ('d1 blocked',
   {'board': {'a1': 'R', 'd1': 'Q', 'e1': 'K', 'e8': 'k'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   False)],
 [('queenside b-file blocked',
   {'board': {'a1': 'R', 'b1': 'N', 'e1': 'K', 'e8': 'k'},
    'rights': 'KQ',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('f1 attacked',
   {'board': {'c4': 'b', 'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('black uses own right',
   {'board': {'e1': 'K', 'e8': 'k', 'h8': 'r'}, 'rights': 'K', 'side': 'b', 'wing': 'K'}, False),
  ('black has right',
   {'board': {'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'rights': 'q', 'side': 'b', 'wing': 'Q'}, True),
  ('enemy rook in corner',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'r'}, 'rights': 'K', 'side': 'w', 'wing': 'K'}, False),
  ('knight in rook corner',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'N'}, 'rights': 'K', 'side': 'w', 'wing': 'K'}, False),
  ('pawn attacks g1 from h2',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R', 'h2': 'p'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('d1 blocked',
   {'board': {'a1': 'R', 'd1': 'Q', 'e1': 'K', 'e8': 'k'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   False)],
 [('queenside b-file blocked',
   {'board': {'a1': 'R', 'b1': 'N', 'e1': 'K', 'e8': 'k'},
    'rights': 'KQ',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('enemy rook in corner',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'r'}, 'rights': 'K', 'side': 'w', 'wing': 'K'}, False),
  ('knight in rook corner',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'N'}, 'rights': 'K', 'side': 'w', 'wing': 'K'}, False),
  ('pawn attacks g1 from h2',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R', 'h2': 'p'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('white pawn on f2 harmless',
   {'board': {'e1': 'K', 'e8': 'k', 'g2': 'P', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   True),
  ('black pawn attacks f8 check',
   {'board': {'e1': 'K', 'e7': 'P', 'e8': 'k', 'h8': 'r'}, 'rights': 'k', 'side': 'b', 'wing': 'K'},
   False),
  ('shielded rook attack',
   {'board': {'a8': 'k', 'e1': 'K', 'f4': 'P', 'f8': 'r', 'h1': 'R'},
    'rights': 'K',
    'side': 'w',
    'wing': 'K'},
   True),
  ('d1 blocked',
   {'board': {'a1': 'R', 'd1': 'Q', 'e1': 'K', 'e8': 'k'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   False)],
 [('white kingside clear',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'KQkq', 'side': 'w', 'wing': 'K'}, True),
  ('queenside b-file blocked',
   {'board': {'a1': 'R', 'b1': 'N', 'e1': 'K', 'e8': 'k'},
    'rights': 'KQ',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('white pawn on f2 harmless',
   {'board': {'e1': 'K', 'e8': 'k', 'g2': 'P', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   True),
  ('black pawn attacks f8 check',
   {'board': {'e1': 'K', 'e7': 'P', 'e8': 'k', 'h8': 'r'}, 'rights': 'k', 'side': 'b', 'wing': 'K'},
   False),
  ('shielded rook attack',
   {'board': {'a8': 'k', 'e1': 'K', 'f4': 'P', 'f8': 'r', 'h1': 'R'},
    'rights': 'K',
    'side': 'w',
    'wing': 'K'},
   True),
  ('own piece shields g1',
   {'board': {'a8': 'k', 'e1': 'K', 'g3': 'N', 'g5': 'q', 'h1': 'R'},
    'rights': 'K',
    'side': 'w',
    'wing': 'K'},
   True),
  ('c1 attacked',
   {'board': {'a1': 'R', 'e1': 'K', 'e8': 'k', 'h6': 'b'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   False),
  ('d1 blocked',
   {'board': {'a1': 'R', 'd1': 'Q', 'e1': 'K', 'e8': 'k'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   False)],
 [('white kingside clear',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'KQkq', 'side': 'w', 'wing': 'K'}, True),
  ('queenside b-file blocked',
   {'board': {'a1': 'R', 'b1': 'N', 'e1': 'K', 'e8': 'k'},
    'rights': 'KQ',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('queenside b-file attacked',
   {'board': {'a1': 'R', 'b8': 'r', 'e1': 'K', 'e8': 'k'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   True),
  ('in check',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('f1 attacked',
   {'board': {'c4': 'b', 'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('own piece shields g1',
   {'board': {'a8': 'k', 'e1': 'K', 'g3': 'N', 'g5': 'q', 'h1': 'R'},
    'rights': 'K',
    'side': 'w',
    'wing': 'K'},
   True),
  ('c1 attacked',
   {'board': {'a1': 'R', 'e1': 'K', 'e8': 'k', 'h6': 'b'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   False),
  ('d1 blocked',
   {'board': {'a1': 'R', 'd1': 'Q', 'e1': 'K', 'e8': 'k'}, 'rights': 'Q', '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
white kingside clearTrueTruePassed
queenside b-file blockedTrueFalseFailed
queenside b-file attackedTrueTruePassed
in checkFalseFalsePassed
f1 attackedFalseFalsePassed
black uses own rightFalseFalsePassed
black has rightTrueTruePassed
d1 blockedFalseFalsePassed

SHA-256 / 85d736fa69afbcda609f1bb47abd0c6f2d04b1528549e2a77c55ca6e63d34577

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'; wing=x['wing']
    rank='1' if white else '8'
    right=wing if white else wing.lower()
    if right not in x['rights']: return False
    if b.get('e'+rank)!=('K' if white else 'k'): return False
    rook_sq=('h' if wing=='K' else 'a')+rank
    if b.get(rook_sq)!=('R' if white else 'r'): return False
    between='fg' if wing=='K' else 'bc'
    if any(f+rank in b for f in between): return False
    path='efg' if wing=='K' else 'edc'
    return not any(attacked(b, f+rank, not white) for f in path)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('white kingside clear',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'KQkq', 'side': 'w', 'wing': 'K'}, True),
  ('queenside b-file blocked',
   {'board': {'a1': 'R', 'b1': 'N', 'e1': 'K', 'e8': 'k'},
    'rights': 'KQ',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('queenside b-file attacked',
   {'board': {'a1': 'R', 'b8': 'r', 'e1': 'K', 'e8': 'k'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   True),
  ('in check',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('f1 attacked',
   {'board': {'c4': 'b', 'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('black uses own right',
   {'board': {'e1': 'K', 'e8': 'k', 'h8': 'r'}, 'rights': 'K', 'side': 'b', 'wing': 'K'}, False),
  ('black has right',
   {'board': {'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'rights': 'q', 'side': 'b', 'wing': 'Q'}, True),
  ('d1 blocked',
   {'board': {'a1': 'R', 'd1': 'Q', 'e1': 'K', 'e8': 'k'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   False)],
 [('queenside b-file blocked',
   {'board': {'a1': 'R', 'b1': 'N', 'e1': 'K', 'e8': 'k'},
    'rights': 'KQ',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('f1 attacked',
   {'board': {'c4': 'b', 'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('black uses own right',
   {'board': {'e1': 'K', 'e8': 'k', 'h8': 'r'}, 'rights': 'K', 'side': 'b', 'wing': 'K'}, False),
  ('black has right',
   {'board': {'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'rights': 'q', 'side': 'b', 'wing': 'Q'}, True),
  ('enemy rook in corner',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'r'}, 'rights': 'K', 'side': 'w', 'wing': 'K'}, False),
  ('knight in rook corner',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'N'}, 'rights': 'K', 'side': 'w', 'wing': 'K'}, False),
  ('pawn attacks g1 from h2',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R', 'h2': 'p'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('d1 blocked',
   {'board': {'a1': 'R', 'd1': 'Q', 'e1': 'K', 'e8': 'k'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   False)],
 [('queenside b-file blocked',
   {'board': {'a1': 'R', 'b1': 'N', 'e1': 'K', 'e8': 'k'},
    'rights': 'KQ',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('enemy rook in corner',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'r'}, 'rights': 'K', 'side': 'w', 'wing': 'K'}, False),
  ('knight in rook corner',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'N'}, 'rights': 'K', 'side': 'w', 'wing': 'K'}, False),
  ('pawn attacks g1 from h2',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R', 'h2': 'p'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('white pawn on f2 harmless',
   {'board': {'e1': 'K', 'e8': 'k', 'g2': 'P', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   True),
  ('black pawn attacks f8 check',
   {'board': {'e1': 'K', 'e7': 'P', 'e8': 'k', 'h8': 'r'}, 'rights': 'k', 'side': 'b', 'wing': 'K'},
   False),
  ('shielded rook attack',
   {'board': {'a8': 'k', 'e1': 'K', 'f4': 'P', 'f8': 'r', 'h1': 'R'},
    'rights': 'K',
    'side': 'w',
    'wing': 'K'},
   True),
  ('d1 blocked',
   {'board': {'a1': 'R', 'd1': 'Q', 'e1': 'K', 'e8': 'k'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   False)],
 [('white kingside clear',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'KQkq', 'side': 'w', 'wing': 'K'}, True),
  ('queenside b-file blocked',
   {'board': {'a1': 'R', 'b1': 'N', 'e1': 'K', 'e8': 'k'},
    'rights': 'KQ',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('white pawn on f2 harmless',
   {'board': {'e1': 'K', 'e8': 'k', 'g2': 'P', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   True),
  ('black pawn attacks f8 check',
   {'board': {'e1': 'K', 'e7': 'P', 'e8': 'k', 'h8': 'r'}, 'rights': 'k', 'side': 'b', 'wing': 'K'},
   False),
  ('shielded rook attack',
   {'board': {'a8': 'k', 'e1': 'K', 'f4': 'P', 'f8': 'r', 'h1': 'R'},
    'rights': 'K',
    'side': 'w',
    'wing': 'K'},
   True),
  ('own piece shields g1',
   {'board': {'a8': 'k', 'e1': 'K', 'g3': 'N', 'g5': 'q', 'h1': 'R'},
    'rights': 'K',
    'side': 'w',
    'wing': 'K'},
   True),
  ('c1 attacked',
   {'board': {'a1': 'R', 'e1': 'K', 'e8': 'k', 'h6': 'b'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   False),
  ('d1 blocked',
   {'board': {'a1': 'R', 'd1': 'Q', 'e1': 'K', 'e8': 'k'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   False)],
 [('white kingside clear',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'KQkq', 'side': 'w', 'wing': 'K'}, True),
  ('queenside b-file blocked',
   {'board': {'a1': 'R', 'b1': 'N', 'e1': 'K', 'e8': 'k'},
    'rights': 'KQ',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('queenside b-file attacked',
   {'board': {'a1': 'R', 'b8': 'r', 'e1': 'K', 'e8': 'k'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   True),
  ('in check',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('f1 attacked',
   {'board': {'c4': 'b', 'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('own piece shields g1',
   {'board': {'a8': 'k', 'e1': 'K', 'g3': 'N', 'g5': 'q', 'h1': 'R'},
    'rights': 'K',
    'side': 'w',
    'wing': 'K'},
   True),
  ('c1 attacked',
   {'board': {'a1': 'R', 'e1': 'K', 'e8': 'k', 'h6': 'b'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   False),
  ('d1 blocked',
   {'board': {'a1': 'R', 'd1': 'Q', 'e1': 'K', 'e8': 'k'}, 'rights': 'Q', '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
white kingside clearTrueTruePassed
queenside b-file blockedFalseFalsePassed
queenside b-file attackedTrueTruePassed
in checkFalseFalsePassed
f1 attackedFalseFalsePassed
black uses own rightFalseFalsePassed
black has rightTrueTruePassed
d1 blockedTrueFalseFailed

SHA-256 / efa0f4f3f4671e7090fb3b8ec8c93dbb529b92133d2cb9833136e1bf4459e0e3

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'; wing=x['wing']
    rank='1' if white else '8'
    right=wing if white else wing.lower()
    if right not in x['rights']: return False
    if b.get('e'+rank)!=('K' if white else 'k'): return False
    rook_sq=('h' if wing=='K' else 'a')+rank
    if b.get(rook_sq)!=('R' if white else 'r'): return False
    between='fg' if wing=='K' else 'bcd'
    if any(f+rank in b for f in between): return False
    path='efg' if wing=='K' else 'edc'
    return not any(attacked(b, f+rank, not white) for f in path)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('white kingside clear',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'KQkq', 'side': 'w', 'wing': 'K'}, True),
  ('queenside b-file blocked',
   {'board': {'a1': 'R', 'b1': 'N', 'e1': 'K', 'e8': 'k'},
    'rights': 'KQ',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('queenside b-file attacked',
   {'board': {'a1': 'R', 'b8': 'r', 'e1': 'K', 'e8': 'k'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   True),
  ('in check',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('f1 attacked',
   {'board': {'c4': 'b', 'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('black uses own right',
   {'board': {'e1': 'K', 'e8': 'k', 'h8': 'r'}, 'rights': 'K', 'side': 'b', 'wing': 'K'}, False),
  ('black has right',
   {'board': {'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'rights': 'q', 'side': 'b', 'wing': 'Q'}, True),
  ('d1 blocked',
   {'board': {'a1': 'R', 'd1': 'Q', 'e1': 'K', 'e8': 'k'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   False)],
 [('queenside b-file blocked',
   {'board': {'a1': 'R', 'b1': 'N', 'e1': 'K', 'e8': 'k'},
    'rights': 'KQ',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('f1 attacked',
   {'board': {'c4': 'b', 'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('black uses own right',
   {'board': {'e1': 'K', 'e8': 'k', 'h8': 'r'}, 'rights': 'K', 'side': 'b', 'wing': 'K'}, False),
  ('black has right',
   {'board': {'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'rights': 'q', 'side': 'b', 'wing': 'Q'}, True),
  ('enemy rook in corner',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'r'}, 'rights': 'K', 'side': 'w', 'wing': 'K'}, False),
  ('knight in rook corner',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'N'}, 'rights': 'K', 'side': 'w', 'wing': 'K'}, False),
  ('pawn attacks g1 from h2',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R', 'h2': 'p'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('d1 blocked',
   {'board': {'a1': 'R', 'd1': 'Q', 'e1': 'K', 'e8': 'k'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   False)],
 [('queenside b-file blocked',
   {'board': {'a1': 'R', 'b1': 'N', 'e1': 'K', 'e8': 'k'},
    'rights': 'KQ',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('enemy rook in corner',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'r'}, 'rights': 'K', 'side': 'w', 'wing': 'K'}, False),
  ('knight in rook corner',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'N'}, 'rights': 'K', 'side': 'w', 'wing': 'K'}, False),
  ('pawn attacks g1 from h2',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R', 'h2': 'p'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('white pawn on f2 harmless',
   {'board': {'e1': 'K', 'e8': 'k', 'g2': 'P', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   True),
  ('black pawn attacks f8 check',
   {'board': {'e1': 'K', 'e7': 'P', 'e8': 'k', 'h8': 'r'}, 'rights': 'k', 'side': 'b', 'wing': 'K'},
   False),
  ('shielded rook attack',
   {'board': {'a8': 'k', 'e1': 'K', 'f4': 'P', 'f8': 'r', 'h1': 'R'},
    'rights': 'K',
    'side': 'w',
    'wing': 'K'},
   True),
  ('d1 blocked',
   {'board': {'a1': 'R', 'd1': 'Q', 'e1': 'K', 'e8': 'k'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   False)],
 [('white kingside clear',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'KQkq', 'side': 'w', 'wing': 'K'}, True),
  ('queenside b-file blocked',
   {'board': {'a1': 'R', 'b1': 'N', 'e1': 'K', 'e8': 'k'},
    'rights': 'KQ',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('white pawn on f2 harmless',
   {'board': {'e1': 'K', 'e8': 'k', 'g2': 'P', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   True),
  ('black pawn attacks f8 check',
   {'board': {'e1': 'K', 'e7': 'P', 'e8': 'k', 'h8': 'r'}, 'rights': 'k', 'side': 'b', 'wing': 'K'},
   False),
  ('shielded rook attack',
   {'board': {'a8': 'k', 'e1': 'K', 'f4': 'P', 'f8': 'r', 'h1': 'R'},
    'rights': 'K',
    'side': 'w',
    'wing': 'K'},
   True),
  ('own piece shields g1',
   {'board': {'a8': 'k', 'e1': 'K', 'g3': 'N', 'g5': 'q', 'h1': 'R'},
    'rights': 'K',
    'side': 'w',
    'wing': 'K'},
   True),
  ('c1 attacked',
   {'board': {'a1': 'R', 'e1': 'K', 'e8': 'k', 'h6': 'b'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   False),
  ('d1 blocked',
   {'board': {'a1': 'R', 'd1': 'Q', 'e1': 'K', 'e8': 'k'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   False)],
 [('white kingside clear',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'KQkq', 'side': 'w', 'wing': 'K'}, True),
  ('queenside b-file blocked',
   {'board': {'a1': 'R', 'b1': 'N', 'e1': 'K', 'e8': 'k'},
    'rights': 'KQ',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('queenside b-file attacked',
   {'board': {'a1': 'R', 'b8': 'r', 'e1': 'K', 'e8': 'k'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   True),
  ('in check',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('f1 attacked',
   {'board': {'c4': 'b', 'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('own piece shields g1',
   {'board': {'a8': 'k', 'e1': 'K', 'g3': 'N', 'g5': 'q', 'h1': 'R'},
    'rights': 'K',
    'side': 'w',
    'wing': 'K'},
   True),
  ('c1 attacked',
   {'board': {'a1': 'R', 'e1': 'K', 'e8': 'k', 'h6': 'b'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   False),
  ('d1 blocked',
   {'board': {'a1': 'R', 'd1': 'Q', 'e1': 'K', 'e8': 'k'}, 'rights': 'Q', '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
white kingside clearTrueTruePassed
queenside b-file blockedFalseFalsePassed
queenside b-file attackedTrueTruePassed
in checkFalseFalsePassed
f1 attackedFalseFalsePassed
black uses own rightFalseFalsePassed
black has rightTrueTruePassed
d1 blockedFalseFalsePassed

SHA-256 / 17681344e19d8481180e60960622b001a787b17d77ee69a9d1fbd255e1dee14c

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

Case digest / 67ccd76a335ca824ac929cad8664836ee7dc6f617e40ae2655ab4b25a68bb0e3