X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fsearch.cpp;h=343c098a587dbb6cf3d8b8eb6aae946d178d733b;hb=98965c139df1483a3d684ee8bc7a60dc4b95efa1;hp=5839763dc7fd647fa8e91d92cb874e54368c1126;hpb=219fa2f0a79381d35d9eb1240781cc598e74f647;p=stockfish diff --git a/src/search.cpp b/src/search.cpp index 5839763d..343c098a 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -81,7 +81,7 @@ namespace { // History and stats update bonus, based on depth int stat_bonus(Depth d) { - return std::min((12 * d + 282) * d - 349 , 1594); + return std::min((12 * d + 282) * d - 349 , 1480); } // Add a small random component to draw evaluations to avoid 3-fold blindness @@ -244,7 +244,7 @@ void MainThread::search() { // Send again PV info if we have a new best thread if (bestThread != this) - sync_cout << UCI::pv(bestThread->rootPos, bestThread->completedDepth, -VALUE_INFINITE, VALUE_INFINITE) << sync_endl; + sync_cout << UCI::pv(bestThread->rootPos, bestThread->completedDepth) << sync_endl; sync_cout << "bestmove " << UCI::move(bestThread->rootMoves[0].pv[0], rootPos.is_chess960()); @@ -392,7 +392,7 @@ void Thread::search() { && multiPV == 1 && (bestValue <= alpha || bestValue >= beta) && Time.elapsed() > 3000) - sync_cout << UCI::pv(rootPos, rootDepth, alpha, beta) << sync_endl; + sync_cout << UCI::pv(rootPos, rootDepth) << sync_endl; // In case of failing low/high increase aspiration window and // re-search, otherwise exit the loop. @@ -423,7 +423,7 @@ void Thread::search() { if ( mainThread && (Threads.stop || pvIdx + 1 == multiPV || Time.elapsed() > 3000)) - sync_cout << UCI::pv(rootPos, rootDepth, alpha, beta) << sync_endl; + sync_cout << UCI::pv(rootPos, rootDepth) << sync_endl; } if (!Threads.stop) @@ -855,7 +855,7 @@ namespace { { assert(probCutBeta < VALUE_INFINITE); - MovePicker mp(pos, ttMove, probCutBeta - ss->staticEval, depth - 3, &captureHistory); + MovePicker mp(pos, ttMove, probCutBeta - ss->staticEval, &captureHistory); while ((move = mp.next_move()) != MOVE_NONE) if (move != excludedMove && pos.legal(move)) @@ -1156,13 +1156,13 @@ moves_loop: // When in check, search starts here if (singularQuietLMR) r--; - // Dicrease reduction if we move a threatened piece (~1 Elo) + // Decrease reduction if we move a threatened piece (~1 Elo) if ( depth > 9 && (mp.threatenedPieces & from_sq(move))) r--; // Increase reduction if next ply has a lot of fail high - if ((ss+1)->cutoffCnt > 3 && !PvNode) + if ((ss+1)->cutoffCnt > 3) r++; ss->statScore = 2 * thisThread->mainHistory[us][from_to(move)] @@ -1172,7 +1172,7 @@ moves_loop: // When in check, search starts here - 4433; // Decrease/increase reduction for moves with a good/bad history (~30 Elo) - r -= ss->statScore / (13628 + 4000 * (depth > 7 && depth < 19)); + r -= ss->statScore / (13000 + 4152 * (depth > 7 && depth < 19)); // In general we want to cap the LMR depth search at newDepth, but when // reduction is negative, we allow this move a limited search extension @@ -1187,8 +1187,13 @@ moves_loop: // When in check, search starts here // Adjust full depth search based on LMR results - if result // was good enough search deeper, if it was bad enough search shallower const bool doDeeperSearch = value > (alpha + 64 + 11 * (newDepth - d)); + const bool doEvenDeeperSearch = value > alpha + 582; const bool doShallowerSearch = value < bestValue + newDepth; - value = -search(pos, ss+1, -(alpha+1), -alpha, newDepth + doDeeperSearch - doShallowerSearch, !cutNode); + + newDepth += doDeeperSearch - doShallowerSearch + doEvenDeeperSearch; + + if (newDepth > d) + value = -search(pos, ss+1, -(alpha+1), -alpha, newDepth, !cutNode); int bonus = value > alpha ? stat_bonus(newDepth) : -stat_bonus(newDepth); @@ -1242,6 +1247,8 @@ moves_loop: // When in check, search starts here { rm.score = value; rm.selDepth = thisThread->selDepth; + rm.scoreLowerbound = value >= beta; + rm.scoreUpperbound = value <= alpha; rm.pv.resize(1); assert((ss+1)->pv); @@ -1295,8 +1302,6 @@ moves_loop: // When in check, search starts here } } } - else - ss->cutoffCnt = 0; // If the move is worse than some previously searched move, remember it to update its stats later @@ -1550,12 +1555,11 @@ moves_loop: // When in check, search starts here && (*contHist[1])[pos.moved_piece(move)][to_sq(move)] < 0) continue; - // movecount pruning for quiet check evasions + // We prune after 2nd quiet check evasion where being 'in check' is implicitly checked through the counter + // and being a 'quiet' apart from being a tt move is assumed after an increment because captures are pushed ahead. if ( bestValue > VALUE_TB_LOSS_IN_MAX_PLY - && quietCheckEvasions > 1 - && !capture - && ss->inCheck) - continue; + && quietCheckEvasions > 1) + break; quietCheckEvasions += !capture && ss->inCheck; @@ -1819,7 +1823,7 @@ void MainThread::check_time() { /// UCI::pv() formats PV information according to the UCI protocol. UCI requires /// that all (if any) unsearched PV lines are sent using a previous search score. -string UCI::pv(const Position& pos, Depth depth, Value alpha, Value beta) { +string UCI::pv(const Position& pos, Depth depth) { std::stringstream ss; TimePoint elapsed = Time.elapsed() + 1; @@ -1857,8 +1861,8 @@ string UCI::pv(const Position& pos, Depth depth, Value alpha, Value beta) { if (Options["UCI_ShowWDL"]) ss << UCI::wdl(v, pos.game_ply()); - if (!tb && i == pvIdx) - ss << (v >= beta ? " lowerbound" : v <= alpha ? " upperbound" : ""); + if (i == pvIdx && !tb && updated) // tablebase- and previous-scores are exact + ss << (rootMoves[i].scoreLowerbound ? " lowerbound" : (rootMoves[i].scoreUpperbound ? " upperbound" : "")); ss << " nodes " << nodesSearched << " nps " << nodesSearched * 1000 / elapsed