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