#ifndef CHESSY_MOVEGENERATION_H #define CHESSY_MOVEGENERATION_H #include "BitBoard.h" #include #include #include namespace chessy { // forward declaration class ChessGame; using Leftright = int; const Leftright LEFT = -1; const Leftright RIGHT = 1; class PositionSet; template class PawnPushGenerator; template class PromotionGenerator; template class PawnDoublePushGenerator; template class PawnCaptureGenerator; class KnightMoveGenerator; class PrimitiveQueenMoveGenerator; class PrimitiveRookMoveGenerator; class PrimitiveBishopMoveGenerator; class KingMoveGenerator; template class CastlingGenerator; template void generatePawnPushes(const ChessGame& cg, std::vector& moves); template void generatePawnDoublePushes(const ChessGame& cg, std::vector& moves); template void generatePawnCaptures(const ChessGame& cg, std::vector& moves); template void generatePawnPromotions(const ChessGame& cg, std::vector& moves); template void generateKnightMoves(const ChessGame& cg, std::vector& moves); template void generateQueenMoves(const ChessGame& cg, std::vector& moves); template void generateRookMoves(const ChessGame& cg, std::vector& moves); template void generateBishopMoves(const ChessGame& cg, std::vector& moves); template void generateKingMoves(const ChessGame& cg, std::vector& moves); template void generateCastling(const ChessGame& cg, std::vector& moves); template void generateAllMoves(const ChessGame& cg, std::vector& moves); } class chessy::PositionSet { Bitboard bitboard; public: inline PositionSet(Bitboard b) : bitboard{ b } {} inline void setBitboard(Bitboard b) { bitboard = b; } inline Bitboard getBitboard(void) const { return bitboard; } struct PositionSetIterator { Bitboard bitboard; inline Index operator *(void) const { return Index{ int8_t(trailingZeroes(bitboard.bits)) }; } inline void operator ++(void) { bitboard.bits &= bitboard.bits - 1ULL; // remove least significant one bit } inline bool operator !=(const PositionSetIterator& psi) const { return bitboard != psi.bitboard; } }; inline PositionSetIterator begin(void) const { return PositionSetIterator{ bitboard }; } inline static PositionSetIterator end(void) { return PositionSetIterator{ 0 }; } }; template class chessy::PawnPushGenerator { const ChessGame& chessGame; struct MoveIterator { PositionSet::PositionSetIterator pawnPushes; inline Move operator *(void) const { Index pp = *pawnPushes; return Move{ int8_t(pp + (side != WHITE_SIDE ? 8 : -8)), pp }; } inline void operator ++(void) { ++pawnPushes; } inline bool operator !=(const MoveIterator& psi) const { return pawnPushes != psi.pawnPushes; } }; public: inline PawnPushGenerator(const ChessGame& cg) : chessGame{ cg } {} MoveIterator begin(void) const; MoveIterator end(void) const; }; // TODO: rewrite better template class chessy::PromotionGenerator { const ChessGame& chessGame; struct MoveIterator { const ChessGame& chessGame; PositionSet::PositionSetIterator pawns; PieceType promotionType; char direction; inline Move operator *(void) const { Index pp = *pawns; return Move{ pp, int8_t(pp + (side == WHITE_SIDE ? 8 : -8) + direction), promotionType }; } private: void next(void); bool valid(void) const; public: inline void operator ++(void) { do { next(); } while(!valid()); } inline bool operator !=(const MoveIterator& psi) const { return pawns != psi.pawns; } }; public: inline PromotionGenerator(const ChessGame& cg) : chessGame{ cg } {} MoveIterator begin(void) const; MoveIterator end(void) const; }; template class chessy::PawnDoublePushGenerator { const ChessGame& chessGame; struct MoveIterator { PositionSet::PositionSetIterator pawnPushes; inline Move operator *(void) const { Index pp = *pawnPushes; return Move{ int8_t(pp + (side != WHITE_SIDE ? 16 : -16)), pp }; } inline void operator ++(void) { ++pawnPushes; } inline bool operator !=(const MoveIterator& psi) const { return pawnPushes != psi.pawnPushes; } }; public: inline PawnDoublePushGenerator(const ChessGame& cg) : chessGame{ cg } {} MoveIterator begin(void) const; MoveIterator end(void) const; }; template class chessy::PawnCaptureGenerator { const ChessGame& chessGame; struct MoveIterator { PositionSet::PositionSetIterator pawnPushes; inline Move operator *(void) const { Index pp = *pawnPushes; return Move{ int8_t(pp + (side != WHITE_SIDE ? 8 : -8) - leftright), pp }; } inline void operator ++(void) { ++pawnPushes; } inline bool operator !=(const MoveIterator& psi) const { return pawnPushes != psi.pawnPushes; } }; public: inline PawnCaptureGenerator(const ChessGame& cg) : chessGame{ cg } {} MoveIterator begin(void) const; MoveIterator end(void) const; }; /*! * extends \link PositionSet \endlink so that all possible destinations for * a knight can be iterated over. */ class chessy::KnightMoveGenerator : public PositionSet { static const std::array moveSets; public: inline KnightMoveGenerator(Index knight, Bitboard occupied) : PositionSet{ moveSets[knight] & ~occupied } {} private: static Bitboard generateFromIndex(Index i); static std::array generateKnightMoves(void); }; /*! * uses a primitive algorithm to calculate all possible move destinations * for a queen. */ class chessy::PrimitiveQueenMoveGenerator : public PositionSet { protected: inline PrimitiveQueenMoveGenerator(Index i, Bitboard enemies, Bitboard friendly, bool straight, bool diagonal) : PositionSet{ generateAttackSet(i, enemies, friendly, straight, diagonal) } {} public: inline PrimitiveQueenMoveGenerator(Index i, Bitboard enemies, Bitboard friendly) : PrimitiveQueenMoveGenerator{ i, enemies, friendly, true, true } {} private: Bitboard generateAttackSet(Index i, Bitboard enemies, Bitboard friendly, bool straight, bool diagonal); }; class chessy::PrimitiveBishopMoveGenerator : public PrimitiveQueenMoveGenerator { public: inline PrimitiveBishopMoveGenerator(Index i, Bitboard enemies, Bitboard friendly) : // bishop moves are actually just diagonal queen moves PrimitiveQueenMoveGenerator{ i, enemies, friendly, false, true } {} }; class chessy::PrimitiveRookMoveGenerator : public PrimitiveQueenMoveGenerator { public: inline PrimitiveRookMoveGenerator(Index i, Bitboard enemies, Bitboard friendly) : // rook moves are actually just straight queen moves PrimitiveQueenMoveGenerator{ i, enemies, friendly, true, false } {} }; class chessy::KingMoveGenerator : public PositionSet { public: inline KingMoveGenerator(Bitboard king, Bitboard friendly) : PositionSet{ generateKingMoves(king) & ~friendly } {} private: Bitboard generateKingMoves(Bitboard king); }; template class chessy::CastlingGenerator : public PositionSet { public: CastlingGenerator(const ChessGame& game); }; #endif // CHESSY_MOVEGENERATION_H