1 /* DreamChess
2 **
3 ** DreamChess is the legal property of its developers, whose names are too
4 ** numerous to list here. Please refer to the AUTHORS.txt file distributed
5 ** with this source distribution.
6 **
7 ** This program is free software: you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License as published by
9 ** the Free Software Foundation, either version 3 of the License, or
10 ** (at your option) any later version.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include <ctype.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "board.h"
28 #include "hashing.h"
29 #include "move.h"
30
31 /* square_bit[i] is a bitboard that marks square 'i' on the board. */
32 bitboard_t square_bit[64];
33
34 /* Pieces values are used to calculate the material balance of the board. */
35 static int piece_value[] = {100, 100, 300, 300, 350, 350, 500, 500, 900, 900, 2000, 2000};
36
add_piece(board_t * board,int square,int piece)37 static void add_piece(board_t *board, int square, int piece)
38 /* Adds a piece to a board.
39 ** Parameters: (board_t *) board: Pointer to the board to add the piece to.
40 ** (int) piece: The piece to add.
41 ** (int) square: The square where the piece should be added.
42 */
43 {
44 board->bitboard[piece] |= square_bit[square];
45 board->bitboard[ALL + (piece & 1)] |= square_bit[square];
46 board->material_value[piece & 1] += piece_value[piece];
47
48 if ((piece & PIECE_MASK) == PAWN)
49 board->num_pawns[piece & 1]++;
50
51 board->hash_key ^= pieces_hash[piece][square];
52 }
53
remove_piece(board_t * board,int square,int piece)54 static void remove_piece(board_t *board, int square, int piece)
55 /* Removes a piece from the board.
56 ** Parameters: (board_t *) board: Pointer to the board to remove the piece
57 ** from.
58 ** (int) piece: The piece to remove.
59 ** (int) square: The square where to remove the piece from.
60 */
61 {
62 board->bitboard[piece] ^= square_bit[square];
63 board->bitboard[ALL + (piece & 1)] ^= square_bit[square];
64 board->material_value[piece & 1] -= piece_value[piece];
65
66 if ((piece & PIECE_MASK) == PAWN)
67 board->num_pawns[piece & 1]--;
68
69 board->hash_key ^= pieces_hash[piece][square];
70 }
71
setup_board(board_t * board)72 void setup_board(board_t *board) {
73 int i;
74
75 clear_board(board);
76
77 add_piece(board, SQUARE_A1, WHITE_ROOK);
78 add_piece(board, SQUARE_B1, WHITE_KNIGHT);
79 add_piece(board, SQUARE_C1, WHITE_BISHOP);
80 add_piece(board, SQUARE_D1, WHITE_QUEEN);
81 add_piece(board, SQUARE_E1, WHITE_KING);
82 add_piece(board, SQUARE_F1, WHITE_BISHOP);
83 add_piece(board, SQUARE_G1, WHITE_KNIGHT);
84 add_piece(board, SQUARE_H1, WHITE_ROOK);
85 add_piece(board, SQUARE_A8, BLACK_ROOK);
86 add_piece(board, SQUARE_B8, BLACK_KNIGHT);
87 add_piece(board, SQUARE_C8, BLACK_BISHOP);
88 add_piece(board, SQUARE_D8, BLACK_QUEEN);
89 add_piece(board, SQUARE_E8, BLACK_KING);
90 add_piece(board, SQUARE_F8, BLACK_BISHOP);
91 add_piece(board, SQUARE_G8, BLACK_KNIGHT);
92 add_piece(board, SQUARE_H8, BLACK_ROOK);
93
94 for (i = SQUARE_A2; i <= SQUARE_H2; i++)
95 add_piece(board, i, WHITE_PAWN);
96
97 for (i = SQUARE_A7; i <= SQUARE_H7; i++)
98 add_piece(board, i, BLACK_PAWN);
99
100 board->castle_flags =
101 WHITE_CAN_CASTLE_KINGSIDE | BLACK_CAN_CASTLE_KINGSIDE | WHITE_CAN_CASTLE_QUEENSIDE | BLACK_CAN_CASTLE_QUEENSIDE;
102
103 board->en_passant = 0LL;
104
105 board->current_player = SIDE_WHITE;
106
107 board->hash_key = hash_key(board);
108
109 board->fifty_moves = 0;
110 }
111
setup_board_fen(board_t * board,char * fen)112 int setup_board_fen(board_t *board, char *fen) {
113 int i = 0;
114 int square = 56;
115 int len = strlen(fen);
116 char *endptr;
117 int done = 0;
118
119 clear_board(board);
120
121 while (done < 64) {
122 char c;
123 char piece = 0;
124
125 if (i == len)
126 return 1;
127
128 c = fen[i++];
129
130 if ((c >= '1') && (c <= '8')) {
131 square += c - '0';
132 done += c - '0';
133 continue;
134 }
135
136 switch (toupper(c)) {
137 case 'P':
138 piece = PAWN;
139 break;
140 case 'N':
141 piece = KNIGHT;
142 break;
143 case 'B':
144 piece = BISHOP;
145 break;
146 case 'R':
147 piece = ROOK;
148 break;
149 case 'Q':
150 piece = QUEEN;
151 break;
152 case 'K':
153 piece = KING;
154 break;
155 case '/':
156 square -= 16;
157 continue;
158 }
159
160 if (c >= 'a')
161 piece += SIDE_BLACK;
162 else
163 piece += SIDE_WHITE;
164
165 if (square < 0 || square > 63)
166 return 1;
167
168 add_piece(board, square++, piece);
169 done++;
170 }
171
172 /* Skip space */
173 if (++i >= len)
174 return 1;
175
176 if (fen[i] == 'w')
177 board->current_player = SIDE_WHITE;
178 else if (fen[i] == 'b')
179 board->current_player = SIDE_BLACK;
180 else
181 return 1;
182
183 i += 2;
184
185 if (i >= len)
186 return 1;
187
188 board->castle_flags = 0;
189
190 if (fen[i] != '-')
191 while ((i < len) && (fen[i] != ' '))
192 switch (fen[i++]) {
193 case 'K':
194 board->castle_flags |= WHITE_CAN_CASTLE_KINGSIDE;
195 break;
196 case 'Q':
197 board->castle_flags |= WHITE_CAN_CASTLE_QUEENSIDE;
198 break;
199 case 'k':
200 board->castle_flags |= BLACK_CAN_CASTLE_KINGSIDE;
201 break;
202 case 'q':
203 board->castle_flags |= BLACK_CAN_CASTLE_QUEENSIDE;
204 }
205 else
206 i++;
207
208 /* Skip space */
209 if (++i >= len)
210 return 1;
211
212 board->en_passant = 0LL;
213
214 if (fen[i] != '-') {
215 if ((fen[i] < 'a') || (fen[i] > 'h'))
216 return 1;
217
218 board->en_passant = 1LL << (fen[i++] - 'a');
219
220 if (i >= len)
221 return 1;
222
223 if ((fen[i] < '1') || (fen[i] > '8'))
224 return 1;
225
226 board->en_passant <<= 8 * (fen[i] - '1');
227 }
228
229 i += 2;
230
231 if (i >= len)
232 return 1;
233
234 errno = 0;
235 board->fifty_moves = strtol(fen + i, &endptr, 10);
236 if (errno || (fen + i == endptr))
237 return 1;
238
239 i = endptr - fen + 1;
240
241 if (i >= len)
242 return 1;
243
244 /* FIXME Implement move counter, legality check */
245
246 return 0;
247 }
248
board_init(void)249 void board_init(void) {
250 int i;
251 for (i = 0; i < 64; i++)
252 square_bit[i] = 1LL << i;
253 }
254
clear_board(board_t * board)255 void clear_board(board_t *board) {
256 int i;
257 for (i = 0; i < NR_BITBOARDS; i++)
258 board->bitboard[i] = 0LL;
259
260 board->num_pawns[SIDE_WHITE] = 0;
261 board->num_pawns[SIDE_BLACK] = 0;
262
263 board->material_value[SIDE_WHITE] = 0;
264 board->material_value[SIDE_BLACK] = 0;
265 }
266
find_black_piece(board_t * board,int square)267 int find_black_piece(board_t *board, int square) {
268 bitboard_t mask = square_bit[square];
269
270 /* We need to check kings first because a fake king might be on the
271 ** same square as a rook. In that case we want to find the king so
272 ** that the illegality of the previous move can be detected.
273 */
274 if (board->bitboard[BLACK_KING] & square_bit[square])
275 return BLACK_KING;
276
277 /* Check for other pieces in order of frequency. */
278 if (board->bitboard[BLACK_PAWN] & mask)
279 return BLACK_PAWN;
280 if (board->bitboard[BLACK_KNIGHT] & mask)
281 return BLACK_KNIGHT;
282 if (board->bitboard[BLACK_BISHOP] & mask)
283 return BLACK_BISHOP;
284 if (board->bitboard[BLACK_ROOK] & mask)
285 return BLACK_ROOK;
286 if (board->bitboard[BLACK_QUEEN] & mask)
287 return BLACK_QUEEN;
288
289 return NONE;
290 }
291
find_white_piece(board_t * board,int square)292 int find_white_piece(board_t *board, int square) {
293 bitboard_t mask = square_bit[square];
294
295 /* We need to check kings first because a fake king might be on the
296 ** same square as a rook. In that case we want to find the king so
297 ** that the illegality of the previous move can be detected.
298 */
299 if (board->bitboard[WHITE_KING] & mask)
300 return WHITE_KING;
301
302 /* Check for other pieces in order of frequency. */
303 if (board->bitboard[WHITE_PAWN] & mask)
304 return WHITE_PAWN;
305 if (board->bitboard[WHITE_KNIGHT] & mask)
306 return WHITE_KNIGHT;
307 if (board->bitboard[WHITE_BISHOP] & mask)
308 return WHITE_BISHOP;
309 if (board->bitboard[WHITE_ROOK] & mask)
310 return WHITE_ROOK;
311 if (board->bitboard[WHITE_QUEEN] & mask)
312 return WHITE_QUEEN;
313
314 return NONE;
315 }
316
execute_move(board_t * board,move_t move)317 void execute_move(board_t *board, move_t move) {
318 if (board->current_player) {
319 /* Black is the side to move. Remove white phantom kings from the
320 ** board.
321 */
322 if (board->castle_flags & WHITE_PHANTOM_KINGS_KINGSIDE) {
323 board->castle_flags ^= WHITE_PHANTOM_KINGS_KINGSIDE;
324 board->bitboard[WHITE_KING] ^= WHITE_PHANTOM_KINGSIDE;
325 board->bitboard[WHITE_ALL] ^= WHITE_PHANTOM_KINGSIDE;
326 board->bitboard[WHITE_ALL] |= board->bitboard[WHITE_ROOK];
327 } else if (board->castle_flags & WHITE_PHANTOM_KINGS_QUEENSIDE) {
328 board->castle_flags ^= WHITE_PHANTOM_KINGS_QUEENSIDE;
329 board->bitboard[WHITE_KING] ^= WHITE_PHANTOM_QUEENSIDE;
330 board->bitboard[WHITE_ALL] ^= WHITE_PHANTOM_QUEENSIDE;
331 board->bitboard[WHITE_ALL] |= board->bitboard[WHITE_ROOK];
332 }
333 } else {
334 /* White is the side to move. Remove black phantom kings from the
335 ** board.
336 */
337 if (board->castle_flags & BLACK_PHANTOM_KINGS_KINGSIDE) {
338 board->castle_flags ^= BLACK_PHANTOM_KINGS_KINGSIDE;
339 board->bitboard[BLACK_KING] ^= BLACK_PHANTOM_KINGSIDE;
340 board->bitboard[BLACK_ALL] ^= BLACK_PHANTOM_KINGSIDE;
341 board->bitboard[BLACK_ALL] |= board->bitboard[BLACK_ROOK];
342 } else if (board->castle_flags & BLACK_PHANTOM_KINGS_QUEENSIDE) {
343 board->castle_flags ^= BLACK_PHANTOM_KINGS_QUEENSIDE;
344 board->bitboard[BLACK_KING] ^= BLACK_PHANTOM_QUEENSIDE;
345 board->bitboard[BLACK_ALL] ^= BLACK_PHANTOM_QUEENSIDE;
346 board->bitboard[BLACK_ALL] |= board->bitboard[BLACK_ROOK];
347 }
348 }
349
350 switch (move & MOVE_NO_PROMOTION_MASK) {
351 case NORMAL_MOVE:
352 remove_piece(board, MOVE_GET(move, SOURCE), MOVE_GET(move, PIECE));
353 add_piece(board, MOVE_GET(move, DEST), MOVE_GET(move, PIECE));
354 if ((MOVE_GET(move, PIECE) & PIECE_MASK) == PAWN)
355 board->fifty_moves = 0;
356 else
357 board->fifty_moves++;
358 break;
359
360 case CAPTURE_MOVE:
361 remove_piece(board, MOVE_GET(move, SOURCE), MOVE_GET(move, PIECE));
362 remove_piece(board, MOVE_GET(move, DEST), MOVE_GET(move, CAPTURED));
363 add_piece(board, MOVE_GET(move, DEST), MOVE_GET(move, PIECE));
364 board->fifty_moves = 0;
365 break;
366
367 case CAPTURE_MOVE_EN_PASSANT:
368 remove_piece(board, MOVE_GET(move, SOURCE), MOVE_GET(move, PIECE));
369
370 /* Remove the captured pawn. */
371 remove_piece(board, MOVE_GET(move, DEST) + (MOVE_GET(move, PIECE) & 1 ? 8 : -8), MOVE_GET(move, CAPTURED));
372 add_piece(board, MOVE_GET(move, DEST), MOVE_GET(move, PIECE));
373 board->fifty_moves = 0;
374 break;
375
376 case CASTLING_MOVE_KINGSIDE: {
377 /* We have to move the rook as well. */
378 int rook = ROOK + board->current_player;
379
380 remove_piece(board, MOVE_GET(move, SOURCE), MOVE_GET(move, PIECE));
381 add_piece(board, MOVE_GET(move, DEST), MOVE_GET(move, PIECE));
382 remove_piece(board, MOVE_GET(move, DEST) + 1, rook);
383 add_piece(board, MOVE_GET(move, DEST) - 1, rook);
384
385 /* Add phantom kings to detect whether or not
386 ** this move is legal.
387 */
388 if (!board->current_player) {
389 /* White castling. */
390 board->castle_flags |= WHITE_PHANTOM_KINGS_KINGSIDE | WHITE_HAS_CASTLED;
391 board->bitboard[WHITE_KING] |= WHITE_PHANTOM_KINGSIDE;
392 board->bitboard[WHITE_ALL] |= WHITE_PHANTOM_KINGSIDE;
393 } else {
394 /* Black castling. */
395 board->castle_flags |= BLACK_PHANTOM_KINGS_KINGSIDE | BLACK_HAS_CASTLED;
396 board->bitboard[BLACK_KING] |= BLACK_PHANTOM_KINGSIDE;
397 board->bitboard[BLACK_ALL] |= BLACK_PHANTOM_KINGSIDE;
398 }
399 board->fifty_moves++;
400 break;
401 }
402 case CASTLING_MOVE_QUEENSIDE: {
403 /* We have to move the rook as well. */
404 int rook = ROOK + board->current_player;
405
406 remove_piece(board, MOVE_GET(move, SOURCE), MOVE_GET(move, PIECE));
407 add_piece(board, MOVE_GET(move, DEST), MOVE_GET(move, PIECE));
408 remove_piece(board, MOVE_GET(move, DEST) - 2, rook);
409 add_piece(board, MOVE_GET(move, DEST) + 1, rook);
410
411 /* Add phantom kings to detect whether or not
412 ** this move is legal.
413 */
414 if (!board->current_player) {
415 /* White castling. */
416 board->castle_flags |= WHITE_PHANTOM_KINGS_QUEENSIDE | WHITE_HAS_CASTLED;
417 board->bitboard[WHITE_KING] |= WHITE_PHANTOM_QUEENSIDE;
418 board->bitboard[WHITE_ALL] |= WHITE_PHANTOM_QUEENSIDE;
419 } else {
420 /* Black castling. */
421 board->castle_flags |= BLACK_PHANTOM_KINGS_QUEENSIDE | BLACK_HAS_CASTLED;
422 board->bitboard[BLACK_KING] |= BLACK_PHANTOM_QUEENSIDE;
423 board->bitboard[BLACK_ALL] |= BLACK_PHANTOM_QUEENSIDE;
424 }
425 board->fifty_moves++;
426 break;
427 }
428 case RESIGN_MOVE:
429 /* Resign or checkmate, do nothing. */
430 return;
431 case STALEMATE_MOVE:
432 /* Stalemate, do nothing. */
433 return;
434 }
435
436 /* Promotion moves. */
437 switch (move & MOVE_PROMOTION_MASK) {
438 case PROMOTION_MOVE_KNIGHT:
439 remove_piece(board, MOVE_GET(move, DEST), MOVE_GET(move, PIECE));
440 add_piece(board, MOVE_GET(move, DEST), KNIGHT + board->current_player);
441 break;
442 case PROMOTION_MOVE_BISHOP:
443 remove_piece(board, MOVE_GET(move, DEST), MOVE_GET(move, PIECE));
444 add_piece(board, MOVE_GET(move, DEST), BISHOP + board->current_player);
445 break;
446 case PROMOTION_MOVE_ROOK:
447 remove_piece(board, MOVE_GET(move, DEST), MOVE_GET(move, PIECE));
448 add_piece(board, MOVE_GET(move, DEST), ROOK + board->current_player);
449 break;
450 case PROMOTION_MOVE_QUEEN:
451 remove_piece(board, MOVE_GET(move, DEST), MOVE_GET(move, PIECE));
452 add_piece(board, MOVE_GET(move, DEST), QUEEN + board->current_player);
453 }
454
455 /* Reset en passant possibility. */
456 if (board->en_passant) {
457 int square;
458 for (square = 0; square < 64; square++) {
459 if (board->en_passant & square_bit[square]) {
460 board->hash_key ^= ep_hash[square];
461 break;
462 }
463 }
464 board->en_passant = 0LL;
465 }
466
467 /* Set en passant possibility in case of a double pawn push. */
468 if ((MOVE_GET(move, PIECE) == WHITE_PAWN) && (MOVE_GET(move, DEST) - MOVE_GET(move, SOURCE) == 16)) {
469 board->en_passant = square_bit[MOVE_GET(move, SOURCE) + 8];
470 board->hash_key ^= ep_hash[MOVE_GET(move, SOURCE) + 8];
471 } else if ((MOVE_GET(move, PIECE) == BLACK_PAWN) && (MOVE_GET(move, SOURCE) - MOVE_GET(move, DEST) == 16)) {
472 board->en_passant = square_bit[MOVE_GET(move, DEST) + 8];
473 board->hash_key ^= ep_hash[MOVE_GET(move, DEST) + 8];
474 }
475
476 /* Set castling possibilities. If the king moves castling is not allowed. */
477 switch (MOVE_GET(move, PIECE)) {
478 case WHITE_KING:
479 if (board->castle_flags & WHITE_CAN_CASTLE_KINGSIDE) {
480 board->hash_key ^= castle_hash[SIDE_WHITE + CASTLE_KINGSIDE];
481 board->castle_flags ^= WHITE_CAN_CASTLE_KINGSIDE;
482 }
483 if (board->castle_flags & WHITE_CAN_CASTLE_QUEENSIDE) {
484 board->hash_key ^= castle_hash[SIDE_WHITE + CASTLE_QUEENSIDE];
485 board->castle_flags ^= WHITE_CAN_CASTLE_QUEENSIDE;
486 }
487 break;
488 case BLACK_KING:
489 if (board->castle_flags & BLACK_CAN_CASTLE_KINGSIDE) {
490 board->hash_key ^= castle_hash[SIDE_BLACK + CASTLE_KINGSIDE];
491 board->castle_flags ^= BLACK_CAN_CASTLE_KINGSIDE;
492 }
493 if (board->castle_flags & BLACK_CAN_CASTLE_QUEENSIDE) {
494 board->hash_key ^= castle_hash[SIDE_BLACK + CASTLE_QUEENSIDE];
495 board->castle_flags ^= BLACK_CAN_CASTLE_QUEENSIDE;
496 }
497 }
498
499 /* Any activety in the corners will make castling impossible, either
500 ** because the rook moves, or because it is captured.
501 */
502 switch (MOVE_GET(move, SOURCE)) {
503 case SQUARE_A1:
504 if (board->castle_flags & WHITE_CAN_CASTLE_QUEENSIDE) {
505 board->hash_key ^= castle_hash[SIDE_WHITE + CASTLE_QUEENSIDE];
506 board->castle_flags ^= WHITE_CAN_CASTLE_QUEENSIDE;
507 }
508 break;
509 case SQUARE_H1:
510 if (board->castle_flags & WHITE_CAN_CASTLE_KINGSIDE) {
511 board->hash_key ^= castle_hash[SIDE_WHITE + CASTLE_KINGSIDE];
512 board->castle_flags ^= WHITE_CAN_CASTLE_KINGSIDE;
513 }
514 break;
515 case SQUARE_A8:
516 if (board->castle_flags & BLACK_CAN_CASTLE_QUEENSIDE) {
517 board->hash_key ^= castle_hash[SIDE_BLACK + CASTLE_QUEENSIDE];
518 board->castle_flags ^= BLACK_CAN_CASTLE_QUEENSIDE;
519 }
520 break;
521 case SQUARE_H8:
522 if (board->castle_flags & BLACK_CAN_CASTLE_KINGSIDE) {
523 board->hash_key ^= castle_hash[SIDE_BLACK + CASTLE_KINGSIDE];
524 board->castle_flags ^= BLACK_CAN_CASTLE_KINGSIDE;
525 }
526 }
527 switch (MOVE_GET(move, DEST)) {
528 case SQUARE_A1:
529 if (board->castle_flags & WHITE_CAN_CASTLE_QUEENSIDE) {
530 board->hash_key ^= castle_hash[SIDE_WHITE + CASTLE_QUEENSIDE];
531 board->castle_flags ^= WHITE_CAN_CASTLE_QUEENSIDE;
532 }
533 break;
534 case SQUARE_H1:
535 if (board->castle_flags & WHITE_CAN_CASTLE_KINGSIDE) {
536 board->hash_key ^= castle_hash[SIDE_WHITE + CASTLE_KINGSIDE];
537 board->castle_flags ^= WHITE_CAN_CASTLE_KINGSIDE;
538 }
539 break;
540 case SQUARE_A8:
541 if (board->castle_flags & BLACK_CAN_CASTLE_QUEENSIDE) {
542 board->hash_key ^= castle_hash[SIDE_BLACK + CASTLE_QUEENSIDE];
543 board->castle_flags ^= BLACK_CAN_CASTLE_QUEENSIDE;
544 }
545 break;
546 case SQUARE_H8:
547 if (board->castle_flags & BLACK_CAN_CASTLE_KINGSIDE) {
548 board->hash_key ^= castle_hash[SIDE_BLACK + CASTLE_KINGSIDE];
549 board->castle_flags ^= BLACK_CAN_CASTLE_KINGSIDE;
550 }
551 }
552
553 /* Switch players. */
554 board->current_player = OPPONENT(board->current_player);
555 board->hash_key ^= black_to_move;
556 }
557
unmake_move(board_t * board,move_t move,bitboard_t old_en_passant,int old_castle_flags,int old_fifty_moves)558 void unmake_move(board_t *board, move_t move, bitboard_t old_en_passant, int old_castle_flags, int old_fifty_moves) {
559 int castle_diff;
560
561 /* Switch players. */
562 board->current_player = OPPONENT(board->current_player);
563 board->hash_key ^= black_to_move;
564
565 /* Promotion moves. */
566 switch (move & MOVE_PROMOTION_MASK) {
567 case PROMOTION_MOVE_KNIGHT:
568 remove_piece(board, MOVE_GET(move, DEST), KNIGHT + board->current_player);
569 add_piece(board, MOVE_GET(move, DEST), MOVE_GET(move, PIECE));
570 break;
571 case PROMOTION_MOVE_BISHOP:
572 remove_piece(board, MOVE_GET(move, DEST), BISHOP + board->current_player);
573 add_piece(board, MOVE_GET(move, DEST), MOVE_GET(move, PIECE));
574 break;
575 case PROMOTION_MOVE_ROOK:
576 remove_piece(board, MOVE_GET(move, DEST), ROOK + board->current_player);
577 add_piece(board, MOVE_GET(move, DEST), MOVE_GET(move, PIECE));
578 break;
579 case PROMOTION_MOVE_QUEEN:
580 remove_piece(board, MOVE_GET(move, DEST), QUEEN + board->current_player);
581 add_piece(board, MOVE_GET(move, DEST), MOVE_GET(move, PIECE));
582 }
583
584 switch (move & MOVE_NO_PROMOTION_MASK) {
585 case NORMAL_MOVE:
586 remove_piece(board, MOVE_GET(move, DEST), MOVE_GET(move, PIECE));
587 add_piece(board, MOVE_GET(move, SOURCE), MOVE_GET(move, PIECE));
588 break;
589
590 case CAPTURE_MOVE:
591 remove_piece(board, MOVE_GET(move, DEST), MOVE_GET(move, PIECE));
592 add_piece(board, MOVE_GET(move, DEST), MOVE_GET(move, CAPTURED));
593 add_piece(board, MOVE_GET(move, SOURCE), MOVE_GET(move, PIECE));
594 break;
595
596 case CAPTURE_MOVE_EN_PASSANT:
597 remove_piece(board, MOVE_GET(move, DEST), MOVE_GET(move, PIECE));
598 add_piece(board, MOVE_GET(move, DEST) + (MOVE_GET(move, PIECE) & 1 ? 8 : -8), MOVE_GET(move, CAPTURED));
599 add_piece(board, MOVE_GET(move, SOURCE), MOVE_GET(move, PIECE));
600 break;
601
602 case CASTLING_MOVE_KINGSIDE: {
603 /* We have to move the rook as well. */
604 int rook = ROOK + board->current_player;
605
606 /* Remove the phantom kings. */
607 if (!board->current_player) {
608 board->bitboard[WHITE_KING] ^= WHITE_PHANTOM_KINGSIDE;
609 board->bitboard[WHITE_ALL] ^= WHITE_PHANTOM_KINGSIDE;
610
611 /* Put back the rook. */
612 board->bitboard[WHITE_ALL] |= board->bitboard[WHITE_ROOK];
613 board->castle_flags ^= WHITE_HAS_CASTLED | WHITE_PHANTOM_KINGS_KINGSIDE;
614 } else {
615 board->bitboard[BLACK_KING] ^= BLACK_PHANTOM_KINGSIDE;
616 board->bitboard[BLACK_ALL] ^= BLACK_PHANTOM_KINGSIDE;
617
618 /* Put back the rook. */
619 board->bitboard[BLACK_ALL] |= board->bitboard[BLACK_ROOK];
620 board->castle_flags ^= BLACK_HAS_CASTLED | BLACK_PHANTOM_KINGS_KINGSIDE;
621 }
622
623 remove_piece(board, MOVE_GET(move, DEST) - 1, rook);
624 add_piece(board, MOVE_GET(move, DEST) + 1, rook);
625 remove_piece(board, MOVE_GET(move, DEST), MOVE_GET(move, PIECE));
626 add_piece(board, MOVE_GET(move, SOURCE), MOVE_GET(move, PIECE));
627
628 break;
629 }
630 case CASTLING_MOVE_QUEENSIDE: {
631 /* We have to move the rook as well. */
632 int rook = ROOK + board->current_player;
633
634 /* Remove the phantom kings. */
635 if (!board->current_player) {
636 board->bitboard[WHITE_KING] ^= WHITE_PHANTOM_QUEENSIDE;
637 board->bitboard[WHITE_ALL] ^= WHITE_PHANTOM_QUEENSIDE;
638
639 /* Put back the rook. */
640 board->bitboard[WHITE_ALL] |= board->bitboard[WHITE_ROOK];
641 board->castle_flags ^= WHITE_HAS_CASTLED | WHITE_PHANTOM_KINGS_QUEENSIDE;
642 } else {
643 board->bitboard[BLACK_KING] ^= BLACK_PHANTOM_QUEENSIDE;
644 board->bitboard[BLACK_ALL] ^= BLACK_PHANTOM_QUEENSIDE;
645
646 /* Put back the rook. */
647 board->bitboard[BLACK_ALL] |= board->bitboard[BLACK_ROOK];
648 board->castle_flags ^= BLACK_HAS_CASTLED | BLACK_PHANTOM_KINGS_QUEENSIDE;
649 }
650
651 remove_piece(board, MOVE_GET(move, DEST) + 1, rook);
652 add_piece(board, MOVE_GET(move, DEST) - 2, rook);
653 remove_piece(board, MOVE_GET(move, DEST), MOVE_GET(move, PIECE));
654 add_piece(board, MOVE_GET(move, SOURCE), MOVE_GET(move, PIECE));
655
656 break;
657 }
658 case RESIGN_MOVE:
659 /* Resign or checkmate, do nothing. */
660 return;
661 case STALEMATE_MOVE:
662 /* Stalemate, do nothing. */
663 return;
664 }
665
666 /* Restore en passant possibility. */
667 if (board->en_passant || old_en_passant) {
668 int square;
669 for (square = 0; square < 64; square++) {
670 if (board->en_passant & square_bit[square])
671 board->hash_key ^= ep_hash[square];
672 if (old_en_passant & square_bit[square])
673 board->hash_key ^= ep_hash[square];
674 }
675 board->en_passant = old_en_passant;
676 }
677
678 castle_diff = board->castle_flags ^ old_castle_flags;
679
680 /* Restore phantom kings. */
681 switch ((castle_diff & PHANTOM_FLAGS) & old_castle_flags) {
682 case WHITE_PHANTOM_KINGS_KINGSIDE:
683 board->castle_flags |= WHITE_PHANTOM_KINGS_KINGSIDE;
684 board->bitboard[WHITE_KING] |= WHITE_PHANTOM_KINGSIDE;
685 board->bitboard[WHITE_ALL] |= WHITE_PHANTOM_KINGSIDE;
686 break;
687
688 case WHITE_PHANTOM_KINGS_QUEENSIDE:
689 board->castle_flags |= WHITE_PHANTOM_KINGS_QUEENSIDE;
690 board->bitboard[WHITE_KING] |= WHITE_PHANTOM_QUEENSIDE;
691 board->bitboard[WHITE_ALL] |= WHITE_PHANTOM_QUEENSIDE;
692 break;
693
694 case BLACK_PHANTOM_KINGS_KINGSIDE:
695 board->castle_flags |= BLACK_PHANTOM_KINGS_KINGSIDE;
696 board->bitboard[BLACK_KING] |= BLACK_PHANTOM_KINGSIDE;
697 board->bitboard[BLACK_ALL] |= BLACK_PHANTOM_KINGSIDE;
698 break;
699
700 case BLACK_PHANTOM_KINGS_QUEENSIDE:
701 board->castle_flags |= BLACK_PHANTOM_KINGS_QUEENSIDE;
702 board->bitboard[BLACK_KING] |= BLACK_PHANTOM_QUEENSIDE;
703 board->bitboard[BLACK_ALL] |= BLACK_PHANTOM_QUEENSIDE;
704 break;
705 }
706
707 /* Restore castle flags. */
708 if (castle_diff & 15) {
709 int i;
710 for (i = 0; i < 4; i++)
711 if (castle_diff & (1 << i))
712 board->hash_key ^= castle_hash[i];
713 board->castle_flags = old_castle_flags;
714 }
715 board->fifty_moves = old_fifty_moves;
716 }
717