X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=9d3734b89365c670415c0a9f8070526ea1e4bc90;hp=5ff23ad0fd894791c7b5e8ac625246c40343e1e5;hb=8a61b030a6cbfa70b7a473e31ae2662f1b8f39b9;hpb=36c82b751ce227c05bfb0dc74c311a469f7f8ec4 diff --git a/src/search.cpp b/src/search.cpp index 5ff23ad0..9d3734b8 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -88,6 +88,7 @@ namespace { Value DrawValue[COLOR_NB]; History Hist; Gains Gain; + RefutationTable Refutation; template Value search(Position& pos, Stack* ss, Value alpha, Value beta, Depth depth); @@ -145,7 +146,7 @@ void Search::init() { // Init futility move count array for (d = 0; d < 32; d++) - FutilityMoveCounts[d] = int(3.001 + 0.25 * pow(double(d), 2.0)); + FutilityMoveCounts[d] = int(3.001 + 0.3 * pow(double(d), 1.8)); } @@ -264,6 +265,10 @@ void Search::think() { finalize: + // When search is stopped this info is not printed + sync_cout << "info nodes " << RootPos.nodes_searched() + << " time " << Time::now() - SearchTime + 1 << sync_endl; + // When we reach max depth we arrive here even without Signals.stop is raised, // 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" @@ -301,6 +306,7 @@ namespace { TT.new_search(); Hist.clear(); Gain.clear(); + Refutation.clear(); PVSize = Options["MultiPV"]; Skill skill(Options["Skill Level"]); @@ -440,6 +446,7 @@ namespace { if ( depth >= 12 && !stop && PVSize == 1 + && bestValue > VALUE_MATED_IN_MAX_PLY && ( RootMoves.size() == 1 || Time::now() - SearchTime > (TimeMgr.available_time() * 20) / 100)) { @@ -522,6 +529,7 @@ namespace { bestValue = -VALUE_INFINITE; ss->currentMove = threatMove = (ss+1)->excludedMove = bestMove = MOVE_NONE; ss->ply = (ss-1)->ply + 1; + ss->futilityMoveCount = 0; (ss+1)->skipNullMove = false; (ss+1)->reduction = DEPTH_ZERO; (ss+2)->killers[0] = (ss+2)->killers[1] = MOVE_NONE; @@ -532,7 +540,7 @@ namespace { if (!RootNode) { // Step 2. Check for aborted search and immediate draw - if (Signals.stop || pos.is_draw() || ss->ply > MAX_PLY) + if (Signals.stop || pos.is_draw() || ss->ply > MAX_PLY) return DrawValue[pos.side_to_move()]; // Step 3. Mate distance pruning. Even if we mate at the next move our score @@ -642,10 +650,11 @@ namespace { && !ss->skipNullMove && depth < 4 * ONE_PLY && !inCheck - && eval - FutilityMargins[depth][0] >= beta + && eval - futility_margin(depth, (ss-1)->futilityMoveCount) >= beta && abs(beta) < VALUE_MATE_IN_MAX_PLY + && abs(eval) < VALUE_KNOWN_WIN && pos.non_pawn_material(pos.side_to_move())) - return eval - FutilityMargins[depth][0]; + return eval - futility_margin(depth, (ss-1)->futilityMoveCount); // Step 8. Null move search with verification search (is omitted in PV nodes) if ( !PvNode @@ -678,7 +687,7 @@ namespace { if (nullValue >= VALUE_MATE_IN_MAX_PLY) nullValue = beta; - if (depth < 6 * ONE_PLY) + if (depth < 12 * ONE_PLY) return nullValue; // Do verification search at high depths @@ -757,7 +766,12 @@ namespace { split_point_start: // At split points actual search starts from here - MovePicker mp(pos, ttMove, depth, Hist, ss, PvNode ? -VALUE_INFINITE : beta); + Move prevMove = (ss-1)->currentMove; + Square prevSq = to_sq(prevMove); + Piece prevP = pos.piece_on(prevSq); + Move refutationMove = Refutation.get(prevP, prevSq); + + MovePicker mp(pos, ttMove, depth, Hist, ss, refutationMove, PvNode ? -VALUE_INFINITE : beta); CheckInfo ci(pos); value = bestValue; // Workaround a bogus 'uninitialized' warning under gcc singularExtensionNode = !RootNode @@ -856,7 +870,7 @@ split_point_start: // At split points actual search starts from here && !captureOrPromotion && !inCheck && !dangerous - && move != ttMove + /* && move != ttMove Already implicit in the next condition */ && bestValue > VALUE_MATED_IN_MAX_PLY) { // Move count based pruning @@ -875,7 +889,7 @@ split_point_start: // At split points actual search starts from here // but fixing this made program slightly weaker. Depth predictedDepth = newDepth - reduction(depth, moveCount); futilityValue = ss->staticEval + ss->evalMargin + futility_margin(predictedDepth, moveCount) - + 2 * Gain[pos.piece_moved(move)][to_sq(move)]; + + Gain[pos.piece_moved(move)][to_sq(move)]; if (futilityValue < beta) { @@ -899,7 +913,13 @@ split_point_start: // At split points actual search starts from here continue; } + + // We have not pruned the move that will be searched, but remember how + // far in the move list we are to be more aggressive in the child node. + ss->futilityMoveCount = moveCount; } + else + ss->futilityMoveCount = 0; // Check for legality only before to do the move if (!RootNode && !SpNode && !pos.pl_move_is_legal(move, ci.pinned)) @@ -1077,6 +1097,7 @@ split_point_start: // At split points actual search starts from here // Increase history value of the cut-off move Value bonus = Value(int(depth) * int(depth)); Hist.update(pos.piece_moved(bestMove), to_sq(bestMove), bonus); + Refutation.update(prevP, prevSq, bestMove); // Decrease history of all the other played non-capture moves for (int i = 0; i < playedMoveCount - 1; i++) @@ -1128,7 +1149,7 @@ split_point_start: // At split points actual search starts from here ss->ply = (ss-1)->ply + 1; // Check for an instant draw or maximum ply reached - if (pos.is_draw() || ss->ply > MAX_PLY) + if (pos.is_draw() || ss->ply > MAX_PLY) return DrawValue[pos.side_to_move()]; // Decide whether or not to include checks, this fixes also the type of @@ -1224,10 +1245,11 @@ split_point_start: // At split points actual search starts from here continue; } - // Prune moves with negative or equal SEE + // Prune moves with negative or equal SEE and also moves with positive + // SEE where capturing piece loses a tempo and SEE < beta - futilityBase. if ( futilityBase < beta && depth < DEPTH_ZERO - && pos.see(move) <= 0) + && pos.see(move, beta - futilityBase) <= 0) { bestValue = std::max(bestValue, futilityBase); continue; @@ -1577,7 +1599,7 @@ void RootMove::extract_pv_from_tt(Position& pos) { && pos.is_pseudo_legal(m = tte->move()) // Local copy, TT could change && pos.pl_move_is_legal(m, pos.pinned_pieces()) && ply < MAX_PLY - && (!pos.is_draw() || ply < 2)); + && (!pos.is_draw() || ply < 2)); pv.push_back(MOVE_NONE); // Must be zero-terminating