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