1
0
Fork 0
mirror of https://github.com/sockspls/badfish synced 2025-05-01 09:13:08 +00:00

Better document encoding

This commit is contained in:
Marco Costalba 2016-05-08 09:09:20 +02:00
parent 2a48e7a69c
commit 9c35466295
2 changed files with 50 additions and 34 deletions

View file

@ -15,6 +15,7 @@
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <type_traits>
#include "../bitboard.h" #include "../bitboard.h"
#include "../movegen.h" #include "../movegen.h"
@ -304,8 +305,6 @@ const uint8_t WDL_MAGIC[] = { 0x71, 0xE8, 0x23, 0x5D };
const uint8_t DTZ_MAGIC[] = { 0xD7, 0x66, 0x0C, 0xA5 }; const uint8_t DTZ_MAGIC[] = { 0xD7, 0x66, 0x0C, 0xA5 };
const int wdl_to_dtz[] = { -1, -101, 0, 101, 1 }; const int wdl_to_dtz[] = { -1, -101, 0, 101, 1 };
const int wdl_to_map[] = { 1, 3, 0, 2, 0 };
const uint8_t pa_flags[] = { 8, 0, 0, 0, 4 };
const Value WDL_to_value[] = { const Value WDL_to_value[] = {
-VALUE_MATE + MAX_PLY + 1, -VALUE_MATE + MAX_PLY + 1,
@ -503,10 +502,11 @@ WDLEntry::WDLEntry(const Position& pos, Key keys[])
has_pawns = pos.count<PAWN>(WHITE) + pos.count<PAWN>(BLACK); has_pawns = pos.count<PAWN>(WHITE) + pos.count<PAWN>(BLACK);
if (has_pawns) { if (has_pawns) {
// FIXME: What it means this one? // Set the leading color. In case both sides have pawns the leading color
bool c = ( !pos.count<PAWN>(BLACK) // is the side with less pawns because this leads to a better compression.
bool c = !pos.count<PAWN>(BLACK)
|| ( pos.count<PAWN>(WHITE) || ( pos.count<PAWN>(WHITE)
&& pos.count<PAWN>(BLACK) >= pos.count<PAWN>(WHITE))); && pos.count<PAWN>(BLACK) >= pos.count<PAWN>(WHITE));
pawn.pawnCount[0] = pos.count<PAWN>(c ? WHITE : BLACK); pawn.pawnCount[0] = pos.count<PAWN>(c ? WHITE : BLACK);
pawn.pawnCount[1] = pos.count<PAWN>(c ? BLACK : WHITE); pawn.pawnCount[1] = pos.count<PAWN>(c ? BLACK : WHITE);
@ -677,10 +677,10 @@ int decompress_pairs(PairsData* d, uint64_t idx)
} }
template<typename Entry> template<typename Entry>
bool check_flags(Entry*, File, int) { return true; } bool check_dtz_stm(Entry*, File, int) { return true; }
template<> template<>
bool check_flags(DTZEntry* entry, File f, int stm) { bool check_dtz_stm(DTZEntry* entry, File f, int stm) {
uint8_t flags = entry->has_pawns ? entry->pawn.file[f].flags uint8_t flags = entry->has_pawns ? entry->pawn.file[f].flags
: entry->piece.flags; : entry->piece.flags;
@ -688,11 +688,18 @@ bool check_flags(DTZEntry* entry, File f, int stm) {
return (flags & 1) == stm || (entry->symmetric && !entry->has_pawns); return (flags & 1) == stm || (entry->symmetric && !entry->has_pawns);
} }
// DTZ scores are sorted by frequency of occurrence and then assigned the
// values 0, 1, 2, 3, ... in order of decreasing frequency. This is done
// in each of the four ranges. The mapping information necessary to
// reconstruct the original values is stored in the TB file and used to
// initialise the map[] array during initialisation of the TB.
template<typename Entry> template<typename Entry>
int map_score(Entry*, File, int res, int) { return res; } int map_score(Entry*, File, int value, WDLScore) { return value - 2; }
template<> template<>
int map_score(DTZEntry* entry, File f, int res, int wdl) { int map_score(DTZEntry* entry, File f, int value, WDLScore wdl) {
const int WDLMap[] = { 1, 3, 0, 2, 0 };
uint8_t flags = entry->has_pawns ? entry->pawn.file[f].flags uint8_t flags = entry->has_pawns ? entry->pawn.file[f].flags
: entry->piece.flags; : entry->piece.flags;
@ -703,18 +710,24 @@ int map_score(DTZEntry* entry, File f, int res, int wdl) {
uint16_t* idx = entry->has_pawns ? entry->pawn.file[f].map_idx uint16_t* idx = entry->has_pawns ? entry->pawn.file[f].map_idx
: entry->piece.map_idx; : entry->piece.map_idx;
if (flags & 2) if (flags & 2)
res = map[idx[wdl_to_map[wdl + 2]] + res]; value = map[idx[WDLMap[wdl + 2]] + value];
if (!(flags & pa_flags[wdl + 2]) || (wdl & 1)) // DTZ tables store distance to zero in number of moves but
res *= 2; // under some conditions we want to return plies, so we have
// to multiply score by 2.
if ( (wdl == WDLWin && !(flags & 4))
|| (wdl == WDLLoss && !(flags & 8))
|| wdl == WDLCursedWin
|| wdl == WDLCursedLoss)
value *= 2;
return res; return value;
} }
int off_A1H8(Square sq) { return int(rank_of(sq)) - file_of(sq); } int off_A1H8(Square sq) { return int(rank_of(sq)) - file_of(sq); }
template<typename Entry> template<typename Entry>
uint64_t probe_table(const Position& pos, Entry* entry, int wdlScore = 0, int* success = nullptr) uint64_t probe_table(const Position& pos, Entry* entry, WDLScore wdl = WDLDraw, int* success = nullptr)
{ {
Square squares[TBPIECES]; Square squares[TBPIECES];
Piece pieces[TBPIECES]; Piece pieces[TBPIECES];
@ -776,8 +789,11 @@ uint64_t probe_table(const Position& pos, Entry* entry, int wdlScore = 0, int*
} else } else
precomp = item(entry->piece, stm, 0).precomp; precomp = item(entry->piece, stm, 0).precomp;
// Check for DTZ tables if look up is available // DTZ tables are one-sided, i.e. they store positions only for white to
if (success && !check_flags(entry, tbFile, stm)) { // move or only for black to move, so check for side to move to be stm,
// early exit otherwise.
if ( std::is_same<Entry, DTZEntry>::value
&& !check_dtz_stm(entry, tbFile, stm)) {
*success = -1; *success = -1;
return 0; return 0;
} }
@ -941,7 +957,7 @@ encode_remaining:
} }
// Now that we have the index, decompress the pair and get the score // Now that we have the index, decompress the pair and get the score
return map_score(entry, tbFile, decompress_pairs(precomp, idx), wdlScore); return map_score(entry, tbFile, decompress_pairs(precomp, idx), wdl);
} }
template<typename T> template<typename T>
@ -1250,10 +1266,10 @@ WDLScore probe_wdl_table(Position& pos, int* success)
assert(key == entry->key || !entry->symmetric); assert(key == entry->key || !entry->symmetric);
return WDLScore(probe_table(pos, entry) - 2); return (WDLScore)probe_table(pos, entry);
} }
int probe_dtz_table(const Position& pos, int wdl, int *success) int probe_dtz_table(const Position& pos, WDLScore wdl, int *success)
{ {
Key key = pos.material_key(); Key key = pos.material_key();
@ -1397,14 +1413,14 @@ int probe_dtz_no_ep(Position& pos, int *success)
{ {
int dtz; int dtz;
WDLScore wdl = probe_ab(pos, WDLHardLoss, WDLHardWin, success); WDLScore wdl = probe_ab(pos, WDLLoss, WDLWin, success);
if (*success == 0) return 0; if (*success == 0) return 0;
if (wdl == WDLDraw) return 0; if (wdl == WDLDraw) return 0;
if (*success == 2) if (*success == 2)
return wdl == WDLHardWin ? 1 : 101; return wdl == WDLWin ? 1 : 101;
ExtMove stack[MAX_MOVES]; ExtMove stack[MAX_MOVES];
ExtMove *moves, *end = nullptr; ExtMove *moves, *end = nullptr;
@ -1428,13 +1444,13 @@ int probe_dtz_no_ep(Position& pos, int *success)
continue; continue;
pos.do_move(move, st, pos.gives_check(move, ci)); pos.do_move(move, st, pos.gives_check(move, ci));
WDLScore v = -probe_ab(pos, WDLHardLoss, -wdl + WDLSoftWin, success); WDLScore v = -probe_ab(pos, WDLLoss, -wdl + WDLCursedWin, success);
pos.undo_move(move); pos.undo_move(move);
if (*success == 0) return 0; if (*success == 0) return 0;
if (v == wdl) if (v == wdl)
return v == WDLHardWin ? 1 : 101; return v == WDLWin ? 1 : 101;
} }
} }
@ -1488,7 +1504,7 @@ int probe_dtz_no_ep(Position& pos, int *success)
if (st.rule50 == 0) { if (st.rule50 == 0) {
if (wdl == -2) v = -1; if (wdl == -2) v = -1;
else { else {
v = probe_ab(pos, WDLSoftWin, WDLHardWin, success); v = probe_ab(pos, WDLCursedWin, WDLWin, success);
v = (v == 2) ? 0 : -101; v = (v == 2) ? 0 : -101;
} }
} else { } else {
@ -1567,7 +1583,7 @@ int probe_dtz(Position& pos, int *success)
continue; continue;
pos.do_move(capture, st, pos.gives_check(capture, ci)); pos.do_move(capture, st, pos.gives_check(capture, ci));
WDLScore v0 = -probe_ab(pos, WDLHardLoss, WDLHardWin, success); WDLScore v0 = -probe_ab(pos, WDLLoss, WDLWin, success);
pos.undo_move(capture); pos.undo_move(capture);
if (*success == 0) if (*success == 0)
@ -1699,7 +1715,7 @@ void Tablebases::init(const std::string& paths)
WDLScore Tablebases::probe_wdl(Position& pos, int *success) WDLScore Tablebases::probe_wdl(Position& pos, int *success)
{ {
*success = 1; *success = 1;
WDLScore v = probe_ab(pos, WDLHardLoss, WDLHardWin, success); WDLScore v = probe_ab(pos, WDLLoss, WDLWin, success);
// If en passant is not possible, we are done. // If en passant is not possible, we are done.
if (pos.ep_square() == SQ_NONE) if (pos.ep_square() == SQ_NONE)
@ -1730,7 +1746,7 @@ WDLScore Tablebases::probe_wdl(Position& pos, int *success)
continue; continue;
pos.do_move(capture, st, pos.gives_check(capture, ci)); pos.do_move(capture, st, pos.gives_check(capture, ci));
WDLScore v0 = -probe_ab(pos, WDLHardLoss, WDLHardWin, success); WDLScore v0 = -probe_ab(pos, WDLLoss, WDLWin, success);
pos.undo_move(capture); pos.undo_move(capture);
if (*success == 0) if (*success == 0)
@ -1949,7 +1965,7 @@ bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, Val
StateInfo st; StateInfo st;
CheckInfo ci(pos); CheckInfo ci(pos);
int best = WDLHardLoss; int best = WDLLoss;
// Probe each move // Probe each move
for (size_t i = 0; i < rootMoves.size(); ++i) { for (size_t i = 0; i < rootMoves.size(); ++i) {

View file

@ -6,11 +6,11 @@
namespace Tablebases { namespace Tablebases {
enum WDLScore { enum WDLScore {
WDLHardLoss = -2, // Loss WDLLoss = -2, // Loss
WDLSoftLoss = -1, // Loss, but draw under 50-move rule WDLCursedLoss = -1, // Loss, but draw under 50-move rule
WDLDraw = 0, // Draw WDLDraw = 0, // Draw
WDLSoftWin = 1, // Win, but draw under 50-move rule WDLCursedWin = 1, // Win, but draw under 50-move rule
WDLHardWin = 2, // Win WDLWin = 2, // Win
}; };
extern int MaxCardinality; extern int MaxCardinality;