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