MoveStack* generate<EVASIONS>(const Position& pos, MoveStack* mlist) { assert(pos.checkers()); Square from, checksq; int checkersCnt = 0; Color us = pos.side_to_move(); Square ksq = pos.king_square(us); Bitboard sliderAttacks = 0; Bitboard b = pos.checkers(); assert(pos.checkers()); // Find squares attacked by slider checkers, we will remove them from the king // evasions so to skip known illegal moves avoiding useless legality check later. do { checkersCnt++; checksq = pop_lsb(&b); assert(color_of(pos.piece_on(checksq)) == ~us); switch (type_of(pos.piece_on(checksq))) { case BISHOP: sliderAttacks |= PseudoAttacks[BISHOP][checksq]; break; case ROOK: sliderAttacks |= PseudoAttacks[ROOK][checksq]; break; case QUEEN: // If queen and king are far or not on a diagonal line we can safely // remove all the squares attacked in the other direction becuase are // not reachable by the king anyway. if (between_bb(ksq, checksq) || !(PseudoAttacks[BISHOP][checksq] & ksq)) sliderAttacks |= PseudoAttacks[QUEEN][checksq]; // Otherwise we need to use real rook attacks to check if king is safe // to move in the other direction. For example: king in B2, queen in A1 // a knight in B1, and we can safely move to C1. else sliderAttacks |= PseudoAttacks[BISHOP][checksq] | pos.attacks_from<ROOK>(checksq); default: break; } } while (b); // Generate evasions for king, capture and non capture moves b = pos.attacks_from<KING>(ksq) & ~pos.pieces(us) & ~sliderAttacks; from = ksq; SERIALIZE(b); if (checkersCnt > 1) return mlist; // Double check, only a king move can save the day // Generate blocking evasions or captures of the checking piece Bitboard target = between_bb(checksq, ksq) | pos.checkers(); return generate_all<EVASIONS>(pos, mlist, us, target); }
ExtMove* generate<EVASIONS>(const Position& pos, ExtMove* moveList) { assert(pos.checkers()); Color us = pos.side_to_move(); Square ksq = pos.square<KING>(us); Bitboard sliderAttacks = 0; Bitboard sliders = pos.checkers() & ~pos.pieces(KNIGHT, PAWN); // Find all the squares attacked by slider checkers. We will remove them from // the king evasions in order to skip known illegal moves, which avoids any // useless legality checks later on. while (sliders) { Square checksq = pop_lsb(&sliders); sliderAttacks |= LineBB[checksq][ksq] ^ checksq; } // Generate evasions for king, capture and non capture moves Bitboard b = pos.attacks_from<KING>(ksq) & ~pos.pieces(us) & ~sliderAttacks; while (b) *moveList++ = make_move(ksq, pop_lsb(&b)); if (more_than_one(pos.checkers())) return moveList; // Double check, only a king move can save the day // Generate blocking evasions or captures of the checking piece Square checksq = lsb(pos.checkers()); Bitboard target = between_bb(checksq, ksq) | checksq; return us == WHITE ? generate_all<WHITE, EVASIONS>(pos, moveList, target) : generate_all<BLACK, EVASIONS>(pos, moveList, target); }
ExtMove* generate<EVASIONS>(const Position& pos, ExtMove* mlist) { assert(pos.checkers()); int checkersCnt = 0; Color us = pos.side_to_move(); Square ksq = pos.king_square(us), from = ksq /* For SERIALIZE */, checksq; Bitboard sliderAttacks = 0; Bitboard b = pos.checkers(); assert(pos.checkers()); // Find all the squares attacked by slider checkers. We will remove them from // the king evasions in order to skip known illegal moves, which avoids any // useless legality checks later on. do { ++checkersCnt; checksq = pop_lsb(&b); assert(color_of(pos.piece_on(checksq)) == ~us); if (type_of(pos.piece_on(checksq)) > KNIGHT) // A slider sliderAttacks |= LineBB[checksq][ksq] ^ checksq; } while (b); // Generate evasions for king, capture and non capture moves b = pos.attacks_from<KING>(ksq) & ~pos.pieces(us) & ~sliderAttacks; SERIALIZE(b); if (checkersCnt > 1) return mlist; // Double check, only a king move can save the day // Generate blocking evasions or captures of the checking piece Bitboard target = between_bb(checksq, ksq) | checksq; return us == WHITE ? generate_all<WHITE, EVASIONS>(pos, mlist, target) : generate_all<BLACK, EVASIONS>(pos, mlist, target); }