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
3 #include "attack.hpp"
4 #include "bit.hpp"
5 #include "piece.hpp"
6 #include "utils.hpp"
7 #include "zobrist.hpp"
9 #include <iostream>
10 #include <string>
12 #define start_position "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 "
14 class Board {
15 public:
16 enum Castle : uint8_t {
17 WK = 1,
18 WQ = 2,
19 BK = 4,
20 BQ = 8
21 };
23 Board() = default;
24 Board(const std::string &fen);
26 friend std::ostream &operator<<(std::ostream &os, const Board &board);
28 /* Getters */
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; }
36 [[nodiscard]] inline constexpr U64 get_bitboard_color(Color side) const;
37 [[nodiscard]] inline constexpr U64 get_bitboard_occupancy() const;
39 [[nodiscard]] inline constexpr U64 get_bitboard_piece(Type piece) const;
40 [[nodiscard]] inline constexpr U64 get_bitboard_piece(Type piece, Color color) const;
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;
46 [[nodiscard]] inline constexpr Color get_square_piece_color(Square square) const;
47 [[nodiscard]] inline constexpr Type get_square_piece_type(Square square) const;
49 /* Setters */
51 inline constexpr void xor_hash(U64 op);
52 inline constexpr void xor_hash_pawn(U32 op);
54 inline void switch_side();
55 inline void and_castle(uint8_t right);
56 inline void set_enpassant(Square target);
58 inline constexpr void pop_bitboard_color(Color color, Square square);
59 inline constexpr void set_bitboard_color(Color color, Square square);
61 inline constexpr void pop_bitboard_piece(Type type, Square square);
62 inline constexpr void set_bitboard_piece(Type type, Square square);
64 inline constexpr void pop_piece(Type type, Color side, Square square);
65 inline constexpr void set_piece(Type type, Color side, Square square);
67 /* Queries */
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;
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 };
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]; }
89 constexpr U64 Board::get_bitboard_piece(Type piece, Color color) const {
90 return pieces[piece] & colors[color];
91 }
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 }
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 }
102 constexpr U64 Board::get_bitboard_square_land(Square land, Type piece, Color side) const {
104 return get_bitboard_piece_attacks(piece, other(side), land) & get_bitboard_piece(piece, side);
105 }
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 }
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 }
120 /* Setters */
122 constexpr void Board::xor_hash(U64 op) { hash ^= op; }
123 constexpr void Board::xor_hash_pawn(U32 op) { hash_pawn ^= op; }
125 void Board::and_castle(uint8_t right) {
126 hash ^= zobrist::key_castle(castle);
127 castle &= right;
128 hash ^= zobrist::key_castle(castle);
129 }
131 void Board::switch_side() {
132 side = other(side);
133 hash ^= zobrist::key_side();
134 }
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 }
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); }
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 }
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 }
157 /* Queries */
159 constexpr bool Board::is_square_occupied(Square square) const {
160 return bit::get(get_bitboard_occupancy(), square);
161 }
163 constexpr bool Board::is_square_attacked(Square square, Color side) const {
164 const Color side_other = other(side);
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 }
172 return false;
173 }
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 }
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 }
186 U64 zobrist::hash(const Board &board) {
187 U64 key_final = C64(0);
188 uint8_t square = 0;
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]; }
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 }
198 key_final ^= keys_castle[board.get_castle()];
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()];
203 return key_final;
204 }
206 U32 zobrist::hash_pawn(const Board &board) {
207 U32 key_final = C32(0);
208 uint8_t square = 0;
210 U64 bitboard_white = board.get_bitboard_piece(PAWN, WHITE);
211 bitboard_for_each_bit(square, bitboard_white) { key_final ^= keys_pawn[WHITE][square]; }
213 U64 bitboard_black = board.get_bitboard_piece(PAWN, BLACK);
214 bitboard_for_each_bit(square, bitboard_black) { key_final ^= keys_pawn[BLACK][square]; }
216 return key_final;
217 }
219 #endif