|
| 1 | +#pragma once |
| 2 | + |
| 3 | +#include <bitbishop/attacks/generate_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 Generates all legal castling moves for the given side. |
| 13 | + * |
| 14 | + * Adds king-side and queen-side castling moves if and only if: |
| 15 | + * - The side is not currently in check |
| 16 | + * - The corresponding castling right is available |
| 17 | + * - The king and rook are on their initial squares |
| 18 | + * - All squares between the king and rook are empty |
| 19 | + * - The squares the king passes through and lands on are not attacked |
| 20 | + * |
| 21 | + * This function does not move any pieces. Castling is emitted as a king move |
| 22 | + * with the castling flag set; rook movement is handled during move execution. |
| 23 | + * |
| 24 | + * @param moves Vector to append generated castling moves to |
| 25 | + * @param board Current board position |
| 26 | + * @param us Color of the side to generate castling moves for |
| 27 | + * @param checkers Bitboard of pieces currently checking the king |
| 28 | + * @param enemy_attacks Bitboard of squares attacked by the opponent |
| 29 | + */ |
| 30 | +void generate_castling_moves(std::vector<Move>& moves, const Board& board, Color us, const Bitboard& checkers, |
| 31 | + const Bitboard& enemy_attacks) { |
| 32 | + using namespace Squares; |
| 33 | + |
| 34 | + if (checkers.any()) { |
| 35 | + return; |
| 36 | + } |
| 37 | + |
| 38 | + const Square king_from = (us == Color::WHITE) ? E1 : E8; |
| 39 | + |
| 40 | + if (board.can_castle_kingside(us)) { |
| 41 | + Square f_square = (us == Color::WHITE) ? F1 : F8; |
| 42 | + Square g_square = (us == Color::WHITE) ? G1 : G8; |
| 43 | + |
| 44 | + if (!enemy_attacks.test(f_square) && !enemy_attacks.test(g_square)) { |
| 45 | + moves.emplace_back(king_from, g_square, std::nullopt, false, false, true); |
| 46 | + } |
| 47 | + } |
| 48 | + |
| 49 | + if (board.can_castle_queenside(us)) { |
| 50 | + Square d_square = (us == Color::WHITE) ? D1 : D8; |
| 51 | + Square c_square = (us == Color::WHITE) ? C1 : C8; |
| 52 | + |
| 53 | + if (!enemy_attacks.test(d_square) && !enemy_attacks.test(c_square)) { |
| 54 | + moves.emplace_back(king_from, c_square, std::nullopt, false, false, true); |
| 55 | + } |
| 56 | + } |
| 57 | +} |
0 commit comments