X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fsearch.cpp;h=6ef74bea5e1a5c7b92951a89961117b37fd60763;hb=e50af36a00ea1df1b395873766408f127dd00c90;hp=567f87660197e719cf83ab492191bd3d26945b30;hpb=07b5a28a68b4cc67f1447fce85fc910aa209b319;p=stockfish diff --git a/src/search.cpp b/src/search.cpp index 567f8766..6ef74bea 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -87,10 +87,9 @@ namespace { // Skill structure is used to implement strength limit struct Skill { - Skill(int l) : level(l) {} + explicit Skill(int l) : level(l) {} bool enabled() const { return level < 20; } bool time_to_pick(Depth depth) const { return depth / ONE_PLY == 1 + level; } - Move best_move(size_t multiPV) { return best ? best : pick_best(multiPV); } Move pick_best(size_t multiPV); int level; @@ -150,6 +149,7 @@ namespace { void update_pv(Move* pv, Move move, Move* childPv); void update_continuation_histories(Stack* ss, Piece pc, Square to, int bonus); void update_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietsCnt, int bonus); + bool pv_is_draw(Position& pos); // perft() is our utility to verify move generation. All the leaf nodes up // to the given depth are generated and counted, and the sum is returned. @@ -476,11 +476,17 @@ void Thread::search() { // from the previous search and just did a fast verification. const int F[] = { mainThread->failedLow, bestValue - mainThread->previousScore }; - int improvingFactor = std::max(229, std::min(715, 357 + 119 * F[0] - 6 * F[1])); - double unstablePvFactor = 1 + mainThread->bestMoveChanges; + + Color us = rootPos.side_to_move(); + bool thinkHard = DrawValue[us] == bestValue + && Limits.time[us] - Time.elapsed() > Limits.time[~us] + && ::pv_is_draw(rootPos); + + double unstablePvFactor = 1 + mainThread->bestMoveChanges + thinkHard; bool doEasyMove = rootMoves[0].pv[0] == easyMove + && !thinkHard && mainThread->bestMoveChanges < 0.03 && Time.elapsed() > Time.optimum() * 5 / 44; @@ -514,8 +520,8 @@ void Thread::search() { // If skill level is enabled, swap best PV line with the sub-optimal one if (skill.enabled()) - std::swap(rootMoves[0], *std::find(rootMoves.begin(), - rootMoves.end(), skill.best_move(multiPV))); + std::swap(rootMoves[0], *std::find(rootMoves.begin(), rootMoves.end(), + skill.best ? skill.best : skill.pick_best(multiPV))); } @@ -1428,6 +1434,24 @@ moves_loop: // When in check search starts from here } + // Is the PV leading to a draw position? Assumes all pv moves are legal + bool pv_is_draw(Position& pos) { + + StateInfo st[MAX_PLY]; + auto& pv = pos.this_thread()->rootMoves[0].pv; + + for (size_t i = 0; i < pv.size(); ++i) + pos.do_move(pv[i], st[i]); + + bool isDraw = pos.is_draw(pv.size()); + + for (size_t i = pv.size(); i > 0; --i) + pos.undo_move(pv[i-1]); + + return isDraw; + } + + // When playing with strength handicap, choose best move among a set of RootMoves // using a statistical rule dependent on 'level'. Idea by Heinz van Saanen. @@ -1451,7 +1475,7 @@ moves_loop: // When in check search starts from here int push = ( weakness * int(topScore - rootMoves[i].score) + delta * (rng.rand() % weakness)) / 128; - if (rootMoves[i].score + push > maxScore) + if (rootMoves[i].score + push >= maxScore) { maxScore = rootMoves[i].score + push; best = rootMoves[i].pv[0]; @@ -1589,6 +1613,10 @@ void Tablebases::filter_root_moves(Position& pos, Search::RootMoves& rootMoves) ProbeDepth = Options["SyzygyProbeDepth"] * ONE_PLY; Cardinality = Options["SyzygyProbeLimit"]; + // Don't filter any moves if the user requested analysis on multiple + if (Options["MultiPV"] != 1) + return; + // Skip TB probing when no TB found: !TBLargest -> !TB::Cardinality if (Cardinality > MaxCardinality) {