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