X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=fc877f3040d0923943a2a21c34f64af2a24b6bbc;hp=8d8d700114153d7642b91876b9f196ec2a58e379;hb=0c1f119069bf915b85126159d4865c4bcc532239;hpb=ced29248c93de7fc5a4e284807f8f052006e647c diff --git a/src/search.cpp b/src/search.cpp index 8d8d7001..fc877f30 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -68,24 +68,25 @@ 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. - const int CounterMovePruneThreshold = VALUE_ZERO; + // Threshold used for countermoves based pruning + const int CounterMovePruneThreshold = 0; template Depth reduction(bool i, Depth d, int mn) { return Reductions[PvNode][i][std::min(d / ONE_PLY, 63)][std::min(mn, 63)] * ONE_PLY; } // History and stats update bonus, based on depth - Value stat_bonus(Depth depth) { + int stat_bonus(Depth depth) { int d = depth / ONE_PLY ; - return d > 17 ? VALUE_ZERO : Value(d * d + 2 * d - 2); + return d > 17 ? 0 : d * d + 2 * d - 2; } // Skill structure is used to implement strength limit @@ -151,8 +152,8 @@ namespace { Value value_to_tt(Value v, int ply); Value value_from_tt(Value v, int ply); void update_pv(Move* pv, Move move, Move* childPv); - void update_cm_stats(Stack* ss, Piece pc, Square s, Value bonus); - void update_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietsCnt, Value bonus); + void update_cm_stats(Stack* ss, Piece pc, Square s, int bonus); + void update_stats(const Position& pos, Stack* ss, Move move, Move* quiets, int quietsCnt, int bonus); void check_time(); } // namespace @@ -195,8 +196,10 @@ void Search::clear() { th->counterMoves.clear(); th->history.clear(); th->counterMoveHistory.clear(); - th->counterMoveHistory[NO_PIECE][0].fill(Value(CounterMovePruneThreshold-1)); th->resetCalls = true; + CounterMoveStats& cm = th->counterMoveHistory[NO_PIECE][0]; + int* t = &cm[NO_PIECE][0]; + std::fill(t, t + sizeof(cm), CounterMovePruneThreshold - 1); } Threads.main()->previousScore = VALUE_INFINITE; @@ -553,8 +556,8 @@ namespace { // Step 1. Initialize node Thread* thisThread = pos.this_thread(); inCheck = pos.checkers(); - moveCount = quietCount = ss->moveCount = 0; - ss->history = VALUE_ZERO; + moveCount = quietCount = ss->moveCount = 0; + ss->history = 0; bestValue = -VALUE_INFINITE; ss->ply = (ss-1)->ply + 1; @@ -562,9 +565,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; } @@ -639,7 +643,7 @@ namespace { // Penalty for a quiet ttMove that fails low else if (!pos.capture_or_promotion(ttMove)) { - Value penalty = -stat_bonus(depth); + int penalty = -stat_bonus(depth); thisThread->history.update(pos.side_to_move(), ttMove, penalty); update_cm_stats(ss, pos.moved_piece(ttMove), to_sq(ttMove), penalty); } @@ -875,7 +879,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 +893,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 +908,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 +979,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)] @@ -985,10 +990,10 @@ moves_loop: // When in check search starts from here - 4000; // Correction factor // Decrease/increase reduction by comparing opponent's stat score - if (ss->history > VALUE_ZERO && (ss-1)->history < VALUE_ZERO) + if (ss->history > 0 && (ss-1)->history < 0) r -= ONE_PLY; - else if (ss->history < VALUE_ZERO && (ss-1)->history > VALUE_ZERO) + else if (ss->history < 0 && (ss-1)->history > 0) r += ONE_PLY; // Decrease/increase reduction for moves with a good/bad history @@ -1111,7 +1116,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 +1130,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); @@ -1278,13 +1282,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 && 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 @@ -1382,7 +1387,7 @@ moves_loop: // When in check search starts from here // update_cm_stats() updates countermove and follow-up move history - void update_cm_stats(Stack* ss, Piece pc, Square s, Value bonus) { + void update_cm_stats(Stack* ss, Piece pc, Square s, int bonus) { for (int i : {1, 2, 4}) if (is_ok((ss-i)->currentMove)) @@ -1393,7 +1398,7 @@ moves_loop: // When in check search starts from here // update_stats() updates move sorting heuristics when a new quiet best move is found void update_stats(const Position& pos, Stack* ss, Move move, - Move* quiets, int quietsCnt, Value bonus) { + Move* quiets, int quietsCnt, int bonus) { if (ss->killers[0] != move) { @@ -1499,7 +1504,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;