FAILURE MAP
← Case archive

FA-82411 / Chess move legality / Open access

En passant looks for the victim on the target square · case 01

Every en passant capture is rejected because the target square is empty.

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

ROOT CAUSE

The captured pawn is assumed to stand on the destination, but in en passant it stands beside the capturer on the origin rank.

THE FAILURE

The captured pawn is assumed to stand on the destination, but in en passant it stands beside the capturer on the origin rank.

Unsuccessful approach: Using the origin file and destination rank points at the empty square in front of the capturer.

Case contract

Input: {"board", "move": [from, to], "ep": target square or null}. Return true when the move is a legal en passant capture: a pawn on its fifth rank moves diagonally forward onto the ep square, an enemy pawn stands beside it on the origin rank, and after removing both pawns from their squares and placing the capturer, no enemy rook, bishop or queen attacks the mover's king along an open line.

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=dict(x['board']); fr,to=x['move']; p=b.get(fr)
    if p not in ('P','p') or to!=x['ep']: return False
    white=p=='P'
    d=1 if white else -1
    f0,r0=ord(fr[0])-97,int(fr[1])-1
    f1,r1=ord(to[0])-97,int(to[1])-1
    if r1-r0!=d or abs(f1-f0)!=1: return False
    if r0!=(4 if white else 3): return False
    victim=to
    if b.get(victim)!=('p' if white else 'P'): return False
    del b[fr]; del b[victim]; b[to]=p
    ks=[s for s,v in b.items() if v==('K' if white else 'k')][0]
    kf,kr=ord(ks[0])-97,int(ks[1])-1
    for df,dr in ((1,0),(-1,0),(0,1),(0,-1),(1,1),(1,-1),(-1,1),(-1,-1)):
        cf,cr=kf+df,kr+dr
        while 0<=cf<8 and 0<=cr<8:
            v=b.get(chr(97+cf)+str(cr+1))
            if v:
                if v.isupper()!=white and v.lower() in (('r','q') if df==0 or dr==0 else ('b','q')): return False
                break
            cf+=df; cr+=dr
    return True
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('plain ep',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k'}, 'ep': 'd6', 'move': ['e5', 'd6']},
   True),
  ('black ep',
   {'board': {'d4': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'ep': 'e3', 'move': ['d4', 'e3']},
   True),
  ('rank pin both pawns',
   {'board': {'a5': 'K', 'd5': 'p', 'e5': 'P', 'e8': 'k', 'h5': 'r'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   False),
  ('rank pin black side',
   {'board': {'a4': 'Q', 'd4': 'p', 'e1': 'K', 'e4': 'P', 'h4': 'k'},
    'ep': 'e3',
    'move': ['d4', 'e3']},
   False),
  ('no ep square',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k'}, 'ep': None, 'move': ['e5', 'd6']},
   False),
  ('wrong target',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k', 'f5': 'p'},
    'ep': 'd6',
    'move': ['e5', 'f6']},
   False),
  ('wrong rank for white',
   {'board': {'d4': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'ep': 'd5', 'move': ['e4', 'd5']},
   False),
  ('black wrong rank',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k'}, 'ep': 'e4', 'move': ['d5', 'e4']},
   False)],
 [('plain ep',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k'}, 'ep': 'd6', 'move': ['e5', 'd6']},
   True),
  ('black ep',
   {'board': {'d4': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'ep': 'e3', 'move': ['d4', 'e3']},
   True),
  ('bishop diagonal after ep',
   {'board': {'c3': 'K', 'e5': 'P', 'e8': 'k', 'f5': 'p', 'f6': 'n', 'h8': 'b'},
    'ep': 'f6',
    'move': ['e5', 'f6']},
   True),
  ('wrong target',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k', 'f5': 'p'},
    'ep': 'd6',
    'move': ['e5', 'f6']},
   False),
  ('wrong rank for white',
   {'board': {'d4': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'ep': 'd5', 'move': ['e4', 'd5']},
   False),
  ('black wrong rank',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k'}, 'ep': 'e4', 'move': ['d5', 'e4']},
   False),
  ('same file ep target',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k'}, 'ep': 'd3', 'move': ['e5', 'd6']},
   False),
  ('rook on file of ep square',
   {'board': {'a1': 'K', 'd1': 'r', 'd5': 'p', 'e5': 'P', 'e8': 'k'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   False)],
 [('plain ep',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k'}, 'ep': 'd6', 'move': ['e5', 'd6']},
   True),
  ('black ep',
   {'board': {'d4': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'ep': 'e3', 'move': ['d4', 'e3']},
   True),
  ('bishop diagonal after ep',
   {'board': {'c3': 'K', 'e5': 'P', 'e8': 'k', 'f5': 'p', 'f6': 'n', 'h8': 'b'},
    'ep': 'f6',
    'move': ['e5', 'f6']},
   True),
  ('file rook behind pawn',
   {'board': {'d1': 'K', 'd5': 'p', 'd8': 'r', 'e5': 'P', 'e8': 'k'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   True),
  ('same file ep target',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k'}, 'ep': 'd3', 'move': ['e5', 'd6']},
   False),
  ('pin by own rook harmless',
   {'board': {'a5': 'K', 'd5': 'p', 'e5': 'P', 'e8': 'k', 'h5': 'R'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   True),
  ('bishop on the rank',
   {'board': {'a5': 'K', 'd5': 'p', 'e5': 'P', 'e8': 'k', 'h5': 'b'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   True),
  ('rook on file of ep square',
   {'board': {'a1': 'K', 'd1': 'r', 'd5': 'p', 'e5': 'P', 'e8': 'k'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   False)],
 [('black ep',
   {'board': {'d4': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'ep': 'e3', 'move': ['d4', 'e3']},
   True),
  ('rank pin both pawns',
   {'board': {'a5': 'K', 'd5': 'p', 'e5': 'P', 'e8': 'k', 'h5': 'r'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   False),
  ('rank pin black side',
   {'board': {'a4': 'Q', 'd4': 'p', 'e1': 'K', 'e4': 'P', 'h4': 'k'},
    'ep': 'e3',
    'move': ['d4', 'e3']},
   False),
  ('bishop diagonal after ep',
   {'board': {'c3': 'K', 'e5': 'P', 'e8': 'k', 'f5': 'p', 'f6': 'n', 'h8': 'b'},
    'ep': 'f6',
    'move': ['e5', 'f6']},
   True),
  ('file rook behind pawn',
   {'board': {'d1': 'K', 'd5': 'p', 'd8': 'r', 'e5': 'P', 'e8': 'k'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   True),
  ('pin by own rook harmless',
   {'board': {'a5': 'K', 'd5': 'p', 'e5': 'P', 'e8': 'k', 'h5': 'R'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   True),
  ('bishop on the rank',
   {'board': {'a5': 'K', 'd5': 'p', 'e5': 'P', 'e8': 'k', 'h5': 'b'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   True),
  ('rook on the diagonal',
   {'board': {'c3': 'K', 'd5': 'p', 'e5': 'P', 'e8': 'k', 'g7': 'r'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   True)],
 [('rank pin both pawns',
   {'board': {'a5': 'K', 'd5': 'p', 'e5': 'P', 'e8': 'k', 'h5': 'r'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   False),
  ('rank pin black side',
   {'board': {'a4': 'Q', 'd4': 'p', 'e1': 'K', 'e4': 'P', 'h4': 'k'},
    'ep': 'e3',
    'move': ['d4', 'e3']},
   False),
  ('no ep square',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k'}, 'ep': None, 'move': ['e5', 'd6']},
   False),
  ('wrong target',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k', 'f5': 'p'},
    'ep': 'd6',
    'move': ['e5', 'f6']},
   False),
  ('wrong rank for white',
   {'board': {'d4': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'ep': 'd5', 'move': ['e4', 'd5']},
   False),
  ('pin by own rook harmless',
   {'board': {'a5': 'K', 'd5': 'p', 'e5': 'P', 'e8': 'k', 'h5': 'R'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   True),
  ('bishop on the rank',
   {'board': {'a5': 'K', 'd5': 'p', 'e5': 'P', 'e8': 'k', 'h5': 'b'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   True),
  ('rook on the diagonal',
   {'board': {'c3': 'K', 'd5': 'p', 'e5': 'P', 'e8': 'k', 'g7': 'r'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   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
plain epFalseTrueFailed
black epFalseTrueFailed
rank pin both pawnsFalseFalsePassed
rank pin black sideFalseFalsePassed
no ep squareFalseFalsePassed
wrong targetFalseFalsePassed
wrong rank for whiteFalseFalsePassed
black wrong rankFalseFalsePassed

SHA-256 / a107ea465041c86e5133167c2d62973f6c77a77d4f41e13062b2675798ff5b37

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']; p=b.get(fr)
    if p not in ('P','p') or to!=x['ep']: return False
    white=p=='P'
    d=1 if white else -1
    f0,r0=ord(fr[0])-97,int(fr[1])-1
    f1,r1=ord(to[0])-97,int(to[1])-1
    if r1-r0!=d or abs(f1-f0)!=1: return False
    if r0!=(4 if white else 3): return False
    victim=fr[0]+to[1]
    if b.get(victim)!=('p' if white else 'P'): return False
    del b[fr]; del b[victim]; b[to]=p
    ks=[s for s,v in b.items() if v==('K' if white else 'k')][0]
    kf,kr=ord(ks[0])-97,int(ks[1])-1
    for df,dr in ((1,0),(-1,0),(0,1),(0,-1),(1,1),(1,-1),(-1,1),(-1,-1)):
        cf,cr=kf+df,kr+dr
        while 0<=cf<8 and 0<=cr<8:
            v=b.get(chr(97+cf)+str(cr+1))
            if v:
                if v.isupper()!=white and v.lower() in (('r','q') if df==0 or dr==0 else ('b','q')): return False
                break
            cf+=df; cr+=dr
    return True
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('plain ep',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k'}, 'ep': 'd6', 'move': ['e5', 'd6']},
   True),
  ('black ep',
   {'board': {'d4': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'ep': 'e3', 'move': ['d4', 'e3']},
   True),
  ('rank pin both pawns',
   {'board': {'a5': 'K', 'd5': 'p', 'e5': 'P', 'e8': 'k', 'h5': 'r'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   False),
  ('rank pin black side',
   {'board': {'a4': 'Q', 'd4': 'p', 'e1': 'K', 'e4': 'P', 'h4': 'k'},
    'ep': 'e3',
    'move': ['d4', 'e3']},
   False),
  ('no ep square',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k'}, 'ep': None, 'move': ['e5', 'd6']},
   False),
  ('wrong target',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k', 'f5': 'p'},
    'ep': 'd6',
    'move': ['e5', 'f6']},
   False),
  ('wrong rank for white',
   {'board': {'d4': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'ep': 'd5', 'move': ['e4', 'd5']},
   False),
  ('black wrong rank',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k'}, 'ep': 'e4', 'move': ['d5', 'e4']},
   False)],
 [('plain ep',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k'}, 'ep': 'd6', 'move': ['e5', 'd6']},
   True),
  ('black ep',
   {'board': {'d4': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'ep': 'e3', 'move': ['d4', 'e3']},
   True),
  ('bishop diagonal after ep',
   {'board': {'c3': 'K', 'e5': 'P', 'e8': 'k', 'f5': 'p', 'f6': 'n', 'h8': 'b'},
    'ep': 'f6',
    'move': ['e5', 'f6']},
   True),
  ('wrong target',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k', 'f5': 'p'},
    'ep': 'd6',
    'move': ['e5', 'f6']},
   False),
  ('wrong rank for white',
   {'board': {'d4': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'ep': 'd5', 'move': ['e4', 'd5']},
   False),
  ('black wrong rank',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k'}, 'ep': 'e4', 'move': ['d5', 'e4']},
   False),
  ('same file ep target',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k'}, 'ep': 'd3', 'move': ['e5', 'd6']},
   False),
  ('rook on file of ep square',
   {'board': {'a1': 'K', 'd1': 'r', 'd5': 'p', 'e5': 'P', 'e8': 'k'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   False)],
 [('plain ep',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k'}, 'ep': 'd6', 'move': ['e5', 'd6']},
   True),
  ('black ep',
   {'board': {'d4': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'ep': 'e3', 'move': ['d4', 'e3']},
   True),
  ('bishop diagonal after ep',
   {'board': {'c3': 'K', 'e5': 'P', 'e8': 'k', 'f5': 'p', 'f6': 'n', 'h8': 'b'},
    'ep': 'f6',
    'move': ['e5', 'f6']},
   True),
  ('file rook behind pawn',
   {'board': {'d1': 'K', 'd5': 'p', 'd8': 'r', 'e5': 'P', 'e8': 'k'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   True),
  ('same file ep target',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k'}, 'ep': 'd3', 'move': ['e5', 'd6']},
   False),
  ('pin by own rook harmless',
   {'board': {'a5': 'K', 'd5': 'p', 'e5': 'P', 'e8': 'k', 'h5': 'R'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   True),
  ('bishop on the rank',
   {'board': {'a5': 'K', 'd5': 'p', 'e5': 'P', 'e8': 'k', 'h5': 'b'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   True),
  ('rook on file of ep square',
   {'board': {'a1': 'K', 'd1': 'r', 'd5': 'p', 'e5': 'P', 'e8': 'k'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   False)],
 [('black ep',
   {'board': {'d4': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'ep': 'e3', 'move': ['d4', 'e3']},
   True),
  ('rank pin both pawns',
   {'board': {'a5': 'K', 'd5': 'p', 'e5': 'P', 'e8': 'k', 'h5': 'r'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   False),
  ('rank pin black side',
   {'board': {'a4': 'Q', 'd4': 'p', 'e1': 'K', 'e4': 'P', 'h4': 'k'},
    'ep': 'e3',
    'move': ['d4', 'e3']},
   False),
  ('bishop diagonal after ep',
   {'board': {'c3': 'K', 'e5': 'P', 'e8': 'k', 'f5': 'p', 'f6': 'n', 'h8': 'b'},
    'ep': 'f6',
    'move': ['e5', 'f6']},
   True),
  ('file rook behind pawn',
   {'board': {'d1': 'K', 'd5': 'p', 'd8': 'r', 'e5': 'P', 'e8': 'k'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   True),
  ('pin by own rook harmless',
   {'board': {'a5': 'K', 'd5': 'p', 'e5': 'P', 'e8': 'k', 'h5': 'R'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   True),
  ('bishop on the rank',
   {'board': {'a5': 'K', 'd5': 'p', 'e5': 'P', 'e8': 'k', 'h5': 'b'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   True),
  ('rook on the diagonal',
   {'board': {'c3': 'K', 'd5': 'p', 'e5': 'P', 'e8': 'k', 'g7': 'r'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   True)],
 [('rank pin both pawns',
   {'board': {'a5': 'K', 'd5': 'p', 'e5': 'P', 'e8': 'k', 'h5': 'r'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   False),
  ('rank pin black side',
   {'board': {'a4': 'Q', 'd4': 'p', 'e1': 'K', 'e4': 'P', 'h4': 'k'},
    'ep': 'e3',
    'move': ['d4', 'e3']},
   False),
  ('no ep square',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k'}, 'ep': None, 'move': ['e5', 'd6']},
   False),
  ('wrong target',
   {'board': {'d5': 'p', 'e1': 'K', 'e5': 'P', 'e8': 'k', 'f5': 'p'},
    'ep': 'd6',
    'move': ['e5', 'f6']},
   False),
  ('wrong rank for white',
   {'board': {'d4': 'p', 'e1': 'K', 'e4': 'P', 'e8': 'k'}, 'ep': 'd5', 'move': ['e4', 'd5']},
   False),
  ('pin by own rook harmless',
   {'board': {'a5': 'K', 'd5': 'p', 'e5': 'P', 'e8': 'k', 'h5': 'R'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   True),
  ('bishop on the rank',
   {'board': {'a5': 'K', 'd5': 'p', 'e5': 'P', 'e8': 'k', 'h5': 'b'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   True),
  ('rook on the diagonal',
   {'board': {'c3': 'K', 'd5': 'p', 'e5': 'P', 'e8': 'k', 'g7': 'r'},
    'ep': 'd6',
    'move': ['e5', 'd6']},
   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
plain epFalseTrueFailed
black epFalseTrueFailed
rank pin both pawnsFalseFalsePassed
rank pin black sideFalseFalsePassed
no ep squareFalseFalsePassed
wrong targetFalseFalsePassed
wrong rank for whiteFalseFalsePassed
black wrong rankFalseFalsePassed

SHA-256 / 71eeaf20d0802763282c91b5fe3ca587ae194ae1862a635cdbfc94ea84eaff09

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

Case digest / 38766bf2190dfd43d5192ad6000eaac02e265cfed2fb59913e048d7b8da08883