Add forgotten files 1.4.70b
[polyglot.git] / game.c
diff --git a/game.c b/game.c
index 199d344..d28031d 100644 (file)
--- a/game.c
+++ b/game.c
-\r
-// game.c\r
-\r
-// includes\r
-\r
-#include "attack.h"\r
-#include "board.h"\r
-#include "fen.h"\r
-#include "game.h"\r
-#include "list.h"\r
-#include "move.h"\r
-#include "move_do.h"\r
-#include "move_legal.h"\r
-#include "piece.h"\r
-#include "square.h"\r
-#include "util.h"\r
-\r
-// constants\r
-\r
-static const bool UseSlowDebug = FALSE;\r
-\r
-// variables\r
-\r
-game_t Game[1];\r
-\r
-// prototypes\r
-\r
-static void game_update      (game_t * game);\r
-static int  game_comp_status (const game_t * game);\r
-\r
-// functions\r
-\r
-// game_is_ok()\r
-\r
-bool game_is_ok(const game_t * game) {\r
-\r
-   board_t board[1];\r
-   int pos, move;\r
-\r
-   if (game == NULL) return FALSE;\r
-\r
-   if (game->size < 0 || game->size > GameSize) return FALSE;\r
-   if (game->pos < 0 || game->pos > game->size) return FALSE;\r
-\r
-   // optional heavy DEBUG mode\r
-\r
-   if (!UseSlowDebug) return TRUE;\r
-\r
-   if (!board_is_ok(game->start_board)) return FALSE;\r
-\r
-   board_copy(board,game->start_board);\r
-\r
-   for (pos = 0; pos <= game->size; pos++) {\r
-\r
-      if (pos == game->pos) {\r
-         if (!board_equal(game->board,board)) return FALSE;\r
-      }\r
-\r
-      if (pos >= game->size) break;\r
-\r
-      if (game->key[pos] != board->key) return FALSE;\r
-\r
-      move = game->move[pos];\r
-      //if (!move_is_legal(move,board));  //huh??\r
-         if (!move_is_legal(move,board)) return FALSE;  \r
-\r
-      move_do(board,move);\r
-   }\r
-\r
-   if (game->status != game_comp_status(game)) return FALSE;\r
-\r
-   return TRUE;\r
-}\r
-\r
-// game_clear()\r
-\r
-void game_clear(game_t * game) {\r
-\r
-   ASSERT(game!=NULL);\r
-\r
-   game_init(game,StartFen);\r
-}\r
-\r
-// game_init()\r
-\r
-bool game_init(game_t * game, const char fen[]) {\r
-\r
-   ASSERT(game!=NULL);\r
-   ASSERT(fen!=NULL);\r
-\r
-   if (!board_from_fen(game->start_board,fen)) return FALSE;\r
-\r
-   game->size = 0;\r
-\r
-   board_copy(game->board,game->start_board);\r
-   game->pos = 0;\r
-\r
-   game_update(game);\r
-\r
-   return TRUE;\r
-}\r
-\r
-// game_status()\r
-\r
-int game_status(const game_t * game) {\r
-\r
-   ASSERT(game!=NULL);\r
-\r
-   return game->status;\r
-}\r
-\r
-// game_size()\r
-\r
-int game_size(const game_t * game) {\r
-\r
-   ASSERT(game!=NULL);\r
-\r
-   return game->size;\r
-}\r
-\r
-// game_pos()\r
-\r
-int game_pos(const game_t * game) {\r
-\r
-   ASSERT(game!=NULL);\r
-\r
-   return game->pos;\r
-}\r
-\r
-// game_move()\r
-\r
-int game_move(const game_t * game, int pos) {\r
-\r
-   ASSERT(game!=NULL);\r
-   ASSERT(pos>=0&&pos<game->pos);\r
-\r
-   return game->move[pos];\r
-}\r
-\r
-// game_get_board()\r
-\r
-void game_get_board(const game_t * game, board_t * board) {\r
-    game_get_board_ex(game, board, -1);\r
-}\r
-\r
-// game_get_board_ex()\r
-\r
-void game_get_board_ex(const game_t * game, board_t * board, int pos) {\r
-\r
-   int start;\r
-   int i;\r
-\r
-   ASSERT(game!=NULL);\r
-   ASSERT(board!=NULL);\r
-   ASSERT(pos==-1||(pos>=0&&pos<=game->size)); // HACK\r
-\r
-   if (pos < 0) pos = game->pos;\r
-\r
-   if (pos >= game->pos) { // forward from current position\r
-      start = game->pos;\r
-      board_copy(board,game->board);\r
-   } else { // backward => replay the whole game\r
-      start = 0;\r
-      board_copy(board,game->start_board);\r
-   }\r
-\r
-   for (i = start; i < pos; i++) move_do(board,game->move[i]);\r
-}\r
-\r
-// game_turn()\r
-\r
-int game_turn(const game_t * game) {\r
-\r
-   ASSERT(game!=NULL);\r
-\r
-   return game->board->turn;\r
-}\r
-\r
-// game_move_nb()\r
-\r
-int game_move_nb(const game_t * game) {\r
-\r
-   ASSERT(game!=NULL);\r
-\r
-   return game->board->move_nb;\r
-}\r
-\r
-// game_add_move()\r
-\r
-void game_add_move(game_t * game, int move) {\r
-\r
-   ASSERT(game!=NULL);\r
-   ASSERT(move_is_ok(move));\r
-\r
-   ASSERT(move_is_legal(move,game->board));\r
-\r
-   if (game->pos >= GameSize) my_fatal("game_add_move(): game overflow\n");\r
-\r
-   game->move[game->pos] = move;\r
-   game->key[game->pos] = game->board->key;\r
-\r
-   move_do(game->board,move);\r
-   game->pos++;\r
-\r
-   game->size = game->pos; // truncate game, HACK: before calling game_is_ok() in game_update()\r
-\r
-   game_update(game);\r
-}\r
-\r
-// game_rem_move()\r
-\r
-void game_rem_move(game_t * game) {\r
-\r
-   ASSERT(game!=NULL);\r
-\r
-   game_goto(game,game->pos-1);\r
-\r
-   game->size = game->pos; // truncate game\r
-}\r
-\r
-// game_goto()\r
-\r
-void game_goto(game_t * game, int pos) {\r
-\r
-   int i;\r
-\r
-   ASSERT(game!=NULL);\r
-   ASSERT(pos>=0&&pos<=game->size);\r
-\r
-   if (pos < game->pos) { // going backward => replay the whole game\r
-      board_copy(game->board,game->start_board);\r
-      game->pos = 0;\r
-   }\r
-\r
-   for (i = game->pos; i < pos; i++) move_do(game->board,game->move[i]);\r
-   ASSERT(i==pos);\r
-\r
-   game->pos = pos;\r
-\r
-   game_update(game);\r
-}\r
-\r
-// game_disp()\r
-\r
-void game_disp(const game_t * game) {\r
-\r
-   board_t board[1];\r
-   int i, move;\r
-\r
-   ASSERT(game_is_ok(game));\r
-\r
-   board_copy(board,game->start_board);\r
-\r
-   board_disp(board);\r
-\r
-   for (i = 0; i < game->pos; i++) {\r
-\r
-      move = game->move[i];\r
-      move_disp(move,board);\r
-\r
-      move_do(board,move);\r
-   }\r
-\r
-   my_log("POLYGLOT\n");\r
-\r
-   board_disp(board);\r
-}\r
-\r
-// game_update()\r
-\r
-static void game_update(game_t * game) {\r
-\r
-   ASSERT(game!=NULL);\r
-\r
-   game->status = game_comp_status(game);\r
-\r
-   ASSERT(game_is_ok(game));\r
-}\r
-\r
-// game_comp_status()\r
-\r
-static int game_comp_status(const game_t * game) {\r
-\r
-   int i, n;\r
-   int wb, bb;\r
-   const board_t * board;\r
-   uint64 key;\r
-   int start;\r
-\r
-   ASSERT(game!=NULL);\r
-\r
-   // init\r
-\r
-   board = game->board;\r
-\r
-   // mate and stalemate\r
-\r
-   if (!board_can_play(board)) {\r
-      if (FALSE) {\r
-      } else if (is_in_check(board,Black)) { // HACK\r
-         return WHITE_MATES;\r
-      } else if (is_in_check(board,White)) { // HACK\r
-         return BLACK_MATES;\r
-      } else {\r
-         return STALEMATE;\r
-      }\r
-   }\r
-\r
-   // insufficient material\r
-\r
-   if (board->number[WhitePawn12]  == 0\r
-    && board->number[BlackPawn12]  == 0\r
-    && board->number[WhiteQueen12] == 0\r
-    && board->number[BlackQueen12] == 0\r
-    && board->number[WhiteRook12]  == 0\r
-    && board->number[BlackRook12]  == 0) {\r
-\r
-      if (board->number[WhiteBishop12]\r
-        + board->number[BlackBishop12]\r
-        + board->number[WhiteKnight12]\r
-        + board->number[BlackKnight12] <= 1) { // KK, KBK and KNK\r
-\r
-         return DRAW_MATERIAL;\r
-\r
-      } else if (board->number[WhiteBishop12] == 1\r
-              && board->number[BlackBishop12] == 1\r
-              && board->number[WhiteKnight12] == 0\r
-              && board->number[BlackKnight12] == 0) {\r
-\r
-         wb = board->list[White][1]; // HACK\r
-         bb = board->list[Black][1]; // HACK\r
-\r
-         if (square_colour(wb) == square_colour(bb)) { // KBKB\r
-            return DRAW_MATERIAL;\r
-         }\r
-      }\r
-   }\r
-\r
-   // 50-move rule\r
-\r
-   if (board->ply_nb >= 100) return DRAW_FIFTY;\r
-\r
-   // position repetition\r
-\r
-   key = board->key;\r
-   n = 0;\r
-\r
-   start = game->pos - board->ply_nb;\r
-   if (start < 0) start = 0;\r
-\r
-   for (i = game->pos-4; i >= start; i -= 2) {\r
-      if (game->key[i] == key) {\r
-         if (++n == 2) return DRAW_REPETITION;\r
-      }\r
-   }\r
-\r
-   return PLAYING;\r
-}\r
-\r
-// end of game.cpp\r
-\r
+
+// game.c
+
+// includes
+
+#include "attack.h"
+#include "board.h"
+#include "fen.h"
+#include "game.h"
+#include "list.h"
+#include "move.h"
+#include "move_do.h"
+#include "move_legal.h"
+#include "piece.h"
+#include "square.h"
+#include "util.h"
+
+// constants
+
+static const bool UseSlowDebug = FALSE;
+
+// variables
+
+game_t Game[1];
+
+// prototypes
+
+static void game_update      (game_t * game);
+static int  game_comp_status (const game_t * game);
+
+// functions
+
+// game_is_ok()
+
+bool game_is_ok(const game_t * game) {
+
+   board_t board[1];
+   int pos, move;
+
+   if (game == NULL) return FALSE;
+
+   if (game->size < 0 || game->size > GameSize) return FALSE;
+   if (game->pos < 0 || game->pos > game->size) return FALSE;
+
+   // optional heavy DEBUG mode
+
+   if (!UseSlowDebug) return TRUE;
+
+   if (!board_is_ok(game->start_board)) return FALSE;
+
+   board_copy(board,game->start_board);
+
+   for (pos = 0; pos <= game->size; pos++) {
+
+      if (pos == game->pos) {
+         if (!board_equal(game->board,board)) return FALSE;
+      }
+
+      if (pos >= game->size) break;
+
+      if (game->key[pos] != board->key) return FALSE;
+
+      move = game->move[pos];
+      //if (!move_is_legal(move,board));  //huh??
+         if (!move_is_legal(move,board)) return FALSE;  
+
+      move_do(board,move);
+   }
+
+   if (game->status != game_comp_status(game)) return FALSE;
+
+   return TRUE;
+}
+
+// game_clear()
+
+void game_clear(game_t * game) {
+
+   ASSERT(game!=NULL);
+
+   game_init(game,StartFen);
+}
+
+// game_init()
+
+bool game_init(game_t * game, const char fen[]) {
+
+   ASSERT(game!=NULL);
+   ASSERT(fen!=NULL);
+
+   if (!board_from_fen(game->start_board,fen)) return FALSE;
+
+   game->size = 0;
+
+   board_copy(game->board,game->start_board);
+   game->pos = 0;
+
+   game_update(game);
+
+   return TRUE;
+}
+
+// game_status()
+
+int game_status(const game_t * game) {
+
+   ASSERT(game!=NULL);
+
+   return game->status;
+}
+
+// game_size()
+
+int game_size(const game_t * game) {
+
+   ASSERT(game!=NULL);
+
+   return game->size;
+}
+
+// game_pos()
+
+int game_pos(const game_t * game) {
+
+   ASSERT(game!=NULL);
+
+   return game->pos;
+}
+
+// game_move()
+
+int game_move(const game_t * game, int pos) {
+
+   ASSERT(game!=NULL);
+   ASSERT(pos>=0&&pos<game->pos);
+
+   return game->move[pos];
+}
+
+// game_get_board()
+
+void game_get_board(const game_t * game, board_t * board) {
+    game_get_board_ex(game, board, -1);
+}
+
+// game_get_board_ex()
+
+void game_get_board_ex(const game_t * game, board_t * board, int pos) {
+
+   int start;
+   int i;
+
+   ASSERT(game!=NULL);
+   ASSERT(board!=NULL);
+   ASSERT(pos==-1||(pos>=0&&pos<=game->size)); // HACK
+
+   if (pos < 0) pos = game->pos;
+
+   if (pos >= game->pos) { // forward from current position
+      start = game->pos;
+      board_copy(board,game->board);
+   } else { // backward => replay the whole game
+      start = 0;
+      board_copy(board,game->start_board);
+   }
+
+   for (i = start; i < pos; i++) move_do(board,game->move[i]);
+}
+
+// game_turn()
+
+int game_turn(const game_t * game) {
+
+   ASSERT(game!=NULL);
+
+   return game->board->turn;
+}
+
+// game_move_nb()
+
+int game_move_nb(const game_t * game) {
+
+   ASSERT(game!=NULL);
+
+   return game->board->move_nb;
+}
+
+// game_add_move()
+
+void game_add_move(game_t * game, int move) {
+
+   ASSERT(game!=NULL);
+   ASSERT(move_is_ok(move));
+
+   ASSERT(move_is_legal(move,game->board));
+
+   if (game->pos >= GameSize) my_fatal("game_add_move(): game overflow\n");
+
+   game->move[game->pos] = move;
+   game->key[game->pos] = game->board->key;
+
+   move_do(game->board,move);
+   game->pos++;
+
+   game->size = game->pos; // truncate game, HACK: before calling game_is_ok() in game_update()
+
+   game_update(game);
+}
+
+// game_rem_move()
+
+void game_rem_move(game_t * game) {
+
+   ASSERT(game!=NULL);
+
+   game_goto(game,game->pos-1);
+
+   game->size = game->pos; // truncate game
+}
+
+// game_goto()
+
+void game_goto(game_t * game, int pos) {
+
+   int i;
+
+   ASSERT(game!=NULL);
+   ASSERT(pos>=0&&pos<=game->size);
+
+   if (pos < game->pos) { // going backward => replay the whole game
+      board_copy(game->board,game->start_board);
+      game->pos = 0;
+   }
+
+   for (i = game->pos; i < pos; i++) move_do(game->board,game->move[i]);
+   ASSERT(i==pos);
+
+   game->pos = pos;
+
+   game_update(game);
+}
+
+// game_disp()
+
+void game_disp(const game_t * game) {
+
+   board_t board[1];
+   int i, move;
+
+   ASSERT(game_is_ok(game));
+
+   board_copy(board,game->start_board);
+
+   board_disp(board);
+
+   for (i = 0; i < game->pos; i++) {
+
+      move = game->move[i];
+      move_disp(move,board);
+
+      move_do(board,move);
+   }
+
+   my_log("POLYGLOT\n");
+
+   board_disp(board);
+}
+
+// game_update()
+
+static void game_update(game_t * game) {
+
+   ASSERT(game!=NULL);
+
+   game->status = game_comp_status(game);
+
+   ASSERT(game_is_ok(game));
+}
+
+// game_comp_status()
+
+static int game_comp_status(const game_t * game) {
+
+   int i, n;
+   int wb, bb;
+   const board_t * board;
+   uint64 key;
+   int start;
+
+   ASSERT(game!=NULL);
+
+   // init
+
+   board = game->board;
+
+   // mate and stalemate
+
+   if (!board_can_play(board)) {
+      if (FALSE) {
+      } else if (is_in_check(board,Black)) { // HACK
+         return WHITE_MATES;
+      } else if (is_in_check(board,White)) { // HACK
+         return BLACK_MATES;
+      } else {
+         return STALEMATE;
+      }
+   }
+
+   // insufficient material
+
+   if (board->number[WhitePawn12]  == 0
+    && board->number[BlackPawn12]  == 0
+    && board->number[WhiteQueen12] == 0
+    && board->number[BlackQueen12] == 0
+    && board->number[WhiteRook12]  == 0
+    && board->number[BlackRook12]  == 0) {
+
+      if (board->number[WhiteBishop12]
+        + board->number[BlackBishop12]
+        + board->number[WhiteKnight12]
+        + board->number[BlackKnight12] <= 1) { // KK, KBK and KNK
+
+         return DRAW_MATERIAL;
+
+      } else if (board->number[WhiteBishop12] == 1
+              && board->number[BlackBishop12] == 1
+              && board->number[WhiteKnight12] == 0
+              && board->number[BlackKnight12] == 0) {
+
+         wb = board->list[White][1]; // HACK
+         bb = board->list[Black][1]; // HACK
+
+         if (square_colour(wb) == square_colour(bb)) { // KBKB
+            return DRAW_MATERIAL;
+         }
+      }
+   }
+
+   // 50-move rule
+
+   if (board->ply_nb >= 100) return DRAW_FIFTY;
+
+   // position repetition
+
+   key = board->key;
+   n = 0;
+
+   start = game->pos - board->ply_nb;
+   if (start < 0) start = 0;
+
+   for (i = game->pos-4; i >= start; i -= 2) {
+      if (game->key[i] == key) {
+         if (++n == 2) return DRAW_REPETITION;
+      }
+   }
+
+   return PLAYING;
+}
+
+// end of game.cpp
+