Unify various perft functions and move all the code
to search.cpp.
Avoid perft implementation to be splitted between
benchmark.cpp (where it has no reason to be) and
search.cpp
No functional and no speed change (tested).
cerr << "\nPosition: " << i + 1 << '/' << fens.size() << endl;
if (limitType == "perft")
cerr << "\nPosition: " << i + 1 << '/' << fens.size() << endl;
if (limitType == "perft")
- for (MoveList<LEGAL> it(pos); *it; ++it)
- {
- StateInfo si;
- pos.do_move(*it, si);
- uint64_t cnt = limits.depth > 1 ? Search::perft(pos, (limits.depth - 1) * ONE_PLY) : 1;
- pos.undo_move(*it);
- cout << move_to_uci(*it, pos.is_chess960()) << ": " << cnt << endl;
- nodes += cnt;
- }
+ nodes += Search::perft<true>(pos, limits.depth * ONE_PLY);
+
else
{
Threads.start_thinking(pos, limits, st);
else
{
Threads.start_thinking(pos, limits, st);
/// Search::perft() is our utility to verify move generation. All the leaf nodes
/// up to the given depth are generated and counted and the sum returned.
/// Search::perft() is our utility to verify move generation. All the leaf nodes
/// up to the given depth are generated and counted and the sum returned.
-
-static uint64_t perft(Position& pos, Depth depth) {
+template<bool Root>
+uint64_t Search::perft(Position& pos, Depth depth) {
+ uint64_t cnt, nodes = 0;
CheckInfo ci(pos);
const bool leaf = depth == 2 * ONE_PLY;
for (MoveList<LEGAL> it(pos); *it; ++it)
{
CheckInfo ci(pos);
const bool leaf = depth == 2 * ONE_PLY;
for (MoveList<LEGAL> it(pos); *it; ++it)
{
- pos.do_move(*it, st, ci, pos.gives_check(*it, ci));
- cnt += leaf ? MoveList<LEGAL>(pos).size() : ::perft(pos, depth - ONE_PLY);
- pos.undo_move(*it);
+ if (Root && depth <= ONE_PLY)
+ cnt = 1;
+ else
+ {
+ pos.do_move(*it, st, ci, pos.gives_check(*it, ci));
+ cnt = leaf ? MoveList<LEGAL>(pos).size() : perft<false>(pos, depth - ONE_PLY);
+ nodes += cnt;
+ pos.undo_move(*it);
+ }
+ if (Root)
+ sync_cout << move_to_uci(*it, pos.is_chess960()) << ": " << cnt << sync_endl;
-uint64_t Search::perft(Position& pos, Depth depth) {
- return depth > ONE_PLY ? ::perft(pos, depth) : MoveList<LEGAL>(pos).size();
-}
+template uint64_t Search::perft<true>(Position& pos, Depth depth);
+
/// Search::think() is the external interface to Stockfish's search, and is
/// called by the main thread when the program receives the UCI 'go' command. It
/// Search::think() is the external interface to Stockfish's search, and is
/// called by the main thread when the program receives the UCI 'go' command. It
extern StateStackPtr SetupStates;
extern void init();
extern StateStackPtr SetupStates;
extern void init();
-extern uint64_t perft(Position& pos, Depth depth);
+template<bool Root> uint64_t perft(Position& pos, Depth depth);