X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=2e8d5c6ff2ec3fbf530f78846822ad9805571eb6;hp=433129d9b5737659cacc8a9307d803a9a0e2d30d;hb=1d31065e1d1f04ecf47fc959523c560e8657fbfa;hpb=9da3b44ddc7bc9ea7094b91663cbc0f8319c46be diff --git a/src/search.cpp b/src/search.cpp index 433129d9..2e8d5c6f 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -68,14 +68,15 @@ namespace { const int skipPhase[] = { 0, 1, 0, 1, 2, 3, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 7 }; // Razoring and futility margin based on depth - const int razor_margin[4] = { 483, 570, 603, 554 }; + // razor_margin[0] is unused as long as depth >= ONE_PLY in search + const int razor_margin[] = { 0, 570, 603, 554 }; Value futility_margin(Depth d) { return Value(150 * d / ONE_PLY); } // Futility and reductions lookup tables, initialized at startup int FutilityMoveCounts[2][16]; // [improving][depth] int Reductions[2][2][64][64]; // [pv][improving][depth][moveNumber] - // Threshold used for countermoves based pruning. + // Threshold used for countermoves based pruning const int CounterMovePruneThreshold = 0; template Depth reduction(bool i, Depth d, int mn) { @@ -184,7 +185,7 @@ void Search::init() { } -/// Search::clear() resets search state to zero, to obtain reproducible results +/// Search::clear() resets search state to its initial value, to obtain reproducible results void Search::clear() { @@ -195,8 +196,11 @@ void Search::clear() { th->counterMoves.clear(); th->history.clear(); th->counterMoveHistory.clear(); - th->counterMoveHistory[NO_PIECE][0].fill(CounterMovePruneThreshold-1); th->resetCalls = true; + + CounterMoveStats& cm = th->counterMoveHistory[NO_PIECE][0]; + auto* t = &cm[NO_PIECE][0]; + std::fill(t, t + sizeof(cm)/sizeof(*t), CounterMovePruneThreshold - 1); } Threads.main()->previousScore = VALUE_INFINITE; @@ -553,7 +557,7 @@ namespace { // Step 1. Initialize node Thread* thisThread = pos.this_thread(); inCheck = pos.checkers(); - moveCount = quietCount = ss->moveCount = 0; + moveCount = quietCount = ss->moveCount = 0; ss->history = 0; bestValue = -VALUE_INFINITE; ss->ply = (ss-1)->ply + 1; @@ -562,9 +566,10 @@ namespace { if (thisThread->resetCalls.load(std::memory_order_relaxed)) { thisThread->resetCalls = false; + // At low node count increase the checking rate to about 0.1% of nodes // otherwise use a default value. - thisThread->callsCnt = Limits.nodes ? std::min((int64_t)4096, Limits.nodes / 1024) + thisThread->callsCnt = Limits.nodes ? std::min(4096, int(Limits.nodes / 1024)) : 4096; } @@ -875,7 +880,7 @@ moves_loop: // When in check search starts from here // (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 and if the result is lower than - // ttValue minus a margin then we extend the ttMove. + // ttValue minus a margin then we will extend the ttMove. if ( singularExtensionNode && move == ttMove && pos.legal(move)) @@ -889,9 +894,9 @@ moves_loop: // When in check search starts from here if (value < rBeta) extension = ONE_PLY; } - else if ( givesCheck + else if ( givesCheck && !moveCountPruning - && pos.see_ge(move, VALUE_ZERO)) + && pos.see_ge(move)) extension = ONE_PLY; // Calculate new depth for this move @@ -904,10 +909,11 @@ moves_loop: // When in check search starts from here { if ( !captureOrPromotion && !givesCheck - && (!pos.advanced_pawn_push(move) || pos.non_pawn_material() >= 5000)) + && (!pos.advanced_pawn_push(move) || pos.non_pawn_material() >= Value(5000))) { // Move count based pruning - if (moveCountPruning) { + if (moveCountPruning) + { skipQuiets = true; continue; } @@ -974,8 +980,8 @@ moves_loop: // When in check search starts from here // Decrease reduction for moves that escape a capture. Filter out // castling moves, because they are coded as "king captures rook" and // hence break make_move(). - else if ( type_of(move) == NORMAL - && !pos.see_ge(make_move(to_sq(move), from_sq(move)), VALUE_ZERO)) + else if ( type_of(move) == NORMAL + && !pos.see_ge(make_move(to_sq(move), from_sq(move)))) r -= 2 * ONE_PLY; ss->history = cmh[moved_piece][to_sq(move)] @@ -1111,7 +1117,6 @@ moves_loop: // When in check search starts from here : inCheck ? mated_in(ss->ply) : DrawValue[pos.side_to_move()]; else if (bestMove) { - // Quiet best move: update move sorting heuristics if (!pos.capture_or_promotion(bestMove)) update_stats(pos, ss, bestMove, quietsSearched, quietCount, stat_bonus(depth)); @@ -1126,11 +1131,11 @@ moves_loop: // When in check search starts from here && is_ok((ss-1)->currentMove)) update_cm_stats(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth)); - if(!excludedMove) + if (!excludedMove) tte->save(posKey, value_to_tt(bestValue, ss->ply), - bestValue >= beta ? BOUND_LOWER : - PvNode && bestMove ? BOUND_EXACT : BOUND_UPPER, - depth, bestMove, ss->staticEval, TT.generation()); + bestValue >= beta ? BOUND_LOWER : + PvNode && bestMove ? BOUND_EXACT : BOUND_UPPER, + depth, bestMove, ss->staticEval, TT.generation()); assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE); @@ -1160,6 +1165,7 @@ moves_loop: // When in check search starts from here Value bestValue, value, ttValue, futilityValue, futilityBase, oldAlpha; bool ttHit, givesCheck, evasionPrunable; Depth ttDepth; + int moveCount; if (PvNode) { @@ -1170,6 +1176,7 @@ moves_loop: // When in check search starts from here ss->currentMove = bestMove = MOVE_NONE; ss->ply = (ss-1)->ply + 1; + moveCount = 0; // Check for an instant draw or if the maximum ply has been reached if (pos.is_draw(ss->ply) || ss->ply >= MAX_PLY) @@ -1253,6 +1260,8 @@ moves_loop: // When in check search starts from here ? pos.check_squares(type_of(pos.piece_on(from_sq(move)))) & to_sq(move) : pos.gives_check(move); + moveCount++; + // Futility pruning if ( !InCheck && !givesCheck @@ -1278,13 +1287,14 @@ moves_loop: // When in check search starts from here // Detect non-capture evasions that are candidates to be pruned evasionPrunable = InCheck + && (depth != DEPTH_ZERO || moveCount > 2) && bestValue > VALUE_MATED_IN_MAX_PLY && !pos.capture(move); // Don't search moves with negative SEE values if ( (!InCheck || evasionPrunable) && type_of(move) != PROMOTION - && !pos.see_ge(move, VALUE_ZERO)) + && !pos.see_ge(move)) continue; // Speculative prefetch as early as possible @@ -1292,7 +1302,10 @@ moves_loop: // When in check search starts from here // Check for legality just before making the move if (!pos.legal(move)) + { + moveCount--; continue; + } ss->currentMove = move; @@ -1499,7 +1512,7 @@ string UCI::pv(const Position& pos, Depth depth, Value alpha, Value beta) { for (size_t i = 0; i < multiPV; ++i) { - bool updated = (i <= PVIdx); + bool updated = (i <= PVIdx && rootMoves[i].score != -VALUE_INFINITE); if (depth == ONE_PLY && !updated) continue;