#ifndef CHESS_ENGINE_BOARD_HPP #define CHESS_ENGINE_BOARD_HPP #include "Piece.hpp" #include "Square.hpp" #include "Move.hpp" #include "CastlingRights.hpp" #include #include #include #define BB_NUM 8 // 6 pieces, 2 colors enum class BoardIndex { }; class Board { public: using Optional = std::optional; using MoveVec = std::vector; using BitBoard = uint64_t; Board(); void setPiece(const Square &square, const Piece::Optional &piece); Piece::Optional piece(const Square &square) const; void setTurn(PieceColor turn); PieceColor turn() const; void setCastlingRights(CastlingRights cr); CastlingRights castlingRights() const; void setEnPassantSquare(const Square::Optional &square); Square::Optional enPassantSquare() const; void makeMove(const Move &move); void pseudoLegalMoves(MoveVec &moves) const; void pseudoLegalMovesFrom(const Square &from, MoveVec &moves) const; private: BitBoard mPieceBBs[BB_NUM] = {}; BitBoard mOccupiedBB = 0; PieceColor mTurn = PieceColor::White; CastlingRights mCR = CastlingRights::None; std::optional mEPS; enum DefinedBoards : BitBoard { AFile = 0x0101010101010101, BFile = AFile << 1, CFile = AFile << 2, DFile = AFile << 3, EFile = AFile << 4, FFile = AFile << 5, GFile = AFile << 6, HFile = AFile << 7, WhiteCastlingRank = (1ULL << A2) - 1, BlackCastlingRank = (~1ULL << H7), CastlingRanks = WhiteCastlingRank | BlackCastlingRank, CastlingSquares = (WhiteCastlingRank | BlackCastlingRank) & (CFile | GFile), }; void handleCastlingRights(const Piece &piece, const BitBoard &bb); // Check if the move is castling without checking the rights or validity. static bool isMoveCastling(const BitBoard &from, const BitBoard &to, const Piece &piece); static inline void clearIndex(BitBoard &b, const unsigned i) { b &= ~(1ULL << i); } static inline void setIndex(BitBoard &b, const unsigned i) { b |= 1ULL << i; } static inline BitBoard indexToBitBoard(const unsigned i) { return (1ULL << i); } static inline BitBoard genShift(BitBoard x, const int s) { return (s < 0) ? (x >> -s) : (s > 63) ? x : (x << s); } static inline BitBoard getRankBB(int r) { return (genShift(1ULL, (r + 1) * 8) - 1) & genShift(~1ULL, r * 8 - 1); } static inline int toIndex(PieceType t) { return static_cast(t); } static inline int toIndex(PieceColor c) { return static_cast(c); } inline PieceColor pieceColor(const BitBoard &mask) const { auto color = PieceColor::White; if (!(mPieceBBs[static_cast(color)] & mask)) { color = !color; } return color; } inline PieceType pieceType(const BitBoard &mask) const { for (int i = 2; i < BB_NUM; i++) { if (mPieceBBs[i] & mask) { return static_cast(i); } } // Should not happen return static_cast(0); } inline void applyMask(const BitBoard &mask) { for (auto &item : mPieceBBs) { item ^= mask; } } // Returns the number of trailing 0-bits in b. // WARN: Check for 0! static inline int getLSB(const BitBoard b) { return __builtin_ctzll(b); } void handlePawnDoubleAdvance(const Move &move, BitBoard bb, const Piece &movedPiece); void handleEnPassant(const Move &move, const Piece &movedPiece); }; std::ostream &operator<<(std::ostream &os, const Board &board); #endif