15 #include "move_legal.h"
23 static const uint8 PromotePiece[5] = { PieceNone64, Knight64, Bishop64, Rook64, Queen64 };
29 bool move_is_ok(int move) {
31 if (move < 0 || move >= 65536) return FALSE;
33 if (move == MoveNone) return FALSE;
40 int move_make(int from, int to) {
42 ASSERT(square_is_ok(from));
43 ASSERT(square_is_ok(to));
45 return (square_to_64(from) << 6) | square_to_64(to);
50 int move_make_flags(int from, int to, int flags) {
52 ASSERT(square_is_ok(from));
53 ASSERT(square_is_ok(to));
54 ASSERT((flags&~0xF000)==0);
58 return (square_to_64(from) << 6) | square_to_64(to) | flags;
63 int move_from(int move) {
67 ASSERT(move_is_ok(move));
69 from_64 = (move >> 6) & 077;
71 return square_from_64(from_64);
76 int move_to(int move) {
80 ASSERT(move_is_ok(move));
84 return square_from_64(to_64);
87 // move_promote_hack()
89 int move_promote_hack(int move) {
93 ASSERT(move_is_ok(move));
95 ASSERT(move_is_promote(move));
98 ASSERT(code>=1&&code<=4);
100 return PromotePiece[code];
105 bool move_is_capture(int move, const board_t * board) {
107 ASSERT(move_is_ok(move));
108 ASSERT(board_is_ok(board));
110 if (move_is_en_passant(move,board)) return TRUE;
111 if (board->square[move_to(move)] != Empty) return TRUE;
118 bool move_is_promote(int move) {
120 ASSERT(move_is_ok(move));
122 return (move & MoveFlags) != 0;
125 // move_is_en_passant()
127 bool move_is_en_passant(int move, const board_t * board) {
129 ASSERT(move_is_ok(move));
130 ASSERT(board_is_ok(board));
132 return piece_is_pawn(move_piece(move,board))
133 && move_to(move) == board->ep_square;
138 bool move_is_castle(int move, const board_t * board) {
140 ASSERT(move_is_ok(move));
141 ASSERT(board_is_ok(board));
143 return colour_equal(board->square[move_to(move)],board->turn);
148 int move_piece(int move, const board_t * board) {
150 ASSERT(move_is_ok(move));
151 ASSERT(board_is_ok(board));
153 return board->square[move_from(move)];
158 int move_capture(int move, const board_t * board) {
160 ASSERT(move_is_ok(move));
161 ASSERT(board_is_ok(board));
163 if (move_is_en_passant(move,board)) {
164 return piece_pawn_opp(move_piece(move,board));
167 return board->square[move_to(move)];
172 int move_promote(int move, const board_t * board) {
176 ASSERT(move_is_ok(move));
177 ASSERT(board_is_ok(board));
179 if (move_is_promote(move)) {
181 ASSERT(code>=1&&code<=4);
182 return PromotePiece[code] | board->turn;
190 bool move_is_check(int move, const board_t * board) {
192 board_t new_board[1];
194 ASSERT(move_is_ok(move));
195 ASSERT(board_is_ok(board));
197 board_copy(new_board,board);
198 move_do(new_board,move);
199 ASSERT(!is_in_check(new_board,colour_opp(new_board->turn)));
201 return board_is_check(new_board);
206 bool move_is_mate(int move, const board_t * board) {
208 board_t new_board[1];
210 ASSERT(move_is_ok(move));
211 ASSERT(board_is_ok(board));
213 board_copy(new_board,board);
214 move_do(new_board,move);
215 ASSERT(!is_in_check(new_board,colour_opp(new_board->turn)));
217 return board_is_mate(new_board);
222 bool move_to_can(int move, const board_t * board, char string[], int size) {
226 ASSERT(move_is_ok(move));
227 ASSERT(board_is_ok(board));
228 ASSERT(string!=NULL);
231 ASSERT(move_is_legal(move,board));
233 if (size < 6) return FALSE;
237 from = move_from(move);
240 // king-slide castling
242 if (move_is_castle(move,board) && !option_get_bool(Option,"Chess960")) {
244 } else if (from == E1 && to == H1) {
246 } else if (from == E1 && to == A1) {
248 } else if (from == E8 && to == H8) {
250 } else if (from == E8 && to == A8) {
257 if (!square_to_string(from,&string[0],3)) ASSERT(FALSE);
258 if (!square_to_string(to,&string[2],3)) ASSERT(FALSE);
259 ASSERT(strlen(string)==4);
263 if (move_is_promote(move)) {
264 string[4] = piece_to_char(move_promote_hack(move)|Black); // HACK: black => lower-case
270 ASSERT(move_from_can(string,board)==move);
277 int move_from_can(const char string[], const board_t * board) {
279 char tmp_string[256];
284 ASSERT(string!=NULL);
285 ASSERT(board_is_ok(board));
289 tmp_string[0] = string[0];
290 tmp_string[1] = string[1];
291 tmp_string[2] = '\0';
293 from = square_from_string(tmp_string);
294 if (from == SquareNone) return MoveNone;
298 tmp_string[0] = string[2];
299 tmp_string[1] = string[3];
300 tmp_string[2] = '\0';
302 to = square_from_string(tmp_string);
303 if (to == SquareNone) return MoveNone;
305 // convert "king slide" castling to KxR
307 if (piece_is_king(board->square[from])
308 && square_rank(to) == square_rank(from)
309 && abs(to-from) > 1) {
310 side = (to > from) ? SideH : SideA;
311 to = board->castle[board->turn][side];
312 if (to == SquareNone) return MoveNone;
316 move = move_make(from,to);
320 case '\0': // not a promotion
321 if (piece_is_pawn(board->square[from])
322 && square_side_rank(to,board->turn) == Rank8
323 && option_get_bool(Option,"PromoteWorkAround")) {
324 move |= MovePromoteQueen;
329 move |= MovePromoteKnight;
333 move |= MovePromoteBishop;
337 move |= MovePromoteRook;
341 move |= MovePromoteQueen;
349 ASSERT(move_is_legal(move,board));
355 int move_order(int move) {
357 ASSERT(move_is_ok(move));
359 return ((move & 07777) << 3) | (move >> 12); // from, to, promote
364 void move_disp(int move, const board_t * board) {
368 ASSERT(move_is_ok(move));
369 ASSERT(board_is_ok(board));
371 if (!move_to_can(move,board,string,256)) ASSERT(FALSE);
372 my_log("POLYGLOT %s\n",string);