|
| 1 | +#pragma once |
| 2 | + |
| 3 | +#include <bitbishop/attacks/bishop_attacks.hpp> |
| 4 | +#include <bitbishop/board.hpp> |
| 5 | +#include <bitbishop/color.hpp> |
| 6 | +#include <bitbishop/move.hpp> |
| 7 | +#include <bitbishop/movegen/pins.hpp> |
| 8 | +#include <utility> |
| 9 | +#include <vector> |
| 10 | + |
| 11 | +/** |
| 12 | + * @brief Generate all legal bishop moves for the side to move. |
| 13 | + * |
| 14 | + * This function enumerates every bishop belonging to the given side and |
| 15 | + * generates all legal destination squares, taking into account: |
| 16 | + * |
| 17 | + * - Sliding attacks along diagonals |
| 18 | + * - Friendly piece blocking |
| 19 | + * - Enemy captures |
| 20 | + * - Active check constraints via @p check_mask |
| 21 | + * - Absolute pins via @p pins |
| 22 | + * |
| 23 | + * The resulting moves are appended to @p moves. Existing contents are |
| 24 | + * preserved. |
| 25 | + * |
| 26 | + * @param[out] moves |
| 27 | + * Vector to which generated bishop moves will be appended. |
| 28 | + * |
| 29 | + * @param[in] board |
| 30 | + * Current board position. |
| 31 | + * |
| 32 | + * @param[in] us |
| 33 | + * Side to generate bishop moves for. |
| 34 | + * |
| 35 | + * @param[in] check_mask |
| 36 | + * Bitboard restricting legal move destinations when the king is in check. |
| 37 | + * Only moves intersecting this mask are generated. |
| 38 | + * |
| 39 | + * @param[in] pins |
| 40 | + * Precomputed pin information. If a bishop is absolutely pinned, its legal |
| 41 | + * moves are restricted to the corresponding pin ray. |
| 42 | + * |
| 43 | + * @note |
| 44 | + * - This function assumes that @p check_mask and @p pins have already been |
| 45 | + * computed for the current position. |
| 46 | + */ |
| 47 | +void generate_bishop_legal_moves(std::vector<Move>& moves, const Board& board, Color us, const Bitboard& check_mask, |
| 48 | + const PinResult& pins) { |
| 49 | + const Bitboard own = board.friendly(us); |
| 50 | + const Bitboard enemy = board.enemy(us); |
| 51 | + const Bitboard occupied = board.occupied(); |
| 52 | + Bitboard bishops = board.bishops(us); |
| 53 | + |
| 54 | + // warning: this loop is destructive on Bitboard bishops |
| 55 | + while (auto from_opt = bishops.pop_lsb()) { |
| 56 | + Square from = from_opt.value(); |
| 57 | + |
| 58 | + Bitboard candidates = bishop_attacks(from, occupied); |
| 59 | + candidates &= ~own; |
| 60 | + candidates &= check_mask; |
| 61 | + if (pins.pinned.test(from)) { |
| 62 | + candidates &= pins.pin_ray[from.value()]; |
| 63 | + } |
| 64 | + |
| 65 | + for (Square to : candidates) { |
| 66 | + const bool is_capture = enemy.test(to); |
| 67 | + moves.emplace_back(from, to, std::nullopt, is_capture, false, false); |
| 68 | + } |
| 69 | + } |
| 70 | +} |
0 commit comments