X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fsyzygy%2Ftbprobe.cpp;h=0281ccc8684d9c158f07d47b49845dddb78b2729;hp=de437d706d8426ac19883a7b0808870b2f9ba165;hb=4c95edddbf1aaec22c343adaca4796df0137e4c3;hpb=7caa6cd3383cf90189a1947c9bdf9c6fea1172a6 diff --git a/src/syzygy/tbprobe.cpp b/src/syzygy/tbprobe.cpp index de437d70..0281ccc8 100644 --- a/src/syzygy/tbprobe.cpp +++ b/src/syzygy/tbprobe.cpp @@ -7,11 +7,14 @@ this code to other chess engines. */ +#define NOMINMAX + +#include + #include "../position.h" #include "../movegen.h" #include "../bitboard.h" #include "../search.h" -#include "../bitcount.h" #include "tbprobe.h" #include "tbcore.h" @@ -19,10 +22,10 @@ #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(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(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(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(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(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(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(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(pos, stack); else end = generate(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(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; }