FA-82801 / Chess move legality / Open access
Every direct check reported as double check · case 01
A knight check with no other attacker is classified "double".
ROOT CAUSE
The discovered-check scan includes the moved piece itself.
THE FAILURE
The discovered-check scan includes the moved piece itself.
Unsuccessful approach: Excluding the vacated origin square has no effect, since it is already empty.
Case contract
Input: {"board", "move": [from, to] or [from, to, promotion letter]}. Apply the move (promotion letter becomes a piece of the mover's colour) and classify the check it gives to the enemy king: "direct" (the moved piece attacks it), "discovered" (another of the mover's pieces now attacks it), "double" (both) or "none". Pawns attack diagonally forward, sliders need a clear path.
Why this case matters
SAN "+" suffixes and double-check rules both depend on this classification.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
b=dict(x['board']); fr,to=x['move'][:2]; p=b.pop(fr)
if len(x['move'])>2: p=x['move'][2].upper() if p.isupper() else x['move'][2].lower()
b[to]=p
white=p.isupper()
ks=[s for s,v in b.items() if v==('k' if white else 'K')][0]
def hits(src, tgt):
v=b[src]; t=v.upper()
f,r=ord(src[0])-97,int(src[1])-1
tf,tr=ord(tgt[0])-97,int(tgt[1])-1
df,dr=tf-f,tr-r
if t=='P': return abs(df)==1 and dr==(1 if v.isupper() else -1)
if t=='N': return (abs(df),abs(dr)) in ((1,2),(2,1))
if t=='K': return max(abs(df),abs(dr))==1
orth=(df==0)!=(dr==0); diag=abs(df)==abs(dr) and df!=0
if not ((t in ('R','Q') and orth) or (t in ('B','Q') and diag)): return False
sf=(df>0)-(df<0); sr=(dr>0)-(dr<0)
cf,cr=f+sf,r+sr
while (cf,cr)!=(tf,tr):
if chr(97+cf)+str(cr+1) in b: return False
cf+=sf; cr+=sr
return True
direct=hits(to,ks)
disc=any(hits(s,ks) for s,v in b.items() if v.isupper()==white and v.upper()!='K')
if direct and disc: return 'double'
if direct: return 'direct'
if disc: return 'discovered'
return 'none'
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('promotion gives check', {'board': {'a1': 'K', 'b7': 'P', 'e8': 'k'}, 'move': ['b7', 'b8', 'q']},
'direct'),
('knight promotion check',
{'board': {'a1': 'K', 'e7': 'P', 'g7': 'k'}, 'move': ['e7', 'e8', 'n']}, 'direct'),
('discovered by bishop',
{'board': {'a1': 'K', 'c3': 'B', 'd4': 'N', 'h8': 'k'}, 'move': ['d4', 'b5']}, 'discovered'),
('double check', {'board': {'a1': 'K', 'e1': 'R', 'e4': 'N', 'e8': 'k'}, 'move': ['e4', 'f6']},
'double'),
('rook lands on king diagonal',
{'board': {'b1': 'R', 'e1': 'K', 'h8': 'k'}, 'move': ['b1', 'b2']}, 'none'),
('rook quiet', {'board': {'a1': 'R', 'e1': 'K', 'h8': 'k'}, 'move': ['a1', 'b1']}, 'none'),
('defender rook on own king line',
{'board': {'a1': 'K', 'b1': 'N', 'e5': 'r', 'e8': 'k'}, 'move': ['b1', 'c3']}, 'none'),
('black discovered',
{'board': {'a8': 'k', 'e1': 'K', 'e7': 'n', 'e8': 'r'}, 'move': ['e7', 'c6']}, 'discovered')],
[('promotion gives check', {'board': {'a1': 'K', 'b7': 'P', 'e8': 'k'}, 'move': ['b7', 'b8', 'q']},
'direct'),
('knight promotion check',
{'board': {'a1': 'K', 'e7': 'P', 'g7': 'k'}, 'move': ['e7', 'e8', 'n']}, 'direct'),
('simple direct', {'board': {'b1': 'N', 'd4': 'k', 'h1': 'K'}, 'move': ['b1', 'c2']}, 'direct'),
('queen diagonal direct', {'board': {'a2': 'K', 'd1': 'Q', 'h8': 'k'}, 'move': ['d1', 'd4']},
'direct'),
('rook quiet', {'board': {'a1': 'R', 'e1': 'K', 'h8': 'k'}, 'move': ['a1', 'b1']}, 'none'),
('defender rook on own king line',
{'board': {'a1': 'K', 'b1': 'N', 'e5': 'r', 'e8': 'k'}, 'move': ['b1', 'c3']}, 'none'),
('black discovered',
{'board': {'a8': 'k', 'e1': 'K', 'e7': 'n', 'e8': 'r'}, 'move': ['e7', 'c6']}, 'discovered'),
('white piece near own line',
{'board': {'a1': 'K', 'a2': 'r', 'c1': 'B', 'e3': 'P', 'h6': 'k'}, 'move': ['e3', 'e4']},
'discovered')],
[('promotion gives check', {'board': {'a1': 'K', 'b7': 'P', 'e8': 'k'}, 'move': ['b7', 'b8', 'q']},
'direct'),
('knight promotion check',
{'board': {'a1': 'K', 'e7': 'P', 'g7': 'k'}, 'move': ['e7', 'e8', 'n']}, 'direct'),
('simple direct', {'board': {'b1': 'N', 'd4': 'k', 'h1': 'K'}, 'move': ['b1', 'c2']}, 'direct'),
('queen diagonal direct', {'board': {'a2': 'K', 'd1': 'Q', 'h8': 'k'}, 'move': ['d1', 'd4']},
'direct'),
('black rook direct', {'board': {'a8': 'r', 'e1': 'K', 'h8': 'k'}, 'move': ['a8', 'a1']},
'direct'),
('bishop direct', {'board': {'a1': 'K', 'e8': 'k', 'f1': 'B'}, 'move': ['f1', 'b5']}, 'direct'),
('pawn push check', {'board': {'a1': 'K', 'd5': 'P', 'e7': 'k'}, 'move': ['d5', 'd6']}, 'direct'),
('white piece near own line',
{'board': {'a1': 'K', 'a2': 'r', 'c1': 'B', 'e3': 'P', 'h6': 'k'}, 'move': ['e3', 'e4']},
'discovered')],
[('simple direct', {'board': {'b1': 'N', 'd4': 'k', 'h1': 'K'}, 'move': ['b1', 'c2']}, 'direct'),
('discovered by bishop',
{'board': {'a1': 'K', 'c3': 'B', 'd4': 'N', 'h8': 'k'}, 'move': ['d4', 'b5']}, 'discovered'),
('double check', {'board': {'a1': 'K', 'e1': 'R', 'e4': 'N', 'e8': 'k'}, 'move': ['e4', 'f6']},
'double'),
('queen diagonal direct', {'board': {'a2': 'K', 'd1': 'Q', 'h8': 'k'}, 'move': ['d1', 'd4']},
'direct'),
('rook lands on king diagonal',
{'board': {'b1': 'R', 'e1': 'K', 'h8': 'k'}, 'move': ['b1', 'b2']}, 'none'),
('black rook direct', {'board': {'a8': 'r', 'e1': 'K', 'h8': 'k'}, 'move': ['a8', 'a1']},
'direct'),
('bishop direct', {'board': {'a1': 'K', 'e8': 'k', 'f1': 'B'}, 'move': ['f1', 'b5']}, 'direct'),
('pawn push check', {'board': {'a1': 'K', 'd5': 'P', 'e7': 'k'}, 'move': ['d5', 'd6']},
'direct')],
[('discovered by bishop',
{'board': {'a1': 'K', 'c3': 'B', 'd4': 'N', 'h8': 'k'}, 'move': ['d4', 'b5']}, 'discovered'),
('double check', {'board': {'a1': 'K', 'e1': 'R', 'e4': 'N', 'e8': 'k'}, 'move': ['e4', 'f6']},
'double'),
('rook lands on king diagonal',
{'board': {'b1': 'R', 'e1': 'K', 'h8': 'k'}, 'move': ['b1', 'b2']}, 'none'),
('rook quiet', {'board': {'a1': 'R', 'e1': 'K', 'h8': 'k'}, 'move': ['a1', 'b1']}, 'none'),
('black rook direct', {'board': {'a8': 'r', 'e1': 'K', 'h8': 'k'}, 'move': ['a8', 'a1']},
'direct'),
('defender rook on own king line',
{'board': {'a1': 'K', 'b1': 'N', 'e5': 'r', 'e8': 'k'}, 'move': ['b1', 'c3']}, 'none'),
('bishop direct', {'board': {'a1': 'K', 'e8': 'k', 'f1': 'B'}, 'move': ['f1', 'b5']}, 'direct'),
('pawn push check', {'board': {'a1': 'K', 'd5': 'P', 'e7': 'k'}, 'move': ['d5', 'd6']},
'direct')]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| promotion gives check | double | direct | Failed |
| knight promotion check | double | direct | Failed |
| discovered by bishop | discovered | discovered | Passed |
| double check | double | double | Passed |
| rook lands on king diagonal | none | none | Passed |
| rook quiet | none | none | Passed |
| defender rook on own king line | none | none | Passed |
| black discovered | discovered | discovered | Passed |
SHA-256 / ac1731e0e5cc309408a0c69543cf841a5ca5c2ec8a92d80f5d98b246eb79faef
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
b=dict(x['board']); fr,to=x['move'][:2]; p=b.pop(fr)
if len(x['move'])>2: p=x['move'][2].upper() if p.isupper() else x['move'][2].lower()
b[to]=p
white=p.isupper()
ks=[s for s,v in b.items() if v==('k' if white else 'K')][0]
def hits(src, tgt):
v=b[src]; t=v.upper()
f,r=ord(src[0])-97,int(src[1])-1
tf,tr=ord(tgt[0])-97,int(tgt[1])-1
df,dr=tf-f,tr-r
if t=='P': return abs(df)==1 and dr==(1 if v.isupper() else -1)
if t=='N': return (abs(df),abs(dr)) in ((1,2),(2,1))
if t=='K': return max(abs(df),abs(dr))==1
orth=(df==0)!=(dr==0); diag=abs(df)==abs(dr) and df!=0
if not ((t in ('R','Q') and orth) or (t in ('B','Q') and diag)): return False
sf=(df>0)-(df<0); sr=(dr>0)-(dr<0)
cf,cr=f+sf,r+sr
while (cf,cr)!=(tf,tr):
if chr(97+cf)+str(cr+1) in b: return False
cf+=sf; cr+=sr
return True
direct=hits(to,ks)
disc=any(hits(s,ks) for s,v in b.items() if s!=fr and v.isupper()==white and v.upper()!='K')
if direct and disc: return 'double'
if direct: return 'direct'
if disc: return 'discovered'
return 'none'
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('promotion gives check', {'board': {'a1': 'K', 'b7': 'P', 'e8': 'k'}, 'move': ['b7', 'b8', 'q']},
'direct'),
('knight promotion check',
{'board': {'a1': 'K', 'e7': 'P', 'g7': 'k'}, 'move': ['e7', 'e8', 'n']}, 'direct'),
('discovered by bishop',
{'board': {'a1': 'K', 'c3': 'B', 'd4': 'N', 'h8': 'k'}, 'move': ['d4', 'b5']}, 'discovered'),
('double check', {'board': {'a1': 'K', 'e1': 'R', 'e4': 'N', 'e8': 'k'}, 'move': ['e4', 'f6']},
'double'),
('rook lands on king diagonal',
{'board': {'b1': 'R', 'e1': 'K', 'h8': 'k'}, 'move': ['b1', 'b2']}, 'none'),
('rook quiet', {'board': {'a1': 'R', 'e1': 'K', 'h8': 'k'}, 'move': ['a1', 'b1']}, 'none'),
('defender rook on own king line',
{'board': {'a1': 'K', 'b1': 'N', 'e5': 'r', 'e8': 'k'}, 'move': ['b1', 'c3']}, 'none'),
('black discovered',
{'board': {'a8': 'k', 'e1': 'K', 'e7': 'n', 'e8': 'r'}, 'move': ['e7', 'c6']}, 'discovered')],
[('promotion gives check', {'board': {'a1': 'K', 'b7': 'P', 'e8': 'k'}, 'move': ['b7', 'b8', 'q']},
'direct'),
('knight promotion check',
{'board': {'a1': 'K', 'e7': 'P', 'g7': 'k'}, 'move': ['e7', 'e8', 'n']}, 'direct'),
('simple direct', {'board': {'b1': 'N', 'd4': 'k', 'h1': 'K'}, 'move': ['b1', 'c2']}, 'direct'),
('queen diagonal direct', {'board': {'a2': 'K', 'd1': 'Q', 'h8': 'k'}, 'move': ['d1', 'd4']},
'direct'),
('rook quiet', {'board': {'a1': 'R', 'e1': 'K', 'h8': 'k'}, 'move': ['a1', 'b1']}, 'none'),
('defender rook on own king line',
{'board': {'a1': 'K', 'b1': 'N', 'e5': 'r', 'e8': 'k'}, 'move': ['b1', 'c3']}, 'none'),
('black discovered',
{'board': {'a8': 'k', 'e1': 'K', 'e7': 'n', 'e8': 'r'}, 'move': ['e7', 'c6']}, 'discovered'),
('white piece near own line',
{'board': {'a1': 'K', 'a2': 'r', 'c1': 'B', 'e3': 'P', 'h6': 'k'}, 'move': ['e3', 'e4']},
'discovered')],
[('promotion gives check', {'board': {'a1': 'K', 'b7': 'P', 'e8': 'k'}, 'move': ['b7', 'b8', 'q']},
'direct'),
('knight promotion check',
{'board': {'a1': 'K', 'e7': 'P', 'g7': 'k'}, 'move': ['e7', 'e8', 'n']}, 'direct'),
('simple direct', {'board': {'b1': 'N', 'd4': 'k', 'h1': 'K'}, 'move': ['b1', 'c2']}, 'direct'),
('queen diagonal direct', {'board': {'a2': 'K', 'd1': 'Q', 'h8': 'k'}, 'move': ['d1', 'd4']},
'direct'),
('black rook direct', {'board': {'a8': 'r', 'e1': 'K', 'h8': 'k'}, 'move': ['a8', 'a1']},
'direct'),
('bishop direct', {'board': {'a1': 'K', 'e8': 'k', 'f1': 'B'}, 'move': ['f1', 'b5']}, 'direct'),
('pawn push check', {'board': {'a1': 'K', 'd5': 'P', 'e7': 'k'}, 'move': ['d5', 'd6']}, 'direct'),
('white piece near own line',
{'board': {'a1': 'K', 'a2': 'r', 'c1': 'B', 'e3': 'P', 'h6': 'k'}, 'move': ['e3', 'e4']},
'discovered')],
[('simple direct', {'board': {'b1': 'N', 'd4': 'k', 'h1': 'K'}, 'move': ['b1', 'c2']}, 'direct'),
('discovered by bishop',
{'board': {'a1': 'K', 'c3': 'B', 'd4': 'N', 'h8': 'k'}, 'move': ['d4', 'b5']}, 'discovered'),
('double check', {'board': {'a1': 'K', 'e1': 'R', 'e4': 'N', 'e8': 'k'}, 'move': ['e4', 'f6']},
'double'),
('queen diagonal direct', {'board': {'a2': 'K', 'd1': 'Q', 'h8': 'k'}, 'move': ['d1', 'd4']},
'direct'),
('rook lands on king diagonal',
{'board': {'b1': 'R', 'e1': 'K', 'h8': 'k'}, 'move': ['b1', 'b2']}, 'none'),
('black rook direct', {'board': {'a8': 'r', 'e1': 'K', 'h8': 'k'}, 'move': ['a8', 'a1']},
'direct'),
('bishop direct', {'board': {'a1': 'K', 'e8': 'k', 'f1': 'B'}, 'move': ['f1', 'b5']}, 'direct'),
('pawn push check', {'board': {'a1': 'K', 'd5': 'P', 'e7': 'k'}, 'move': ['d5', 'd6']},
'direct')],
[('discovered by bishop',
{'board': {'a1': 'K', 'c3': 'B', 'd4': 'N', 'h8': 'k'}, 'move': ['d4', 'b5']}, 'discovered'),
('double check', {'board': {'a1': 'K', 'e1': 'R', 'e4': 'N', 'e8': 'k'}, 'move': ['e4', 'f6']},
'double'),
('rook lands on king diagonal',
{'board': {'b1': 'R', 'e1': 'K', 'h8': 'k'}, 'move': ['b1', 'b2']}, 'none'),
('rook quiet', {'board': {'a1': 'R', 'e1': 'K', 'h8': 'k'}, 'move': ['a1', 'b1']}, 'none'),
('black rook direct', {'board': {'a8': 'r', 'e1': 'K', 'h8': 'k'}, 'move': ['a8', 'a1']},
'direct'),
('defender rook on own king line',
{'board': {'a1': 'K', 'b1': 'N', 'e5': 'r', 'e8': 'k'}, 'move': ['b1', 'c3']}, 'none'),
('bishop direct', {'board': {'a1': 'K', 'e8': 'k', 'f1': 'B'}, 'move': ['f1', 'b5']}, 'direct'),
('pawn push check', {'board': {'a1': 'K', 'd5': 'P', 'e7': 'k'}, 'move': ['d5', 'd6']},
'direct')]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| promotion gives check | double | direct | Failed |
| knight promotion check | double | direct | Failed |
| discovered by bishop | discovered | discovered | Passed |
| double check | double | double | Passed |
| rook lands on king diagonal | none | none | Passed |
| rook quiet | none | none | Passed |
| defender rook on own king line | none | none | Passed |
| black discovered | discovered | discovered | Passed |
SHA-256 / 5e7d4370ca61f0cca0eafe6ec25a0d8819a3f4c78427203da15d5dc6b4a4afe5
HELD IN THE MEMBER ARCHIVE
The verified repair and its recorded checks are member-only.
This mechanism has 8 recorded checks per implementation. The open-access tier publishes the failure and the unsuccessful fix; the repaired source that passes every check, and the observations that prove it, are available to members.
Every case sharing this mechanism uses the same contract and the same repair, so this one record is held back for all of them.
Member access is invitation-based. Sign in with your invited account to inspect the repair.
Sign in to the archive ↗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:15.428667+00:00.
Case digest / 2eb2986480a6d9ae8d499d3d5f671167b91c0f3d2661a21e314e1c9f5656e353