X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=2ae1c368c4e76b62c17f8e275b27ed32a5f5f1d8;hp=3baa5bc25f40b4b4ecd81e11d5d4ed2335d885d0;hb=0d8a4c7565390c9f7ccc99799a76a19fb50e6f7b;hpb=4808d15a85c444c3c7071b4033aaa22e269b2d49 diff --git a/src/search.cpp b/src/search.cpp index 3baa5bc2..2ae1c368 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -43,7 +43,7 @@ namespace Search { std::vector RootMoves; Position RootPos; Color RootColor; - Time::point SearchTime, IterationTime; + Time::point SearchTime; StateStackPtr SetupStates; } @@ -185,6 +185,10 @@ void Search::think() { RootColor = RootPos.side_to_move(); TimeMgr.init(Limits, RootPos.game_ply(), RootColor); + int cf = Options["Contempt Factor"] * PawnValueEg / 100; // From centipawns + DrawValue[ RootColor] = VALUE_DRAW - Value(cf); + DrawValue[~RootColor] = VALUE_DRAW + Value(cf); + if (RootMoves.empty()) { RootMoves.push_back(MOVE_NONE); @@ -206,16 +210,6 @@ void Search::think() { } } - if (Options["Contempt Factor"] && !Options["UCI_AnalyseMode"]) - { - int cf = Options["Contempt Factor"] * PawnValueMg / 100; // From centipawns - cf = cf * Material::game_phase(RootPos) / PHASE_MIDGAME; // Scale down with phase - DrawValue[ RootColor] = VALUE_DRAW - Value(cf); - DrawValue[~RootColor] = VALUE_DRAW + Value(cf); - } - else - DrawValue[WHITE] = DrawValue[BLACK] = VALUE_DRAW; - if (Options["Write Search Log"]) { Log log(Options["Search Log Filename"]); @@ -225,7 +219,7 @@ void Search::think() { << " time: " << Limits.time[RootColor] << " increment: " << Limits.inc[RootColor] << " moves to go: " << Limits.movestogo - << std::endl; + << "\n" << std::endl; } // Reset the threads, still sleeping: will wake up at split time @@ -397,8 +391,6 @@ namespace { sync_cout << uci_pv(pos, depth, alpha, beta) << sync_endl; } - IterationTime = Time::now() - SearchTime; - // If skill levels are enabled and time is up, pick a sub-optimal best move if (skill.enabled() && skill.time_to_pick(depth)) skill.pick_move(); @@ -423,8 +415,6 @@ namespace { // Do we have time for the next iteration? Can we stop searching now? if (Limits.use_time_management() && !Signals.stop && !Signals.stopOnPonderhit) { - bool stop = false; // Local variable, not the volatile Signals.stop - // Take some extra time if the best move has changed if (depth > 4 && depth < 50 && MultiPV == 1) TimeMgr.pv_instability(BestMoveChanges); @@ -432,10 +422,7 @@ namespace { // Stop the search if only one legal move is available or all // of the available time has been used. if ( RootMoves.size() == 1 - || IterationTime > TimeMgr.available_time() ) - stop = true; - - if (stop) + || Time::now() - SearchTime > TimeMgr.available_time()) { // If we are allowed to ponder do not stop the search now but // keep pondering until the GUI sends "ponderhit" or "stop". @@ -547,7 +534,6 @@ namespace { : ttValue >= beta ? (tte->bound() & BOUND_LOWER) : (tte->bound() & BOUND_UPPER))) { - TT.refresh(tte); ss->currentMove = ttMove; // Can be MOVE_NONE // If ttMove is quiet, update killers, history, counter move and followup move on TT hit @@ -659,7 +645,7 @@ namespace { } } - // Step 9. Multi-Cut (skipped when in check) + // Step 9. ProbCut (skipped when in check) // If we have a very good capture (i.e. SEE > seeValues[captured_piece_type]) // and a reduced search returns a value much above beta, we can (almost) safely // prune the previous move. @@ -668,8 +654,8 @@ namespace { && !ss->skipNullMove && abs(beta) < VALUE_MATE_IN_MAX_PLY) { - Value rbeta = beta + 200; - Depth rdepth = depth - ONE_PLY - 3 * ONE_PLY; + Value rbeta = std::min(beta + 200, VALUE_INFINITE); + Depth rdepth = depth - 4 * ONE_PLY; assert(rdepth >= ONE_PLY); assert((ss-1)->currentMove != MOVE_NONE); @@ -779,7 +765,7 @@ moves_loop: // When in check and at SpNode search starts from here || pos.advanced_pawn_push(move); // Step 12. Extend checks - if (givesCheck && pos.see_sign(move) >= 0) + if (givesCheck && pos.see_sign(move) >= VALUE_ZERO) ext = ONE_PLY; // Singular extension search. If all moves but one fail low on a search of @@ -850,7 +836,7 @@ moves_loop: // When in check and at SpNode search starts from here } // Prune moves with negative SEE at low depths - if (predictedDepth < 4 * ONE_PLY && pos.see_sign(move) < 0) + if (predictedDepth < 4 * ONE_PLY && pos.see_sign(move) < VALUE_ZERO) { if (SpNode) splitPoint->mutex.lock(); @@ -1022,7 +1008,7 @@ moves_loop: // When in check and at SpNode search starts from here // case of Signals.stop or thread.cutoff_occurred() are set, but this is // harmless because return value is discarded anyhow in the parent nodes. // If we are in a singular extension search then return a fail low score. - // A split node has at least one move - the one tried before to be splitted. + // A split node has at least one move - the one tried before to be split. if (!moveCount) return excludedMove ? alpha : inCheck ? mated_in(ss->ply) : DrawValue[pos.side_to_move()]; @@ -1175,7 +1161,7 @@ moves_loop: // When in check and at SpNode search starts from here continue; } - if (futilityBase < beta && pos.see(move) <= 0) + if (futilityBase < beta && pos.see(move) <= VALUE_ZERO) { bestValue = std::max(bestValue, futilityBase); continue; @@ -1193,7 +1179,7 @@ moves_loop: // When in check and at SpNode search starts from here && (!InCheck || evasionPrunable) && move != ttMove && type_of(move) != PROMOTION - && pos.see_sign(move) < 0) + && pos.see_sign(move) < VALUE_ZERO) continue; // Check for legality just before making the move @@ -1356,7 +1342,7 @@ moves_loop: // When in check and at SpNode search starts from here string uci_pv(const Position& pos, int depth, Value alpha, Value beta) { - std::stringstream s; + std::stringstream ss; Time::point elapsed = Time::now() - SearchTime + 1; size_t uciPVSize = std::min((size_t)Options["MultiPV"], RootMoves.size()); int selDepth = 0; @@ -1375,23 +1361,23 @@ moves_loop: // When in check and at SpNode search starts from here int d = updated ? depth : depth - 1; Value v = updated ? RootMoves[i].score : RootMoves[i].prevScore; - if (s.rdbuf()->in_avail()) // Not at first line - s << "\n"; + if (ss.rdbuf()->in_avail()) // Not at first line + ss << "\n"; - s << "info depth " << d - << " seldepth " << selDepth - << " score " << (i == PVIdx ? score_to_uci(v, alpha, beta) : score_to_uci(v)) - << " nodes " << pos.nodes_searched() - << " nps " << pos.nodes_searched() * 1000 / elapsed - << " time " << elapsed - << " multipv " << i + 1 - << " pv"; + ss << "info depth " << d + << " seldepth " << selDepth + << " score " << (i == PVIdx ? score_to_uci(v, alpha, beta) : score_to_uci(v)) + << " nodes " << pos.nodes_searched() + << " nps " << pos.nodes_searched() * 1000 / elapsed + << " time " << elapsed + << " multipv " << i + 1 + << " pv"; for (size_t j = 0; RootMoves[i].pv[j] != MOVE_NONE; ++j) - s << " " << move_to_uci(RootMoves[i].pv[j], pos.is_chess960()); + ss << " " << move_to_uci(RootMoves[i].pv[j], pos.is_chess960()); } - return s.str(); + return ss.str(); } } // namespace @@ -1483,7 +1469,7 @@ void Thread::idle_loop() { mutex.lock(); // If we are master and all slaves have finished then exit idle_loop - if (this_sp && !this_sp->slavesMask) + if (this_sp && this_sp->slavesMask.none()) { mutex.unlock(); break; @@ -1542,14 +1528,14 @@ void Thread::idle_loop() { searching = false; activePosition = NULL; - sp->slavesMask &= ~(1ULL << idx); + sp->slavesMask.reset(idx); sp->nodes += pos.nodes_searched(); // Wake up the master thread so to allow it to return from the idle // loop in case we are the last slave of the split point. if ( Threads.sleepWhileIdle && this != sp->masterThread - && !sp->slavesMask) + && sp->slavesMask.none()) { assert(!sp->masterThread->searching); sp->masterThread->notify_one(); @@ -1564,10 +1550,10 @@ void Thread::idle_loop() { // If this thread is the master of a split point and all slaves have finished // their work at this split point, return from the idle loop. - if (this_sp && !this_sp->slavesMask) + if (this_sp && this_sp->slavesMask.none()) { this_sp->mutex.lock(); - bool finished = !this_sp->slavesMask; // Retest under lock protection + bool finished = this_sp->slavesMask.none(); // Retest under lock protection this_sp->mutex.unlock(); if (finished) return; @@ -1610,13 +1596,10 @@ void check_time() { sp.mutex.lock(); nodes += sp.nodes; - Bitboard sm = sp.slavesMask; - while (sm) - { - Position* pos = Threads[pop_lsb(&sm)]->activePosition; - if (pos) - nodes += pos->nodes_searched(); - } + + for (size_t idx = 0; idx < Threads.size(); ++idx) + if (sp.slavesMask.test(idx) && Threads[idx]->activePosition) + nodes += Threads[idx]->activePosition->nodes_searched(); sp.mutex.unlock(); } @@ -1627,8 +1610,7 @@ void check_time() { Time::point elapsed = Time::now() - SearchTime; bool stillAtFirstMove = Signals.firstRootMove && !Signals.failedLowAtRoot - && elapsed > TimeMgr.available_time() - && elapsed > IterationTime * 1.4; + && elapsed > TimeMgr.available_time() * 75 / 100; bool noMoreTime = elapsed > TimeMgr.maximum_time() - 2 * TimerThread::Resolution || stillAtFirstMove;