Rev 33 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
33 | pmbaty | 1 | #include "chess.h" |
2 | #include "data.h" |
||
108 | pmbaty | 3 | /* modified 12/31/15 */ |
33 | pmbaty | 4 | /* |
5 | ******************************************************************************* |
||
6 | * * |
||
7 | * GenerateCaptures() is used to generate capture and pawn promotion moves * |
||
8 | * from the current position. * |
||
9 | * * |
||
10 | * The destination square set is the set of squares occupied by opponent * |
||
11 | * pieces, plus the set of squares on the 8th rank that pawns can advance to * |
||
12 | * and promote. * |
||
13 | * * |
||
14 | ******************************************************************************* |
||
15 | */ |
||
108 | pmbaty | 16 | unsigned *GenerateCaptures(TREE * RESTRICT tree, int ply, int side, |
17 | unsigned *move) { |
||
18 | uint64_t target, piecebd, moves, promotions, pcapturesl, pcapturesr; |
||
33 | pmbaty | 19 | int from, to, temp, common, enemy = Flip(side); |
20 | |||
21 | /* |
||
22 | ************************************************************ |
||
23 | * * |
||
24 | * We produce knight moves by locating the most advanced * |
||
25 | * knight and then using that <from> square as an index * |
||
26 | * into the precomputed knight_attacks data. We repeat * |
||
27 | * for each knight. * |
||
28 | * * |
||
29 | ************************************************************ |
||
30 | */ |
||
31 | for (piecebd = Knights(side); piecebd; Clear(from, piecebd)) { |
||
108 | pmbaty | 32 | from = MostAdvanced(side, piecebd); |
33 | pmbaty | 33 | moves = knight_attacks[from] & Occupied(enemy); |
34 | temp = from + (knight << 12); |
||
35 | Extract(side, move, moves, temp); |
||
36 | } |
||
37 | /* |
||
38 | ************************************************************ |
||
39 | * * |
||
108 | pmbaty | 40 | * We produce sliding piece moves by locating each piece * |
41 | * type in turn. We then start with the most advanced * |
||
42 | * piece and generate moves from that square. This uses * |
||
43 | * "magic move generation" to produce the destination * |
||
44 | * squares. * |
||
33 | pmbaty | 45 | * * |
46 | ************************************************************ |
||
47 | */ |
||
48 | for (piecebd = Bishops(side); piecebd; Clear(from, piecebd)) { |
||
108 | pmbaty | 49 | from = MostAdvanced(side, piecebd); |
33 | pmbaty | 50 | moves = BishopAttacks(from, OccupiedSquares) & Occupied(enemy); |
51 | temp = from + (bishop << 12); |
||
52 | Extract(side, move, moves, temp); |
||
53 | } |
||
54 | for (piecebd = Rooks(side); piecebd; Clear(from, piecebd)) { |
||
108 | pmbaty | 55 | from = MostAdvanced(side, piecebd); |
33 | pmbaty | 56 | moves = RookAttacks(from, OccupiedSquares) & Occupied(enemy); |
57 | temp = from + (rook << 12); |
||
58 | Extract(side, move, moves, temp); |
||
59 | } |
||
60 | for (piecebd = Queens(side); piecebd; Clear(from, piecebd)) { |
||
108 | pmbaty | 61 | from = MostAdvanced(side, piecebd); |
33 | pmbaty | 62 | moves = QueenAttacks(from, OccupiedSquares) & Occupied(enemy); |
63 | temp = from + (queen << 12); |
||
64 | Extract(side, move, moves, temp); |
||
65 | } |
||
66 | /* |
||
67 | ************************************************************ |
||
68 | * * |
||
69 | * We produce king moves by locating the only king and * |
||
70 | * then using that <from> square as an index into the * |
||
71 | * precomputed king_attacks data. * |
||
72 | * * |
||
73 | ************************************************************ |
||
74 | */ |
||
75 | from = KingSQ(side); |
||
76 | moves = king_attacks[from] & Occupied(enemy); |
||
77 | temp = from + (king << 12); |
||
78 | Extract(side, move, moves, temp); |
||
79 | /* |
||
80 | ************************************************************ |
||
81 | * * |
||
82 | * Now, produce pawn moves. This is done differently due * |
||
83 | * to inconsistencies in the way a pawn moves when it * |
||
84 | * captures as opposed to normal non-capturing moves. * |
||
85 | * Another exception is capturing enpassant. The first * |
||
86 | * step is to generate all possible pawn promotions. We * |
||
87 | * do this by removing all pawns but those on the 7th rank * |
||
88 | * and then advancing them if the square in front is empty.* |
||
89 | * * |
||
90 | ************************************************************ |
||
91 | */ |
||
108 | pmbaty | 92 | promotions = Pawns(side) & rank_mask[rank7[side]]; |
33 | pmbaty | 93 | promotions = |
108 | pmbaty | 94 | ((side) ? promotions << 8 : promotions >> 8) & ~OccupiedSquares; |
33 | pmbaty | 95 | for (; promotions; Clear(to, promotions)) { |
96 | to = LSB(promotions); |
||
97 | *move++ = |
||
98 | (to + pawnadv1[side]) | (to << 6) | (pawn << 12) | (queen << 18); |
||
99 | } |
||
100 | target = Occupied(enemy) | EnPassantTarget(ply); |
||
101 | pcapturesl = |
||
102 | ((side) ? (Pawns(white) & mask_left_edge) << 7 : (Pawns(black) & |
||
103 | mask_left_edge) >> 9) & target; |
||
104 | for (; pcapturesl; Clear(to, pcapturesl)) { |
||
108 | pmbaty | 105 | to = MostAdvanced(side, pcapturesl); |
33 | pmbaty | 106 | common = (to + capleft[side]) | (to << 6) | (pawn << 12); |
107 | if ((side) ? to < 56 : to > 7) |
||
108 | *move++ = common | (((PcOnSq(to)) ? Abs(PcOnSq(to)) : pawn) << 15); |
||
109 | else |
||
110 | *move++ = common | Abs(PcOnSq(to)) << 15 | queen << 18; |
||
111 | } |
||
112 | pcapturesr = |
||
113 | ((side) ? (Pawns(white) & mask_right_edge) << 9 : (Pawns(black) & |
||
114 | mask_right_edge) >> 7) & target; |
||
115 | for (; pcapturesr; Clear(to, pcapturesr)) { |
||
108 | pmbaty | 116 | to = MostAdvanced(side, pcapturesr); |
33 | pmbaty | 117 | common = (to + capright[side]) | (to << 6) | (pawn << 12); |
118 | if ((side) ? to < 56 : to > 7) |
||
119 | *move++ = common | (((PcOnSq(to)) ? Abs(PcOnSq(to)) : pawn) << 15); |
||
120 | else |
||
121 | *move++ = common | Abs(PcOnSq(to)) << 15 | queen << 18; |
||
122 | } |
||
123 | return move; |
||
124 | } |
||
125 | |||
108 | pmbaty | 126 | /* modified 12/31/15 */ |
33 | pmbaty | 127 | /* |
128 | ******************************************************************************* |
||
129 | * * |
||
130 | * GenerateChecks() is used to generate non-capture moves from the current * |
||
131 | * position. * |
||
132 | * * |
||
133 | * The first pass produces a bitmap that contains the squares a particular * |
||
134 | * piece type would attack if sitting on the square the enemy king sits on. * |
||
135 | * We then use each of these squares as a source and check to see if the * |
||
136 | * same piece type attacks one of these common targets. If so, we can move * |
||
137 | * that piece to that square and it will directly attack the king. We do * |
||
138 | * this for pawns, knights, bishops, rooks and queens to produce the set of * |
||
139 | * "direct checking moves." * |
||
140 | * * |
||
141 | * Then we generate discovered checks in two passes, once for diagonal * |
||
142 | * attacks and once for rank/file attacks (we do it in two passes since a * |
||
143 | * rook can't produce a discovered check along a rank or file since it moves * |
||
144 | * in that direction as well. For diagonals, we first generate the bishop * |
||
145 | * attacks from the enemy king square and mask them with the friendly piece * |
||
146 | * occupied squares bitmap. This gives us a set of up to 4 "blocking * |
||
147 | * pieces" that could be preventing a check. We then remove them via the * |
||
148 | * "magic move generation" tricks, and see if we now reach friendly bishops * |
||
149 | * or queens on those diagonals. If we have a friendly blocker, and a * |
||
150 | * friendly diagonal mover behind that blocker, then moving the blocker is * |
||
151 | * a discovered check (and there could be double-checks included but we do * |
||
152 | * not check for that since a single check is good enough). We repeat this * |
||
153 | * for the ranks/files and we are done. * |
||
154 | * * |
||
155 | * For the present, this code does not produce discovered checks by the * |
||
156 | * king since all king moves are not discovered checks because the king can * |
||
157 | * move in the same direction as the piece it blocks and not uncover the * |
||
158 | * attack. This might be fixed at some point, but it is rare enough to not * |
||
159 | * be an issue except in far endgames. * |
||
160 | * * |
||
161 | ******************************************************************************* |
||
162 | */ |
||
108 | pmbaty | 163 | unsigned *GenerateChecks(TREE * RESTRICT tree, int side, unsigned *move) { |
33 | pmbaty | 164 | uint64_t temp_target, target, piecebd, moves; |
165 | uint64_t padvances1, blockers, checkers; |
||
166 | int from, to, promote, temp, enemy = Flip(side); |
||
167 | |||
168 | /* |
||
108 | pmbaty | 169 | ************************************************************ |
170 | * * |
||
171 | * First pass: produce direct checks. For each piece * |
||
172 | * type, we pretend that a piece of that type stands on * |
||
173 | * the square of the king and we generate attacks from * |
||
174 | * that square for that piece. Now, if we can find any * |
||
175 | * piece of that type that attacks one of those squares, * |
||
176 | * then that piece move would deliver a direct check to * |
||
177 | * the enemy king. Easy, wasn't it? * |
||
178 | * * |
||
179 | ************************************************************ |
||
33 | pmbaty | 180 | */ |
181 | target = ~OccupiedSquares; |
||
182 | /* |
||
183 | ************************************************************ |
||
184 | * * |
||
185 | * Knight direct checks. * |
||
186 | * * |
||
187 | ************************************************************ |
||
188 | */ |
||
189 | temp_target = target & knight_attacks[KingSQ(enemy)]; |
||
190 | for (piecebd = Knights(side); piecebd; Clear(from, piecebd)) { |
||
108 | pmbaty | 191 | from = MostAdvanced(side, piecebd); |
33 | pmbaty | 192 | moves = knight_attacks[from] & temp_target; |
193 | temp = from + (knight << 12); |
||
194 | Extract(side, move, moves, temp); |
||
195 | } |
||
196 | /* |
||
197 | ************************************************************ |
||
198 | * * |
||
108 | pmbaty | 199 | * Sliding piece direct checks. * |
33 | pmbaty | 200 | * * |
201 | ************************************************************ |
||
202 | */ |
||
203 | temp_target = target & BishopAttacks(KingSQ(enemy), OccupiedSquares); |
||
204 | for (piecebd = Bishops(side); piecebd; Clear(from, piecebd)) { |
||
108 | pmbaty | 205 | from = MostAdvanced(side, piecebd); |
33 | pmbaty | 206 | moves = BishopAttacks(from, OccupiedSquares) & temp_target; |
207 | temp = from + (bishop << 12); |
||
208 | Extract(side, move, moves, temp); |
||
209 | } |
||
210 | temp_target = target & RookAttacks(KingSQ(enemy), OccupiedSquares); |
||
211 | for (piecebd = Rooks(side); piecebd; Clear(from, piecebd)) { |
||
108 | pmbaty | 212 | from = MostAdvanced(side, piecebd); |
33 | pmbaty | 213 | moves = RookAttacks(from, OccupiedSquares) & temp_target; |
214 | temp = from + (rook << 12); |
||
215 | Extract(side, move, moves, temp); |
||
216 | } |
||
217 | temp_target = target & QueenAttacks(KingSQ(enemy), OccupiedSquares); |
||
218 | for (piecebd = Queens(side); piecebd; Clear(from, piecebd)) { |
||
108 | pmbaty | 219 | from = MostAdvanced(side, piecebd); |
33 | pmbaty | 220 | moves = QueenAttacks(from, OccupiedSquares) & temp_target; |
221 | temp = from + (queen << 12); |
||
222 | Extract(side, move, moves, temp); |
||
223 | } |
||
224 | /* |
||
225 | ************************************************************ |
||
226 | * * |
||
227 | * Pawn direct checks. * |
||
228 | * * |
||
229 | ************************************************************ |
||
230 | */ |
||
231 | temp_target = target & pawn_attacks[enemy][KingSQ(enemy)]; |
||
232 | padvances1 = ((side) ? Pawns(white) << 8 : Pawns(black) >> 8) & temp_target; |
||
233 | for (; padvances1; Clear(to, padvances1)) { |
||
108 | pmbaty | 234 | to = MostAdvanced(side, padvances1); |
33 | pmbaty | 235 | *move++ = (to + pawnadv1[side]) | (to << 6) | (pawn << 12); |
236 | } |
||
237 | /* |
||
238 | ************************************************************ |
||
239 | * * |
||
108 | pmbaty | 240 | * Second pass: produce discovered checks. Here we do * |
241 | * things a bit differently. We first take diagonal * |
||
242 | * movers. From the enemy king's position, we generate * |
||
243 | * diagonal moves to see if any of them end at one of our * |
||
244 | * pieces that does not slide diagonally, such as a rook, * |
||
245 | * knight or pawn. If we find one, we look further down * |
||
246 | * that diagonal to see if we now find a diagonal moves * |
||
247 | * (queen or bishop). If so, any legal move by the * |
||
248 | * blocking piece (except captures which have already been * |
||
249 | * generated) will be a discovered check that needs to be * |
||
250 | * searched. We do the same for vertical / horizontal * |
||
251 | * rays that are blocked by bishops, knights or pawns that * |
||
252 | * would hide a discovered check by a rook or queen. * |
||
253 | * * |
||
33 | pmbaty | 254 | * First we look for diagonal discovered attacks. Once we * |
255 | * know which squares hold pieces that create a discovered * |
||
256 | * check when they move, we generate those piece moves * |
||
257 | * piece type by piece type. * |
||
258 | * * |
||
259 | ************************************************************ |
||
260 | */ |
||
261 | blockers = |
||
262 | BishopAttacks(KingSQ(enemy), |
||
263 | OccupiedSquares) & (Rooks(side) | Knights(side) | Pawns(side)); |
||
264 | if (blockers) { |
||
265 | checkers = |
||
266 | BishopAttacks(KingSQ(enemy), |
||
267 | OccupiedSquares & ~blockers) & (Bishops(side) | Queens(side)); |
||
268 | if (checkers) { |
||
269 | if (plus7dir[KingSQ(enemy)] & blockers && |
||
270 | !(plus7dir[KingSQ(enemy)] & checkers)) |
||
271 | blockers &= ~plus7dir[KingSQ(enemy)]; |
||
272 | if (plus9dir[KingSQ(enemy)] & blockers && |
||
273 | !(plus9dir[KingSQ(enemy)] & checkers)) |
||
274 | blockers &= ~plus9dir[KingSQ(enemy)]; |
||
275 | if (minus7dir[KingSQ(enemy)] & blockers && |
||
276 | !(minus7dir[KingSQ(enemy)] & checkers)) |
||
277 | blockers &= ~minus7dir[KingSQ(enemy)]; |
||
278 | if (minus9dir[KingSQ(enemy)] & blockers && |
||
279 | !(minus9dir[KingSQ(enemy)] & checkers)) |
||
280 | blockers &= ~minus9dir[KingSQ(enemy)]; |
||
281 | target = ~OccupiedSquares; |
||
282 | /* |
||
283 | ************************************************************ |
||
284 | * * |
||
285 | * Knight discovered checks. * |
||
286 | * * |
||
287 | ************************************************************ |
||
288 | */ |
||
289 | temp_target = target & ~knight_attacks[KingSQ(enemy)]; |
||
290 | for (piecebd = Knights(side) & blockers; piecebd; Clear(from, piecebd)) { |
||
108 | pmbaty | 291 | from = MostAdvanced(side, piecebd); |
33 | pmbaty | 292 | moves = knight_attacks[from] & temp_target; |
293 | temp = from + (knight << 12); |
||
294 | Extract(side, move, moves, temp); |
||
295 | } |
||
296 | /* |
||
297 | ************************************************************ |
||
298 | * * |
||
299 | * Rook discovered checks. * |
||
300 | * * |
||
301 | ************************************************************ |
||
302 | */ |
||
303 | target = ~OccupiedSquares; |
||
304 | temp_target = target & ~RookAttacks(KingSQ(enemy), OccupiedSquares); |
||
305 | for (piecebd = Rooks(side) & blockers; piecebd; Clear(from, piecebd)) { |
||
108 | pmbaty | 306 | from = MostAdvanced(side, piecebd); |
33 | pmbaty | 307 | moves = RookAttacks(from, OccupiedSquares) & temp_target; |
308 | temp = from + (rook << 12); |
||
309 | Extract(side, move, moves, temp); |
||
310 | } |
||
311 | /* |
||
312 | ************************************************************ |
||
313 | * * |
||
314 | * Pawn discovered checks. * |
||
315 | * * |
||
316 | ************************************************************ |
||
317 | */ |
||
318 | piecebd = |
||
319 | Pawns(side) & blockers & ((side) ? ~OccupiedSquares >> 8 : |
||
320 | ~OccupiedSquares << 8); |
||
321 | for (; piecebd; Clear(from, piecebd)) { |
||
108 | pmbaty | 322 | from = MostAdvanced(side, piecebd); |
33 | pmbaty | 323 | to = from + pawnadv1[enemy]; |
324 | if ((side) ? to > 55 : to < 8) |
||
325 | promote = queen; |
||
326 | else |
||
327 | promote = 0; |
||
328 | *move++ = from | (to << 6) | (pawn << 12) | (promote << 18); |
||
329 | } |
||
330 | } |
||
331 | } |
||
332 | /* |
||
333 | ************************************************************ |
||
334 | * * |
||
335 | * Next, we look for rank/file discovered attacks. Once * |
||
336 | * we know which squares hold pieces that create a * |
||
337 | * discovered check when they move, we generate them * |
||
338 | * piece type by piece type. * |
||
339 | * * |
||
340 | ************************************************************ |
||
341 | */ |
||
342 | blockers = |
||
343 | RookAttacks(KingSQ(enemy), |
||
344 | OccupiedSquares) & (Bishops(side) | Knights(side) | (Pawns(side) & |
||
345 | rank_mask[Rank(KingSQ(enemy))])); |
||
346 | if (blockers) { |
||
347 | checkers = |
||
348 | RookAttacks(KingSQ(enemy), |
||
349 | OccupiedSquares & ~blockers) & (Rooks(side) | Queens(side)); |
||
350 | if (checkers) { |
||
351 | if (plus1dir[KingSQ(enemy)] & blockers && |
||
352 | !(plus1dir[KingSQ(enemy)] & checkers)) |
||
353 | blockers &= ~plus1dir[KingSQ(enemy)]; |
||
354 | if (plus8dir[KingSQ(enemy)] & blockers && |
||
355 | !(plus8dir[KingSQ(enemy)] & checkers)) |
||
356 | blockers &= ~plus8dir[KingSQ(enemy)]; |
||
357 | if (minus1dir[KingSQ(enemy)] & blockers && |
||
358 | !(minus1dir[KingSQ(enemy)] & checkers)) |
||
359 | blockers &= ~minus1dir[KingSQ(enemy)]; |
||
360 | if (minus8dir[KingSQ(enemy)] & blockers && |
||
361 | !(minus8dir[KingSQ(enemy)] & checkers)) |
||
362 | blockers &= ~minus8dir[KingSQ(enemy)]; |
||
363 | target = ~OccupiedSquares; |
||
364 | /* |
||
365 | ************************************************************ |
||
366 | * * |
||
367 | * Knight discovered checks. * |
||
368 | * * |
||
369 | ************************************************************ |
||
370 | */ |
||
371 | temp_target = target & ~knight_attacks[KingSQ(enemy)]; |
||
372 | for (piecebd = Knights(side) & blockers; piecebd; Clear(from, piecebd)) { |
||
108 | pmbaty | 373 | from = MostAdvanced(side, piecebd); |
33 | pmbaty | 374 | moves = knight_attacks[from] & temp_target; |
375 | temp = from + (knight << 12); |
||
376 | Extract(side, move, moves, temp); |
||
377 | } |
||
378 | /* |
||
379 | ************************************************************ |
||
380 | * * |
||
381 | * Bishop discovered checks. * |
||
382 | * * |
||
383 | ************************************************************ |
||
384 | */ |
||
385 | target = ~OccupiedSquares; |
||
386 | temp_target = target & ~BishopAttacks(KingSQ(enemy), OccupiedSquares); |
||
387 | for (piecebd = Bishops(side) & blockers; piecebd; Clear(from, piecebd)) { |
||
108 | pmbaty | 388 | from = MostAdvanced(side, piecebd); |
33 | pmbaty | 389 | moves = BishopAttacks(from, OccupiedSquares) & temp_target; |
390 | temp = from + (bishop << 12); |
||
391 | Extract(side, move, moves, temp); |
||
392 | } |
||
393 | /* |
||
394 | ************************************************************ |
||
395 | * * |
||
396 | * Pawn discovered checks. * |
||
397 | * * |
||
398 | ************************************************************ |
||
399 | */ |
||
400 | piecebd = |
||
401 | Pawns(side) & blockers & ((side) ? ~OccupiedSquares >> 8 : |
||
402 | ~OccupiedSquares << 8); |
||
403 | for (; piecebd; Clear(from, piecebd)) { |
||
108 | pmbaty | 404 | from = MostAdvanced(side, piecebd); |
33 | pmbaty | 405 | to = from + pawnadv1[enemy]; |
406 | if ((side) ? to > 55 : to < 8) |
||
407 | promote = queen; |
||
408 | else |
||
409 | promote = 0; |
||
410 | *move++ = from | (to << 6) | (pawn << 12) | (promote << 18); |
||
411 | } |
||
412 | } |
||
413 | } |
||
414 | return move; |
||
415 | } |
||
416 | |||
108 | pmbaty | 417 | /* modified 12/31/15 */ |
33 | pmbaty | 418 | /* |
419 | ******************************************************************************* |
||
420 | * * |
||
421 | * GenerateCheckEvasions() is used to generate moves when the king is in * |
||
422 | * check. * |
||
423 | * * |
||
424 | * Three types of check-evasion moves are generated: * |
||
425 | * * |
||
426 | * (1) Generate king moves to squares that are not attacked by the * |
||
427 | * opponent's pieces. This includes capture and non-capture moves. * |
||
428 | * * |
||
429 | * (2) Generate interpositions along the rank/file that the checking attack * |
||
430 | * is coming along (assuming (a) only one piece is checking the king, and * |
||
431 | * (b) the checking piece is a sliding piece [bishop, rook, queen]). * |
||
432 | * * |
||
433 | * (3) Generate capture moves, but only to the square(s) that are giving * |
||
434 | * check. Captures are a special case. If there is one checking piece, * |
||
435 | * then capturing it by any piece is tried. If there are two pieces * |
||
436 | * checking the king, then the only legal capture to try is for the king to * |
||
437 | * capture one of the checking pieces that is on an unattacked square. * |
||
438 | * * |
||
439 | ******************************************************************************* |
||
440 | */ |
||
108 | pmbaty | 441 | unsigned *GenerateCheckEvasions(TREE * RESTRICT tree, int ply, int side, |
442 | unsigned *move) { |
||
443 | uint64_t target, targetc, targetp, piecebd, moves, empty, checksqs; |
||
444 | uint64_t padvances1, padvances2, pcapturesl, pcapturesr, padvances1_all; |
||
445 | int from, to, temp, common, enemy = Flip(side), king_square, checkers; |
||
446 | int checking_square, check_direction1 = 0, check_direction2 = 0; |
||
33 | pmbaty | 447 | |
448 | /* |
||
449 | ************************************************************ |
||
450 | * * |
||
451 | * First, determine how many pieces are attacking the king * |
||
452 | * and where they are, so we can figure out how to legally * |
||
453 | * get out of check. * |
||
454 | * * |
||
455 | ************************************************************ |
||
456 | */ |
||
457 | king_square = KingSQ(side); |
||
458 | checksqs = AttacksTo(tree, king_square) & Occupied(enemy); |
||
459 | checkers = PopCnt(checksqs); |
||
460 | if (checkers == 1) { |
||
461 | checking_square = LSB(checksqs); |
||
462 | if (PcOnSq(checking_square) != pieces[enemy][pawn]) |
||
463 | check_direction1 = directions[checking_square][king_square]; |
||
464 | target = InterposeSquares(king_square, checking_square); |
||
465 | target |= checksqs; |
||
466 | target |= Kings(enemy); |
||
467 | } else { |
||
468 | target = Kings(enemy); |
||
469 | checking_square = LSB(checksqs); |
||
470 | if (PcOnSq(checking_square) != pieces[enemy][pawn]) |
||
471 | check_direction1 = directions[checking_square][king_square]; |
||
472 | checking_square = MSB(checksqs); |
||
473 | if (PcOnSq(checking_square) != pieces[enemy][pawn]) |
||
474 | check_direction2 = directions[checking_square][king_square]; |
||
475 | } |
||
476 | /* |
||
477 | ************************************************************ |
||
478 | * * |
||
479 | * The next step is to produce the set of valid * |
||
480 | * destination squares. For king moves, this is simply * |
||
481 | * the set of squares that are not attacked by enemy * |
||
482 | * pieces (if there are any such squares.) * |
||
483 | * * |
||
484 | * Then, if the checking piece is not a knight, we need * |
||
485 | * to know the checking direction so that we can either * |
||
486 | * move the king off of that ray, or else block that ray. * |
||
487 | * * |
||
488 | * We produce king moves by locating the only king and * |
||
489 | * then using that <from> square as an index into the * |
||
490 | * precomputed king_attacks data. * |
||
491 | * * |
||
492 | ************************************************************ |
||
493 | */ |
||
494 | from = king_square; |
||
495 | temp = from + (king << 12); |
||
496 | for (moves = king_attacks[from] & ~Occupied(side); moves; Clear(to, moves)) { |
||
108 | pmbaty | 497 | to = MostAdvanced(side, moves); |
33 | pmbaty | 498 | if (!Attacks(tree, enemy, to) |
499 | && directions[from][to] != check_direction1 && |
||
500 | directions[from][to] != check_direction2) |
||
501 | *move++ = temp | (to << 6) | (Abs(PcOnSq(to)) << 15); |
||
502 | } |
||
503 | /* |
||
504 | ************************************************************ |
||
505 | * * |
||
506 | * We produce knight moves by locating the most advanced * |
||
507 | * knight and then using that <from> square as an index * |
||
508 | * into the precomputed knight_attacks data. We repeat * |
||
509 | * for each knight. * |
||
510 | * * |
||
511 | ************************************************************ |
||
512 | */ |
||
513 | if (checkers == 1) { |
||
514 | for (piecebd = Knights(side); piecebd; Clear(from, piecebd)) { |
||
108 | pmbaty | 515 | from = MostAdvanced(side, piecebd); |
33 | pmbaty | 516 | if (!PinnedOnKing(tree, side, from)) { |
517 | moves = knight_attacks[from] & target; |
||
518 | temp = from + (knight << 12); |
||
519 | Extract(side, move, moves, temp); |
||
520 | } |
||
521 | } |
||
522 | /* |
||
523 | ************************************************************ |
||
524 | * * |
||
108 | pmbaty | 525 | * We produce sliding piece moves by locating each piece * |
526 | * type in turn. We then start with the most advanced * |
||
527 | * piece and generate moves from that square. This uses * |
||
528 | * "magic move generation" to produce the destination * |
||
529 | * squares. * |
||
33 | pmbaty | 530 | * * |
531 | ************************************************************ |
||
532 | */ |
||
533 | for (piecebd = Bishops(side); piecebd; Clear(from, piecebd)) { |
||
108 | pmbaty | 534 | from = MostAdvanced(side, piecebd); |
33 | pmbaty | 535 | if (!PinnedOnKing(tree, side, from)) { |
536 | moves = BishopAttacks(from, OccupiedSquares) & target; |
||
537 | temp = from + (bishop << 12); |
||
538 | Extract(side, move, moves, temp); |
||
539 | } |
||
540 | } |
||
541 | for (piecebd = Rooks(side); piecebd; Clear(from, piecebd)) { |
||
108 | pmbaty | 542 | from = MostAdvanced(side, piecebd); |
33 | pmbaty | 543 | if (!PinnedOnKing(tree, side, from)) { |
544 | moves = RookAttacks(from, OccupiedSquares) & target; |
||
545 | temp = from + (rook << 12); |
||
546 | Extract(side, move, moves, temp); |
||
547 | } |
||
548 | } |
||
549 | for (piecebd = Queens(side); piecebd; Clear(from, piecebd)) { |
||
108 | pmbaty | 550 | from = MostAdvanced(side, piecebd); |
33 | pmbaty | 551 | if (!PinnedOnKing(tree, side, from)) { |
552 | moves = QueenAttacks(from, OccupiedSquares) & target; |
||
553 | temp = from + (queen << 12); |
||
554 | Extract(side, move, moves, temp); |
||
555 | } |
||
556 | } |
||
557 | /* |
||
558 | ************************************************************ |
||
559 | * * |
||
560 | * Now, produce pawn moves. This is done differently due * |
||
561 | * to inconsistencies in the way a pawn moves when it * |
||
562 | * captures as opposed to normal non-capturing moves. * |
||
563 | * Another exception is capturing enpassant. The first * |
||
564 | * step is to generate all possible pawn moves. We do * |
||
565 | * this in 2 operations: (1) shift the pawns forward one * |
||
566 | * rank then AND with empty squares; (2) shift the pawns * |
||
567 | * forward two ranks and then AND with empty squares. * |
||
568 | * * |
||
569 | ************************************************************ |
||
570 | */ |
||
571 | empty = ~OccupiedSquares; |
||
572 | targetp = target & empty; |
||
573 | if (side) { |
||
574 | padvances1 = Pawns(white) << 8 & targetp; |
||
575 | padvances1_all = Pawns(white) << 8 & empty; |
||
576 | padvances2 = ((padvances1_all & ((uint64_t) 255 << 16)) << 8) & targetp; |
||
577 | } else { |
||
578 | padvances1 = Pawns(black) >> 8 & targetp; |
||
579 | padvances1_all = Pawns(black) >> 8 & empty; |
||
580 | padvances2 = ((padvances1_all & ((uint64_t) 255 << 40)) >> 8) & targetp; |
||
581 | } |
||
582 | /* |
||
583 | ************************************************************ |
||
584 | * * |
||
585 | * Now that we got 'em, we simply enumerate the to squares * |
||
586 | * as before, but in four steps since we have four sets of * |
||
587 | * potential moves. * |
||
588 | * * |
||
589 | ************************************************************ |
||
590 | */ |
||
591 | for (; padvances2; Clear(to, padvances2)) { |
||
108 | pmbaty | 592 | to = MostAdvanced(side, padvances2); |
33 | pmbaty | 593 | if (!PinnedOnKing(tree, side, to + pawnadv2[side])) |
594 | *move++ = (to + pawnadv2[side]) | (to << 6) | (pawn << 12); |
||
595 | } |
||
596 | for (; padvances1; Clear(to, padvances1)) { |
||
108 | pmbaty | 597 | to = MostAdvanced(side, padvances1); |
33 | pmbaty | 598 | if (!PinnedOnKing(tree, side, to + pawnadv1[side])) { |
599 | common = (to + pawnadv1[side]) | (to << 6) | (pawn << 12); |
||
600 | if ((side) ? to < 56 : to > 7) |
||
601 | *move++ = common; |
||
602 | else { |
||
603 | *move++ = common | (queen << 18); |
||
604 | *move++ = common | (knight << 18); |
||
605 | } |
||
606 | } |
||
607 | } |
||
108 | pmbaty | 608 | /* |
609 | ************************************************************ |
||
610 | * * |
||
611 | * And then we try to see if the checking piece can be * |
||
612 | * captured by a friendly pawn. * |
||
613 | * * |
||
614 | ************************************************************ |
||
615 | */ |
||
33 | pmbaty | 616 | targetc = Occupied(enemy) | EnPassantTarget(ply); |
617 | targetc = targetc & target; |
||
618 | if (Pawns(enemy) & target & ((side) ? EnPassantTarget(ply) >> 8 : |
||
619 | EnPassantTarget(ply) << 8)) |
||
620 | targetc = targetc | EnPassantTarget(ply); |
||
621 | if (side) { |
||
622 | pcapturesl = (Pawns(white) & mask_left_edge) << 7 & targetc; |
||
623 | pcapturesr = (Pawns(white) & mask_right_edge) << 9 & targetc; |
||
624 | } else { |
||
625 | pcapturesl = (Pawns(black) & mask_left_edge) >> 9 & targetc; |
||
626 | pcapturesr = (Pawns(black) & mask_right_edge) >> 7 & targetc; |
||
627 | } |
||
628 | for (; pcapturesl; Clear(to, pcapturesl)) { |
||
108 | pmbaty | 629 | to = MostAdvanced(side, pcapturesl); |
33 | pmbaty | 630 | if (!PinnedOnKing(tree, side, to + capleft[side])) { |
631 | common = (to + capleft[side]) | (to << 6) | (pawn << 12); |
||
632 | if ((side) ? to < 56 : to > 7) |
||
633 | *move++ = common | (((PcOnSq(to)) ? Abs(PcOnSq(to)) : pawn) << 15); |
||
634 | else { |
||
635 | *move++ = common | Abs(PcOnSq(to)) << 15 | queen << 18; |
||
636 | *move++ = common | Abs(PcOnSq(to)) << 15 | knight << 18; |
||
637 | } |
||
638 | } |
||
639 | } |
||
640 | for (; pcapturesr; Clear(to, pcapturesr)) { |
||
108 | pmbaty | 641 | to = MostAdvanced(side, pcapturesr); |
33 | pmbaty | 642 | if (!PinnedOnKing(tree, side, to + capright[side])) { |
643 | common = (to + capright[side]) | (to << 6) | (pawn << 12); |
||
644 | if ((side) ? to < 56 : to > 7) |
||
645 | *move++ = common | (((PcOnSq(to)) ? Abs(PcOnSq(to)) : pawn) << 15); |
||
646 | else { |
||
647 | *move++ = common | Abs(PcOnSq(to)) << 15 | queen << 18; |
||
648 | *move++ = common | Abs(PcOnSq(to)) << 15 | knight << 18; |
||
649 | } |
||
650 | } |
||
651 | } |
||
652 | } |
||
653 | return move; |
||
654 | } |
||
655 | |||
108 | pmbaty | 656 | /* modified 12/31/15 */ |
33 | pmbaty | 657 | /* |
658 | ******************************************************************************* |
||
659 | * * |
||
660 | * GenerateNoncaptures() is used to generate non-capture moves from the * |
||
661 | * current position. * |
||
662 | * * |
||
663 | * Once the valid destination squares are known, we have to locate a * |
||
108 | pmbaty | 664 | * friendly piece to compute the squares it attacks. * |
33 | pmbaty | 665 | * * |
666 | * Pawns are handled differently. Regular pawn moves are produced by * |
||
667 | * shifting the pawn bitmap 8 bits "forward" and anding this with the * |
||
108 | pmbaty | 668 | * complement of the occupied squares bitmap double advances are then * |
33 | pmbaty | 669 | * produced by anding the pawn bitmap with a mask containing 1's on the * |
670 | * second rank, shifting this 16 bits "forward" and then anding this with * |
||
671 | * the complement of the occupied squares bitmap as before. If [to] reaches * |
||
108 | pmbaty | 672 | * the 8th rank, we produce a set of three moves, promoting the pawn to * |
673 | * knight, bishop and rook (queen promotions were generated earlier by * |
||
674 | * GenerateCaptures()). * |
||
33 | pmbaty | 675 | * * |
676 | ******************************************************************************* |
||
677 | */ |
||
108 | pmbaty | 678 | unsigned *GenerateNoncaptures(TREE * RESTRICT tree, int ply, int side, |
679 | unsigned *move) { |
||
33 | pmbaty | 680 | uint64_t target, piecebd, moves; |
681 | uint64_t padvances1, padvances2, pcapturesl, pcapturesr; |
||
682 | int from, to, temp, common, enemy = Flip(side); |
||
683 | |||
684 | /* |
||
685 | ************************************************************ |
||
686 | * * |
||
108 | pmbaty | 687 | * First, produce castling moves when they are legal. * |
33 | pmbaty | 688 | * * |
689 | ************************************************************ |
||
690 | */ |
||
691 | if (Castle(ply, side) > 0) { |
||
692 | if (Castle(ply, side) & 1 && !(OccupiedSquares & OO[side]) |
||
693 | && !Attacks(tree, enemy, OOsqs[side][0]) |
||
694 | && !Attacks(tree, enemy, OOsqs[side][1]) |
||
695 | && !Attacks(tree, enemy, OOsqs[side][2])) { |
||
696 | *move++ = (king << 12) + (OOto[side] << 6) + OOfrom[side]; |
||
697 | } |
||
698 | if (Castle(ply, side) & 2 && !(OccupiedSquares & OOO[side]) |
||
699 | && !Attacks(tree, enemy, OOOsqs[side][0]) |
||
700 | && !Attacks(tree, enemy, OOOsqs[side][1]) |
||
701 | && !Attacks(tree, enemy, OOOsqs[side][2])) { |
||
702 | *move++ = (king << 12) + (OOOto[side] << 6) + OOfrom[side]; |
||
703 | } |
||
704 | } |
||
705 | target = ~OccupiedSquares; |
||
706 | /* |
||
707 | ************************************************************ |
||
708 | * * |
||
709 | * We produce knight moves by locating the most advanced * |
||
710 | * knight and then using that <from> square as an index * |
||
711 | * into the precomputed knight_attacks data. We repeat * |
||
712 | * for each knight. * |
||
713 | * * |
||
714 | ************************************************************ |
||
715 | */ |
||
716 | for (piecebd = Knights(side); piecebd; Clear(from, piecebd)) { |
||
108 | pmbaty | 717 | from = MostAdvanced(side, piecebd); |
33 | pmbaty | 718 | moves = knight_attacks[from] & target; |
719 | temp = from + (knight << 12); |
||
720 | Extract(side, move, moves, temp); |
||
721 | } |
||
722 | /* |
||
723 | ************************************************************ |
||
724 | * * |
||
108 | pmbaty | 725 | * We produce sliding piece moves by locating each piece * |
726 | * type in turn. We then start with the most advanced * |
||
727 | * piece and generate moves from that square. This uses * |
||
728 | * "magic move generation" to produce the destination * |
||
729 | * squares. * |
||
33 | pmbaty | 730 | * * |
731 | ************************************************************ |
||
732 | */ |
||
733 | for (piecebd = Bishops(side); piecebd; Clear(from, piecebd)) { |
||
108 | pmbaty | 734 | from = MostAdvanced(side, piecebd); |
33 | pmbaty | 735 | moves = BishopAttacks(from, OccupiedSquares) & target; |
736 | temp = from + (bishop << 12); |
||
737 | Extract(side, move, moves, temp); |
||
738 | } |
||
739 | for (piecebd = Rooks(side); piecebd; Clear(from, piecebd)) { |
||
108 | pmbaty | 740 | from = MostAdvanced(side, piecebd); |
33 | pmbaty | 741 | moves = RookAttacks(from, OccupiedSquares) & target; |
742 | temp = from + (rook << 12); |
||
743 | Extract(side, move, moves, temp); |
||
744 | } |
||
745 | for (piecebd = Queens(side); piecebd; Clear(from, piecebd)) { |
||
108 | pmbaty | 746 | from = MostAdvanced(side, piecebd); |
33 | pmbaty | 747 | moves = QueenAttacks(from, OccupiedSquares) & target; |
748 | temp = from + (queen << 12); |
||
749 | Extract(side, move, moves, temp); |
||
750 | } |
||
751 | /* |
||
752 | ************************************************************ |
||
753 | * * |
||
754 | * We produce king moves by locating the only king and * |
||
755 | * then using that <from> square as an index into the * |
||
756 | * precomputed king_attacks data. * |
||
757 | * * |
||
758 | ************************************************************ |
||
759 | */ |
||
760 | from = KingSQ(side); |
||
761 | moves = king_attacks[from] & target; |
||
762 | temp = from + (king << 12); |
||
763 | Extract(side, move, moves, temp); |
||
764 | /* |
||
765 | ************************************************************ |
||
766 | * * |
||
767 | * Now, produce pawn moves. This is done differently due * |
||
768 | * to inconsistencies in the way a pawn moves when it * |
||
769 | * captures as opposed to normal non-capturing moves. * |
||
770 | * First we generate all possible pawn moves. We do this * |
||
771 | * in 4 operations: (1) shift the pawns forward one rank * |
||
772 | * then and with empty squares; (2) shift the pawns * |
||
773 | * forward two ranks and then and with empty squares; * |
||
774 | * (3) remove the a-pawn(s) then shift the pawns * |
||
775 | * diagonally left then and with enemy occupied squares; * |
||
776 | * (4) remove the h-pawn(s) then shift the pawns * |
||
777 | * diagonally right then and with enemy occupied squares. * |
||
778 | * note that the only captures produced are under- * |
||
779 | * promotions, because the rest were done in GenCap. * |
||
780 | * * |
||
781 | ************************************************************ |
||
782 | */ |
||
783 | padvances1 = ((side) ? Pawns(side) << 8 : Pawns(side) >> 8) & target; |
||
784 | padvances2 = |
||
785 | ((side) ? (padvances1 & mask_advance_2_w) << 8 : (padvances1 & |
||
786 | mask_advance_2_b) >> 8) & target; |
||
787 | /* |
||
788 | ************************************************************ |
||
789 | * * |
||
790 | * Now that we got 'em, we simply enumerate the to * |
||
791 | * squares as before, but in four steps since we have * |
||
792 | * four sets of potential moves. * |
||
793 | * * |
||
794 | ************************************************************ |
||
795 | */ |
||
796 | for (; padvances2; Clear(to, padvances2)) { |
||
108 | pmbaty | 797 | to = MostAdvanced(side, padvances2); |
33 | pmbaty | 798 | *move++ = (to + pawnadv2[side]) | (to << 6) | (pawn << 12); |
799 | } |
||
800 | for (; padvances1; Clear(to, padvances1)) { |
||
108 | pmbaty | 801 | to = MostAdvanced(side, padvances1); |
33 | pmbaty | 802 | common = (to + pawnadv1[side]) | (to << 6) | (pawn << 12); |
803 | if ((side) ? to < 56 : to > 7) |
||
804 | *move++ = common; |
||
805 | else { |
||
806 | *move++ = common | (rook << 18); |
||
807 | *move++ = common | (bishop << 18); |
||
808 | *move++ = common | (knight << 18); |
||
809 | } |
||
810 | } |
||
811 | /* |
||
812 | ************************************************************ |
||
813 | * * |
||
108 | pmbaty | 814 | * Generate the rest of the promotions here since * |
815 | * GenerateCaptures() only generated captures or * |
||
33 | pmbaty | 816 | * promotions to a queen. * |
817 | * * |
||
818 | ************************************************************ |
||
819 | */ |
||
108 | pmbaty | 820 | target = Occupied(enemy) & rank_mask[rank8[side]]; |
33 | pmbaty | 821 | pcapturesl = |
822 | ((side) ? (Pawns(white) & mask_left_edge) << 7 : (Pawns(black) & |
||
823 | mask_left_edge) >> 9) & target; |
||
824 | for (; pcapturesl; Clear(to, pcapturesl)) { |
||
108 | pmbaty | 825 | to = MostAdvanced(side, pcapturesl); |
33 | pmbaty | 826 | common = (to + capleft[side]) | (to << 6) | (pawn << 12); |
827 | *move++ = common | (Abs(PcOnSq(to)) << 15) | (rook << 18); |
||
828 | *move++ = common | (Abs(PcOnSq(to)) << 15) | (bishop << 18); |
||
829 | *move++ = common | (Abs(PcOnSq(to)) << 15) | (knight << 18); |
||
830 | } |
||
831 | pcapturesr = |
||
832 | ((side) ? (Pawns(white) & mask_right_edge) << 9 : (Pawns(black) & |
||
833 | mask_right_edge) >> 7) & target; |
||
834 | for (; pcapturesr; Clear(to, pcapturesr)) { |
||
108 | pmbaty | 835 | to = MostAdvanced(side, pcapturesr); |
33 | pmbaty | 836 | common = (to + capright[side]) | (to << 6) | (pawn << 12); |
837 | *move++ = common | (Abs(PcOnSq(to)) << 15) | (rook << 18); |
||
838 | *move++ = common | (Abs(PcOnSq(to)) << 15) | (bishop << 18); |
||
839 | *move++ = common | (Abs(PcOnSq(to)) << 15) | (knight << 18); |
||
840 | } |
||
841 | return move; |
||
842 | } |
||
843 | |||
108 | pmbaty | 844 | /* modified 12/31/15 */ |
33 | pmbaty | 845 | /* |
846 | ******************************************************************************* |
||
847 | * * |
||
848 | * PinnedOnKing() is used to determine if the piece on <square> is pinned * |
||
849 | * against the king, so that it's illegal to move it. This is used to cull * |
||
850 | * potential moves by GenerateCheckEvasions() so that illegal moves are not * |
||
851 | * produced. * |
||
852 | * * |
||
853 | ******************************************************************************* |
||
854 | */ |
||
855 | int PinnedOnKing(TREE * RESTRICT tree, int side, int square) { |
||
108 | pmbaty | 856 | int ray, enemy = Flip(side); |
33 | pmbaty | 857 | |
858 | /* |
||
859 | ************************************************************ |
||
860 | * * |
||
861 | * First, determine if the piece being moved is on the * |
||
862 | * same diagonal, rank or file as the king. If not, then * |
||
863 | * it can't be pinned and we return (0). * |
||
864 | * * |
||
865 | ************************************************************ |
||
866 | */ |
||
867 | ray = directions[square][KingSQ(side)]; |
||
868 | if (!ray) |
||
869 | return 0; |
||
870 | /* |
||
871 | ************************************************************ |
||
872 | * * |
||
873 | * If they are on the same ray, then determine if the king * |
||
874 | * blocks a bishop attack in one direction from this * |
||
875 | * square and a bishop or queen blocks a bishop attack on * |
||
876 | * the same diagonal in the opposite direction (or the * |
||
877 | * same rank/file for rook/queen.) * |
||
878 | * * |
||
879 | ************************************************************ |
||
880 | */ |
||
881 | switch (Abs(ray)) { |
||
882 | case 1: |
||
883 | if (RankAttacks(square) & Kings(side)) |
||
884 | return (RankAttacks(square) & (Rooks(enemy) | Queens(enemy))) != 0; |
||
885 | else |
||
886 | return 0; |
||
887 | case 7: |
||
888 | if (Diagh1Attacks(square) & Kings(side)) |
||
889 | return (Diagh1Attacks(square) & (Bishops(enemy) | Queens(enemy))) != |
||
890 | 0; |
||
891 | else |
||
892 | return 0; |
||
893 | case 8: |
||
894 | if (FileAttacks(square) & Kings(side)) |
||
895 | return (FileAttacks(square) & (Rooks(enemy) | Queens(enemy))) != 0; |
||
896 | else |
||
897 | return 0; |
||
898 | case 9: |
||
899 | if (Diaga1Attacks(square) & Kings(side)) |
||
900 | return (Diaga1Attacks(square) & (Bishops(enemy) | Queens(enemy))) != |
||
901 | 0; |
||
902 | else |
||
903 | return 0; |
||
904 | } |
||
905 | return 0; |
||
906 | } |