]> git.sesse.net Git - stockfish/blobdiff - src/search.cpp
TEST: extend when few moves available
[stockfish] / src / search.cpp
index 8279d15780474d598144d5d1a0c16a0804f9e501..d19c9a9015423192991319e4e6b910db955c4e8e 100644 (file)
@@ -1,13 +1,14 @@
 /*
-  Glaurung, a UCI chess playing engine.
-  Copyright (C) 2004-2008 Tord Romstad
+  Stockfish, a UCI chess playing engine derived from Glaurung 2.1
+  Copyright (C) 2004-2008 Tord Romstad (Glaurung author)
+  Copyright (C) 2008 Marco Costalba
 
-  Glaurung is free software: you can redistribute it and/or modify
+  Stockfish is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
-  Glaurung is distributed in the hope that it will be useful,
+  Stockfish is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
@@ -152,6 +153,12 @@ namespace {
   Depth RazorDepth = 4*OnePly;
   Value RazorMargin = Value(0x300);
 
+  // Last seconds noise filtering (LSN)
+  bool UseLSNFiltering = false;
+  bool looseOnTime = false;
+  int LSNTime = 4 * 1000; // In milliseconds
+  Value LSNValue = Value(0x200);
+
   // Extensions.  Array index 0 is used at non-PV nodes, index 1 at PV nodes.
   Depth CheckExtension[2] = {OnePly, OnePly};
   Depth SingleReplyExtension[2] = {OnePly / 2, OnePly / 2};
@@ -220,7 +227,7 @@ namespace {
 
   /// Functions
 
-  void id_loop(const Position &pos, Move searchMoves[]);
+  Value id_loop(const Position &pos, Move searchMoves[]);
   Value root_search(Position &pos, SearchStack ss[], RootMoveList &rml);
   Value search_pv(Position &pos, SearchStack ss[], Value alpha, Value beta,
                   Depth depth, int ply, int threadID);
@@ -295,7 +302,7 @@ History H;  // Should be made local?
 //// Functions
 ////
 
-/// think() is the external interface to Glaurung's search, and is called when
+/// think() is the external interface to Stockfish's search, and is called when
 /// the program receives the UCI 'go' command.  It initializes various
 /// search-related global variables, and calls root_search()
 
@@ -394,6 +401,10 @@ void think(const Position &pos, bool infinite, bool ponder, int side_to_move,
   RazorDepth = (get_option_value_int("Maximum Razoring Depth") + 1) * OnePly;
   RazorMargin = value_from_centipawns(get_option_value_int("Razoring Margin"));
 
+  UseLSNFiltering = get_option_value_bool("LSN filtering");
+  LSNTime = get_option_value_int("LSN Time Margin (sec)") * 1000;
+  LSNValue = value_from_centipawns(get_option_value_int("LSN Value Margin"));
+
   MinimumSplitDepth = get_option_value_int("Minimum Split Depth") * OnePly;
   MaxThreadsPerSplitPoint =
     get_option_value_int("Maximum Number of Threads per Split Point");
@@ -468,7 +479,21 @@ void think(const Position &pos, bool infinite, bool ponder, int side_to_move,
 
   // We're ready to start thinking.  Call the iterative deepening loop
   // function:
-  id_loop(pos, searchMoves);
+  if (!looseOnTime)
+  {
+      Value v = id_loop(pos, searchMoves);
+      looseOnTime = (   UseLSNFiltering
+                     && myTime < LSNTime
+                     && myIncrement == 0
+                     && v < -LSNValue);
+  }
+  else
+  {
+      looseOnTime = false; // reset for next match
+      while (SearchStartTime + myTime + 1000 > get_system_time())
+          ; // wait here
+      id_loop(pos, searchMoves); // to fail gracefully
+  }
 
   if(UseLogFile)
     LogFile.close();
@@ -570,7 +595,7 @@ namespace {
   // been consumed, the user stops the search, or the maximum search depth is
   // reached.
 
-  void id_loop(const Position &pos, Move searchMoves[]) {
+  Value id_loop(const Position &pos, Move searchMoves[]) {
     Position p(pos);
     SearchStack ss[PLY_MAX_PLUS_2];
 
@@ -694,6 +719,7 @@ namespace {
       LogFile << "Ponder move: " << move_to_san(p, ss[0].pv[1]) << '\n';
       LogFile << std::endl;
     }
+    return rml.get_move_score(0);
   }
 
 
@@ -905,6 +931,7 @@ namespace {
     {
       assert(move_is_ok(move));
 
+      bool fewMoves = (depth <= OnePly && mp.number_of_moves() < 4);
       bool singleReply = (pos.is_check() && mp.number_of_moves() == 1);
       bool moveIsCheck = pos.move_is_check(move, dcCandidates);
       bool moveIsCapture = pos.move_is_capture(move);
@@ -916,7 +943,7 @@ namespace {
         PawnValueMidgame : pos.midgame_value_of_piece_on(move_to(move));
 
       // Decide the new search depth
-      Depth ext = extension(pos, move, true, moveIsCheck, singleReply, mateThreat);
+      Depth ext = extension(pos, move, true, moveIsCheck, singleReply || fewMoves, mateThreat);
       Depth newDepth = depth - OnePly + ext;
 
       // Make and search the move
@@ -1122,7 +1149,8 @@ namespace {
         }
     }
     // Null move search not allowed, try razoring
-    else if (depth < RazorDepth && approximateEval < beta - RazorMargin)
+    else if (  (approximateEval < beta - RazorMargin && depth < RazorDepth)
+             ||(approximateEval < beta - PawnValueMidgame && depth <= OnePly))
     {
         Value v = qsearch(pos, ss, beta-1, beta, Depth(0), ply, threadID);
         if (v < beta)