stellarUCI Chess engine written in C++20 |
git clone git://git.dimitrijedobrota.com/stellar.git |
Log | Files | Refs | README | LICENSE |
board.hpp (7893B)
0 #ifndef STELLAR_BOARD_H 1 #define STELLAR_BOARD_H 2 3 #include "attack.hpp" 4 #include "bit.hpp" 5 #include "piece.hpp" 6 #include "utils.hpp" 7 #include "zobrist.hpp" 8 9 #include <iostream> 10 #include <string> 11 12 #define start_position "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 " 13 14 class Board { 15 public: 16 enum Castle : uint8_t { 17 WK = 1, 18 WQ = 2, 19 BK = 4, 20 BQ = 8 21 }; 22 23 Board() = default; 24 Board(const std::string &fen); 25 26 friend std::ostream &operator<<(std::ostream &os, const Board &board); 27 28 /* Getters */ 29 30 [[nodiscard]] inline constexpr U64 get_hash() const { return hash; } 31 [[nodiscard]] inline constexpr Color get_side() const { return side; } 32 [[nodiscard]] inline constexpr uint8_t get_castle() const { return castle; } 33 [[nodiscard]] inline constexpr Square get_enpassant() const { return enpassant; } 34 [[nodiscard]] inline constexpr U64 get_hash_pawn() const { return hash_pawn; } 35 36 [[nodiscard]] inline constexpr U64 get_bitboard_color(Color side) const; 37 [[nodiscard]] inline constexpr U64 get_bitboard_occupancy() const; 38 39 [[nodiscard]] inline constexpr U64 get_bitboard_piece(Type piece) const; 40 [[nodiscard]] inline constexpr U64 get_bitboard_piece(Type piece, Color color) const; 41 42 [[nodiscard]] inline constexpr U64 get_bitboard_piece_attacks(Type piece, Color color, Square from) const; 43 [[nodiscard]] inline constexpr U64 get_bitboard_piece_moves(Type piece, Color color, Square from) const; 44 [[nodiscard]] inline constexpr U64 get_bitboard_square_land(Square land, Type piece, Color side) const; 45 46 [[nodiscard]] inline constexpr Color get_square_piece_color(Square square) const; 47 [[nodiscard]] inline constexpr Type get_square_piece_type(Square square) const; 48 49 /* Setters */ 50 51 inline constexpr void xor_hash(U64 op); 52 inline constexpr void xor_hash_pawn(U32 op); 53 54 inline void switch_side(); 55 inline void and_castle(uint8_t right); 56 inline void set_enpassant(Square target); 57 58 inline constexpr void pop_bitboard_color(Color color, Square square); 59 inline constexpr void set_bitboard_color(Color color, Square square); 60 61 inline constexpr void pop_bitboard_piece(Type type, Square square); 62 inline constexpr void set_bitboard_piece(Type type, Square square); 63 64 inline constexpr void pop_piece(Type type, Color side, Square square); 65 inline constexpr void set_piece(Type type, Color side, Square square); 66 67 /* Queries */ 68 69 [[nodiscard]] inline constexpr bool is_square_attacked(Square square, Color side) const; 70 [[nodiscard]] inline constexpr bool is_square_occupied(Square square) const; 71 [[nodiscard]] inline constexpr bool is_piece_attack_square(Type type, Color color, Square source, 72 Square target) const; 73 [[nodiscard]] inline constexpr bool is_check() const; 74 75 private: 76 U64 colors[2] = {0}; 77 U64 pieces[6] = {0}; 78 U64 hash = 0; 79 U32 hash_pawn = 0; 80 Color side = WHITE; 81 Square enpassant = Square::no_sq; 82 uint8_t castle = 0; 83 }; 84 85 constexpr U64 Board::get_bitboard_color(Color side) const { return colors[side]; } 86 constexpr U64 Board::get_bitboard_occupancy() const { return colors[WHITE] | colors[BLACK]; } 87 constexpr U64 Board::get_bitboard_piece(Type piece) const { return pieces[piece]; } 88 89 constexpr U64 Board::get_bitboard_piece(Type piece, Color color) const { 90 return pieces[piece] & colors[color]; 91 } 92 93 constexpr U64 Board::get_bitboard_piece_attacks(Type type, Color color, Square from) const { 94 if (type == PAWN) return attack::attack_pawn(color, from); 95 return attack::attack(type, from, get_bitboard_occupancy()); 96 } 97 98 constexpr U64 Board::get_bitboard_piece_moves(Type type, Color color, Square square) const { 99 return get_bitboard_piece_attacks(type, color, square) & ~get_bitboard_color(color); 100 } 101 102 constexpr U64 Board::get_bitboard_square_land(Square land, Type piece, Color side) const { 103 104 return get_bitboard_piece_attacks(piece, other(side), land) & get_bitboard_piece(piece, side); 105 } 106 107 constexpr Color Board::get_square_piece_color(Square square) const { 108 if (bit::get(colors[WHITE], square)) return WHITE; 109 if (bit::get(colors[BLACK], square)) return BLACK; 110 return COLOR_NB; 111 } 112 113 constexpr Type Board::get_square_piece_type(Square square) const { 114 for (Type type = PAWN; type <= KING; ++type) { 115 if (bit::get(pieces[type], square)) return type; 116 } 117 return Type::NO_TYPE; 118 } 119 120 /* Setters */ 121 122 constexpr void Board::xor_hash(U64 op) { hash ^= op; } 123 constexpr void Board::xor_hash_pawn(U32 op) { hash_pawn ^= op; } 124 125 void Board::and_castle(uint8_t right) { 126 hash ^= zobrist::key_castle(castle); 127 castle &= right; 128 hash ^= zobrist::key_castle(castle); 129 } 130 131 void Board::switch_side() { 132 side = other(side); 133 hash ^= zobrist::key_side(); 134 } 135 136 void Board::set_enpassant(Square target) { 137 if (enpassant != Square::no_sq) hash ^= zobrist::key_enpassant(enpassant); 138 if (target != Square::no_sq) hash ^= zobrist::key_enpassant(target); 139 enpassant = target; 140 } 141 142 constexpr void Board::pop_bitboard_color(Color color, Square square) { bit::pop(colors[color], square); } 143 constexpr void Board::set_bitboard_color(Color color, Square square) { bit::set(colors[color], square); } 144 constexpr void Board::pop_bitboard_piece(Type type, Square square) { bit::pop(pieces[type], square); } 145 constexpr void Board::set_bitboard_piece(Type type, Square square) { bit::set(pieces[type], square); } 146 147 constexpr void Board::pop_piece(Type type, Color side, Square square) { 148 pop_bitboard_color(side, square); 149 pop_bitboard_piece(type, square); 150 } 151 152 constexpr void Board::set_piece(Type type, Color side, Square square) { 153 set_bitboard_color(side, square); 154 set_bitboard_piece(type, square); 155 } 156 157 /* Queries */ 158 159 constexpr bool Board::is_square_occupied(Square square) const { 160 return bit::get(get_bitboard_occupancy(), square); 161 } 162 163 constexpr bool Board::is_square_attacked(Square square, Color side) const { 164 const Color side_other = other(side); 165 166 for (Type type = PAWN; type <= KING; ++type) { 167 if (get_bitboard_piece_attacks(type, side_other, square) & get_bitboard_piece(type, side)) { 168 return true; 169 } 170 } 171 172 return false; 173 } 174 175 constexpr bool Board::is_piece_attack_square(Type type, Color color, Square source, Square target) const { 176 return get_bitboard_piece_attacks(type, color, source) & (C64(1) << target); 177 } 178 179 constexpr bool Board::is_check() const { 180 U64 king = pieces[Type::KING] & colors[side]; 181 Color side_other = (side == BLACK) ? WHITE : BLACK; 182 auto square = static_cast<Square>(bit::lsb_index(king)); 183 return is_square_attacked(square, side_other); 184 } 185 186 U64 zobrist::hash(const Board &board) { 187 U64 key_final = C64(0); 188 uint8_t square = 0; 189 190 for (Type type = PAWN; type <= KING; ++type) { 191 U64 bitboard_white = board.get_bitboard_piece(type, WHITE); 192 bitboard_for_each_bit(square, bitboard_white) { key_final ^= keys_piece[WHITE][type][square]; } 193 194 U64 bitboard_black = board.get_bitboard_piece(type, BLACK); 195 bitboard_for_each_bit(square, bitboard_black) { key_final ^= keys_piece[BLACK][type][square]; } 196 } 197 198 key_final ^= keys_castle[board.get_castle()]; 199 200 if (board.get_side() == BLACK) key_final ^= keys_side; 201 if (board.get_enpassant() != Square::no_sq) key_final ^= keys_enpassant[board.get_enpassant()]; 202 203 return key_final; 204 } 205 206 U32 zobrist::hash_pawn(const Board &board) { 207 U32 key_final = C32(0); 208 uint8_t square = 0; 209 210 U64 bitboard_white = board.get_bitboard_piece(PAWN, WHITE); 211 bitboard_for_each_bit(square, bitboard_white) { key_final ^= keys_pawn[WHITE][square]; } 212 213 U64 bitboard_black = board.get_bitboard_piece(PAWN, BLACK); 214 bitboard_for_each_bit(square, bitboard_black) { key_final ^= keys_pawn[BLACK][square]; } 215 216 return key_final; 217 } 218 219 #endif