version 1.4.67b
[polyglot.git] / move.c
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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