version 1.4.30b
[polyglot.git] / move.c
diff --git a/move.c b/move.c
new file mode 100644 (file)
index 0000000..8d5699f
--- /dev/null
+++ b/move.c
@@ -0,0 +1,376 @@
+\r
+// move.c\r
+\r
+// includes\r
+\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+#include "attack.h"\r
+#include "colour.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 "option.h"\r
+#include "piece.h"\r
+#include "square.h"\r
+#include "util.h"\r
+\r
+// "constants"\r
+\r
+static const uint8 PromotePiece[5] = { PieceNone64, Knight64, Bishop64, Rook64, Queen64 };\r
+\r
+// functions\r
+\r
+// move_is_ok()\r
+\r
+bool move_is_ok(int move) {\r
+\r
+   if (move < 0 || move >= 65536) return FALSE;\r
+\r
+   if (move == MoveNone) return FALSE;\r
+\r
+   return TRUE;\r
+}\r
+\r
+// move_make()\r
+\r
+int move_make(int from, int to) {\r
+\r
+   ASSERT(square_is_ok(from));\r
+   ASSERT(square_is_ok(to));\r
+\r
+   return (square_to_64(from) << 6) | square_to_64(to);\r
+}\r
+\r
+// move_make_flags()\r
+\r
+int move_make_flags(int from, int to, int flags) {\r
+\r
+   ASSERT(square_is_ok(from));\r
+   ASSERT(square_is_ok(to));\r
+   ASSERT((flags&~0xF000)==0);\r
+\r
+   ASSERT(to!=from);\r
+\r
+   return (square_to_64(from) << 6) | square_to_64(to) | flags;\r
+}\r
+\r
+// move_from()\r
+\r
+int move_from(int move) {\r
+\r
+   int from_64;\r
+\r
+   ASSERT(move_is_ok(move));\r
+\r
+   from_64 = (move >> 6) & 077;\r
+\r
+   return square_from_64(from_64);\r
+}\r
+\r
+// move_to()\r
+\r
+int move_to(int move) {\r
+\r
+   int to_64;\r
+\r
+   ASSERT(move_is_ok(move));\r
+\r
+   to_64 = move & 077;\r
+\r
+   return square_from_64(to_64);\r
+}\r
+\r
+// move_promote_hack()\r
+\r
+int move_promote_hack(int move) {\r
+\r
+   int code;\r
+\r
+   ASSERT(move_is_ok(move));\r
+\r
+   ASSERT(move_is_promote(move));\r
+\r
+   code = move >> 12;\r
+   ASSERT(code>=1&&code<=4);\r
+\r
+   return PromotePiece[code];\r
+}\r
+\r
+// move_is_capture()\r
+\r
+bool move_is_capture(int move, const board_t * board) {\r
+\r
+   ASSERT(move_is_ok(move));\r
+   ASSERT(board_is_ok(board));\r
+\r
+   if (move_is_en_passant(move,board)) return TRUE;\r
+   if (board->square[move_to(move)] != Empty) return TRUE;\r
+\r
+   return FALSE;\r
+}\r
+\r
+// move_is_promote()\r
+\r
+bool move_is_promote(int move) {\r
+\r
+   ASSERT(move_is_ok(move));\r
+\r
+   return (move & MoveFlags) != 0;\r
+}\r
+\r
+// move_is_en_passant()\r
+\r
+bool move_is_en_passant(int move, const board_t * board) {\r
+\r
+   ASSERT(move_is_ok(move));\r
+   ASSERT(board_is_ok(board));\r
+\r
+   return piece_is_pawn(move_piece(move,board))\r
+       && move_to(move) == board->ep_square;\r
+}\r
+\r
+// move_is_castle()\r
+\r
+bool move_is_castle(int move, const board_t * board) {\r
+\r
+   ASSERT(move_is_ok(move));\r
+   ASSERT(board_is_ok(board));\r
+\r
+   return colour_equal(board->square[move_to(move)],board->turn);\r
+}\r
+\r
+// move_piece()\r
+\r
+int move_piece(int move, const board_t * board) {\r
+\r
+   ASSERT(move_is_ok(move));\r
+   ASSERT(board_is_ok(board));\r
+\r
+   return board->square[move_from(move)];\r
+}\r
+\r
+// move_capture()\r
+\r
+int move_capture(int move, const board_t * board) {\r
+\r
+   ASSERT(move_is_ok(move));\r
+   ASSERT(board_is_ok(board));\r
+\r
+   if (move_is_en_passant(move,board)) {\r
+      return piece_pawn_opp(move_piece(move,board));\r
+   }\r
+\r
+   return board->square[move_to(move)];\r
+}\r
+\r
+// move_promote()\r
+\r
+int move_promote(int move, const board_t * board) {\r
+\r
+   int code;\r
+\r
+   ASSERT(move_is_ok(move));\r
+   ASSERT(board_is_ok(board));\r
+\r
+   if (move_is_promote(move)) {\r
+      code = move >> 12;\r
+      ASSERT(code>=1&&code<=4);\r
+      return PromotePiece[code] | board->turn;\r
+   }\r
+\r
+   return Empty;\r
+}\r
+\r
+// move_is_check()\r
+\r
+bool move_is_check(int move, const board_t * board) {\r
+\r
+   board_t new_board[1];\r
+\r
+   ASSERT(move_is_ok(move));\r
+   ASSERT(board_is_ok(board));\r
+\r
+   board_copy(new_board,board);\r
+   move_do(new_board,move);\r
+   ASSERT(!is_in_check(new_board,colour_opp(new_board->turn)));\r
+\r
+   return board_is_check(new_board);\r
+}\r
+\r
+// move_is_mate()\r
+\r
+bool move_is_mate(int move, const board_t * board) {\r
+\r
+   board_t new_board[1];\r
+\r
+   ASSERT(move_is_ok(move));\r
+   ASSERT(board_is_ok(board));\r
+\r
+   board_copy(new_board,board);\r
+   move_do(new_board,move);\r
+   ASSERT(!is_in_check(new_board,colour_opp(new_board->turn)));\r
+\r
+   return board_is_mate(new_board);\r
+}\r
+\r
+// move_to_can()\r
+\r
+bool move_to_can(int move, const board_t * board, char string[], int size) {\r
+\r
+   int from, to;\r
+\r
+   ASSERT(move_is_ok(move));\r
+   ASSERT(board_is_ok(board));\r
+   ASSERT(string!=NULL);\r
+   ASSERT(size>=6);\r
+\r
+   ASSERT(move_is_legal(move,board));\r
+\r
+   if (size < 6) return FALSE;\r
+\r
+   // init\r
+\r
+   from = move_from(move);\r
+   to = move_to(move);\r
+\r
+   // king-slide castling\r
+\r
+   if (move_is_castle(move,board) && !option_get_bool("Chess960")) {\r
+      if (FALSE) {\r
+      } else if (from == E1 && to == H1) {\r
+         to = G1;\r
+      } else if (from == E1 && to == A1) {\r
+         to = C1;\r
+      } else if (from == E8 && to == H8) {\r
+         to = G8;\r
+      } else if (from == E8 && to == A8) {\r
+         to = C8;\r
+      }\r
+   }\r
+\r
+   // normal moves\r
+\r
+   if (!square_to_string(from,&string[0],3)) ASSERT(FALSE);\r
+   if (!square_to_string(to,&string[2],3)) ASSERT(FALSE);\r
+   ASSERT(strlen(string)==4);\r
+\r
+   // promotes\r
+\r
+   if (move_is_promote(move)) {\r
+      string[4] = piece_to_char(move_promote_hack(move)|Black); // HACK: black => lower-case\r
+      string[5] = '\0';\r
+   }\r
+\r
+   // debug\r
+\r
+   ASSERT(move_from_can(string,board)==move);\r
+\r
+   return TRUE;\r
+}\r
+\r
+// move_from_can()\r
+\r
+int move_from_can(const char string[], const board_t * board) {\r
+\r
+   char tmp_string[256];\r
+   int from, to;\r
+   int side;\r
+   int move;\r
+\r
+   ASSERT(string!=NULL);\r
+   ASSERT(board_is_ok(board));\r
+\r
+   // from\r
+\r
+   tmp_string[0] = string[0];\r
+   tmp_string[1] = string[1];\r
+   tmp_string[2] = '\0';\r
+\r
+   from = square_from_string(tmp_string);\r
+   if (from == SquareNone) return MoveNone;\r
+\r
+   // to\r
+\r
+   tmp_string[0] = string[2];\r
+   tmp_string[1] = string[3];\r
+   tmp_string[2] = '\0';\r
+\r
+   to = square_from_string(tmp_string);\r
+   if (to == SquareNone) return MoveNone;\r
+\r
+   // convert "king slide" castling to KxR\r
+\r
+   if (piece_is_king(board->square[from])\r
+    && square_rank(to) == square_rank(from)\r
+    && abs(to-from) > 1) {\r
+      side = (to > from) ? SideH : SideA;\r
+      to = board->castle[board->turn][side];\r
+      if (to == SquareNone) return MoveNone;\r
+   }\r
+   // move\r
+\r
+   move = move_make(from,to);\r
+\r
+   // promote\r
+   switch (string[4]) {\r
+   case '\0': // not a promotion\r
+      if (piece_is_pawn(board->square[from])\r
+       && square_side_rank(to,board->turn) == Rank8\r
+       && option_get_bool("PromoteWorkAround")) {\r
+         move |= MovePromoteQueen;\r
+      }\r
+      break;\r
+   case 'N':\r
+   case 'n':\r
+      move |= MovePromoteKnight;\r
+      break;\r
+   case 'B':\r
+   case 'b':\r
+      move |= MovePromoteBishop;\r
+      break;\r
+   case 'R':\r
+   case 'r':\r
+      move |= MovePromoteRook;\r
+      break;\r
+   case 'Q':\r
+   case 'q':\r
+      move |= MovePromoteQueen;\r
+      break;\r
+   default:\r
+      return MoveNone;\r
+      break;\r
+   }\r
+   // debug\r
+\r
+   ASSERT(move_is_legal(move,board));\r
+   return move;\r
+}\r
+\r
+// move_order()\r
+\r
+int move_order(int move) {\r
+\r
+   ASSERT(move_is_ok(move));\r
+\r
+   return ((move & 07777) << 3) | (move >> 12); // from, to, promote\r
+}\r
+\r
+// move_disp()\r
+\r
+void move_disp(int move, const board_t * board) {\r
+\r
+   char string[256];\r
+\r
+   ASSERT(move_is_ok(move));\r
+   ASSERT(board_is_ok(board));\r
+\r
+   if (!move_to_can(move,board,string,256)) ASSERT(FALSE);\r
+   my_log("POLYGLOT %s\n",string);\r
+}\r
+\r
+// end of move.cpp\r
+\r