From e50af36a00ea1df1b395873766408f127dd00c90 Mon Sep 17 00:00:00 2001 From: Joost VandeVondele Date: Fri, 20 Oct 2017 19:17:49 +0200 Subject: [PATCH] Extra thinking before accepting draw PVs. If the PV leads to a draw (3-fold / 50-moves) position and we're ahead of time, think a little longer, possibly finding a better way. As this is most likely effective at higher draw rates, tried speculative LTC after a yellow STC: STC: http://tests.stockfishchess.org/tests/view/59eb173a0ebc590ccbb8975d LLR: -2.95 (-2.94,2.94) [0.00,5.00] Total: 56095 W: 10013 L: 9902 D: 36180 elo = 0.688 +- 1.711 LOS: 78.425% LTC: http://tests.stockfishchess.org/tests/view/59eba1670ebc590ccbb897b4 LLR: 2.95 (-2.94,2.94) [0.00,5.00] Total: 59579 W: 7577 L: 7273 D: 44729 elo = 1.773 +- 1.391 LOS: 99.381% bench: 5234652 --- src/search.cpp | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 76afd5da..6ef74bea 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -149,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. @@ -475,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; @@ -1427,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. -- 2.39.2