FAILURE MAP
← Case archive

FA-82521 / Chess move legality / Open access

Double check answered by a blocking move · case 01

With rook and knight both giving check, a queen interposition is accepted.

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

ROOT CAUSE

The double-check guard requires more than two checkers.

VERIFIED REPAIR

Two or more checkers can only be answered by a king move.

Unsuccessful approach: Allowing capture of one checker still leaves the other giving check.

Case contract

Input: {"board", "move": [from, to]} for a non-king piece whose king may be in check (pins are ignored). Return true if the move is allowed by the check rules: no check means true; double check means false; a single check is answered by capturing the checker or, for a rook, bishop or queen checker, by moving onto a square strictly between it and the king.

Why this case matters

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

1 / The failure

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

N = 1
observations = []
def solve(x):
    b=x['board']; fr,to=x['move']; p=b[fr]; white=p.isupper()
    ks=[s for s,v in b.items() if v==('K' if white else 'k')][0]
    def at(f,r): return b.get(chr(97+f)+str(r+1)) if 0<=f<8 and 0<=r<8 else None
    def sq(f,r): return chr(97+f)+str(r+1)
    def attackers(s, by_white):
        f,r=ord(s[0])-97,int(s[1])-1
        P,N,B,R,Q=('PNBRQ' if by_white else 'pnbrq')
        out=[]
        pr=r-1 if by_white else r+1
        for df in (-1,1):
            if at(f+df,pr)==P: out.append(sq(f+df,pr))
        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: out.append(sq(f+df,r+dr))
        for df,dr in ((1,0),(-1,0),(0,1),(0,-1),(1,1),(1,-1),(-1,1),(-1,-1)):
            kinds=(R,Q) if df==0 or dr==0 else (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: out.append(sq(ff,rr))
                    break
                ff+=df; rr+=dr
        return out
    checkers=attackers(ks, not white)
    if len(checkers)>2: return False
    if not checkers: return True
    c=checkers[0]
    if to==c: return True
    if b[c].lower() in ('n','p'): return False
    cf,cr=ord(c[0])-97,int(c[1])-1
    kf,kr=ord(ks[0])-97,int(ks[1])-1
    sf=(cf>kf)-(cf<kf); sr=(cr>kr)-(cr<kr)
    f,r=kf+sf,kr+sr
    between=[]
    while (f,r)!=(cf,cr) and 0<=f<8 and 0<=r<8:
        between.append(sq(f,r)); f+=sf; r+=sr
    return to in between
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('no check', {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k'}, 'move': ['b1', 'c3']}, True),
  ('block rook check',
   {'board': {'a8': 'k', 'b1': 'N', 'e1': 'K', 'e8': 'r'}, 'move': ['b1', 'c3']}, False),
  ('interpose on file',
   {'board': {'a8': 'k', 'd1': 'Q', 'e1': 'K', 'e8': 'r'}, 'move': ['d1', 'e2']}, True),
  ('capture rook checker',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'h8': 'R'}, 'move': ['h8', 'e8']}, True),
  ('knight check sidestep piece',
   {'board': {'a8': 'k', 'b2': 'B', 'd3': 'n', 'e1': 'K'}, 'move': ['b2', 'c3']}, False),
  ('bishop takes knight checker',
   {'board': {'a8': 'k', 'e1': 'K', 'f3': 'n', 'g2': 'B'}, 'move': ['g2', 'f3']}, True),
  ('cannot block knight',
   {'board': {'a8': 'k', 'd1': 'Q', 'e1': 'K', 'f3': 'n'}, 'move': ['d1', 'e2']}, False),
  ('double check capture one',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'f3': 'n', 'g2': 'B'}, 'move': ['g2', 'f3']},
   False)],
 [('capture rook checker',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'h8': 'R'}, 'move': ['h8', 'e8']}, True),
  ('knight check sidestep piece',
   {'board': {'a8': 'k', 'b2': 'B', 'd3': 'n', 'e1': 'K'}, 'move': ['b2', 'c3']}, False),
  ('bishop takes knight checker',
   {'board': {'a8': 'k', 'e1': 'K', 'f3': 'n', 'g2': 'B'}, 'move': ['g2', 'f3']}, True),
  ('cannot block knight',
   {'board': {'a8': 'k', 'd1': 'Q', 'e1': 'K', 'f3': 'n'}, 'move': ['d1', 'e2']}, False),
  ('double check block',
   {'board': {'a8': 'k', 'd1': 'Q', 'e1': 'K', 'e8': 'r', 'f3': 'n'}, 'move': ['d1', 'e2']},
   False),
  ('double check capture one',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'f3': 'n', 'g2': 'B'}, 'move': ['g2', 'f3']},
   False),
  ('diagonal interpose',
   {'board': {'a5': 'b', 'c1': 'N', 'e1': 'K', 'h8': 'k'}, 'move': ['c1', 'b3']}, False),
  ('diagonal interpose d2',
   {'board': {'a5': 'b', 'e1': 'K', 'f3': 'N', 'h8': 'k'}, 'move': ['f3', 'd2']}, True)],
 [('cannot block knight',
   {'board': {'a8': 'k', 'd1': 'Q', 'e1': 'K', 'f3': 'n'}, 'move': ['d1', 'e2']}, False),
  ('double check block',
   {'board': {'a8': 'k', 'd1': 'Q', 'e1': 'K', 'e8': 'r', 'f3': 'n'}, 'move': ['d1', 'e2']},
   False),
  ('double check capture one',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'f3': 'n', 'g2': 'B'}, 'move': ['g2', 'f3']},
   False),
  ('diagonal interpose',
   {'board': {'a5': 'b', 'c1': 'N', 'e1': 'K', 'h8': 'k'}, 'move': ['c1', 'b3']}, False),
  ('diagonal interpose d2',
   {'board': {'a5': 'b', 'e1': 'K', 'f3': 'N', 'h8': 'k'}, 'move': ['f3', 'd2']}, True),
  ('black blocks white queen',
   {'board': {'a1': 'K', 'c6': 'n', 'e1': 'Q', 'e8': 'k'}, 'move': ['c6', 'e7']}, True),
  ('black cannot block white knight',
   {'board': {'a1': 'K', 'c8': 'b', 'd6': 'N', 'e8': 'k'}, 'move': ['c8', 'd7']}, False),
  ('irrelevant move in check',
   {'board': {'a2': 'P', 'a8': 'k', 'e1': 'K', 'e8': 'r'}, 'move': ['a2', 'a3']}, False)],
 [('no check', {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k'}, 'move': ['b1', 'c3']}, True),
  ('block rook check',
   {'board': {'a8': 'k', 'b1': 'N', 'e1': 'K', 'e8': 'r'}, 'move': ['b1', 'c3']}, False),
  ('double check capture one',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'f3': 'n', 'g2': 'B'}, 'move': ['g2', 'f3']},
   False),
  ('diagonal interpose d2',
   {'board': {'a5': 'b', 'e1': 'K', 'f3': 'N', 'h8': 'k'}, 'move': ['f3', 'd2']}, True),
  ('black blocks white queen',
   {'board': {'a1': 'K', 'c6': 'n', 'e1': 'Q', 'e8': 'k'}, 'move': ['c6', 'e7']}, True),
  ('black cannot block white knight',
   {'board': {'a1': 'K', 'c8': 'b', 'd6': 'N', 'e8': 'k'}, 'move': ['c8', 'd7']}, False),
  ('irrelevant move in check',
   {'board': {'a2': 'P', 'a8': 'k', 'e1': 'K', 'e8': 'r'}, 'move': ['a2', 'a3']}, False),
  ('rank check interpose',
   {'board': {'a1': 'K', 'a8': 'k', 'b3': 'N', 'h1': 'q'}, 'move': ['b3', 'c1']}, True)],
 [('no check', {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k'}, 'move': ['b1', 'c3']}, True),
  ('block rook check',
   {'board': {'a8': 'k', 'b1': 'N', 'e1': 'K', 'e8': 'r'}, 'move': ['b1', 'c3']}, False),
  ('interpose on file',
   {'board': {'a8': 'k', 'd1': 'Q', 'e1': 'K', 'e8': 'r'}, 'move': ['d1', 'e2']}, True),
  ('capture rook checker',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'h8': 'R'}, 'move': ['h8', 'e8']}, True),
  ('knight check sidestep piece',
   {'board': {'a8': 'k', 'b2': 'B', 'd3': 'n', 'e1': 'K'}, 'move': ['b2', 'c3']}, False),
  ('double check capture one',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'f3': 'n', 'g2': 'B'}, 'move': ['g2', 'f3']},
   False),
  ('irrelevant move in check',
   {'board': {'a2': 'P', 'a8': 'k', 'e1': 'K', 'e8': 'r'}, 'move': ['a2', 'a3']}, False),
  ('rank check interpose',
   {'board': {'a1': 'K', 'a8': 'k', 'b3': 'N', 'h1': 'q'}, 'move': ['b3', 'c1']}, 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)
