version 1.4.30b
[polyglot.git] / move_do.c
diff --git a/move_do.c b/move_do.c
new file mode 100644 (file)
index 0000000..8c00687
--- /dev/null
+++ b/move_do.c
@@ -0,0 +1,363 @@
+\r
+// move_do.c\r
+\r
+// includes\r
+\r
+#include <stdlib.h>\r
+\r
+#include "board.h"\r
+#include "colour.h"\r
+#include "hash.h"\r
+#include "move.h"\r
+#include "move_do.h"\r
+#include "move_legal.h"\r
+#include "piece.h"\r
+#include "random.h"\r
+#include "util.h"\r
+\r
+// prototypes\r
+\r
+static void square_clear (board_t * board, int square, int piece);\r
+static void square_set   (board_t * board, int square, int piece, int pos);\r
+static void square_move  (board_t * board, int from, int to, int piece);\r
+\r
+// functions\r
+\r
+// move_do()\r
+\r
+void move_do(board_t * board, int move) {\r
+\r
+   int me, opp;\r
+   int from, to;\r
+   int piece, pos, capture;\r
+   int old_flags, new_flags;\r
+   int sq, ep_square;\r
+   int pawn;\r
+\r
+   ASSERT(board_is_ok(board));\r
+   ASSERT(move_is_ok(move));\r
+\r
+   ASSERT(move_is_pseudo(move,board));\r
+\r
+   // init\r
+\r
+   me = board->turn;\r
+   opp = colour_opp(me);\r
+\r
+   from = move_from(move);\r
+   to = move_to(move);\r
+\r
+   piece = board->square[from];\r
+   ASSERT(colour_equal(piece,me));\r
+\r
+   pos = board->pos[from];\r
+   ASSERT(pos>=0);\r
+\r
+   // update turn\r
+\r
+   board->turn = opp;\r
+   board->key ^= random_64(RandomTurn);\r
+\r
+   // update castling rights\r
+\r
+   old_flags = board_flags(board);\r
+\r
+   if (piece_is_king(piece)) {\r
+      board->castle[me][SideH] = SquareNone;\r
+      board->castle[me][SideA] = SquareNone;\r
+   }\r
+\r
+   if (board->castle[me][SideH] == from) board->castle[me][SideH] = SquareNone;\r
+   if (board->castle[me][SideA] == from) board->castle[me][SideA] = SquareNone;\r
+\r
+   if (board->castle[opp][SideH] == to) board->castle[opp][SideH] = SquareNone;\r
+   if (board->castle[opp][SideA] == to) board->castle[opp][SideA] = SquareNone;\r
+\r
+   new_flags = board_flags(board);\r
+\r
+   board->key ^= hash_castle_key(new_flags^old_flags); // HACK\r
+\r
+   // update en-passant square\r
+\r
+   ep_square = sq = board->ep_square;\r
+   if (sq != SquareNone) {\r
+      board->key ^= random_64(RandomEnPassant+square_file(sq));\r
+      board->ep_square = SquareNone;\r
+   }\r
+\r
+   if (piece_is_pawn(piece) && abs(to-from) == 32) {\r
+      pawn = piece_make_pawn(opp);\r
+      if (board->square[to-1] == pawn || board->square[to+1] == pawn) {\r
+         board->ep_square = sq = (from + to) / 2;\r
+         board->key ^= random_64(RandomEnPassant+square_file(sq));\r
+      }\r
+   }\r
+\r
+   // update ply number (captures are handled later)\r
+\r
+   board->ply_nb++;\r
+   if (piece_is_pawn(piece)) board->ply_nb = 0; // conversion\r
+\r
+   // update move number\r
+\r
+   if (me == Black) board->move_nb++;\r
+\r
+   // castle\r
+\r
+   if (colour_equal(board->square[to],me)) {\r
+\r
+      int rank;\r
+      int king_from, king_to;\r
+      int rook_from, rook_to;\r
+      int rook;\r
+\r
+      rank = colour_is_white(me) ? Rank1 : Rank8;\r
+\r
+      king_from = from;\r
+      rook_from = to;\r
+\r
+      if (to > from) { // h side\r
+         king_to = square_make(FileG,rank);\r
+         rook_to = square_make(FileF,rank);\r
+      } else { // a side\r
+         king_to = square_make(FileC,rank);\r
+         rook_to = square_make(FileD,rank);\r
+      }\r
+\r
+      // remove the rook\r
+\r
+      pos = board->pos[rook_from];\r
+      ASSERT(pos>=0);\r
+\r
+      rook = Rook64 | me; // HACK\r
+\r
+      square_clear(board,rook_from,rook);\r
+\r
+      // move the king\r
+\r
+      square_move(board,king_from,king_to,piece);\r
+\r
+      // put the rook back\r
+\r
+      square_set(board,rook_to,rook,pos);\r
+\r
+      ASSERT(board->key==hash_key(board));\r
+\r
+      return;\r
+   }\r
+\r
+   // remove the captured piece\r
+\r
+   if (piece_is_pawn(piece) && to == ep_square) {\r
+\r
+      // en-passant capture\r
+\r
+      sq = square_ep_dual(to);\r
+      capture = board->square[sq];\r
+      ASSERT(capture==piece_make_pawn(opp));\r
+\r
+      square_clear(board,sq,capture);\r
+\r
+      board->ply_nb = 0; // conversion\r
+\r
+   } else {\r
+\r
+      capture = board->square[to];\r
+\r
+      if (capture != Empty) {\r
+\r
+         // normal capture\r
+\r
+         ASSERT(colour_equal(capture,opp));\r
+         ASSERT(!piece_is_king(capture));\r
+\r
+         square_clear(board,to,capture);\r
+\r
+         board->ply_nb = 0; // conversion\r
+      }\r
+   }\r
+\r
+   // move the piece\r
+\r
+   if (move_is_promote(move)) {\r
+\r
+      // promote\r
+\r
+      square_clear(board,from,piece);\r
+      piece = move_promote_hack(move) | me; // HACK\r
+      square_set(board,to,piece,pos);\r
+\r
+   } else {\r
+\r
+      // normal move\r
+\r
+      square_move(board,from,to,piece);\r
+   }\r
+\r
+   ASSERT(board->key==hash_key(board));\r
+}\r
+\r
+// square_clear()\r
+\r
+static void square_clear(board_t * board, int square, int piece) {\r
+\r
+   int pos, piece_12, colour;\r
+   int sq, size;\r
+\r
+   ASSERT(board!=NULL);\r
+   ASSERT(square_is_ok(square));\r
+   ASSERT(piece_is_ok(piece));\r
+\r
+   // init\r
+\r
+   pos = board->pos[square];\r
+   ASSERT(pos>=0);\r
+\r
+   colour = piece_colour(piece);\r
+   piece_12 = piece_to_12(piece);\r
+\r
+   // square\r
+\r
+   ASSERT(board->square[square]==piece);\r
+   board->square[square] = Empty;\r
+\r
+   ASSERT(board->pos[square]==pos);\r
+   board->pos[square] = -1; // not needed\r
+\r
+   // piece list\r
+\r
+   ASSERT(board->list_size[colour]>=2);\r
+   size = --board->list_size[colour];\r
+   ASSERT(pos<=size);\r
+\r
+   if (pos != size) {\r
+\r
+      sq = board->list[colour][size];\r
+      ASSERT(square_is_ok(sq));\r
+      ASSERT(sq!=square);\r
+\r
+      ASSERT(board->pos[sq]==size);\r
+      board->pos[sq] = pos;\r
+\r
+      ASSERT(board->list[colour][pos]==square);\r
+      board->list[colour][pos] = sq;\r
+   }\r
+\r
+   board->list[colour][size] = SquareNone;\r
+\r
+   // material\r
+\r
+   ASSERT(board->number[piece_12]>=1);\r
+   board->number[piece_12]--;\r
+\r
+   // hash key\r
+\r
+   board->key ^= random_64(RandomPiece+piece_12*64+square_to_64(square));\r
+}\r
+\r
+// square_set()\r
+\r
+static void square_set(board_t * board, int square, int piece, int pos) {\r
+\r
+   int piece_12, colour;\r
+   int sq, size;\r
+\r
+   ASSERT(board!=NULL);\r
+   ASSERT(square_is_ok(square));\r
+   ASSERT(piece_is_ok(piece));\r
+   ASSERT(pos>=0);\r
+\r
+   // init\r
+\r
+   colour = piece_colour(piece);\r
+   piece_12 = piece_to_12(piece);\r
+\r
+   // square\r
+\r
+   ASSERT(board->square[square]==Empty);\r
+   board->square[square] = piece;\r
+\r
+   ASSERT(board->pos[square]==-1);\r
+   board->pos[square] = pos;\r
+\r
+   // piece list\r
+\r
+   size = board->list_size[colour]++;\r
+   ASSERT(board->list[colour][size]==SquareNone);\r
+   ASSERT(pos<=size);\r
+\r
+   if (pos != size) {\r
+\r
+      sq = board->list[colour][pos];\r
+      ASSERT(square_is_ok(sq));\r
+      ASSERT(sq!=square);\r
+\r
+      ASSERT(board->pos[sq]==pos);\r
+      board->pos[sq] = size;\r
+\r
+      ASSERT(board->list[colour][size]==SquareNone);\r
+      board->list[colour][size] = sq;\r
+   }\r
+\r
+   board->list[colour][pos] = square;\r
+\r
+   // material\r
+\r
+   ASSERT(board->number[piece_12]<=8);\r
+   board->number[piece_12]++;\r
+\r
+   // hash key\r
+\r
+   board->key ^= random_64(RandomPiece+piece_12*64+square_to_64(square));\r
+}\r
+\r
+// square_move()\r
+\r
+static void square_move(board_t * board, int from, int to, int piece) {\r
+\r
+   int colour, pos;\r
+   int piece_index;\r
+\r
+   ASSERT(board!=NULL);\r
+   ASSERT(square_is_ok(from));\r
+   ASSERT(square_is_ok(to));\r
+   ASSERT(piece_is_ok(piece));\r
+\r
+   // init\r
+\r
+   colour = piece_colour(piece);\r
+\r
+   pos = board->pos[from];\r
+   ASSERT(pos>=0);\r
+\r
+   // from\r
+\r
+   ASSERT(board->square[from]==piece);\r
+   board->square[from] = Empty;\r
+\r
+   ASSERT(board->pos[from]==pos);\r
+   board->pos[from] = -1; // not needed\r
+\r
+   // to\r
+\r
+   ASSERT(board->square[to]==Empty);\r
+   board->square[to] = piece;\r
+\r
+   ASSERT(board->pos[to]==-1);\r
+   board->pos[to] = pos;\r
+\r
+   // piece list\r
+\r
+   ASSERT(board->list[colour][pos]==from);\r
+   board->list[colour][pos] = to;\r
+\r
+   // hash key\r
+\r
+   piece_index = RandomPiece + piece_to_12(piece) * 64;\r
+\r
+   board->key ^= random_64(piece_index+square_to_64(from))\r
+               ^ random_64(piece_index+square_to_64(to));\r
+}\r
+\r
+// end of move_do.cpp\r
+\r