| 50 CX_TEST_ASSERT(strcmp(gs.fen_start, fen) == 0); |
50 CX_TEST_ASSERT(strcmp(gs.fen_start, fen) == 0); |
| 51 /* counter for fifty-move rule initialized with zero */ |
51 /* counter for fifty-move rule initialized with zero */ |
| 52 CX_TEST_ASSERT(gs.fifty_cntr_start == 0); |
52 CX_TEST_ASSERT(gs.fifty_cntr_start == 0); |
| 53 /* we start after 53 half-moves have been played */ |
53 /* we start after 53 half-moves have been played */ |
| 54 CX_TEST_ASSERT(gs.move_start == 53); |
54 CX_TEST_ASSERT(gs.move_start == 53); |
| |
55 /* it's black's turn */ |
| |
56 CX_TEST_ASSERT(current_color(&gs) == BLACK); |
| 55 /* we have no move history */ |
57 /* we have no move history */ |
| 56 CX_TEST_ASSERT(gs.movecount == 0); |
58 CX_TEST_ASSERT(gs.movecount == 0); |
| 57 CX_TEST_ASSERT(gs.movecapacity == 0); |
59 CX_TEST_ASSERT(gs.movecapacity == 0); |
| 58 CX_TEST_ASSERT(gs.moves == NULL); |
60 CX_TEST_ASSERT(gs.moves == NULL); |
| 59 CX_TEST_ASSERT(gs.fen == NULL); |
61 CX_TEST_ASSERT(gs.fen == NULL); |
| 92 CX_TEST_ASSERTM(strcmp(fen, fen_chk) == 0, fen_chk); |
94 CX_TEST_ASSERTM(strcmp(fen, fen_chk) == 0, fen_chk); |
| 93 } |
95 } |
| 94 gamestate_cleanup(&gs); |
96 gamestate_cleanup(&gs); |
| 95 } |
97 } |
| 96 |
98 |
| |
99 static CX_TEST(test_fen_with_castling_rights) { |
| |
100 /* a test that simply checks if an arbitrary FEN is parsed correctly */ |
| |
101 const char * fen = "1rbqk1nr/ppp2ppp/2np4/2b1p3/2P5/2N1P1P1/PP1P1PBP/R1BQK1NR w KQk - 1 6"; |
| |
102 Board expected_board = { |
| |
103 {WROOK, 0, WBISHOP, WQUEEN, WKING, 0, WKNIGHT, WROOK}, |
| |
104 {WPAWN, WPAWN, 0, WPAWN, 0, WPAWN, WBISHOP, WPAWN}, |
| |
105 {0, 0, WKNIGHT, 0, WPAWN, 0, WPAWN, 0}, |
| |
106 {0, 0, WPAWN, 0, 0, 0, 0, 0}, |
| |
107 {0, 0, BBISHOP, 0, BPAWN, 0, 0, 0}, |
| |
108 {0, 0, BKNIGHT, BPAWN, 0, 0, 0, 0}, |
| |
109 {BPAWN, BPAWN, BPAWN, 0, 0, BPAWN, BPAWN, BPAWN}, |
| |
110 {0, BROOK, BBISHOP, BQUEEN, BKING, 0, BKNIGHT, BROOK} |
| |
111 }; |
| |
112 GameState gs; |
| |
113 int result = fen_parse(fen, &gs); |
| |
114 CX_TEST_DO { |
| |
115 CX_TEST_ASSERT(result == 0); |
| |
116 CX_TEST_ASSERT(strcmp(gs.fen_start, fen) == 0); |
| |
117 /* counter for fifty-move rule */ |
| |
118 CX_TEST_ASSERT(gs.fifty_cntr_start == 1); |
| |
119 /* we start after 10 half-moves have been played */ |
| |
120 CX_TEST_ASSERT(gs.move_start == 10); |
| |
121 /* it's white's turn */ |
| |
122 CX_TEST_ASSERT(current_color(&gs) == WHITE); |
| |
123 /* we have no move history */ |
| |
124 CX_TEST_ASSERT(gs.movecount == 0); |
| |
125 CX_TEST_ASSERT(gs.movecapacity == 0); |
| |
126 CX_TEST_ASSERT(gs.moves == NULL); |
| |
127 CX_TEST_ASSERT(gs.fen == NULL); |
| |
128 /* black queen-side castling right revoked */ |
| |
129 CX_TEST_ASSERT(gs.castling.K == false); |
| |
130 CX_TEST_ASSERT(gs.castling.Q == false); |
| |
131 CX_TEST_ASSERT(gs.castling.k == false); |
| |
132 CX_TEST_ASSERT(gs.castling.q == true); |
| |
133 /* check the board */ |
| |
134 for (File f = 0 ; f < 8 ; f++) { |
| |
135 for (Rank r = 0 ; r < 8 ; r++) { |
| |
136 Piece exp = expected_board[r][f]; |
| |
137 Piece p = piece_at(&gs, f, r); |
| |
138 char msg[64]; |
| |
139 sprintf(msg, "expected %u at %c:%c but got %u", |
| |
140 exp, filechr(f), rankchr(r), p); |
| |
141 CX_TEST_ASSERTM(exp == p, msg); |
| |
142 } |
| |
143 } |
| |
144 /* check that other stuff is empty-initialized */ |
| |
145 CX_TEST_ASSERT(gs.bname[0] == 0); |
| |
146 CX_TEST_ASSERT(gs.wname[0] == 0); |
| |
147 CX_TEST_ASSERT(gs.premove[0] == 0); |
| |
148 CX_TEST_ASSERT(!gs.checkmate); |
| |
149 CX_TEST_ASSERT(!gs.stalemate); |
| |
150 CX_TEST_ASSERT(!gs.threefold); |
| |
151 CX_TEST_ASSERT(!gs.nomaterial); |
| |
152 CX_TEST_ASSERT(!gs.remis); |
| |
153 CX_TEST_ASSERT(!gs.wresign); |
| |
154 CX_TEST_ASSERT(!gs.bresign); |
| |
155 CX_TEST_ASSERT(!gs.ragequit); |
| |
156 CX_TEST_ASSERT(!gs.review); |
| |
157 /* check that we get the original FEN back */ |
| |
158 char fen_chk[FEN_MAX_LENGTH]; |
| |
159 fen_compute(fen_chk, &gs); |
| |
160 CX_TEST_ASSERTM(strcmp(fen, fen_chk) == 0, fen_chk); |
| |
161 } |
| |
162 gamestate_cleanup(&gs); |
| |
163 } |
| |
164 |
| 97 CxTestSuite* test_fen_suite(void) { |
165 CxTestSuite* test_fen_suite(void) { |
| 98 CxTestSuite* suite = cx_test_suite_new("Test FEN API"); |
166 CxTestSuite* suite = cx_test_suite_new("Test FEN API"); |
| 99 |
167 |
| 100 cx_test_register(suite, test_fen_basic); |
168 cx_test_register(suite, test_fen_basic); |
| |
169 cx_test_register(suite, test_fen_with_castling_rights); |
| 101 // TODO: test FENs that describe definitely ended games (for each type of ending) |
170 // TODO: test FENs that describe definitely ended games (for each type of ending) |
| 102 // TODO: test FEN that comes with a non-zero fifty-move rule counter |
|
| 103 // TODO: test FEN with en-passant threat |
171 // TODO: test FEN with en-passant threat |
| 104 |
172 |
| 105 return suite; |
173 return suite; |
| 106 } |
174 } |