X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=5ea00331b9bd85b012f66f473295c092e0808066;hp=0901187acee2af63bebbc120bed03e33948962da;hb=ba1464751d1186f723a2d2a5d18c06ddfc9a4cb3;hpb=2c52147dbfdc714a0ae95982f37fc5141b225f8c diff --git a/src/search.cpp b/src/search.cpp index 0901187a..5ea00331 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -33,27 +33,30 @@ #include "thread.h" #include "tt.h" #include "uci.h" - -#ifdef SYZYGY #include "syzygy/tbprobe.h" -#endif namespace Search { volatile SignalsType Signals; LimitsType Limits; - std::vector RootMoves; + RootMoveVector RootMoves; Position RootPos; Time::point SearchTime; StateStackPtr SetupStates; - int TBCardinality; - uint64_t TBHits; +} + +namespace Tablebases { + + int Cardinality; + uint64_t Hits; bool RootInTB; - bool TB50MoveRule; - Depth TBProbeDepth; - Value TBScore; + bool UseRule50; + Depth ProbeDepth; + Value Score; } +namespace TB = Tablebases; + using std::string; using Eval::evaluate; using namespace Search; @@ -191,13 +194,24 @@ template uint64_t Search::perft(Position& pos, Depth depth); void Search::think() { TimeMgr.init(Limits, RootPos.game_ply(), RootPos.side_to_move()); - TBHits = TBCardinality = 0; - RootInTB = false; int cf = Options["Contempt"] * PawnValueEg / 100; // From centipawns DrawValue[ RootPos.side_to_move()] = VALUE_DRAW - Value(cf); DrawValue[~RootPos.side_to_move()] = VALUE_DRAW + Value(cf); + 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(MOVE_NONE); @@ -207,59 +221,36 @@ void Search::think() { } else { -#ifdef SYZYGY - // Check Tablebases at root - int piecesCnt = RootPos.total_piece_count(); - TBCardinality = Options["SyzygyProbeLimit"]; - TBProbeDepth = Options["SyzygyProbeDepth"] * ONE_PLY; - if (TBCardinality > Tablebases::TBLargest) - { - TBCardinality = Tablebases::TBLargest; - TBProbeDepth = 0 * ONE_PLY; - } - TB50MoveRule = Options["Syzygy50MoveRule"]; - - if (piecesCnt <= TBCardinality) + if (TB::Cardinality >= RootPos.count(WHITE) + + RootPos.count(BLACK)) { - TBHits = RootMoves.size(); - // If the current root position is in the tablebases then RootMoves // contains only moves that preserve the draw or win. - RootInTB = Tablebases::root_probe(RootPos, TBScore); + TB::RootInTB = Tablebases::root_probe(RootPos, RootMoves, TB::Score); - if (RootInTB) - { - TBCardinality = 0; // Do not probe tablebases during the search - - // It might be a good idea to mangle the hash key (xor it - // with a fixed value) in order to "clear" the hash table of - // the results of previous probes. However, that would have to - // be done from within the Position class, so we skip it for now. + if (TB::RootInTB) + TB::Cardinality = 0; // Do not probe tablebases during the search - // Optional: decrease target time. - } else // If DTZ tables are missing, use WDL tables as a fallback { // Filter out moves that do not preserve a draw or win - RootInTB = Tablebases::root_probe_wdl(RootPos, TBScore); + TB::RootInTB = Tablebases::root_probe_wdl(RootPos, RootMoves, TB::Score); // Only probe during search if winning - if (TBScore <= VALUE_DRAW) - TBCardinality = 0; + if (TB::Score <= VALUE_DRAW) + TB::Cardinality = 0; } - if (!RootInTB) + if (TB::RootInTB) { - TBHits = 0; - } - else if (!TB50MoveRule) - { - TBScore = TBScore > VALUE_DRAW ? VALUE_MATE - MAX_PLY - 1 - : TBScore < VALUE_DRAW ? -VALUE_MATE + MAX_PLY + 1 - : TBScore; + 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; } } -#endif for (size_t i = 0; i < Threads.size(); ++i) Threads[i]->maxPly = 0; @@ -552,38 +543,35 @@ namespace { return ttValue; } -#ifdef SYZYGY // Step 4a. Tablebase probe - if ( !RootNode - && pos.total_piece_count() <= TBCardinality - && ( pos.total_piece_count() < TBCardinality || depth >= TBProbeDepth ) - && pos.rule50_count() == 0) + if (!RootNode && TB::Cardinality) { - int found, v = Tablebases::probe_wdl(pos, &found); + int piecesCnt = pos.count(WHITE) + pos.count(BLACK); - if (found) + if ( piecesCnt <= TB::Cardinality + && (piecesCnt < TB::Cardinality || depth >= TB::ProbeDepth) + && pos.rule50_count() == 0) { - TBHits++; + int found, v = Tablebases::probe_wdl(pos, &found); - if (TB50MoveRule) { - value = v < -1 ? -VALUE_MATE + MAX_PLY + ss->ply - : v > 1 ? VALUE_MATE - MAX_PLY - ss->ply - : VALUE_DRAW + 2 * v; - } - else + if (found) { - value = v < 0 ? -VALUE_MATE + MAX_PLY + ss->ply - : v > 0 ? VALUE_MATE - MAX_PLY - ss->ply - : VALUE_DRAW; - } + TB::Hits++; + + int drawScore = TB::UseRule50 ? 1 : 0; + + value = v < -drawScore ? -VALUE_MATE + MAX_PLY + ss->ply + : v > drawScore ? VALUE_MATE - MAX_PLY - ss->ply + : VALUE_DRAW + 2 * v * drawScore; - TT.store(posKey, value_to_tt(value, ss->ply), BOUND_EXACT, - std::min(DEPTH_MAX - ONE_PLY, depth + 6 * ONE_PLY), MOVE_NONE, VALUE_NONE); + TT.store(posKey, value_to_tt(value, ss->ply), BOUND_EXACT, + std::min(DEPTH_MAX - ONE_PLY, depth + 6 * ONE_PLY), + MOVE_NONE, VALUE_NONE); - return value; + return value; + } } } -#endif // Step 5. Evaluate the position statically and update parent's gain statistics if (inCheck) @@ -1451,14 +1439,8 @@ moves_loop: // When in check and at SpNode search starts from here Depth d = updated ? depth : depth - ONE_PLY; Value v = updated ? RootMoves[i].score : RootMoves[i].prevScore; - bool tb = RootInTB; - if (tb) - { - if (abs(v) >= VALUE_MATE - MAX_PLY) - tb = false; - else - v = TBScore; - } + bool tb = TB::RootInTB && abs(v) < VALUE_MATE - MAX_PLY; + v = tb ? TB::Score : v; if (ss.rdbuf()->in_avail()) // Not at first line ss << "\n"; @@ -1469,7 +1451,7 @@ moves_loop: // When in check and at SpNode search starts from here << " score " << ((!tb && i == PVIdx) ? UCI::format_value(v, alpha, beta) : UCI::format_value(v)) << " nodes " << pos.nodes_searched() << " nps " << pos.nodes_searched() * 1000 / elapsed - << " tbhits " << TBHits + << " tbhits " << TB::Hits << " time " << elapsed << " pv";