12 #include "move_do.h"
\r
13 #include "move_legal.h"
\r
20 static const bool UseSlowDebug = false;
\r
28 static void game_update (game_t * game);
\r
29 static int game_comp_status (const game_t * game);
\r
35 bool game_is_ok(const game_t * game) {
\r
40 if (game == NULL) return false;
\r
42 if (game->size < 0 || game->size > GameSize) return false;
\r
43 if (game->pos < 0 || game->pos > game->size) return false;
\r
45 // optional heavy DEBUG mode
\r
47 if (!UseSlowDebug) return true;
\r
49 if (!board_is_ok(game->start_board)) return false;
\r
51 board_copy(board,game->start_board);
\r
53 for (pos = 0; pos <= game->size; pos++) {
\r
55 if (pos == game->pos) {
\r
56 if (!board_equal(game->board,board)) return false;
\r
59 if (pos >= game->size) break;
\r
61 if (game->key[pos] != board->key) return false;
\r
63 move = game->move[pos];
\r
64 //if (!move_is_legal(move,board)); //huh??
\r
65 if (!move_is_legal(move,board)) return false;
\r
67 move_do(board,move);
\r
70 if (game->status != game_comp_status(game)) return false;
\r
77 void game_clear(game_t * game) {
\r
81 game_init(game,StartFen);
\r
86 bool game_init(game_t * game, const char fen[]) {
\r
91 if (!board_from_fen(game->start_board,fen)) return false;
\r
95 board_copy(game->board,game->start_board);
\r
105 int game_status(const game_t * game) {
\r
107 ASSERT(game!=NULL);
\r
109 return game->status;
\r
114 int game_size(const game_t * game) {
\r
116 ASSERT(game!=NULL);
\r
123 int game_pos(const game_t * game) {
\r
125 ASSERT(game!=NULL);
\r
132 int game_move(const game_t * game, int pos) {
\r
134 ASSERT(game!=NULL);
\r
135 ASSERT(pos>=0&&pos<game->pos);
\r
137 return game->move[pos];
\r
140 // game_get_board()
\r
142 void game_get_board(const game_t * game, board_t * board, int pos) {
\r
147 ASSERT(game!=NULL);
\r
148 ASSERT(board!=NULL);
\r
149 ASSERT(pos==-1||(pos>=0&&pos<=game->size)); // HACK
\r
151 if (pos < 0) pos = game->pos;
\r
153 if (pos >= game->pos) { // forward from current position
\r
155 board_copy(board,game->board);
\r
156 } else { // backward => replay the whole game
\r
158 board_copy(board,game->start_board);
\r
161 for (i = start; i < pos; i++) move_do(board,game->move[i]);
\r
166 int game_turn(const game_t * game) {
\r
168 ASSERT(game!=NULL);
\r
170 return game->board->turn;
\r
175 int game_move_nb(const game_t * game) {
\r
177 ASSERT(game!=NULL);
\r
179 return game->board->move_nb;
\r
184 void game_add_move(game_t * game, int move) {
\r
186 ASSERT(game!=NULL);
\r
187 ASSERT(move_is_ok(move));
\r
189 ASSERT(move_is_legal(move,game->board));
\r
191 if (game->pos >= GameSize) my_fatal("game_add_move(): game overflow\n");
\r
193 game->move[game->pos] = move;
\r
194 game->key[game->pos] = game->board->key;
\r
196 move_do(game->board,move);
\r
199 game->size = game->pos; // truncate game, HACK: before calling game_is_ok() in game_update()
\r
206 void game_rem_move(game_t * game) {
\r
208 ASSERT(game!=NULL);
\r
210 game_goto(game,game->pos-1);
\r
212 game->size = game->pos; // truncate game
\r
217 void game_goto(game_t * game, int pos) {
\r
221 ASSERT(game!=NULL);
\r
222 ASSERT(pos>=0&&pos<=game->size);
\r
224 if (pos < game->pos) { // going backward => replay the whole game
\r
225 board_copy(game->board,game->start_board);
\r
229 for (i = game->pos; i < pos; i++) move_do(game->board,game->move[i]);
\r
239 void game_disp(const game_t * game) {
\r
244 ASSERT(game_is_ok(game));
\r
246 board_copy(board,game->start_board);
\r
250 for (i = 0; i < game->pos; i++) {
\r
252 move = game->move[i];
\r
253 move_disp(move,board);
\r
255 move_do(board,move);
\r
258 my_log("POLYGLOT\n");
\r
265 static void game_update(game_t * game) {
\r
267 ASSERT(game!=NULL);
\r
269 game->status = game_comp_status(game);
\r
271 ASSERT(game_is_ok(game));
\r
274 // game_comp_status()
\r
276 static int game_comp_status(const game_t * game) {
\r
280 const board_t * board;
\r
284 ASSERT(game!=NULL);
\r
288 board = game->board;
\r
290 // mate and stalemate
\r
292 if (!board_can_play(board)) {
\r
294 } else if (is_in_check(board,Black)) { // HACK
\r
295 return WHITE_MATES;
\r
296 } else if (is_in_check(board,White)) { // HACK
\r
297 return BLACK_MATES;
\r
303 // insufficient material
\r
305 if (board->number[WhitePawn12] == 0
\r
306 && board->number[BlackPawn12] == 0
\r
307 && board->number[WhiteQueen12] == 0
\r
308 && board->number[BlackQueen12] == 0
\r
309 && board->number[WhiteRook12] == 0
\r
310 && board->number[BlackRook12] == 0) {
\r
312 if (board->number[WhiteBishop12]
\r
313 + board->number[BlackBishop12]
\r
314 + board->number[WhiteKnight12]
\r
315 + board->number[BlackKnight12] <= 1) { // KK, KBK and KNK
\r
317 return DRAW_MATERIAL;
\r
319 } else if (board->number[WhiteBishop12] == 1
\r
320 && board->number[BlackBishop12] == 1
\r
321 && board->number[WhiteKnight12] == 0
\r
322 && board->number[BlackKnight12] == 0) {
\r
324 wb = board->list[White][1]; // HACK
\r
325 bb = board->list[Black][1]; // HACK
\r
327 if (square_colour(wb) == square_colour(bb)) { // KBKB
\r
328 return DRAW_MATERIAL;
\r
335 if (board->ply_nb >= 100) return DRAW_FIFTY;
\r
337 // position repetition
\r
342 start = game->pos - board->ply_nb;
\r
343 if (start < 0) start = 0;
\r
345 for (i = game->pos-4; i >= start; i -= 2) {
\r
346 if (game->key[i] == key) {
\r
347 if (++n == 2) return DRAW_REPETITION;
\r