X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=cd874ff816156bfcfd036c65de3443a917325341;hp=fcadc9228992155d11eb9f4729014442d3424cb8;hb=06a350f1aee97f05c3416853fb54385b23030ebc;hpb=9fc602bae74b8e09bd45ace3b42a8ce84d56b23c diff --git a/src/search.cpp b/src/search.cpp index fcadc922..cd874ff8 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -87,7 +87,7 @@ namespace { Depth depth, bool mateThreat, int* moves, MovePicker* mp, int master, bool pvNode); private: - friend void poll(SearchStack ss[], int ply); + friend void poll(); int ActiveThreads; volatile bool AllThreadsShouldExit, AllThreadsShouldSleep; @@ -232,7 +232,7 @@ namespace { const Value EasyMoveMargin = Value(0x200); // Last seconds noise filtering (LSN) - const bool UseLSNFiltering = true; + const bool UseLSNFiltering = false; const int LSNTime = 4000; // In milliseconds const Value LSNValue = value_from_centipawns(200); bool loseOnTime = false; @@ -259,9 +259,6 @@ namespace { bool UseTimeManagement, InfiniteSearch, PonderSearch, StopOnPonderhit; bool FirstRootMove, AbortSearch, Quit, AspirationFailLow; - // Show current line? - bool ShowCurrentLine; - // Log file bool UseLogFile; std::ofstream LogFile; @@ -305,7 +302,7 @@ namespace { int current_search_time(); int nps(); - void poll(SearchStack ss[], int ply); + void poll(); void ponderhit(); void wait_for_stop_or_ponderhit(); void init_ss_array(SearchStack ss[]); @@ -425,7 +422,6 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move, MinimumSplitDepth = get_option_value_int("Minimum Split Depth") * OnePly; MaxThreadsPerSplitPoint = get_option_value_int("Maximum Number of Threads per Split Point"); - ShowCurrentLine = get_option_value_bool("UCI_ShowCurrLine"); MultiPV = get_option_value_int("MultiPV"); Chess960 = get_option_value_bool("UCI_Chess960"); UseLogFile = get_option_value_bool("Use Search Log"); @@ -441,10 +437,6 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move, { TM.set_active_threads(newActiveThreads); init_eval(TM.active_threads()); - // HACK: init_eval() destroys the static castleRightsMask[] array in the - // Position class. The below line repairs the damage. - Position p(pos.to_fen()); - assert(pos.is_ok()); } // Wake up sleeping threads @@ -1105,14 +1097,13 @@ namespace { tte = TT.retrieve(pos.get_key()); } - // Step 10. Loop through moves - // Loop through all legal moves until no moves remain or a beta cutoff occurs - // Initialize a MovePicker object for the current position mateThreat = pos.has_mate_threat(opposite_color(pos.side_to_move())); MovePicker mp = MovePicker(pos, ttMove, depth, H, &ss[ply]); CheckInfo ci(pos); + // Step 10. Loop through moves + // Loop through all legal moves until no moves remain or a beta cutoff occurs while ( alpha < beta && (move = mp.get_next_move()) != MOVE_NONE && !TM.thread_should_stop(threadID)) @@ -1329,12 +1320,12 @@ namespace { } // Step 6. Razoring - if ( !value_is_mate(beta) + if ( refinedValue < beta - razor_margin(depth) + && ttMove == MOVE_NONE + && ss[ply - 1].currentMove != MOVE_NULL + && depth < RazorDepth && !isCheck - && depth < RazorDepth - && refinedValue < beta - razor_margin(depth) - && ss[ply - 1].currentMove != MOVE_NULL - && ttMove == MOVE_NONE + && !value_is_mate(beta) && !pos.has_pawn_on_7th(pos.side_to_move())) { Value rbeta = beta - razor_margin(depth); @@ -1347,11 +1338,13 @@ namespace { // Step 7. Static null move pruning // We're betting that the opponent doesn't have a move that will reduce - // the score by more than fuility_margin(depth) if we do a null move. - if ( !isCheck - && allowNullmove - && depth < RazorDepth - && refinedValue - futility_margin(depth, 0) >= beta) + // the score by more than futility_margin(depth) if we do a null move. + if ( allowNullmove + && depth < RazorDepth + && !isCheck + && !value_is_mate(beta) + && ok_to_do_nullmove(pos) + && refinedValue >= beta + futility_margin(depth, 0)) return refinedValue - futility_margin(depth, 0); // Step 8. Null move search with verification search @@ -1367,8 +1360,6 @@ namespace { { ss[ply].currentMove = MOVE_NULL; - pos.do_null_move(st); - // Null move dynamic reduction based on depth int R = 3 + (depth >= 5 * OnePly ? depth / 8 : 0); @@ -1376,19 +1367,30 @@ namespace { if (refinedValue - beta > PawnValueMidgame) R++; + pos.do_null_move(st); + nullValue = -search(pos, ss, -(beta-1), depth-R*OnePly, ply+1, false, threadID); pos.undo_null_move(); if (nullValue >= beta) { - if (depth < 6 * OnePly) - return beta; + // Do not return unproven mate scores + if (nullValue >= value_mate_in(PLY_MAX)) + nullValue = beta; + + // Do zugzwang verification search for high depths, don't store in TT + // if search was stopped. + if ( ( depth < 6 * OnePly + || search(pos, ss, beta, depth-5*OnePly, ply, false, threadID) >= beta) + && !AbortSearch + && !TM.thread_should_stop(threadID)) + { + assert(value_to_tt(nullValue, ply) == nullValue); - // Do zugzwang verification search - Value v = search(pos, ss, beta, depth-5*OnePly, ply, false, threadID); - if (v >= beta) - return beta; + TT.store(posKey, nullValue, VALUE_TYPE_NS_LO, depth, MOVE_NONE); + return nullValue; + } } else { // The null move failed low, which means that we may be faced with // some kind of threat. If the previous move was reduced, check if @@ -1418,13 +1420,12 @@ namespace { tte = TT.retrieve(posKey); } - // Step 10. Loop through moves - // Loop through all legal moves until no moves remain or a beta cutoff occurs - // Initialize a MovePicker object for the current position MovePicker mp = MovePicker(pos, ttMove, depth, H, &ss[ply], beta); CheckInfo ci(pos); + // Step 10. Loop through moves + // Loop through all legal moves until no moves remain or a beta cutoff occurs while ( bestValue < beta && (move = mp.get_next_move()) != MOVE_NONE && !TM.thread_should_stop(threadID)) @@ -1447,7 +1448,7 @@ namespace { if ( depth >= SingularExtensionDepthAtNonPVNodes && tte && move == tte->move() - && !excludedMove // Do not allow recursive single-reply search + && !excludedMove // Do not allow recursive singular extension search && ext < OnePly && is_lower_bound(tte->type()) && tte->depth() >= depth - 3 * OnePly) @@ -1497,8 +1498,8 @@ namespace { // Step 13. Make the move pos.do_move(move, st, ci, moveIsCheck); - // Step 14. Reduced search - // if the move fails high will be re-searched at full depth. + // Step 14. Reduced search, if the move fails high + // will be re-searched at full depth. bool doFullDepthSearch = true; if ( depth >= 3*OnePly @@ -1552,11 +1553,11 @@ namespace { } // Step 19. Check for mate and stalemate - // All legal moves have been searched and if there were + // All legal moves have been searched and if there are // no legal moves, it must be mate or stalemate. - // If one move was excluded return fail low. + // If one move was excluded return fail low score. if (!moveCount) - return excludedMove ? beta - 1 : (pos.is_check() ? value_mated_in(ply) : VALUE_DRAW); + return excludedMove ? beta - 1 : (isCheck ? value_mated_in(ply) : VALUE_DRAW); // Step 20. Update tables // If the search is not aborted, update the transposition table, @@ -1665,7 +1666,7 @@ namespace { alpha = bestValue; // If we are near beta then try to get a cutoff pushing checks a bit further - bool deepChecks = depth == -OnePly && staticValue >= beta - PawnValueMidgame / 8; + bool deepChecks = (depth == -OnePly && staticValue >= beta - PawnValueMidgame / 8); // Initialize a MovePicker object for the current position, and prepare // to search the moves. Because the depth is <= 0 here, only captures, @@ -1676,8 +1677,7 @@ namespace { enoughMaterial = pos.non_pawn_material(pos.side_to_move()) > RookValueMidgame; futilityBase = staticValue + FutilityMarginQS + ei.futilityMargin[pos.side_to_move()]; - // Loop through the moves until no moves remain or a beta cutoff - // occurs. + // Loop through the moves until no moves remain or a beta cutoff occurs while ( alpha < beta && (move = mp.get_next_move()) != MOVE_NONE) { @@ -1746,7 +1746,7 @@ namespace { // All legal moves have been searched. A special case: If we're in check // and no legal moves were found, it is checkmate. - if (!moveCount && pos.is_check()) // Mate! + if (!moveCount && isCheck) // Mate! return value_mated_in(ply); // Update transposition table @@ -2051,7 +2051,7 @@ namespace { NodesSincePoll++; if (NodesSincePoll >= NodesBetweenPolls) { - poll(ss, ply); + poll(); NodesSincePoll = 0; } } @@ -2414,7 +2414,7 @@ namespace { // looks at the time consumed so far and decides if it's time to abort the // search. - void poll(SearchStack ss[], int ply) { + void poll() { static int lastInfoTime; int t = current_search_time(); @@ -2465,16 +2465,6 @@ namespace { cout << "info nodes " << TM.nodes_searched() << " nps " << nps() << " time " << t << " hashfull " << TT.full() << endl; - - // We only support current line printing in single thread mode - if (ShowCurrentLine && TM.active_threads() == 1) - { - cout << "info currline"; - for (int p = 0; p < ply; p++) - cout << " " << ss[p].currentMove; - - cout << endl; - } } // Should we stop the search?