{"abstract":"Nb1-d2 with a knight on f3 is written \"N1d2\" instead of \"Nbd2\".","category":"Chess move legality","checks":8,"contract":"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.","evaluation_group":"w2-chess_move_legality-san-disambiguation-writer","failed_approach":"Always writing the file produces \"Raa3\" for two rooks on the a-file.","family":"w2-chess_move_legality-san-disambiguation-writer-file-before-rank-preference","id":"FA-82666","implementations":{"attempt":{"sha256":"d1948838e445f888d3056250d992707867ac26bc6f4b8109f03c4cefe4cf7265","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    b=x['board']; fr,to=x['from'],x['to']; p=b[fr]; white=p.isupper()\n    def c(q): return ord(q[0])-97,int(q[1])-1\n    def reach(q):\n        f,r=c(q); tf,tr=c(to); df,dr=tf-f,tr-r\n        t=p.upper()\n        if t=='N': return (abs(df),abs(dr)) in ((1,2),(2,1))\n        if t=='K': return max(abs(df),abs(dr))==1\n        orth=(df==0)!=(dr==0); diag=abs(df)==abs(dr) and df!=0\n        if not ((t=='R' and orth) or (t=='B' and diag) or (t=='Q' and (orth or diag))): return False\n        sf=(df>0)-(df<0); sr=(dr>0)-(dr<0)\n        cf,cr=f+sf,r+sr\n        while (cf,cr)!=(tf,tr):\n            if chr(97+cf)+str(cr+1) in b: return False\n            cf+=sf; cr+=sr\n        return True\n    others=[q for q,v in b.items() if v==p and q!=fr and reach(q)]\n    dis=''\n    if others:\n        dis=fr[0]\n    cap='x' if to in b else ''\n    return p.upper()+dis+cap+to\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('two knights different files',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),\n  ('two rooks same file',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),\n  ('three queens need square',\n   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},\n   'Qh4e1'),\n  ('blocked rook no disambiguation',\n   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},\n   'Rd1'),\n  ('enemy knight irrelevant',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),\n  ('black knights',\n   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),\n  ('black rook capture',\n   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),\n  ('queen diagonal twin',\n   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')],\n [('two knights different files',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),\n  ('two rooks same file',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),\n  ('three queens need square',\n   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},\n   'Qh4e1'),\n  ('black knights',\n   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),\n  ('queen diagonal twin',\n   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4'),\n  ('capture with file',\n   {'board': {'a1': 'K', 'a8': 'k', 'c3': 'N', 'e4': 'p', 'g3': 'N'}, 'from': 'c3', 'to': 'e4'},\n   'Ncxe4'),\n  ('simple bishop', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'from': 'c1', 'to': 'g5'}, 'Bg5'),\n  ('rooks on same rank',\n   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1')],\n [('two knights different files',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),\n  ('two rooks same file',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),\n  ('three queens need square',\n   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},\n   'Qh4e1'),\n  ('blocked rook no disambiguation',\n   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},\n   'Rd1'),\n  ('enemy knight irrelevant',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),\n  ('black knights',\n   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),\n  ('rooks on same rank',\n   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1'),\n  ('rook shielded by bishop',\n   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},\n   'Rd4')],\n [('two knights different files',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),\n  ('two rooks same file',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),\n  ('three queens need square',\n   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},\n   'Qh4e1'),\n  ('blocked rook no disambiguation',\n   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},\n   'Rd1'),\n  ('enemy knight irrelevant',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),\n  ('black knights',\n   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),\n  ('black rook capture',\n   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),\n  ('queen diagonal twin',\n   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')],\n [('two knights different files',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),\n  ('two rooks same file',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),\n  ('three queens need square',\n   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},\n   'Qh4e1'),\n  ('blocked rook no disambiguation',\n   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},\n   'Rd1'),\n  ('enemy knight irrelevant',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),\n  ('black knights',\n   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),\n  ('black rook capture',\n   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),\n  ('queen diagonal twin',\n   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')]]\nfor label, args, expected in fixtures[N-1]:\n    try:\n        actual = solve(args)\n    except Exception as exc:\n        actual = 'error:' + type(exc).__name__\n    check(label, actual, expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"broken":{"sha256":"5dc888040333e3b8a76adb2cb0078c5d9ca479466dbf2ea7be4660df2e1bfc09","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    b=x['board']; fr,to=x['from'],x['to']; p=b[fr]; white=p.isupper()\n    def c(q): return ord(q[0])-97,int(q[1])-1\n    def reach(q):\n        f,r=c(q); tf,tr=c(to); df,dr=tf-f,tr-r\n        t=p.upper()\n        if t=='N': return (abs(df),abs(dr)) in ((1,2),(2,1))\n        if t=='K': return max(abs(df),abs(dr))==1\n        orth=(df==0)!=(dr==0); diag=abs(df)==abs(dr) and df!=0\n        if not ((t=='R' and orth) or (t=='B' and diag) or (t=='Q' and (orth or diag))): return False\n        sf=(df>0)-(df<0); sr=(dr>0)-(dr<0)\n        cf,cr=f+sf,r+sr\n        while (cf,cr)!=(tf,tr):\n            if chr(97+cf)+str(cr+1) in b: return False\n            cf+=sf; cr+=sr\n        return True\n    others=[q for q,v in b.items() if v==p and q!=fr and reach(q)]\n    dis=''\n    if others:\n        if all(q[1]!=fr[1] for q in others): dis=fr[1]\n        elif all(q[0]!=fr[0] for q in others): dis=fr[0]\n        else: dis=fr\n    cap='x' if to in b else ''\n    return p.upper()+dis+cap+to\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('two knights different files',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),\n  ('two rooks same file',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),\n  ('three queens need square',\n   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},\n   'Qh4e1'),\n  ('blocked rook no disambiguation',\n   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},\n   'Rd1'),\n  ('enemy knight irrelevant',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),\n  ('black knights',\n   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),\n  ('black rook capture',\n   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),\n  ('queen diagonal twin',\n   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')],\n [('two knights different files',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),\n  ('two rooks same file',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),\n  ('three queens need square',\n   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},\n   'Qh4e1'),\n  ('black knights',\n   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),\n  ('queen diagonal twin',\n   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4'),\n  ('capture with file',\n   {'board': {'a1': 'K', 'a8': 'k', 'c3': 'N', 'e4': 'p', 'g3': 'N'}, 'from': 'c3', 'to': 'e4'},\n   'Ncxe4'),\n  ('simple bishop', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'from': 'c1', 'to': 'g5'}, 'Bg5'),\n  ('rooks on same rank',\n   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1')],\n [('two knights different files',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),\n  ('two rooks same file',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),\n  ('three queens need square',\n   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},\n   'Qh4e1'),\n  ('blocked rook no disambiguation',\n   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},\n   'Rd1'),\n  ('enemy knight irrelevant',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),\n  ('black knights',\n   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),\n  ('rooks on same rank',\n   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1'),\n  ('rook shielded by bishop',\n   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},\n   'Rd4')],\n [('two knights different files',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),\n  ('two rooks same file',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),\n  ('three queens need square',\n   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},\n   'Qh4e1'),\n  ('blocked rook no disambiguation',\n   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},\n   'Rd1'),\n  ('enemy knight irrelevant',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),\n  ('black knights',\n   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),\n  ('black rook capture',\n   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),\n  ('queen diagonal twin',\n   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')],\n [('two knights different files',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),\n  ('two rooks same file',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),\n  ('three queens need square',\n   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},\n   'Qh4e1'),\n  ('blocked rook no disambiguation',\n   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},\n   'Rd1'),\n  ('enemy knight irrelevant',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),\n  ('black knights',\n   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),\n  ('black rook capture',\n   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),\n  ('queen diagonal twin',\n   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')]]\nfor label, args, expected in fixtures[N-1]:\n    try:\n        actual = solve(args)\n    except Exception as exc:\n        actual = 'error:' + type(exc).__name__\n    check(label, actual, expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"fixed":{"sha256":"b86b089d62bb33c16cac310ccd37744ce824a715d8cf31b8d46ab37b132ce918","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(x):\n    b=x['board']; fr,to=x['from'],x['to']; p=b[fr]; white=p.isupper()\n    def c(q): return ord(q[0])-97,int(q[1])-1\n    def reach(q):\n        f,r=c(q); tf,tr=c(to); df,dr=tf-f,tr-r\n        t=p.upper()\n        if t=='N': return (abs(df),abs(dr)) in ((1,2),(2,1))\n        if t=='K': return max(abs(df),abs(dr))==1\n        orth=(df==0)!=(dr==0); diag=abs(df)==abs(dr) and df!=0\n        if not ((t=='R' and orth) or (t=='B' and diag) or (t=='Q' and (orth or diag))): return False\n        sf=(df>0)-(df<0); sr=(dr>0)-(dr<0)\n        cf,cr=f+sf,r+sr\n        while (cf,cr)!=(tf,tr):\n            if chr(97+cf)+str(cr+1) in b: return False\n            cf+=sf; cr+=sr\n        return True\n    others=[q for q,v in b.items() if v==p and q!=fr and reach(q)]\n    dis=''\n    if others:\n        if all(q[0]!=fr[0] for q in others): dis=fr[0]\n        elif all(q[1]!=fr[1] for q in others): dis=fr[1]\n        else: dis=fr\n    cap='x' if to in b else ''\n    return p.upper()+dis+cap+to\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('two knights different files',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),\n  ('two rooks same file',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),\n  ('three queens need square',\n   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},\n   'Qh4e1'),\n  ('blocked rook no disambiguation',\n   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},\n   'Rd1'),\n  ('enemy knight irrelevant',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),\n  ('black knights',\n   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),\n  ('black rook capture',\n   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),\n  ('queen diagonal twin',\n   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')],\n [('two knights different files',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),\n  ('two rooks same file',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),\n  ('three queens need square',\n   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},\n   'Qh4e1'),\n  ('black knights',\n   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),\n  ('queen diagonal twin',\n   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4'),\n  ('capture with file',\n   {'board': {'a1': 'K', 'a8': 'k', 'c3': 'N', 'e4': 'p', 'g3': 'N'}, 'from': 'c3', 'to': 'e4'},\n   'Ncxe4'),\n  ('simple bishop', {'board': {'c1': 'B', 'e1': 'K', 'e8': 'k'}, 'from': 'c1', 'to': 'g5'}, 'Bg5'),\n  ('rooks on same rank',\n   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1')],\n [('two knights different files',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),\n  ('two rooks same file',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),\n  ('three queens need square',\n   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},\n   'Qh4e1'),\n  ('blocked rook no disambiguation',\n   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},\n   'Rd1'),\n  ('enemy knight irrelevant',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),\n  ('black knights',\n   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),\n  ('rooks on same rank',\n   {'board': {'a1': 'R', 'f1': 'R', 'h2': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd1'}, 'Rad1'),\n  ('rook shielded by bishop',\n   {'board': {'a4': 'R', 'a8': 'k', 'c4': 'B', 'h1': 'K', 'h4': 'R'}, 'from': 'h4', 'to': 'd4'},\n   'Rd4')],\n [('two knights different files',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),\n  ('two rooks same file',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),\n  ('three queens need square',\n   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},\n   'Qh4e1'),\n  ('blocked rook no disambiguation',\n   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},\n   'Rd1'),\n  ('enemy knight irrelevant',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),\n  ('black knights',\n   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),\n  ('black rook capture',\n   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),\n  ('queen diagonal twin',\n   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')],\n [('two knights different files',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'N'}, 'from': 'b1', 'to': 'd2'}, 'Nbd2'),\n  ('two rooks same file',\n   {'board': {'a1': 'R', 'a5': 'R', 'e1': 'K', 'e8': 'k'}, 'from': 'a1', 'to': 'a3'}, 'R1a3'),\n  ('three queens need square',\n   {'board': {'a1': 'K', 'a8': 'k', 'e4': 'Q', 'h1': 'Q', 'h4': 'Q'}, 'from': 'h4', 'to': 'e1'},\n   'Qh4e1'),\n  ('blocked rook no disambiguation',\n   {'board': {'a1': 'R', 'c1': 'B', 'e2': 'K', 'e8': 'k', 'h1': 'R'}, 'from': 'h1', 'to': 'd1'},\n   'Rd1'),\n  ('enemy knight irrelevant',\n   {'board': {'b1': 'N', 'e1': 'K', 'e8': 'k', 'f3': 'n'}, 'from': 'b1', 'to': 'd2'}, 'Nd2'),\n  ('black knights',\n   {'board': {'b8': 'n', 'e1': 'K', 'e8': 'k', 'f6': 'n'}, 'from': 'b8', 'to': 'd7'}, 'Nbd7'),\n  ('black rook capture',\n   {'board': {'a2': 'P', 'a8': 'r', 'e1': 'K', 'e8': 'k'}, 'from': 'a8', 'to': 'a2'}, 'Rxa2'),\n  ('queen diagonal twin',\n   {'board': {'a1': 'Q', 'g1': 'Q', 'h1': 'K', 'h8': 'k'}, 'from': 'a1', 'to': 'd4'}, 'Qad4')]]\nfor label, args, expected in fixtures[N-1]:\n    try:\n        actual = solve(args)\n    except Exception as exc:\n        actual = 'error:' + type(exc).__name__\n    check(label, actual, expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"}},"limitations":"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.","method":"Deterministic executable model with adversarial boundary fixtures.","provenance":{"created_by":"Failure Map","dependencies":"Python standard library","family":"w2-chess_move_legality-san-disambiguation-writer-file-before-rank-preference","generated_at":"2026-09-29T14:50:14.116840+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Exported PGN must be re-readable; a wrong disambiguator makes the game unreplayable.","repair":"Prefer the file, then the rank, then the full square.","root_cause":"The rank is tried before the file.","sha256":"6eef486f6acc226ecce7b2d79bee8c00f2f8a106f5bbaac2b5927127358d9efc","title":"Rank disambiguator chosen when the file suffices · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":42.068,"exit_code":1,"observations":[{"actual":"Nbd2","check":"two knights different files","expected":"Nbd2","passed":true},{"actual":"Raa3","check":"two rooks same file","expected":"R1a3","passed":false},{"actual":"Qhe1","check":"three queens need square","expected":"Qh4e1","passed":false},{"actual":"Rd1","check":"blocked rook no disambiguation","expected":"Rd1","passed":true},{"actual":"Nd2","check":"enemy knight irrelevant","expected":"Nd2","passed":true},{"actual":"Nbd7","check":"black knights","expected":"Nbd7","passed":true},{"actual":"Rxa2","check":"black rook capture","expected":"Rxa2","passed":true},{"actual":"Qad4","check":"queen diagonal twin","expected":"Qad4","passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"two knights different files\", \"actual\": \"Nbd2\", \"expected\": \"Nbd2\", \"passed\": true}, {\"check\": \"two rooks same file\", \"actual\": \"Raa3\", \"expected\": \"R1a3\", \"passed\": false}, {\"check\": \"three queens need square\", \"actual\": \"Qhe1\", \"expected\": \"Qh4e1\", \"passed\": false}, {\"check\": \"blocked rook no disambiguation\", \"actual\": \"Rd1\", \"expected\": \"Rd1\", \"passed\": true}, {\"check\": \"enemy knight irrelevant\", \"actual\": \"Nd2\", \"expected\": \"Nd2\", \"passed\": true}, {\"check\": \"black knights\", \"actual\": \"Nbd7\", \"expected\": \"Nbd7\", \"passed\": true}, {\"check\": \"black rook capture\", \"actual\": \"Rxa2\", \"expected\": \"Rxa2\", \"passed\": true}, {\"check\": \"queen diagonal twin\", \"actual\": \"Qad4\", \"expected\": \"Qad4\", \"passed\": true}], \"passed\": false}\n"},"broken":{"elapsed_ms":41.448,"exit_code":1,"observations":[{"actual":"N1d2","check":"two knights different files","expected":"Nbd2","passed":false},{"actual":"R1a3","check":"two rooks same file","expected":"R1a3","passed":true},{"actual":"Qh4e1","check":"three queens need square","expected":"Qh4e1","passed":true},{"actual":"Rd1","check":"blocked rook no disambiguation","expected":"Rd1","passed":true},{"actual":"Nd2","check":"enemy knight irrelevant","expected":"Nd2","passed":true},{"actual":"N8d7","check":"black knights","expected":"Nbd7","passed":false},{"actual":"Rxa2","check":"black rook capture","expected":"Rxa2","passed":true},{"actual":"Qad4","check":"queen diagonal twin","expected":"Qad4","passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"two knights different files\", \"actual\": \"N1d2\", \"expected\": \"Nbd2\", \"passed\": false}, {\"check\": \"two rooks same file\", \"actual\": \"R1a3\", \"expected\": \"R1a3\", \"passed\": true}, {\"check\": \"three queens need square\", \"actual\": \"Qh4e1\", \"expected\": \"Qh4e1\", \"passed\": true}, {\"check\": \"blocked rook no disambiguation\", \"actual\": \"Rd1\", \"expected\": \"Rd1\", \"passed\": true}, {\"check\": \"enemy knight irrelevant\", \"actual\": \"Nd2\", \"expected\": \"Nd2\", \"passed\": true}, {\"check\": \"black knights\", \"actual\": \"N8d7\", \"expected\": \"Nbd7\", \"passed\": false}, {\"check\": \"black rook capture\", \"actual\": \"Rxa2\", \"expected\": \"Rxa2\", \"passed\": true}, {\"check\": \"queen diagonal twin\", \"actual\": \"Qad4\", \"expected\": \"Qad4\", \"passed\": true}], \"passed\": false}\n"},"fixed":{"elapsed_ms":43.227,"exit_code":0,"observations":[{"actual":"Nbd2","check":"two knights different files","expected":"Nbd2","passed":true},{"actual":"R1a3","check":"two rooks same file","expected":"R1a3","passed":true},{"actual":"Qh4e1","check":"three queens need square","expected":"Qh4e1","passed":true},{"actual":"Rd1","check":"blocked rook no disambiguation","expected":"Rd1","passed":true},{"actual":"Nd2","check":"enemy knight irrelevant","expected":"Nd2","passed":true},{"actual":"Nbd7","check":"black knights","expected":"Nbd7","passed":true},{"actual":"Rxa2","check":"black rook capture","expected":"Rxa2","passed":true},{"actual":"Qad4","check":"queen diagonal twin","expected":"Qad4","passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"two knights different files\", \"actual\": \"Nbd2\", \"expected\": \"Nbd2\", \"passed\": true}, {\"check\": \"two rooks same file\", \"actual\": \"R1a3\", \"expected\": \"R1a3\", \"passed\": true}, {\"check\": \"three queens need square\", \"actual\": \"Qh4e1\", \"expected\": \"Qh4e1\", \"passed\": true}, {\"check\": \"blocked rook no disambiguation\", \"actual\": \"Rd1\", \"expected\": \"Rd1\", \"passed\": true}, {\"check\": \"enemy knight irrelevant\", \"actual\": \"Nd2\", \"expected\": \"Nd2\", \"passed\": true}, {\"check\": \"black knights\", \"actual\": \"Nbd7\", \"expected\": \"Nbd7\", \"passed\": true}, {\"check\": \"black rook capture\", \"actual\": \"Rxa2\", \"expected\": \"Rxa2\", \"passed\": true}, {\"check\": \"queen diagonal twin\", \"actual\": \"Qad4\", \"expected\": \"Qad4\", \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}