mirror of
https://github.com/sockspls/badfish
synced 2025-05-01 17:19:36 +00:00
Retire probe_dtz() from Tablebases
It is not needed in SF.
This commit is contained in:
parent
7aeef7285f
commit
39e4398133
2 changed files with 236 additions and 235 deletions
|
@ -505,7 +505,7 @@ public:
|
|||
|
||||
// Given a position, produce a 64-bit material signature key. If the engine
|
||||
// supports such a key, it should equal the engine's key.
|
||||
Key get_key(Position& pos, bool mirror)
|
||||
Key get_key(const Position& pos, bool mirror)
|
||||
{
|
||||
Key key = 0;
|
||||
|
||||
|
@ -1520,7 +1520,7 @@ WDLScore probe_wdl_table(Position& pos, int* success)
|
|||
}
|
||||
}
|
||||
|
||||
int probe_dtz_table(Position& pos, int wdl, int *success)
|
||||
int probe_dtz_table(const Position& pos, int wdl, int *success)
|
||||
{
|
||||
uint64_t idx;
|
||||
int i, res;
|
||||
|
@ -1727,6 +1727,238 @@ WDLScore probe_ab(Position& pos, WDLScore alpha, WDLScore beta, int *success)
|
|||
}
|
||||
}
|
||||
|
||||
int probe_dtz(Position& pos, int *success);
|
||||
|
||||
// This routine treats a position with en passant captures as one without.
|
||||
int probe_dtz_no_ep(Position& pos, int *success)
|
||||
{
|
||||
int dtz;
|
||||
|
||||
WDLScore wdl = probe_ab(pos, WDLHardLoss, WDLHardWin, success);
|
||||
|
||||
if (*success == 0) return 0;
|
||||
|
||||
if (wdl == WDLDraw) return 0;
|
||||
|
||||
if (*success == 2)
|
||||
return wdl == WDLHardWin ? 1 : 101;
|
||||
|
||||
ExtMove stack[MAX_MOVES];
|
||||
ExtMove *moves, *end = NULL;
|
||||
StateInfo st;
|
||||
CheckInfo ci(pos);
|
||||
|
||||
if (wdl > 0) {
|
||||
// Generate at least all legal non-capturing pawn moves
|
||||
// including non-capturing promotions.
|
||||
if (!pos.checkers())
|
||||
end = generate<NON_EVASIONS>(pos, stack);
|
||||
else
|
||||
end = generate<EVASIONS>(pos, stack);
|
||||
|
||||
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))
|
||||
continue;
|
||||
|
||||
pos.do_move(move, st, pos.gives_check(move, ci));
|
||||
WDLScore v = -probe_ab(pos, WDLHardLoss, -wdl + WDLSoftWin, success);
|
||||
pos.undo_move(move);
|
||||
|
||||
if (*success == 0) return 0;
|
||||
|
||||
if (v == wdl)
|
||||
return v == WDLHardWin ? 1 : 101;
|
||||
}
|
||||
}
|
||||
|
||||
dtz = 1 + probe_dtz_table(pos, wdl, success);
|
||||
|
||||
if (*success >= 0) {
|
||||
if (wdl & 1) dtz += 100;
|
||||
|
||||
return wdl >= 0 ? dtz : -dtz;
|
||||
}
|
||||
|
||||
if (wdl > 0) {
|
||||
int best = 0xffff;
|
||||
|
||||
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))
|
||||
continue;
|
||||
|
||||
pos.do_move(move, st, pos.gives_check(move, ci));
|
||||
int v = -probe_dtz(pos, success);
|
||||
pos.undo_move(move);
|
||||
|
||||
if (*success == 0)
|
||||
return 0;
|
||||
|
||||
if (v > 0 && v + 1 < best)
|
||||
best = v + 1;
|
||||
}
|
||||
|
||||
return best;
|
||||
} else {
|
||||
int best = -1;
|
||||
|
||||
if (!pos.checkers())
|
||||
end = generate<NON_EVASIONS>(pos, stack);
|
||||
else
|
||||
end = generate<EVASIONS>(pos, stack);
|
||||
|
||||
for (moves = stack; moves < end; ++moves) {
|
||||
int v;
|
||||
Move move = moves->move;
|
||||
|
||||
if (!pos.legal(move, ci.pinned))
|
||||
continue;
|
||||
|
||||
pos.do_move(move, st, pos.gives_check(move, ci));
|
||||
|
||||
if (st.rule50 == 0) {
|
||||
if (wdl == -2) v = -1;
|
||||
else {
|
||||
v = probe_ab(pos, WDLSoftWin, WDLHardWin, success);
|
||||
v = (v == 2) ? 0 : -101;
|
||||
}
|
||||
} else {
|
||||
v = -probe_dtz(pos, success) - 1;
|
||||
}
|
||||
|
||||
pos.undo_move(move);
|
||||
|
||||
if (*success == 0)
|
||||
return 0;
|
||||
|
||||
if (v < best)
|
||||
best = v;
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
}
|
||||
|
||||
// Probe the DTZ table for a particular position.
|
||||
// If *success != 0, the probe was successful.
|
||||
// The return value is from the point of view of the side to move:
|
||||
// n < -100 : loss, but draw under 50-move rule
|
||||
// -100 <= n < -1 : loss in n ply (assuming 50-move counter == 0)
|
||||
// 0 : draw
|
||||
// 1 < n <= 100 : win in n ply (assuming 50-move counter == 0)
|
||||
// 100 < n : win, but draw under 50-move rule
|
||||
//
|
||||
// The return value n can be off by 1: a return value -n can mean a loss
|
||||
// in n+1 ply and a return value +n can mean a win in n+1 ply. This
|
||||
// cannot happen for tables with positions exactly on the "edge" of
|
||||
// the 50-move rule.
|
||||
//
|
||||
// This implies that if dtz > 0 is returned, the position is certainly
|
||||
// a win if dtz + 50-move-counter <= 99. Care must be taken that the engine
|
||||
// picks moves that preserve dtz + 50-move-counter <= 99.
|
||||
//
|
||||
// If n = 100 immediately after a capture or pawn move, then the position
|
||||
// is also certainly a win, and during the whole phase until the next
|
||||
// capture or pawn move, the inequality to be preserved is
|
||||
// dtz + 50-movecounter <= 100.
|
||||
//
|
||||
// In short, if a move is available resulting in dtz + 50-move-counter <= 99,
|
||||
// then do not accept moves leading to dtz + 50-move-counter == 100.
|
||||
//
|
||||
int probe_dtz(Position& pos, int *success)
|
||||
{
|
||||
*success = 1;
|
||||
int v = probe_dtz_no_ep(pos, success);
|
||||
|
||||
if (pos.ep_square() == SQ_NONE)
|
||||
return v;
|
||||
|
||||
if (*success == 0)
|
||||
return 0;
|
||||
|
||||
// Now handle en passant.
|
||||
int v1 = -3;
|
||||
|
||||
ExtMove stack[MAX_MOVES];
|
||||
ExtMove *moves, *end;
|
||||
StateInfo st;
|
||||
|
||||
if (!pos.checkers())
|
||||
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))
|
||||
continue;
|
||||
|
||||
pos.do_move(capture, st, pos.gives_check(capture, ci));
|
||||
WDLScore v0 = -probe_ab(pos, WDLHardLoss, WDLHardWin, success);
|
||||
pos.undo_move(capture);
|
||||
|
||||
if (*success == 0)
|
||||
return 0;
|
||||
|
||||
if (v0 > v1) v1 = v0;
|
||||
}
|
||||
|
||||
if (v1 > -3) {
|
||||
v1 = wdl_to_dtz[v1 + 2];
|
||||
|
||||
if (v < -100) {
|
||||
if (v1 >= 0)
|
||||
v = v1;
|
||||
} else if (v < 0) {
|
||||
if (v1 >= 0 || v1 < -100)
|
||||
v = v1;
|
||||
} else if (v > 100) {
|
||||
if (v1 > 0)
|
||||
v = v1;
|
||||
} else if (v > 0) {
|
||||
if (v1 == 1)
|
||||
v = v1;
|
||||
} else if (v1 >= 0) {
|
||||
v = v1;
|
||||
} else {
|
||||
for (moves = stack; moves < end; ++moves) {
|
||||
Move move = moves->move;
|
||||
|
||||
if (type_of(move) == ENPASSANT) continue;
|
||||
|
||||
if (pos.legal(move, ci.pinned))
|
||||
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))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (moves == end)
|
||||
v = v1;
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Tablebases::free()
|
||||
|
@ -1895,236 +2127,6 @@ WDLScore Tablebases::probe_wdl(Position& pos, int *success)
|
|||
return v;
|
||||
}
|
||||
|
||||
// This routine treats a position with en passant captures as one without.
|
||||
static int probe_dtz_no_ep(Position& pos, int *success)
|
||||
{
|
||||
int dtz;
|
||||
|
||||
WDLScore wdl = probe_ab(pos, WDLHardLoss, WDLHardWin, success);
|
||||
|
||||
if (*success == 0) return 0;
|
||||
|
||||
if (wdl == WDLDraw) return 0;
|
||||
|
||||
if (*success == 2)
|
||||
return wdl == WDLHardWin ? 1 : 101;
|
||||
|
||||
ExtMove stack[MAX_MOVES];
|
||||
ExtMove *moves, *end = NULL;
|
||||
StateInfo st;
|
||||
CheckInfo ci(pos);
|
||||
|
||||
if (wdl > 0) {
|
||||
// Generate at least all legal non-capturing pawn moves
|
||||
// including non-capturing promotions.
|
||||
if (!pos.checkers())
|
||||
end = generate<NON_EVASIONS>(pos, stack);
|
||||
else
|
||||
end = generate<EVASIONS>(pos, stack);
|
||||
|
||||
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))
|
||||
continue;
|
||||
|
||||
pos.do_move(move, st, pos.gives_check(move, ci));
|
||||
WDLScore v = -probe_ab(pos, WDLHardLoss, -wdl + WDLSoftWin, success);
|
||||
pos.undo_move(move);
|
||||
|
||||
if (*success == 0) return 0;
|
||||
|
||||
if (v == wdl)
|
||||
return v == WDLHardWin ? 1 : 101;
|
||||
}
|
||||
}
|
||||
|
||||
dtz = 1 + probe_dtz_table(pos, wdl, success);
|
||||
|
||||
if (*success >= 0) {
|
||||
if (wdl & 1) dtz += 100;
|
||||
|
||||
return wdl >= 0 ? dtz : -dtz;
|
||||
}
|
||||
|
||||
if (wdl > 0) {
|
||||
int best = 0xffff;
|
||||
|
||||
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))
|
||||
continue;
|
||||
|
||||
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;
|
||||
|
||||
if (v > 0 && v + 1 < best)
|
||||
best = v + 1;
|
||||
}
|
||||
|
||||
return best;
|
||||
} else {
|
||||
int best = -1;
|
||||
|
||||
if (!pos.checkers())
|
||||
end = generate<NON_EVASIONS>(pos, stack);
|
||||
else
|
||||
end = generate<EVASIONS>(pos, stack);
|
||||
|
||||
for (moves = stack; moves < end; ++moves) {
|
||||
int v;
|
||||
Move move = moves->move;
|
||||
|
||||
if (!pos.legal(move, ci.pinned))
|
||||
continue;
|
||||
|
||||
pos.do_move(move, st, pos.gives_check(move, ci));
|
||||
|
||||
if (st.rule50 == 0) {
|
||||
if (wdl == -2) v = -1;
|
||||
else {
|
||||
v = probe_ab(pos, WDLSoftWin, WDLHardWin, success);
|
||||
v = (v == 2) ? 0 : -101;
|
||||
}
|
||||
} else {
|
||||
v = -Tablebases::probe_dtz(pos, success) - 1;
|
||||
}
|
||||
|
||||
pos.undo_move(move);
|
||||
|
||||
if (*success == 0)
|
||||
return 0;
|
||||
|
||||
if (v < best)
|
||||
best = v;
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
}
|
||||
|
||||
// Probe the DTZ table for a particular position.
|
||||
// If *success != 0, the probe was successful.
|
||||
// The return value is from the point of view of the side to move:
|
||||
// n < -100 : loss, but draw under 50-move rule
|
||||
// -100 <= n < -1 : loss in n ply (assuming 50-move counter == 0)
|
||||
// 0 : draw
|
||||
// 1 < n <= 100 : win in n ply (assuming 50-move counter == 0)
|
||||
// 100 < n : win, but draw under 50-move rule
|
||||
//
|
||||
// The return value n can be off by 1: a return value -n can mean a loss
|
||||
// in n+1 ply and a return value +n can mean a win in n+1 ply. This
|
||||
// cannot happen for tables with positions exactly on the "edge" of
|
||||
// the 50-move rule.
|
||||
//
|
||||
// This implies that if dtz > 0 is returned, the position is certainly
|
||||
// a win if dtz + 50-move-counter <= 99. Care must be taken that the engine
|
||||
// picks moves that preserve dtz + 50-move-counter <= 99.
|
||||
//
|
||||
// If n = 100 immediately after a capture or pawn move, then the position
|
||||
// is also certainly a win, and during the whole phase until the next
|
||||
// capture or pawn move, the inequality to be preserved is
|
||||
// dtz + 50-movecounter <= 100.
|
||||
//
|
||||
// In short, if a move is available resulting in dtz + 50-move-counter <= 99,
|
||||
// then do not accept moves leading to dtz + 50-move-counter == 100.
|
||||
//
|
||||
int Tablebases::probe_dtz(Position& pos, int *success)
|
||||
{
|
||||
*success = 1;
|
||||
int v = probe_dtz_no_ep(pos, success);
|
||||
|
||||
if (pos.ep_square() == SQ_NONE)
|
||||
return v;
|
||||
|
||||
if (*success == 0)
|
||||
return 0;
|
||||
|
||||
// Now handle en passant.
|
||||
int v1 = -3;
|
||||
|
||||
ExtMove stack[MAX_MOVES];
|
||||
ExtMove *moves, *end;
|
||||
StateInfo st;
|
||||
|
||||
if (!pos.checkers())
|
||||
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))
|
||||
continue;
|
||||
|
||||
pos.do_move(capture, st, pos.gives_check(capture, ci));
|
||||
WDLScore v0 = -probe_ab(pos, WDLHardLoss, WDLHardWin, success);
|
||||
pos.undo_move(capture);
|
||||
|
||||
if (*success == 0)
|
||||
return 0;
|
||||
|
||||
if (v0 > v1) v1 = v0;
|
||||
}
|
||||
|
||||
if (v1 > -3) {
|
||||
v1 = wdl_to_dtz[v1 + 2];
|
||||
|
||||
if (v < -100) {
|
||||
if (v1 >= 0)
|
||||
v = v1;
|
||||
} else if (v < 0) {
|
||||
if (v1 >= 0 || v1 < -100)
|
||||
v = v1;
|
||||
} else if (v > 100) {
|
||||
if (v1 > 0)
|
||||
v = v1;
|
||||
} else if (v > 0) {
|
||||
if (v1 == 1)
|
||||
v = v1;
|
||||
} else if (v1 >= 0) {
|
||||
v = v1;
|
||||
} else {
|
||||
for (moves = stack; moves < end; ++moves) {
|
||||
Move move = moves->move;
|
||||
|
||||
if (type_of(move) == ENPASSANT) continue;
|
||||
|
||||
if (pos.legal(move, ci.pinned))
|
||||
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))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (moves == end)
|
||||
v = v1;
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
// Check whether there has been at least one repetition of positions
|
||||
// since the last capture or pawn move.
|
||||
static int has_repeated(StateInfo *st)
|
||||
|
@ -2182,14 +2184,14 @@ bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves, Value&
|
|||
|
||||
if (!v) {
|
||||
if (st.rule50 != 0) {
|
||||
v = -Tablebases::probe_dtz(pos, &success);
|
||||
v = -probe_dtz(pos, &success);
|
||||
|
||||
if (v > 0)
|
||||
++v;
|
||||
else if (v < 0)
|
||||
--v;
|
||||
} else {
|
||||
v = -Tablebases::probe_wdl(pos, &success);
|
||||
v = -probe_wdl(pos, &success);
|
||||
v = wdl_to_dtz[v + 2];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ extern int MaxCardinality;
|
|||
void init(const std::string& paths);
|
||||
void free();
|
||||
WDLScore probe_wdl(Position& pos, int* success);
|
||||
int probe_dtz(Position& pos, int* success);
|
||||
bool root_probe(Position& pos, Search::RootMoves& rootMoves, Value& score);
|
||||
bool root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, Value& score);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue