1
0
Fork 0
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:
Marco Costalba 2016-04-24 12:40:29 +02:00
parent 7aeef7285f
commit 39e4398133
2 changed files with 236 additions and 235 deletions

View file

@ -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];
}
}

View file

@ -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);