* Count nodes in make_move function
[owl.git] / move.c
blobc918bf97e48d9c32b127490bffb7c9e468e0e9b1
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 #include "common.h"
17 #include "attacks.h"
18 #include "board.h"
19 #include "engine.h"
20 #include "move.h"
22 const char pieces[] = {' ', 'p', 'n', 'b', 'r', 'q', 'k'};
24 /* move in coordinate notation */
25 char *
26 coord_move(int move, char *buf)
28 assert(move);
30 if (GET_PROMOTE(move))
31 snprintf(buf, 6, "%s%s%c", char_board[GET_FROM(move)], \
32 char_board[GET_TO(move)], pieces[GET_PROMOTE(move)]);
33 else
34 snprintf(buf, 5, "%s%s", char_board[GET_FROM(move)], \
35 char_board[GET_TO(move)]);
37 return buf;
40 /* PV in coordinate notation */
41 char *
42 get_pv_string_coord(char *buf)
44 int i;
45 char move_buf[256];
47 buf[0] = '\0';
48 for (i = 0; i < pv_length[0]; i++) {
49 strcat(buf, coord_move(pv[0][i], move_buf));
50 strcat(buf, " ");
52 strcat(buf, "\n");
54 return buf;
57 /* PV in SAN notation */
58 char *
59 get_pv_string_san(char *buf)
61 int i;
62 char move_buf[256];
63 char move_buf2[256];
65 if (pv_length[0]) {
66 if (brd.wtm)
67 sprintf(buf, "%d. ... ", (game_history.count + 1) / 2 + \
68 (game_history.count ? 0 : 1));
69 else
70 sprintf(buf, "%d. ", (game_history.count + 1) / 2 + 1);
72 for (i = 0; i < pv_length[0]; i++) {
73 if (i && !brd.wtm) {
74 sprintf(move_buf, "%d. ", (game_history.count + 1) / 2 + 1);
75 strcat(buf, move_buf);
77 sprintf(move_buf, "%s ", san_move(pv[0][i], move_buf2));
78 strcat(buf, move_buf);
80 make_move(pv[0][i], FALSE);
82 strcat(buf, "\n");
84 for (i = 0; i < pv_length[0]; i++)
85 takeback();
86 } else
87 assert(0 == 1); /* no PV! */
89 return buf;
92 /* make move and update board info */
93 int
94 make_move(int move, int tb)
96 int ep_square;
97 int to, from, type;
98 int cap_piece, piece_from, piece_to;
99 int go_castle;
100 int xwtm;
102 assert(board_is_legal(&brd));
103 assert(move_is_legal(move));
105 from = GET_FROM(move); /* 'from' coordinate */
106 to = GET_TO(move); /* 'to' coordinate */
107 type = GET_TYPE(move); /* type flags */
108 go_castle = FALSE;
109 xwtm = 1 ^ brd.wtm;
111 if (type & TYPE_CASTLE) {
112 /* check if castle move is legal here */
113 if (to == G1) {
114 if (IS_ATTACKED(E1, BLACK) || IS_ATTACKED(F1, BLACK) || \
115 IS_ATTACKED(G1, BLACK))
116 return FALSE;
117 } else if (to == C1) {
118 if (IS_ATTACKED(E1, BLACK) || IS_ATTACKED(D1, BLACK) || \
119 IS_ATTACKED(C1, BLACK))
120 return FALSE;
121 } else if (to == G8) {
122 if (IS_ATTACKED(E8, WHITE) || IS_ATTACKED(F8, WHITE) || \
123 IS_ATTACKED(G8, WHITE))
124 return FALSE;
125 } else if (to == C8) {
126 if (IS_ATTACKED(E8, WHITE) || IS_ATTACKED(D8, WHITE) || \
127 IS_ATTACKED(C8, WHITE))
128 return FALSE;
130 go_castle = TRUE;
133 cap_piece = brd.cap_piece = square64[to];
134 brd.move = move;
136 /* copy parameters for takeback */
137 memcpy(&game_history.board[game_history.count++], &brd, \
138 sizeof(struct board_t));
140 piece_from = square64[from];
142 if (brd.ep != -1)
143 brd.hash_key ^= hash_ep[_FILE(brd.ep)]; /* clear ep hash */
145 if (cap_piece)
146 /* remove captured piece */
147 remove_piece(to, cap_piece, xwtm);
149 /* handle promote move */
150 piece_to = (type & TYPE_PROMOTE) ? GET_PROMOTE(move) : piece_from;
152 remove_piece(from, piece_from, brd.wtm);
153 add_piece(to, piece_to, brd.wtm);
155 if (type & TYPE_ENPASSANT) {
156 /* remove enpassant victim */
157 ep_square = to - (brd.wtm? -1 : 1) * 8;
158 remove_piece(ep_square, PAWN, xwtm);
161 brd.ep = -1; /* remove ep status by default */
162 if (type & TYPE_PAWN_TWO)
163 /* polyglot-compatibility hack! if there is no pawn on enpassant
164 target square skip ep */
165 if ((BIT(to - 1) & PAWNS(xwtm)) || (BIT(to + 1) & PAWNS(xwtm))) {
166 brd.ep = (to + from) / 2;
167 brd.hash_key ^= hash_ep[_FILE(brd.ep)];
170 if (go_castle) {
171 if (to == G1) {
172 add_piece(F1, ROOK, brd.wtm);
173 remove_piece(H1, ROOK, brd.wtm);
174 castled[WHITE] = TRUE;
175 } else if (to == C1) {
176 add_piece(D1, ROOK, brd.wtm);
177 remove_piece(A1, ROOK, brd.wtm);
178 castled[WHITE] = TRUE;
179 } else if (to == G8) {
180 add_piece(F8, ROOK, brd.wtm);
181 remove_piece(H8, ROOK, brd.wtm);
182 castled[BLACK] = TRUE;
183 } else if (to == C8) {
184 add_piece(D8, ROOK, brd.wtm);
185 remove_piece(A8, ROOK, brd.wtm);
186 castled[BLACK] = TRUE;
190 if (brd.castle_mask) {
191 if (from == E1) {
192 if (brd.castle_mask & WHITE_CASTLE_KINGSIDE)
193 brd.hash_key ^= hash_wck;
194 if (brd.castle_mask & WHITE_CASTLE_QUEENSIDE)
195 brd.hash_key ^= hash_wcq;
196 brd.castle_mask &= ~(WHITE_CASTLE_KINGSIDE | WHITE_CASTLE_QUEENSIDE);
197 } else if (from == E8) {
198 if (brd.castle_mask & BLACK_CASTLE_KINGSIDE)
199 brd.hash_key ^= hash_bck;
200 if (brd.castle_mask & BLACK_CASTLE_QUEENSIDE)
201 brd.hash_key ^= hash_bcq;
202 brd.castle_mask &= ~(BLACK_CASTLE_KINGSIDE | BLACK_CASTLE_QUEENSIDE);
203 } else {
204 if (from == H1 || to == H1) {
205 if (brd.castle_mask & WHITE_CASTLE_KINGSIDE)
206 brd.hash_key ^= hash_wck;
207 brd.castle_mask &= ~WHITE_CASTLE_KINGSIDE;
209 if (from == A1 || to == A1) {
210 if (brd.castle_mask & WHITE_CASTLE_QUEENSIDE)
211 brd.hash_key ^= hash_wcq;
212 brd.castle_mask &= ~WHITE_CASTLE_QUEENSIDE;
214 if (from == H8 || to == H8) {
215 if (brd.castle_mask & BLACK_CASTLE_KINGSIDE)
216 brd.hash_key ^= hash_bck;
217 brd.castle_mask &= ~BLACK_CASTLE_KINGSIDE;
219 if (from == A8 || to == A8) {
220 if (brd.castle_mask & BLACK_CASTLE_QUEENSIDE)
221 brd.hash_key ^= hash_bcq;
222 brd.castle_mask &= ~BLACK_CASTLE_QUEENSIDE;
226 /* if the move is not a capture or pawn push, increase fifty_rule */
227 brd.fifty_rule = (!type || type == TYPE_CASTLE)? brd.fifty_rule + 1 : 0;
229 update_boards();
230 brd.wtm = xwtm;
231 brd.hash_key ^= hash_side;
233 if (IS_CHECKED(1 ^ brd.wtm)) {
234 takeback();
235 return FALSE;
236 } else {
237 if (tb)
238 takeback();
239 counters.searched_nodes++;
240 return TRUE;
244 /* used for sanity check */
245 int
246 move_is_legal(int move)
248 int from = GET_FROM(move);
249 int to = GET_TO(move);
251 if (to == from)
252 return FALSE;
254 int piece_from = square64[from];
255 int piece_to = square64[to];
257 if (!piece_from)
258 return FALSE;
260 if ((BIT(from) & piece_boards[brd.wtm][piece_from]) == 0)
261 return FALSE;
263 if (piece_to) {
264 if (BIT(to) & side_boards[brd.wtm])
265 return FALSE;
266 if (piece_to == KING)
267 return FALSE;
270 return TRUE;
273 /* return internal binary move representation from coordinate */
274 int
275 parse_move_coord(char *move)
277 char buf[256];
278 int i;
279 struct moves_t moves;
281 gen_legal_moves(&moves);
283 /* generate pseudolegal moves and find target move */
284 for (i = 0; i < moves.count; i++) {
285 if (!strcmp(move, coord_move(moves.move[i], buf)))
286 return moves.move[i];
288 return 0;
291 /* return internal binary move representation from SAN */
292 int
293 parse_move_san(char *move)
295 int i;
296 char buf[MAX_STRING];
297 struct moves_t moves;
299 gen_legal_moves(&moves);
301 /* generate pseudolegal moves and find target move */
302 for (i = 0; i < moves.count; i++) {
303 if (!strncmp(move, san_move(moves.move[i], buf), 6))
304 return moves.move[i];
307 return 0;
310 void
311 print_move_coord(int move)
313 char buf[256];
314 printf("%s\n", coord_move(move, buf));
317 void
318 print_moves_coord(struct moves_t *moves)
320 int i;
321 char buf[256];
323 for (i = 0; i < moves->count; i++)
324 printf("%s ", coord_move(moves->move[i], buf));
325 printf("\n");
328 void
329 print_moves_san(struct moves_t *moves)
331 int i;
332 char buf[256];
334 for (i = 0; i < moves->count; i++) {
335 if (make_move(moves->move[i], TRUE))
336 printf("%s ", san_move(moves->move[i], buf));
338 printf("\n");
341 /* undo move */
342 void
343 takeback(void)
345 int c;
346 int cap_piece;
347 int move;
348 int from, to, type;
349 int to_piece;
350 int xwtm;
352 assert(board_is_legal(&brd));
354 c = --game_history.count;
355 cap_piece = game_history.board[c].cap_piece;
356 move = game_history.board[c].move;
358 brd.castle_mask = game_history.board[c].castle_mask;
359 brd.ep = game_history.board[c].ep;
361 /* do the following if move is not 'NULL move' */
362 if (move) {
363 from = GET_FROM(move);
364 to = GET_TO(move);
365 type = GET_TYPE(move);
366 to_piece = square64[to];
367 xwtm = 1 ^ brd.wtm;
369 remove_piece(to, to_piece, xwtm);
371 if (cap_piece) {
372 /* restore captured piece */
373 add_piece(to, cap_piece, brd.wtm);
374 add_piece(from, (type & TYPE_PROMOTE)? PAWN : to_piece, xwtm);
375 } else if (type & TYPE_ENPASSANT) {
376 /* restore captured by enpassant pawn */
377 add_piece(brd.wtm? to - 8 : to + 8, PAWN, brd.wtm);
378 add_piece(from, PAWN, xwtm);
379 } else if (type & TYPE_PROMOTE)
380 add_piece(from, PAWN, xwtm);
381 else
382 add_piece(from, to_piece, xwtm);
384 /* undo castle */
385 if (type & TYPE_CASTLE) {
386 if (to == G1) {
387 add_piece(H1, ROOK, xwtm);
388 remove_piece(F1, ROOK, xwtm);
389 castled[WHITE] = FALSE;
390 } else if (to == C1) {
391 add_piece(A1, ROOK, xwtm);
392 remove_piece(D1, ROOK, xwtm);
393 castled[WHITE] = FALSE;
394 } else if (to == G8) {
395 add_piece(H8, ROOK, xwtm);
396 remove_piece(F8, ROOK, xwtm);
397 castled[BLACK] = FALSE;
398 } else if (to == C8) {
399 add_piece(A8, ROOK, xwtm);
400 remove_piece(D8, ROOK, xwtm);
401 castled[BLACK] = FALSE;
405 update_boards();
407 brd.wtm = 1 ^ brd.wtm;
408 brd.hash_key = game_history.board[c].hash_key;
409 brd.hash_pawn_key = game_history.board[c].hash_pawn_key;
410 brd.fifty_rule = game_history.board[c].fifty_rule;