Boundary fixtureActualExpectedOutcome
no checkTrueTruePassed
block rook checkFalseFalsePassed
interpose on fileTrueTruePassed
capture rook checkerTrueTruePassed
knight check sidestep pieceFalseFalsePassed
bishop takes knight checkerTrueTruePassed
cannot block knightFalseFalsePassed
double check capture oneTrueFalseFailed

SHA-256 / 084fada82f20052e7e047477b90d9f9fd331f9674474bc392f84b4e987bfede7

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(x):
    b=x['board']; fr,to=x['move']; p=b[fr]; white=p.isupper()
    ks=[s for s,v in b.items() if v==('K' if white else 'k')][0]
    def at(f,r): return b.get(chr(97+f)+str(r+1)) if 0<=f<8 and 0<=r<8 else None
    def sq(f,r): return chr(97+f)+str(r+1)
    def attackers(s, by_white):
        f,r=ord(s[0])-97,int(s[1])-1
        P,N,B,R,Q=('PNBRQ' if by_white else 'pnbrq')
        out=[]
        pr=r-1 if by_white else r+1
        for df in (-1,1):
            if at(f+df,pr)==P: out.append(sq(f+df,pr))
        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: out.append(sq(f+df,r+dr))
        for df,dr in ((1,0),(-1,0),(0,1),(0,-1),(1,1),(1,-1),(-1,1),(-1,-1)):
            kinds=(R,Q) if df==0 or dr==0 else (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: out.append(sq(ff,rr))
                    break
                ff+=df; rr+=dr
        return out
    checkers=attackers(ks, not white)
    if len(checkers)>=2 and to not in checkers: return False
    if not checkers: return True
    c=checkers[0]
    if to==c: return True
    if b[c].lower() in ('n','p'): return False
    cf,cr=ord(c[0])-97,int(c[1])-1
    kf,kr=ord(ks[0])-97,int(ks[1])-1
    sf=(cf>kf)-(cf<kf); sr=(cr>kr)-(cr<kr)
    f,r=kf+sf,kr+sr
    between=[]
    while (f,r)!=(cf,cr) and 0<=f<8 and 0<=r<8:
        between.append(sq(f,r)); f+=sf; r+=sr
    return to in between
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('no check', {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k'}, 'move': ['b1', 'c3']}, True),
  ('block rook check',
   {'board': {'a8': 'k', 'b1': 'N', 'e1': 'K', 'e8': 'r'}, 'move': ['b1', 'c3']}, False),
  ('interpose on file',
   {'board': {'a8': 'k', 'd1': 'Q', 'e1': 'K', 'e8': 'r'}, 'move': ['d1', 'e2']}, True),
  ('capture rook checker',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'h8': 'R'}, 'move': ['h8', 'e8']}, True),
  ('knight check sidestep piece',
   {'board': {'a8': 'k', 'b2': 'B', 'd3': 'n', 'e1': 'K'}, 'move': ['b2', 'c3']}, False),
  ('bishop takes knight checker',
   {'board': {'a8': 'k', 'e1': 'K', 'f3': 'n', 'g2': 'B'}, 'move': ['g2', 'f3']}, True),
  ('cannot block knight',
   {'board': {'a8': 'k', 'd1': 'Q', 'e1': 'K', 'f3': 'n'}, 'move': ['d1', 'e2']}, False),
  ('double check capture one',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'f3': 'n', 'g2': 'B'}, 'move': ['g2', 'f3']},
   False)],
 [('capture rook checker',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'h8': 'R'}, 'move': ['h8', 'e8']}, True),
  ('knight check sidestep piece',
   {'board': {'a8': 'k', 'b2': 'B', 'd3': 'n', 'e1': 'K'}, 'move': ['b2', 'c3']}, False),
  ('bishop takes knight checker',
   {'board': {'a8': 'k', 'e1': 'K', 'f3': 'n', 'g2': 'B'}, 'move': ['g2', 'f3']}, True),
  ('cannot block knight',
   {'board': {'a8': 'k', 'd1': 'Q', 'e1': 'K', 'f3': 'n'}, 'move': ['d1', 'e2']}, False),
  ('double check block',
   {'board': {'a8': 'k', 'd1': 'Q', 'e1': 'K', 'e8': 'r', 'f3': 'n'}, 'move': ['d1', 'e2']},
   False),
  ('double check capture one',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'f3': 'n', 'g2': 'B'}, 'move': ['g2', 'f3']},
   False),
  ('diagonal interpose',
   {'board': {'a5': 'b', 'c1': 'N', 'e1': 'K', 'h8': 'k'}, 'move': ['c1', 'b3']}, False),
  ('diagonal interpose d2',
   {'board': {'a5': 'b', 'e1': 'K', 'f3': 'N', 'h8': 'k'}, 'move': ['f3', 'd2']}, True)],
 [('cannot block knight',
   {'board': {'a8': 'k', 'd1': 'Q', 'e1': 'K', 'f3': 'n'}, 'move': ['d1', 'e2']}, False),
  ('double check block',
   {'board': {'a8': 'k', 'd1': 'Q', 'e1': 'K', 'e8': 'r', 'f3': 'n'}, 'move': ['d1', 'e2']},
   False),
  ('double check capture one',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'f3': 'n', 'g2': 'B'}, 'move': ['g2', 'f3']},
   False),
  ('diagonal interpose',
   {'board': {'a5': 'b', 'c1': 'N', 'e1': 'K', 'h8': 'k'}, 'move': ['c1', 'b3']}, False),
  ('diagonal interpose d2',
   {'board': {'a5': 'b', 'e1': 'K', 'f3': 'N', 'h8': 'k'}, 'move': ['f3', 'd2']}, True),
  ('black blocks white queen',
   {'board': {'a1': 'K', 'c6': 'n', 'e1': 'Q', 'e8': 'k'}, 'move': ['c6', 'e7']}, True),
  ('black cannot block white knight',
   {'board': {'a1': 'K', 'c8': 'b', 'd6': 'N', 'e8': 'k'}, 'move': ['c8', 'd7']}, False),
  ('irrelevant move in check',
   {'board': {'a2': 'P', 'a8': 'k', 'e1': 'K', 'e8': 'r'}, 'move': ['a2', 'a3']}, False)],
 [('no check', {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k'}, 'move': ['b1', 'c3']}, True),
  ('block rook check',
   {'board': {'a8': 'k', 'b1': 'N', 'e1': 'K', 'e8': 'r'}, 'move': ['b1', 'c3']}, False),
  ('double check capture one',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'f3': 'n', 'g2': 'B'}, 'move': ['g2', 'f3']},
   False),
  ('diagonal interpose d2',
   {'board': {'a5': 'b', 'e1': 'K', 'f3': 'N', 'h8': 'k'}, 'move': ['f3', 'd2']}, True),
  ('black blocks white queen',
   {'board': {'a1': 'K', 'c6': 'n', 'e1': 'Q', 'e8': 'k'}, 'move': ['c6', 'e7']}, True),
  ('black cannot block white knight',
   {'board': {'a1': 'K', 'c8': 'b', 'd6': 'N', 'e8': 'k'}, 'move': ['c8', 'd7']}, False),
  ('irrelevant move in check',
   {'board': {'a2': 'P', 'a8': 'k', 'e1': 'K', 'e8': 'r'}, 'move': ['a2', 'a3']}, False),
  ('rank check interpose',
   {'board': {'a1': 'K', 'a8': 'k', 'b3': 'N', 'h1': 'q'}, 'move': ['b3', 'c1']}, True)],
 [('no check', {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k'}, 'move': ['b1', 'c3']}, True),
  ('block rook check',
   {'board': {'a8': 'k', 'b1': 'N', 'e1': 'K', 'e8': 'r'}, 'move': ['b1', 'c3']}, False),
  ('interpose on file',
   {'board': {'a8': 'k', 'd1': 'Q', 'e1': 'K', 'e8': 'r'}, 'move': ['d1', 'e2']}, True),
  ('capture rook checker',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'h8': 'R'}, 'move': ['h8', 'e8']}, True),
  ('knight check sidestep piece',
   {'board': {'a8': 'k', 'b2': 'B', 'd3': 'n', 'e1': 'K'}, 'move': ['b2', 'c3']}, False),
  ('double check capture one',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'f3': 'n', 'g2': 'B'}, 'move': ['g2', 'f3']},
   False),
  ('irrelevant move in check',
   {'board': {'a2': 'P', 'a8': 'k', 'e1': 'K', 'e8': 'r'}, 'move': ['a2', 'a3']}, False),
  ('rank check interpose',
   {'board': {'a1': 'K', 'a8': 'k', 'b3': 'N', 'h1': 'q'}, 'move': ['b3', 'c1']}, 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)
