Compute checkers from scratch
[stockfish] / src / syzygy / tbprobe.cpp
index de437d706d8426ac19883a7b0808870b2f9ba165..17326970a49c55194ddc7e37c3a2946306c87a47 100644 (file)
@@ -7,6 +7,8 @@
   this code to other chess engines.
 */
 
   this code to other chess engines.
 */
 
+#include <algorithm>
+
 #include "../position.h"
 #include "../movegen.h"
 #include "../bitboard.h"
 #include "../position.h"
 #include "../movegen.h"
 #include "../bitboard.h"
@@ -22,7 +24,7 @@ namespace Zobrist {
   extern Key psq[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
 }
 
   extern Key psq[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
 }
 
-int Tablebases::TBLargest = 0;
+int Tablebases::MaxCardinality = 0;
 
 // Given a position with 6 or fewer pieces, produce a text string
 // of the form KQPvKRP, where "KQP" represents the white pieces if
 
 // Given a position with 6 or fewer pieces, produce a text string
 // of the form KQPvKRP, where "KQP" represents the white pieces if
@@ -32,7 +34,7 @@ static void prt_str(Position& pos, char *str, int mirror)
   Color color;
   PieceType pt;
   int i;
   Color color;
   PieceType pt;
   int i;
-  
+
   color = !mirror ? WHITE : BLACK;
   for (pt = KING; pt >= PAWN; --pt)
     for (i = popcount<Max15>(pos.pieces(color, pt)); i > 0; i--)
   color = !mirror ? WHITE : BLACK;
   for (pt = KING; pt >= PAWN; --pt)
     for (i = popcount<Max15>(pos.pieces(color, pt)); i > 0; i--)
@@ -144,7 +146,11 @@ static int probe_wdl_table(Position& pos, int *success)
         return 0;
       }
       // Memory barrier to ensure ptr->ready = 1 is not reordered.
         return 0;
       }
       // Memory barrier to ensure ptr->ready = 1 is not reordered.
+#ifdef _MSC_VER
+      _ReadWriteBarrier();
+#else
       __asm__ __volatile__ ("" ::: "memory");
       __asm__ __volatile__ ("" ::: "memory");
+#endif
       ptr->ready = 1;
     }
     UNLOCK(TB_mutex);
       ptr->ready = 1;
     }
     UNLOCK(TB_mutex);
@@ -361,7 +367,7 @@ static int probe_ab(Position& pos, int alpha, int beta, int *success)
     if (!pos.capture(capture) || type_of(capture) == ENPASSANT
                         || !pos.legal(capture, ci.pinned))
       continue;
     if (!pos.capture(capture) || type_of(capture) == ENPASSANT
                         || !pos.legal(capture, ci.pinned))
       continue;
-    pos.do_move(capture, st, ci, pos.gives_check(capture, ci));
+    pos.do_move(capture, st, pos.gives_check(capture, ci));
     v = -probe_ab(pos, -beta, -alpha, success);
     pos.undo_move(capture);
     if (*success == 0) return 0;
     v = -probe_ab(pos, -beta, -alpha, success);
     pos.undo_move(capture);
     if (*success == 0) return 0;
@@ -424,7 +430,7 @@ int Tablebases::probe_wdl(Position& pos, int *success)
     if (type_of(capture) != ENPASSANT
           || !pos.legal(capture, ci.pinned))
       continue;
     if (type_of(capture) != ENPASSANT
           || !pos.legal(capture, ci.pinned))
       continue;
-    pos.do_move(capture, st, ci, pos.gives_check(capture, ci));
+    pos.do_move(capture, st, pos.gives_check(capture, ci));
     int v0 = -probe_ab(pos, -2, 2, success);
     pos.undo_move(capture);
     if (*success == 0) return 0;
     int v0 = -probe_ab(pos, -2, 2, success);
     pos.undo_move(capture);
     if (*success == 0) return 0;
