BenBot 1.7.5
A chess engine
Loading...
Searching...
No Matches
Pieces.hpp
Go to the documentation of this file.
1/*
2 * ======================================================================================
3 *
4 * ░▒▓███████▓▒░░▒▓████████▓▒░▒▓███████▓▒░ ░▒▓███████▓▒░ ░▒▓██████▓▒░▒▓████████▓▒░
5 * ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░
6 * ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░
7 * ░▒▓███████▓▒░░▒▓██████▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓███████▓▒░░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░
8 * ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░
9 * ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░
10 * ░▒▓███████▓▒░░▒▓████████▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓███████▓▒░ ░▒▓██████▓▒░ ░▒▓█▓▒░
11 *
12 * ======================================================================================
13 */
14
19
20#pragma once
21
22#include <algorithm>
23#include <cassert>
32#include <magic_enum/magic_enum.hpp>
33#include <optional>
34
35namespace chess::board {
36
37using pieces::Color;
38
40
49struct Pieces final {
51 explicit constexpr Pieces(Color color) noexcept;
52
54 consteval Pieces() noexcept = default;
55
58
61
64
67
70
76
85
87 [[nodiscard]] constexpr auto operator==(const Pieces&) const noexcept -> bool = default;
88
90 [[nodiscard]] constexpr auto get_type(PieceType type) noexcept -> Bitboard&;
91
93 [[nodiscard]] constexpr auto get_type(PieceType type) const noexcept -> Bitboard;
94
98 [[nodiscard]] constexpr auto free() const noexcept -> Bitboard { return occupied.inverse(); }
99
101 [[nodiscard]] constexpr auto is_file_half_open(File file) const noexcept -> bool;
102
104 [[nodiscard]] constexpr auto has_bishop_pair() const noexcept -> bool;
105
107 [[nodiscard]] constexpr auto get_king_location() const noexcept -> Square;
108
113 [[nodiscard]] constexpr auto get_piece_on(Square square) const noexcept
114 -> std::optional<PieceType>;
115
119 constexpr void capture_at(Square square) noexcept;
120
122 constexpr void our_move(moves::Move move, Color ourColor) noexcept;
123
125 constexpr void refresh_occupied() noexcept;
126
128 constexpr void vertical_flip() noexcept;
129};
130
131/*
132 ___ ,--,
133 ,---, ,--.'|_ ,--, ,--.'|
134 ,---.'| | | :,' ,--.'| | | :
135 | | : : : ' : | |, : : ' .--.--.
136 | | | ,---. .;__,' / ,--.--. `--'_ | ' | / / '
137 ,--.__| | / \ | | | / \ ,' ,'| ' | | | : /`./
138 / ,' | / / |:__,'| : .--. .-. | ' | | | | : | : ;_
139. ' / |. ' / | ' : |__ \__\/: . . | | : ' : |__ \ \ `.
140' ; |: |' ; /| | | '.'| ," .--.; | ' : |__ | | '.'| `----. \
141| | '/ '' | / | ; : ;/ / ,. | | | '.'|; : ;/ /`--' /__ ___ ___
142| : :|| : | | , /; : .' \; : ;| , /'--'. / .\/ .\/ .\
143 \ \ / \ \ / ---`-' | , .-./| , / ---`-' `--'---'\ ; \ ; \ ; |
144 `----' `----' `--`---' ---`-' `--" `--" `--"
145
146 */
147
148constexpr Pieces::Pieces(const Color color) noexcept
149 : pawns { masks::starting::pawns(color) }
152 , rooks { masks::starting::rooks(color) }
153 , queens { masks::starting::queen(color) }
154 , king { masks::starting::king(color) }
155{
156}
157
158constexpr void Pieces::refresh_occupied() noexcept
159{
161}
162
163constexpr void Pieces::vertical_flip() noexcept
164{
165 using flips::vertical;
166
167 pawns = vertical(pawns);
168 knights = vertical(knights);
169 bishops = vertical(bishops);
170 rooks = vertical(rooks);
171 queens = vertical(queens);
172 king = vertical(king);
173
175}
176
177constexpr auto Pieces::get_type(const PieceType type) noexcept -> Bitboard&
178{
179 switch (type) {
180 case PieceType::Knight: return knights;
181 case PieceType::Bishop: return bishops;
182 case PieceType::Rook : return rooks;
183 case PieceType::Queen : return queens;
184 case PieceType::King : return king;
185 case PieceType::Pawn : [[fallthrough]];
186 default:
187 return pawns;
188 }
189}
190
191constexpr auto Pieces::get_type(const PieceType type) const noexcept -> Bitboard
192{
193 switch (type) {
194 case PieceType::Knight: return knights;
195 case PieceType::Bishop: return bishops;
196 case PieceType::Rook : return rooks;
197 case PieceType::Queen : return queens;
198 case PieceType::King : return king;
199 case PieceType::Pawn : [[fallthrough]];
200 default:
201 return pawns;
202 }
203}
204
205constexpr auto Pieces::is_file_half_open(const File file) const noexcept -> bool
206{
207 return (pawns & masks::files::get(file)).none();
208}
209
210constexpr auto Pieces::has_bishop_pair() const noexcept -> bool
211{
212 // NB. can't just check that bishops.count() == 2 because
213 // it's possible that we have 2 bishops of the same color
214
215 return (bishops & masks::LIGHT_SQUARES).any()
216 and (bishops & masks::DARK_SQUARES).any();
217}
218
219constexpr auto Pieces::get_king_location() const noexcept -> Square
220{
221 assert(std::cmp_equal(king.count(), 1));
222
223 return Square::from_index(king.first());
224}
225
226constexpr auto Pieces::get_piece_on(const Square square) const noexcept
227 -> std::optional<PieceType>
228{
229 if (not occupied.test(square))
230 return std::nullopt;
231
232 static constexpr auto allTypes = magic_enum::enum_values<PieceType>();
233
234 if (const auto found = std::ranges::find_if(
235 allTypes,
236 [this, index = square.index()](const PieceType type) {
237 return get_type(type).test(index);
238 });
239 found != allTypes.end()) {
240 // we should find a piece unless the occupied bitboard has gotten out of sync
241 [[likely]];
242
243 return *found;
244 }
245
246 assert(false);
247
248 return std::nullopt;
249}
250
251constexpr void Pieces::capture_at(const Square square) noexcept
252{
253 const auto idx = square.index();
254
255 // if we're trying to capture the king, then an illegal move has already been played
256 assert(not king.test(idx));
257
258 pawns.unset(idx);
259 knights.unset(idx);
260 bishops.unset(idx);
261 rooks.unset(idx);
262 queens.unset(idx);
263
264 occupied.unset(idx);
265}
266
267constexpr void Pieces::our_move(const moves::Move move, const Color ourColor) noexcept
268{
269 const auto movementMask = Bitboard::from_square(move.from()) | Bitboard::from_square(move.to());
270
271 occupied ^= movementMask;
272
273 move.promoted_type()
274 .transform([move, this](const PieceType type) {
275 get_type(move.piece()).unset(move.from());
276 get_type(type).set(move.to());
277 return std::monostate { };
278 })
279 .or_else([move, movementMask, ourColor, this] {
280 get_type(move.piece()) ^= movementMask;
281
282 if (move.is_castling()) {
283 const auto castleMask = move.to().is_queenside()
286
287 rooks ^= castleMask;
288 occupied ^= castleMask;
289 }
290
291 return std::make_optional(std::monostate { });
292 });
293}
294
295} // namespace chess::board
constexpr auto DARK_SQUARES
Definition Masks.hpp:55
constexpr auto queenside_castle_rook_pos_mask(const Color side) noexcept -> Bitboard
Definition Masks.hpp:100
constexpr auto knights(const Color color) noexcept -> Bitboard
Definition Masks.hpp:317
constexpr auto bishops(const Color color) noexcept -> Bitboard
Definition Masks.hpp:326
constexpr auto get(const File file) noexcept -> Bitboard
Definition Masks.hpp:171
constexpr auto pawns(const Color color) noexcept -> Bitboard
Definition Masks.hpp:299
constexpr auto king(const Color color) noexcept -> Bitboard
Definition Masks.hpp:344
constexpr auto queen(const Color color) noexcept -> Bitboard
Definition Masks.hpp:335
constexpr auto LIGHT_SQUARES
Definition Masks.hpp:58
constexpr auto rooks(const Color color) noexcept -> Bitboard
Definition Masks.hpp:308
constexpr auto kingside_castle_rook_pos_mask(const Color side) noexcept -> Bitboard
Definition Masks.hpp:119
constexpr auto vertical(Bitboard board) noexcept -> Bitboard
Definition Flips.hpp:57
pieces::Type PieceType
Definition Pieces.hpp:39
constexpr auto any() const noexcept -> bool
Definition Bitboard.hpp:67
static constexpr auto from_square(Square square) noexcept -> Bitboard
Definition Bitboard.hpp:279
constexpr Pieces(Color color) noexcept
Definition Pieces.hpp:148
constexpr auto free() const noexcept -> Bitboard
Definition Pieces.hpp:98
constexpr auto get_type(PieceType type) noexcept -> Bitboard &
Definition Pieces.hpp:177
constexpr auto has_bishop_pair() const noexcept -> bool
Definition Pieces.hpp:210
constexpr void capture_at(Square square) noexcept
Definition Pieces.hpp:251
constexpr auto operator==(const Pieces &) const noexcept -> bool=default
constexpr void refresh_occupied() noexcept
Definition Pieces.hpp:158
constexpr void our_move(moves::Move move, Color ourColor) noexcept
Definition Pieces.hpp:267
constexpr auto get_piece_on(Square square) const noexcept -> std::optional< PieceType >
Definition Pieces.hpp:226
constexpr void vertical_flip() noexcept
Definition Pieces.hpp:163
constexpr auto is_file_half_open(File file) const noexcept -> bool
Definition Pieces.hpp:205
consteval Pieces() noexcept=default
constexpr auto get_king_location() const noexcept -> Square
Definition Pieces.hpp:219
static constexpr auto from_index(BitboardIndex index) noexcept -> Square
Definition Square.hpp:191