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