@@ -487,7 +493,7 @@ static int probe_dtz_no_ep(Position& pos, int *success)
       if (type_of(pos.moved_piece(move)) != PAWN || pos.capture(move)
                 || !pos.legal(move, ci.pinned))
         continue;
       if (type_of(pos.moved_piece(move)) != PAWN || pos.capture(move)
                 || !pos.legal(move, ci.pinned))
         continue;
-      pos.do_move(move, st, ci, pos.gives_check(move, ci));
+      pos.do_move(move, st, pos.gives_check(move, ci));
       int v = -probe_ab(pos, -2, -wdl + 1, success);
       pos.undo_move(move);
       if (*success == 0) return 0;
       int v = -probe_ab(pos, -2, -wdl + 1, success);
       pos.undo_move(move);
       if (*success == 0) return 0;
@@ -509,7 +515,7 @@ static int probe_dtz_no_ep(Position& pos, int *success)
       if (pos.capture(move) || type_of(pos.moved_piece(move)) == PAWN
                 || !pos.legal(move, ci.pinned))
         continue;
       if (pos.capture(move) || type_of(pos.moved_piece(move)) == PAWN
                 || !pos.legal(move, ci.pinned))
         continue;
-      pos.do_move(move, st, ci, pos.gives_check(move, ci));
+      pos.do_move(move, st, pos.gives_check(move, ci));
       int v = -Tablebases::probe_dtz(pos, success);
       pos.undo_move(move);
       if (*success == 0) return 0;
       int v = -Tablebases::probe_dtz(pos, success);
       pos.undo_move(move);
       if (*success == 0) return 0;
@@ -528,7 +534,7 @@ static int probe_dtz_no_ep(Position& pos, int *success)
       Move move = moves->move;
       if (!pos.legal(move, ci.pinned))
         continue;
       Move move = moves->move;
       if (!pos.legal(move, ci.pinned))
         continue;
