#ifndef SRC_BOARD_H_ #define SRC_BOARD_H_ #include #include enum PieceType : std::uint8_t { NONEPIECE, PAWN, KNIGHT, BISHOP, ROOK, QUEEN, KING, }; enum GameState : std::uint8_t { TURN, WHITE_WON, BLACK_WON, DRAW, }; struct Piece { bool color = false; PieceType type = NONEPIECE; }; struct Position { int rank = 0; int file = 0; bool operator==(const Position &) const = default; }; /* * Maybe we can try to be efficent with memory by using a byte (char) or * something like that let me brainstorm a little * * first two bits can be promotion flag because there are 4 posible options: * NONE BISHOP ROOK QUEEN * but wait none it not requided because its only applied * when on last rank * but that doesnt help becuase we cant have three options * ok so first 2 bits for promotion flag * like this ZZYYYYYY with ZZ being the promotion flag * 00 for none piece * 01 for queen * 10 for rook * 11 for bishop * these valuesa are abritrari * so we have other 6 bytes which doesnt work that well because we need to store * two 64 bit numbers one for "From" and second for "To" * so wait how much is a 64 for bit * 2 * 2 = 4 (2 bits) * 4 * 2 = 8 (3 bits) * 8 * 2 = 16 (4 bits) * 16 * 2 = 32 (5 bits) * 32 * 2 = 64 (6 bits) * so six bits that means that we can only store one posiiton we need a 2 + 6 * * 2 (14) bits of value to represent it but wait when promotion flag isnt 0 we * know its last rank oh but we dont know if from white or black perpective so * 14 bits is required let me search if there is a way to store that data * alright search done result seams that best way is to use 16 bit interger * which look like good solution and we have 2 bits left if we want to add more * things here is a diagram for it uint16_t: XXFFFFFFTTTTTT XX for promotion * flag F for from position T for to position so we can try first writing a * helper function for working with it then replace existing move struct */ struct Move { Position From; Position To; PieceType promotion = NONEPIECE; bool operator==(const Move &other) const { return From == other.From && To == other.To && promotion == other.promotion; } }; enum Flag : std::uint8_t { EXACT, LOWERBOUND, UPPERBOUND }; struct TranspositionsEntry { int depth = -1; int Eval = 0; Flag flag = EXACT; Move bestMove = {}; }; struct Game { Piece pieces[64]; uint64_t PieceBitboard = 0; // used for quicly iterating over all squares uint64_t WhitePieceBitboard = 0; uint64_t BlackPieceBitboard = 0; uint64_t PieceBitboards[2][7] = {}; bool turn = true; // 1 white; 0 black bool whiteCastleKing = false; bool whiteCastleQueen = false; bool blackCastleKing = false; bool blackCastleQueen = false; int halfMoveClock = 0; int MoveClock = 0; Position enPassant; bool canEnpassant = false; GameState state = TURN; std::unordered_map ThreeFoldMap; std::unordered_map *Transpositions = nullptr; }; struct UndoMove { Piece movedPiece; Piece capturedPiece; Position from; Position to; bool wasEnPassantCapture = false; Position enPassantCapturedSquare; Piece enPassantCapturedPiece; bool oldTurn; bool oldCanEnpassant; Position oldEnPassant; bool OldWhiteCastleKing; bool OldWhiteCastleQueen; bool OldBlackCastleKing; bool OldBlackCastleQueen; int oldHalfMoveClock; int oldMoveClock; uint64_t ZobristKey; GameState oldState; // castling bool wasCastle = false; bool CastledSide = false; // 0 for queen side, 1 for king side }; int PositionToIndex(Position i); UndoMove MakeMove(Move move, Game *g); void UnMakeMove(UndoMove undo, Game *g); Position FindKing(Game *g, bool white); void UpdateHelpers(Game *g); #endif /* SRC_BOARD_H_ */