]> git.sesse.net Git - stockfish/commitdiff
Merge pull request #11 from glinscott/squash
authorMarco Costalba <mcostalba@gmail.com>
Wed, 28 Mar 2012 05:40:17 +0000 (22:40 -0700)
committerMarco Costalba <mcostalba@gmail.com>
Wed, 28 Mar 2012 06:48:30 +0000 (07:48 +0100)
Add more detailed pawn shelter/storm evaluation

After 10670 games at 10"+0.05
Mod vs Orig 2277 - 1941 - 6452 ELO +11 !!!

The first real increase since 2.2.2, congratulations Gary !!!

Signed-off-by: Marco Costalba <mcostalba@gmail.com>
src/benchmark.cpp
src/evaluate.cpp
src/search.cpp
src/search.h
src/thread.cpp
src/thread.h
src/timeman.cpp
src/timeman.h
src/uci.cpp

index 4124899b33d4fd7a1b84a36a3eb1490b29509166..136c6e80f5bc9ee7f4d86683194fc553e29f8c2d 100644 (file)
@@ -74,13 +74,13 @@ void benchmark(int argc, char* argv[]) {
   Options["Threads"] = threads;
 
   if (valType == "time")
-      limits.maxTime = 1000 * atoi(valStr.c_str()); // maxTime is in ms
+      limits.movetime = 1000 * atoi(valStr.c_str()); // movetime is in ms
 
   else if (valType == "nodes")
-      limits.maxNodes = atoi(valStr.c_str());
+      limits.nodes = atoi(valStr.c_str());
 
   else
-      limits.maxDepth = atoi(valStr.c_str());
+      limits.depth = atoi(valStr.c_str());
 
   if (fenFile != "default")
   {
@@ -112,13 +112,14 @@ void benchmark(int argc, char* argv[]) {
 
       if (valType == "perft")
       {
-          int64_t cnt = Search::perft(pos, limits.maxDepth * ONE_PLY);
-          cerr << "\nPerft " << limits.maxDepth  << " leaf nodes: " << cnt << endl;
+          int64_t cnt = Search::perft(pos, limits.depth * ONE_PLY);
+          cerr << "\nPerft " << limits.depth  << " leaf nodes: " << cnt << endl;
           nodes += cnt;
       }
       else
       {
-          Threads.start_thinking(pos, limits);
+          Threads.start_searching(pos, limits);
+          Threads.wait_for_search_finished();
           nodes += Search::RootPosition.nodes_searched();
       }
   }
index b2cae94c0e30de30956bfa6d9a92107e1b1e0db1..6e515d88998f612c8dea4669e3d577cb9802636b 100644 (file)
@@ -167,8 +167,8 @@ namespace {
   // happen in Chess960 games.
   const Score TrappedBishopA1H1Penalty = make_score(100, 100);
 
-  // Penalty for a minor piece that is not defended by anything
-  const Score UndefendedMinorPenalty = make_score(25, 10);
+  // Penalty for BNR that is not defended by anything
+  const Score UndefendedPiecePenalty = make_score(25, 10);
 
   // The SpaceMask[Color] contains the area of the board which is considered
   // by the space evaluation. In the middle game, each side is given a bonus
@@ -678,21 +678,24 @@ Value do_evaluate(const Position& pos, Value& margin) {
 
     const Color Them = (Us == WHITE ? BLACK : WHITE);
 
-    Bitboard b;
+    Bitboard b, undefended, undefendedMinors, weakEnemies;
     Score score = SCORE_ZERO;
 
-    // Undefended minors get penalized even if not under attack
-    Bitboard undefended =  pos.pieces(Them)
-                         & (pos.pieces(BISHOP) | pos.pieces(KNIGHT))
-                         & ~ei.attackedBy[Them][0];
-    if (undefended)
-        score += single_bit(undefended) ? UndefendedMinorPenalty
-                                        : UndefendedMinorPenalty * 2;
+    // Undefended pieces get penalized even if not under attack
+    undefended = pos.pieces(Them) & ~ei.attackedBy[Them][0];
+    undefendedMinors = undefended & (pos.pieces(BISHOP) | pos.pieces(KNIGHT));
+
+    if (undefendedMinors)
+        score += single_bit(undefendedMinors) ? UndefendedPiecePenalty
+                                              : UndefendedPiecePenalty * 2;
+    if (undefended & pos.pieces(ROOK))
+        score += UndefendedPiecePenalty;
 
     // Enemy pieces not defended by a pawn and under our attack
-    Bitboard weakEnemies =  pos.pieces(Them)
-                          & ~ei.attackedBy[Them][PAWN]
-                          & ei.attackedBy[Us][0];
+    weakEnemies =  pos.pieces(Them)
+                 & ~ei.attackedBy[Them][PAWN]
+                 & ei.attackedBy[Us][0];
+
     if (!weakEnemies)
         return score;
 
index a76a9521c9ee7a19d7ee52c231414a4ce111ba13..8d0c0c6b27199acc722d72e3188ce7c400a0f0b7 100644 (file)
@@ -254,7 +254,7 @@ void Search::think() {
   Chess960 = pos.is_chess960();
   Eval::RootColor = pos.side_to_move();
   SearchTime.restart();
-  TimeMgr.init(Limits, pos.startpos_ply_counter());
+  TimeMgr.init(Limits, pos.startpos_ply_counter(), pos.side_to_move());
   TT.new_search();
   H.clear();
 
@@ -292,9 +292,9 @@ void Search::think() {
       log << "\nSearching: "  << pos.to_fen()
           << "\ninfinite: "   << Limits.infinite
           << " ponder: "      << Limits.ponder
-          << " time: "        << Limits.time
-          << " increment: "   << Limits.increment
-          << " moves to go: " << Limits.movesToGo
+          << " time: "        << Limits.times[pos.side_to_move()]
+          << " increment: "   << Limits.incs[pos.side_to_move()]
+          << " moves to go: " << Limits.movestogo
           << endl;
   }
 
@@ -362,7 +362,7 @@ namespace {
     ss->currentMove = MOVE_NULL; // Hack to skip update gains
 
     // Iterative deepening loop until requested to stop or target depth reached
-    while (!Signals.stop && ++depth <= MAX_PLY && (!Limits.maxDepth || depth <= Limits.maxDepth))
+    while (!Signals.stop && ++depth <= MAX_PLY && (!Limits.depth || depth <= Limits.depth))
     {
         // Save last iteration's scores before first PV line is searched and all
         // the move scores but the (new) PV are set to -VALUE_INFINITE.
@@ -584,7 +584,7 @@ namespace {
 
     // Step 2. Check for aborted search and immediate draw
     // Enforce node limit here. FIXME: This only works with 1 search thread.
-    if (Limits.maxNodes && pos.nodes_searched() >= Limits.maxNodes)
+    if (Limits.nodes && pos.nodes_searched() >= Limits.nodes)
         Signals.stop = true;
 
     if ((   Signals.stop
@@ -1894,6 +1894,6 @@ void check_time() {
                    || stillAtFirstMove;
 
   if (   (Limits.use_time_management() && noMoreTime)
-      || (Limits.maxTime && e >= Limits.maxTime))
+      || (Limits.movetime && e >= Limits.movetime))
       Signals.stop = true;
 }
index bd371a4aac1b705fb3b6a8eb1a1df9c7799bf09a..c957c34bf6259b1107ddd860209454ffffed9351 100644 (file)
@@ -77,9 +77,9 @@ struct RootMove {
 struct LimitsType {
 
   LimitsType() { memset(this, 0, sizeof(LimitsType)); }
-  bool use_time_management() const { return !(maxTime | maxDepth | maxNodes | infinite); }
+  bool use_time_management() const { return !(movetime | depth | nodes | infinite); }
 
-  int time, increment, movesToGo, maxTime, maxDepth, maxNodes, infinite, ponder;
+  int times[2], incs[2], movestogo, depth, nodes, movetime, infinite, ponder;
 };
 
 
index f2a2c821151aa0219d525be1779e83d86c9dd2d1..6a5454faa9ed5abc0dc07a06ab585cb7b5f0bea8 100644 (file)
@@ -50,7 +50,7 @@ Thread::Thread(Fn fn) {
   start_fn = fn;
   threadID = Threads.size();
 
-  do_sleep = (fn != &Thread::main_loop); // Avoid a race with start_thinking()
+  do_sleep = (fn != &Thread::main_loop); // Avoid a race with start_searching()
 
   lock_init(sleepLock);
   cond_init(sleepCond);
@@ -154,10 +154,7 @@ void Thread::wait_for_stop_or_ponderhit() {
   Signals.stopOnPonderhit = true;
 
   lock_grab(sleepLock);
-
-  while (!Signals.stop)
-      cond_wait(sleepCond, sleepLock);
-
+  while (!Signals.stop) cond_wait(sleepCond, sleepLock);
   lock_release(sleepLock);
 }
 
@@ -258,8 +255,8 @@ void ThreadsManager::wake_up() const {
 
   for (int i = 0; i < size(); i++)
   {
-      threads[i]->do_sleep = false;
       threads[i]->maxPly = 0;
+      threads[i]->do_sleep = false;
 
       if (!useSleepingThreads)
           threads[i]->wake_up();
@@ -273,7 +270,7 @@ void ThreadsManager::wake_up() const {
 void ThreadsManager::sleep() const {
 
   for (int i = 1; i < size(); i++) // Main thread will go to sleep by itself
-      threads[i]->do_sleep = true; // to avoid a race with start_thinking()
+      threads[i]->do_sleep = true; // to avoid a race with start_searching()
 }
 
 
@@ -415,19 +412,24 @@ void ThreadsManager::set_timer(int msec) {
 }
 
 
-// ThreadsManager::start_thinking() is used by UI thread to wake up the main
-// thread parked in main_loop() and starting a new search. If async is true
-// then function returns immediately, otherwise caller is blocked waiting for
-// the search to finish.
+// ThreadsManager::wait_for_search_finished() waits for main thread to go to
+// sleep, this means search is finished. Then returns.
+
+void ThreadsManager::wait_for_search_finished() {
+
+  Thread* main = threads[0];
+  lock_grab(main->sleepLock);
+  while (!main->do_sleep) cond_wait(sleepCond, main->sleepLock);
+  lock_release(main->sleepLock);
+}
 
-void ThreadsManager::start_thinking(const Position& pos, const LimitsType& limits,
-                                    const std::set<Move>& searchMoves, bool async) {
-  Thread& main = *threads.front();
 
-  lock_grab(main.sleepLock);
+// ThreadsManager::start_searching() wakes up the main thread sleeping in
+// main_loop() so to start a new search, then returns immediately.
 
-  while (!main.do_sleep)
-      cond_wait(sleepCond, main.sleepLock); // Wait main thread has finished
+void ThreadsManager::start_searching(const Position& pos, const LimitsType& limits,
+                                     const std::set<Move>& searchMoves) {
+  wait_for_search_finished();
 
   Signals.stopOnPonderhit = Signals.firstRootMove = false;
   Signals.stop = Signals.failedLowAtRoot = false;
@@ -440,33 +442,6 @@ void ThreadsManager::start_thinking(const Position& pos, const LimitsType& limit
       if (searchMoves.empty() || searchMoves.count(ml.move()))
           RootMoves.push_back(RootMove(ml.move()));
 
-  main.do_sleep = false;
-  cond_signal(main.sleepCond); // Wake up main thread and start searching
-
-  if (!async)
-      while (!main.do_sleep)
-          cond_wait(sleepCond, main.sleepLock);
-
-  lock_release(main.sleepLock);
-}
-
-
-// ThreadsManager::stop_thinking() is used by UI thread to raise a stop request
-// and to wait for the main thread finishing the search. We cannot return before
-// main has finished to avoid a crash in case of a 'quit' command.
-
-void ThreadsManager::stop_thinking() {
-
-  Thread& main = *threads.front();
-
-  Search::Signals.stop = true;
-
-  lock_grab(main.sleepLock);
-
-  cond_signal(main.sleepCond); // In case is waiting for stop or ponderhit
-
-  while (!main.do_sleep)
-      cond_wait(sleepCond, main.sleepLock);
-
-  lock_release(main.sleepLock);
+  threads[0]->do_sleep = false;
+  threads[0]->wake_up();
 }
index 04e023067999c63fefb432cfa67cfcda1b1787f5..9b0a8bcf7965d42ba2e226d43a894b06afcb1b63 100644 (file)
@@ -47,7 +47,6 @@ struct SplitPoint {
   MovePicker* mp;
   SplitPoint* parent;
 
-
   // Shared data
   Lock lock;
   volatile uint64_t slavesMask;
@@ -125,9 +124,9 @@ public:
   void read_uci_options();
   bool available_slave_exists(int master) const;
   void set_timer(int msec);
-  void stop_thinking();
-  void start_thinking(const Position& pos, const Search::LimitsType& limits,
-                      const std::set<Move>& = std::set<Move>(), bool async = false);
+  void wait_for_search_finished();
+  void start_searching(const Position& pos, const Search::LimitsType& limits,
+                       const std::set<Move>& = std::set<Move>());
 
   template <bool Fake>
   Value split(Position& pos, Search::Stack* ss, Value alpha, Value beta, Value bestValue, Move* bestMove,
index 9ca46c93313c7bf86f75f747ae7ed53923feeaaa..d545269ca31a963a39df29fef6614f707e720a59 100644 (file)
@@ -83,7 +83,7 @@ void TimeManager::pv_instability(int curChanges, int prevChanges) {
 }
 
 
-void TimeManager::init(const Search::LimitsType& limits, int currentPly)
+void TimeManager::init(const Search::LimitsType& limits, int currentPly, Color us)
 {
   /* We support four different kind of time controls:
 
@@ -111,15 +111,15 @@ void TimeManager::init(const Search::LimitsType& limits, int currentPly)
 
   // Initialize to maximum values but unstablePVExtraTime that is reset
   unstablePVExtraTime = 0;
-  optimumSearchTime = maximumSearchTime = limits.time;
+  optimumSearchTime = maximumSearchTime = limits.times[us];
 
   // We calculate optimum time usage for different hypothetic "moves to go"-values and choose the
   // minimum of calculated search time values. Usually the greatest hypMTG gives the minimum values.
-  for (hypMTG = 1; hypMTG <= (limits.movesToGo ? std::min(limits.movesToGo, MoveHorizon) : MoveHorizon); hypMTG++)
+  for (hypMTG = 1; hypMTG <= (limits.movestogo ? std::min(limits.movestogo, MoveHorizon) : MoveHorizon); hypMTG++)
   {
       // Calculate thinking time for hypothetic "moves to go"-value
-      hypMyTime =  limits.time
-                 + limits.increment * (hypMTG - 1)
+      hypMyTime =  limits.times[us]
+                 + limits.incs[us] * (hypMTG - 1)
                  - emergencyBaseTime
                  - emergencyMoveTime * std::min(hypMTG, emergencyMoveHorizon);
 
index 2030cc20672a13b4de4658ddcc7fe7f3d7408182..ddf96c677cd2495d7afae1ca2c358ef0e2cbf216 100644 (file)
@@ -25,7 +25,7 @@
 
 class TimeManager {
 public:
-  void init(const Search::LimitsType& limits, int currentPly);
+  void init(const Search::LimitsType& limits, int currentPly, Color us);
   void pv_instability(int curChanges, int prevChanges);
   int available_time() const { return optimumSearchTime + unstablePVExtraTime; }
   int maximum_time() const { return maximumSearchTime; }
index 718c78752502b61bd991b25191c94b2d30487e41..1b7705065cd5de4dc6fefca0b2a1f9912cb07dd9 100644 (file)
@@ -67,7 +67,12 @@ void uci_loop() {
       is >> skipws >> token;
 
       if (token == "quit" || token == "stop")
-          Threads.stop_thinking();
+      {
+          Search::Signals.stop = true;
+
+          if (token == "quit") // Cannot quit while threads are still running
+              Threads.wait_for_search_finished();
+      }
 
       else if (token == "ponderhit")
       {
@@ -77,7 +82,7 @@ void uci_loop() {
           Search::Limits.ponder = false;
 
           if (Search::Signals.stopOnPonderhit)
-              Threads.stop_thinking();
+              Search::Signals.stop = true;
       }
 
       else if (token == "go")
@@ -184,46 +189,42 @@ namespace {
 
   // go() is called when engine receives the "go" UCI command. The function sets
   // the thinking time and other parameters from the input string, and then starts
-  // the main searching thread.
+  // the search.
 
   void go(Position& pos, istringstream& is) {
 
-    string token;
     Search::LimitsType limits;
     std::set<Move> searchMoves;
-    int time[] = { 0, 0 }, inc[] = { 0, 0 };
+    string token;
 
     while (is >> token)
     {
-        if (token == "infinite")
-            limits.infinite = true;
-        else if (token == "ponder")
-            limits.ponder = true;
-        else if (token == "wtime")
-            is >> time[WHITE];
+        if (token == "wtime")
+            is >> limits.times[WHITE];
         else if (token == "btime")
-            is >> time[BLACK];
+            is >> limits.times[BLACK];
         else if (token == "winc")
-            is >> inc[WHITE];
+            is >> limits.incs[WHITE];
         else if (token == "binc")
-            is >> inc[BLACK];
+            is >> limits.incs[BLACK];
         else if (token == "movestogo")
-            is >> limits.movesToGo;
+            is >> limits.movestogo;
         else if (token == "depth")
-            is >> limits.maxDepth;
+            is >> limits.depth;
         else if (token == "nodes")
-            is >> limits.maxNodes;
+            is >> limits.nodes;
         else if (token == "movetime")
-            is >> limits.maxTime;
+            is >> limits.movetime;
+        else if (token == "infinite")
+            limits.infinite = true;
+        else if (token == "ponder")
+            limits.ponder = true;
         else if (token == "searchmoves")
             while (is >> token)
                 searchMoves.insert(move_from_uci(pos, token));
     }
 
-    limits.time = time[pos.side_to_move()];
-    limits.increment = inc[pos.side_to_move()];
-
-    Threads.start_thinking(pos, limits, searchMoves, true);
+    Threads.start_searching(pos, limits, searchMoves);
   }