15 #include "move_do.h"
\r
16 #include "move_gen.h"
\r
17 #include "move_legal.h"
\r
23 static const bool UseSlowDebug = false;
\r
29 bool board_is_ok(const board_t * board) {
\r
35 if (board == NULL) return false;
\r
37 // optional heavy DEBUG mode
\r
39 if (!UseSlowDebug) return true;
\r
43 for (sq = 0; sq < SquareNb; sq++) {
\r
44 piece = board->square[sq];
\r
45 if (square_is_ok(sq)) {
\r
46 pos = board->pos[sq];
\r
47 if (piece == Empty) {
\r
48 if (pos != -1) return false;
\r
50 if (pos < 0) return false;
\r
51 if (board->list[piece_colour(piece)][pos] != sq) return false;
\r
54 if (piece != Knight64) return false;
\r
63 if (board->list_size[colour] <= 0 || board->list_size[colour] > 16) return false;
\r
65 sq = board->list[colour][pos];
\r
66 if (sq == SquareNone) return false;
\r
67 if (board->pos[sq] != pos) return false;
\r
68 piece = board->square[sq];
\r
69 if (!colour_equal(piece,colour) || !piece_is_king(piece)) return false;
\r
71 for (pos++; pos < board->list_size[colour]; pos++) {
\r
72 sq = board->list[colour][pos];
\r
73 if (sq == SquareNone) return false;
\r
74 if (board->pos[sq] != pos) return false;
\r
75 if (!colour_equal(board->square[sq],colour)) return false;
\r
78 sq = board->list[colour][pos];
\r
79 if (sq != SquareNone) return false;
\r
86 if (board->list_size[colour] <= 0 || board->list_size[colour] > 16) return false;
\r
88 sq = board->list[colour][pos];
\r
89 if (sq == SquareNone) return false;
\r
90 if (board->pos[sq] != pos) return false;
\r
91 piece = board->square[sq];
\r
92 if (!colour_equal(piece,colour) || !piece_is_king(piece)) return false;
\r
94 for (pos++; pos < board->list_size[colour]; pos++) {
\r
95 sq = board->list[colour][pos];
\r
96 if (sq == SquareNone) return false;
\r
97 if (board->pos[sq] != pos) return false;
\r
98 if (!colour_equal(board->square[sq],colour)) return false;
\r
101 sq = board->list[colour][pos];
\r
102 if (sq != SquareNone) return false;
\r
106 if (board->number[WhiteKing12] != 1) return false;
\r
107 if (board->number[BlackKing12] != 1) return false;
\r
109 if (!colour_is_ok(board->turn)) return false;
\r
113 if (board->castle[White][SideH] != SquareNone) {
\r
115 king = board->list[White][0];
\r
116 if (king < A1 || king > H1) return false;
\r
117 if (board->square[king] != WhiteKing256) return false;
\r
119 rook = board->castle[White][SideH];
\r
120 if (rook < A1 || rook > H1) return false;
\r
121 if (board->square[rook] != WhiteRook256) return false;
\r
123 if (rook <= king) return false;
\r
126 if (board->castle[White][SideA] != SquareNone) {
\r
128 king = board->list[White][0];
\r
129 if (king < A1 || king > H1) return false;
\r
130 if (board->square[king] != WhiteKing256) return false;
\r
132 rook = board->castle[White][SideA];
\r
133 if (rook < A1 || rook > H1) return false;
\r
134 if (board->square[rook] != WhiteRook256) return false;
\r
136 if (rook >= king) return false;
\r
139 if (board->castle[Black][SideH] != SquareNone) {
\r
141 king = board->list[Black][0];
\r
142 if (king < A8 || king > H8) return false;
\r
143 if (board->square[king] != BlackKing256) return false;
\r
145 rook = board->castle[Black][SideH];
\r
146 if (rook < A8 || rook > H8) return false;
\r
147 if (board->square[rook] != BlackRook256) return false;
\r
149 if (rook <= king) return false;
\r
152 if (board->castle[Black][SideA] != SquareNone) {
\r
154 king = board->list[Black][0];
\r
155 if (king < A8 || king > H8) return false;
\r
156 if (board->square[king] != BlackKing256) return false;
\r
158 rook = board->castle[Black][SideA];
\r
159 if (rook < A8 || rook > H8) return false;
\r
160 if (board->square[rook] != BlackRook256) return false;
\r
162 if (rook >= king) return false;
\r
170 void board_clear(board_t * board) {
\r
172 int file, rank, sq;
\r
176 ASSERT(board!=NULL);
\r
180 for (sq = 0; sq < SquareNb; sq++) {
\r
181 board->square[sq] = Knight64; // HACK: uncoloured knight
\r
182 board->pos[sq] = -1;
\r
187 for (rank = 0; rank < 8; rank++) {
\r
188 for (file = 0; file < 8; file++) {
\r
189 sq = square_make(file,rank);
\r
190 board->square[sq] = Empty;
\r
196 for (colour = 0; colour < 3; colour++) {
\r
197 for (pos = 0; pos < 32; pos++) { // HACK
\r
198 board->list[colour][pos] = SquareNone;
\r
200 board->list_size[colour] = 0;
\r
205 for (piece = 0; piece < 12; piece++) {
\r
206 board->number[piece] = 0;
\r
211 board->turn = ColourNone;
\r
212 board->castle[White][SideH] = SquareNone;
\r
213 board->castle[White][SideA] = SquareNone;
\r
214 board->castle[Black][SideH] = SquareNone;
\r
215 board->castle[Black][SideA] = SquareNone;
\r
216 board->ep_square = SquareNone;
\r
219 board->move_nb = 0;
\r
226 void board_start(board_t * board) {
\r
228 ASSERT(board!=NULL);
\r
230 if (!board_from_fen(board,StartFen)) ASSERT(false);
\r
235 void board_copy(board_t * dst, const board_t * src) {
\r
238 ASSERT(board_is_ok(src));
\r
245 bool board_equal(const board_t * board_1, const board_t * board_2) {
\r
249 ASSERT(board_is_ok(board_1));
\r
250 ASSERT(board_is_ok(board_2));
\r
254 if (board_1->key != board_2->key) return false;
\r
258 for (sq_64 = 0; sq_64 < 64; sq_64++) {
\r
259 sq = square_from_64(sq_64);
\r
260 if (board_1->square[sq] != board_2->square[sq]) return false;
\r
263 if (board_1->turn != board_2->turn) return false;
\r
264 if (board_1->castle[White][SideH] != board_2->castle[White][SideH]) return false;
\r
265 if (board_1->castle[White][SideA] != board_2->castle[White][SideA]) return false;
\r
266 if (board_1->castle[Black][SideH] != board_2->castle[Black][SideH]) return false;
\r
267 if (board_1->castle[Black][SideA] != board_2->castle[Black][SideA]) return false;
\r
268 if (board_1->ep_square != board_2->ep_square) return false;
\r
273 // board_init_list()
\r
275 void board_init_list(board_t * board) {
\r
277 int sq_64, sq, piece;
\r
280 ASSERT(board!=NULL);
\r
284 for (sq_64 = 0; sq_64 < 64; sq_64++) {
\r
285 sq = square_from_64(sq_64);
\r
286 board->pos[sq] = -1;
\r
289 for (piece = 0; piece < 12; piece++) board->number[piece] = 0;
\r
291 // white piece list
\r
296 for (sq_64 = 0; sq_64 < 64; sq_64++) {
\r
297 sq = square_from_64(sq_64);
\r
298 piece = board->square[sq];
\r
299 ASSERT(pos>=0&&pos<=16);
\r
300 if (colour_equal(piece,colour) && piece_is_king(piece)) {
\r
301 board->pos[sq] = pos;
\r
302 board->list[colour][pos] = sq;
\r
304 board->number[piece_to_12(piece)]++;
\r
309 for (sq_64 = 0; sq_64 < 64; sq_64++) {
\r
310 sq = square_from_64(sq_64);
\r
311 piece = board->square[sq];
\r
312 ASSERT(pos>=0&&pos<=16);
\r
313 if (colour_equal(piece,colour) && !piece_is_king(piece)) {
\r
314 board->pos[sq] = pos;
\r
315 board->list[colour][pos] = sq;
\r
317 board->number[piece_to_12(piece)]++;
\r
321 ASSERT(pos>=1&&pos<=16);
\r
322 board->list[colour][pos] = SquareNone;
\r
323 board->list_size[colour] = pos;
\r
325 // black piece list
\r
330 for (sq_64 = 0; sq_64 < 64; sq_64++) {
\r
331 sq = square_from_64(sq_64);
\r
332 piece = board->square[sq];
\r
333 ASSERT(pos>=0&&pos<=16);
\r
334 if (colour_equal(piece,colour) && piece_is_king(piece)) {
\r
335 board->pos[sq] = pos;
\r
336 board->list[colour][pos] = sq;
\r
338 board->number[piece_to_12(piece)]++;
\r
343 for (sq_64 = 0; sq_64 < 64; sq_64++) {
\r
344 sq = square_from_64(sq_64);
\r
345 piece = board->square[sq];
\r
346 ASSERT(pos>=1&&pos<=16);
\r
347 if (colour_equal(piece,colour) && !piece_is_king(piece)) {
\r
348 board->pos[sq] = pos;
\r
349 board->list[colour][pos] = sq;
\r
351 board->number[piece_to_12(piece)]++;
\r
355 ASSERT(pos>=1&&pos<=16);
\r
356 board->list[colour][pos] = SquareNone;
\r
357 board->list_size[colour] = pos;
\r
361 board->key = hash_key(board);
\r
366 int board_flags(const board_t * board) {
\r
372 if (board->castle[White][SideH] != SquareNone) flags |= 1 << 0;
\r
373 if (board->castle[White][SideA] != SquareNone) flags |= 1 << 1;
\r
374 if (board->castle[Black][SideH] != SquareNone) flags |= 1 << 2;
\r
375 if (board->castle[Black][SideA] != SquareNone) flags |= 1 << 3;
\r
380 // board_can_play()
\r
382 bool board_can_play(const board_t * board) {
\r
387 ASSERT(board_is_ok(board));
\r
389 gen_moves(list,board);
\r
391 for (i = 0; i < list_size(list); i++) {
\r
392 move = list_move(list,i);
\r
393 if (pseudo_is_legal(move,board)) return true;
\r
396 return false; // no legal move
\r
399 // board_mobility()
\r
401 int board_mobility(const board_t * board) {
\r
405 ASSERT(board_is_ok(board));
\r
407 gen_legal_moves(list,board);
\r
409 return list_size(list);
\r
412 // board_is_check()
\r
414 bool board_is_check(const board_t * board) {
\r
416 ASSERT(board_is_ok(board));
\r
418 return is_in_check(board,board->turn);
\r
423 bool board_is_mate(const board_t * board) {
\r
425 ASSERT(board_is_ok(board));
\r
427 if (!board_is_check(board)) return false;
\r
428 if (board_can_play(board)) return false;
\r
433 // board_is_stalemate()
\r
435 bool board_is_stalemate(const board_t * board) {
\r
437 ASSERT(board_is_ok(board));
\r
439 if (board_is_check(board)) return false;
\r
440 if (board_can_play(board)) return false;
\r
447 int king_pos(const board_t * board, int colour) {
\r
449 ASSERT(board_is_ok(board));
\r
450 ASSERT(colour_is_ok(colour));
\r
452 return board->list[colour][0];
\r
457 void board_disp(const board_t * board) {
\r
459 int file, rank, sq;
\r
463 ASSERT(board!=NULL);
\r
465 if (!board_to_fen(board,fen,256)) ASSERT(false);
\r
466 my_log("POLYGLOT %s\n",fen);
\r
467 my_log("POLYGLOT\n");
\r
469 for (rank = 7; rank >= 0; rank--) {
\r
471 my_log("POLYGLOT ");
\r
473 for (file = 0; file < 8; file++) {
\r
475 sq = square_make(file,rank);
\r
476 piece = board->square[sq];
\r
478 c = (piece != Empty) ? piece_to_char(piece) : '-';
\r
485 my_log("POLYGLOT\n");
\r
487 my_log("POLYGLOT %s to play\n",(colour_is_black(board->turn))?"black":"white");
\r
488 my_log("POLYGLOT\n");
\r
491 // end of board.cpp
\r