mirror of
https://github.com/sockspls/badfish
synced 2025-05-01 01:03:09 +00:00
Complete work in do_probe_table()
This commit is contained in:
parent
c568078c16
commit
f9d894a675
1 changed files with 55 additions and 54 deletions
|
@ -616,9 +616,9 @@ int decompress_pairs(PairsData* d, uint64_t idx)
|
||||||
return d->btree[sym].get<LR::Value>();
|
return d->btree[sym].get<LR::Value>();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_dtz_stm(WDLEntry*, File, int) { return true; }
|
bool check_dtz_stm(WDLEntry*, int, File) { return true; }
|
||||||
|
|
||||||
bool check_dtz_stm(DTZEntry* entry, File f, int stm)
|
bool check_dtz_stm(DTZEntry* entry, int stm, File f)
|
||||||
{
|
{
|
||||||
int flags = entry->hasPawns ? entry->pawnTable.file[f].precomp->flags
|
int flags = entry->hasPawns ? entry->pawnTable.file[f].precomp->flags
|
||||||
: entry->pieceTable.precomp->flags;
|
: entry->pieceTable.precomp->flags;
|
||||||
|
@ -674,7 +674,7 @@ T do_probe_table(const Position& pos, Entry* entry, WDLScore wdl, ProbeState* r
|
||||||
Piece pieces[TBPIECES];
|
Piece pieces[TBPIECES];
|
||||||
uint64_t idx;
|
uint64_t idx;
|
||||||
int next = 0, size = 0, leadPawnsCnt = 0;
|
int next = 0, size = 0, leadPawnsCnt = 0;
|
||||||
PairsData* precomp;
|
PairsData* d;
|
||||||
Bitboard b, leadPawns = 0;
|
Bitboard b, leadPawns = 0;
|
||||||
File tbFile = FILE_A;
|
File tbFile = FILE_A;
|
||||||
|
|
||||||
|
@ -717,14 +717,14 @@ T do_probe_table(const Position& pos, Entry* entry, WDLScore wdl, ProbeState* r
|
||||||
if (tbFile > FILE_D)
|
if (tbFile > FILE_D)
|
||||||
tbFile = file_of(squares[0] ^ 7); // Horizontal flip: SQ_H1 -> SQ_A1
|
tbFile = file_of(squares[0] ^ 7); // Horizontal flip: SQ_H1 -> SQ_A1
|
||||||
|
|
||||||
precomp = item(entry->pawnTable , stm, tbFile).precomp;
|
d = item(entry->pawnTable , stm, tbFile).precomp;
|
||||||
} else
|
} else
|
||||||
precomp = item(entry->pieceTable, stm, tbFile).precomp;
|
d = item(entry->pieceTable, stm, tbFile).precomp;
|
||||||
|
|
||||||
// DTZ tables are one-sided, i.e. they store positions only for white to
|
// DTZ tables are one-sided, i.e. they store positions only for white to
|
||||||
// move or only for black to move, so check for side to move to be stm,
|
// move or only for black to move, so check for side to move to be stm,
|
||||||
// early exit otherwise.
|
// early exit otherwise.
|
||||||
if (!IsWDL && !check_dtz_stm(entry, tbFile, stm))
|
if (!IsWDL && !check_dtz_stm(entry, stm, tbFile))
|
||||||
return *result = CHANGE_STM, T();
|
return *result = CHANGE_STM, T();
|
||||||
|
|
||||||
// Now we are ready to get all the position pieces (but the lead pawns) and
|
// Now we are ready to get all the position pieces (but the lead pawns) and
|
||||||
|
@ -737,10 +737,10 @@ T do_probe_table(const Position& pos, Entry* entry, WDLScore wdl, ProbeState* r
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then we reorder the pieces to have the same sequence as the one stored
|
// Then we reorder the pieces to have the same sequence as the one stored
|
||||||
// in precomp->pieces[i]. The sequence ensures the best compression.
|
// in precomp->pieces[i]: the sequence that ensures the best compression.
|
||||||
for (int i = leadPawnsCnt; i < size; ++i)
|
for (int i = leadPawnsCnt; i < size; ++i)
|
||||||
for (int j = i; j < size; ++j)
|
for (int j = i; j < size; ++j)
|
||||||
if (precomp->pieces[i] == pieces[j])
|
if (d->pieces[i] == pieces[j])
|
||||||
{
|
{
|
||||||
std::swap(pieces[i], pieces[j]);
|
std::swap(pieces[i], pieces[j]);
|
||||||
std::swap(squares[i], squares[j]);
|
std::swap(squares[i], squares[j]);
|
||||||
|
@ -748,8 +748,7 @@ T do_probe_table(const Position& pos, Entry* entry, WDLScore wdl, ProbeState* r
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we map again the squares so that the square of the lead piece is in
|
// Now we map again the squares so that the square of the lead piece is in
|
||||||
// the triangle A1-D1-D4. We take care that the condition on the diagonal
|
// the triangle A1-D1-D4.
|
||||||
// flip is checked after horizontal and vertical flips are already done.
|
|
||||||
if (file_of(squares[0]) > FILE_D)
|
if (file_of(squares[0]) > FILE_D)
|
||||||
for (int i = 0; i < size; ++i)
|
for (int i = 0; i < size; ++i)
|
||||||
squares[i] ^= 7; // Horizontal flip: SQ_H1 -> SQ_A1
|
squares[i] ^= 7; // Horizontal flip: SQ_H1 -> SQ_A1
|
||||||
|
@ -768,28 +767,31 @@ T do_probe_table(const Position& pos, Entry* entry, WDLScore wdl, ProbeState* r
|
||||||
goto encode_remaining; // With pawns we have finished special treatments
|
goto encode_remaining; // With pawns we have finished special treatments
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In positions withouth pawns, we further flip the squares to ensure leading
|
||||||
|
// piece is below RANK_5.
|
||||||
if (rank_of(squares[0]) > RANK_4)
|
if (rank_of(squares[0]) > RANK_4)
|
||||||
for (int i = 0; i < size; ++i)
|
for (int i = 0; i < size; ++i)
|
||||||
squares[i] ^= 070; // Vertical flip: SQ_A8 -> SQ_A1
|
squares[i] ^= 070; // Vertical flip: SQ_A8 -> SQ_A1
|
||||||
|
|
||||||
// Look for the first piece not on the A1-D4 diagonal and ensure it is
|
// Look for the first piece of the leading group not on the A1-D4 diagonal
|
||||||
// mapped below the diagonal.
|
// and ensure it is mapped below the diagonal.
|
||||||
for (int i = 0; i < size; ++i) {
|
for (int i = 0; i < d->groupLen[0]; ++i) {
|
||||||
if (!off_A1H8(squares[i]))
|
if (!off_A1H8(squares[i]))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (off_A1H8(squares[i]) > 0 && i < (entry->hasUniquePieces ? 3 : 2))
|
if (off_A1H8(squares[i]) > 0) // A1-H8 diagonal flip: SQ_A3 -> SQ_C3
|
||||||
for (int j = i; j < size; ++j) // A1-H8 diagonal flip: SQ_A3 -> SQ_C3
|
for (int j = i; j < size; ++j)
|
||||||
squares[j] = Square(((squares[j] >> 3) | (squares[j] << 3)) & 63);
|
squares[j] = Square(((squares[j] >> 3) | (squares[j] << 3)) & 63);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The encoding function maps a position to its index into the table.
|
// Encode the leading group.
|
||||||
|
//
|
||||||
// Suppose we have KRvK. Let's say the pieces are on square numbers wK, wR
|
// Suppose we have KRvK. Let's say the pieces are on square numbers wK, wR
|
||||||
// and bK (each 0...63). The simplest way to map this position to an index
|
// and bK (each 0...63). The simplest way to map this position to an index
|
||||||
// is like this:
|
// is like this:
|
||||||
//
|
//
|
||||||
// index = wK * 64*64 + wR * 64 + bK;
|
// index = wK * 64 * 64 + wR * 64 + bK;
|
||||||
//
|
//
|
||||||
// But this way the TB is going to have 64*64*64 = 262144 positions, with
|
// But this way the TB is going to have 64*64*64 = 262144 positions, with
|
||||||
// lots of positions being equivalent (because they are mirrors of each
|
// lots of positions being equivalent (because they are mirrors of each
|
||||||
|
@ -798,15 +800,16 @@ T do_probe_table(const Position& pos, Entry* entry, WDLScore wdl, ProbeState* r
|
||||||
// Usually the first step is to take the wK and bK together. There are just
|
// Usually the first step is to take the wK and bK together. There are just
|
||||||
// 462 ways legal and not-mirrored ways to place the wK and bK on the board.
|
// 462 ways legal and not-mirrored ways to place the wK and bK on the board.
|
||||||
// Once we have placed the wK and bK, there are 62 squares left for the wR
|
// Once we have placed the wK and bK, there are 62 squares left for the wR
|
||||||
// Mapping its square from 0..63 to 0..61 can be done like:
|
// Mapping its square from 0..63 to available squares 0..61 can be done like:
|
||||||
//
|
//
|
||||||
// wR -= (wR > wK) + (wR > bK);
|
// wR -= (wR > wK) + (wR > bK);
|
||||||
//
|
//
|
||||||
// In words: if wR "comes later" than wK, we deduct 1, and the same if wR
|
// In words: if wR "comes later" than wK, we deduct 1, and the same if wR
|
||||||
// "comes later" than bK. In case of two same pieces like KRRvK we want to
|
// "comes later" than bK. In case of two same pieces like KRRvK we want to
|
||||||
// place the two Rs "together". If we have 62 squares left, we can place two
|
// place the two Rs "together". If we have 62 squares left, we can place two
|
||||||
// Rs "together" in 62*61/2 ways.
|
// Rs "together" in 62 * 61 / 2 ways (we divide by 2 because rooks can be
|
||||||
|
// swapped and still get the same position.)
|
||||||
|
//
|
||||||
// In case we have at least 3 unique pieces (inlcuded kings) we encode them
|
// In case we have at least 3 unique pieces (inlcuded kings) we encode them
|
||||||
// together.
|
// together.
|
||||||
if (entry->hasUniquePieces) {
|
if (entry->hasUniquePieces) {
|
||||||
|
@ -814,22 +817,23 @@ T do_probe_table(const Position& pos, Entry* entry, WDLScore wdl, ProbeState* r
|
||||||
int adjust1 = squares[1] > squares[0];
|
int adjust1 = squares[1] > squares[0];
|
||||||
int adjust2 = (squares[2] > squares[0]) + (squares[2] > squares[1]);
|
int adjust2 = (squares[2] > squares[0]) + (squares[2] > squares[1]);
|
||||||
|
|
||||||
// MapA1D1D4[] maps the b1-d1-d3 triangle to 0...5. There are 63 squares
|
// First piece is below a1-h8 diagonal. MapA1D1D4[] maps the b1-d1-d3
|
||||||
// for second piece and and 62 (mapped to 0...61) for the third.
|
// triangle to 0...5. There are 63 squares for second piece and and 62
|
||||||
|
// (mapped to 0...61) for the third.
|
||||||
if (off_A1H8(squares[0]))
|
if (off_A1H8(squares[0]))
|
||||||
idx = MapA1D1D4[squares[0]] * 63 * 62
|
idx = ( MapA1D1D4[squares[0]] * 63
|
||||||
+ (squares[1] - adjust1) * 62
|
+ (squares[1] - adjust1)) * 62
|
||||||
+ squares[2] - adjust2;
|
+ squares[2] - adjust2;
|
||||||
|
|
||||||
// First piece is on diagonal: map to 6, rank_of() maps a1-d4 diagonal
|
// First piece is on a1-h8 diagonal, second below: map this occurence to
|
||||||
// to 0...3 and MapB1H1H7[] maps the b1-h1-h7 triangle to 0..27
|
// 6 to differentiate from the above case, rank_of() maps a1-d4 diagonal
|
||||||
|
// to 0...3 and finally MapB1H1H7[] maps the b1-h1-h7 triangle to 0..27.
|
||||||
else if (off_A1H8(squares[1]))
|
else if (off_A1H8(squares[1]))
|
||||||
idx = 6 * 63 * 62
|
idx = ( 6 * 63 + rank_of(squares[0]) * 28
|
||||||
+ rank_of(squares[0]) * 28 * 62
|
+ MapB1H1H7[squares[1]]) * 62
|
||||||
+ MapB1H1H7[squares[1]] * 62
|
+ squares[2] - adjust2;
|
||||||
+ squares[2] - adjust2;
|
|
||||||
|
|
||||||
// First 2 pieces are on the diagonal a1-h8
|
// First two pieces are on a1-h8 diagonal, third below
|
||||||
else if (off_A1H8(squares[2]))
|
else if (off_A1H8(squares[2]))
|
||||||
idx = 6 * 63 * 62 + 4 * 28 * 62
|
idx = 6 * 63 * 62 + 4 * 28 * 62
|
||||||
+ rank_of(squares[0]) * 7 * 28
|
+ rank_of(squares[0]) * 7 * 28
|
||||||
|
@ -852,36 +856,33 @@ T do_probe_table(const Position& pos, Entry* entry, WDLScore wdl, ProbeState* r
|
||||||
}
|
}
|
||||||
|
|
||||||
encode_remaining:
|
encode_remaining:
|
||||||
idx *= precomp->groupSize[0];
|
idx *= d->groupSize[0];
|
||||||
|
|
||||||
// Reorder remainig pawns then pieces according to square, in ascending order
|
// Encode remainig pawns then pieces according to square, in ascending order
|
||||||
int remainingPawns = entry->hasPawns ? entry->pawnTable.pawnCount[1] : 0;
|
bool remainingPawns = entry->hasPawns && entry->pawnTable.pawnCount[1];
|
||||||
|
|
||||||
while (next < size) {
|
while (next < size)
|
||||||
|
{
|
||||||
|
Square* groupSq = squares + next;
|
||||||
|
std::sort(groupSq, groupSq + d->groupLen[next]);
|
||||||
|
uint64_t n = 0;
|
||||||
|
|
||||||
int end = next + (remainingPawns ? remainingPawns : precomp->groupLen[next]);
|
// Map down a square if "comes later" than a square in the previous
|
||||||
|
// groups (similar to what done earlier for leading group pieces).
|
||||||
std::sort(squares + next, squares + end);
|
for (int i = 0; i < d->groupLen[next]; ++i)
|
||||||
|
{
|
||||||
uint64_t s = 0;
|
auto f = [&](Square s){ return groupSq[i] > s; };
|
||||||
|
int adjust = std::count_if(squares, groupSq, f);
|
||||||
// Map squares to lower index if "come later" than previous (as done earlier for pieces)
|
n += Binomial[i + 1][groupSq[i] - adjust - 8 * remainingPawns];
|
||||||
for (int i = next; i < end; ++i) {
|
|
||||||
int adjust = 0;
|
|
||||||
|
|
||||||
for (int j = 0; j < next; ++j)
|
|
||||||
adjust += squares[i] > squares[j];
|
|
||||||
|
|
||||||
s += Binomial[i - next + 1][squares[i] - adjust - (remainingPawns ? 8 : 0)];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
remainingPawns = 0;
|
remainingPawns = false;
|
||||||
idx += s * precomp->groupSize[next];
|
idx += n * d->groupSize[next];
|
||||||
next = end;
|
next += d->groupLen[next];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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), wdl);
|
return map_score(entry, tbFile, decompress_pairs(d, idx), wdl);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Group together pieces that will be encoded together. For instance in
|
// Group together pieces that will be encoded together. For instance in
|
||||||
|
|
Loading…
Add table
Reference in a new issue