Boundary fixtureActualExpectedOutcome
no checkTrueTruePassed
block rook checkFalseFalsePassed
interpose on fileTrueTruePassed
capture rook checkerTrueTruePassed
knight check sidestep pieceFalseFalsePassed
bishop takes knight checkerTrueTruePassed
cannot block knightFalseFalsePassed
double check capture oneTrueFalseFailed

SHA-256 / ef0232de267c379d1cac86f03e0214d42f70118b99024a5c352530fffa5ca7bb

3 / The verified repair

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

N = 1
observations = []
def solve(x):
    b=x['board']; fr,to=x['move']; p=b[fr]; white=p.isupper()
    ks=[s for s,v in b.items() if v==('K' if white else 'k')][0]
    def at(f,r): return b.get(chr(97+f)+str(r+1)) if 0<=f<8 and 0<=r<8 else None
    def sq(f,r): return chr(97+f)+str(r+1)
    def attackers(s, by_white):
        f,r=ord(s[0])-97,int(s[1])-1
        P,N,B,R,Q=('PNBRQ' if by_white else 'pnbrq')
        out=[]
        pr=r-1 if by_white else r+1
        for df in (-1,1):
            if at(f+df,pr)==P: out.append(sq(f+df,pr))
        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: out.append(sq(f+df,r+dr))
        for df,dr in ((1,0),(-1,0),(0,1),(0,-1),(1,1),(1,-1),(-1,1),(-1,-1)):
            kinds=(R,Q) if df==0 or dr==0 else (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: out.append(sq(ff,rr))
                    break
                ff+=df; rr+=dr
        return out
    checkers=attackers(ks, not white)
    if len(checkers)>=2: return False
    if not checkers: return True
    c=checkers[0]
    if to==c: return True
    if b[c].lower() in ('n','p'): return False
    cf,cr=ord(c[0])-97,int(c[1])-1
    kf,kr=ord(ks[0])-97,int(ks[1])-1
    sf=(cf>kf)-(cf<kf); sr=(cr>kr)-(cr<kr)
    f,r=kf+sf,kr+sr
    between=[]
    while (f,r)!=(cf,cr) and 0<=f<8 and 0<=r<8:
        between.append(sq(f,r)); f+=sf; r+=sr
    return to in between
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('no check', {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k'}, 'move': ['b1', 'c3']}, True),
  ('block rook check',
   {'board': {'a8': 'k', 'b1': 'N', 'e1': 'K', 'e8': 'r'}, 'move': ['b1', 'c3']}, False),
  ('interpose on file',
   {'board': {'a8': 'k', 'd1': 'Q', 'e1': 'K', 'e8': 'r'}, 'move': ['d1', 'e2']}, True),
  ('capture rook checker',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'h8': 'R'}, 'move': ['h8', 'e8']}, True),
  ('knight check sidestep piece',
   {'board': {'a8': 'k', 'b2': 'B', 'd3': 'n', 'e1': 'K'}, 'move': ['b2', 'c3']}, False),
  ('bishop takes knight checker',
   {'board': {'a8': 'k', 'e1': 'K', 'f3': 'n', 'g2': 'B'}, 'move': ['g2', 'f3']}, True),
  ('cannot block knight',
   {'board': {'a8': 'k', 'd1': 'Q', 'e1': 'K', 'f3': 'n'}, 'move': ['d1', 'e2']}, False),
  ('double check capture one',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'f3': 'n', 'g2': 'B'}, 'move': ['g2', 'f3']},
   False)],
 [('capture rook checker',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'h8': 'R'}, 'move': ['h8', 'e8']}, True),
  ('knight check sidestep piece',
   {'board': {'a8': 'k', 'b2': 'B', 'd3': 'n', 'e1': 'K'}, 'move': ['b2', 'c3']}, False),
  ('bishop takes knight checker',
   {'board': {'a8': 'k', 'e1': 'K', 'f3': 'n', 'g2': 'B'}, 'move': ['g2', 'f3']}, True),
  ('cannot block knight',
   {'board': {'a8': 'k', 'd1': 'Q', 'e1': 'K', 'f3': 'n'}, 'move': ['d1', 'e2']}, False),
  ('double check block',
   {'board': {'a8': 'k', 'd1': 'Q', 'e1': 'K', 'e8': 'r', 'f3': 'n'}, 'move': ['d1', 'e2']},
   False),
  ('double check capture one',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'f3': 'n', 'g2': 'B'}, 'move': ['g2', 'f3']},
   False),
  ('diagonal interpose',
   {'board': {'a5': 'b', 'c1': 'N', 'e1': 'K', 'h8': 'k'}, 'move': ['c1', 'b3']}, False),
  ('diagonal interpose d2',
   {'board': {'a5': 'b', 'e1': 'K', 'f3': 'N', 'h8': 'k'}, 'move': ['f3', 'd2']}, True)],
 [('cannot block knight',
   {'board': {'a8': 'k', 'd1': 'Q', 'e1': 'K', 'f3': 'n'}, 'move': ['d1', 'e2']}, False),
  ('double check block',
   {'board': {'a8': 'k', 'd1': 'Q', 'e1': 'K', 'e8': 'r', 'f3': 'n'}, 'move': ['d1', 'e2']},
   False),
  ('double check capture one',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'f3': 'n', 'g2': 'B'}, 'move': ['g2', 'f3']},
   False),
  ('diagonal interpose',
   {'board': {'a5': 'b', 'c1': 'N', 'e1': 'K', 'h8': 'k'}, 'move': ['c1', 'b3']}, False),
  ('diagonal interpose d2',
   {'board': {'a5': 'b', 'e1': 'K', 'f3': 'N', 'h8': 'k'}, 'move': ['f3', 'd2']}, True),
  ('black blocks white queen',
   {'board': {'a1': 'K', 'c6': 'n', 'e1': 'Q', 'e8': 'k'}, 'move': ['c6', 'e7']}, True),
  ('black cannot block white knight',
   {'board': {'a1': 'K', 'c8': 'b', 'd6': 'N', 'e8': 'k'}, 'move': ['c8', 'd7']}, False),
  ('irrelevant move in check',
   {'board': {'a2': 'P', 'a8': 'k', 'e1': 'K', 'e8': 'r'}, 'move': ['a2', 'a3']}, False)],
 [('no check', {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k'}, 'move': ['b1', 'c3']}, True),
  ('block rook check',
   {'board': {'a8': 'k', 'b1': 'N', 'e1': 'K', 'e8': 'r'}, 'move': ['b1', 'c3']}, False),
  ('double check capture one',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'f3': 'n', 'g2': 'B'}, 'move': ['g2', 'f3']},
   False),
  ('diagonal interpose d2',
   {'board': {'a5': 'b', 'e1': 'K', 'f3': 'N', 'h8': 'k'}, 'move': ['f3', 'd2']}, True),
  ('black blocks white queen',
   {'board': {'a1': 'K', 'c6': 'n', 'e1': 'Q', 'e8': 'k'}, 'move': ['c6', 'e7']}, True),
  ('black cannot block white knight',
   {'board': {'a1': 'K', 'c8': 'b', 'd6': 'N', 'e8': 'k'}, 'move': ['c8', 'd7']}, False),
  ('irrelevant move in check',
   {'board': {'a2': 'P', 'a8': 'k', 'e1': 'K', 'e8': 'r'}, 'move': ['a2', 'a3']}, False),
  ('rank check interpose',
   {'board': {'a1': 'K', 'a8': 'k', 'b3': 'N', 'h1': 'q'}, 'move': ['b3', 'c1']}, True)],
 [('no check', {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k'}, 'move': ['b1', 'c3']}, True),
  ('block rook check',
   {'board': {'a8': 'k', 'b1': 'N', 'e1': 'K', 'e8': 'r'}, 'move': ['b1', 'c3']}, False),
  ('interpose on file',
   {'board': {'a8': 'k', 'd1': 'Q', 'e1': 'K', 'e8': 'r'}, 'move': ['d1', 'e2']}, True),
  ('capture rook checker',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'h8': 'R'}, 'move': ['h8', 'e8']}, True),
  ('knight check sidestep piece',
   {'board': {'a8': 'k', 'b2': 'B', 'd3': 'n', 'e1': 'K'}, 'move': ['b2', 'c3']}, False),
  ('double check capture one',
   {'board': {'a8': 'k', 'e1': 'K', 'e8': 'r', 'f3': 'n', 'g2': 'B'}, 'move': ['g2', 'f3']},
   False),
  ('irrelevant move in check',
   {'board': {'a2': 'P', 'a8': 'k', 'e1': 'K', 'e8': 'r'}, 'move': ['a2', 'a3']}, False),
  ('rank check interpose',
   {'board': {'a1': 'K', 'a8': 'k', 'b3': 'N', 'h1': 'q'}, 'move': ['b3', 'c1']}, 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)
Boundary fixtureActualExpectedOutcome
no checkTrueTruePassed
block rook checkFalseFalsePassed
interpose on fileTrueTruePassed
capture rook checkerTrueTruePassed
knight check sidestep pieceFalseFalsePassed
bishop takes knight checkerTrueTruePassed
cannot block knightFalseFalsePassed
double check capture oneFalseFalsePassed

SHA-256 / fafe17e1a1c531b6e3c3cb2abec44483c04774536703816d19b41dd29aa878aa

Verification & scope

A deterministic toy model with an explicitly stated contract; boards are {square: piece} with white upper-case and black lower-case pieces; no claim of full FIDE Laws conformance. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

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

Case digest / 676dc3755061db34a8e2b590459ec0fcb71307221d3897374f26fb2bcf9d39e5