]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
Small cleanup of unused code in sp_search
[stockfish] / src / search.cpp
index 1668a74a40a3bfcf87b2e45300ca6a4706a4537a..64cdf1c4e5fac5f27d679e7ed4c2ad865c961a19 100644 (file)
@@ -172,9 +172,9 @@ namespace {
   // best move from the previous iteration, Problem is set back to false.
   const Value NoProblemMargin = Value(0x14);
 
-  // Null move margin. A null move search will not be done if the approximate
+  // 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(0x300);
+  const Value NullMoveMargin = Value(0x200);
 
   // If the TT move is at least SingleReplyMargin better then the
   // remaining ones we will extend it.
@@ -190,13 +190,6 @@ namespace {
   // Depth limit for razoring
   const Depth RazorDepth = 4 * OnePly;
 
-  // Remaining depth:                 1 ply         1.5 ply       2 ply         2.5 ply       3 ply         3.5 ply
-  const Value RazorMargins[6]     = { Value(0x180), Value(0x300), Value(0x300), Value(0x3C0), Value(0x3C0), Value(0x3C0) };
-
-  // Remaining depth:                 1 ply         1.5 ply       2 ply         2.5 ply       3 ply         3.5 ply
-  const Value RazorApprMargins[6] = { Value(0x520), Value(0x300), Value(0x300), Value(0x300), Value(0x300), Value(0x300) };
-
-
   /// Variables initialized by UCI options
 
   // Minimum number of full depth (i.e. non-reduced) moves at PV and non-PV nodes
@@ -231,7 +224,7 @@ namespace {
   int SearchStartTime;
   int MaxNodes, MaxDepth;
   int MaxSearchTime, AbsoluteMaxSearchTime, ExtraSearchTime, ExactMaxTime;
-  bool InfiniteSearch, PonderSearch, StopOnPonderhit;
+  bool UseTimeManagement, InfiniteSearch, PonderSearch, StopOnPonderhit;
   bool AbortSearch, Quit;
   bool FailHigh, FailLow, Problem;
 
@@ -288,6 +281,7 @@ namespace {
   bool ok_to_do_nullmove(const Position& pos);
   bool ok_to_prune(const Position& pos, Move m, Move threat);
   bool ok_to_use_TT(const TTEntry* tte, Depth depth, Value beta, int ply);
+  Value refine_eval(const TTEntry* tte, Value defaultEval, int ply);
   void update_history(const Position& pos, Move move, Depth depth, Move movesSearched[], int moveCount);
   void update_killers(Move m, SearchStack& ss);
 
@@ -325,6 +319,13 @@ namespace {
 //// Functions
 ////
 
+//FIXME: HACK
+static double lnArray[512];
+
+inline double ln(int i)
+{
+    return lnArray[i];
+}
 
 /// perft() is our utility to verify move generation is bug free. All the legal
 /// moves up to given depth are generated and counted and the sum returned.
@@ -365,8 +366,20 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move,
            int time[], int increment[], int movesToGo, int maxDepth,
            int maxNodes, int maxTime, Move searchMoves[]) {
 
-  // Look for a book move
-  if (!infinite && !ponder && get_option_value_bool("OwnBook"))
+  // Initialize global search variables
+  Idle = StopOnPonderhit = AbortSearch = Quit = false;
+  FailHigh = FailLow = Problem = false;
+  NodesSincePoll = 0;
+  SearchStartTime = get_system_time();
+  ExactMaxTime = maxTime;
+  MaxDepth = maxDepth;
+  MaxNodes = maxNodes;
+  InfiniteSearch = infinite;
+  PonderSearch = ponder;
+  UseTimeManagement = !ExactMaxTime && !MaxDepth && !MaxNodes && !InfiniteSearch;
+
+  // Look for a book move, only during games, not tests
+  if (UseTimeManagement && !ponder && get_option_value_bool("OwnBook"))
   {
       Move bookMove;
       if (get_option_value_string("Book File") != OpeningBook.file_name())
@@ -380,15 +393,6 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move,
       }
   }
 
-  // Initialize global search variables
-  Idle = StopOnPonderhit = AbortSearch = Quit = false;
-  FailHigh = FailLow = Problem = false;
-  SearchStartTime = get_system_time();
-  ExactMaxTime = maxTime;
-  NodesSincePoll = 0;
-  InfiniteSearch = infinite;
-  PonderSearch = ponder;
-
   for (int i = 0; i < THREAD_MAX; i++)
   {
       Threads[i].nodes = 0ULL;
@@ -456,51 +460,45 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move,
   // Set thinking time
   int myTime = time[side_to_move];
   int myIncrement = increment[side_to_move];
-
-  if (!movesToGo) // Sudden death time control
+  if (UseTimeManagement)
   {
-      if (myIncrement)
+      if (!movesToGo) // Sudden death time control
       {
-          MaxSearchTime = myTime / 30 + myIncrement;
-          AbsoluteMaxSearchTime = Max(myTime / 4, myIncrement - 100);
-      }
-      else // Blitz game without increment
-      {
-          MaxSearchTime = myTime / 30;
-          AbsoluteMaxSearchTime = myTime / 8;
+          if (myIncrement)
+          {
+              MaxSearchTime = myTime / 30 + myIncrement;
+              AbsoluteMaxSearchTime = Max(myTime / 4, myIncrement - 100);
+          }
+          else // Blitz game without increment
+          {
+              MaxSearchTime = myTime / 30;
+              AbsoluteMaxSearchTime = myTime / 8;
+          }
       }
-  }
-  else // (x moves) / (y minutes)
-  {
-      if (movesToGo == 1)
+      else // (x moves) / (y minutes)
       {
-          MaxSearchTime = myTime / 2;
-          AbsoluteMaxSearchTime = (myTime > 3000)? (myTime - 500) : ((myTime * 3) / 4);
+          if (movesToGo == 1)
+          {
+              MaxSearchTime = myTime / 2;
+              AbsoluteMaxSearchTime = (myTime > 3000)? (myTime - 500) : ((myTime * 3) / 4);
+          }
+          else
+          {
+              MaxSearchTime = myTime / Min(movesToGo, 20);
+              AbsoluteMaxSearchTime = Min((4 * myTime) / movesToGo, myTime / 3);
+          }
       }
-      else
+
+      if (PonderingEnabled)
       {
-          MaxSearchTime = myTime / Min(movesToGo, 20);
-          AbsoluteMaxSearchTime = Min((4 * myTime) / movesToGo, myTime / 3);
+          MaxSearchTime += MaxSearchTime / 4;
+          MaxSearchTime = Min(MaxSearchTime, AbsoluteMaxSearchTime);
       }
   }
 
-  if (PonderingEnabled)
-  {
-      MaxSearchTime += MaxSearchTime / 4;
-      MaxSearchTime = Min(MaxSearchTime, AbsoluteMaxSearchTime);
-  }
-
-  // Fixed depth or fixed number of nodes?
-  MaxDepth = maxDepth;
-  if (MaxDepth)
-      InfiniteSearch = true; // HACK
-
-  MaxNodes = maxNodes;
+  // Set best NodesBetweenPolls interval
   if (MaxNodes)
-  {
       NodesBetweenPolls = Min(MaxNodes, 30000);
-      InfiniteSearch = true; // HACK
-  }
   else if (myTime && myTime < 1000)
       NodesBetweenPolls = 1000;
   else if (myTime && myTime < 5000)
@@ -561,8 +559,14 @@ bool think(const Position& pos, bool infinite, bool ponder, int side_to_move,
 /// and initializes the split point stack and the global locks and condition
 /// objects.
 
+#include <cmath> //FIXME: HACK
+
 void init_threads() {
 
+  // FIXME: HACK!!
+  for (int i = 0; i < 512; i++)
+    lnArray[i] = log(double(i));
+
   volatile int i;
 
 #if !defined(_MSC_VER)
@@ -648,6 +652,7 @@ void SearchStack::init(int ply) {
   pv[ply] = pv[ply + 1] = MOVE_NONE;
   currentMove = threatMove = MOVE_NONE;
   reduction = Depth(0);
+  eval = VALUE_NONE;
 }
 
 void SearchStack::initKillers() {
@@ -777,7 +782,7 @@ namespace {
 
         Problem = false;
 
-        if (!InfiniteSearch)
+        if (UseTimeManagement)
         {
             // Time to stop?
             bool stopSearch = false;
@@ -831,9 +836,9 @@ namespace {
 
     rml.sort();
 
-    // If we are pondering, we shouldn't print the best move before we
-    // are told to do so
-    if (PonderSearch)
+    // If we are pondering or in infinite search, we shouldn't print the
+    // best move before we are told to do so.
+    if (!AbortSearch && (PonderSearch || InfiniteSearch))
         wait_for_stop_or_ponderhit();
     else
         // Print final search statistics
@@ -898,7 +903,7 @@ namespace {
         int64_t nodes;
         Move move;
         StateInfo st;
-        Depth ext, newDepth;
+        Depth depth, ext, newDepth;
 
         RootMoveNumber = i + 1;
         FailHigh = false;
@@ -921,8 +926,9 @@ namespace {
         bool moveIsCheck = pos.move_is_check(move);
         bool captureOrPromotion = pos.move_is_capture_or_promotion(move);
         bool dangerous;
+        depth =  (Iteration - 2) * OnePly + InitialDepth;
         ext = extension(pos, move, true, captureOrPromotion, moveIsCheck, false, false, &dangerous);
-        newDepth = (Iteration - 2) * OnePly + ext + InitialDepth;
+        newDepth = depth + ext;
 
         // Make the move, and search it
         pos.do_move(move, st, ci, moveIsCheck);
@@ -949,14 +955,19 @@ namespace {
         {
             // Try to reduce non-pv search depth by one ply if move seems not problematic,
             // if the move fails high will be re-searched at full depth.
-            if (   newDepth >= 3*OnePly
-                && i >= MultiPV + LMRPVMoves
+            if (   depth >= 3*OnePly // FIXME was newDepth
                 && !dangerous
                 && !captureOrPromotion
                 && !move_is_castle(move))
             {
-                ss[0].reduction = OnePly;
-                value = -search(pos, ss, -alpha, newDepth-OnePly, 1, true, 0);
+                double red = 0.5 + ln(RootMoveNumber - MultiPV + 1) * ln(depth / 2) / 6.0;
+                if (red >= 1.0)
+                {
+                    ss[0].reduction = Depth(int(floor(red * int(OnePly))));
+                    value = -search(pos, ss, -alpha, newDepth-ss[0].reduction, 1, true, 0);
+                }
+                else
+                    value = alpha + 1; // Just to trigger next condition
             } else
                 value = alpha + 1; // Just to trigger next condition
 
@@ -1087,7 +1098,6 @@ namespace {
     assert(threadID >= 0 && threadID < ActiveThreads);
 
     Move movesSearched[256];
-    EvalInfo ei;
     StateInfo st;
     const TTEntry* tte;
     Move ttMove, move;
@@ -1108,12 +1118,9 @@ namespace {
     if (AbortSearch || thread_should_stop(threadID))
         return Value(0);
 
-    if (pos.is_draw())
+    if (pos.is_draw() || ply >= PLY_MAX - 1)
         return VALUE_DRAW;
 
-    if (ply >= PLY_MAX - 1)
-        return pos.is_check() ? quick_evaluate(pos) : evaluate(pos, ei, threadID);
-
     // Mate distance pruning
     oldAlpha = alpha;
     alpha = Max(value_mated_in(ply), alpha);
@@ -1201,14 +1208,19 @@ namespace {
         // Try to reduce non-pv search depth by one ply if move seems not problematic,
         // if the move fails high will be re-searched at full depth.
         if (    depth >= 3*OnePly
-            &&  moveCount >= LMRPVMoves
             && !dangerous
             && !captureOrPromotion
             && !move_is_castle(move)
             && !move_is_killer(move, ss[ply]))
         {
-            ss[ply].reduction = OnePly;
-            value = -search(pos, ss, -alpha, newDepth-OnePly, ply+1, true, threadID);
+          double red = 0.5 + ln(moveCount) * ln(depth / 2) / 6.0;
+          if (red >= 1.0)
+          {
+              ss[ply].reduction = Depth(int(floor(red * int(OnePly))));
+              value = -search(pos, ss, -alpha, newDepth-ss[ply].reduction, ply+1, true, threadID);
+          }
+          else
+              value = alpha + 1; // Just to trigger next condition
         }
         else
             value = alpha + 1; // Just to trigger next condition
@@ -1316,11 +1328,11 @@ namespace {
     const TTEntry* tte;
     Move ttMove, move;
     Depth ext, newDepth;
-    Value approximateEval, nullValue, value, futilityValue, futilityValueScaled;
+    Value bestValue, staticValue, nullValue, value, futilityValue, futilityValueScaled;
     bool isCheck, useFutilityPruning, singleEvasion, moveIsCheck, captureOrPromotion, dangerous;
     bool mateThreat = false;
     int moveCount = 0;
-    Value bestValue = -VALUE_INFINITE;
+    futilityValue = staticValue = bestValue = -VALUE_INFINITE;
 
     if (depth < OnePly)
         return qsearch(pos, ss, beta-1, beta, Depth(0), ply, threadID);
@@ -1333,12 +1345,9 @@ namespace {
     if (AbortSearch || thread_should_stop(threadID))
         return Value(0);
 
-    if (pos.is_draw())
+    if (pos.is_draw() || ply >= PLY_MAX - 1)
         return VALUE_DRAW;
 
-    if (ply >= PLY_MAX - 1)
-        return pos.is_check() ? quick_evaluate(pos) : evaluate(pos, ei, threadID);
-
     // Mate distance pruning
     if (value_mated_in(ply) >= beta)
         return beta;
@@ -1360,26 +1369,44 @@ namespace {
         return value_from_tt(tte->value(), ply);
     }
 
-    approximateEval = quick_evaluate(pos);
     isCheck = pos.is_check();
 
+    // Calculate depth dependant futility pruning parameters
+    const int FutilityMoveCountMargin = 3 + (1 << (3 * int(depth) / 8));
+    const int FutilityValueMargin = 112 * bitScanReverse32(int(depth) * int(depth) / 2);
+
+    // Evaluate the position statically
+    if (isCheck)
+        ss[ply].eval = VALUE_NONE;
+    else
+    {
+        if (tte && (tte->type() & VALUE_TYPE_EVAL))
+            staticValue = value_from_tt(tte->value(), ply);
+        else
+            staticValue = evaluate(pos, ei, threadID);
+
+        ss[ply].eval = staticValue;
+        futilityValue = staticValue + FutilityValueMargin;
+        staticValue = refine_eval(tte, staticValue, ply); // Enhance accuracy with TT value if possible
+    }
+
     // Null move search
     if (    allowNullmove
         &&  depth > OnePly
         && !isCheck
         && !value_is_mate(beta)
         &&  ok_to_do_nullmove(pos)
-        &&  approximateEval >= beta - NullMoveMargin)
+        &&  staticValue >= beta - NullMoveMargin)
     {
         ss[ply].currentMove = MOVE_NULL;
 
         pos.do_null_move(st);
 
         // Null move dynamic reduction based on depth
-        int R = (depth >= 5 * OnePly ? 4 : 3);
+        int R = 3 + (depth >= 5 * OnePly ? depth / 8 : 0);
 
         // Null move dynamic reduction based on value
-        if (approximateEval - beta > PawnValueMidgame)
+        if (staticValue - beta > PawnValueMidgame)
             R++;
 
         nullValue = -search(pos, ss, -(beta-1), depth-R*OnePly, ply+1, false, threadID);
@@ -1414,13 +1441,14 @@ namespace {
     }
     // Null move search not allowed, try razoring
     else if (   !value_is_mate(beta)
+             && !isCheck
              && depth < RazorDepth
-             && approximateEval < beta - RazorApprMargins[int(depth) - 2]
+             && staticValue < beta - (NullMoveMargin + 16 * depth)
              && ss[ply - 1].currentMove != MOVE_NULL
              && ttMove == MOVE_NONE
              && !pos.has_pawn_on_7th(pos.side_to_move()))
     {
-        Value rbeta = beta - RazorMargins[int(depth) - 2];
+        Value rbeta = beta - (NullMoveMargin + 16 * depth);
         Value v = qsearch(pos, ss, rbeta-1, rbeta, Depth(0), ply, threadID);
         if (v < rbeta)
           return v;
@@ -1439,17 +1467,8 @@ namespace {
     // to search all moves.
     MovePicker mp = MovePicker(pos, ttMove, depth, H, &ss[ply]);
     CheckInfo ci(pos);
-    futilityValue = VALUE_NONE;
     useFutilityPruning = depth < SelectiveDepth && !isCheck;
 
-    // Calculate depth dependant futility pruning parameters
-    const int FutilityMoveCountMargin = 3 + (1 << (3 * int(depth) / 8));
-    const int FutilityValueMargin = 112 * bitScanReverse32(int(depth) * int(depth) / 2);
-
-    // Avoid calling evaluate() if we already have the score in TT
-    if (tte && (tte->type() & VALUE_TYPE_EVAL))
-        futilityValue = value_from_tt(tte->value(), ply) + FutilityValueMargin;
-
     // Loop through all legal moves until no moves remain or a beta cutoff occurs
     while (   bestValue < beta
            && (move = mp.get_next_move()) != MOVE_NONE
@@ -1460,8 +1479,8 @@ namespace {
       if (move == excludedMove)
           continue;
 
-      singleEvasion = (isCheck && mp.number_of_evasions() == 1);
       moveIsCheck = pos.move_is_check(move, ci);
+      singleEvasion = (isCheck && mp.number_of_evasions() == 1);
       captureOrPromotion = pos.move_is_capture_or_promotion(move);
 
       // Decide the new search depth
@@ -1507,9 +1526,6 @@ namespace {
               continue;
 
           // Value based pruning
-          if (futilityValue == VALUE_NONE)
-              futilityValue = evaluate(pos, ei, threadID) + FutilityValueMargin;
-
           futilityValueScaled = futilityValue - moveCount * IncrementalFutilityMargin;
 
           if (futilityValueScaled < beta)
@@ -1526,14 +1542,20 @@ namespace {
       // Try to reduce non-pv search depth by one ply if move seems not problematic,
       // if the move fails high will be re-searched at full depth.
       if (    depth >= 3*OnePly
-          &&  moveCount >= LMRNonPVMoves
           && !dangerous
           && !captureOrPromotion
           && !move_is_castle(move)
-          && !move_is_killer(move, ss[ply]))
+          && !move_is_killer(move, ss[ply])
+          /* && move != ttMove*/)
       {
-          ss[ply].reduction = OnePly;
-          value = -search(pos, ss, -(beta-1), newDepth-OnePly, ply+1, true, threadID);
+          double red = 0.5 + ln(moveCount) * ln(depth / 2) / 3.0;
+          if (red >= 1.0)
+          {
+              ss[ply].reduction = Depth(int(floor(red * int(OnePly))));
+              value = -search(pos, ss, -(beta-1), newDepth-ss[ply].reduction, ply+1, true, threadID);
+          }
+          else
+              value = beta; // Just to trigger next condition
       }
       else
           value = beta; // Just to trigger next condition
@@ -1571,9 +1593,9 @@ namespace {
           break;
     }
 
-    // All legal moves have been searched.  A special case: If there were
+    // All legal moves have been searched. A special case: If there were
     // no legal moves, it must be mate or stalemate.
-    if (moveCount == 0)
+    if (!moveCount)
         return excludedMove ? beta - 1 : (pos.is_check() ? value_mated_in(ply) : VALUE_DRAW);
 
     // If the search is not aborted, update the transposition table,
@@ -1587,12 +1609,13 @@ namespace {
     {
         BetaCounter.add(pos.side_to_move(), depth, threadID);
         move = ss[ply].pv[ply];
+        TT.store(posKey, value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, depth, move);
         if (!pos.move_is_capture_or_promotion(move))
         {
             update_history(pos, move, depth, movesSearched, moveCount);
             update_killers(move, ss[ply]);
         }
-        TT.store(posKey, value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, depth, move);
+
     }
 
     assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);
@@ -1617,7 +1640,7 @@ namespace {
     EvalInfo ei;
     StateInfo st;
     Move ttMove, move;
-    Value staticValue, bestValue, value, futilityValue;
+    Value staticValue, bestValue, value, futilityBase, futilityValue;
     bool isCheck, enoughMaterial, moveIsCheck;
     const TTEntry* tte = NULL;
     int moveCount = 0;
@@ -1631,42 +1654,32 @@ namespace {
     if (AbortSearch || thread_should_stop(threadID))
         return Value(0);
 
-    if (pos.is_draw())
+    if (pos.is_draw() || ply >= PLY_MAX - 1)
         return VALUE_DRAW;
 
-    // Transposition table lookup, only when not in PV
-    if (!pvNode)
+    // Transposition table lookup. At PV nodes, we don't use the TT for
+    // pruning, but only for move ordering.
+    tte = TT.retrieve(pos.get_key());
+    ttMove = (tte ? tte->move() : MOVE_NONE);
+
+    if (!pvNode && tte && ok_to_use_TT(tte, depth, beta, ply))
     {
-        tte = TT.retrieve(pos.get_key());
-        if (tte && ok_to_use_TT(tte, depth, beta, ply))
-        {
-            assert(tte->type() != VALUE_TYPE_EVAL);
+        assert(tte->type() != VALUE_TYPE_EVAL);
 
-            return value_from_tt(tte->value(), ply);
-        }
+        ss[ply].currentMove = ttMove; // Can be MOVE_NONE
+        return value_from_tt(tte->value(), ply);
     }
-    ttMove = (tte ? tte->move() : MOVE_NONE);
 
     isCheck = pos.is_check();
-    ei.futilityMargin = Value(0); // Manually initialize futilityMargin
 
     // Evaluate the position statically
     if (isCheck)
         staticValue = -VALUE_INFINITE;
-
     else if (tte && (tte->type() & VALUE_TYPE_EVAL))
-    {
-        // Use the cached evaluation score if possible
-        assert(ei.futilityMargin == Value(0));
-
         staticValue = value_from_tt(tte->value(), ply);
-    }
     else
         staticValue = evaluate(pos, ei, threadID);
 
-    if (ply >= PLY_MAX - 1)
-        return pos.is_check() ? quick_evaluate(pos) : evaluate(pos, ei, threadID);
-
     // Initialize "stand pat score", and return it immediately if it is
     // at least beta.
     bestValue = staticValue;
@@ -1689,6 +1702,7 @@ namespace {
     MovePicker mp = MovePicker(pos, ttMove, depth, H);
     CheckInfo ci(pos);
     enoughMaterial = pos.non_pawn_material(pos.side_to_move()) > RookValueMidgame;
+    futilityBase = staticValue + FutilityMarginQS + ei.futilityMargin;
 
     // Loop through the moves until no moves remain or a beta cutoff
     // occurs.
@@ -1697,11 +1711,12 @@ namespace {
     {
       assert(move_is_ok(move));
 
+      moveIsCheck = pos.move_is_check(move, ci);
+
+      // Update current move
       moveCount++;
       ss[ply].currentMove = move;
 
-      moveIsCheck = pos.move_is_check(move, ci);
-
       // Futility pruning
       if (   enoughMaterial
           && !isCheck
@@ -1711,12 +1726,9 @@ namespace {
           && !move_is_promotion(move)
           && !pos.move_is_passed_pawn_push(move))
       {
-          futilityValue =  staticValue
-                         + Max(pos.midgame_value_of_piece_on(move_to(move)),
-                               pos.endgame_value_of_piece_on(move_to(move)))
-                         + (move_is_ep(move) ? PawnValueEndgame : Value(0))
-                         + FutilityMarginQS
-                         + ei.futilityMargin;
+          futilityValue =  futilityBase
+                         + pos.endgame_value_of_piece_on(move_to(move))
+                         + (move_is_ep(move) ? PawnValueEndgame : Value(0));
 
           if (futilityValue < alpha)
           {
@@ -1752,31 +1764,31 @@ namespace {
        }
     }
 
-    // All legal moves have been searched.  A special case: If we're in check
+    // All legal moves have been searched. A special case: If we're in check
     // and no legal moves were found, it is checkmate.
     if (!moveCount && pos.is_check()) // Mate!
         return value_mated_in(ply);
 
-    assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);
-
     // Update transposition table
-    move = ss[ply].pv[ply];
-    if (!pvNode)
+    Depth d = (depth == Depth(0) ? Depth(0) : Depth(-1));
+    if (bestValue < beta)
     {
-        // If bestValue isn't changed it means it is still the static evaluation of
-        // the node, so keep this info to avoid a future costly evaluation() call.
+        // If bestValue isn't changed it means it is still the static evaluation
+        // of the node, so keep this info to avoid a future evaluation() call.
         ValueType type = (bestValue == staticValue && !ei.futilityMargin ? VALUE_TYPE_EV_UP : VALUE_TYPE_UPPER);
-        Depth d = (depth == Depth(0) ? Depth(0) : Depth(-1));
+        TT.store(pos.get_key(), value_to_tt(bestValue, ply), type, d, MOVE_NONE);
+    }
+    else
+    {
+        move = ss[ply].pv[ply];
+        TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, d, move);
 
-        if (bestValue < beta)
-            TT.store(pos.get_key(), value_to_tt(bestValue, ply), type, d, MOVE_NONE);
-        else
-            TT.store(pos.get_key(), value_to_tt(bestValue, ply), VALUE_TYPE_LOWER, d, move);
+        // Update killers only for good checking moves
+        if (!pos.move_is_capture_or_promotion(move))
+            update_killers(move, ss[ply]);
     }
 
-    // Update killers only for good check moves
-    if (alpha >= beta && !pos.move_is_capture_or_promotion(move))
-        update_killers(move, ss[ply]);
+    assert(bestValue > -VALUE_INFINITE && bestValue < VALUE_INFINITE);
 
     return bestValue;
   }
@@ -1805,7 +1817,6 @@ namespace {
                               && !isCheck;
 
     const int FutilityMoveCountMargin = 3 + (1 << (3 * int(sp->depth) / 8));
-    const int FutilityValueMargin = 112 * bitScanReverse32(int(sp->depth) * int(sp->depth) / 2);
 
     while (    sp->bestValue < sp->beta
            && !thread_should_stop(threadID)
@@ -1839,12 +1850,6 @@ namespace {
               continue;
 
           // Value based pruning
-          if (sp->futilityValue == VALUE_NONE)
-          {
-              EvalInfo ei;
-              sp->futilityValue = evaluate(pos, ei, threadID) + FutilityValueMargin;
-          }
-
           Value futilityValueScaled = sp->futilityValue - moveCount * IncrementalFutilityMargin;
 
           if (futilityValueScaled < sp->beta)
@@ -1867,13 +1872,18 @@ namespace {
       // Try to reduce non-pv search depth by one ply if move seems not problematic,
       // if the move fails high will be re-searched at full depth.
       if (   !dangerous
-          &&  moveCount >= LMRNonPVMoves
           && !captureOrPromotion
           && !move_is_castle(move)
           && !move_is_killer(move, ss[sp->ply]))
       {
-          ss[sp->ply].reduction = OnePly;
-          value = -search(pos, ss, -(sp->beta-1), newDepth - OnePly, sp->ply+1, true, threadID);
+          double red = 0.5 + ln(moveCount) * ln(sp->depth / 2) / 3.0;
+          if (red >= 1.0)
+          {
+              ss[sp->ply].reduction = Depth(int(floor(red * int(OnePly))));
+              value = -search(pos, ss, -(sp->beta-1), newDepth-ss[sp->ply].reduction, sp->ply+1, true, threadID);
+          }
+          else
+              value = sp->beta; // Just to trigger next condition
       }
       else
           value = sp->beta; // Just to trigger next condition
@@ -1973,13 +1983,18 @@ namespace {
       // Try to reduce non-pv search depth by one ply if move seems not problematic,
       // if the move fails high will be re-searched at full depth.
       if (   !dangerous
-          &&  moveCount >= LMRPVMoves
           && !captureOrPromotion
           && !move_is_castle(move)
           && !move_is_killer(move, ss[sp->ply]))
       {
-          ss[sp->ply].reduction = OnePly;
-          value = -search(pos, ss, -sp->alpha, newDepth - OnePly, sp->ply+1, true, threadID);
+          double red = 0.5 + ln(moveCount) * ln(sp->depth / 2) / 6.0;
+          if (red >= 1.0)
+          {
+              ss[sp->ply].reduction = Depth(int(floor(red * int(OnePly))));
+              value = -search(pos, ss, -sp->alpha, newDepth-ss[sp->ply].reduction, sp->ply+1, true, threadID);
+          }
+          else
+              value = sp->alpha + 1; // Just to trigger next condition
       }
       else
           value = sp->alpha + 1; // Just to trigger next condition
@@ -2474,6 +2489,23 @@ namespace {
   }
 
 
+  // refine_eval() returns the transposition table score if
+  // possible otherwise falls back on static position evaluation.
+
+  Value refine_eval(const TTEntry* tte, Value defaultEval, int ply) {
+
+      if (!tte)
+          return defaultEval;
+
+      Value v = value_from_tt(tte->value(), ply);
+
+      if (   (is_lower_bound(tte->type()) && v >= defaultEval)
+          || (is_upper_bound(tte->type()) && v < defaultEval))
+          return v;
+
+      return defaultEval;
+  }
+
   // update_history() registers a good move that produced a beta-cutoff
   // in history and marks as failures all the other moves of that ply.
 
@@ -2624,7 +2656,7 @@ namespace {
                      || stillAtFirstMove //FIXME: We are not checking any problem flags, BUG?
                      || noProblemFound;
 
-    if (   (Iteration >= 3 && !InfiniteSearch && noMoreTime)
+    if (   (Iteration >= 3 && UseTimeManagement && noMoreTime)
         || (ExactMaxTime && t >= ExactMaxTime)
         || (Iteration >= 3 && MaxNodes && nodes_searched() >= MaxNodes))
         AbortSearch = true;
@@ -2654,7 +2686,7 @@ namespace {
                      || stillAtFirstMove
                      || noProblemFound;
 
-    if (Iteration >= 3 && !InfiniteSearch && (noMoreTime || StopOnPonderhit))
+    if (Iteration >= 3 && UseTimeManagement && (noMoreTime || StopOnPonderhit))
         AbortSearch = true;
   }