BenBot 1.7.5
A chess engine
Loading...
Searching...
No Matches
Bitboard.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 <bit>
23#include <cassert>
24#include <cstddef> // IWYU pragma: keep - for size_t
25#include <cstdint> // IWYU pragma: keep - for std::uint64_t
26#include <iterator>
29#include <ranges>
30#include <string>
31#include <utility>
32
33namespace chess::board {
34
35using std::size_t;
36
48struct Bitboard final {
50 using Integer = std::uint64_t;
51
53 constexpr Bitboard() noexcept = default;
54
58 explicit constexpr Bitboard(Integer val) noexcept;
59
61 [[nodiscard]] constexpr auto operator==(const Bitboard&) const noexcept -> bool = default;
62
65
67 [[nodiscard]] constexpr auto any() const noexcept -> bool { return std::cmp_not_equal(value, 0); }
68
70 [[nodiscard]] constexpr auto none() const noexcept -> bool { return std::cmp_equal(value, 0); }
71
73 [[nodiscard]] constexpr auto count() const noexcept -> size_t { return static_cast<size_t>(std::popcount(value)); }
74
76 [[nodiscard]] constexpr auto test(const Square square) const noexcept -> bool { return test(square.index()); }
77
81 [[nodiscard]] constexpr auto test(BitboardIndex index) const noexcept -> bool;
82
87 [[nodiscard]] constexpr auto first() const noexcept -> BitboardIndex;
88
93 [[nodiscard]] constexpr auto last() const noexcept -> BitboardIndex;
94
96
99
101 constexpr void set(const Square square) noexcept { set(square.index()); }
102
106 constexpr void set(BitboardIndex index) noexcept;
107
109 constexpr void unset(const Square square) noexcept { unset(square.index()); }
110
114 constexpr void unset(BitboardIndex index) noexcept;
115
117 constexpr void clear() noexcept { value = UINT64_C(0); }
118
120
122 [[nodiscard]] constexpr auto to_int() const noexcept -> Integer { return value; }
123
126
135 [[nodiscard]] constexpr auto indices() const noexcept;
136
145 [[nodiscard]] constexpr auto squares() const noexcept;
146
158 [[nodiscard]] constexpr auto subboards() const noexcept;
159
161
164
166 [[nodiscard]] constexpr auto inverse() const noexcept -> Bitboard;
167
169 constexpr auto operator&=(const Bitboard& other) noexcept -> Bitboard&;
170
172 constexpr auto operator|=(const Bitboard& other) noexcept -> Bitboard&;
173
175 constexpr auto operator^=(const Bitboard& other) noexcept -> Bitboard&;
176
180 constexpr auto operator<<=(size_t num) noexcept -> Bitboard&;
181
185 constexpr auto operator>>=(size_t num) noexcept -> Bitboard&;
186
188
190 [[nodiscard, gnu::const]] static constexpr auto from_square(Square square) noexcept -> Bitboard;
191
192private:
193 Integer value { UINT64_C(0) };
194};
195
198
202[[nodiscard, gnu::const]] constexpr auto operator&(const Bitboard& lhs, const Bitboard& rhs) noexcept -> Bitboard;
203
207[[nodiscard, gnu::const]] constexpr auto operator|(const Bitboard& lhs, const Bitboard& rhs) noexcept -> Bitboard;
208
212[[nodiscard, gnu::const]] constexpr auto operator^(const Bitboard& lhs, const Bitboard& rhs) noexcept -> Bitboard;
213
217[[nodiscard, gnu::const]] constexpr auto operator<<(const Bitboard& board, size_t num) noexcept -> Bitboard;
218
222[[nodiscard, gnu::const]] constexpr auto operator>>(const Bitboard& board, size_t num) noexcept -> Bitboard;
223
231[[nodiscard]] auto print_ascii(Bitboard board) -> std::string;
232
234
238namespace literals {
239
244 [[nodiscard, gnu::const]] consteval auto operator""_bb(
245 const unsigned long long value) noexcept // NOLINT(runtime/int)
246 -> Bitboard
247 {
248 return Bitboard { static_cast<Bitboard::Integer>(value) };
249 }
250
251} // namespace literals
252
253} // namespace chess::board
254
255/*
256 ___ ,--,
257 ,---, ,--.'|_ ,--, ,--.'|
258 ,---.'| | | :,' ,--.'| | | :
259 | | : : : ' : | |, : : ' .--.--.
260 | | | ,---. .;__,' / ,--.--. `--'_ | ' | / / '
261 ,--.__| | / \ | | | / \ ,' ,'| ' | | | : /`./
262 / ,' | / / |:__,'| : .--. .-. | ' | | | | : | : ;_
263. ' / |. ' / | ' : |__ \__\/: . . | | : ' : |__ \ \ `.
264' ; |: |' ; /| | | '.'| ," .--.; | ' : |__ | | '.'| `----. \
265| | '/ '' | / | ; : ;/ / ,. | | | '.'|; : ;/ /`--' /__ ___ ___
266| : :|| : | | , /; : .' \; : ;| , /'--'. / .\/ .\/ .\
267 \ \ / \ \ / ---`-' | , .-./| , / ---`-' `--'---'\ ; \ ; \ ; |
268 `----' `----' `--`---' ---`-' `--" `--" `--"
269
270 */
271
272namespace chess::board {
273
274constexpr Bitboard::Bitboard(const Integer val) noexcept
275 : value { val }
276{
277}
278
279constexpr auto Bitboard::from_square(const Square square) noexcept -> Bitboard
280{
281 return Bitboard { UINT64_C(1) << square.index() };
282}
283
284constexpr auto Bitboard::test(const BitboardIndex index) const noexcept -> bool
285{
286 assert(std::cmp_less_equal(index, MAX_BITBOARD_IDX));
287
288 return std::cmp_not_equal(
289 (value >> index) & UINT64_C(1),
290 0);
291}
292
293constexpr void Bitboard::set(const BitboardIndex index) noexcept
294{
295 assert(std::cmp_less_equal(index, MAX_BITBOARD_IDX));
296
297 value |= UINT64_C(1) << index;
298}
299
300constexpr void Bitboard::unset(const BitboardIndex index) noexcept
301{
302 assert(std::cmp_less_equal(index, MAX_BITBOARD_IDX));
303
304 const Integer mask { UINT64_C(1) << index };
305
306 value &= ~mask;
307}
308
309constexpr auto Bitboard::first() const noexcept -> BitboardIndex
310{
311 // same as number of leading zeroes
312 return static_cast<BitboardIndex>(std::countr_zero(value));
313}
314
315constexpr auto Bitboard::last() const noexcept -> BitboardIndex
316{
317 if (none()) {
318 [[unlikely]]; // this is probably an error condition, but we want this function to be noexcept
319 return NUM_SQUARES;
320 }
321
322 const auto trailingZeroes = std::countl_zero(value);
323
324 return static_cast<BitboardIndex>(NUM_SQUARES - trailingZeroes - 1);
325}
326
327constexpr auto Bitboard::operator&=(const Bitboard& other) noexcept -> Bitboard&
328{
329 value &= other.value;
330 return *this;
331}
332
333constexpr auto Bitboard::operator|=(const Bitboard& other) noexcept -> Bitboard&
334{
335 value |= other.value;
336 return *this;
337}
338
339constexpr auto Bitboard::operator^=(const Bitboard& other) noexcept -> Bitboard&
340{
341 value ^= other.value;
342 return *this;
343}
344
345constexpr auto Bitboard::operator<<=(const size_t num) noexcept -> Bitboard&
346{
347 value <<= num;
348 return *this;
349}
350
351constexpr auto Bitboard::operator>>=(const size_t num) noexcept -> Bitboard&
352{
353 value >>= num;
354 return *this;
355}
356
357constexpr auto Bitboard::inverse() const noexcept -> Bitboard
358{
359 return Bitboard { ~value };
360}
361
362constexpr auto operator&(const Bitboard& lhs, const Bitboard& rhs) noexcept -> Bitboard
363{
364 auto ret = lhs;
365 ret &= rhs;
366 return ret;
367}
368
369constexpr auto operator|(const Bitboard& lhs, const Bitboard& rhs) noexcept -> Bitboard
370{
371 auto ret = lhs;
372 ret |= rhs;
373 return ret;
374}
375
376constexpr auto operator^(const Bitboard& lhs, const Bitboard& rhs) noexcept -> Bitboard
377{
378 auto ret = lhs;
379 ret ^= rhs;
380 return ret;
381}
382
383constexpr auto operator<<(const Bitboard& board, const size_t num) noexcept -> Bitboard
384{
385 auto ret = board;
386 ret <<= num;
387 return ret;
388}
389
390constexpr auto operator>>(const Bitboard& board, const size_t num) noexcept -> Bitboard
391{
392 auto ret = board;
393 ret >>= num;
394 return ret;
395}
396
397namespace detail {
398
399 // an STL iterator that iterates the set bits in a bitboard, quickly scanning through them using bitscan
400 struct BitboardIterator final {
405
406 using difference_type = std::ptrdiff_t;
407
408 using iterator_category = std::forward_iterator_tag;
409 using iterator_concept = std::forward_iterator_tag;
410
411 consteval BitboardIterator() = default;
412
413 explicit constexpr BitboardIterator(const Bitboard& bitboard)
414 : value { bitboard.to_int() }
415 {
416 }
417
418 constexpr auto operator==(const BitboardIterator& other) const noexcept -> bool = default;
419
420 constexpr auto operator==([[maybe_unused]] std::default_sentinel_t sentinel) const noexcept -> bool
421 {
422 return std::cmp_equal(value, 0);
423 }
424
425 [[nodiscard]] constexpr auto operator*() const noexcept -> value_type
426 {
427 return static_cast<value_type>(std::countr_zero(value));
428 }
429
430 constexpr auto operator++() noexcept -> BitboardIterator&
431 {
432 assert(std::cmp_greater(value, 0));
433
434 value &= value - UINT64_C(1);
435
436 return *this;
437 }
438
439 [[nodiscard]] constexpr auto operator++(int) noexcept -> BitboardIterator
440 {
441 const auto ret { *this };
442 ++*this;
443 return ret;
444 }
445
446 private:
447 Bitboard::Integer value { UINT64_C(0) };
448 };
449
450} // namespace detail
451
452constexpr auto Bitboard::indices() const noexcept
453{
454 return std::ranges::subrange {
455 detail::BitboardIterator { *this },
457 count()
458 };
459}
460
461constexpr auto Bitboard::squares() const noexcept
462{
463 return indices()
464 | std::views::transform(Square::from_index);
465}
466
467constexpr auto Bitboard::subboards() const noexcept
468{
469 return indices()
470 | std::views::transform(
471 [](const BitboardIndex index) {
473 board.set(index);
474 return board;
475 });
476}
477
478} // namespace chess::board
auto print_ascii(Bitboard board) -> std::string
std::uint_fast8_t BitboardIndex
constexpr BitboardIndex NUM_SQUARES
constexpr BitboardIndex MAX_BITBOARD_IDX
constexpr auto operator&(const Bitboard &lhs, const Bitboard &rhs) noexcept -> Bitboard
Definition Bitboard.hpp:362
constexpr auto operator>>(const Bitboard &board, const size_t num) noexcept -> Bitboard
Definition Bitboard.hpp:390
constexpr auto operator|(const Bitboard &lhs, const Bitboard &rhs) noexcept -> Bitboard
Definition Bitboard.hpp:369
constexpr auto operator<<(const Bitboard &board, const size_t num) noexcept -> Bitboard
Definition Bitboard.hpp:383
constexpr auto operator^(const Bitboard &lhs, const Bitboard &rhs) noexcept -> Bitboard
Definition Bitboard.hpp:376
constexpr auto operator>>=(size_t num) noexcept -> Bitboard &
Definition Bitboard.hpp:351
constexpr auto test(const Square square) const noexcept -> bool
Definition Bitboard.hpp:76
constexpr void set(const Square square) noexcept
Definition Bitboard.hpp:101
constexpr auto to_int() const noexcept -> Integer
Definition Bitboard.hpp:122
constexpr auto inverse() const noexcept -> Bitboard
Definition Bitboard.hpp:357
constexpr auto squares() const noexcept
Definition Bitboard.hpp:461
constexpr void clear() noexcept
Definition Bitboard.hpp:117
constexpr auto any() const noexcept -> bool
Definition Bitboard.hpp:67
static constexpr auto from_square(Square square) noexcept -> Bitboard
Definition Bitboard.hpp:279
constexpr auto operator|=(const Bitboard &other) noexcept -> Bitboard &
Definition Bitboard.hpp:333
constexpr Bitboard() noexcept=default
constexpr auto operator<<=(size_t num) noexcept -> Bitboard &
Definition Bitboard.hpp:345
std::uint64_t Integer
Definition Bitboard.hpp:50
constexpr auto count() const noexcept -> size_t
Definition Bitboard.hpp:73
constexpr auto operator&=(const Bitboard &other) noexcept -> Bitboard &
Definition Bitboard.hpp:327
constexpr auto first() const noexcept -> BitboardIndex
Definition Bitboard.hpp:309
constexpr void unset(const Square square) noexcept
Definition Bitboard.hpp:109
constexpr auto none() const noexcept -> bool
Definition Bitboard.hpp:70
constexpr auto last() const noexcept -> BitboardIndex
Definition Bitboard.hpp:315
constexpr auto subboards() const noexcept
Definition Bitboard.hpp:467
constexpr auto indices() const noexcept
Definition Bitboard.hpp:452
constexpr auto operator^=(const Bitboard &other) noexcept -> Bitboard &
Definition Bitboard.hpp:339
static constexpr auto from_index(BitboardIndex index) noexcept -> Square
Definition Square.hpp:191
constexpr auto operator++() noexcept -> BitboardIterator &
Definition Bitboard.hpp:430
constexpr auto operator++(int) noexcept -> BitboardIterator
Definition Bitboard.hpp:439
constexpr auto operator==(const BitboardIterator &other) const noexcept -> bool=default
constexpr auto operator*() const noexcept -> value_type
Definition Bitboard.hpp:425
constexpr BitboardIterator(const Bitboard &bitboard)
Definition Bitboard.hpp:413
std::forward_iterator_tag iterator_category
Definition Bitboard.hpp:408
constexpr auto operator==(std::default_sentinel_t sentinel) const noexcept -> bool
Definition Bitboard.hpp:420
std::forward_iterator_tag iterator_concept
Definition Bitboard.hpp:409