--- /dev/null
+\r
+// board.c\r
+\r
+// includes\r
+\r
+#include <stdio.h>\r
+\r
+#include "attack.h"\r
+#include "board.h"\r
+#include "colour.h"\r
+#include "fen.h"\r
+#include "hash.h"\r
+#include "list.h"\r
+#include "move.h"\r
+#include "move_do.h"\r
+#include "move_gen.h"\r
+#include "move_legal.h"\r
+#include "piece.h"\r
+#include "util.h"\r
+\r
+// constants\r
+\r
+static const bool UseSlowDebug = FALSE;\r
+\r
+// functions\r
+\r
+// board_is_ok()\r
+\r
+bool board_is_ok(const board_t * board) {\r
+\r
+ int sq, piece;\r
+ int colour, pos;\r
+ int king, rook;\r
+\r
+ if (board == NULL) return FALSE;\r
+\r
+ // optional heavy DEBUG mode\r
+\r
+ if (!UseSlowDebug) return TRUE;\r
+\r
+ // squares\r
+\r
+ for (sq = 0; sq < SquareNb; sq++) {\r
+ piece = board->square[sq];\r
+ if (square_is_ok(sq)) {\r
+ pos = board->pos[sq];\r
+ if (piece == Empty) {\r
+ if (pos != -1) return FALSE;\r
+ } else {\r
+ if (pos < 0) return FALSE;\r
+ if (board->list[piece_colour(piece)][pos] != sq) return FALSE;\r
+ }\r
+ } else {\r
+ if (piece != Knight64) return FALSE;\r
+ }\r
+ }\r
+\r
+ // white piece list\r
+\r
+ colour = White;\r
+ pos = 0;\r
+\r
+ if (board->list_size[colour] <= 0 || board->list_size[colour] > 16) return FALSE;\r
+\r
+ sq = board->list[colour][pos];\r
+ if (sq == SquareNone) return FALSE;\r
+ if (board->pos[sq] != pos) return FALSE;\r
+ piece = board->square[sq];\r
+ if (!colour_equal(piece,colour) || !piece_is_king(piece)) return FALSE;\r
+\r
+ for (pos++; pos < board->list_size[colour]; pos++) {\r
+ sq = board->list[colour][pos];\r
+ if (sq == SquareNone) return FALSE;\r
+ if (board->pos[sq] != pos) return FALSE;\r
+ if (!colour_equal(board->square[sq],colour)) return FALSE;\r
+ }\r
+\r
+ sq = board->list[colour][pos];\r
+ if (sq != SquareNone) return FALSE;\r
+\r
+ // black piece list\r
+\r
+ colour = Black;\r
+ pos = 0;\r
+\r
+ if (board->list_size[colour] <= 0 || board->list_size[colour] > 16) return FALSE;\r
+\r
+ sq = board->list[colour][pos];\r
+ if (sq == SquareNone) return FALSE;\r
+ if (board->pos[sq] != pos) return FALSE;\r
+ piece = board->square[sq];\r
+ if (!colour_equal(piece,colour) || !piece_is_king(piece)) return FALSE;\r
+\r
+ for (pos++; pos < board->list_size[colour]; pos++) {\r
+ sq = board->list[colour][pos];\r
+ if (sq == SquareNone) return FALSE;\r
+ if (board->pos[sq] != pos) return FALSE;\r
+ if (!colour_equal(board->square[sq],colour)) return FALSE;\r
+ }\r
+\r
+ sq = board->list[colour][pos];\r
+ if (sq != SquareNone) return FALSE;\r
+\r
+ // TODO: material\r
+\r
+ if (board->number[WhiteKing12] != 1) return FALSE;\r
+ if (board->number[BlackKing12] != 1) return FALSE;\r
+\r
+ if (!colour_is_ok(board->turn)) return FALSE;\r
+\r
+ // castling status\r
+\r
+ if (board->castle[White][SideH] != SquareNone) {\r
+\r
+ king = board->list[White][0];\r
+ if ((king < A1) || (king > H1)) return FALSE;\r
+ if (board->square[king] != WhiteKing256) return FALSE;\r
+\r
+ rook = board->castle[White][SideH];\r
+ if ((rook < A1) || (rook > H1)) return FALSE;\r
+ if (board->square[rook] != WhiteRook256) return FALSE;\r
+\r
+ if (rook <= king) return FALSE;\r
+ }\r
+\r
+ if (board->castle[White][SideA] != SquareNone) {\r
+\r
+ king = board->list[White][0];\r
+ if ((king < A1) || (king > H1)) return FALSE;\r
+ if (board->square[king] != WhiteKing256) return FALSE;\r
+\r
+ rook = board->castle[White][SideA];\r
+ if ((rook < A1) || (rook > H1)) return FALSE;\r
+ if (board->square[rook] != WhiteRook256) return FALSE;\r
+\r
+ if (rook >= king) return FALSE;\r
+ }\r
+\r
+ if (board->castle[Black][SideH] != SquareNone) {\r
+\r
+ king = board->list[Black][0];\r
+ if ((king < A8) || (king > H8)) return FALSE;\r
+ if (board->square[king] != BlackKing256) return FALSE;\r
+\r
+ rook = board->castle[Black][SideH];\r
+ if ((rook < A8) || (rook > H8)) return FALSE;\r
+ if (board->square[rook] != BlackRook256) return FALSE;\r
+\r
+ if (rook <= king) return FALSE;\r
+ }\r
+\r
+ if (board->castle[Black][SideA] != SquareNone) {\r
+\r
+ king = board->list[Black][0];\r
+ if (king < A8 || king > H8) return FALSE;\r
+ if (board->square[king] != BlackKing256) return FALSE;\r
+\r
+ rook = board->castle[Black][SideA];\r
+ if (rook < A8 || rook > H8) return FALSE;\r
+ if (board->square[rook] != BlackRook256) return FALSE;\r
+\r
+ if (rook >= king) return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+// board_clear()\r
+\r
+void board_clear(board_t * board) {\r
+\r
+ int file, rank, sq;\r
+ int colour, pos;\r
+ int piece;\r
+\r
+ ASSERT(board!=NULL);\r
+\r
+ // edge squares\r
+\r
+ for (sq = 0; sq < SquareNb; sq++) {\r
+ board->square[sq] = Knight64; // HACK: uncoloured knight\r
+ board->pos[sq] = -1;\r
+ }\r
+\r
+ // empty squares\r
+\r
+ for (rank = 0; rank < 8; rank++) {\r
+ for (file = 0; file < 8; file++) {\r
+ sq = square_make(file,rank);\r
+ board->square[sq] = Empty;\r
+ }\r
+ }\r
+\r
+ // piece lists\r
+\r
+ for (colour = 0; colour < 3; colour++) {\r
+ for (pos = 0; pos < 32; pos++) { // HACK\r
+ board->list[colour][pos] = SquareNone;\r
+ }\r
+ board->list_size[colour] = 0;\r
+ }\r
+\r
+ // material\r
+\r
+ for (piece = 0; piece < 12; piece++) {\r
+ board->number[piece] = 0;\r
+ }\r
+\r
+ // rest\r
+\r
+ board->turn = ColourNone;\r
+ board->castle[White][SideH] = SquareNone;\r
+ board->castle[White][SideA] = SquareNone;\r
+ board->castle[Black][SideH] = SquareNone;\r
+ board->castle[Black][SideA] = SquareNone;\r
+ board->ep_square = SquareNone;\r
+\r
+ board->ply_nb = 0;\r
+ board->move_nb = 0;\r
+\r
+ board->key = 0;\r
+}\r
+\r
+// board_start()\r
+\r
+void board_start(board_t * board) {\r
+\r
+ ASSERT(board!=NULL);\r
+\r
+ if (!board_from_fen(board,StartFen)) ASSERT(FALSE);\r
+}\r
+\r
+// board_copy()\r
+\r
+void board_copy(board_t * dst, const board_t * src) {\r
+\r
+ ASSERT(dst!=NULL);\r
+ ASSERT(board_is_ok(src));\r
+\r
+ *dst = *src;\r
+}\r
+\r
+// board_equal()\r
+\r
+bool board_equal(const board_t * board_1, const board_t * board_2) {\r
+\r
+ int sq_64, sq;\r
+\r
+ ASSERT(board_is_ok(board_1));\r
+ ASSERT(board_is_ok(board_2));\r
+\r
+ // fast comparison\r
+\r
+ if (board_1->key != board_2->key) return FALSE;\r
+\r
+ // slow comparison\r
+\r
+ for (sq_64 = 0; sq_64 < 64; sq_64++) {\r
+ sq = square_from_64(sq_64);\r
+ if (board_1->square[sq] != board_2->square[sq]) return FALSE;\r
+ }\r
+\r
+ if (board_1->turn != board_2->turn) return FALSE;\r
+ if (board_1->castle[White][SideH] != board_2->castle[White][SideH]) return FALSE;\r
+ if (board_1->castle[White][SideA] != board_2->castle[White][SideA]) return FALSE;\r
+ if (board_1->castle[Black][SideH] != board_2->castle[Black][SideH]) return FALSE;\r
+ if (board_1->castle[Black][SideA] != board_2->castle[Black][SideA]) return FALSE;\r
+ if (board_1->ep_square != board_2->ep_square) return FALSE;\r
+\r
+ return TRUE;\r
+}\r
+\r
+// board_init_list()\r
+\r
+void board_init_list(board_t * board) {\r
+\r
+ int sq_64, sq, piece;\r
+ int colour, pos;\r
+\r
+ ASSERT(board!=NULL);\r
+\r
+ // init\r
+\r
+ for (sq_64 = 0; sq_64 < 64; sq_64++) {\r
+ sq = square_from_64(sq_64);\r
+ board->pos[sq] = -1;\r
+ }\r
+\r
+ for (piece = 0; piece < 12; piece++) board->number[piece] = 0;\r
+\r
+ // white piece list\r
+\r
+ colour = White;\r
+ pos = 0;\r
+\r
+ for (sq_64 = 0; sq_64 < 64; sq_64++) {\r
+ sq = square_from_64(sq_64);\r
+ piece = board->square[sq];\r
+ ASSERT(pos>=0&&pos<=16);\r
+ if (colour_equal(piece,colour) && piece_is_king(piece)) {\r
+ board->pos[sq] = pos;\r
+ board->list[colour][pos] = sq;\r
+ pos++;\r
+ board->number[piece_to_12(piece)]++;\r
+ }\r
+ }\r
+ ASSERT(pos==1);\r
+\r
+ for (sq_64 = 0; sq_64 < 64; sq_64++) {\r
+ sq = square_from_64(sq_64);\r
+ piece = board->square[sq];\r
+ ASSERT(pos>=0&&pos<=16);\r
+ if (colour_equal(piece,colour) && !piece_is_king(piece)) {\r
+ board->pos[sq] = pos;\r
+ board->list[colour][pos] = sq;\r
+ pos++;\r
+ board->number[piece_to_12(piece)]++;\r
+ }\r
+ }\r
+\r
+ ASSERT(pos>=1&&pos<=16);\r
+ board->list[colour][pos] = SquareNone;\r
+ board->list_size[colour] = pos;\r
+\r
+ // black piece list\r
+\r
+ colour = Black;\r
+ pos = 0;\r
+\r
+ for (sq_64 = 0; sq_64 < 64; sq_64++) {\r
+ sq = square_from_64(sq_64);\r
+ piece = board->square[sq];\r
+ ASSERT(pos>=0&&pos<=16);\r
+ if (colour_equal(piece,colour) && piece_is_king(piece)) {\r
+ board->pos[sq] = pos;\r
+ board->list[colour][pos] = sq;\r
+ pos++;\r
+ board->number[piece_to_12(piece)]++;\r
+ }\r
+ }\r
+ ASSERT(pos==1);\r
+\r
+ for (sq_64 = 0; sq_64 < 64; sq_64++) {\r
+ sq = square_from_64(sq_64);\r
+ piece = board->square[sq];\r
+ ASSERT(pos>=1&&pos<=16);\r
+ if (colour_equal(piece,colour) && !piece_is_king(piece)) {\r
+ board->pos[sq] = pos;\r
+ board->list[colour][pos] = sq;\r
+ pos++;\r
+ board->number[piece_to_12(piece)]++;\r
+ }\r
+ }\r
+\r
+ ASSERT(pos>=1&&pos<=16);\r
+ board->list[colour][pos] = SquareNone;\r
+ board->list_size[colour] = pos;\r
+\r
+ // hash key\r
+\r
+ board->key = hash_key(board);\r
+}\r
+\r
+// board_flags()\r
+\r
+int board_flags(const board_t * board) {\r
+\r
+ int flags;\r
+\r
+ flags = 0;\r
+\r
+ if (board->castle[White][SideH] != SquareNone) flags |= 1 << 0;\r
+ if (board->castle[White][SideA] != SquareNone) flags |= 1 << 1;\r
+ if (board->castle[Black][SideH] != SquareNone) flags |= 1 << 2;\r
+ if (board->castle[Black][SideA] != SquareNone) flags |= 1 << 3;\r
+\r
+ return flags;\r
+}\r
+\r
+// board_can_play()\r
+\r
+bool board_can_play(const board_t * board) {\r
+\r
+ list_t list[1];\r
+ int i, move;\r
+\r
+ ASSERT(board_is_ok(board));\r
+\r
+ gen_moves(list,board);\r
+\r
+ for (i = 0; i < list_size(list); i++) {\r
+ move = list_move(list,i);\r
+ if (pseudo_is_legal(move,board)) return TRUE;\r
+ }\r
+\r
+ return FALSE; // no legal move\r
+}\r
+\r
+// board_mobility()\r
+\r
+int board_mobility(const board_t * board) {\r
+\r
+ list_t list[1];\r
+\r
+ ASSERT(board_is_ok(board));\r
+\r
+ gen_legal_moves(list,board);\r
+\r
+ return list_size(list);\r
+}\r
+\r
+// board_is_check()\r
+\r
+bool board_is_check(const board_t * board) {\r
+\r
+ ASSERT(board_is_ok(board));\r
+\r
+ return is_in_check(board,board->turn);\r
+}\r
+\r
+// board_is_mate()\r
+\r
+bool board_is_mate(const board_t * board) {\r
+\r
+ ASSERT(board_is_ok(board));\r
+\r
+ if (!board_is_check(board)) return FALSE;\r
+ if (board_can_play(board)) return FALSE;\r
+\r
+ return TRUE;\r
+}\r
+\r
+// board_is_stalemate()\r
+\r
+bool board_is_stalemate(const board_t * board) {\r
+\r
+ ASSERT(board_is_ok(board));\r
+\r
+ if (board_is_check(board)) return FALSE;\r
+ if (board_can_play(board)) return FALSE;\r
+\r
+ return TRUE;\r
+}\r
+\r
+// king_pos()\r
+\r
+int king_pos(const board_t * board, int colour) {\r
+\r
+ ASSERT(board_is_ok(board));\r
+ ASSERT(colour_is_ok(colour));\r
+\r
+ return board->list[colour][0];\r
+}\r
+\r
+// board_disp()\r
+\r
+void board_disp(const board_t * board) {\r
+\r
+ int file, rank, sq;\r
+ int piece, c;\r
+ char fen[256];\r
+\r
+ ASSERT(board!=NULL);\r
+\r
+ if (!board_to_fen(board,fen,256)) ASSERT(FALSE);\r
+ my_log("POLYGLOT %s\n",fen);\r
+ my_log("POLYGLOT\n");\r
+\r
+ for (rank = 7; rank >= 0; rank--) {\r
+\r
+ my_log("POLYGLOT ");\r
+\r
+ for (file = 0; file < 8; file++) {\r
+\r
+ sq = square_make(file,rank);\r
+ piece = board->square[sq];\r
+\r
+ c = (piece != Empty) ? piece_to_char(piece) : '-';\r
+ my_log("%c ",c);\r
+ }\r
+\r
+ my_log("\n");\r
+ }\r
+\r
+ my_log("POLYGLOT\n");\r
+\r
+ my_log("POLYGLOT %s to play\n",(colour_is_black(board->turn))?"black":"white");\r
+ my_log("POLYGLOT\n");\r
+}\r
+\r
+// end of board.cpp\r
+\r