Add forgotten files 1.4.70b
[polyglot.git] / move.cpp
1 \r
2 // move.cpp\r
3 \r
4 // includes\r
5 \r
6 #include <cstdlib>\r
7 #include <cstring>\r
8 \r
9 #include "attack.h"\r
10 #include "colour.h"\r
11 #include "list.h"\r
12 #include "move.h"\r
13 #include "move_do.h"\r
14 #include "move_gen.h"\r
15 #include "move_legal.h"\r
16 #include "option.h"\r
17 #include "piece.h"\r
18 #include "square.h"\r
19 #include "util.h"\r
20 \r
21 // "constants"\r
22 \r
23 static const uint8 PromotePiece[5] = { PieceNone64, Knight64, Bishop64, Rook64, Queen64 };\r
24 \r
25 // functions\r
26 \r
27 // move_is_ok()\r
28 \r
29 bool move_is_ok(int move) {\r
30 \r
31    if (move < 0 || move >= 65536) return false;\r
32 \r
33    if (move == MoveNone) return false;\r
34 \r
35    return true;\r
36 }\r
37 \r
38 // move_make()\r
39 \r
40 int move_make(int from, int to) {\r
41 \r
42    ASSERT(square_is_ok(from));\r
43    ASSERT(square_is_ok(to));\r
44 \r
45    return (square_to_64(from) << 6) | square_to_64(to);\r
46 }\r
47 \r
48 // move_make_flags()\r
49 \r
50 int move_make_flags(int from, int to, int flags) {\r
51 \r
52    ASSERT(square_is_ok(from));\r
53    ASSERT(square_is_ok(to));\r
54    ASSERT((flags&~0xF000)==0);\r
55 \r
56    ASSERT(to!=from);\r
57 \r
58    return (square_to_64(from) << 6) | square_to_64(to) | flags;\r
59 }\r
60 \r
61 // move_from()\r
62 \r
63 int move_from(int move) {\r
64 \r
65    int from_64;\r
66 \r
67    ASSERT(move_is_ok(move));\r
68 \r
69    from_64 = (move >> 6) & 077;\r
70 \r
71    return square_from_64(from_64);\r
72 }\r
73 \r
74 // move_to()\r
75 \r
76 int move_to(int move) {\r
77 \r
78    int to_64;\r
79 \r
80    ASSERT(move_is_ok(move));\r
81 \r
82    to_64 = move & 077;\r
83 \r
84    return square_from_64(to_64);\r
85 }\r
86 \r
87 // move_promote_hack()\r
88 \r
89 int move_promote_hack(int move) {\r
90 \r
91    int code;\r
92 \r
93    ASSERT(move_is_ok(move));\r
94 \r
95    ASSERT(move_is_promote(move));\r
96 \r
97    code = move >> 12;\r
98    ASSERT(code>=1&&code<=4);\r
99 \r
100    return PromotePiece[code];\r
101 }\r
102 \r
103 // move_is_capture()\r
104 \r
105 bool move_is_capture(int move, const board_t * board) {\r
106 \r
107    ASSERT(move_is_ok(move));\r
108    ASSERT(board_is_ok(board));\r
109 \r
110    if (move_is_en_passant(move,board)) return true;\r
111    if (board->square[move_to(move)] != Empty) return true;\r
112 \r
113    return false;\r
114 }\r
115 \r
116 // move_is_promote()\r
117 \r
118 bool move_is_promote(int move) {\r
119 \r
120    ASSERT(move_is_ok(move));\r
121 \r
122    return (move & MoveFlags) != 0;\r
123 }\r
124 \r
125 // move_is_en_passant()\r
126 \r
127 bool move_is_en_passant(int move, const board_t * board) {\r
128 \r
129    ASSERT(move_is_ok(move));\r
130    ASSERT(board_is_ok(board));\r
131 \r
132    return piece_is_pawn(move_piece(move,board))\r
133        && move_to(move) == board->ep_square;\r
134 }\r
135 \r
136 // move_is_castle()\r
137 \r
138 bool move_is_castle(int move, const board_t * board) {\r
139 \r
140    ASSERT(move_is_ok(move));\r
141    ASSERT(board_is_ok(board));\r
142 \r
143    return colour_equal(board->square[move_to(move)],board->turn);\r
144 }\r
145 \r
146 // move_piece()\r
147 \r
148 int move_piece(int move, const board_t * board) {\r
149 \r
150    ASSERT(move_is_ok(move));\r
151    ASSERT(board_is_ok(board));\r
152 \r
153    return board->square[move_from(move)];\r
154 }\r
155 \r
156 // move_capture()\r
157 \r
158 int move_capture(int move, const board_t * board) {\r
159 \r
160    ASSERT(move_is_ok(move));\r
161    ASSERT(board_is_ok(board));\r
162 \r
163    if (move_is_en_passant(move,board)) {\r
164       return piece_pawn_opp(move_piece(move,board));\r
165    }\r
166 \r
167    return board->square[move_to(move)];\r
168 }\r
169 \r
170 // move_promote()\r
171 \r
172 int move_promote(int move, const board_t * board) {\r
173 \r
174    int code;\r
175 \r
176    ASSERT(move_is_ok(move));\r
177    ASSERT(board_is_ok(board));\r
178 \r
179    if (move_is_promote(move)) {\r
180       code = move >> 12;\r
181       ASSERT(code>=1&&code<=4);\r
182       return PromotePiece[code] | board->turn;\r
183    }\r
184 \r
185    return Empty;\r
186 }\r
187 \r
188 // move_is_check()\r
189 \r
190 bool move_is_check(int move, const board_t * board) {\r
191 \r
192    board_t new_board[1];\r
193 \r
194    ASSERT(move_is_ok(move));\r
195    ASSERT(board_is_ok(board));\r
196 \r
197    board_copy(new_board,board);\r
198    move_do(new_board,move);\r
199    ASSERT(!is_in_check(new_board,colour_opp(new_board->turn)));\r
200 \r
201    return board_is_check(new_board);\r
202 }\r
203 \r
204 // move_is_mate()\r
205 \r
206 bool move_is_mate(int move, const board_t * board) {\r
207 \r
208    board_t new_board[1];\r
209 \r
210    ASSERT(move_is_ok(move));\r
211    ASSERT(board_is_ok(board));\r
212 \r
213    board_copy(new_board,board);\r
214    move_do(new_board,move);\r
215    ASSERT(!is_in_check(new_board,colour_opp(new_board->turn)));\r
216 \r
217    return board_is_mate(new_board);\r
218 }\r
219 \r
220 // move_to_can()\r
221 \r
222 bool move_to_can(int move, const board_t * board, char string[], int size) {\r
223 \r
224    int from, to;\r
225 \r
226    ASSERT(move_is_ok(move));\r
227    ASSERT(board_is_ok(board));\r
228    ASSERT(string!=NULL);\r
229    ASSERT(size>=6);\r
230 \r
231    ASSERT(move_is_legal(move,board));\r
232 \r
233    if (size < 6) return false;\r
234 \r
235    // init\r
236 \r
237    from = move_from(move);\r
238    to = move_to(move);\r
239 \r
240    // king-slide castling\r
241 \r
242    if (move_is_castle(move,board) && !option_get_bool("Chess960")) {\r
243       if (false) {\r
244       } else if (from == E1 && to == H1) {\r
245          to = G1;\r
246       } else if (from == E1 && to == A1) {\r
247          to = C1;\r
248       } else if (from == E8 && to == H8) {\r
249          to = G8;\r
250       } else if (from == E8 && to == A8) {\r
251          to = C8;\r
252       }\r
253    }\r
254 \r
255    // normal moves\r
256 \r
257    if (!square_to_string(from,&string[0],3)) ASSERT(false);\r
258    if (!square_to_string(to,&string[2],3)) ASSERT(false);\r
259    ASSERT(strlen(string)==4);\r
260 \r
261    // promotes\r
262 \r
263    if (move_is_promote(move)) {\r
264       string[4] = piece_to_char(move_promote_hack(move)|Black); // HACK: black => lower-case\r
265       string[5] = '\0';\r
266    }\r
267 \r
268    // debug\r
269 \r
270    ASSERT(move_from_can(string,board)==move);\r
271 \r
272    return true;\r
273 }\r
274 \r
275 // move_from_can()\r
276 \r
277 int move_from_can(const char string[], const board_t * board) {\r
278 \r
279    char tmp_string[256];\r
280    int from, to;\r
281    int side;\r
282    int move;\r
283 \r
284    ASSERT(string!=NULL);\r
285    ASSERT(board_is_ok(board));\r
286 \r
287    // from\r
288 \r
289    tmp_string[0] = string[0];\r
290    tmp_string[1] = string[1];\r
291    tmp_string[2] = '\0';\r
292 \r
293    from = square_from_string(tmp_string);\r
294    if (from == SquareNone) return MoveNone;\r
295 \r
296    // to\r
297 \r
298    tmp_string[0] = string[2];\r
299    tmp_string[1] = string[3];\r
300    tmp_string[2] = '\0';\r
301 \r
302    to = square_from_string(tmp_string);\r
303    if (to == SquareNone) return MoveNone;\r
304 \r
305    // convert "king slide" castling to KxR\r
306 \r
307    if (piece_is_king(board->square[from])\r
308     && square_rank(to) == square_rank(from)\r
309     && abs(to-from) > 1) {\r
310       side = (to > from) ? SideH : SideA;\r
311       to = board->castle[board->turn][side];\r
312       if (to == SquareNone) return MoveNone;\r
313    }\r
314 \r
315    // move\r
316 \r
317    move = move_make(from,to);\r
318 \r
319    // promote\r
320 \r
321    switch (string[4]) {\r
322    case '\0': // not a promotion\r
323       if (piece_is_pawn(board->square[from])\r
324        && square_side_rank(to,board->turn) == Rank8\r
325        && option_get_bool("PromoteWorkAround")) {\r
326          move |= MovePromoteQueen;\r
327       }\r
328       break;\r
329    case 'N':\r
330    case 'n':\r
331       move |= MovePromoteKnight;\r
332       break;\r
333    case 'B':\r
334    case 'b':\r
335       move |= MovePromoteBishop;\r
336       break;\r
337    case 'R':\r
338    case 'r':\r
339       move |= MovePromoteRook;\r
340       break;\r
341    case 'Q':\r
342    case 'q':\r
343       move |= MovePromoteQueen;\r
344       break;\r
345    default:\r
346       return MoveNone;\r
347       break;\r
348    }\r
349 \r
350    // debug\r
351 \r
352    ASSERT(move_is_legal(move,board));\r
353 \r
354    return move;\r
355 }\r
356 \r
357 // move_order()\r
358 \r
359 int move_order(int move) {\r
360 \r
361    ASSERT(move_is_ok(move));\r
362 \r
363    return ((move & 07777) << 3) | (move >> 12); // from, to, promote\r
364 }\r
365 \r
366 // move_disp()\r
367 \r
368 void move_disp(int move, const board_t * board) {\r
369 \r
370    char string[256];\r
371 \r
372    ASSERT(move_is_ok(move));\r
373    ASSERT(board_is_ok(board));\r
374 \r
375    if (!move_to_can(move,board,string,256)) ASSERT(false);\r
376    my_log("POLYGLOT %s\n",string);\r
377 }\r
378 \r
379 // end of move.cpp\r
380 \r