17 #include "move_legal.h"
23 static const bool UseSlowDebug = FALSE;
29 bool board_is_ok(const board_t * board) {
35 if (board == NULL) return FALSE;
37 // optional heavy DEBUG mode
39 if (!UseSlowDebug) return TRUE;
43 for (sq = 0; sq < SquareNb; sq++) {
44 piece = board->square[sq];
45 if (square_is_ok(sq)) {
48 if (pos != -1) return FALSE;
50 if (pos < 0) return FALSE;
51 if (board->list[piece_colour(piece)][pos] != sq) return FALSE;
54 if (piece != Knight64) return FALSE;
63 if (board->list_size[colour] <= 0 || board->list_size[colour] > 16) return FALSE;
65 sq = board->list[colour][pos];
66 if (sq == SquareNone) return FALSE;
67 if (board->pos[sq] != pos) return FALSE;
68 piece = board->square[sq];
69 if (!colour_equal(piece,colour) || !piece_is_king(piece)) return FALSE;
71 for (pos++; pos < board->list_size[colour]; pos++) {
72 sq = board->list[colour][pos];
73 if (sq == SquareNone) return FALSE;
74 if (board->pos[sq] != pos) return FALSE;
75 if (!colour_equal(board->square[sq],colour)) return FALSE;
78 sq = board->list[colour][pos];
79 if (sq != SquareNone) return FALSE;
86 if (board->list_size[colour] <= 0 || board->list_size[colour] > 16) return FALSE;
88 sq = board->list[colour][pos];
89 if (sq == SquareNone) return FALSE;
90 if (board->pos[sq] != pos) return FALSE;
91 piece = board->square[sq];
92 if (!colour_equal(piece,colour) || !piece_is_king(piece)) return FALSE;
94 for (pos++; pos < board->list_size[colour]; pos++) {
95 sq = board->list[colour][pos];
96 if (sq == SquareNone) return FALSE;
97 if (board->pos[sq] != pos) return FALSE;
98 if (!colour_equal(board->square[sq],colour)) return FALSE;
101 sq = board->list[colour][pos];
102 if (sq != SquareNone) return FALSE;
106 if (board->number[WhiteKing12] != 1) return FALSE;
107 if (board->number[BlackKing12] != 1) return FALSE;
109 if (!colour_is_ok(board->turn)) return FALSE;
113 if (board->castle[White][SideH] != SquareNone) {
115 king = board->list[White][0];
116 if ((king < A1) || (king > H1)) return FALSE;
117 if (board->square[king] != WhiteKing256) return FALSE;
119 rook = board->castle[White][SideH];
120 if ((rook < A1) || (rook > H1)) return FALSE;
121 if (board->square[rook] != WhiteRook256) return FALSE;
123 if (rook <= king) return FALSE;
126 if (board->castle[White][SideA] != SquareNone) {
128 king = board->list[White][0];
129 if ((king < A1) || (king > H1)) return FALSE;
130 if (board->square[king] != WhiteKing256) return FALSE;
132 rook = board->castle[White][SideA];
133 if ((rook < A1) || (rook > H1)) return FALSE;
134 if (board->square[rook] != WhiteRook256) return FALSE;
136 if (rook >= king) return FALSE;
139 if (board->castle[Black][SideH] != SquareNone) {
141 king = board->list[Black][0];
142 if ((king < A8) || (king > H8)) return FALSE;
143 if (board->square[king] != BlackKing256) return FALSE;
145 rook = board->castle[Black][SideH];
146 if ((rook < A8) || (rook > H8)) return FALSE;
147 if (board->square[rook] != BlackRook256) return FALSE;
149 if (rook <= king) return FALSE;
152 if (board->castle[Black][SideA] != SquareNone) {
154 king = board->list[Black][0];
155 if (king < A8 || king > H8) return FALSE;
156 if (board->square[king] != BlackKing256) return FALSE;
158 rook = board->castle[Black][SideA];
159 if (rook < A8 || rook > H8) return FALSE;
160 if (board->square[rook] != BlackRook256) return FALSE;
162 if (rook >= king) return FALSE;
170 void board_clear(board_t * board) {
180 for (sq = 0; sq < SquareNb; sq++) {
181 board->square[sq] = Knight64; // HACK: uncoloured knight
187 for (rank = 0; rank < 8; rank++) {
188 for (file = 0; file < 8; file++) {
189 sq = square_make(file,rank);
190 board->square[sq] = Empty;
196 for (colour = 0; colour < 3; colour++) {
197 for (pos = 0; pos < 32; pos++) { // HACK
198 board->list[colour][pos] = SquareNone;
200 board->list_size[colour] = 0;
205 for (piece = 0; piece < 12; piece++) {
206 board->number[piece] = 0;
211 board->turn = ColourNone;
212 board->castle[White][SideH] = SquareNone;
213 board->castle[White][SideA] = SquareNone;
214 board->castle[Black][SideH] = SquareNone;
215 board->castle[Black][SideA] = SquareNone;
216 board->ep_square = SquareNone;
226 void board_start(board_t * board) {
230 if (!board_from_fen(board,StartFen)) ASSERT(FALSE);
235 void board_copy(board_t * dst, const board_t * src) {
238 ASSERT(board_is_ok(src));
245 bool board_equal(const board_t * board_1, const board_t * board_2) {
249 ASSERT(board_is_ok(board_1));
250 ASSERT(board_is_ok(board_2));
254 if (board_1->key != board_2->key) return FALSE;
258 for (sq_64 = 0; sq_64 < 64; sq_64++) {
259 sq = square_from_64(sq_64);
260 if (board_1->square[sq] != board_2->square[sq]) return FALSE;
263 if (board_1->turn != board_2->turn) return FALSE;
264 if (board_1->castle[White][SideH] != board_2->castle[White][SideH]) return FALSE;
265 if (board_1->castle[White][SideA] != board_2->castle[White][SideA]) return FALSE;
266 if (board_1->castle[Black][SideH] != board_2->castle[Black][SideH]) return FALSE;
267 if (board_1->castle[Black][SideA] != board_2->castle[Black][SideA]) return FALSE;
268 if (board_1->ep_square != board_2->ep_square) return FALSE;
275 bool board_has_queen(const board_t * board, int colour) {
277 int sq_64, sq, piece;
281 for (sq_64 = 0; sq_64 < 64; sq_64++) {
282 sq = square_from_64(sq_64);
283 piece = board->square[sq];
284 if (colour_equal(piece,colour) && piece_is_queen(piece)) {
293 void board_init_list(board_t * board) {
295 int sq_64, sq, piece;
302 for (sq_64 = 0; sq_64 < 64; sq_64++) {
303 sq = square_from_64(sq_64);
307 for (piece = 0; piece < 12; piece++) board->number[piece] = 0;
314 for (sq_64 = 0; sq_64 < 64; sq_64++) {
315 sq = square_from_64(sq_64);
316 piece = board->square[sq];
317 ASSERT(pos>=0&&pos<=16);
318 if (colour_equal(piece,colour) && piece_is_king(piece)) {
319 board->pos[sq] = pos;
320 board->list[colour][pos] = sq;
322 board->number[piece_to_12(piece)]++;
327 for (sq_64 = 0; sq_64 < 64; sq_64++) {
328 sq = square_from_64(sq_64);
329 piece = board->square[sq];
330 ASSERT(pos>=0&&pos<=16);
331 if (colour_equal(piece,colour) && !piece_is_king(piece)) {
332 board->pos[sq] = pos;
333 board->list[colour][pos] = sq;
335 board->number[piece_to_12(piece)]++;
339 ASSERT(pos>=1&&pos<=16);
340 board->list[colour][pos] = SquareNone;
341 board->list_size[colour] = pos;
348 for (sq_64 = 0; sq_64 < 64; sq_64++) {
349 sq = square_from_64(sq_64);
350 piece = board->square[sq];
351 ASSERT(pos>=0&&pos<=16);
352 if (colour_equal(piece,colour) && piece_is_king(piece)) {
353 board->pos[sq] = pos;
354 board->list[colour][pos] = sq;
356 board->number[piece_to_12(piece)]++;
361 for (sq_64 = 0; sq_64 < 64; sq_64++) {
362 sq = square_from_64(sq_64);
363 piece = board->square[sq];
364 ASSERT(pos>=1&&pos<=16);
365 if (colour_equal(piece,colour) && !piece_is_king(piece)) {
366 board->pos[sq] = pos;
367 board->list[colour][pos] = sq;
369 board->number[piece_to_12(piece)]++;
373 ASSERT(pos>=1&&pos<=16);
374 board->list[colour][pos] = SquareNone;
375 board->list_size[colour] = pos;
379 board->key = hash_key(board);
384 int board_flags(const board_t * board) {
390 if (board->castle[White][SideH] != SquareNone) flags |= 1 << 0;
391 if (board->castle[White][SideA] != SquareNone) flags |= 1 << 1;
392 if (board->castle[Black][SideH] != SquareNone) flags |= 1 << 2;
393 if (board->castle[Black][SideA] != SquareNone) flags |= 1 << 3;
400 bool board_can_play(const board_t * board) {
405 ASSERT(board_is_ok(board));
407 gen_moves(list,board);
409 for (i = 0; i < list_size(list); i++) {
410 move = list_move(list,i);
411 if (pseudo_is_legal(move,board)) return TRUE;
414 return FALSE; // no legal move
419 int board_mobility(const board_t * board) {
423 ASSERT(board_is_ok(board));
425 gen_legal_moves(list,board);
427 return list_size(list);
432 bool board_is_check(const board_t * board) {
434 ASSERT(board_is_ok(board));
436 return is_in_check(board,board->turn);
441 bool board_is_mate(const board_t * board) {
443 ASSERT(board_is_ok(board));
445 if (!board_is_check(board)) return FALSE;
446 if (board_can_play(board)) return FALSE;
451 // board_is_stalemate()
453 bool board_is_stalemate(const board_t * board) {
455 ASSERT(board_is_ok(board));
457 if (board_is_check(board)) return FALSE;
458 if (board_can_play(board)) return FALSE;
465 int king_pos(const board_t * board, int colour) {
467 ASSERT(board_is_ok(board));
468 ASSERT(colour_is_ok(colour));
470 return board->list[colour][0];
475 void board_disp(const board_t * board) {
485 if (!board_to_fen(board,fen,256)) ASSERT(FALSE);
486 my_log("POLYGLOT FEN %s\n",fen);
487 my_log("POLYGLOT *** CURRENT BOARD ***\n");
489 for (rank = 7; rank >= 0; rank--) {
491 for (file = 0; file < 8; file++) {
493 sq = square_make(file,rank);
494 piece = board->square[sq];
496 c = (piece != Empty) ? piece_to_char(piece) : '-';
500 snprintf(line,sizeof(line),"POLYGLOT %s\n",row);
501 line[sizeof(line)-1]='\0';
505 my_log("POLYGLOT %s to play\n",(colour_is_black(board->turn))?"black":"white");
506 my_log("POLYGLOT\n");