tests.sh - chess-puzzles - chess puzzle book generator
 (HTM) git clone git://git.codemadness.org/chess-puzzles
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       tests.sh (28832B)
       ---
            1 #!/bin/sh
            2 
            3 statuscode=0
            4 failed=0
            5 
            6 # testfen(name, expect, fen, moves)
            7 testfen() {
            8         name="$1"
            9         expect="$2"
           10         fen="$3"
           11         moves="$4"
           12 
           13         # input FEN with no moves should match output FEN (except "startpos").
           14         output=$(./fen -o fen "$fen" "")
           15         if test "$fen" != "startpos" && test "$fen" != "$output"; then
           16                 printf '[FEN] Fail: %s, input FEN does not match output FEN\n' "$name" >&2
           17                 printf '\texpected: %s\n' "$fen" >&2
           18                 printf '\tgot:      %s\n' "$output" >&2
           19                 statuscode=1
           20                 failed=$((failed+1))
           21         fi
           22 
           23         output=$(./fen -o fen "$fen" "$moves")
           24         if test "$output" = "$expect"; then
           25                 printf '[FEN] OK: %s\n' "$name"
           26         else
           27                 printf '[FEN] Fail: %s\n' "$name" >&2
           28                 printf '\texpected: %s\n' "$expect" >&2
           29                 printf '\tgot:      %s\n' "$output" >&2
           30                 printf '\tInput FEN, moves: "%s" "%s"\n' "$fen" "$moves" >&2
           31                 statuscode=1
           32                 failed=$((failed+1))
           33         fi
           34 }
           35 
           36 # testpgn(name, expect, fen, moves)
           37 testpgn() {
           38         name="$1"
           39         expect="$2"
           40         fen="$3"
           41         moves="$4"
           42 
           43         output=$(./fen -o pgn "$fen" "$moves")
           44         if test "$output" = "$expect"; then
           45                 printf '[PGN] OK: %s\n' "$name"
           46         else
           47                 printf '[PGN] Fail: %s\n' "$name" >&2
           48                 printf '\texpected: %s\n' "$expect" >&2
           49                 printf '\tgot:      %s\n' "$output" >&2
           50                 printf '\tInput FEN, moves: "%s" "%s"\n' "$fen" "$moves" >&2
           51                 statuscode=1
           52                 failed=$((failed+1))
           53         fi
           54 }
           55 
           56 tests_fen() {
           57 testfen 'startpos'\
           58         'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1' \
           59         "startpos"\
           60 ""
           61 
           62 # white castles kingside
           63 testfen 'white castles kingside'\
           64         'rnbqkb1r/p4ppp/1pp1pn2/3p4/3P1B2/3BPN2/PPP2PPP/RN1Q1RK1 b kq - 1 6'\
           65         'rnbqkb1r/p4ppp/1pp1pn2/3p4/3P1B2/3BPN2/PPP2PPP/RN1QK2R w KQkq - 0 6'\
           66         'e1g1'
           67 testfen 'white castles kingside'\
           68         'r3k2r/p2bqpp1/nppbpn1p/3p4/3P1B2/2NBPN2/PPPQ1PPP/R4RK1 b kq - 9 11'\
           69         'r3k2r/p2bqpp1/nppbpn1p/3p4/3P1B2/2NBPN2/PPPQ1PPP/R3K2R w KQkq - 8 11'\
           70         'e1g1'
           71 testfen 'white castles queenside'\
           72         'r3k2r/p2bqpp1/nppbpn1p/3p4/3P1B2/2NBPN2/PPPQ1PPP/2KR3R b kq - 9 11'\
           73         'r3k2r/p2bqpp1/nppbpn1p/3p4/3P1B2/2NBPN2/PPPQ1PPP/R3K2R w KQkq - 8 11'\
           74         'e1c1'
           75 
           76 # black castles kingside
           77 testfen 'black castles kingside'\
           78         'rnbq1rk1/p3bppp/1pp1pn2/3p4/3P1B2/3BPN2/PPPN1PPP/R2Q1RK1 w - - 4 8'\
           79         'rnbqk2r/p3bppp/1pp1pn2/3p4/3P1B2/3BPN2/PPPN1PPP/R2Q1RK1 b kq - 3 7'\
           80         'e8g8'
           81 testfen 'black castles kingside'\
           82         'r4rk1/p2bqpp1/nppbpn1p/3p4/3P1B2/2NBPN2/PPPQ1PPP/R4RK1 w - - 10 12'\
           83         'r3k2r/p2bqpp1/nppbpn1p/3p4/3P1B2/2NBPN2/PPPQ1PPP/R4RK1 b kq - 9 11'\
           84         'e8g8'
           85 testfen 'black castles queenside'\
           86         '2kr3r/p2bqpp1/nppbpn1p/3p4/3P1B2/2NBPN2/PPPQ1PPP/R4RK1 w - - 10 12'\
           87         'r3k2r/p2bqpp1/nppbpn1p/3p4/3P1B2/2NBPN2/PPPQ1PPP/R4RK1 b kq - 9 11'\
           88         'e8c8'
           89 
           90 # check castling: the white queen is in check, but this doesn't change the castling state.
           91 testfen 'white queen is in check, shouldnt change castling state'\
           92         'rnb1kb1r/pp2qppp/2p2n2/3p4/3P1B2/3B1N2/PPP2PPP/RN1QK2R w KQkq - 0 8'\
           93         'rnb1kb1r/pp2qppp/2p1pn2/3P4/3P1B2/3B1N2/PPP2PPP/RN1QK2R b KQkq - 0 7'\
           94         'e6d5'
           95 
           96 # check castling: black moves kingside rook: this removes castling on this side.
           97 testfen 'black moves kingside rook: this removes castling on this side'\
           98         'rnb1kbr1/pp2qppp/2p2n2/3p4/3P1B2/3B1N2/PPP1QPPP/RN2K2R w KQq - 2 9'\
           99         'rnb1kb1r/pp2qppp/2p2n2/3p4/3P1B2/3B1N2/PPP1QPPP/RN2K2R b KQkq - 1 8'\
          100         'h8g8'
          101 
          102 # check castling: white moves kingside rook: this removes castling on this side.
          103 testfen 'white moves kingside rook: this removes castling on this side'\
          104         'rnb1kb2/pp2qppr/2p2n2/3p4/3P1B2/3B1N2/PPP1QPPP/RN2K1R1 b Qq - 3 9'\
          105         'rnb1kb2/pp2qppr/2p2n2/3p4/3P1B2/3B1N2/PPP1QPPP/RN2K2R w KQq - 2 9'\
          106         'h1g1'
          107 # check castling: white moves queenside rook: this removes castling on this side.
          108 testfen 'white moves queenside rook: this removes castling on this side'\
          109         'rnb1kb2/1p2qpp1/p1p2n2/3p4/3P1B2/3B1N2/PPPNQPPr/1R2K1R1 b q - 1 11'\
          110         'rnb1kb2/1p2qpp1/p1p2n2/3p4/3P1B2/3B1N2/PPPNQPPr/R3K1R1 w Qq - 0 11'\
          111         'a1b1'
          112 # white king move, remove castling availability
          113 testfen 'white king move, remove castling availability'\
          114         'rnb1kb2/1p2qpp1/p1p2n2/3p4/3P1B2/3B1N2/PPPNQPPr/R2K2R1 b q - 1 11'\
          115         'rnb1kb2/1p2qpp1/p1p2n2/3p4/3P1B2/3B1N2/PPPNQPPr/R3K1R1 w Qq - 0 11'\
          116         'e1d1'
          117 # white king move, remove castling availability
          118 testfen 'white king move, remove castling availability'\
          119         'r3k2r/pppppppp/8/8/8/8/PPPPPPPP/R2K3R b kq - 1 1'\
          120         'r3k2r/pppppppp/8/8/8/8/PPPPPPPP/R3K2R w KQkq - 0 1'\
          121         'e1d1'
          122 # black king move, remove castling availability
          123 testfen 'black king move, remove castling availability'\
          124         'r4k1r/pppppppp/8/8/8/8/PPPPPPPP/R2K3R w - - 2 2'\
          125         'r3k2r/pppppppp/8/8/8/8/PPPPPPPP/R2K3R b kq - 1 1'\
          126         'e8f8'
          127 
          128 # black is laz0rbeamed by white bishop on the queenside on b8, but not on the
          129 # castling square it is allowed to castle.
          130 testfen 'black is laz0rbeamed by white bishop'\
          131         '2kr1br1/pp2qppp/n1p1bn2/3p4/3P1B2/3BQN2/PPP2PPP/RN2K2R w KQ - 8 12'\
          132         'r3kbr1/pp2qppp/n1p1bn2/3p4/3P1B2/3BQN2/PPP2PPP/RN2K2R b KQq - 7 11'\
          133         'e8c8'
          134 # white moves bishop and blocks castling for black, but this doesn't change the
          135 # castle state itself.
          136 testfen 'white moves bishop and blocks castling for black, shouldnt change castling state'\
          137         'r3kbr1/pp2qppp/n1p2n2/3p1B2/3P1B2/4QN1b/PPP2PPP/RN2K2R b KQq - 9 12'\
          138         'r3kbr1/pp2qppp/n1p2n2/3p4/3P1B2/3BQN1b/PPP2PPP/RN2K2R w KQq - 8 12'\
          139         'd3f5'
          140 
          141 # test en passant: move white pawn g2 to g4, enpassant square becomes g3.
          142 testfen 'move white pawn g2 to g4, enpassant square becomes g3'\
          143         'r4k1r/ppppp1pp/8/8/5pP1/4P3/PPPP1P1P/R3K2R b - g3 0 4'\
          144         'r4k1r/ppppp1pp/8/8/5p2/4P3/PPPP1PPP/R3K2R w - - 0 4'\
          145         'g2g4'
          146 
          147 # moving 2 squares near a pawn, but not en passant.
          148 testfen 'moving 2 squares near a pawn, but not en passant'\
          149         'r4k1r/ppppp1p1/8/5p2/6P1/4P2p/PPPP1P1P/R3K2R b - - 0 6'\
          150         'r4k1r/ppppp1p1/8/5p2/8/4P2p/PPPP1PPP/R3K2R w - - 0 6'\
          151         'g2g4'
          152 # test en passant for black.
          153 testfen 'en passant for black'\
          154         'r4k1r/ppp1p1p1/8/2Pp1p2/6P1/4P2p/PP1P1P1P/R3K2R w - d6 0 9'\
          155         'r4k1r/ppppp1p1/8/2P2p2/6P1/4P2p/PP1P1P1P/R3K2R b - - 0 8'\
          156         'd7d5'
          157 testfen 'en passant move for black'\
          158         'r4k1r/p1ppp1p1/8/1pP2p2/6P1/4P2p/PP1P1P1P/R3K2R w - b6 0 9'\
          159         'r4k1r/ppppp1p1/8/2P2p2/6P1/4P2p/PP1P1P1P/R3K2R b - - 0 8'\
          160         'b7b5'
          161 # white takes en passant
          162 testfen 'white takes en passant'\
          163         'rnbqkbnr/pppp1pp1/4P3/7p/8/8/PPP1PPPP/RNBQKBNR b KQkq - 0 3'\
          164         'rnbqkbnr/pppp1pp1/8/3Pp2p/8/8/PPP1PPPP/RNBQKBNR w KQkq e6 0 3'\
          165         'd5e6'
          166 # black takes en passant
          167 testfen 'black takes en passant'\
          168         'rnbqkbnr/ppppppp1/8/8/3P4/4P1p1/PPP2P1P/RNBQKBNR w KQkq - 0 4'\
          169         'rnbqkbnr/ppppppp1/8/8/3P2Pp/4P3/PPP2P1P/RNBQKBNR b KQkq g3 0 3'\
          170         'h4g3'
          171 
          172 # white takes en passant: should reset halfmove counter
          173 testfen 'white takes en passant: should reset halfmove counter'\
          174         'rnbqkbnr/pppp1pp1/4P3/7p/8/8/PPP1PPPP/RNBQKBNR b KQkq - 0 3'\
          175         'rnbqkbnr/pppp1pp1/8/3Pp2p/8/8/PPP1PPPP/RNBQKBNR w KQkq e6 1 3'\
          176         'd5e6'
          177 
          178 # check halfmove counter on check, white checks black: should increase halfmove counter
          179 testfen 'check halfmove counter on check, white checks black: should increase halfmove counter'\
          180         'rnbqkbnr/ppp1pp1p/6p1/1B1p4/3P4/4P3/PPP2PPP/RNBQK1NR b KQkq - 21 1'\
          181         'rnbqkbnr/ppp1pp1p/6p1/3p4/3P4/4P3/PPP2PPP/RNBQKBNR w KQkq - 20 1'\
          182         'f1b5'
          183 
          184 # TODO: this is incorrect (illegal move), fix it?
          185 # 960 white queenside castle
          186 testfen '960 white queenside castle'\
          187         'qrn1bk1n/ppb1pprp/2p3p1/3p4/1B1P4/3NPB2/PPP2PPP/Q1KR2RN b q - 5 6'\
          188         'qrn1bk1n/ppb1pprp/2p3p1/3p4/1B1P4/3NPB2/PPP2PPP/QR3KRN w KQq - 4 6'\
          189         'f1c1'
          190 # 960, rook moved: remove ability for black to castle
          191 testfen '960, rook moved: remove ability for black to castle'\
          192         'q1r1bk1n/ppb1pprp/2pn2p1/3p4/1B1P4/3NPB2/PPP2PPP/Q1KRR2N w - - 8 8'\
          193         'qr2bk1n/ppb1pprp/2pn2p1/3p4/1B1P4/3NPB2/PPP2PPP/Q1KRR2N b q - 7 7'\
          194         'b8c8'
          195 # 960, rook moved
          196 testfen '960, rook moved, castling ability'\
          197         'bbnrkrnq/ppp1p1pp/8/3p1p2/3P1P2/3R4/PPP1P1PP/BBN1KRNQ b Kkq - 1 3'\
          198         'bbnrkrnq/ppp1p1pp/8/3p1p2/3P1P2/8/PPP1P1PP/BBNRKRNQ w KQkq - 0 3'\
          199         'd1d3'
          200 # 960, rook moved
          201 testfen '960, rook moved, castling ability'\
          202         'bbnrkrnq/ppp1p1pp/8/3p1p2/3P1P2/5R2/PPP1P1PP/BBNRK1NQ b Qkq - 1 3'\
          203         'bbnrkrnq/ppp1p1pp/8/3p1p2/3P1P2/8/PPP1P1PP/BBNRKRNQ w KQkq - 0 3'\
          204         'f1f3'
          205 # 960, rook moved
          206 testfen '960, rook moved, castling ability'\
          207         'bbn1krnq/ppp1p1pp/3r4/3p1p2/P2P1P2/8/1PP1P1PP/BBNRKRNQ w KQk - 1 4'\
          208         'bbnrkrnq/ppp1p1pp/8/3p1p2/P2P1P2/8/1PP1P1PP/BBNRKRNQ b KQkq - 0 3'\
          209         'd8d6'
          210 # 960, rook moved
          211 testfen '960, rook moved, castling ability'\
          212         'bbnrk1nq/ppp1p1pp/5r2/3p1p2/P2P1P2/8/1PP1P1PP/BBNRKRNQ w KQq - 1 4'\
          213         'bbnrkrnq/ppp1p1pp/8/3p1p2/P2P1P2/8/1PP1P1PP/BBNRKRNQ b KQkq - 0 3'\
          214         'f8f6'
          215 # 960, en passant move
          216 testfen '960, en passant move'\
          217         'bbnrk1nq/ppp1p2p/3r4/3p1ppP/P2P1P2/8/1PP1P1P1/BBNRKRNQ w KQq g6 0 6'\
          218         'bbnrk1nq/ppp1p1pp/3r4/3p1p1P/P2P1P2/8/1PP1P1P1/BBNRKRNQ b KQq - 0 5'\
          219         'g7g5'
          220 # 960, en passant take
          221 testfen '960, en passant take'\
          222         'bbnrk1nq/ppp1p2p/3r2P1/3p1p2/P2P1P2/8/1PP1P1P1/BBNRKRNQ b KQq - 0 6'\
          223         'bbnrk1nq/ppp1p2p/3r4/3p1ppP/P2P1P2/8/1PP1P1P1/BBNRKRNQ w KQq g6 0 6'\
          224         'h5g6'
          225 
          226 # 960, white castle kingside with rook right next to the king, doesnt reset halfmove counter
          227 testfen '960, castle with rook right next to the king, doesnt reset halfmove counter'\
          228         'nnbrqkrb/ppp1pp1p/8/3p2p1/1Q1P4/8/PPP1PPPP/NNBR1RKB b kq - 1 3'\
          229         'nnbrqkrb/ppp1pp1p/8/3p2p1/1Q1P4/8/PPP1PPPP/NNBR1KRB w KQkq - 0 3'\
          230         'f1g1'
          231 testfen '960, black castle kingside with rook right next to the king, doesnt reset halfmove counter'\
          232         'nnbrqrkb/ppp1pp1p/8/3p2p1/3P4/2Q5/PPP1PPPP/NNBR1KRB w KQ - 2 4'\
          233         'nnbrqkrb/ppp1pp1p/8/3p2p1/3P4/2Q5/PPP1PPPP/NNBR1KRB b KQkq - 1 3'\
          234         'f8g8'
          235 
          236 testfen '960, castle king on queenside with many empty squares between them'\
          237         '1rb1krq1/pp2ppb1/3p2p1/1Np4p/2P1P3/1P2N3/P4PPP/2KR1RQB b kq - 1 11'\
          238         '1rb1krq1/pp2ppb1/3p2p1/1Np4p/2P1P3/1P2N3/P4PPP/1R2KRQB w KQkq - 0 11'\
          239         'e1c1'
          240 
          241 testfen 'black moves pawn en passant into check (not mate, can take en passant)'\
          242         'rnbqkbnr/p2ppppp/1p6/1PpPP3/2PKQ3/2PQQ3/P1PP1PPP/RNBQ1BNR w kq c6 0 2'\
          243         'rnbqkbnr/p1pppppp/1p6/1P1PP3/2PKQ3/2PQQ3/P1PP1PPP/RNBQ1BNR b kq - 0 1'\
          244         'c7c5'
          245 
          246 # NOTE: Lichess checks if en passant moves can actually be played, but the PGN
          247 # reference specifies this doesn't necesarily have to be the case.
          248 testfen 'black moves pawn en passant into checkmate (cant take en passant to defend)'\
          249         'rnbqkbnr/p3pppp/1p6/2pPP3/2PKQ3/2PQQ3/P1PP1PPP/RNBQ1BNR w kq - 0 2'\
          250         'rnbqkbnr/p1p1pppp/1p6/3PP3/2PKQ3/2PQQ3/P1PP1PPP/RNBQ1BNR b kq - 0 1'\
          251         'c7c5'
          252 
          253 testfen 'white is checkmated (en passant square is not set), do not remove pawn (illegal move though)'\
          254         'rnbqkbnr/p2ppppp/1pP5/1Pp1P3/2PKQ3/2PQQ3/P1PP1PPP/RNBQ1BNR b kq - 0 1'\
          255         'rnbqkbnr/p2ppppp/1p6/1PpPP3/2PKQ3/2PQQ3/P1PP1PPP/RNBQ1BNR w kq - 0 1'\
          256         'd5c6'
          257 
          258 testfen 'white is not checkmated (en passant square is set and can be played), remove pawn'\
          259         'rnbqkbnr/p2ppppp/1pP5/1P2P3/2PKQ3/2PQQ3/P1PP1PPP/RNBQ1BNR b kq - 0 1'\
          260         'rnbqkbnr/p2ppppp/1p6/1PpPP3/2PKQ3/2PQQ3/P1PP1PPP/RNBQ1BNR w kq c6 0 1'\
          261         'd5c6'
          262 
          263 testfen 'white promote to queen'\
          264         'rnbqkbQr/p1pppp1p/8/8/8/8/PpPPPP1P/R1BQKBNR b KQkq - 0 1'\
          265         'rnbqkb1r/p1ppppPp/8/8/8/8/PpPPPP1P/R1BQKBNR w KQkq - 0 1'\
          266         'g7g8Q'
          267 
          268 testfen 'white promote to rook'\
          269         'rnbqkbRr/p1pppp1p/8/8/8/8/PpPPPP1P/R1BQKBNR b KQkq - 0 1'\
          270         'rnbqkb1r/p1ppppPp/8/8/8/8/PpPPPP1P/R1BQKBNR w KQkq - 0 1'\
          271         'g7g8R'
          272 
          273 testfen 'white promote to bishop'\
          274         'rnbqkbBr/p1pppp1p/8/8/8/8/PpPPPP1P/R1BQKBNR b KQkq - 0 1'\
          275         'rnbqkb1r/p1ppppPp/8/8/8/8/PpPPPP1P/R1BQKBNR w KQkq - 0 1'\
          276         'g7g8B'
          277 
          278 testfen 'white promote to knight'\
          279         'rnbqkbNr/p1pppp1p/8/8/8/8/PpPPPP1P/R1BQKBNR b KQkq - 0 1'\
          280         'rnbqkb1r/p1ppppPp/8/8/8/8/PpPPPP1P/R1BQKBNR w KQkq - 0 1'\
          281         'g7g8N'
          282 
          283 testfen 'white promote to knight (fixup lowercase to uppercase)'\
          284         'rnbqkbNr/p1pppp1p/8/8/8/8/PpPPPP1P/R1BQKBNR b KQkq - 0 1'\
          285         'rnbqkb1r/p1ppppPp/8/8/8/8/PpPPPP1P/R1BQKBNR w KQkq - 0 1'\
          286         'g7g8n'
          287 
          288 testfen 'black promote to queen'\
          289         'rnbqkb1r/p1ppppPp/8/8/8/8/P1PPPP1P/RqBQKBNR w KQkq - 0 2'\
          290         'rnbqkb1r/p1ppppPp/8/8/8/8/PpPPPP1P/R1BQKBNR b KQkq - 0 1'\
          291         'b2b1q'
          292 
          293 testfen 'black promote to rook'\
          294         'rnbqkb1r/p1ppppPp/8/8/8/8/P1PPPP1P/RrBQKBNR w KQkq - 0 2'\
          295         'rnbqkb1r/p1ppppPp/8/8/8/8/PpPPPP1P/R1BQKBNR b KQkq - 0 1'\
          296         'b2b1r'
          297 
          298 testfen 'black promote to bishop'\
          299         'rnbqkb1r/p1ppppPp/8/8/8/8/P1PPPP1P/RbBQKBNR w KQkq - 0 2'\
          300         'rnbqkb1r/p1ppppPp/8/8/8/8/PpPPPP1P/R1BQKBNR b KQkq - 0 1'\
          301         'b2b1b'
          302 
          303 testfen 'black promote to knight'\
          304         'rnbqkb1r/p1ppppPp/8/8/8/8/P1PPPP1P/RnBQKBNR w KQkq - 0 2'\
          305         'rnbqkb1r/p1ppppPp/8/8/8/8/PpPPPP1P/R1BQKBNR b KQkq - 0 1'\
          306         'b2b1n'
          307 
          308 testfen 'black promote to knight (fixup uppercase to lowercase)'\
          309         'rnbqkb1r/p1ppppPp/8/8/8/8/P1PPPP1P/RnBQKBNR w KQkq - 0 2'\
          310         'rnbqkb1r/p1ppppPp/8/8/8/8/PpPPPP1P/R1BQKBNR b KQkq - 0 1'\
          311         'b2b1N'
          312 
          313 testfen 'castling chess960'\
          314         'qnkr1r2/p1p1p2p/4nppN/1p6/1P1p4/3P2P1/PQPNPP1P/2RK2Rb w KQ - 4 13'\
          315         'qnrkbnrb/pppppppp/8/8/8/8/PPPPPPPP/QNRKBNRB w KQkq - 0 1'\
          316         'd2d3 g7g6 e1c3 d7d5 c3h8 g8h8 b2b4 h8g8 g2g3 e8c6 f1e3 b7b5 a1e5 f7f6 e5d4 f8e6 d4b2 d5d4 e3g4 c6h1 g4h6 g8f8 b1d2 d8c8'
          317 
          318 testfen 'castling chess960'\
          319         'r2k1r2/1pb3pp/2ppqp2/p2np3/P3N1P1/1N1P1P2/1PPBP1QP/R4RK1 b kq - 1 14'\
          320         'r2k1r2/1pb3pp/2ppqp2/p2np3/P3N1P1/1N1P1P2/1PPBP1QP/R2K1R2 w KQkq - 0 14'\
          321         'd1g1'
          322 
          323 testfen 'test castles chess960'\
          324         'rk1r1n2/ppqp1bnp/2pbpp2/6p1/4P1P1/1PPN1P1P/P1QPBN1B/R4RK1 b kq - 1 1'\
          325         'rk1r1n2/ppqp1bnp/2pbpp2/6p1/4P1P1/1PPN1P1P/P1QPBN1B/RK1R4 w KQkq - 0 1'\
          326         'b1g1'
          327 
          328 testfen 'castles chess 960'\
          329         'r4rk1/ppqp1bnp/2pbppn1/6p1/4P1P1/1PPN1P1P/P1QPBN1B/RK1R4 w KQ - 1 2'\
          330         'rk1r4/ppqp1bnp/2pbppn1/6p1/4P1P1/1PPN1P1P/P1QPBN1B/RK1R4 b KQkq - 0 1'\
          331         'b8g8'
          332 }
          333 
          334 tests_pgn() {
          335 testpgn 'simple pawn move'\
          336         '2. ... e5'\
          337         'rnbqkbnr/ppp1pppp/8/3p4/3PP3/8/PPP2PPP/RNBQKBNR b KQkq - 0 2'\
          338         'e7e5'
          339 
          340 testpgn 'check: check with white pawn'\
          341         '4. gxf7+'\
          342         'rnbqkbnr/pppp1ppp/6P1/8/8/4p3/PPPPPP1P/RNBQKBNR w KQkq - 0 4'\
          343         'g6f7'
          344 testpgn 'check: check with black pawn'\
          345         '4. ... exf2+'\
          346         'rnbqkbnr/pppp1ppP/8/8/8/4p3/PPPPPP1P/RNBQKBNR b KQkq - 0 4'\
          347         'e3f2'
          348 
          349 testpgn 'check: check with bishop'\
          350         '3. Bb5+'\
          351         'rnbqkbnr/ppp2ppp/8/3pp3/3PP3/8/PPP2PPP/RNBQKBNR w KQkq - 0 3'\
          352         'f1b5'
          353 testpgn 'check: check with white queen, open file'\
          354         '6. Qe4+'\
          355         'rnbqkbnr/1ppp1pp1/p5Pp/8/3Q4/4P3/PPP1PP1P/RNB1KBNR w KQkq - 0 6'\
          356         'd4e4'
          357 
          358 testpgn 'check: check and takes with white knight'\
          359         '8. Nxc7+'\
          360         'rnbqkbn1/pppp1ppr/6P1/3N4/7p/4PN2/PPP1PP1P/R1BQKB1R w KQq - 2 8'\
          361         'd5c7'
          362 
          363 testpgn 'black moves, but the move from white is unknown, use "..."'\
          364         '1. ... e5'\
          365         'rnbqkbnr/pppppppp/8/8/3P4/8/PPP1PPPP/RNBQKBNR b KQkq - 0 1'\
          366         'e7e5'
          367 
          368 testpgn 'black moves with knight, ambigous move, needs file name'\
          369         '8. ... Nbd7'\
          370         'rn2kb1r/pp4pp/1qp1pn2/3p4/3P1B2/1P1BP3/P1P2P1P/RN1QK1NR b KQkq - 0 8'\
          371         'b8d7'
          372 
          373 testpgn 'black moves with knight, non-ambigous move'\
          374         '8. ... Nd7'\
          375         'rn2kb1r/pp4pp/1qp1p3/3p4/3P1B2/1P1BP3/P1P2P1P/RN1QK1NR b KQkq - 0 8'\
          376         'b8d7'
          377 
          378 testpgn '2 queens, ambigous move, needs rank'\
          379         '8. Q3g3'\
          380         'rn2kb1r/pp4pp/1qp1p3/3p4/3P1B1Q/1P1BP2Q/P1P2P1P/RN2K1NR w KQkq - 0 8'\
          381         'h3g3'
          382 
          383 testpgn 'king moves into range of king (illegal move), but played, so notate it'\
          384         '1. Kd5+'\
          385         '8/8/3k4/8/3K2R1/8/8/8 w - - 0 1'\
          386         'd4d5'
          387 
          388 # Long list of moves, checkmate at the end.
          389 testpgn 'Long list of moves, compared to Lichess board analyzer'\
          390         '1. d4 d5 2. Bf4 c6 3. e3 Bf5 4. Bd3 e6 5. g4 Nf6 6. gxf5 Qb6 7. fxe6 fxe6 8. b3 Nbd7 9. Nd2 O-O-O 10. c4 Be7 11. c5 Qa5 12. a3 Ne4 13. Bxe4 Bxc5 14. b4 Qb5 15. Bc2 g5 16. Ba4 Qa6 17. Bxg5 Bd6 18. Bxd8 Rxd8 19. b5 cxb5 20. Rc1+ Bc5 21. Bxb5 Qxb5 22. dxc5 Nxc5 23. Nb3 b6 24. Nxc5 Qxc5 25. Rxc5+ bxc5 26. Qg4 c4 27. Qxe6+ Kc7 28. Nf3 a5 29. Nd4 Rd7 30. Qc6+ Kd8 31. Ne6+ Ke7 32. f4 Rd6 33. Qxd6+ Kxd6 34. f5 Kc6 35. Rg1 Kd6 36. h4 h6 37. h5 Kd7 38. Rg6 Ke7 39. Rxh6 a4 40. Rg6 Kd6 41. Rg5 c3 42. h6 Ke5 43. h7 Ke4 44. h8=Q Kd3 45. Qd4+ Kc2 46. Rg2+ Kb3 47. Nc5+ Kxa3 48. Qxa4#'\
          391         'startpos'\
          392         'd2d4 d7d5 c1f4 c7c6 e2e3 c8f5 f1d3 e7e6 g2g4 g8f6 g4f5 d8b6 f5e6 f7e6 b2b3 b8d7 b1d2 e8c8 c2c4 f8e7 c4c5 b6a5 a2a3 f6e4 d3e4 e7c5 b3b4 a5b5 e4c2 g7g5 c2a4 b5a6 f4g5 c5d6 g5d8 h8d8 b4b5 c6b5 a1c1 d6c5 a4b5 a6b5 d4c5 d7c5 d2b3 b7b6 b3c5 b5c5 c1c5 b6c5 d1g4 c5c4 g4e6 c8c7 g1f3 a7a5 f3d4 d8d7 e6c6 c7d8 d4e6 d8e7 f2f4 d7d6 c6d6 e7d6 f4f5 d6c6 h1g1 c6d6 h2h4 h7h6 h4h5 d6d7 g1g6 d7e7 g6h6 a5a4 h6g6 e7d6 g6g5 c4c3 h5h6 d6e5 h6h7 e5e4 h7h8q e4d3 h8d4 d3c2 g5g2 c2b3 e6c5 b3a3 d4a4'
          393 
          394 testpgn 'Rook on same file, only one is legal, Rd7d1+ -> Rd1+'\
          395         '34. Rc6 Rd1+ 35. Rxd1 Rxd1#'\
          396         '3r2k1/3r2p1/R6p/4bp2/2P1p2P/7N/2P2PP1/2R3K1 w - - 1 34'\
          397         'a6c6 d7d1 c1d1 d8d1'
          398 
          399 testpgn 'black moves pawn en passant into check (not mate, can take en passant)'\
          400         '1. ... c5+'\
          401         'rnbqkbnr/p1pppppp/1p6/1P1PP3/2PKQ3/2PQQ3/P1PP1PPP/RNBQ1BNR b kq - 0 1'\
          402         'c7c5'
          403 
          404 # NOTE: Lichess checks if en passant moves can actually be played, but the PGN
          405 # reference specifies this doesn't necesarily have to be the case.
          406 testpgn 'black moves pawn en passant into checkmate (cant take en passant to defend)'\
          407         '1. ... c5#'\
          408         'rnbqkbnr/p1p1pppp/1p6/3PP3/2PKQ3/2PQQ3/P1PP1PPP/RNBQ1BNR b kq - 0 1'\
          409         'c7c5'
          410 
          411 # check also if the en passant square is set (but it is not legal to play).
          412 testpgn 'black moves pawn en passant into checkmate (cant take en passant to defend), part 2'\
          413         '1. ... c5#'\
          414         'rnbqkbnr/p1p1pppp/1p6/3PP3/2PKQ3/2PQQ3/P1PP1PPP/RNBQ1BNR b kq c6 0 1'\
          415         'c7c5'
          416 
          417 testpgn 'Knights on the same rank can move to the same square'\
          418         '1. Nde5'\
          419         'rnbqkbnr/pppppppp/8/8/8/3N1N2/PPPPPPPP/R1BQKB1R w KQkq - 0 1'\
          420         'd3e5'
          421 
          422 testpgn 'Knights on the same rank can move to the same square, part 2'\
          423         '1. Nfe5'\
          424         'rnbqkbnr/pppppppp/8/8/8/3N1N2/PPPPPPPP/R1BQKB1R w KQkq - 0 1'\
          425         'f3e5'
          426 
          427 testpgn 'Knights on the same same file can move to the same square'\
          428         '1. N3c4'\
          429         'rnbqkbnr/pppppppp/8/4N3/8/4N3/PPPPPPPP/R1BQKB1R w KQkq - 0 1'\
          430         'e3c4'
          431 
          432 testpgn 'Knights on the same same file can move to the same square, part 2'\
          433         '1. N5c4'\
          434         'rnbqkbnr/pppppppp/8/4N3/8/4N3/PPPPPPPP/R1BQKB1R w KQkq - 0 1'\
          435         'e5c4'
          436 
          437 testpgn 'Knights on the same same file can move to the same square, part 3'\
          438         '1. N5g4'\
          439         'rnbqkbnr/pppppppp/8/4N3/8/4N3/PPPPPPPP/R1BQKB1R w KQkq - 0 1'\
          440         'e5g4'
          441 
          442 testpgn 'Rook on the same file can move to the same square'\
          443         '1. R3d4'\
          444         'rnbqkbnr/pppppppp/3R4/8/8/3R4/PPPPPPPP/1NBQKBN1 w kq - 0 1'\
          445         'd3d4'
          446 
          447 testpgn 'Rook on the same file can move to the same square, part 2'\
          448         '1. R6d4'\
          449         'rnbqkbnr/pppppppp/3R4/8/8/3R4/PPPPPPPP/1NBQKBN1 w kq - 0 1'\
          450         'd6d4'
          451 
          452 testpgn 'Rook on the same rank can move to the same square'\
          453         '1. Rge4'\
          454         'rnbqkbnr/pppppppp/8/8/2R3R1/8/PPPPPPPP/1NBQKBN1 w kq - 0 1'\
          455         'g4e4'
          456 
          457 testpgn 'Rook on the same rank can move to the same square, part 2'\
          458         '1. Rce4'\
          459         'rnbqkbnr/pppppppp/8/8/2R3R1/8/PPPPPPPP/1NBQKBN1 w kq - 0 1'\
          460         'c4e4'
          461 
          462 testpgn 'Rook on the same rank can take on the same square (with check), part 3'\
          463         '1. Rgxe4+'\
          464         'rnbqkbnr/pppp1ppp/8/8/2R1p1R1/8/PPPPPPPP/1NBQKBN1 w kq - 0 1'\
          465         'g4e4'
          466 
          467 testpgn 'Rook on the same rank can take on the same square (with check), part 4'\
          468         '1. Rcxe4+'\
          469         'rnbqkbnr/pppp1ppp/8/8/2R1p1R1/8/PPPPPPPP/1NBQKBN1 w kq - 0 1'\
          470         'c4e4'
          471 
          472 testpgn 'Knights on the same same file can take on the same square'\
          473         '1. N3xc4'\
          474         'rnbqkbnr/pppppppp/8/4N3/2p5/4N3/PPPPPPPP/R1BQKB1R w KQkq - 0 1'\
          475         'e3c4'
          476 
          477 testpgn 'Knights on the same same file can take on the same square, part 2'\
          478         '1. N5xc4'\
          479         'rnbqkbnr/pppppppp/8/4N3/2p5/4N3/PPPPPPPP/R1BQKB1R w KQkq - 0 1'\
          480         'e5c4'
          481 
          482 testpgn 'Knights on same files and ranks move to same square'\
          483         '1. Nf3e5'\
          484         'rnbqkbnr/pppNpNpp/8/8/8/3N1N2/PPPPPPPP/R1BQKB1R w KQkq - 0 1'\
          485         'f3e5'
          486 
          487 testpgn 'Knights on same files and ranks move to same square, part 2'\
          488         '1. Nd7e5'\
          489         'rnbqkbnr/pppNpNpp/8/8/8/3N1N2/PPPPPPPP/R1BQKB1R w KQkq - 0 1'\
          490         'd7e5'
          491 
          492 testpgn 'Knights on same files and ranks move to same square, part 3'\
          493         '1. Nd3e5'\
          494         'rnbqkbnr/pppNpNpp/8/8/8/3N1N2/PPPPPPPP/R1BQKB1R w KQkq - 0 1'\
          495         'd3e5'
          496 
          497 testpgn '4 knights that can move to the same square, but not on the same file or ranks'\
          498         '1. Nfe5'\
          499         'rnbqkbnr/ppp1pNpp/2N5/8/6N1/3N4/PPPPPPPP/R1BQKB1R w KQkq - 0 1'\
          500         'f7e5'
          501 
          502 testpgn '4 knights that can move to the same square, but not on the same file or ranks, part 2'\
          503         '1. Nce5'\
          504         'rnbqkbnr/ppp1pNpp/2N5/8/6N1/3N4/PPPPPPPP/R1BQKB1R w KQkq - 0 1'\
          505         'c6e5'
          506 
          507 testpgn '4 knights that can move to the same square, but not on the same file or ranks, part 3'\
          508         '1. Nde5'\
          509         'rnbqkbnr/ppp1pNpp/2N5/8/6N1/3N4/PPPPPPPP/R1BQKB1R w KQkq - 0 1'\
          510         'd3e5'
          511 
          512 testpgn '4 knights that can move to the same square, but not on the same file or ranks, part 4'\
          513         '1. Nge5'\
          514         'rnbqkbnr/ppp1pNpp/2N5/8/6N1/3N4/PPPPPPPP/R1BQKB1R w KQkq - 0 1'\
          515         'g4e5'
          516 
          517 testpgn 'Move bishop, 2 bishops can move to the same square'\
          518         '1. Bge4'\
          519         'rnbqkbnr/pppppppp/6B1/8/8/3B4/PPPP1PPP/RNBQK1NR w KQkq - 0 1'\
          520         'g6e4'
          521 
          522 testpgn 'Move bishop, 2 bishops can move to the same square, part 2'\
          523         '1. Bde4'\
          524         'rnbqkbnr/pppppppp/6B1/8/8/3B4/PPPP1PPP/RNBQK1NR w KQkq - 0 1'\
          525         'd3e4'
          526 
          527 testpgn 'Move bishop, 2 bishops can move to the same square, part 3'\
          528         '1. Bde4'\
          529         'rnbqkbnr/pppppppp/2B3B1/8/8/2BB4/PPPP1PPP/RNBQK1NR w KQkq - 0 1'\
          530         'd3e4'
          531 
          532 # white takes en passant
          533 testpgn 'white takes en passant'\
          534         '3. dxe6'\
          535         'rnbqkbnr/pppp1pp1/8/3Pp2p/8/8/PPP1PPPP/RNBQKBNR w KQkq e6 0 3'\
          536         'd5e6'
          537 # black takes en passant
          538 testpgn 'black takes en passant'\
          539         '3. ... hxg3'\
          540         'rnbqkbnr/ppppppp1/8/8/3P2Pp/4P3/PPP2P1P/RNBQKBNR b KQkq g3 0 3'\
          541         'h4g3'
          542 
          543 # NOTE: this is ambigous, but this is not dc6, because the en passant square is not set either.
          544 testpgn 'white is checkmated (en passant square is not set), do not remove pawn (illegal move though)'\
          545         '1. c6'\
          546         'rnbqkbnr/p2ppppp/1p6/1PpPP3/2PKQ3/2PQQ3/P1PP1PPP/RNBQ1BNR w kq - 0 1'\
          547         'd5c6'
          548 
          549 testpgn 'white is not checkmated (en passant square is set and can be played), remove pawn'\
          550         '1. dxc6'\
          551         'rnbqkbnr/p2ppppp/1p6/1PpPP3/2PKQ3/2PQQ3/P1PP1PPP/RNBQ1BNR w kq c6 0 1'\
          552         'd5c6'
          553 
          554 testpgn 'Smothered mate, mate in 3'\
          555         '1. Nh6+ Kh8 2. Qg8+ Rxg8 3. Nf7#'\
          556         '5rk1/5Npp/8/3Q4/8/8/8/K7 w - - 0 1'\
          557         'f7h6 g8h8 d5g8 f8g8 h6f7'
          558 
          559 testpgn 'white is in check, defend with knight and checkmate'\
          560         '1. Ng1#'\
          561         '8/7k/8/8/8/7N/6RR/3r3K w - - 0 1'\
          562         'h3g1'
          563 
          564 testpgn 'Black checks white (blunder), white defends with knight and checkmate'\
          565         '1. ... Rd1+ 2. Ng1#'\
          566         '8/7k/8/8/3r4/7N/6RR/7K b - - 0 1'\
          567         'd4d1 h3g1'
          568 
          569 testpgn 'Test a longer sequence of moves, promotion, castling, etc'\
          570         '1. d4 d5 2. Bf4 c6 3. e3 Bf5 4. Bd3 e6 5. g4 Nf6 6. gxf5 Qb6 7. fxe6 fxe6 8. b3 Nbd7 9. Nd2 O-O-O 10. c4 Be7 11. c5 Qa5 12. a3 Ne4 13. Bxe4 Bxc5 14. b4 Qb5 15. Bc2 g5 16. Ba4 Qa6 17. Bxg5 Bd6 18. Bxd8 Rxd8 19. b5 cxb5 20. Rc1+ Bc5 21. Bxb5 Qxb5 22. dxc5 Nxc5 23. Nb3 b6 24. Nxc5 Qxc5 25. Rxc5+ bxc5 26. Qg4 c4 27. Qxe6+ Kc7 28. Nf3 a5 29. Nd4 Rd7 30. Qc6+ Kd8 31. Ne6+ Ke7 32. f4 Rd6 33. Qxd6+ Kxd6 34. f5 Kc6 35. Rg1 Kd6 36. h4 h6 37. h5 Kd7 38. Rg6 Ke7 39. Rxh6 a4 40. Rg6 Kd6 41. Rg5 c3 42. h6 Ke5 43. h7 Ke4 44. h8=Q Kd3 45. Qd4+ Kc2 46. Rg2+ Kb3 47. Nc5+ Kxa3 48. Qxa4#'\
          571         'startpos'\
          572         'd2d4 d7d5 c1f4 c7c6 e2e3 c8f5 f1d3 e7e6 g2g4 g8f6 g4f5 d8b6 f5e6 f7e6 b2b3 b8d7 b1d2 e8c8 c2c4 f8e7 c4c5 b6a5 a2a3 f6e4 d3e4 e7c5 b3b4 a5b5 e4c2 g7g5 c2a4 b5a6 f4g5 c5d6 g5d8 h8d8 b4b5 c6b5 a1c1 d6c5 a4b5 a6b5 d4c5 d7c5 d2b3 b7b6 b3c5 b5c5 c1c5 b6c5 d1g4 c5c4 g4e6 c8c7 g1f3 a7a5 f3d4 d8d7 e6c6 c7d8 d4e6 d8e7 f2f4 d7d6 c6d6 e7d6 f4f5 d6c6 h1g1 c6d6 h2h4 h7h6 h4h5 d6d7 g1g6 d7e7 g6h6 a5a4 h6g6 e7d6 g6g5 c4c3 h5h6 d6e5 h6h7 e5e4 h7h8Q e4d3 h8d4 d3c2 g5g2 c2b3 e6c5 b3a3 d4a4'
          573 
          574 # test castling chess 960
          575 testpgn 'Castling chess960'\
          576         '1. d3 g6 2. Bc3 d5 3. Bxh8 Rxh8 4. b4 Rg8 5. g3 Bc6 6. Ne3 b5 7. Qe5 f6 8. Qd4 Ne6 9. Qb2 d4 10. Ng4 Bxh1 11. Nh6 Rf8 12. Nd2 O-O-O'\
          577         'qnrkbnrb/pppppppp/8/8/8/8/PPPPPPPP/QNRKBNRB w KQkq - 0 1'\
          578         'd2d3 g7g6 e1c3 d7d5 c3h8 g8h8 b2b4 h8g8 g2g3 e8c6 f1e3 b7b5 a1e5 f7f6 e5d4 f8e6 d4b2 d5d4 e3g4 c6h1 g4h6 g8f8 b1d2 d8c8'
          579 
          580 testpgn 'PGN chess960'\
          581         '1. d3 g6 2. Bc3 d5 3. Bxh8 Rxh8 4. b4 Rg8 5. g3 Bc6 6. Ne3 b5 7. Qe5 f6 8. Qd4 Ne6 9. Qb2 d4 10. Ng4 Bxh1 11. Nh6 Rf8 12. Nd2 O-O-O 13. f3 Qc6 14. Rxh1 Nd7 15. Ne4 Kb7 16. c4 Qb6 17. c5 Qc6 18. Nd2 Ne5 19. Nb3 Qa6 20. f4 Nc6 21. Ng4 Qa4 22. a3 h5 23. Nf2 Rg8 24. Nh3 Rh8 25. Ng1 Rhf8 26. Nf3 Rfe8 27. O-O-O Rf8 28. Rhe1 a6 29. e3 Ng7 30. exd4 Rg8 31. Re3 e6 32. Rde1 Rh8 33. Nbd2 Rhe8 34. Ne4 h4 35. Nxh4 Nxd4 36. Nxf6 Re7 37. Nxg6 Ne8 38. Nxe7 Nxf6 39. c6+ Kb6 40. Qc3 a5 41. Qc5+ Ka6 42. Qc3 axb4 43. Qxb4 Qc2#'\
          582         'qnrkbnrb/pppppppp/8/8/8/8/PPPPPPPP/QNRKBNRB w KQkq - 0 1'\
          583         'd2d3 g7g6 e1c3 d7d5 c3h8 g8h8 b2b4 h8g8 g2g3 e8c6 f1e3 b7b5 a1e5 f7f6 e5d4 f8e6 d4b2 d5d4 e3g4 c6h1 g4h6 g8f8 b1d2 d8c8 f2f3 a8c6 g1h1 b8d7 d2e4 c8b7 c2c4 c6b6 c4c5 b6c6 e4d2 d7e5 d2b3 c6a6 f3f4 e5c6 h6g4 a6a4 a2a3 h7h5 g4f2 f8g8 f2h3 g8h8 h3g1 h8f8 g1f3 f8e8 d1c1 e8f8 h1e1 a7a6 e2e3 e6g7 e3d4 f8g8 e1e3 e7e6 d1e1 g8h8 b3d2 h8e8 d2e4 h5h4 f3h4 c6d4 e4f6 e8e7 h4g6 g7e8 g6e7 e8f6 c5c6 b7b6 b2c3 a6a5 c3c5 b6a6 c5c3 a5b4 c3b4 a4c2'
          584 
          585 testpgn 'castling chess960'\
          586         '1. d3 c6 2. Bd2 a5 3. a4 f6 4. Ba2 Bf7 5. Bxf7 Qxf7 6. Nb3 Bc7 7. g4 e5 8. Ng3 Qe6 9. f3 Ng6 10. Qg2 Nf4 11. Bxf4 Nb6 12. Bd2 Nd5 13. Ne4 d6 14. Qh3 Nf4 15. Qxh7 d5 16. Nec5 Qc8 17. Bxf4 exf4 18. Qxg7 Ke8 19. Qg6+ Ke7 20. Nd4 Kd6 21. Nce6 Bb6 22. Nxf8 Bxd4 23. Nh7 Qd8 24. c3 Be3 25. Qxf6+ Qxf6 26. Nxf6 Rf8 27. Nh5 Ra8 28. h4 Rd8 29. Rh1 Rb8 30. Ng7 Bf2 31. h5 Bb6 32. h6 Ke5 33. Kc2 Kf6 34. Rh3 Ra8 35. Rah1 Bf2 36. Nh5+ Ke6 37. Nxf4+ Kd6 38. h7 Bd4 39. cxd4 Rh8 40. Ng6 Re8 41. h8=Q Rxe2+ 42. Kc3 Rg2 43. Qd8+ Ke6 44. Re1+ Kf7 45. Qe8+ Kf6 46. Re6+ Kg5 47. Rh5#'\
          587         'rbnkbrqn/pppppppp/8/8/8/8/PPPPPPPP/RBNKBRQN w KQkq - 0 1'\
          588         'd2d3 c7c6 e1d2 a7a5 a2a4 f7f6 b1a2 e8f7 a2f7 g8f7 c1b3 b8c7 g2g4 e7e5 h1g3 f7e6 f2f3 h8g6 g1g2 g6f4 d2f4 c8b6 f4d2 b6d5 g3e4 d7d6 g2h3 d5f4 h3h7 d6d5 e4c5 e6c8 d2f4 e5f4 h7g7 d8e8 g7g6 e8e7 b3d4 e7d6 c5e6 c7b6 e6f8 b6d4 f8h7 c8d8 c2c3 d4e3 g6f6 d8f6 h7f6 a8f8 f6h5 f8a8 h2h4 a8d8 f1h1 d8b8 h5g7 e3f2 h4h5 f2b6 h5h6 d6e5 d1c2 e5f6 h1h3 b8a8 a1h1 b6f2 g7h5 f6e6 h5f4 e6d6 h6h7 f2d4 c3d4 a8h8 f4g6 h8e8 h7h8Q e8e2 c2c3 e2g2 h8d8 d6e6 h1e1 e6f7 d8e8 f7f6 e1e6 f6g5 h3h5'
          589 
          590 testpgn 'test castles chess960'\
          591         '14. O-O'\
          592         'r2k1r2/1pb3pp/2ppqp2/p2np3/P3N1P1/1N1P1P2/1PPBP1QP/R2K1R2 w KQkq - 0 14'\
          593         'd1g1'
          594 
          595 testpgn 'test castles chess960'\
          596         '1. O-O'\
          597         'rk1r1n2/ppqp1bnp/2pbpp2/6p1/4P1P1/1PPN1P1P/P1QPBN1B/RK1R4 w KQkq - 0 1'\
          598         'b1g1'
          599 
          600 testpgn 'castles chess 960'\
          601         '1. ... O-O'\
          602         'rk1r4/ppqp1bnp/2pbppn1/6p1/4P1P1/1PPN1P1P/P1QPBN1B/RK1R4 b KQkq - 0 1'\
          603         'b8g8'
          604 
          605 testpgn 'test file/rank for pawn move (was bug)'\
          606         '7. gxf3 Qh4#'\
          607         'rn1qk1nr/ppp2ppp/3b4/8/8/2N2b2/PPPPP1PP/R1BQKB1R w KQkq - 0 7'\
          608         'g2f3 d8h4'
          609 
          610 testpgn 'test en passant check (was bug)'\
          611         '35. Kg4 h5+ 36. gxh6 f5+ 37. Kg5 Rg3#'\
          612         '8/2R2p1p/4k1p1/6P1/5P1P/r5K1/8/8 w - - 1 35'\
          613         'g3g4 h7h5 g5h6 f7f5 g4g5 a3g3'
          614 
          615 testpgn 'test ambigous queen move'\
          616         '1. Qf3d5'\
          617         '8/1Q3Q2/8/8/8/1Q3Q2/8/3K2k1 w - - 0 1'\
          618         'f3d5'
          619 
          620 testpgn 'test ambigous queen move 2'\
          621         '1. Q7b5'\
          622         '8/1Q3Q2/8/8/8/1Q3Q2/8/3K2k1 w - - 0 1'\
          623         'b7b5'
          624 
          625 testpgn 'test ambigous queen move 3'\
          626         '1. Qfe7'\
          627         '8/1Q3Q2/8/8/8/1Q3Q2/8/3K2k1 w - - 0 1'\
          628         'f7e7'
          629 }
          630 
          631 tests_fen
          632 tests_pgn
          633 
          634 # Test all castle positions for both sides for chess960
          635 # this includes classical positions.
          636 
          637 IFS="        "
          638 while read -r kingside f kingpos rpos; do
          639         # test last part of the side that is tested.
          640         # 5RK1 - kingside
          641         # 2KR4 - queenside
          642 
          643         # lowercase for black
          644         fb="$(printf '%s' "$f" | tr '[:upper:]' '[:lower:]')"
          645 
          646         # test white kingside or queenside castle.
          647         move="${kingpos}1${rpos}1"
          648         if test "$kingside" = "1"; then
          649                 fullfen="${fb}/pppppppp/8/8/8/8/PPPPPPPP/${f} w Kk - 0 1"
          650                 expect="${fb}/pppppppp/8/8/8/8/PPPPPPPP/5RK1 b k - 1 1"
          651         else
          652                 fullfen="${fb}/pppppppp/8/8/8/8/PPPPPPPP/${f} w Qq - 0 1"
          653                 expect="${fb}/pppppppp/8/8/8/8/PPPPPPPP/2KR4 b q - 1 1"
          654                 move="${kingpos}1${rpos}1"
          655         fi
          656         testfen "Chess960 position, $fullfen (white), $move, kingside? $kingside" \
          657                 "$expect" \
          658                 "$fullfen" \
          659                 "$move"
          660 
          661         if test "$kingside" = "1"; then
          662                 expect="1. O-O"
          663         else
          664                 expect="1. O-O-O"
          665         fi
          666         testpgn "Chess960 position, $fullfen (white), $move" \
          667                 "$expect" \
          668                 "$fullfen" \
          669                 "$move"
          670 
          671         # test black kingside or queenside castle.
          672         move="${kingpos}8${rpos}8"
          673         if test "$kingside" = "1"; then
          674                 fullfen="${fb}/pppppppp/8/8/8/8/PPPPPPPP/${f} b Kk - 0 1"
          675                 expect="5rk1/pppppppp/8/8/8/8/PPPPPPPP/${f} w K - 1 2"
          676         else
          677                 fullfen="${fb}/pppppppp/8/8/8/8/PPPPPPPP/${f} b Qq - 0 1"
          678                 expect="2kr4/pppppppp/8/8/8/8/PPPPPPPP/${f} w Q - 1 2"
          679         fi
          680         testfen "Chess960 position, $fullfen (black), $move, kingside? $kingside" \
          681                 "$expect" \
          682                 "$fullfen" \
          683                 "$move"
          684 
          685         if test "$kingside" = "1"; then
          686                 expect="1. ... O-O"
          687         else
          688                 expect="1. ... O-O-O"
          689         fi
          690         testpgn "Chess960 position, $fullfen (black), $move" \
          691                 "$expect" \
          692                 "$fullfen" \
          693                 "$move"
          694 done <<!
          695 0        1R1K4        d        b
          696 0        1R2K3        e        b
          697 0        1R3K2        f        b
          698 0        1R4K1        g        b
          699 0        1RK5        c        b
          700 0        2R1K3        e        c
          701 0        2R2K2        f        c
          702 0        2R3K1        g        c
          703 0        2RK4        d        c
          704 0        3R1K2        f        d
          705 0        3R2K1        g        d
          706 0        3RK3        e        d
          707 0        4R1K1        g        e
          708 0        4RK2        f        e
          709 0        5RK1        g        f
          710 0        R1K5        c        a
          711 0        R2K4        d        a
          712 0        R3K3        e        a
          713 0        R4K2        f        a
          714 0        R5K1        g        a
          715 0        RK6        b        a
          716 1        1K1R4        b        d
          717 1        1K2R3        b        e
          718 1        1K3R2        b        f
          719 1        1K4R1        b        g
          720 1        1K5R        b        h
          721 1        1KR5        b        c
          722 1        2K1R3        c        e
          723 1        2K2R2        c        f
          724 1        2K3R1        c        g
          725 1        2K4R        c        h
          726 1        2KR4        c        d
          727 1        3K1R2        d        f
          728 1        3K2R1        d        g
          729 1        3K3R        d        h
          730 1        3KR3        d        e
          731 1        4K1R1        e        g
          732 1        4K2R        e        h
          733 1        4KR2        e        f
          734 1        5K1R        f        h
          735 1        5KR1        f        g
          736 1        6KR        g        h
          737 !
          738 
          739 if test "$statuscode" = "1"; then
          740         echo "$failed tests failed"
          741 else
          742         echo "All tests OK"
          743 fi
          744 
          745 exit "$statuscode"