diff --git a/src/Makefile b/src/Makefile index 9680ca7f..907b6155 100644 --- a/src/Makefile +++ b/src/Makefile @@ -63,7 +63,7 @@ HEADERS = benchmark.h bitboard.h evaluate.h misc.h movegen.h movepick.h \ nnue/layers/sqr_clipped_relu.h nnue/nnue_accumulator.h nnue/nnue_architecture.h \ nnue/nnue_common.h nnue/nnue_feature_transformer.h position.h \ search.h syzygy/tbprobe.h thread.h thread_win32_osx.h timeman.h \ - tt.h tune.h types.h uci.h ucioption.h + tt.h tune.h types.h uci.h ucioption.h perft.h OBJS = $(notdir $(SRCS:.cpp=.o)) diff --git a/src/perft.h b/src/perft.h new file mode 100644 index 00000000..2edc3ad0 --- /dev/null +++ b/src/perft.h @@ -0,0 +1,69 @@ +/* + Stockfish, a UCI chess playing engine derived from Glaurung 2.1 + Copyright (C) 2004-2024 The Stockfish developers (see AUTHORS file) + + Stockfish is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Stockfish is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef PERFT_H_INCLUDED +#define PERFT_H_INCLUDED + +#include + +#include "movegen.h" +#include "position.h" +#include "types.h" +#include "uci.h" + +namespace Stockfish { + +// Utility to verify move generation. All the leaf nodes up +// to the given depth are generated and counted, and the sum is returned. +template +uint64_t perft(Position& pos, Depth depth) { + + StateInfo st; + ASSERT_ALIGNED(&st, Eval::NNUE::CacheLineSize); + + uint64_t cnt, nodes = 0; + const bool leaf = (depth == 2); + + for (const auto& m : MoveList(pos)) + { + if (Root && depth <= 1) + cnt = 1, nodes++; + else + { + pos.do_move(m, st); + cnt = leaf ? MoveList(pos).size() : perft(pos, depth - 1); + nodes += cnt; + pos.undo_move(m); + } + if (Root) + sync_cout << UCI::move(m, pos.is_chess960()) << ": " << cnt << sync_endl; + } + return nodes; +} + +inline void perft(const std::string& fen, Depth depth, bool isChess960) { + StateListPtr states(new std::deque(1)); + Position p; + p.set(fen, isChess960, &states->back()); + + uint64_t nodes = perft(p, depth); + sync_cout << "\nNodes searched: " << nodes << "\n" << sync_endl; +} +} + +#endif // PERFT_H_INCLUDED diff --git a/src/search.cpp b/src/search.cpp index f4b37253..086bff34 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -122,37 +122,8 @@ void update_all_stats(const Position& pos, int captureCount, Depth depth); -// Utility to verify move generation. All the leaf nodes up -// to the given depth are generated and counted, and the sum is returned. -template -uint64_t perft(Position& pos, Depth depth) { - - StateInfo st; - ASSERT_ALIGNED(&st, Eval::NNUE::CacheLineSize); - - uint64_t cnt, nodes = 0; - const bool leaf = (depth == 2); - - for (const auto& m : MoveList(pos)) - { - if (Root && depth <= 1) - cnt = 1, nodes++; - else - { - pos.do_move(m, st); - cnt = leaf ? MoveList(pos).size() : perft(pos, depth - 1); - nodes += cnt; - pos.undo_move(m); - } - if (Root) - sync_cout << UCI::move(m, pos.is_chess960()) << ": " << cnt << sync_endl; - } - return nodes; -} - } // namespace - Search::Worker::Worker(SharedState& sharedState, std::unique_ptr sm, size_t thread_id) : @@ -173,13 +144,6 @@ void Search::Worker::start_searching() { return; } - if (limits.perft) - { - nodes = perft(rootPos, limits.perft); - sync_cout << "\nNodes searched: " << nodes << "\n" << sync_endl; - return; - } - main_manager()->tm.init(limits, rootPos.side_to_move(), rootPos.game_ply(), options); tt.new_search(); diff --git a/src/uci.cpp b/src/uci.cpp index 2a55fbfa..e6107d47 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -39,6 +39,7 @@ #include "syzygy/tbprobe.h" #include "types.h" #include "ucioption.h" +#include "perft.h" namespace Stockfish { @@ -172,7 +173,6 @@ void UCI::loop() { void UCI::go(Position& pos, std::istringstream& is, StateListPtr& states) { - Search::LimitsType limits; std::string token; bool ponderMode = false; @@ -211,6 +211,12 @@ void UCI::go(Position& pos, std::istringstream& is, StateListPtr& states) { Eval::NNUE::verify(options, evalFiles); + if (limits.perft) + { + perft(pos.fen(), limits.perft, options["UCI_Chess960"]); + return; + } + threads.start_thinking(options, pos, states, limits, ponderMode); }