X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=sidebyside;f=src%2Fsearch.cpp;h=ddcc851eb8cfa1d014fe5ecd06d21075507500b4;hb=b7c36d078b2a11252f0b66e703e134673997fd29;hp=a9953bb69e736c4b6c3eaf071bbbabd3de28869a;hpb=c3ba5fb9d382f378541fc4c92d19f94071885c0f;p=stockfish diff --git a/src/search.cpp b/src/search.cpp index a9953bb6..ddcc851e 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -133,6 +133,9 @@ namespace { // evaluation of the position is more than NullMoveMargin below beta. const Value NullMoveMargin = Value(0x300); + // Use null capture pruning? + const bool UseNullCapturePruning = false; + // Pruning criterions. See the code and comments in ok_to_prune() to // understand their precise meaning. const bool PruneEscapeMoves = false; @@ -188,7 +191,7 @@ namespace { // Time managment variables int SearchStartTime; int MaxNodes, MaxDepth; - int MaxSearchTime, AbsoluteMaxSearchTime, ExtraSearchTime, TimeAdvantage; + int MaxSearchTime, AbsoluteMaxSearchTime, ExtraSearchTime; Move BestRootMove, PonderMove, EasyMove; int RootMoveNumber; bool InfiniteSearch; @@ -427,8 +430,6 @@ void think(const Position &pos, bool infinite, bool ponder, int side_to_move, int myIncrement = increment[side_to_move]; int oppTime = time[1 - side_to_move]; - TimeAdvantage = myTime - oppTime; - if (!movesToGo) // Sudden death time control { if (myIncrement) @@ -436,7 +437,7 @@ void think(const Position &pos, bool infinite, bool ponder, int side_to_move, MaxSearchTime = myTime / 30 + myIncrement; AbsoluteMaxSearchTime = Max(myTime / 4, myIncrement - 100); } else { // Blitz game without increment - MaxSearchTime = myTime / 40; + MaxSearchTime = myTime / 30; AbsoluteMaxSearchTime = myTime / 8; } } @@ -680,10 +681,6 @@ namespace { ExtraSearchTime = BestMoveChangesByIteration[Iteration] * (MaxSearchTime / 2) + BestMoveChangesByIteration[Iteration-1] * (MaxSearchTime / 3); - // If we need some more and we are in time advantage take it - if (ExtraSearchTime > 0 && TimeAdvantage > 2 * MaxSearchTime) - ExtraSearchTime += MaxSearchTime / 2; - // Try to guess if the current iteration is the last one or the last two LastIterations = (current_search_time() > ((MaxSearchTime + ExtraSearchTime)*58) / 128); @@ -1136,6 +1133,7 @@ namespace { Value approximateEval = quick_evaluate(pos); bool mateThreat = false; + bool nullCapturePruning = false; bool isCheck = pos.is_check(); // Null move search @@ -1149,7 +1147,20 @@ namespace { UndoInfo u; pos.do_null_move(u); int R = (depth > 7 ? 4 : 3); + Value nullValue = -search(pos, ss, -(beta-1), depth-R*OnePly, ply+1, false, threadID); + + // Check for a null capture artifact, if the value without the null capture + // is above beta then mark the node as a suspicious failed low. We will verify + // later if we are really under threat. + if ( UseNullCapturePruning + && nullValue < beta + && depth < 5 * OnePly + && ss[ply + 1].currentMove != MOVE_NONE + && pos.move_is_capture(ss[ply + 1].currentMove) + && pos.see(ss[ply + 1].currentMove) * PawnValueMidgame + nullValue > beta) + nullCapturePruning = true; + pos.undo_null_move(u); if (nullValue >= beta) @@ -1176,6 +1187,26 @@ namespace { && ss[ply - 1].reduction && connected_moves(pos, ss[ply - 1].currentMove, ss[ply].threatMove)) return beta - 1; + + if (nullCapturePruning && !mateThreat) + { + // The null move failed low due to a suspicious capture. Verify if + // position is really dangerous or we are facing a null capture + // artifact due to the side to move change. So search this + // position with a reduced depth and see if we still fail low. + Move tm = ss[ply].threatMove; + + assert(tm != MOVE_NONE); + + Value v = search(pos, ss, beta, depth-3*OnePly, ply, false, threadID); + if (v >= beta) + return beta; + + // Restore stack and update ttMove if was empty + ss[ply].threatMove = tm; + if (ttMove == MOVE_NONE) + ttMove = ss[ply].pv[ply]; + } } } // Null move search not allowed, try razoring