X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fsearch.cpp;h=a97c73485523eaf13002ddf3c6895b3f7c52d663;hb=ea6c1f7a17572f1cd291ffd00e28cfbd3b2947d5;hp=46636787f58ee7afa99059126c80761b394a6b4c;hpb=9d1978e217812eaa3626f5e1058962c0aca1bc46;p=stockfish diff --git a/src/search.cpp b/src/search.cpp index 46636787..a97c7348 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -194,7 +194,7 @@ void Search::think() { goto finalize; } - if (Options["OwnBook"] && !Limits.infinite) + if (Options["OwnBook"] && !Limits.infinite && !Limits.mate) { Move bookMove = book.probe(RootPos, Options["Book File"], Options["Best Book Move"]); @@ -227,7 +227,15 @@ void Search::think() { << std::endl; } - Threads.wake_up(); + // Reset and wake up the threads + for (size_t i = 0; i < Threads.size(); i++) + { + Threads[i].maxPly = 0; + Threads[i].do_sleep = false; + + if (!Threads.use_sleeping_threads()) + Threads[i].notify_one(); + } // Set best timer interval to avoid lagging under time pressure. Timer is // used to check for remaining available thinking time. @@ -242,7 +250,11 @@ void Search::think() { id_loop(RootPos); // Let's start searching ! Threads.set_timer(0); // Stop timer - Threads.sleep(); + + // Main thread will go to sleep by itself to avoid a race with start_searching() + for (size_t i = 0; i < Threads.size(); i++) + if (&Threads[i] != Threads.main_thread()) + Threads[i].do_sleep = true; if (Options["Use Search Log"]) { @@ -262,10 +274,15 @@ void Search::think() { finalize: // When we reach max depth we arrive here even without Signals.stop is raised, - // but if we are pondering or in infinite search, we shouldn't print the best - // move before we are told to do so. + // but if we are pondering or in infinite search, according to UCI protocol, + // we shouldn't print the best move before the GUI sends a "stop" or "ponderhit" + // command. We simply wait here until GUI sends one of those commands (that + // raise Signals.stop). if (!Signals.stop && (Limits.ponder || Limits.infinite)) - RootPos.this_thread()->wait_for_stop_or_ponderhit(); + { + Signals.stopOnPonderhit = true; + RootPos.this_thread()->wait_for(Signals.stop); + } // Best move could be MOVE_NONE when searching on a stalemate position sync_cout << "bestmove " << move_to_uci(RootMoves[0].pv[0], RootPos.is_chess960()) @@ -410,6 +427,12 @@ namespace { if (depth > 2 && BestMoveChanges) bestMoveNeverChanged = false; + // Do we have found a "mate in x"? + if ( Limits.mate + && bestValue >= VALUE_MATE_IN_MAX_PLY + && VALUE_MATE - bestValue <= 2 * Limits.mate) + Signals.stop = true; + // Do we have time for the next iteration? Can we stop searching now? if (Limits.use_time_management() && !Signals.stopOnPonderhit) { @@ -575,17 +598,25 @@ namespace { // Step 5. Evaluate the position statically and update parent's gain statistics if (inCheck) ss->staticEval = ss->evalMargin = eval = VALUE_NONE; - else + + else if (tte) { - eval = ss->staticEval = evaluate(pos, ss->evalMargin); + // Never assume anything on values stored in TT + if ( (ss->staticEval = eval = tte->static_value()) == VALUE_NONE + ||(ss->evalMargin = tte->static_value_margin()) == VALUE_NONE) + eval = ss->staticEval = evaluate(pos, ss->evalMargin); // Can ttValue be used as a better position evaluation? - if (tte && ttValue != VALUE_NONE) - { + if (ttValue != VALUE_NONE) if ( ((tte->type() & BOUND_LOWER) && ttValue > eval) || ((tte->type() & BOUND_UPPER) && ttValue < eval)) eval = ttValue; - } + } + else + { + eval = ss->staticEval = evaluate(pos, ss->evalMargin); + TT.store(posKey, VALUE_NONE, BOUND_NONE, DEPTH_NONE, MOVE_NONE, + ss->staticEval, ss->evalMargin); } // Update gain for the parent non-capture move given the static position @@ -888,7 +919,7 @@ split_point_start: // At split points actual search starts from here continue; } - pvMove = PvNode ? moveCount == 1 : false; + pvMove = PvNode && moveCount == 1; ss->currentMove = move; if (!SpNode && !captureOrPromotion && playedMoveCount < 64) movesSearched[playedMoveCount++] = move; @@ -980,24 +1011,21 @@ split_point_start: // At split points actual search starts from here if (value > bestValue) { - bestValue = value; - if (SpNode) sp->bestValue = value; + bestValue = SpNode ? sp->bestValue = value : value; if (value > alpha) { - bestMove = move; - if (SpNode) sp->bestMove = move; + bestMove = SpNode ? sp->bestMove = move : move; - if (PvNode && value < beta) - { - alpha = value; // Update alpha here! Always alpha < beta - if (SpNode) sp->alpha = value; - } + if (PvNode && value < beta) // Update alpha! Always alpha < beta + alpha = SpNode ? sp->alpha = value : value; else { assert(value >= beta); // Fail high - if (SpNode) sp->cutoff = true; + if (SpNode) + sp->cutoff = true; + break; } } @@ -1041,7 +1069,8 @@ split_point_start: // At split points actual search starts from here if (bestValue >= beta) // Failed high { - TT.store(posKey, value_to_tt(bestValue, ss->ply), BOUND_LOWER, depth, bestMove); + TT.store(posKey, value_to_tt(bestValue, ss->ply), BOUND_LOWER, depth, + bestMove, ss->staticEval, ss->evalMargin); if (!pos.is_capture_or_promotion(bestMove) && !inCheck) { @@ -1066,7 +1095,7 @@ split_point_start: // At split points actual search starts from here else // Failed low or PV search TT.store(posKey, value_to_tt(bestValue, ss->ply), PvNode && bestMove != MOVE_NONE ? BOUND_EXACT : BOUND_UPPER, - depth, bestMove); + depth, bestMove, ss->staticEval, ss->evalMargin); assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE); @@ -1094,7 +1123,7 @@ split_point_start: // At split points actual search starts from here Key posKey; Move ttMove, move, bestMove; Value bestValue, value, ttValue, futilityValue, futilityBase, oldAlpha; - bool givesCheck, enoughMaterial, evasionPrunable, fromNull; + bool givesCheck, enoughMaterial, evasionPrunable; Depth ttDepth; // To flag BOUND_EXACT a node with eval above alpha and no available moves @@ -1103,7 +1132,6 @@ split_point_start: // At split points actual search starts from here ss->currentMove = bestMove = MOVE_NONE; ss->ply = (ss-1)->ply + 1; - fromNull = (ss-1)->currentMove == MOVE_NULL; // Check for an instant draw or maximum ply reached if (pos.is_draw() || ss->ply > MAX_PLY) @@ -1141,11 +1169,12 @@ split_point_start: // At split points actual search starts from here } else { - if (fromNull) + if (tte) { - // Approximated score. Real one is slightly higher due to tempo - ss->staticEval = bestValue = -(ss-1)->staticEval; - ss->evalMargin = VALUE_ZERO; + // Never assume anything on values stored in TT + if ( (ss->staticEval = bestValue = tte->static_value()) == VALUE_NONE + ||(ss->evalMargin = tte->static_value_margin()) == VALUE_NONE) + ss->staticEval = bestValue = evaluate(pos, ss->evalMargin); } else ss->staticEval = bestValue = evaluate(pos, ss->evalMargin); @@ -1154,7 +1183,8 @@ split_point_start: // At split points actual search starts from here if (bestValue >= beta) { if (!tte) - TT.store(pos.key(), value_to_tt(bestValue, ss->ply), BOUND_LOWER, DEPTH_NONE, MOVE_NONE); + TT.store(pos.key(), value_to_tt(bestValue, ss->ply), BOUND_LOWER, + DEPTH_NONE, MOVE_NONE, ss->staticEval, ss->evalMargin); return bestValue; } @@ -1183,7 +1213,6 @@ split_point_start: // At split points actual search starts from here // Futility pruning if ( !PvNode && !InCheck - && !fromNull && !givesCheck && move != ttMove && enoughMaterial @@ -1263,7 +1292,9 @@ split_point_start: // At split points actual search starts from here } else // Fail high { - TT.store(posKey, value_to_tt(value, ss->ply), BOUND_LOWER, ttDepth, move); + TT.store(posKey, value_to_tt(value, ss->ply), BOUND_LOWER, + ttDepth, move, ss->staticEval, ss->evalMargin); + return value; } } @@ -1277,7 +1308,7 @@ split_point_start: // At split points actual search starts from here TT.store(posKey, value_to_tt(bestValue, ss->ply), PvNode && bestValue > oldAlpha ? BOUND_EXACT : BOUND_UPPER, - ttDepth, bestMove); + ttDepth, bestMove, ss->staticEval, ss->evalMargin); assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE); @@ -1574,7 +1605,7 @@ void RootMove::insert_pv_in_tt(Position& pos) { tte = TT.probe(pos.key()); if (!tte || tte->move() != pv[ply]) // Don't overwrite correct entries - TT.store(pos.key(), VALUE_NONE, BOUND_NONE, DEPTH_NONE, pv[ply]); + TT.store(pos.key(), VALUE_NONE, BOUND_NONE, DEPTH_NONE, pv[ply], VALUE_NONE, VALUE_NONE); assert(MoveList(pos).contains(pv[ply])); @@ -1679,7 +1710,7 @@ void Thread::idle_loop() { && !sp->slavesMask) { assert(!sp->master->is_searching); - sp->master->wake_up(); + sp->master->notify_one(); } // After releasing the lock we cannot access anymore any SplitPoint