mirror of
https://github.com/sockspls/badfish
synced 2025-04-30 08:43:09 +00:00
Use SF Position to calculate material key
Don't reinvent the wheel. Also clarify that init_tb it is used to populate TBHash: rename it in proper way.
This commit is contained in:
parent
024fec7a2b
commit
63b39c5bff
4 changed files with 78 additions and 95 deletions
|
@ -83,26 +83,6 @@ namespace {
|
|||
return sq;
|
||||
}
|
||||
|
||||
// Get the material key of Position out of the given endgame key code
|
||||
// like "KBPKN". The trick here is to first forge an ad-hoc FEN string
|
||||
// and then let a Position object do the work for us.
|
||||
Key key(const string& code, Color c) {
|
||||
|
||||
assert(code.length() > 0 && code.length() < 8);
|
||||
assert(code[0] == 'K');
|
||||
|
||||
string sides[] = { code.substr(code.find('K', 1)), // Weak
|
||||
code.substr(0, code.find('K', 1)) }; // Strong
|
||||
|
||||
std::transform(sides[c].begin(), sides[c].end(), sides[c].begin(), tolower);
|
||||
|
||||
string fen = sides[0] + char(8 - sides[0].length() + '0') + "/8/8/8/8/8/8/"
|
||||
+ sides[1] + char(8 - sides[1].length() + '0') + " w - - 0 10";
|
||||
|
||||
StateInfo st;
|
||||
return Position().set(fen, false, &st, nullptr).material_key();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
@ -132,8 +112,9 @@ Endgames::Endgames() {
|
|||
|
||||
template<EndgameType E, typename T>
|
||||
void Endgames::add(const string& code) {
|
||||
map<T>()[key(code, WHITE)] = std::unique_ptr<EndgameBase<T>>(new Endgame<E>(WHITE));
|
||||
map<T>()[key(code, BLACK)] = std::unique_ptr<EndgameBase<T>>(new Endgame<E>(BLACK));
|
||||
StateInfo st;
|
||||
map<T>()[Position().set(code, WHITE, &st).material_key()] = std::unique_ptr<EndgameBase<T>>(new Endgame<E>(WHITE));
|
||||
map<T>()[Position().set(code, BLACK, &st).material_key()] = std::unique_ptr<EndgameBase<T>>(new Endgame<E>(BLACK));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -357,6 +357,28 @@ void Position::set_state(StateInfo* si) const {
|
|||
}
|
||||
|
||||
|
||||
/// Position::set() is an overload to initialize the position object with
|
||||
/// the given endgame code string like "KBPKN". It is manily an helper to
|
||||
/// get the material key out of an endgame code. Position is not playable,
|
||||
/// indeed is even not guaranteed to be legal.
|
||||
|
||||
Position& Position::set(const string& code, Color c, StateInfo* si) {
|
||||
|
||||
assert(code.length() > 0 && code.length() < 8);
|
||||
assert(code[0] == 'K');
|
||||
|
||||
string sides[] = { code.substr(code.find('K', 1)), // Weak
|
||||
code.substr(0, code.find('K', 1)) }; // Strong
|
||||
|
||||
std::transform(sides[c].begin(), sides[c].end(), sides[c].begin(), tolower);
|
||||
|
||||
string fenStr = sides[0] + char(8 - sides[0].length() + '0') + "/8/8/8/8/8/8/"
|
||||
+ sides[1] + char(8 - sides[1].length() + '0') + " w - - 0 10";
|
||||
|
||||
return set(fenStr, false, si, nullptr);
|
||||
}
|
||||
|
||||
|
||||
/// Position::fen() returns a FEN representation of the position. In case of
|
||||
/// Chess960 the Shredder-FEN notation is used. This is mainly a debugging function.
|
||||
|
||||
|
|
|
@ -98,6 +98,7 @@ public:
|
|||
|
||||
// FEN string input/output
|
||||
Position& set(const std::string& fenStr, bool isChess960, StateInfo* si, Thread* th);
|
||||
Position& set(const std::string& code, Color c, StateInfo* si);
|
||||
const std::string fen() const;
|
||||
|
||||
// Position representation
|
||||
|
|
|
@ -388,6 +388,20 @@ class HashTable {
|
|||
|
||||
Entry table[1 << TBHASHBITS][HSHMAX];
|
||||
|
||||
void insert(Key key, TBEntry* ptr) {
|
||||
Entry* entry = table[key >> (64 - TBHASHBITS)];
|
||||
|
||||
for (int i = 0; i < HSHMAX; ++i, ++entry)
|
||||
if (!entry->ptr || entry->key == key) {
|
||||
entry->key = key;
|
||||
entry->ptr = ptr;
|
||||
return;
|
||||
}
|
||||
|
||||
std::cerr << "HSHMAX too low!" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
public:
|
||||
TBEntry* operator[](Key key) {
|
||||
Entry* entry = table[key >> (64 - TBHASHBITS)];
|
||||
|
@ -399,21 +413,8 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void insert(TBEntry* ptr, Key key) {
|
||||
Entry* entry = table[key >> (64 - TBHASHBITS)];
|
||||
|
||||
for (int i = 0; i < HSHMAX; ++i, ++entry)
|
||||
if (!entry->ptr) {
|
||||
entry->key = key;
|
||||
entry->ptr = ptr;
|
||||
return;
|
||||
}
|
||||
|
||||
std::cerr << "HSHMAX too low!" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void clear() { std::memset(table, 0, sizeof(table)); }
|
||||
void insert(const std::vector<PieceType>& pieces);
|
||||
};
|
||||
|
||||
HashTable TBHash;
|
||||
|
@ -519,22 +520,6 @@ Key get_key(Position& pos, bool mirror)
|
|||
return key;
|
||||
}
|
||||
|
||||
// Produce a 64-bit material key corresponding to the material combination
|
||||
// defined by pcs[16], where pcs[1], ..., pcs[6] is the number of white
|
||||
// pawns, ..., kings and pcs[9], ..., pcs[14] is the number of black
|
||||
// pawns, ..., kings.
|
||||
Key get_key(uint8_t* pcs, bool mirror)
|
||||
{
|
||||
Key key = 0;
|
||||
|
||||
for (Color c = WHITE; c <= BLACK; ++c)
|
||||
for (PieceType pt = PAWN; pt <= KING; ++pt)
|
||||
for (int cnt = 0; cnt < pcs[8 * (c ^ mirror) + pt]; ++cnt)
|
||||
key ^= Zobrist::psq[c][pt][cnt];
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
// Given a position with 6 or fewer pieces, produce a text string
|
||||
// of the form KQPvKRP, where "KQP" represents the white pieces if
|
||||
// mirror == false and the black pieces if mirror == true.
|
||||
|
@ -582,39 +567,32 @@ void free_dtz_entry(TBEntry* entry)
|
|||
free(entry);
|
||||
}
|
||||
|
||||
void init_tb(const std::vector<PieceType>& pieces)
|
||||
void HashTable::insert(const std::vector<PieceType>& pieces)
|
||||
{
|
||||
TBEntry* entry;
|
||||
std::string fname;
|
||||
Color c = BLACK;
|
||||
uint8_t pcs[PIECE_NB] = {0};
|
||||
int num = 0;
|
||||
StateInfo st;
|
||||
Position pos;
|
||||
std::string code;
|
||||
|
||||
for (PieceType pt : pieces) {
|
||||
if (pt == KING) {
|
||||
c = ~c;
|
||||
for (PieceType pt : pieces)
|
||||
code += PieceChar[pt];
|
||||
|
||||
if (!fname.empty())
|
||||
fname += 'v';
|
||||
}
|
||||
|
||||
++pcs[make_piece(c, pt)];
|
||||
++num;
|
||||
fname += PieceChar[pt];
|
||||
}
|
||||
|
||||
TBFile f(fname + ".rtbw");
|
||||
int bk = code.find('K', 1); // Black king
|
||||
TBFile f(code.substr(0, bk) + 'v' + code.substr(bk) + ".rtbw");
|
||||
|
||||
if (!f.is_open())
|
||||
return;
|
||||
|
||||
f.close();
|
||||
|
||||
pos.set(code, WHITE, &st);
|
||||
|
||||
int num = pos.count<ALL_PIECES>(WHITE) + pos.count<ALL_PIECES>(BLACK);
|
||||
bool hasPawns = pos.count<PAWN>(WHITE) + pos.count<PAWN>(BLACK);
|
||||
|
||||
if (num > Tablebases::MaxCardinality)
|
||||
Tablebases::MaxCardinality = num;
|
||||
|
||||
bool hasPawns = pcs[W_PAWN] + pcs[B_PAWN];
|
||||
|
||||
if (hasPawns) {
|
||||
if (TBnum_pawn == TBMAX_PAWN) {
|
||||
std::cerr << "TBMAX_PAWN limit too low!" << std::endl;
|
||||
|
@ -622,14 +600,16 @@ void init_tb(const std::vector<PieceType>& pieces)
|
|||
}
|
||||
|
||||
TBEntry_pawn* ptr = &TB_pawn[TBnum_pawn++];
|
||||
ptr->pawns[0] = pcs[W_PAWN];
|
||||
ptr->pawns[1] = pcs[B_PAWN];
|
||||
|
||||
// FIXME: What it means this one?
|
||||
if ( pcs[B_PAWN] > 0
|
||||
&& (pcs[W_PAWN] == 0 || pcs[B_PAWN] < pcs[W_PAWN])) {
|
||||
ptr->pawns[0] = pcs[B_PAWN];
|
||||
ptr->pawns[1] = pcs[W_PAWN];
|
||||
if ( !pos.count<PAWN>(BLACK)
|
||||
|| ( pos.count<PAWN>(WHITE)
|
||||
&& pos.count<PAWN>(BLACK) >= pos.count<PAWN>(WHITE))) {
|
||||
ptr->pawns[0] = pos.count<PAWN>(WHITE);
|
||||
ptr->pawns[1] = pos.count<PAWN>(BLACK);
|
||||
} else {
|
||||
ptr->pawns[0] = pos.count<PAWN>(BLACK);
|
||||
ptr->pawns[1] = pos.count<PAWN>(WHITE);
|
||||
}
|
||||
|
||||
entry = (TBEntry*)ptr;
|
||||
|
@ -642,23 +622,24 @@ void init_tb(const std::vector<PieceType>& pieces)
|
|||
TBEntry_piece* ptr = &TB_piece[TBnum_piece++];
|
||||
int uniquePieces = 0;
|
||||
|
||||
for (auto n : pcs)
|
||||
if (n == 1)
|
||||
++uniquePieces;
|
||||
for (PieceType pt = PAWN; pt <= KING; ++pt)
|
||||
uniquePieces += (popcount(pos.pieces(WHITE, pt)) == 1)
|
||||
+ (popcount(pos.pieces(BLACK, pt)) == 1);
|
||||
|
||||
if (uniquePieces >= 3)
|
||||
ptr->enc_type = 0;
|
||||
else {
|
||||
// W_KING and B_KING are the only unique pieces
|
||||
assert(uniquePieces == 2);
|
||||
|
||||
ptr->enc_type = 2;
|
||||
}
|
||||
|
||||
entry = (TBEntry*)ptr;
|
||||
}
|
||||
|
||||
Key key1 = get_key(pcs, 0);
|
||||
Key key2 = get_key(pcs, 1);
|
||||
Key key1 = pos.material_key();
|
||||
Key key2 = pos.set(code, BLACK, &st).material_key();
|
||||
|
||||
entry->key = key1;
|
||||
entry->ready = 0;
|
||||
|
@ -666,10 +647,8 @@ void init_tb(const std::vector<PieceType>& pieces)
|
|||
entry->symmetric = (key1 == key2);
|
||||
entry->has_pawns = hasPawns;
|
||||
|
||||
TBHash.insert(entry, key1);
|
||||
|
||||
if (key2 != key1) // Asymmetric distribution
|
||||
TBHash.insert(entry, key2);
|
||||
insert(key1, entry);
|
||||
insert(key2, entry);
|
||||
}
|
||||
|
||||
uint64_t encode_piece(TBEntry_piece* ptr, uint8_t* norm, int* pos, int* factor)
|
||||
|
@ -1822,28 +1801,28 @@ void Tablebases::init(const std::string& paths)
|
|||
}
|
||||
|
||||
for (PieceType p1 = PAWN; p1 < KING; ++p1) {
|
||||
init_tb({KING, p1, KING});
|
||||
TBHash.insert({KING, p1, KING});
|
||||
|
||||
for (PieceType p2 = PAWN; p2 <= p1; ++p2) {
|
||||
init_tb({KING, p1, p2, KING});
|
||||
init_tb({KING, p1, KING, p2});
|
||||
TBHash.insert({KING, p1, p2, KING});
|
||||
TBHash.insert({KING, p1, KING, p2});
|
||||
|
||||
for (PieceType p3 = PAWN; p3 < KING; ++p3)
|
||||
init_tb({KING, p1, p2, KING, p3});
|
||||
TBHash.insert({KING, p1, p2, KING, p3});
|
||||
|
||||
for (PieceType p3 = PAWN; p3 <= p2; ++p3) {
|
||||
init_tb({KING, p1, p2, p3, KING});
|
||||
TBHash.insert({KING, p1, p2, p3, KING});
|
||||
|
||||
for (PieceType p4 = PAWN; p4 <= p3; ++p4)
|
||||
init_tb({KING, p1, p2, p3, p4, KING});
|
||||
TBHash.insert({KING, p1, p2, p3, p4, KING});
|
||||
|
||||
for (PieceType p4 = PAWN; p4 < KING; ++p4)
|
||||
init_tb({KING, p1, p2, p3, KING, p4});
|
||||
TBHash.insert({KING, p1, p2, p3, KING, p4});
|
||||
}
|
||||
|
||||
for (PieceType p3 = PAWN; p3 <= p1; ++p3)
|
||||
for (PieceType p4 = PAWN; p4 <= (p1 == p3 ? p2 : p3); ++p4)
|
||||
init_tb({KING, p1, p2, KING, p3, p4});
|
||||
TBHash.insert({KING, p1, p2, KING, p3, p4});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue