Add forgotten files 1.4.70b
[polyglot.git] / move_do.cpp
1 \r
2 // move_do.cpp\r
3 \r
4 // includes\r
5 \r
6 #include <cstdlib>\r
7 \r
8 #include "board.h"\r
9 #include "colour.h"\r
10 #include "hash.h"\r
11 #include "move.h"\r
12 #include "move_do.h"\r
13 #include "move_legal.h"\r
14 #include "piece.h"\r
15 #include "random.h"\r
16 #include "util.h"\r
17 \r
18 // prototypes\r
19 \r
20 static void square_clear (board_t * board, int square, int piece);\r
21 static void square_set   (board_t * board, int square, int piece, int pos);\r
22 static void square_move  (board_t * board, int from, int to, int piece);\r
23 \r
24 // functions\r
25 \r
26 // move_do()\r
27 \r
28 void move_do(board_t * board, int move) {\r
29 \r
30    int me, opp;\r
31    int from, to;\r
32    int piece, pos, capture;\r
33    int old_flags, new_flags;\r
34    int sq, ep_square;\r
35    int pawn;\r
36 \r
37    ASSERT(board_is_ok(board));\r
38    ASSERT(move_is_ok(move));\r
39 \r
40    ASSERT(move_is_pseudo(move,board));\r
41 \r
42    // init\r
43 \r
44    me = board->turn;\r
45    opp = colour_opp(me);\r
46 \r
47    from = move_from(move);\r
48    to = move_to(move);\r
49 \r
50    piece = board->square[from];\r
51    ASSERT(colour_equal(piece,me));\r
52 \r
53    pos = board->pos[from];\r
54    ASSERT(pos>=0);\r
55 \r
56    // update turn\r
57 \r
58    board->turn = opp;\r
59    board->key ^= random_64(RandomTurn);\r
60 \r
61    // update castling rights\r
62 \r
63    old_flags = board_flags(board);\r
64 \r
65    if (piece_is_king(piece)) {\r
66       board->castle[me][SideH] = SquareNone;\r
67       board->castle[me][SideA] = SquareNone;\r
68    }\r
69 \r
70    if (board->castle[me][SideH] == from) board->castle[me][SideH] = SquareNone;\r
71    if (board->castle[me][SideA] == from) board->castle[me][SideA] = SquareNone;\r
72 \r
73    if (board->castle[opp][SideH] == to) board->castle[opp][SideH] = SquareNone;\r
74    if (board->castle[opp][SideA] == to) board->castle[opp][SideA] = SquareNone;\r
75 \r
76    new_flags = board_flags(board);\r
77 \r
78    board->key ^= hash_castle_key(new_flags^old_flags); // HACK\r
79 \r
80    // update en-passant square\r
81 \r
82    ep_square = sq = board->ep_square;\r
83    if (sq != SquareNone) {\r
84       board->key ^= random_64(RandomEnPassant+square_file(sq));\r
85       board->ep_square = SquareNone;\r
86    }\r
87 \r
88    if (piece_is_pawn(piece) && abs(to-from) == 32) {\r
89       pawn = piece_make_pawn(opp);\r
90       if (board->square[to-1] == pawn || board->square[to+1] == pawn) {\r
91          board->ep_square = sq = (from + to) / 2;\r
92          board->key ^= random_64(RandomEnPassant+square_file(sq));\r
93       }\r
94    }\r
95 \r
96    // update ply number (captures are handled later)\r
97 \r
98    board->ply_nb++;\r
99    if (piece_is_pawn(piece)) board->ply_nb = 0; // conversion\r
100 \r
101    // update move number\r
102 \r
103    if (me == Black) board->move_nb++;\r
104 \r
105    // castle\r
106 \r
107    if (colour_equal(board->square[to],me)) {\r
108 \r
109       int rank;\r
110       int king_from, king_to;\r
111       int rook_from, rook_to;\r
112       int rook;\r
113 \r
114       rank = colour_is_white(me) ? Rank1 : Rank8;\r
115 \r
116       king_from = from;\r
117       rook_from = to;\r
118 \r
119       if (to > from) { // h side\r
120          king_to = square_make(FileG,rank);\r
121          rook_to = square_make(FileF,rank);\r
122       } else { // a side\r
123          king_to = square_make(FileC,rank);\r
124          rook_to = square_make(FileD,rank);\r
125       }\r
126 \r
127       // remove the rook\r
128 \r
129       pos = board->pos[rook_from];\r
130       ASSERT(pos>=0);\r
131 \r
132       rook = Rook64 | me; // HACK\r
133 \r
134       square_clear(board,rook_from,rook);\r
135 \r
136       // move the king\r
137 \r
138       square_move(board,king_from,king_to,piece);\r
139 \r
140       // put the rook back\r
141 \r
142       square_set(board,rook_to,rook,pos);\r
143 \r
144       ASSERT(board->key==hash_key(board));\r
145 \r
146       return;\r
147    }\r
148 \r
149    // remove the captured piece\r
150 \r
151    if (piece_is_pawn(piece) && to == ep_square) {\r
152 \r
153       // en-passant capture\r
154 \r
155       sq = square_ep_dual(to);\r
156       capture = board->square[sq];\r
157       ASSERT(capture==piece_make_pawn(opp));\r
158 \r
159       square_clear(board,sq,capture);\r
160 \r
161       board->ply_nb = 0; // conversion\r
162 \r
163    } else {\r
164 \r
165       capture = board->square[to];\r
166 \r
167       if (capture != Empty) {\r
168 \r
169          // normal capture\r
170 \r
171          ASSERT(colour_equal(capture,opp));\r
172          ASSERT(!piece_is_king(capture));\r
173 \r
174          square_clear(board,to,capture);\r
175 \r
176          board->ply_nb = 0; // conversion\r
177       }\r
178    }\r
179 \r
180    // move the piece\r
181 \r
182    if (move_is_promote(move)) {\r
183 \r
184       // promote\r
185 \r
186       square_clear(board,from,piece);\r
187       piece = move_promote_hack(move) | me; // HACK\r
188       square_set(board,to,piece,pos);\r
189 \r
190    } else {\r
191 \r
192       // normal move\r
193 \r
194       square_move(board,from,to,piece);\r
195    }\r
196 \r
197    ASSERT(board->key==hash_key(board));\r
198 }\r
199 \r
200 // square_clear()\r
201 \r
202 static void square_clear(board_t * board, int square, int piece) {\r
203 \r
204    int pos, piece_12, colour;\r
205    int sq, size;\r
206 \r
207    ASSERT(board!=NULL);\r
208    ASSERT(square_is_ok(square));\r
209    ASSERT(piece_is_ok(piece));\r
210 \r
211    // init\r
212 \r
213    pos = board->pos[square];\r
214    ASSERT(pos>=0);\r
215 \r
216    colour = piece_colour(piece);\r
217    piece_12 = piece_to_12(piece);\r
218 \r
219    // square\r
220 \r
221    ASSERT(board->square[square]==piece);\r
222    board->square[square] = Empty;\r
223 \r
224    ASSERT(board->pos[square]==pos);\r
225    board->pos[square] = -1; // not needed\r
226 \r
227    // piece list\r
228 \r
229    ASSERT(board->list_size[colour]>=2);\r
230    size = --board->list_size[colour];\r
231    ASSERT(pos<=size);\r
232 \r
233    if (pos != size) {\r
234 \r
235       sq = board->list[colour][size];\r
236       ASSERT(square_is_ok(sq));\r
237       ASSERT(sq!=square);\r
238 \r
239       ASSERT(board->pos[sq]==size);\r
240       board->pos[sq] = pos;\r
241 \r
242       ASSERT(board->list[colour][pos]==square);\r
243       board->list[colour][pos] = sq;\r
244    }\r
245 \r
246    board->list[colour][size] = SquareNone;\r
247 \r
248    // material\r
249 \r
250    ASSERT(board->number[piece_12]>=1);\r
251    board->number[piece_12]--;\r
252 \r
253    // hash key\r
254 \r
255    board->key ^= random_64(RandomPiece+piece_12*64+square_to_64(square));\r
256 }\r
257 \r
258 // square_set()\r
259 \r
260 static void square_set(board_t * board, int square, int piece, int pos) {\r
261 \r
262    int piece_12, colour;\r
263    int sq, size;\r
264 \r
265    ASSERT(board!=NULL);\r
266    ASSERT(square_is_ok(square));\r
267    ASSERT(piece_is_ok(piece));\r
268    ASSERT(pos>=0);\r
269 \r
270    // init\r
271 \r
272    colour = piece_colour(piece);\r
273    piece_12 = piece_to_12(piece);\r
274 \r
275    // square\r
276 \r
277    ASSERT(board->square[square]==Empty);\r
278    board->square[square] = piece;\r
279 \r
280    ASSERT(board->pos[square]==-1);\r
281    board->pos[square] = pos;\r
282 \r
283    // piece list\r
284 \r
285    size = board->list_size[colour]++;\r
286    ASSERT(board->list[colour][size]==SquareNone);\r
287    ASSERT(pos<=size);\r
288 \r
289    if (pos != size) {\r
290 \r
291       sq = board->list[colour][pos];\r
292       ASSERT(square_is_ok(sq));\r
293       ASSERT(sq!=square);\r
294 \r
295       ASSERT(board->pos[sq]==pos);\r
296       board->pos[sq] = size;\r
297 \r
298       ASSERT(board->list[colour][size]==SquareNone);\r
299       board->list[colour][size] = sq;\r
300    }\r
301 \r
302    board->list[colour][pos] = square;\r
303 \r
304    // material\r
305 \r
306    ASSERT(board->number[piece_12]<=8);\r
307    board->number[piece_12]++;\r
308 \r
309    // hash key\r
310 \r
311    board->key ^= random_64(RandomPiece+piece_12*64+square_to_64(square));\r
312 }\r
313 \r
314 // square_move()\r
315 \r
316 static void square_move(board_t * board, int from, int to, int piece) {\r
317 \r
318    int colour, pos;\r
319    int piece_index;\r
320 \r
321    ASSERT(board!=NULL);\r
322    ASSERT(square_is_ok(from));\r
323    ASSERT(square_is_ok(to));\r
324    ASSERT(piece_is_ok(piece));\r
325 \r
326    // init\r
327 \r
328    colour = piece_colour(piece);\r
329 \r
330    pos = board->pos[from];\r
331    ASSERT(pos>=0);\r
332 \r
333    // from\r
334 \r
335    ASSERT(board->square[from]==piece);\r
336    board->square[from] = Empty;\r
337 \r
338    ASSERT(board->pos[from]==pos);\r
339    board->pos[from] = -1; // not needed\r
340 \r
341    // to\r
342 \r
343    ASSERT(board->square[to]==Empty);\r
344    board->square[to] = piece;\r
345 \r
346    ASSERT(board->pos[to]==-1);\r
347    board->pos[to] = pos;\r
348 \r
349    // piece list\r
350 \r
351    ASSERT(board->list[colour][pos]==from);\r
352    board->list[colour][pos] = to;\r
353 \r
354    // hash key\r
355 \r
356    piece_index = RandomPiece + piece_to_12(piece) * 64;\r
357 \r
358    board->key ^= random_64(piece_index+square_to_64(from))\r
359                ^ random_64(piece_index+square_to_64(to));\r
360 }\r
361 \r
362 // end of move_do.cpp\r
363 \r