broken_source:
"""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)

source:
"""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)

prompt:
White castles long with a knight still on b1.

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.

split: open-access


broken_source:
"""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 'edcb'
    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),
  ('enemy rook in corner',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'r'}, 'rights': 'K', 'side': 'w', 'wing': 'K'}, 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),
  ('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),
  ('white pawn on f2 harmless',
   {'board': {'e1': 'K', 'e8': 'k', 'g2': 'P', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   True)],
 [('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),
  ('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),
  ('own piece shields g1',
   {'board': {'a8': 'k', 'e1': 'K', 'g3': 'N', 'g5': 'q', 'h1': 'R'},
    'rights': 'K',
    'side': 'w',
    'wing': 'K'},
   True)],
 [('white kingside clear',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'KQkq', 'side': 'w', 'wing': 'K'}, True),
  ('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),
  ('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),
  ('black uses own right',
   {'board': {'e1': 'K', 'e8': 'k', 'h8': 'r'}, 'rights': 'K', 'side': 'b', 'wing': 'K'}, False),
  ('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)

meaning: Fixture-count band, not measured model difficulty

deps: stdlib

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

N = 1
observations = []
def solve(x):
    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='fg' if wing=='K' else 'dc'
    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),
  ('enemy rook in corner',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'r'}, 'rights': 'K', 'side': 'w', 'wing': 'K'}, 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),
  ('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),
  ('white pawn on f2 harmless',
   {'board': {'e1': 'K', 'e8': 'k', 'g2': 'P', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   True)],
 [('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),
  ('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),
  ('own piece shields g1',
   {'board': {'a8': 'k', 'e1': 'K', 'g3': 'N', 'g5': 'q', 'h1': 'R'},
    'rights': 'K',
    'side': 'w',
    'wing': 'K'},
   True)],
 [('white kingside clear',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'KQkq', 'side': 'w', 'wing': 'K'}, True),
  ('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),
  ('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),
  ('black uses own right',
   {'board': {'e1': 'K', 'e8': 'k', 'h8': 'r'}, 'rights': 'K', 'side': 'b', 'wing': 'K'}, False),
  ('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)

prompt:
A rook attacking b1 prevents white from castling long.

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.

split: open-access


broken_source:
"""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 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),
  ('enemy rook in corner',
   {'board': {'e1': 'K', 'e8': 'k', '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),
  ('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),
  ('black pawn attacks f8 check',
   {'board': {'e1': 'K', 'e7': 'P', 'e8': 'k', 'h8': 'r'}, 'rights': 'k', 'side': 'b', 'wing': 'K'},
   False),
  ('c1 attacked',
   {'board': {'a1': 'R', 'e1': 'K', 'e8': 'k', 'h6': 'b'}, 'rights': 'Q', '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),
  ('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),
  ('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),
  ('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 attacked',
   {'board': {'a1': 'R', 'b8': 'r', 'e1': 'K', 'e8': 'k'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   True),
  ('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),
  ('white pawn on f2 harmless',
   {'board': {'e1': 'K', 'e8': 'k', 'g2': 'P', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   True),
  ('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),
  ('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),
  ('in check',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', '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),
  ('white pawn on f2 harmless',
   {'board': {'e1': 'K', 'e8': 'k', 'g2': 'P', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   True),
  ('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)]]
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)

source:
"""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.lower() if white else wing
    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),
  ('enemy rook in corner',
   {'board': {'e1': 'K', 'e8': 'k', '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),
  ('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),
  ('black pawn attacks f8 check',
   {'board': {'e1': 'K', 'e7': 'P', 'e8': 'k', 'h8': 'r'}, 'rights': 'k', 'side': 'b', 'wing': 'K'},
   False),
  ('c1 attacked',
   {'board': {'a1': 'R', 'e1': 'K', 'e8': 'k', 'h6': 'b'}, 'rights': 'Q', '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),
  ('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),
  ('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),
  ('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 attacked',
   {'board': {'a1': 'R', 'b8': 'r', 'e1': 'K', 'e8': 'k'}, 'rights': 'Q', 'side': 'w', 'wing': 'Q'},
   True),
  ('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),
  ('white pawn on f2 harmless',
   {'board': {'e1': 'K', 'e8': 'k', 'g2': 'P', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   True),
  ('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),
  ('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),
  ('in check',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', '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),
  ('white pawn on f2 harmless',
   {'board': {'e1': 'K', 'e8': 'k', 'g2': 'P', 'h1': 'R'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   True),
  ('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)]]
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)

prompt:
Black may castle kingside when only white holds the K right, and is refused with its own q right.

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.

split: open-access


broken_source:
"""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 rook_sq not in b: 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),
  ('knight in rook corner',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'N'}, 'rights': 'K', 'side': 'w', 'wing': 'K'}, False)],
 [('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),
  ('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 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),
  ('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)],
 [('white kingside clear',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'KQkq', 'side': 'w', 'wing': 'K'}, True),
  ('black has right',
   {'board': {'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'rights': 'q', 'side': 'b', 'wing': 'Q'}, True),
  ('knight in rook corner',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'N'}, 'rights': 'K', 'side': 'w', 'wing': 'K'}, False),
  ('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),
  ('black has right',
   {'board': {'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'rights': 'q', 'side': 'b', 'wing': 'Q'}, True),
  ('knight in rook corner',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'N'}, 'rights': 'K', 'side': 'w', 'wing': 'K'}, False),
  ('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)

source:
"""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': 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),
  ('knight in rook corner',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'N'}, 'rights': 'K', 'side': 'w', 'wing': 'K'}, False)],
 [('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),
  ('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 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),
  ('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)],
 [('white kingside clear',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'KQkq', 'side': 'w', 'wing': 'K'}, True),
  ('black has right',
   {'board': {'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'rights': 'q', 'side': 'b', 'wing': 'Q'}, True),
  ('knight in rook corner',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'N'}, 'rights': 'K', 'side': 'w', 'wing': 'K'}, False),
  ('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),
  ('black has right',
   {'board': {'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'rights': 'q', 'side': 'b', 'wing': 'Q'}, True),
  ('knight in rook corner',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'N'}, 'rights': 'K', 'side': 'w', 'wing': 'K'}, False),
  ('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)

prompt:
White castles kingside with a knight or an enemy rook on h1.

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.

split: open-access


broken_source:
"""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),
  ('pawn attacks g1 from h2',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R', 'h2': 'p'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('black pawn attacks f8 check',
   {'board': {'e1': 'K', 'e7': 'P', 'e8': 'k', 'h8': 'r'}, 'rights': 'k', 'side': 'b', 'wing': 'K'},
   False)],
 [('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),
  ('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),
  ('black pawn attacks f8 check',
   {'board': {'e1': 'K', 'e7': 'P', '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),
  ('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)],
 [('white kingside clear',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'KQkq', 'side': 'w', 'wing': 'K'}, True),
  ('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),
  ('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),
  ('pawn attacks g1 from h2',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R', 'h2': 'p'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('black pawn attacks f8 check',
   {'board': {'e1': 'K', 'e7': 'P', 'e8': 'k', 'h8': 'r'}, 'rights': 'k', 'side': 'b', 'wing': 'K'},
   False),
  ('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)

source:
"""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 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),
  ('pawn attacks g1 from h2',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R', 'h2': 'p'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('black pawn attacks f8 check',
   {'board': {'e1': 'K', 'e7': 'P', 'e8': 'k', 'h8': 'r'}, 'rights': 'k', 'side': 'b', 'wing': 'K'},
   False)],
 [('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),
  ('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),
  ('black pawn attacks f8 check',
   {'board': {'e1': 'K', 'e7': 'P', '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),
  ('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)],
 [('white kingside clear',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'KQkq', 'side': 'w', 'wing': 'K'}, True),
  ('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),
  ('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),
  ('pawn attacks g1 from h2',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R', 'h2': 'p'}, 'rights': 'K', 'side': 'w', 'wing': 'K'},
   False),
  ('black pawn attacks f8 check',
   {'board': {'e1': 'K', 'e7': 'P', 'e8': 'k', 'h8': 'r'}, 'rights': 'k', 'side': 'b', 'wing': 'K'},
   False),
  ('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)

prompt:
A black pawn on h2 attacking g1 does not stop white from castling.

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.

split: open-access


broken_source:
"""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
                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),
  ('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)],
 [('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),
  ('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),
  ('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)],
 [('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),
  ('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)],
 [('white kingside clear',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'KQkq', 'side': 'w', 'wing': 'K'}, True),
  ('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),
  ('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),
  ('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)]]
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)

source:
"""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
                    if v.isupper()==by_white: 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),
  ('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)],
 [('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),
  ('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),
  ('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)],
 [('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),
  ('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)],
 [('white kingside clear',
   {'board': {'e1': 'K', 'e8': 'k', 'h1': 'R'}, 'rights': 'KQkq', 'side': 'w', 'wing': 'K'}, True),
  ('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),
  ('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),
  ('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)]]
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)

prompt:
A rook behind a white pawn on the f-file stops white from castling kingside.

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.

split: open-access