diff --git a/src/search.cpp b/src/search.cpp index a26a7bc4..995204f3 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -261,19 +261,6 @@ void MainThread::search() { DrawValue[ us] = VALUE_DRAW - Value(contempt); DrawValue[~us] = VALUE_DRAW + Value(contempt); - TB::Hits = 0; - TB::RootInTB = false; - TB::UseRule50 = Options["Syzygy50MoveRule"]; - TB::ProbeDepth = Options["SyzygyProbeDepth"] * ONE_PLY; - TB::Cardinality = Options["SyzygyProbeLimit"]; - - // Skip TB probing when no TB found: !TBLargest -> !TB::Cardinality - if (TB::Cardinality > TB::MaxCardinality) - { - TB::Cardinality = TB::MaxCardinality; - TB::ProbeDepth = DEPTH_ZERO; - } - if (rootMoves.empty()) { rootMoves.push_back(RootMove(MOVE_NONE)); @@ -283,38 +270,6 @@ void MainThread::search() { } else { - if ( TB::Cardinality >= rootPos.count(WHITE) - + rootPos.count(BLACK) - && !rootPos.can_castle(ANY_CASTLING)) - { - // If the current root position is in the tablebases, then RootMoves - // contains only moves that preserve the draw or the win. - TB::RootInTB = Tablebases::root_probe(rootPos, rootMoves, TB::Score); - - if (TB::RootInTB) - TB::Cardinality = 0; // Do not probe tablebases during the search - - else // If DTZ tables are missing, use WDL tables as a fallback - { - // Filter out moves that do not preserve the draw or the win. - TB::RootInTB = Tablebases::root_probe_wdl(rootPos, rootMoves, TB::Score); - - // Only probe during search if winning - if (TB::Score <= VALUE_DRAW) - TB::Cardinality = 0; - } - - if (TB::RootInTB) - { - TB::Hits = rootMoves.size(); - - if (!TB::UseRule50) - TB::Score = TB::Score > VALUE_DRAW ? VALUE_MATE - MAX_PLY - 1 - : TB::Score < VALUE_DRAW ? -VALUE_MATE + MAX_PLY + 1 - : VALUE_DRAW; - } - } - for (Thread* th : Threads) if (th != this) th->start_searching(); @@ -1661,3 +1616,49 @@ bool RootMove::extract_ponder_from_tt(Position& pos) return false; } + +void Tablebases::filter_root_moves(Position& pos, Search::RootMoves& rootMoves) { + + Hits = 0; + RootInTB = false; + UseRule50 = Options["Syzygy50MoveRule"]; + ProbeDepth = Options["SyzygyProbeDepth"] * ONE_PLY; + Cardinality = Options["SyzygyProbeLimit"]; + + // Skip TB probing when no TB found: !TBLargest -> !TB::Cardinality + if (Cardinality > MaxCardinality) + { + Cardinality = MaxCardinality; + ProbeDepth = DEPTH_ZERO; + } + + if (Cardinality < popcount(pos.pieces()) || pos.can_castle(ANY_CASTLING)) + return; + + // If the current root position is in the tablebases, then RootMoves + // contains only moves that preserve the draw or the win. + RootInTB = root_probe(pos, rootMoves, TB::Score); + + if (RootInTB) + Cardinality = 0; // Do not probe tablebases during the search + + else // If DTZ tables are missing, use WDL tables as a fallback + { + // Filter out moves that do not preserve the draw or the win. + RootInTB = root_probe_wdl(pos, rootMoves, TB::Score); + + // Only probe during search if winning + if (TB::Score <= VALUE_DRAW) + Cardinality = 0; + } + + if (RootInTB) + { + Hits = rootMoves.size(); + + if (!UseRule50) + TB::Score = TB::Score > VALUE_DRAW ? VALUE_MATE - MAX_PLY - 1 + : TB::Score < VALUE_DRAW ? -VALUE_MATE + MAX_PLY + 1 + : VALUE_DRAW; + } +} diff --git a/src/syzygy/tbprobe.h b/src/syzygy/tbprobe.h index 2bcc0834..b23fdf66 100644 --- a/src/syzygy/tbprobe.h +++ b/src/syzygy/tbprobe.h @@ -12,6 +12,7 @@ int probe_wdl(Position& pos, int *success); int probe_dtz(Position& pos, int *success); bool root_probe(Position& pos, Search::RootMoves& rootMoves, Value& score); bool root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, Value& score); +void filter_root_moves(Position& pos, Search::RootMoves& rootMoves); } diff --git a/src/thread.cpp b/src/thread.cpp index 4dc7d9e9..b38bdd6e 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -25,6 +25,7 @@ #include "search.h" #include "thread.h" #include "uci.h" +#include "syzygy/tbprobe.h" ThreadPool Threads; // Global object @@ -169,7 +170,7 @@ int64_t ThreadPool::nodes_searched() { /// ThreadPool::start_thinking() wakes up the main thread sleeping in idle_loop() /// and starts a new search, then returns immediately. -void ThreadPool::start_thinking(const Position& pos, StateListPtr& states, +void ThreadPool::start_thinking(Position& pos, StateListPtr& states, const Search::LimitsType& limits) { main()->wait_for_search_finished(); @@ -183,6 +184,8 @@ void ThreadPool::start_thinking(const Position& pos, StateListPtr& states, || std::count(limits.searchmoves.begin(), limits.searchmoves.end(), m)) rootMoves.push_back(Search::RootMove(m)); + Tablebases::filter_root_moves(pos, rootMoves); + // After ownership transfer 'states' becomes empty, so if we stop the search // and call 'go' again without setting a new position states.get() == NULL. assert(states.get() || setupStates.get()); diff --git a/src/thread.h b/src/thread.h index 0b112de9..4e63fe47 100644 --- a/src/thread.h +++ b/src/thread.h @@ -94,7 +94,7 @@ struct ThreadPool : public std::vector { void exit(); // be initialized and valid during the whole thread lifetime. MainThread* main() { return static_cast(at(0)); } - void start_thinking(const Position&, StateListPtr&, const Search::LimitsType&); + void start_thinking(Position&, StateListPtr&, const Search::LimitsType&); void read_uci_options(); int64_t nodes_searched(); diff --git a/src/uci.cpp b/src/uci.cpp index a9811a9a..4ae66620 100644 --- a/src/uci.cpp +++ b/src/uci.cpp @@ -108,7 +108,7 @@ namespace { // the thinking time and other parameters from the input string, then starts // the search. - void go(const Position& pos, istringstream& is) { + void go(Position& pos, istringstream& is) { Search::LimitsType limits; string token;