--- /dev/null
+\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