]> git.sesse.net Git - stockfish/blobdiff - src/syzygy/tbprobe.cpp
Reorder evaluation start
[stockfish] / src / syzygy / tbprobe.cpp
index de437d706d8426ac19883a7b0808870b2f9ba165..0281ccc8684d9c158f07d47b49845dddb78b2729 100644 (file)
@@ -7,11 +7,14 @@
   this code to other chess engines.
 */
 
+#define NOMINMAX
+
+#include <algorithm>
+
 #include "../position.h"
 #include "../movegen.h"
 #include "../bitboard.h"
 #include "../search.h"
-#include "../bitcount.h"
 
 #include "tbprobe.h"
 #include "tbcore.h"
 #include "tbcore.cpp"
 
 namespace Zobrist {
-  extern Key psq[COLOR_NB][PIECE_TYPE_NB][SQUARE_NB];
+  extern Key psq[PIECE_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
@@ -32,15 +35,15 @@ static void prt_str(Position& pos, char *str, int mirror)
   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--)
+    for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
       *str++ = pchr[6 - pt];
   *str++ = 'v';
   color = ~color;
   for (pt = KING; pt >= PAWN; --pt)
-    for (i = popcount<Max15>(pos.pieces(color, pt)); i > 0; i--)
+    for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
       *str++ = pchr[6 - pt];
   *str++ = 0;
 }
@@ -56,12 +59,12 @@ static uint64 calc_key(Position& pos, int mirror)
 
   color = !mirror ? WHITE : BLACK;
   for (pt = PAWN; pt <= KING; ++pt)
-    for (i = popcount<Max15>(pos.pieces(color, pt)); i > 0; i--)
-      key ^= Zobrist::psq[WHITE][pt][i - 1];
+    for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
+      key ^= Zobrist::psq[make_piece(WHITE, pt)][i - 1];
   color = ~color;
   for (pt = PAWN; pt <= KING; ++pt)
-    for (i = popcount<Max15>(pos.pieces(color, pt)); i > 0; i--)
-      key ^= Zobrist::psq[BLACK][pt][i - 1];
+    for (i = popcount(pos.pieces(color, pt)); i > 0; i--)
+      key ^= Zobrist::psq[make_piece(BLACK, pt)][i - 1];
 
   return key;
 }
@@ -80,11 +83,11 @@ static uint64 calc_key_from_pcs(int *pcs, int mirror)
   color = !mirror ? 0 : 8;
   for (pt = PAWN; pt <= KING; ++pt)
     for (i = 0; i < pcs[color + pt]; i++)
-      key ^= Zobrist::psq[WHITE][pt][i];
+      key ^= Zobrist::psq[make_piece(WHITE, pt)][i];
   color ^= 8;
   for (pt = PAWN; pt <= KING; ++pt)
     for (i = 0; i < pcs[color + pt]; i++)
-      key ^= Zobrist::psq[BLACK][pt][i];
+      key ^= Zobrist::psq[make_piece(BLACK, pt)][i];
 
   return key;
 }
@@ -120,7 +123,7 @@ static int probe_wdl_table(Position& pos, int *success)
   key = pos.material_key();
 
   // Test for KvK.
-  if (key == (Zobrist::psq[WHITE][KING][0] ^ Zobrist::psq[BLACK][KING][0]))
+  if (key == (Zobrist::psq[W_KING][0] ^ Zobrist::psq[B_KING][0]))
     return 0;
 
   ptr2 = TB_hash[key >> (64 - TBHASHBITS)];
@@ -144,7 +147,11 @@ static int probe_wdl_table(Position& pos, int *success)
         return 0;
       }
       // Memory barrier to ensure ptr->ready = 1 is not reordered.
+#ifdef _MSC_VER
+      _ReadWriteBarrier();
+#else
       __asm__ __volatile__ ("" ::: "memory");
+#endif
       ptr->ready = 1;
     }
     UNLOCK(TB_mutex);
@@ -354,14 +361,12 @@ static int probe_ab(Position& pos, int alpha, int beta, int *success)
   } else
     end = generate<EVASIONS>(pos, stack);
 
-  CheckInfo ci(pos);
-
   for (moves = stack; moves < end; moves++) {
     Move capture = moves->move;
     if (!pos.capture(capture) || type_of(capture) == ENPASSANT
-                        || !pos.legal(capture, ci.pinned))
+                        || !pos.legal(capture))
       continue;
-    pos.do_move(capture, st, ci, pos.gives_check(capture, ci));
+    pos.do_move(capture, st, pos.gives_check(capture));
     v = -probe_ab(pos, -beta, -alpha, success);
     pos.undo_move(capture);
     if (*success == 0) return 0;
@@ -417,14 +422,12 @@ int Tablebases::probe_wdl(Position& pos, int *success)
   else
     end = generate<EVASIONS>(pos, stack);
 
-  CheckInfo ci(pos);
-
   for (moves = stack; moves < end; moves++) {
     Move capture = moves->move;
     if (type_of(capture) != ENPASSANT
-          || !pos.legal(capture, ci.pinned))
+          || !pos.legal(capture))
       continue;
-    pos.do_move(capture, st, ci, pos.gives_check(capture, ci));
+    pos.do_move(capture, st, pos.gives_check(capture));
     int v0 = -probe_ab(pos, -2, 2, success);
     pos.undo_move(capture);
     if (*success == 0) return 0;
