mcostalba wrote:Could you please do the same walk through for pawn encoding? I have seen there are some differences, but I am not able to figure them out.
One tricky aspect of pawn encoding is that TB files store separate tables for files a, b, c and d. Determining this file is easy if the position for one color has a single pawn, as that pawn will (possibly after mirroring) be in one of the files a, b, c and d, which will determine the table within the TB file that must be probed. Things are a bit more complicated with at least 2 pawns of the same color, as one pawn might be in a and the other in b. Or even worse, one might be in b and the other in h which after mirroring means that one is in a and the other in g. So basically the generator and the probing code have to agree on how to assign pawn combinations to the files a-d.
Things are complicated further by the fact that ordering of pawns and pieces (for the purpose of improving compression) is done separately for each file-table. So arrays like norm[] and factor[] may be different for each file, and the order in which piece positions are extracted from the current board representation may also be different.
This is why probe_wdl_table() and probe_dtz_table() first extracts the pawn positions for the "leading color" (the same for all files, int k in probe_wdl_table()) and then calls pawn_file() to determine the correct file. This function orders the pawns according to which comes first on a2-a6,b2-b6,c2-c6,d2-d6 after mirroring the pawn to the left-hand side of the board and returns the file (from a-d) of the "first" pawn:
Code: Select all
static const ubyte flap[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 6, 12, 18, 18, 12, 6, 0,
1, 7, 13, 19, 19, 13, 7, 1,
2, 8, 14, 20, 20, 14, 8, 2,
3, 9, 15, 21, 21, 15, 9, 3,
4, 10, 16, 22, 22, 16, 10, 4,
5, 11, 17, 23, 23, 17, 11, 5,
0, 0, 0, 0, 0, 0, 0, 0
};
...
static int pawn_file(struct TBEntry_pawn *ptr, int *pos)
{
int i;
for (i = 1; i < ptr->pawns[0]; i++)
if (flap[pos[0]] > flap[pos[i]])
Swap(pos[0], pos[i]);
return file_to_file[pos[0] & 0x07];
}
When this is done, the probing code extracts the remaining pawn and piece positions and calculates the index for the position by calling encode_pawn() with the norm[] and factor[] arrays for that file.
The function encode_pawn() first mirrors the leading piece to one of the a-d files, if necessary:
Code: Select all
if (pos[0] & 0x04)
for (i = 0; i < n; i++)
pos[i] ^= 0x07;
(This cannot yet be done in pawn_file(), because that function is called before all piece positions are extracted from the board representation.)
Now the non-leading pawns of the leading color are sorted according to the ptwist[] array and an index is calculated for the pawns of the leading color:
Code: Select all
static const ubyte ptwist[] = {
0, 0, 0, 0, 0, 0, 0, 0,
47, 35, 23, 11, 10, 22, 34, 46,
45, 33, 21, 9, 8, 20, 32, 44,
43, 31, 19, 7, 6, 18, 30, 42,
41, 29, 17, 5, 4, 16, 28, 40,
39, 27, 15, 3, 2, 14, 26, 38,
37, 25, 13, 1, 0, 12, 24, 36,
0, 0, 0, 0, 0, 0, 0, 0
};
...
for (i = 1; i < ptr->pawns[0]; i++)
for (j = i + 1; j < ptr->pawns[0]; j++)
if (ptwist[pos[i]] < ptwist[pos[j]])
Swap(pos[i], pos[j]);
t = ptr->pawns[0] - 1;
idx = pawnidx[t][flap[pos[0]]];
for (i = t; i > 0; i--)
idx += binomial[t - i][ptwist[pos[i]]];
idx *= factor[0];
This is basically the same binomial formula for placing a number of like pieces as used in encode_piece(), but with a twist.
Next, an index is calculated for the pawns of the non-leading color (if there are such pawns). This is the same as placing a number of like pieces, except that there can be no pawns in a1-h1, so at one place you can see a "- 8".
Finally, an index is calculated for each remaining piece or group of remaining like pieces. No "- 8" here.
The arrays norm[] and factor[] do the same as in encode_piece().