X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=sidebyside;f=src%2Fsearch.cpp;h=0afa0a281b60acece9abd16b0c8630e0989144d3;hb=6e06db93fde225eeae75dc8b3d5d1432c5cd14a8;hp=8313381a4ccaec06ef891e2631d07b85fdc43f68;hpb=04e1ba8aa2dd0a7dbf4110503d71494df91b4ef5;p=stockfish diff --git a/src/search.cpp b/src/search.cpp index 8313381a..0afa0a28 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -233,12 +233,6 @@ namespace { // better than the second best move. const Value EasyMoveMargin = Value(0x200); - // Last seconds noise filtering (LSN) - const bool UseLSNFiltering = true; - const int LSNTime = 100; // In milliseconds - const Value LSNValue = value_from_centipawns(200); - bool loseOnTime = false; - /// Global variables @@ -297,6 +291,8 @@ namespace { bool connected_moves(const Position& pos, Move m1, Move m2); bool value_is_mate(Value value); + Value value_to_tt(Value v, int ply); + Value value_from_tt(Value v, int ply); bool move_is_killer(Move m, SearchStack* ss); bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value beta, int ply); bool connected_threat(const Position& pos, Move m, Move threat); @@ -306,6 +302,7 @@ namespace { void update_gains(const Position& pos, Move move, Value before, Value after); int current_search_time(); + std::string value_to_uci(Value v); int nps(); void poll(); void ponderhit(); @@ -345,8 +342,8 @@ void init_search() { // Init reductions array for (hd = 1; hd < 64; hd++) for (mc = 1; mc < 64; mc++) { - double pvRed = log(double(hd)) * log(double(mc)) / 3.0; - double nonPVRed = log(double(hd)) * log(double(mc)) / 1.5; + double pvRed = 0.33 + log(double(hd)) * log(double(mc)) / 4.5; + double nonPVRed = 0.33 + log(double(hd)) * log(double(mc)) / 2.25; ReductionMatrix[PV][hd][mc] = (int8_t) ( pvRed >= 1.0 ? floor( pvRed * int(OnePly)) : 0); ReductionMatrix[NonPV][hd][mc] = (int8_t) (nonPVRed >= 1.0 ? floor(nonPVRed * int(OnePly)) : 0); } @@ -414,9 +411,8 @@ int perft(Position& pos, Depth depth) /// search-related global variables, and calls root_search(). It returns false /// when a quit command is received during the search. -bool think(const Position& pos, bool infinite, bool ponder, int side_to_move, - int time[], int increment[], int movesToGo, int maxDepth, - int maxNodes, int maxTime, Move searchMoves[]) { +bool think(const Position& pos, bool infinite, bool ponder, int time[], int increment[], + int movesToGo, int maxDepth, int maxNodes, int maxTime, Move searchMoves[]) { // Initialize global search variables StopOnPonderhit = AbortSearch = Quit = AspirationFailLow = false; @@ -448,10 +444,6 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move, } } - // Reset loseOnTime flag at the beginning of a new game - if (button_was_pressed("New Game")) - loseOnTime = false; - // Read UCI option values TT.set_size(get_option_value_int("Hash")); if (button_was_pressed("Clear Hash")) @@ -493,8 +485,8 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move, TM.wake_sleeping_threads(); // Set thinking time - int myTime = time[side_to_move]; - int myIncrement = increment[side_to_move]; + int myTime = time[pos.side_to_move()]; + int myIncrement = increment[pos.side_to_move()]; if (UseTimeManagement) { if (!movesToGo) // Sudden death time control @@ -551,36 +543,8 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move, << " increment: " << myIncrement << " moves to go: " << movesToGo << endl; - // LSN filtering. Used only for developing purposes, disabled by default - if ( UseLSNFiltering - && loseOnTime) - { - // Step 2. If after last move we decided to lose on time, do it now! - while (SearchStartTime + myTime + 1000 > get_system_time()) - /* wait here */; - } - // We're ready to start thinking. Call the iterative deepening loop function - Value v = id_loop(pos, searchMoves); - - if (UseLSNFiltering) - { - // Step 1. If this is sudden death game and our position is hopeless, - // decide to lose on time. - if ( !loseOnTime // If we already lost on time, go to step 3. - && myTime < LSNTime - && myIncrement == 0 - && movesToGo == 0 - && v < -LSNValue) - { - loseOnTime = true; - } - else if (loseOnTime) - { - // Step 3. Now after stepping over the time limit, reset flag for next match. - loseOnTime = false; - } - } + id_loop(pos, searchMoves); if (UseLogFile) LogFile.close(); @@ -622,7 +586,7 @@ namespace { // so to output information also for iteration 1. cout << "info depth " << 1 << "\ninfo depth " << 1 - << " score " << value_to_string(rml.get_move_score(0)) + << " score " << value_to_uci(rml.get_move_score(0)) << " time " << current_search_time() << " nodes " << TM.nodes_searched() << " nps " << nps() @@ -738,8 +702,7 @@ namespace { // Print final search statistics cout << "info nodes " << TM.nodes_searched() << " nps " << nps() - << " time " << current_search_time() - << " hashfull " << TT.full() << endl; + << " time " << current_search_time() << endl; // Print the best move and the ponder move to the standard output if (pv[0] == MOVE_NONE) @@ -999,7 +962,7 @@ namespace { for (int j = 0; j < Min(MultiPV, rml.move_count()); j++) { cout << "info multipv " << j + 1 - << " score " << value_to_string(rml.get_move_score(j)) + << " score " << value_to_uci(rml.get_move_score(j)) << " depth " << (j <= i ? Iteration : Iteration - 1) << " time " << current_search_time() << " nodes " << TM.nodes_searched() @@ -1204,12 +1167,12 @@ namespace { if (nullValue >= value_mate_in(PLY_MAX)) nullValue = beta; - // Do zugzwang verification search at high depths if (depth < 6 * OnePly) return nullValue; + // Do verification search at high depths ss->skipNullMove = true; - Value v = search(pos, ss, alpha, beta, depth-5*OnePly, ply); + Value v = search(pos, ss, alpha, beta, depth-R*OnePly, ply); ss->skipNullMove = false; if (v >= beta) @@ -1280,9 +1243,10 @@ namespace { // Step 11. Decide the new search depth ext = extension(pos, move, captureOrPromotion, moveIsCheck, singleEvasion, mateThreat, &dangerous); - // Singular extension search. We extend the TT move if its value is much better than - // its siblings. To verify this we do a reduced search on all the other moves but the - // ttMove, if result is lower then ttValue minus a margin then we extend ttMove. + // Singular extension search. If all moves but one fail low on a search of (alpha-s, beta-s), + // and just one fails high on (alpha, beta), then that move is singular and should be extended. + // To verify this we do a reduced search on all the other moves but the ttMove, if result is + // lower then ttValue minus a margin then we extend ttMove. if ( singularExtensionNode && move == tte->move() && ext < OnePly) @@ -1297,7 +1261,7 @@ namespace { Value v = search(pos, ss, b - 1, b, depth / 2, ply); ss->skipNullMove = false; ss->excludedMove = MOVE_NONE; - if (v < ttValue - SingularExtensionMargin) + if (v < b) ext = OnePly; } } @@ -1862,8 +1826,8 @@ namespace { } - // value_is_mate() checks if the given value is a mate one - // eventually compensated for the ply. + // value_is_mate() checks if the given value is a mate one eventually + // compensated for the ply. bool value_is_mate(Value value) { @@ -1874,8 +1838,38 @@ namespace { } - // move_is_killer() checks if the given move is among the - // killer moves of that ply. + // value_to_tt() adjusts a mate score from "plies to mate from the root" to + // "plies to mate from the current ply". Non-mate scores are unchanged. + // The function is called before storing a value to the transposition table. + + Value value_to_tt(Value v, int ply) { + + if (v >= value_mate_in(PLY_MAX)) + return v + ply; + + if (v <= value_mated_in(PLY_MAX)) + return v - ply; + + return v; + } + + + // value_from_tt() is the inverse of value_to_tt(): It adjusts a mate score from + // the transposition table to a mate score corrected for the current ply. + + Value value_from_tt(Value v, int ply) { + + if (v >= value_mate_in(PLY_MAX)) + return v - ply; + + if (v <= value_mated_in(PLY_MAX)) + return v + ply; + + return v; + } + + + // move_is_killer() checks if the given move is among the killer moves bool move_is_killer(Move m, SearchStack* ss) { @@ -2090,6 +2084,20 @@ namespace { } + // value_to_uci() converts a value to a string suitable for use with the UCI protocol + + std::string value_to_uci(Value v) { + + std::stringstream s; + + if (abs(v) < VALUE_MATE - PLY_MAX * OnePly) + s << "cp " << int(v) * 100 / int(PawnValueMidgame); // Scale to pawn = 100 + else + s << "mate " << (v > 0 ? (VALUE_MATE - v + 1) / 2 : -(VALUE_MATE + v) / 2 ); + + return s.str(); + } + // nps() computes the current nodes/second count. int nps() { @@ -2153,7 +2161,7 @@ namespace { dbg_print_hit_rate(); cout << "info nodes " << TM.nodes_searched() << " nps " << nps() - << " time " << t << " hashfull " << TT.full() << endl; + << " time " << t << endl; } // Should we stop the search? @@ -2247,7 +2255,7 @@ namespace { void print_pv_info(const Position& pos, Move pv[], Value alpha, Value beta, Value value) { cout << "info depth " << Iteration - << " score " << value_to_string(value) + << " score " << value_to_uci(value) << (value >= beta ? " lowerbound" : value <= alpha ? " upperbound" : "") << " time " << current_search_time() << " nodes " << TM.nodes_searched()