#include "MoveGenerator.hpp" #include "Board.hpp" #include "BoardState.hpp" void MoveGenerator::generatePawnMoves(const BoardState &bs, const Square &from, const std::optional &eps, PieceColor color, MoveVec &moves) { BitBoard targets = 0; if (eps.has_value()) { targets |= BitBoard::fromIndex(eps.value().index()); } generatePawnMoves(bs, from, targets, color, moves); } void MoveGenerator::generatePawnMoves(const BoardState &bs, const Square &from, PieceColor color, MoveVec &moves) { generatePawnMoves(bs, from, BitBoard(0), color, moves); } void MoveGenerator::generatePawnMoves(const BoardState &bs, const Square &from, BitBoard targets, PieceColor color, MoveVec &moves) { auto fromBB = BitBoard::fromIndex(from.index()); targets |= *bs.pieceBBs[Board::toIndex(!color)]; BitBoard movesBB; if (color == PieceColor::White) { movesBB = BitBoard::pawnNorthAttacks(fromBB, targets) & ~*bs.pieceBBs[Board::toIndex(color)]; movesBB |= BitBoard::pawnNorthMoves(fromBB, ~bs.occupiedBB); } else { movesBB = BitBoard::pawnSouthAttacks(fromBB, targets) & ~*bs.pieceBBs[Board::toIndex(color)]; movesBB |= BitBoard::pawnSouthMoves(fromBB, ~bs.occupiedBB); } bool isPromotion = movesBB & (Rank1 | Rank8); if (isPromotion) { generateMovesWithPromotion(from, movesBB, moves); } else { generateMoves(from, movesBB, moves); } } void MoveGenerator::generateBishopMoves(const BoardState &bs, const Square &from, PieceColor color, MoveVec &moves) { auto fromBB = BitBoard::fromIndex(from.index()); auto movesBB = BitBoard::bishopAttacks(fromBB, ~bs.occupiedBB) & ~*bs.pieceBBs[Board::toIndex(color)]; generateMoves(from, movesBB, moves); } void MoveGenerator::generateMoves(const Square &from, BitBoard movesBB, MoveVec &moves) { while (movesBB) { auto to = Square(movesBB.pop()); moves.emplace_back(from, to, std::nullopt); } } void MoveGenerator::generateMovesWithPromotion(const Square &from, BitBoard movesBB, MoveVec &moves) { while (movesBB) { auto to = Square(movesBB.pop()); for (const auto &kItem : Piece::PromotionTypes) { moves.emplace_back(from, to, static_cast(kItem)); } } } void MoveGenerator::generateKingMoves(const BoardState &bs, const Square &from, PieceColor color, CastlingRights cr, MoveGenerator::MoveVec &moves) { auto fromBB = BitBoard::fromIndex(from.index()); auto movesBB = BitBoard::kingAttacks(fromBB) & ~*bs.pieceBBs[Board::toIndex(color)]; if ((cr & CastlingRights::All) != CastlingRights::None) { auto checkCR = CastlingRights::White; auto castlingRank = WhiteCastlingRank; if (color == PieceColor::Black) { checkCR = CastlingRights::Black; castlingRank = BlackCastlingRank; } checkCR &= cr; if (checkCR != CastlingRights::None) { // Generate attacked squares auto opponentBB = *bs.pieceBBs[Board::toIndex(!color)]; BitBoard target = CastlingRanks | bs.occupiedBB; // pawns BitBoard attacked = 0; if (!color == PieceColor::White) { attacked |= BitBoard::pawnNorthAttacks(*bs.pieceBBs[Board::toIndex(PieceType::Pawn)] & opponentBB, target); } else { attacked |= BitBoard::pawnSouthAttacks(*bs.pieceBBs[Board::toIndex(PieceType::Pawn)] & opponentBB, target); } movesBB |= BitBoard::castlingMoves(fromBB, *bs.pieceBBs[Board::toIndex(PieceType::Rook)], ~bs.occupiedBB) & castlingRank;// & ~attacked; if ((checkCR & CastlingRights::KingSide) == CastlingRights::None) { movesBB &= ~GFile; } if ((checkCR & CastlingRights::QueenSide) == CastlingRights::None) { movesBB &= ~CFile; } } } generateMoves(from, movesBB, moves); } void MoveGenerator::generateRookMoves(const BoardState &bs, const Square &from, PieceColor color, MoveVec &moves) { auto fromBB = BitBoard::fromIndex(from.index()); auto movesBB = BitBoard::rookAttacks(fromBB, ~bs.occupiedBB) & ~*bs.pieceBBs[Board::toIndex(color)]; generateMoves(from, movesBB, moves); } void MoveGenerator::generateQueenMoves(const BoardState &bs, const Square &from, PieceColor color, MoveVec &moves) { auto fromBB = BitBoard::fromIndex(from.index()); auto movesBB = BitBoard::queenAttacks(fromBB, ~bs.occupiedBB) & ~*bs.pieceBBs[Board::toIndex(color)]; generateMoves(from, movesBB, moves); }