Code: Select all
#include <dctl.hpp>
using namespace dctl::core;
using namespace dctl::algo;
int main()
{
static_assert(
traversal::depth_limited_count<true>( // perft with bulk-counting
basic_state<
international,
basic_board<international>
>::initial(), // the starting position in International Draughts
7, // depth = 7
drop_duplicates_gen // no duplicate captures
) == 1'049'442
);
}
Code: Select all
rein@rein-virtual-machine:~/projects/dctl/build$ time example/constexpr
real 0m0,003s
user 0m0,000s
sys 0m0,003s
What makes this possible? Short answer: g++12 and a machine with at leat 38Gb of RAM and 15 minutes of compilation time. Long answer: a conforming C++20 compiler. In C++20, almost everything is constexpr: all the Standard Library algorithms and some of the containers such as std::string and std::vector. There are some caveats (e.g. you must use a compiletime std::vector within the constexpr computation).
In C++20, you can also use almost the full language at compile time. I simply sprinkled "constexpr" in front of every function and increased the default compiler limit of constexpr operations by 1000X from 1<<25 to 1<<35. Without this limit expansion, only perft(4) works out of the box. But that's it: my regular perft() function works at compile-time and the compiler can count over a million positions.
Why not the full perft(11)? I tried it, and g++ ran out of memory The perft(7) run took 38Gb of RAM, higher depths consumed at least 48Gb (the size of my Linux VM on my 64Gb machine). Perhaps in the near future, compiler technology improves to a state where perft(11) can be comfortably computed. Since g++12 came out in April 2022, I could have done this computation already 6 months ago, but I only realized it this weekend and it worked almost out of the box with very little modification.
Note to other authors: every draughts program can now achieve this, as long as you mark all your own functions constexpr and use a constexpr container to store your generated moves into (C-array, std::array, std::vector or a homegrown datastructure that is constexpr-ified). You might have troubles using other libraries (I had when I used Boost.StaticVector or Boost.SmallVector to store the generated moves).