X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsearch.cpp;h=d2e3cd32caef87b97a523d53708532de0c9a0c71;hp=f981664dbb9255fd2efb75c7ef13b11e3d90e112;hb=01b228b5e179d2e15927d617c5415302be234e3f;hpb=7bcd97933a20b649964bf96eb840a6190e777428 diff --git a/src/search.cpp b/src/search.cpp index f981664d..d2e3cd32 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -158,35 +158,40 @@ namespace { }; - /// Constants + /// Adjustments - // Search depth at iteration 1 - const Depth InitialDepth = OnePly; + // Step 6. Razoring + + const Depth RazorDepth = 4 * OnePly; + inline Value razor_margin(Depth d) { return Value(0x200 + 0x10 * d); } + + // Step 8. Null move search with verification search + + // Null move margin. A null move search will not be done if the static + // evaluation of the position is more than NullMoveMargin below beta. + const Value NullMoveMargin = Value(0x200); - // Use internal iterative deepening? - const bool UseIIDAtPVNodes = true; - const bool UseIIDAtNonPVNodes = true; + // Step 9. Internal iterative deepening - // Internal iterative deepening margin. At Non-PV moves, when - // UseIIDAtNonPVNodes is true, we do an internal iterative deepening + const Depth IIDDepthAtPVNodes = 5 * OnePly; + const Depth IIDDepthAtNonPVNodes = 8 * OnePly; + + // Internal iterative deepening margin. At Non-PV nodes + // we do an internal iterative deepening // search when the static evaluation is at most IIDMargin below beta. const Value IIDMargin = Value(0x100); + // Search depth at iteration 1 + const Depth InitialDepth = OnePly; + // Easy move margin. An easy move candidate must be at least this much // better than the second best move. const Value EasyMoveMargin = Value(0x200); - // Null move margin. A null move search will not be done if the static - // evaluation of the position is more than NullMoveMargin below beta. - const Value NullMoveMargin = Value(0x200); - // If the TT move is at least SingleReplyMargin better then the // remaining ones we will extend it. const Value SingleReplyMargin = Value(0x20); - // Depth limit for razoring - const Depth RazorDepth = 4 * OnePly; - /// Lookup tables initialized at startup // Reduction lookup tables and their getter functions @@ -1039,14 +1044,16 @@ namespace { assert(threadID >= 0 && threadID < TM.active_threads()); Move movesSearched[256]; + EvalInfo ei; StateInfo st; const TTEntry* tte; Move ttMove, move; Depth ext, newDepth; - Value oldAlpha, value; - bool isCheck, mateThreat, singleEvasion, moveIsCheck, captureOrPromotion, dangerous; + Value bestValue, value, oldAlpha; + bool isCheck, singleEvasion, moveIsCheck, captureOrPromotion, dangerous; + bool mateThreat = false; int moveCount = 0; - Value bestValue = value = -VALUE_INFINITE; + bestValue = value = -VALUE_INFINITE; if (depth < OnePly) return qsearch(pos, ss, alpha, beta, Depth(0), ply, threadID); @@ -1085,7 +1092,6 @@ namespace { isCheck = pos.is_check(); if (!isCheck) { - EvalInfo ei; ss[ply].eval = evaluate(pos, ei, threadID); update_gains(pos, ss[ply - 1].currentMove, ss[ply - 1].eval, ss[ply].eval); } @@ -1095,8 +1101,7 @@ namespace { // Step 8. Null move search with verification search (is omitted in PV nodes) // Step 9. Internal iterative deepening - if ( UseIIDAtPVNodes - && depth >= 5*OnePly + if ( depth >= IIDDepthAtPVNodes && ttMove == MOVE_NONE) { search_pv(pos, ss, alpha, beta, depth-2*OnePly, ply, threadID); @@ -1331,15 +1336,15 @@ namespace { if ( !value_is_mate(beta) && !isCheck && depth < RazorDepth - && refinedValue < beta - (0x200 + 16 * depth) + && refinedValue < beta - razor_margin(depth) && ss[ply - 1].currentMove != MOVE_NULL && ttMove == MOVE_NONE && !pos.has_pawn_on_7th(pos.side_to_move())) { - Value rbeta = beta - (0x200 + 16 * depth); + Value rbeta = beta - razor_margin(depth); Value v = qsearch(pos, ss, rbeta-1, rbeta, Depth(0), ply, threadID); if (v < rbeta) - return v; //FIXME: Logically should be: return (v + 0x200 + 16 * depth); + return v; //FIXME: Logically should be: return (v + razor_margin(depth)); } // Step 7. Static null move pruning @@ -1405,8 +1410,10 @@ namespace { } // Step 9. Internal iterative deepening - if (UseIIDAtNonPVNodes && ttMove == MOVE_NONE && depth >= 8*OnePly && - !isCheck && ss[ply].eval >= beta - IIDMargin) + if ( depth >= IIDDepthAtNonPVNodes + && ttMove == MOVE_NONE + && !isCheck + && ss[ply].eval >= beta - IIDMargin) { search(pos, ss, beta, depth/2, ply, false, threadID); ttMove = ss[ply].pv[ply]; @@ -1778,20 +1785,25 @@ namespace { // splitting, we don't have to repeat all this work in sp_search(). We // also don't need to store anything to the hash table here: This is taken // care of after we return from the split point. + // FIXME: We are currently ignoring mateThreat flag here void sp_search(SplitPoint* sp, int threadID) { assert(threadID >= 0 && threadID < TM.active_threads()); assert(TM.active_threads() > 1); - Position pos(*sp->pos); - CheckInfo ci(pos); - SearchStack* ss = sp->sstack[threadID]; StateInfo st; - Value value = -VALUE_INFINITE; Move move; + Depth ext, newDepth; + Value value, futilityValueScaled; + bool isCheck, moveIsCheck, captureOrPromotion, dangerous; int moveCount; - bool isCheck = pos.is_check(); + value = -VALUE_INFINITE; + + Position pos(*sp->pos); + CheckInfo ci(pos); + SearchStack* ss = sp->sstack[threadID]; + isCheck = pos.is_check(); // Step 10. Loop through moves // Loop through all legal moves until no moves remain or a beta cutoff occurs @@ -1806,13 +1818,12 @@ namespace { assert(move_is_ok(move)); - bool moveIsCheck = pos.move_is_check(move, ci); - bool captureOrPromotion = pos.move_is_capture_or_promotion(move); + moveIsCheck = pos.move_is_check(move, ci); + captureOrPromotion = pos.move_is_capture_or_promotion(move); // Step 11. Decide the new search depth - bool dangerous; - Depth ext = extension(pos, move, false, captureOrPromotion, moveIsCheck, false, false, &dangerous); - Depth newDepth = sp->depth - OnePly + ext; + ext = extension(pos, move, false, captureOrPromotion, moveIsCheck, false, false, &dangerous); + newDepth = sp->depth - OnePly + ext; // Update current move ss[sp->ply].currentMove = move; @@ -1834,7 +1845,7 @@ namespace { // Value based pruning Depth predictedDepth = newDepth - nonpv_reduction(sp->depth, moveCount); - Value futilityValueScaled = ss[sp->ply].eval + futility_margin(predictedDepth, moveCount) + futilityValueScaled = ss[sp->ply].eval + futility_margin(predictedDepth, moveCount) + H.gain(pos.piece_on(move_from(move)), move_to(move)) + 45; if (futilityValueScaled < sp->beta) @@ -1909,19 +1920,24 @@ namespace { // don't have to repeat all this work in sp_search_pv(). We also don't // need to store anything to the hash table here: This is taken care of // after we return from the split point. + // FIXME: We are ignoring mateThreat flag! void sp_search_pv(SplitPoint* sp, int threadID) { assert(threadID >= 0 && threadID < TM.active_threads()); assert(TM.active_threads() > 1); + StateInfo st; + Move move; + Depth ext, newDepth; + Value value; + bool moveIsCheck, captureOrPromotion, dangerous; + int moveCount; + value = -VALUE_INFINITE; + Position pos(*sp->pos); CheckInfo ci(pos); SearchStack* ss = sp->sstack[threadID]; - StateInfo st; - Value value = -VALUE_INFINITE; - int moveCount; - Move move; // Step 10. Loop through moves // Loop through all legal moves until no moves remain or a beta cutoff occurs @@ -1936,13 +1952,12 @@ namespace { assert(move_is_ok(move)); - bool moveIsCheck = pos.move_is_check(move, ci); - bool captureOrPromotion = pos.move_is_capture_or_promotion(move); + moveIsCheck = pos.move_is_check(move, ci); + captureOrPromotion = pos.move_is_capture_or_promotion(move); // Step 11. Decide the new search depth - bool dangerous; - Depth ext = extension(pos, move, true, captureOrPromotion, moveIsCheck, false, false, &dangerous); - Depth newDepth = sp->depth - OnePly + ext; + ext = extension(pos, move, true, captureOrPromotion, moveIsCheck, false, false, &dangerous); + newDepth = sp->depth - OnePly + ext; // Update current move ss[sp->ply].currentMove = move;