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 | } |