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

N = 1
observations = []
def solve(x):
    b=x['board']; fr,to=x['from'],x['to']; p=b[fr]; white=p.isupper()
    def c(q): return ord(q[0])-97,int(q[1])-1
    def reach(q):
        f,r=c(q); tf,tr=c(to); df,dr=tf-f,tr-r
        t=p.upper()
        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=='R' and orth) or (t=='B' and diag) or (t=='Q' and (orth or 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
    others=[q for q,v in b.items() if v.upper()==p.upper() and q!=fr and reach(q)]
    dis=''
    if others:
        if all(q[0]!=fr[0] for q in others): dis=fr[0]
        elif all(q[1]!=fr[1] for q in others): dis=fr[1]
        else: dis=fr
    cap='x' if to in b else ''
    return p.upper()+dis+cap+to
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')],
 [('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4'),
  ('capture with file',
   {'board': {'a1': 'K', 'a8': 'k', 'c3': 'N', 'e4': 'p', 'g3': 'N'}, 'from': 'c3', 'to': 'e4'},
   'Ncxe4'),
  ('simple bishop', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'from': 'c1', 'to': 'g5'}, 'Bg5'),
  ('rooks on same rank',
   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('capture with file',
   {'board': {'a1': 'K', 'a8': 'k', 'c3': 'N', 'e4': 'p', 'g3': 'N'}, 'from': 'c3', 'to': 'e4'},
   'Ncxe4'),
  ('simple bishop', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'from': 'c1', 'to': 'g5'}, 'Bg5'),
  ('rooks on same rank',
   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')]]
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):
    b=x['board']; fr,to=x['from'],x['to']; p=b[fr]; white=p.isupper()
    def c(q): return ord(q[0])-97,int(q[1])-1
    def reach(q):
        f,r=c(q); tf,tr=c(to); df,dr=tf-f,tr-r
        t=p.upper()
        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=='R' and orth) or (t=='B' and diag) or (t=='Q' and (orth or 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
    others=[q for q,v in b.items() if v==p.upper() and q!=fr and reach(q)]
    dis=''
    if others:
        if all(q[0]!=fr[0] for q in others): dis=fr[0]
        elif all(q[1]!=fr[1] for q in others): dis=fr[1]
        else: dis=fr
    cap='x' if to in b else ''
    return p.upper()+dis+cap+to
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')],
 [('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4'),
  ('capture with file',
   {'board': {'a1': 'K', 'a8': 'k', 'c3': 'N', 'e4': 'p', 'g3': 'N'}, 'from': 'c3', 'to': 'e4'},
   'Ncxe4'),
  ('simple bishop', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'from': 'c1', 'to': 'g5'}, 'Bg5'),
  ('rooks on same rank',
   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('capture with file',
   {'board': {'a1': 'K', 'a8': 'k', 'c3': 'N', 'e4': 'p', 'g3': 'N'}, 'from': 'c3', 'to': 'e4'},
   'Ncxe4'),
  ('simple bishop', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'from': 'c1', 'to': 'g5'}, 'Bg5'),
  ('rooks on same rank',
   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')]]
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:
With a black knight on f3, the white move Nb1-d2 is written "Nbd2".

Input: {"board", "from", "to"} for a knight, bishop, rook, queen or king move. Return SAN (no check suffix): upper-case piece letter, then a disambiguator only if another same-colour piece of the same type could also reach the target (sliders need a clear path): the origin file if it is unique among those pieces, else the origin rank if unique, else the full origin square; then "x" if the target is occupied; then the target.

split: open-access


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

N = 1
observations = []
def solve(x):
    b=x['board']; fr,to=x['from'],x['to']; p=b[fr]; white=p.isupper()
    def c(q): return ord(q[0])-97,int(q[1])-1
    def reach(q):
        f,r=c(q); tf,tr=c(to); df,dr=tf-f,tr-r
        t=p.upper()
        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=='R' and orth) or (t=='B' and diag) or (t=='Q' and (orth or 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
    others=[q for q,v in b.items() if v==p and q!=fr and reach(q)]
    dis=''
    if others:
        if all(q[1]!=fr[1] for q in others): dis=fr[1]
        elif all(q[0]!=fr[0] for q in others): dis=fr[0]
        else: dis=fr
    cap='x' if to in b else ''
    return p.upper()+dis+cap+to
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4'),
  ('capture with file',
   {'board': {'a1': 'K', 'a8': 'k', 'c3': 'N', 'e4': 'p', 'g3': 'N'}, 'from': 'c3', 'to': 'e4'},
   'Ncxe4'),
  ('simple bishop', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'from': 'c1', 'to': 'g5'}, 'Bg5'),
  ('rooks on same rank',
   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('rooks on same rank',
   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')]]
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):
    b=x['board']; fr,to=x['from'],x['to']; p=b[fr]; white=p.isupper()
    def c(q): return ord(q[0])-97,int(q[1])-1
    def reach(q):
        f,r=c(q); tf,tr=c(to); df,dr=tf-f,tr-r
        t=p.upper()
        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=='R' and orth) or (t=='B' and diag) or (t=='Q' and (orth or 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
    others=[q for q,v in b.items() if v==p and q!=fr and reach(q)]
    dis=''
    if others:
        dis=fr[0]
    cap='x' if to in b else ''
    return p.upper()+dis+cap+to
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4'),
  ('capture with file',
   {'board': {'a1': 'K', 'a8': 'k', 'c3': 'N', 'e4': 'p', 'g3': 'N'}, 'from': 'c3', 'to': 'e4'},
   'Ncxe4'),
  ('simple bishop', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'from': 'c1', 'to': 'g5'}, 'Bg5'),
  ('rooks on same rank',
   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('rooks on same rank',
   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')]]
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:
Nb1-d2 with a knight on f3 is written "N1d2" instead of "Nbd2".

Input: {"board", "from", "to"} for a knight, bishop, rook, queen or king move. Return SAN (no check suffix): upper-case piece letter, then a disambiguator only if another same-colour piece of the same type could also reach the target (sliders need a clear path): the origin file if it is unique among those pieces, else the origin rank if unique, else the full origin square; then "x" if the target is occupied; then the target.

split: open-access


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

N = 1
observations = []
def solve(x):
    b=x['board']; fr,to=x['from'],x['to']; p=b[fr]; white=p.isupper()
    def c(q): return ord(q[0])-97,int(q[1])-1
    def reach(q):
        f,r=c(q); tf,tr=c(to); df,dr=tf-f,tr-r
        t=p.upper()
        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=='R' and orth) or (t=='B' and diag) or (t=='Q' and (orth or diag))): return False
        sf=(df>0)-(df<0); sr=(dr>0)-(dr<0)
        return True
    others=[q for q,v in b.items() if v==p and q!=fr and reach(q)]
    dis=''
    if others:
        if all(q[0]!=fr[0] for q in others): dis=fr[0]
        elif all(q[1]!=fr[1] for q in others): dis=fr[1]
        else: dis=fr
    cap='x' if to in b else ''
    return p.upper()+dis+cap+to
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')],
 [('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4'),
  ('capture with file',
   {'board': {'a1': 'K', 'a8': 'k', 'c3': 'N', 'e4': 'p', 'g3': 'N'}, 'from': 'c3', 'to': 'e4'},
   'Ncxe4'),
  ('simple bishop', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'from': 'c1', 'to': 'g5'}, 'Bg5'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4'),
  ('capture with file',
   {'board': {'a1': 'K', 'a8': 'k', 'c3': 'N', 'e4': 'p', 'g3': 'N'}, 'from': 'c3', 'to': 'e4'},
   'Ncxe4'),
  ('simple bishop', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'from': 'c1', 'to': 'g5'}, 'Bg5'),
  ('rooks on same rank',
   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('rooks on same rank',
   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')]]
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):
    b=x['board']; fr,to=x['from'],x['to']; p=b[fr]; white=p.isupper()
    def c(q): return ord(q[0])-97,int(q[1])-1
    def reach(q):
        f,r=c(q); tf,tr=c(to); df,dr=tf-f,tr-r
        t=p.upper()
        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=='R' and orth) or (t=='B' and diag) or (t=='Q' and (orth or diag))): return False
        sf=(df>0)-(df<0); sr=(dr>0)-(dr<0)
        cf,cr=f+sf,r+sr
        if (cf,cr)!=(tf,tr) and chr(97+cf)+str(cr+1) in b: return False
        return True
    others=[q for q,v in b.items() if v==p and q!=fr and reach(q)]
    dis=''
    if others:
        if all(q[0]!=fr[0] for q in others): dis=fr[0]
        elif all(q[1]!=fr[1] for q in others): dis=fr[1]
        else: dis=fr
    cap='x' if to in b else ''
    return p.upper()+dis+cap+to
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')],
 [('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4'),
  ('capture with file',
   {'board': {'a1': 'K', 'a8': 'k', 'c3': 'N', 'e4': 'p', 'g3': 'N'}, 'from': 'c3', 'to': 'e4'},
   'Ncxe4'),
  ('simple bishop', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'from': 'c1', 'to': 'g5'}, 'Bg5'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4'),
  ('capture with file',
   {'board': {'a1': 'K', 'a8': 'k', 'c3': 'N', 'e4': 'p', 'g3': 'N'}, 'from': 'c3', 'to': 'e4'},
   'Ncxe4'),
  ('simple bishop', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'from': 'c1', 'to': 'g5'}, 'Bg5'),
  ('rooks on same rank',
   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('rooks on same rank',
   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')]]
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:
Rh1-d1 with the a1 rook shielded by a bishop on c1 is written "Rhd1".

Input: {"board", "from", "to"} for a knight, bishop, rook, queen or king move. Return SAN (no check suffix): upper-case piece letter, then a disambiguator only if another same-colour piece of the same type could also reach the target (sliders need a clear path): the origin file if it is unique among those pieces, else the origin rank if unique, else the full origin square; then "x" if the target is occupied; then the target.

split: open-access


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

N = 1
observations = []
def solve(x):
    b=x['board']; fr,to=x['from'],x['to']; p=b[fr]; white=p.isupper()
    def c(q): return ord(q[0])-97,int(q[1])-1
    def reach(q):
        f,r=c(q); tf,tr=c(to); df,dr=tf-f,tr-r
        t=p.upper()
        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=='R' and orth) or (t=='B' and diag) or (t=='Q' and (orth or 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
    others=[q for q,v in b.items() if v==p and q!=fr and reach(q)]
    dis=''
    if others:
        if all(q[0]!=fr[0] for q in others): dis=fr[0]
        elif all(q[1]!=fr[1] for q in others): dis=fr[1]
        else: dis=fr
    cap='x' if to in b else ''
    return p+dis+cap+to
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')],
 [('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4'),
  ('capture with file',
   {'board': {'a1': 'K', 'a8': 'k', 'c3': 'N', 'e4': 'p', 'g3': 'N'}, 'from': 'c3', 'to': 'e4'},
   'Ncxe4'),
  ('simple bishop', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'from': 'c1', 'to': 'g5'}, 'Bg5'),
  ('rooks on same rank',
   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('capture with file',
   {'board': {'a1': 'K', 'a8': 'k', 'c3': 'N', 'e4': 'p', 'g3': 'N'}, 'from': 'c3', 'to': 'e4'},
   'Ncxe4'),
  ('simple bishop', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'from': 'c1', 'to': 'g5'}, 'Bg5'),
  ('rooks on same rank',
   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')]]
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):
    b=x['board']; fr,to=x['from'],x['to']; p=b[fr]; white=p.isupper()
    def c(q): return ord(q[0])-97,int(q[1])-1
    def reach(q):
        f,r=c(q); tf,tr=c(to); df,dr=tf-f,tr-r
        t=p.upper()
        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=='R' and orth) or (t=='B' and diag) or (t=='Q' and (orth or 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
    others=[q for q,v in b.items() if v==p and q!=fr and reach(q)]
    dis=''
    if others:
        if all(q[0]!=fr[0] for q in others): dis=fr[0]
        elif all(q[1]!=fr[1] for q in others): dis=fr[1]
        else: dis=fr
    cap='x' if to in b else ''
    return ('N' if p in 'Nn' else p)+dis+cap+to
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')],
 [('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4'),
  ('capture with file',
   {'board': {'a1': 'K', 'a8': 'k', 'c3': 'N', 'e4': 'p', 'g3': 'N'}, 'from': 'c3', 'to': 'e4'},
   'Ncxe4'),
  ('simple bishop', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'from': 'c1', 'to': 'g5'}, 'Bg5'),
  ('rooks on same rank',
   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('capture with file',
   {'board': {'a1': 'K', 'a8': 'k', 'c3': 'N', 'e4': 'p', 'g3': 'N'}, 'from': 'c3', 'to': 'e4'},
   'Ncxe4'),
  ('simple bishop', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'from': 'c1', 'to': 'g5'}, 'Bg5'),
  ('rooks on same rank',
   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')]]
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 rook capture is written "rxa2".

Input: {"board", "from", "to"} for a knight, bishop, rook, queen or king move. Return SAN (no check suffix): upper-case piece letter, then a disambiguator only if another same-colour piece of the same type could also reach the target (sliders need a clear path): the origin file if it is unique among those pieces, else the origin rank if unique, else the full origin square; then "x" if the target is occupied; then the target.

split: open-access


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

N = 1
observations = []
def solve(x):
    b=x['board']; fr,to=x['from'],x['to']; p=b[fr]; white=p.isupper()
    def c(q): return ord(q[0])-97,int(q[1])-1
    def reach(q):
        f,r=c(q); tf,tr=c(to); df,dr=tf-f,tr-r
        t=p.upper()
        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=='R' and orth) or (t=='B' and diag) or (t=='Q' and orth)): 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
    others=[q for q,v in b.items() if v==p and q!=fr and reach(q)]
    dis=''
    if others:
        if all(q[0]!=fr[0] for q in others): dis=fr[0]
        elif all(q[1]!=fr[1] for q in others): dis=fr[1]
        else: dis=fr
    cap='x' if to in b else ''
    return p.upper()+dis+cap+to
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')],
 [('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4'),
  ('capture with file',
   {'board': {'a1': 'K', 'a8': 'k', 'c3': 'N', 'e4': 'p', 'g3': 'N'}, 'from': 'c3', 'to': 'e4'},
   'Ncxe4'),
  ('simple bishop', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'from': 'c1', 'to': 'g5'}, 'Bg5'),
  ('rooks on same rank',
   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4'),
  ('capture with file',
   {'board': {'a1': 'K', 'a8': 'k', 'c3': 'N', 'e4': 'p', 'g3': 'N'}, 'from': 'c3', 'to': 'e4'},
   'Ncxe4'),
  ('simple bishop', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'from': 'c1', 'to': 'g5'}, 'Bg5'),
  ('rooks on same rank',
   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')]]
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):
    b=x['board']; fr,to=x['from'],x['to']; p=b[fr]; white=p.isupper()
    def c(q): return ord(q[0])-97,int(q[1])-1
    def reach(q):
        f,r=c(q); tf,tr=c(to); df,dr=tf-f,tr-r
        t=p.upper()
        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=='R' and orth) or (t=='B' and diag) or (t=='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
    others=[q for q,v in b.items() if v==p and q!=fr and reach(q)]
    dis=''
    if others:
        if all(q[0]!=fr[0] for q in others): dis=fr[0]
        elif all(q[1]!=fr[1] for q in others): dis=fr[1]
        else: dis=fr
    cap='x' if to in b else ''
    return p.upper()+dis+cap+to
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')],
 [('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4'),
  ('capture with file',
   {'board': {'a1': 'K', 'a8': 'k', 'c3': 'N', 'e4': 'p', 'g3': 'N'}, 'from': 'c3', 'to': 'e4'},
   'Ncxe4'),
  ('simple bishop', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'from': 'c1', 'to': 'g5'}, 'Bg5'),
  ('rooks on same rank',
   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4'),
  ('capture with file',
   {'board': {'a1': 'K', 'a8': 'k', 'c3': 'N', 'e4': 'p', 'g3': 'N'}, 'from': 'c3', 'to': 'e4'},
   'Ncxe4'),
  ('simple bishop', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'from': 'c1', 'to': 'g5'}, 'Bg5'),
  ('rooks on same rank',
   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4'),
  ('rook shielded by bishop',
   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},
   'Rd4')],
 [('two knights different files',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),
  ('two rooks same file',
   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),
  ('three queens need square',
   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},
   'Qh4e1'),
  ('blocked rook no disambiguation',
   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},
   'Rd1'),
  ('enemy knight irrelevant',
   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),
  ('black knights',
   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),
  ('black rook capture',
   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),
  ('queen diagonal twin',
   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')]]
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:
Qa1-d4 with another queen able to reach d4 diagonally is written without a disambiguator.

Input: {"board", "from", "to"} for a knight, bishop, rook, queen or king move. Return SAN (no check suffix): upper-case piece letter, then a disambiguator only if another same-colour piece of the same type could also reach the target (sliders need a clear path): the origin file if it is unique among those pieces, else the origin rank if unique, else the full origin square; then "x" if the target is occupied; then the target.

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'; rank='1' if white else '8'
    kf=ord(x['king_from'][0])-97; rf=ord(x['rook_from'][0])-97
    if b.get(x['king_from'])!=('K' if white else 'k') or b.get(x['rook_from'])!=('R' if white else 'r'): return False
    if x['wing']=='K':
        if rf<kf: return False
        kd,rd=kf+2,kf+1
    else:
        if rf>kf: return False
        kd,rd=2,3
    lo=min(kf,kd,rf,rd); hi=max(kf,kd,rf,rd)
    for f in range(lo,hi+1):
        q=chr(97+f)+rank
        if q in b and f not in (kf,rf): return False
    step=1 if kd>=kf else -1
    for f in range(kf,kd+step,step):
        if attacked(b, chr(97+f)+rank, not white): return False
    return True
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('king b1 rook a1 queenside',
   {'board': {'a1': 'R', 'b1': 'K', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   True),
  ('king b1 rook c1 kingside',
   {'board': {'b1': 'K', 'c1': 'R', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king f1 rook h1',
   {'board': {'e8': 'k', 'f1': 'K', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king g1 rook h1 stays',
   {'board': {'e8': 'k', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('rook destination occupied',
   {'board': {'e8': 'k', 'f1': 'B', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('queenside d1 occupied',
   {'board': {'a1': 'R', 'b1': 'K', 'd1': 'N', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('rook on wrong side',
   {'board': {'b1': 'R', 'd1': 'K', 'e8': 'k'},
    'king_from': 'd1',
    'rook_from': 'b1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king b1 rook c1 f1 attacked',
   {'board': {'a8': 'k', 'b1': 'K', 'c1': 'R', 'f8': 'r'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   False)],
 [('king g1 rook h1 stays',
   {'board': {'e8': 'k', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('rook destination occupied',
   {'board': {'e8': 'k', 'f1': 'B', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('queenside d1 occupied',
   {'board': {'a1': 'R', 'b1': 'K', 'd1': 'N', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('rook on wrong side',
   {'board': {'b1': 'R', 'd1': 'K', 'e8': 'k'},
    'king_from': 'd1',
    'rook_from': 'b1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king destination attacked',
   {'board': {'a8': 'k', 'e1': 'K', 'g8': 'r', 'h1': 'R'},
    'king_from': 'e1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king in check',
   {'board': {'a8': 'k', 'f1': 'K', 'f8': 'r', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('black queenside c8 d8',
   {'board': {'a8': 'r', 'd8': 'k', 'e1': 'K'},
    'king_from': 'd8',
    'rook_from': 'a8',
    'side': 'b',
    'wing': 'Q'},
   True),
  ('king b1 rook c1 f1 attacked',
   {'board': {'a8': 'k', 'b1': 'K', 'c1': 'R', 'f8': 'r'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   False)],
 [('rook destination occupied',
   {'board': {'e8': 'k', 'f1': 'B', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king destination attacked',
   {'board': {'a8': 'k', 'e1': 'K', 'g8': 'r', 'h1': 'R'},
    'king_from': 'e1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king in check',
   {'board': {'a8': 'k', 'f1': 'K', 'f8': 'r', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('black queenside c8 d8',
   {'board': {'a8': 'r', 'd8': 'k', 'e1': 'K'},
    'king_from': 'd8',
    'rook_from': 'a8',
    'side': 'b',
    'wing': 'Q'},
   True),
  ('king c1 rook a1 queenside',
   {'board': {'a1': 'R', 'b1': 'N', 'c1': 'K', 'e8': 'k'},
    'king_from': 'c1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('rook f1 king e1 kingside',
   {'board': {'e1': 'K', 'e8': 'k', 'f1': 'R'},
    'king_from': 'e1',
    'rook_from': 'f1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king b1 rook c1 f1 attacked',
   {'board': {'a8': 'k', 'b1': 'K', 'c1': 'R', 'f8': 'r'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('rook adjacent on a-side kingside',
   {'board': {'c1': 'R', 'd1': 'K', 'e8': 'k'},
    'king_from': 'd1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   False)],
 [('king b1 rook a1 queenside',
   {'board': {'a1': 'R', 'b1': 'K', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   True),
  ('king b1 rook c1 kingside',
   {'board': {'b1': 'K', 'c1': 'R', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('rook destination occupied',
   {'board': {'e8': 'k', 'f1': 'B', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king c1 rook a1 queenside',
   {'board': {'a1': 'R', 'b1': 'N', 'c1': 'K', 'e8': 'k'},
    'king_from': 'c1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('rook f1 king e1 kingside',
   {'board': {'e1': 'K', 'e8': 'k', 'f1': 'R'},
    'king_from': 'e1',
    'rook_from': 'f1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king b1 rook c1 f1 attacked',
   {'board': {'a8': 'k', 'b1': 'K', 'c1': 'R', 'f8': 'r'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('rook adjacent on a-side kingside',
   {'board': {'c1': 'R', 'd1': 'K', 'e8': 'k'},
    'king_from': 'd1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king b1 rook a1 c1 attacked',
   {'board': {'a1': 'R', 'b1': 'K', 'c8': 'r', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False)],
 [('king b1 rook a1 queenside',
   {'board': {'a1': 'R', 'b1': 'K', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   True),
  ('king b1 rook c1 kingside',
   {'board': {'b1': 'K', 'c1': 'R', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king f1 rook h1',
   {'board': {'e8': 'k', 'f1': 'K', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king g1 rook h1 stays',
   {'board': {'e8': 'k', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('rook destination occupied',
   {'board': {'e8': 'k', 'f1': 'B', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('queenside d1 occupied',
   {'board': {'a1': 'R', 'b1': 'K', 'd1': 'N', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('king b1 rook c1 f1 attacked',
   {'board': {'a8': 'k', 'b1': 'K', 'c1': 'R', 'f8': 'r'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king b1 rook a1 c1 attacked',
   {'board': {'a1': 'R', 'b1': 'K', 'c8': 'r', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    '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'; rank='1' if white else '8'
    kf=ord(x['king_from'][0])-97; rf=ord(x['rook_from'][0])-97
    if b.get(x['king_from'])!=('K' if white else 'k') or b.get(x['rook_from'])!=('R' if white else 'r'): return False
    if x['wing']=='K':
        if rf<kf: return False
        kd,rd=min(kf+2,6),min(kf+1,5)
    else:
        if rf>kf: return False
        kd,rd=2,3
    lo=min(kf,kd,rf,rd); hi=max(kf,kd,rf,rd)
    for f in range(lo,hi+1):
        q=chr(97+f)+rank
        if q in b and f not in (kf,rf): return False
    step=1 if kd>=kf else -1
    for f in range(kf,kd+step,step):
        if attacked(b, chr(97+f)+rank, not white): return False
    return True
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('king b1 rook a1 queenside',
   {'board': {'a1': 'R', 'b1': 'K', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   True),
  ('king b1 rook c1 kingside',
   {'board': {'b1': 'K', 'c1': 'R', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king f1 rook h1',
   {'board': {'e8': 'k', 'f1': 'K', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king g1 rook h1 stays',
   {'board': {'e8': 'k', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('rook destination occupied',
   {'board': {'e8': 'k', 'f1': 'B', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('queenside d1 occupied',
   {'board': {'a1': 'R', 'b1': 'K', 'd1': 'N', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('rook on wrong side',
   {'board': {'b1': 'R', 'd1': 'K', 'e8': 'k'},
    'king_from': 'd1',
    'rook_from': 'b1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king b1 rook c1 f1 attacked',
   {'board': {'a8': 'k', 'b1': 'K', 'c1': 'R', 'f8': 'r'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   False)],
 [('king g1 rook h1 stays',
   {'board': {'e8': 'k', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('rook destination occupied',
   {'board': {'e8': 'k', 'f1': 'B', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('queenside d1 occupied',
   {'board': {'a1': 'R', 'b1': 'K', 'd1': 'N', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('rook on wrong side',
   {'board': {'b1': 'R', 'd1': 'K', 'e8': 'k'},
    'king_from': 'd1',
    'rook_from': 'b1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king destination attacked',
   {'board': {'a8': 'k', 'e1': 'K', 'g8': 'r', 'h1': 'R'},
    'king_from': 'e1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king in check',
   {'board': {'a8': 'k', 'f1': 'K', 'f8': 'r', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('black queenside c8 d8',
   {'board': {'a8': 'r', 'd8': 'k', 'e1': 'K'},
    'king_from': 'd8',
    'rook_from': 'a8',
    'side': 'b',
    'wing': 'Q'},
   True),
  ('king b1 rook c1 f1 attacked',
   {'board': {'a8': 'k', 'b1': 'K', 'c1': 'R', 'f8': 'r'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   False)],
 [('rook destination occupied',
   {'board': {'e8': 'k', 'f1': 'B', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king destination attacked',
   {'board': {'a8': 'k', 'e1': 'K', 'g8': 'r', 'h1': 'R'},
    'king_from': 'e1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king in check',
   {'board': {'a8': 'k', 'f1': 'K', 'f8': 'r', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('black queenside c8 d8',
   {'board': {'a8': 'r', 'd8': 'k', 'e1': 'K'},
    'king_from': 'd8',
    'rook_from': 'a8',
    'side': 'b',
    'wing': 'Q'},
   True),
  ('king c1 rook a1 queenside',
   {'board': {'a1': 'R', 'b1': 'N', 'c1': 'K', 'e8': 'k'},
    'king_from': 'c1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('rook f1 king e1 kingside',
   {'board': {'e1': 'K', 'e8': 'k', 'f1': 'R'},
    'king_from': 'e1',
    'rook_from': 'f1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king b1 rook c1 f1 attacked',
   {'board': {'a8': 'k', 'b1': 'K', 'c1': 'R', 'f8': 'r'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('rook adjacent on a-side kingside',
   {'board': {'c1': 'R', 'd1': 'K', 'e8': 'k'},
    'king_from': 'd1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   False)],
 [('king b1 rook a1 queenside',
   {'board': {'a1': 'R', 'b1': 'K', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   True),
  ('king b1 rook c1 kingside',
   {'board': {'b1': 'K', 'c1': 'R', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('rook destination occupied',
   {'board': {'e8': 'k', 'f1': 'B', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king c1 rook a1 queenside',
   {'board': {'a1': 'R', 'b1': 'N', 'c1': 'K', 'e8': 'k'},
    'king_from': 'c1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('rook f1 king e1 kingside',
   {'board': {'e1': 'K', 'e8': 'k', 'f1': 'R'},
    'king_from': 'e1',
    'rook_from': 'f1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king b1 rook c1 f1 attacked',
   {'board': {'a8': 'k', 'b1': 'K', 'c1': 'R', 'f8': 'r'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('rook adjacent on a-side kingside',
   {'board': {'c1': 'R', 'd1': 'K', 'e8': 'k'},
    'king_from': 'd1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king b1 rook a1 c1 attacked',
   {'board': {'a1': 'R', 'b1': 'K', 'c8': 'r', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False)],
 [('king b1 rook a1 queenside',
   {'board': {'a1': 'R', 'b1': 'K', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   True),
  ('king b1 rook c1 kingside',
   {'board': {'b1': 'K', 'c1': 'R', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king f1 rook h1',
   {'board': {'e8': 'k', 'f1': 'K', 'h1': 'R'},
    'king_from': 'f1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('king g1 rook h1 stays',
   {'board': {'e8': 'k', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   True),
  ('rook destination occupied',
   {'board': {'e8': 'k', 'f1': 'B', 'g1': 'K', 'h1': 'R'},
    'king_from': 'g1',
    'rook_from': 'h1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('queenside d1 occupied',
   {'board': {'a1': 'R', 'b1': 'K', 'd1': 'N', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    'side': 'w',
    'wing': 'Q'},
   False),
  ('king b1 rook c1 f1 attacked',
   {'board': {'a8': 'k', 'b1': 'K', 'c1': 'R', 'f8': 'r'},
    'king_from': 'b1',
    'rook_from': 'c1',
    'side': 'w',
    'wing': 'K'},
   False),
  ('king b1 rook a1 c1 attacked',
   {'board': {'a1': 'R', 'b1': 'K', 'c8': 'r', 'e8': 'k'},
    'king_from': 'b1',
    'rook_from': 'a1',
    '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:
King b1 castling kingside is treated as landing on d1, so attacks on g1 are never checked.

Input: {"board", "side", "wing", "king_from", "rook_from"}; rights are assumed held. Chess960 castling: the king ends on g (kingside) or c (queenside) and the rook on f or d; the kingside rook must be on the king's h-side and the queenside rook on its a-side. Every square from the leftmost to the rightmost of king start, king end, rook start and rook end must be empty apart from the castling king and rook, and no square the king stands on or passes through (start to end inclusive) may be attacked.

split: open-access