Use Color-From-To history stats to help sort moves
authorVoyagerOne <excelgeek@gmail.com>
Mon, 25 Jul 2016 13:53:18 +0000 (09:53 -0400)
committerMarco Costalba <mcostalba@gmail.com>
Tue, 2 Aug 2016 07:17:14 +0000 (09:17 +0200)
STC:
LLR: 2.95 (-2.94,2.94) [0.00,5.00]
Total: 33502 W: 6498 L: 6223 D: 20781
http://tests.stockfishchess.org/tests/view/578abb940ebc5972faa169e2

LTC:
LLR: 2.95 (-2.94,2.94) [0.00,5.00]
Total: 50782 W: 7124 L: 6832 D: 36826
http://tests.stockfishchess.org/tests/view/578b8e5d0ebc5972faa169fd

LTC: (Sanity test against latest master)
LLR: 2.95 (-2.94,2.94) [0.00,5.00]
Total: 32759 W: 4600 L: 4370 D: 23789
http://tests.stockfishchess.org/tests/view/5798b7d30ebc591c761f5b72

bench: 6985912

P.S. Thanks @mstembera for rewriting my code to make it smp compatible. A BIG thank you!

src/movepick.cpp
src/movepick.h
src/search.cpp
src/thread.h

index 3e90750..78765be 100644 (file)
@@ -142,16 +142,20 @@ template<>
 void MovePicker::score<QUIETS>() {
 
   const HistoryStats& history = pos.this_thread()->history;
+  const FromToStats& fromTo = pos.this_thread()->fromTo;
 
   const CounterMoveStats* cm = (ss-1)->counterMoves;
   const CounterMoveStats* fm = (ss-2)->counterMoves;
   const CounterMoveStats* f2 = (ss-4)->counterMoves;
 
+  Color c = pos.side_to_move();
+
   for (auto& m : *this)
       m.value =      history[pos.moved_piece(m)][to_sq(m)]
                + (cm ? (*cm)[pos.moved_piece(m)][to_sq(m)] : VALUE_ZERO)
                + (fm ? (*fm)[pos.moved_piece(m)][to_sq(m)] : VALUE_ZERO)
-               + (f2 ? (*f2)[pos.moved_piece(m)][to_sq(m)] : VALUE_ZERO);
+               + (f2 ? (*f2)[pos.moved_piece(m)][to_sq(m)] : VALUE_ZERO)
+               + fromTo.get(c, m);
 }
 
 template<>
@@ -160,6 +164,8 @@ void MovePicker::score<EVASIONS>() {
   // by history value, then bad captures and quiet moves with a negative SEE ordered
   // by SEE value.
   const HistoryStats& history = pos.this_thread()->history;
+  const FromToStats& fromTo = pos.this_thread()->fromTo;
+  Color c = pos.side_to_move();
   Value see;
 
   for (auto& m : *this)
@@ -170,7 +176,7 @@ void MovePicker::score<EVASIONS>() {
           m.value =  PieceValue[MG][pos.piece_on(to_sq(m))]
                    - Value(type_of(pos.moved_piece(m))) + HistoryStats::Max;
       else
-          m.value = history[pos.moved_piece(m)][to_sq(m)];
+          m.value = history[pos.moved_piece(m)][to_sq(m)] + fromTo.get(c, m);
 }
 
 
index fffd470..8028d48 100644 (file)
@@ -66,6 +66,26 @@ typedef Stats<Value, false> HistoryStats;
 typedef Stats<Value,  true> CounterMoveStats;
 typedef Stats<CounterMoveStats> CounterMoveHistoryStats;
 
+struct FromToStats {
+
+    Value get(Color c, Move m) const { return table[c][from_sq(m)][to_sq(m)]; }
+    void clear() { std::memset(table, 0, sizeof(table)); }
+
+    void update(Color c, Move m, Value v)
+    {
+        if (abs(int(v)) >= 324)
+            return;
+
+        Square f = from_sq(m);
+        Square t = to_sq(m);
+
+        table[c][f][t] -= table[c][f][t] * abs(int(v)) / 324;
+        table[c][f][t] += int(v) * 32;
+    }
+
+private:
+    Value table[COLOR_NB][SQUARE_NB][SQUARE_NB];
+};
 
 /// MovePicker class is used to pick one pseudo legal move at a time from the
 /// current position. The most important method is next_move(), which returns a
index 64e9028..8b6e169 100644 (file)
@@ -213,6 +213,7 @@ void Search::clear() {
   {
       th->history.clear();
       th->counterMoves.clear();
+      th->fromTo.clear();
   }
 
   Threads.main()->previousScore = VALUE_INFINITE;
@@ -967,7 +968,8 @@ moves_loop: // When in check search starts from here
           Value val = thisThread->history[moved_piece][to_sq(move)]
                      +    (cmh  ? (*cmh )[moved_piece][to_sq(move)] : VALUE_ZERO)
                      +    (fmh  ? (*fmh )[moved_piece][to_sq(move)] : VALUE_ZERO)
-                     +    (fmh2 ? (*fmh2)[moved_piece][to_sq(move)] : VALUE_ZERO);
+                     +    (fmh2 ? (*fmh2)[moved_piece][to_sq(move)] : VALUE_ZERO)
+                     +    thisThread->fromTo.get(~pos.side_to_move(), move);
 
           // Increase reduction for cut nodes
           if (cutNode)
@@ -1395,7 +1397,8 @@ moves_loop: // When in check search starts from here
         ss->killers[1] = ss->killers[0];
         ss->killers[0] = move;
     }
-
+       
+    Color c = pos.side_to_move();
     Value bonus = Value((depth / ONE_PLY) * (depth / ONE_PLY) + 2 * depth / ONE_PLY - 2);
 
     Square prevSq = to_sq((ss-1)->currentMove);
@@ -1405,6 +1408,7 @@ moves_loop: // When in check search starts from here
     Thread* thisThread = pos.this_thread();
 
     thisThread->history.update(pos.moved_piece(move), to_sq(move), bonus);
+    thisThread->fromTo.update(c, move, bonus);
 
     if (cmh)
     {
@@ -1422,6 +1426,7 @@ moves_loop: // When in check search starts from here
     for (int i = 0; i < quietsCnt; ++i)
     {
         thisThread->history.update(pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
+        thisThread->fromTo.update(c, quiets[i], -bonus);
 
         if (cmh)
             cmh->update(pos.moved_piece(quiets[i]), to_sq(quiets[i]), -bonus);
index 4e63fe4..8181163 100644 (file)
@@ -68,6 +68,7 @@ public:
   Depth rootDepth;
   HistoryStats history;
   MoveStats counterMoves;
+  FromToStats fromTo;
   Depth completedDepth;
   std::atomic_bool resetCalls;
 };