13 #include "move_legal.h"
20 static const bool UseSlowDebug = FALSE;
28 static void game_update (game_t * game);
29 static int game_comp_status (const game_t * game);
35 bool game_is_ok(const game_t * game) {
40 if (game == NULL) return FALSE;
42 if (game->size < 0 || game->size > GameSize) return FALSE;
43 if (game->pos < 0 || game->pos > game->size) return FALSE;
45 // optional heavy DEBUG mode
47 if (!UseSlowDebug) return TRUE;
49 if (!board_is_ok(game->start_board)) return FALSE;
51 board_copy(board,game->start_board);
53 for (pos = 0; pos <= game->size; pos++) {
55 if (pos == game->pos) {
56 if (!board_equal(game->board,board)) return FALSE;
59 if (pos >= game->size) break;
61 if (game->key[pos] != board->key) return FALSE;
63 move = game->move[pos];
64 //if (!move_is_legal(move,board)); //huh??
65 if (!move_is_legal(move,board)) return FALSE;
70 if (game->status != game_comp_status(game)) return FALSE;
77 void game_clear(game_t * game) {
81 game_init(game,StartFen);
86 bool game_init(game_t * game, const char fen[]) {
91 if (!board_from_fen(game->start_board,fen)) return FALSE;
95 board_copy(game->board,game->start_board);
105 int game_status(const game_t * game) {
114 int game_size(const game_t * game) {
123 int game_pos(const game_t * game) {
132 int game_move(const game_t * game, int pos) {
135 ASSERT(pos>=0&&pos<game->pos);
137 return game->move[pos];
142 void game_get_board(const game_t * game, board_t * board) {
143 game_get_board_ex(game, board, -1);
146 // game_get_board_ex()
148 void game_get_board_ex(const game_t * game, board_t * board, int pos) {
155 ASSERT(pos==-1||(pos>=0&&pos<=game->size)); // HACK
157 if (pos < 0) pos = game->pos;
159 if (pos >= game->pos) { // forward from current position
161 board_copy(board,game->board);
162 } else { // backward => replay the whole game
164 board_copy(board,game->start_board);
167 for (i = start; i < pos; i++) move_do(board,game->move[i]);
172 int game_turn(const game_t * game) {
176 return game->board->turn;
181 int game_move_nb(const game_t * game) {
185 return game->board->move_nb;
190 void game_add_move(game_t * game, int move) {
193 ASSERT(move_is_ok(move));
195 ASSERT(move_is_legal(move,game->board));
197 if (game->pos >= GameSize) my_fatal("game_add_move(): game overflow\n");
199 game->move[game->pos] = move;
200 game->key[game->pos] = game->board->key;
202 move_do(game->board,move);
205 game->size = game->pos; // truncate game, HACK: before calling game_is_ok() in game_update()
212 void game_rem_move(game_t * game) {
216 game_goto(game,game->pos-1);
218 game->size = game->pos; // truncate game
223 void game_goto(game_t * game, int pos) {
228 ASSERT(pos>=0&&pos<=game->size);
230 if (pos < game->pos) { // going backward => replay the whole game
231 board_copy(game->board,game->start_board);
235 for (i = game->pos; i < pos; i++) move_do(game->board,game->move[i]);
245 void game_disp(const game_t * game) {
250 ASSERT(game_is_ok(game));
252 board_copy(board,game->start_board);
256 for (i = 0; i < game->pos; i++) {
258 move = game->move[i];
259 move_disp(move,board);
264 my_log("POLYGLOT\n");
271 static void game_update(game_t * game) {
275 game->status = game_comp_status(game);
277 ASSERT(game_is_ok(game));
280 // game_comp_status()
282 static int game_comp_status(const game_t * game) {
286 const board_t * board;
296 // mate and stalemate
298 if (!board_can_play(board)) {
300 } else if (is_in_check(board,Black)) { // HACK
302 } else if (is_in_check(board,White)) { // HACK
309 // insufficient material
311 if (board->number[WhitePawn12] == 0
312 && board->number[BlackPawn12] == 0
313 && board->number[WhiteQueen12] == 0
314 && board->number[BlackQueen12] == 0
315 && board->number[WhiteRook12] == 0
316 && board->number[BlackRook12] == 0) {
318 if (board->number[WhiteBishop12]
319 + board->number[BlackBishop12]
320 + board->number[WhiteKnight12]
321 + board->number[BlackKnight12] <= 1) { // KK, KBK and KNK
323 return DRAW_MATERIAL;
325 } else if (board->number[WhiteBishop12] == 1
326 && board->number[BlackBishop12] == 1
327 && board->number[WhiteKnight12] == 0
328 && board->number[BlackKnight12] == 0) {
330 wb = board->list[White][1]; // HACK
331 bb = board->list[Black][1]; // HACK
333 if (square_colour(wb) == square_colour(bb)) { // KBKB
334 return DRAW_MATERIAL;
341 if (board->ply_nb >= 100) return DRAW_FIFTY;
343 // position repetition
348 start = game->pos - board->ply_nb;
349 if (start < 0) start = 0;
351 for (i = game->pos-4; i >= start; i -= 2) {
352 if (game->key[i] == key) {
353 if (++n == 2) return DRAW_REPETITION;