1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-04-30 16:53:09 +00:00

Introduce WDLScore

Start to add some type safety above naked int

Improve code self-documenting readibility as well.
This commit is contained in:
Marco Costalba 2016-04-22 09:18:48 +02:00
parent 54d0cf1f89
commit 5414eaba35
2 changed files with 55 additions and 42 deletions

View file

@ -48,6 +48,8 @@
#define DTZSUFFIX ".rtbz"
#define TBPIECES 6
using namespace Tablebases;
int Tablebases::MaxCardinality = 0;
namespace Zobrist {
@ -58,6 +60,9 @@ namespace {
typedef uint64_t base_t;
inline WDLScore operator-(WDLScore d) { return WDLScore(-int(d)); }
inline WDLScore operator+(WDLScore d1, WDLScore d2) { return WDLScore(int(d1) + int(d2)); }
struct PairsData {
char *indextable;
uint16_t *sizetable;
@ -1482,17 +1487,17 @@ std::string prt_str(Position& pos, bool mirror)
return s;
}
int probe_wdl_table(Position& pos, int* success)
WDLScore probe_wdl_table(Position& pos, int* success)
{
Key key = pos.material_key();
if (pos.count<ALL_PIECES>(WHITE) + pos.count<ALL_PIECES>(BLACK) == 2)
return 0; // KvK
return WDLDraw; // KvK
TBEntry* ptr = TBHash[key];
if (!ptr) {
*success = 0;
return 0;
return WDLDraw;
}
// Init table at first access attempt
@ -1502,7 +1507,7 @@ int probe_wdl_table(Position& pos, int* success)
if (!init_table_wdl(ptr, prt_str(pos, ptr->key != key))) {
// Was ptr2->key = 0ULL; Just leave !ptr->ready condition
*success = 0;
return 0;
return WDLDraw;
}
ptr->ready = 1;
}
@ -1544,7 +1549,7 @@ int probe_wdl_table(Position& pos, int* success)
}
uint64_t idx = encode_piece(entry, entry->norm[bside], squares, entry->factor[bside]);
return decompress_pairs(entry->precomp[bside], idx) - 2;
return WDLScore(decompress_pairs(entry->precomp[bside], idx) - 2);
} else {
TBEntry_pawn* entry = (TBEntry_pawn*)ptr;
Piece pc = Piece(entry->file[0].pieces[0][0] ^ cmirror);
@ -1565,7 +1570,7 @@ int probe_wdl_table(Position& pos, int* success)
}
uint64_t idx = encode_pawn(entry, entry->file[f].norm[bside], squares, entry->file[f].factor[bside]);
return decompress_pairs(entry->file[f].precomp[bside], idx) - 2;
return WDLScore(decompress_pairs(entry->file[f].precomp[bside], idx) - 2);
}
}
@ -1719,9 +1724,9 @@ ExtMove *add_underprom_caps(Position& pos, ExtMove *stack, ExtMove *end)
return extra;
}
int probe_ab(Position& pos, int alpha, int beta, int *success)
WDLScore probe_ab(Position& pos, WDLScore alpha, WDLScore beta, int *success)
{
int v;
WDLScore value;
ExtMove stack[64];
ExtMove *moves, *end;
StateInfo st;
@ -1740,38 +1745,39 @@ int probe_ab(Position& pos, int alpha, int beta, int *success)
for (moves = stack; moves < end; ++moves) {
Move capture = moves->move;
if (!pos.capture(capture) || type_of(capture) == ENPASSANT
|| !pos.legal(capture, ci.pinned))
if ( !pos.capture(capture)
|| type_of(capture) == ENPASSANT
|| !pos.legal(capture, ci.pinned))
continue;
pos.do_move(capture, st, pos.gives_check(capture, ci));
v = -probe_ab(pos, -beta, -alpha, success);
value = -probe_ab(pos, -beta, -alpha, success);
pos.undo_move(capture);
if (*success == 0)
return 0;
return WDLDraw;
if (v > alpha) {
if (v >= beta) {
if (value > alpha) {
if (value >= beta) {
*success = 2;
return v;
return value;
}
alpha = v;
alpha = value;
}
}
v = probe_wdl_table(pos, success);
value = probe_wdl_table(pos, success);
if (*success == 0)
return 0;
return WDLDraw;
if (alpha >= v) {
if (alpha >= value) {
*success = 1 + (alpha > 0);
return alpha;
} else {
*success = 1;
return v;
return value;
}
}
@ -1861,22 +1867,20 @@ void Tablebases::init(const std::string& paths)
// 0 : draw
// 1 : win, but draw under 50-move rule
// 2 : win
int Tablebases::probe_wdl(Position& pos, int *success)
WDLScore Tablebases::probe_wdl(Position& pos, int *success)
{
int v;
*success = 1;
v = probe_ab(pos, -2, 2, success);
WDLScore v = probe_ab(pos, WDLHardLoss, WDLHardWin, success);
// If en passant is not possible, we are done.
if (pos.ep_square() == SQ_NONE)
return v;
if (*success == 0)
return 0;
return WDLDraw;
// Now handle en passant.
int v1 = -3;
WDLScore v1 = WDLScore(-3); // FIXME use a proper enum value here
// Generate (at least) all legal en passant captures.
ExtMove stack[MAX_MOVES];
ExtMove *moves, *end;
@ -1897,11 +1901,11 @@ int Tablebases::probe_wdl(Position& pos, int *success)
continue;
pos.do_move(capture, st, pos.gives_check(capture, ci));
int v0 = -probe_ab(pos, -2, 2, success);
WDLScore v0 = -probe_ab(pos, WDLHardLoss, WDLHardWin, success);
pos.undo_move(capture);
if (*success == 0)
return 0;
return WDLDraw;
if (v0 > v1) v1 = v0;
}
@ -1942,16 +1946,16 @@ int Tablebases::probe_wdl(Position& pos, int *success)
// This routine treats a position with en passant captures as one without.
static int probe_dtz_no_ep(Position& pos, int *success)
{
int wdl, dtz;
int dtz;
wdl = probe_ab(pos, -2, 2, success);
WDLScore wdl = probe_ab(pos, WDLHardLoss, WDLHardWin, success);
if (*success == 0) return 0;
if (wdl == 0) return 0;
if (wdl == WDLDraw) return 0;
if (*success == 2)
return wdl == 2 ? 1 : 101;
return wdl == WDLHardWin ? 1 : 101;
ExtMove stack[MAX_MOVES];
ExtMove *moves, *end = NULL;
@ -1969,18 +1973,19 @@ 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))
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));
int v = -probe_ab(pos, -2, -wdl + 1, success);
WDLScore v = -probe_ab(pos, WDLHardLoss, -wdl + WDLSoftWin, success);
pos.undo_move(move);
if (*success == 0) return 0;
if (v == wdl)
return v == 2 ? 1 : 101;
return v == WDLHardWin ? 1 : 101;
}
}
@ -2034,7 +2039,7 @@ static int probe_dtz_no_ep(Position& pos, int *success)
if (st.rule50 == 0) {
if (wdl == -2) v = -1;
else {
v = probe_ab(pos, 1, 2, success);
v = probe_ab(pos, WDLSoftWin, WDLHardWin, success);
v = (v == 2) ? 0 : -101;
}
} else {
@ -2117,7 +2122,7 @@ int Tablebases::probe_dtz(Position& pos, int *success)
continue;
pos.do_move(capture, st, pos.gives_check(capture, ci));
int v0 = -probe_ab(pos, -2, 2, success);
WDLScore v0 = -probe_ab(pos, WDLHardLoss, WDLHardWin, success);
pos.undo_move(capture);
if (*success == 0)
@ -2340,7 +2345,7 @@ bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, Val
{
int success;
int wdl = Tablebases::probe_wdl(pos, &success);
WDLScore wdl = Tablebases::probe_wdl(pos, &success);
if (!success)
return false;
@ -2350,13 +2355,13 @@ bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, Val
StateInfo st;
CheckInfo ci(pos);
int best = -2;
int best = WDLHardLoss;
// Probe each move
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);
WDLScore v = -Tablebases::probe_wdl(pos, &success);
pos.undo_move(move);
if (!success)

View file

@ -5,10 +5,18 @@
namespace Tablebases {
enum WDLScore {
WDLHardLoss = -2, // Loss
WDLSoftLoss = -1, // Loss, but draw under 50-move rule
WDLDraw = 0, // Draw
WDLSoftWin = 1, // Win, but draw under 50-move rule
WDLHardWin = 2, // Win
};
extern int MaxCardinality;
void init(const std::string& paths);
int probe_wdl(Position& pos, int* success);
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);