-      pos.do_move(move, st, ci, pos.gives_check(move, ci));
+      pos.do_move(move, st, pos.gives_check(move, ci));
       if (st.rule50 == 0) {
         if (wdl == -2) v = -1;
         else {
       if (st.rule50 == 0) {
         if (wdl == -2) v = -1;
         else {
@@ -604,7 +610,7 @@ int Tablebases::probe_dtz(Position& pos, int *success)
     if (type_of(capture) != ENPASSANT
                 || !pos.legal(capture, ci.pinned))
       continue;
     if (type_of(capture) != ENPASSANT
                 || !pos.legal(capture, ci.pinned))
       continue;
-    pos.do_move(capture, st, ci, pos.gives_check(capture, ci));
+    pos.do_move(capture, st, pos.gives_check(capture, ci));
     int v0 = -probe_ab(pos, -2, 2, success);
     pos.undo_move(capture);
     if (*success == 0) return 0;
     int v0 = -probe_ab(pos, -2, 2, success);
     pos.undo_move(capture);
     if (*success == 0) return 0;
@@ -681,7 +687,7 @@ static Value wdl_to_Value[5] = {
 //
 // A return value false indicates that not all probes were successful and that
 // no moves were filtered out.
 //
 // A return value false indicates that not all probes were successful and that
 // no moves were filtered out.
-bool Tablebases::root_probe(Position& pos, Value& TBScore)
+bool Tablebases::root_probe(Position& pos, Search::RootMoveVector& rootMoves, Value& score)
 {
   int success;
 
 {
   int success;
 
@@ -692,9 +698,9 @@ bool Tablebases::root_probe(Position& pos, Value& TBScore)
   CheckInfo ci(pos);
 
   // Probe each move.
   CheckInfo ci(pos);
 
   // Probe each move.
-  for (size_t i = 0; i < Search::RootMoves.size(); i++) {
-    Move move = Search::RootMoves[i].pv[0];
-    pos.do_move(move, st, ci, pos.gives_check(move, ci));
+  for (size_t i = 0; i < rootMoves.size(); i++) {
+    Move move = rootMoves[i].pv[0];
+    pos.do_move(move, st, pos.gives_check(move, ci));
     int v = 0;
     if (pos.checkers() && dtz > 0) {
       ExtMove s[192];
     int v = 0;
     if (pos.checkers() && dtz > 0) {
       ExtMove s[192];
@@ -713,7 +719,7 @@ bool Tablebases::root_probe(Position& pos, Value& TBScore)
     }
     pos.undo_move(move);
     if (!success) return false;
     }
     pos.undo_move(move);
     if (!success) return false;
-    Search::RootMoves[i].score = (Value)v;
+    rootMoves[i].score = (Value)v;
   }
 
   // Obtain 50-move counter for the root position.
   }
 
   // Obtain 50-move counter for the root position.
@@ -729,21 +735,21 @@ bool Tablebases::root_probe(Position& pos, Value& TBScore)
     wdl = (-dtz + cnt50 <= 100) ? -2 : -1;
 
   // Determine the score to report to the user.
     wdl = (-dtz + cnt50 <= 100) ? -2 : -1;
 
   // Determine the score to report to the user.
-  TBScore = wdl_to_Value[wdl + 2];
+  score = wdl_to_Value[wdl + 2];
   // If the position is winning or losing, but too few moves left, adjust the
   // score to show how close it is to winning or losing.
   // NOTE: int(PawnValueEg) is used as scaling factor in score_to_uci().
   if (wdl == 1 && dtz <= 100)
   // If the position is winning or losing, but too few moves left, adjust the
   // score to show how close it is to winning or losing.
   // NOTE: int(PawnValueEg) is used as scaling factor in score_to_uci().
   if (wdl == 1 && dtz <= 100)
-    TBScore = (Value)(((200 - dtz - cnt50) * int(PawnValueEg)) / 200);
+    score = (Value)(((200 - dtz - cnt50) * int(PawnValueEg)) / 200);
   else if (wdl == -1 && dtz >= -100)
   else if (wdl == -1 && dtz >= -100)
-    TBScore = -(Value)(((200 + dtz - cnt50) * int(PawnValueEg)) / 200);
+    score = -(Value)(((200 + dtz - cnt50) * int(PawnValueEg)) / 200);
 
   // Now be a bit smart about filtering out moves.
   size_t j = 0;
   if (dtz > 0) { // winning (or 50-move rule draw)
     int best = 0xffff;
 
   // Now be a bit smart about filtering out moves.
   size_t j = 0;
   if (dtz > 0) { // winning (or 50-move rule draw)
     int best = 0xffff;
-    for (size_t i = 0; i < Search::RootMoves.size(); i++) {
-      int v = Search::RootMoves[i].score;
+    for (size_t i = 0; i < rootMoves.size(); i++) {
+      int v = rootMoves[i].score;
       if (v > 0 && v < best)
         best = v;
     }
       if (v > 0 && v < best)
         best = v;
     }
@@ -752,33 +758,33 @@ bool Tablebases::root_probe(Position& pos, Value& TBScore)
     // that stay safely within the 50-move budget, if there are any.
     if (!has_repeated(st.previous) && best + cnt50 <= 99)
       max = 99 - cnt50;
     // that stay safely within the 50-move budget, if there are any.
     if (!has_repeated(st.previous) && best + cnt50 <= 99)
       max = 99 - cnt50;
-    for (size_t i = 0; i < Search::RootMoves.size(); i++) {
-      int v = Search::RootMoves[i].score;
+    for (size_t i = 0; i < rootMoves.size(); i++) {
+      int v = rootMoves[i].score;
       if (v > 0 && v <= max)
       if (v > 0 && v <= max)
-        Search::RootMoves[j++] = Search::RootMoves[i];
+        rootMoves[j++] = rootMoves[i];
     }
   } else if (dtz < 0) { // losing (or 50-move rule draw)
     int best = 0;
     }
   } else if (dtz < 0) { // losing (or 50-move rule draw)
     int best = 0;
-    for (size_t i = 0; i < Search::RootMoves.size(); i++) {
-      int v = Search::RootMoves[i].score;
+    for (size_t i = 0; i < rootMoves.size(); i++) {
+      int v = rootMoves[i].score;
       if (v < best)
         best = v;
     }
     // Try all moves, unless we approach or have a 50-move rule draw.
     if (-best * 2 + cnt50 < 100)
       return true;
       if (v < best)
         best = v;
     }
     // Try all moves, unless we approach or have a 50-move rule draw.
     if (-best * 2 + cnt50 < 100)
       return true;
-    for (size_t i = 0; i < Search::RootMoves.size(); i++) {
-      if (Search::RootMoves[i].score == best)
-        Search::RootMoves[j++] = Search::RootMoves[i];
+    for (size_t i = 0; i < rootMoves.size(); i++) {
+      if (rootMoves[i].score == best)
+        rootMoves[j++] = rootMoves[i];
     }
   } else { // drawing
     // Try all moves that preserve the draw.
     }
   } else { // drawing
     // Try all moves that preserve the draw.
-    for (size_t i = 0; i < Search::RootMoves.size(); i++) {
-      if (Search::RootMoves[i].score == 0)
-        Search::RootMoves[j++] = Search::RootMoves[i];
+    for (size_t i = 0; i < rootMoves.size(); i++) {
+      if (rootMoves[i].score == 0)
+        rootMoves[j++] = rootMoves[i];
     }
   }
     }
   }
-  Search::RootMoves.resize(j, Search::RootMove(MOVE_NONE));
+  rootMoves.resize(j, Search::RootMove(MOVE_NONE));
 
   return true;
 }
 
   return true;
 }
@@ -788,13 +794,13 @@ bool Tablebases::root_probe(Position& pos, Value& TBScore)
 //
 // A return value false indicates that not all probes were successful and that
 // no moves were filtered out.
 //
 // A return value false indicates that not all probes were successful and that
 // no moves were filtered out.
-bool Tablebases::root_probe_wdl(Position& pos, Value& TBScore)
+bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoveVector& rootMoves, Value& score)
 {
   int success;
 
   int wdl = Tablebases::probe_wdl(pos, &success);
   if (!success) return false;
 {
   int success;
 
   int wdl = Tablebases::probe_wdl(pos, &success);
   if (!success) return false;
-  TBScore = wdl_to_Value[wdl + 2];
+  score = wdl_to_Value[wdl + 2];
 
   StateInfo st;
   CheckInfo ci(pos);
 
   StateInfo st;
   CheckInfo ci(pos);
@@ -802,23 +808,23 @@ bool Tablebases::root_probe_wdl(Position& pos, Value& TBScore)
   int best = -2;
 
   // Probe each move.
   int best = -2;
 
   // Probe each move.
-  for (size_t i = 0; i < Search::RootMoves.size(); i++) {
-    Move move = Search::RootMoves[i].pv[0];
-    pos.do_move(move, st, ci, pos.gives_check(move, ci));
+  for (size_t i = 0; i < rootMoves.size(); i++) {
+    Move move = rootMoves[i].pv[0];
+    pos.do_move(move, st, pos.gives_check(move, ci));
     int v = -Tablebases::probe_wdl(pos, &success);
     pos.undo_move(move);
     if (!success) return false;
     int v = -Tablebases::probe_wdl(pos, &success);
     pos.undo_move(move);
     if (!success) return false;
-    Search::RootMoves[i].score = (Value)v;
+    rootMoves[i].score = (Value)v;
     if (v > best)
       best = v;
   }
 
   size_t j = 0;
     if (v > best)
       best = v;
   }
 
   size_t j = 0;
-  for (size_t i = 0; i < Search::RootMoves.size(); i++) {
-    if (Search::RootMoves[i].score == best)
-      Search::RootMoves[j++] = Search::RootMoves[i];
+  for (size_t i = 0; i < rootMoves.size(); i++) {
+    if (rootMoves[i].score == best)
+      rootMoves[j++] = rootMoves[i];
   }
   }
-  Search::RootMoves.resize(j, Search::RootMove(MOVE_NONE));
+  rootMoves.resize(j, Search::RootMove(MOVE_NONE));
 
   return true;
 }
 
   return true;
 }