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