BenBot 1.7.5
A chess engine
Loading...
Searching...
No Matches
ThreefoldChecker.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 <beman/inplace_vector/inplace_vector.hpp>
24#include <cstdint> // IWYU pragma: keep - for std::uint64_t
25#include <iterator>
26#include <utility>
27
28namespace chess::game {
29
33struct ThreefoldChecker final {
34 using HashValue = std::uint64_t;
35
37 constexpr void reset(HashValue initialPositionHash);
38
40 constexpr void push(HashValue newHash);
41
43 [[nodiscard]] constexpr auto is_threefold() const noexcept -> bool;
44
45private:
46 // stores a history of hash values
47 // the most recent value is at front() and the oldest is at back()
48 using History = beman::inplace_vector::inplace_vector<HashValue, 50uz>;
49
50 History history;
51};
52
53/*
54 ___ ,--,
55 ,---, ,--.'|_ ,--, ,--.'|
56 ,---.'| | | :,' ,--.'| | | :
57 | | : : : ' : | |, : : ' .--.--.
58 | | | ,---. .;__,' / ,--.--. `--'_ | ' | / / '
59 ,--.__| | / \ | | | / \ ,' ,'| ' | | | : /`./
60 / ,' | / / |:__,'| : .--. .-. | ' | | | | : | : ;_
61. ' / |. ' / | ' : |__ \__\/: . . | | : ' : |__ \ \ `.
62' ; |: |' ; /| | | '.'| ," .--.; | ' : |__ | | '.'| `----. \
63| | '/ '' | / | ; : ;/ / ,. | | | '.'|; : ;/ /`--' /__ ___ ___
64| : :|| : | | , /; : .' \; : ;| , /'--'. / .\/ .\/ .\
65 \ \ / \ \ / ---`-' | , .-./| , / ---`-' `--'---'\ ; \ ; \ ; |
66 `----' `----' `--`---' ---`-' `--" `--" `--"
67
68 */
69
70constexpr void ThreefoldChecker::reset(const HashValue initialPositionHash)
71{
72 history.clear();
73 history.emplace_back(initialPositionHash);
74}
75
76constexpr void ThreefoldChecker::push(const HashValue newHash)
77{
78 // make room for new element
79 if (std::cmp_less(history.size(), History::capacity()))
80 history.emplace_back(0uz);
81
82 // move the last element to the front,
83 // and move all other elements back 1
84 std::ranges::rotate(
85 history.begin(),
86 std::prev(history.end()),
87 history.end());
88
89 history.front() = newHash;
90}
91
92constexpr auto ThreefoldChecker::is_threefold() const noexcept -> bool
93{
94 // NB. the threefold repetition doesn't need to be consecutive within the history
95 return std::cmp_greater_equal(
96 std::ranges::count(history, history.front()),
97 3uz);
98}
99
100} // namespace chess::game
constexpr void reset(HashValue initialPositionHash)
constexpr auto is_threefold() const noexcept -> bool
constexpr void push(HashValue newHash)