@@ -437,13 +440,13 @@ int Tablebases::probe_wdl(Position& pos, int *success)
       for (moves = stack; moves < end; moves++) {
         Move capture = moves->move;
         if (type_of(capture) == ENPASSANT) continue;
-        if (pos.legal(capture, ci.pinned)) break;
+        if (pos.legal(capture)) break;
       }
       if (moves == end && !pos.checkers()) {
         end = generate<QUIETS>(pos, end);
         for (; moves < end; moves++) {
           Move move = moves->move;
-          if (pos.legal(move, ci.pinned))
+          if (pos.legal(move))
             break;
         }
       }
@@ -472,7 +475,6 @@ static int probe_dtz_no_ep(Position& pos, int *success)
   ExtMove stack[192];
   ExtMove *moves, *end = NULL;
   StateInfo st;
-  CheckInfo ci(pos);
 
   if (wdl > 0) {
     // Generate at least all legal non-capturing pawn moves
@@ -485,10 +487,10 @@ static int probe_dtz_no_ep(Position& pos, int *success)
     for (moves = stack; moves < end; moves++) {
       Move move = moves->move;
       if (type_of(pos.moved_piece(move)) != PAWN || pos.capture(move)
-                || !pos.legal(move, ci.pinned))
+                || !pos.legal(move))
         continue;
-      pos.do_move(move, st, ci, pos.gives_check(move, ci));
-      int v = -probe_ab(pos, -2, -wdl + 1, success);
+      pos.do_move(move, st, pos.gives_check(move));
+      int v = -Tablebases::probe_wdl(pos, success);
       pos.undo_move(move);
       if (*success == 0) return 0;
       if (v == wdl)
@@ -507,9 +509,9 @@ static int probe_dtz_no_ep(Position& pos, int *success)
     for (moves = stack; moves < end; moves++) {
       Move move = moves->move;
       if (pos.capture(move) || type_of(pos.moved_piece(move)) == PAWN
-                || !pos.legal(move, ci.pinned))
+                || !pos.legal(move))
         continue;
-      pos.do_move(move, st, ci, pos.gives_check(move, ci));
+      pos.do_move(move, st, pos.gives_check(move));
       int v = -Tablebases::probe_dtz(pos, success);
       pos.undo_move(move);
       if (*success == 0) return 0;
@@ -526,9 +528,9 @@ static int probe_dtz_no_ep(Position& pos, int *success)
     for (moves = stack; moves < end; moves++) {
       int v;
       Move move = moves->move;
-      if (!pos.legal(move, ci.pinned))
+      if (!pos.legal(move))
         continue;
-      pos.do_move(move, st, ci, pos.gives_check(move, ci));
+      pos.do_move(move, st, pos.gives_check(move));
       if (st.rule50 == 0) {
         if (wdl == -2) v = -1;
         else {
@@ -597,14 +599,13 @@ int Tablebases::probe_dtz(Position& pos, int *success)
     end = generate<CAPTURES>(pos, stack);
   else
     end = generate<EVASIONS>(pos, stack);
-  CheckInfo ci(pos);
 
   for (moves = stack; moves < end; moves++) {
     Move capture = moves->move;
     if (type_of(capture) != ENPASSANT
-                || !pos.legal(capture, ci.pinned))
+                || !pos.legal(capture))
       continue;
-    pos.do_move(capture, st, ci, pos.gives_check(capture, ci));
+    pos.do_move(capture, st, pos.gives_check(capture));
     int v0 = -probe_ab(pos, -2, 2, success);
     pos.undo_move(capture);
     if (*success == 0) return 0;
@@ -616,7 +617,7 @@ int Tablebases::probe_dtz(Position& pos, int *success)
       if (v1 >= 0)
         v = v1;
     } else if (v < 0) {
-      if (v1 >= 0 || v1 < 100)
+      if (v1 >= 0 || v1 < -100)
         v = v1;
     } else if (v > 100) {
       if (v1 > 0)
@@ -630,13 +631,13 @@ int Tablebases::probe_dtz(Position& pos, int *success)
       for (moves = stack; moves < end; moves++) {
         Move move = moves->move;
         if (type_of(move) == ENPASSANT) continue;
-        if (pos.legal(move, ci.pinned)) break;
+        if (pos.legal(move)) break;
       }
       if (moves == end && !pos.checkers()) {
         end = generate<QUIETS>(pos, end);
         for (; moves < end; moves++) {
           Move move = moves->move;
-          if (pos.legal(move, ci.pinned))
+          if (pos.legal(move))
             break;
         }
       }
@@ -681,7 +682,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.
-bool Tablebases::root_probe(Position& pos, Value& TBScore)
+bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves, Value& score)
 {
   int success;
 
@@ -689,12 +690,11 @@ bool Tablebases::root_probe(Position& pos, Value& TBScore)
   if (!success) return false;
 
   StateInfo st;
-  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));
     int v = 0;
     if (pos.checkers() && dtz > 0) {
       ExtMove s[192];
@@ -713,7 +713,7 @@ bool Tablebases::root_probe(Position& pos, Value& TBScore)
     }
     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.
@@ -729,21 +729,21 @@ bool Tablebases::root_probe(Position& pos, Value& TBScore)
     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)
-    TBScore = (Value)(((200 - dtz - cnt50) * int(PawnValueEg)) / 200);
+    score = (Value)(((200 - dtz - cnt50) * int(PawnValueEg)) / 200);
   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;
-    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;
     }
@@ -752,33 +752,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;
-    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)
-        Search::RootMoves[j++] = Search::RootMoves[i];
+        rootMoves[j++] = rootMoves[i];
     }
   } 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;
-    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.
-    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;
 }
@@ -788,37 +788,36 @@ 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.
-bool Tablebases::root_probe_wdl(Position& pos, Value& TBScore)
+bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, Value& score)
 {
   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);
 
   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));
     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;
-  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;
 }