X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=6cab3f6cf7496713c1ac033bd3866ea2a9d22323;hp=1cf9428ef43e47c5610e611350386877d2257edf;hb=d53c928261a3a1b50304ec0a69312b6c2c338ccb;hpb=b50ce5ebfbc9f8b043f0d915c47b0ac550d4affc diff --git a/src/search.cpp b/src/search.cpp index 1cf9428e..6cab3f6c 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -224,7 +224,7 @@ size_t Search::perft(Position& pos, Depth depth) { void Search::think() { - static Book book; // Defined static to initialize the PRNG only once + static PolyglotBook book; // Defined static to initialize the PRNG only once Position& pos = RootPosition; Chess960 = pos.is_chess960(); @@ -290,11 +290,11 @@ void Search::think() { if (Options["Use Search Log"]) { - int e = Time::now() - SearchTime; + Time::point elapsed = Time::now() - SearchTime + 1; Log log(Options["Search Log Filename"]); log << "Nodes: " << pos.nodes_searched() - << "\nNodes/second: " << (e > 0 ? pos.nodes_searched() * 1000 / e : 0) + << "\nNodes/second: " << pos.nodes_searched() * 1000 / elapsed << "\nBest move: " << move_to_san(pos, RootMoves[0].pv[0]); StateInfo st; @@ -365,7 +365,8 @@ namespace { // Start with a small aspiration window and, in case of fail high/low, // research with bigger window until not failing high/low anymore. - do { + while (true) + { // Search starts from ss+1 to allow referencing (ss-1). This is // needed by update gains and ss copy when splitting at Root. bestValue = search(pos, ss+1, alpha, beta, depth * ONE_PLY); @@ -419,9 +420,15 @@ namespace { else break; - assert(alpha >= -VALUE_INFINITE && beta <= VALUE_INFINITE); + // Search with full window in case we have a win/mate score + if (abs(bestValue) >= VALUE_KNOWN_WIN) + { + alpha = -VALUE_INFINITE; + beta = VALUE_INFINITE; + } - } while (abs(bestValue) < VALUE_KNOWN_WIN); + assert(alpha >= -VALUE_INFINITE && beta <= VALUE_INFINITE); + } } // Skills: Do we need to pick now the best move ? @@ -521,7 +528,7 @@ namespace { Bound bt; Value bestValue, value, oldAlpha, ttValue; Value refinedValue, nullValue, futilityBase, futilityValue; - bool isPvMove, inCheck, singularExtensionNode, givesCheck; + bool pvMove, inCheck, singularExtensionNode, givesCheck; bool captureOrPromotion, dangerous, doFullDepthSearch; int moveCount = 0, playedMoveCount = 0; Thread* thisThread = pos.this_thread(); @@ -811,12 +818,12 @@ split_point_start: // At split points actual search starts from here if (RootNode && !std::count(RootMoves.begin() + PVIdx, RootMoves.end(), move)) continue; - // At PV and SpNode nodes we want all moves to be legal since the beginning - if ((PvNode || SpNode) && !pos.pl_move_is_legal(move, ci.pinned)) - continue; - if (SpNode) { + // Shared counter cannot be decremented later if move turns out to be illegal + if (!pos.pl_move_is_legal(move, ci.pinned)) + continue; + moveCount = ++sp->moveCount; sp->mutex.unlock(); } @@ -833,7 +840,6 @@ split_point_start: // At split points actual search starts from here << " currmovenumber " << moveCount + PVIdx << sync_endl; } - isPvMove = (PvNode && moveCount <= 1); captureOrPromotion = pos.is_capture_or_promotion(move); givesCheck = pos.move_gives_check(move, ci); dangerous = givesCheck || is_dangerous(pos, move, captureOrPromotion); @@ -922,6 +928,7 @@ split_point_start: // At split points actual search starts from here continue; } + pvMove = PvNode ? moveCount <= 1 : false; ss->currentMove = move; if (!SpNode && !captureOrPromotion && playedMoveCount < 64) movesSearched[playedMoveCount++] = move; @@ -932,7 +939,7 @@ split_point_start: // At split points actual search starts from here // Step 15. Reduced depth search (LMR). If the move fails high will be // re-searched at full depth. if ( depth > 3 * ONE_PLY - && !isPvMove + && !pvMove && !captureOrPromotion && !dangerous && ss->killers[0] != move @@ -948,7 +955,7 @@ split_point_start: // At split points actual search starts from here ss->reduction = DEPTH_ZERO; } else - doFullDepthSearch = !isPvMove; + doFullDepthSearch = !pvMove; // Step 16. Full depth search, when LMR is skipped or fails high if (doFullDepthSearch) @@ -961,7 +968,7 @@ split_point_start: // At split points actual search starts from here // Only for PV nodes do a full PV search on the first move or after a fail // high, in the latter case search only if value < beta, otherwise let the // parent node to fail low with value <= alpha and to try another move. - if (PvNode && (isPvMove || (value > alpha && (RootNode || value < beta)))) + if (PvNode && (pvMove || (value > alpha && (RootNode || value < beta)))) value = newDepth < ONE_PLY ? -qsearch(pos, ss+1, -beta, -alpha, DEPTH_ZERO) : - search(pos, ss+1, -beta, -alpha, newDepth); @@ -987,7 +994,7 @@ split_point_start: // At split points actual search starts from here RootMove& rm = *std::find(RootMoves.begin(), RootMoves.end(), move); // PV move or new best move ? - if (isPvMove || value > alpha) + if (pvMove || value > alpha) { rm.score = value; rm.extract_pv_from_tt(pos); @@ -995,7 +1002,7 @@ split_point_start: // At split points actual search starts from here // We record how often the best move has been changed in each // iteration. This information is used for time management: When // the best move changes frequently, we allocate some more time. - if (!isPvMove && MultiPV == 1) + if (!pvMove && MultiPV == 1) BestMoveChanges++; } else @@ -1536,7 +1543,7 @@ split_point_start: // At split points actual search starts from here string uci_pv(const Position& pos, int depth, Value alpha, Value beta) { std::stringstream s; - int t = Time::now() - SearchTime; + Time::point elaspsed = Time::now() - SearchTime + 1; int selDepth = 0; for (size_t i = 0; i < Threads.size(); i++) @@ -1557,12 +1564,12 @@ split_point_start: // At split points actual search starts from here s << "\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 " << (t > 0 ? pos.nodes_searched() * 1000 / t : 0) - << " time " << t - << " multipv " << i + 1 + << " seldepth " << selDepth + << " score " << (i == PVIdx ? score_to_uci(v, alpha, beta) : score_to_uci(v)) + << " nodes " << pos.nodes_searched() + << " nps " << pos.nodes_searched() * 1000 / elaspsed + << " time " << elaspsed + << " multipv " << i + 1 << " pv"; for (size_t j = 0; RootMoves[i].pv[j] != MOVE_NONE; j++) @@ -1760,15 +1767,15 @@ void check_time() { if (Limits.ponder) return; - int e = Time::now() - SearchTime; + Time::point elapsed = Time::now() - SearchTime; bool stillAtFirstMove = Signals.firstRootMove && !Signals.failedLowAtRoot - && e > TimeMgr.available_time(); + && elapsed > TimeMgr.available_time(); - bool noMoreTime = e > TimeMgr.maximum_time() - 2 * TimerResolution + bool noMoreTime = elapsed > TimeMgr.maximum_time() - 2 * TimerResolution || stillAtFirstMove; if ( (Limits.use_time_management() && noMoreTime) - || (Limits.movetime && e >= Limits.movetime)) + || (Limits.movetime && elapsed >= Limits.movetime)) Signals.stop = true; }