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