To my knowledge the Syzygy tablebase doesn't have a function that magically returns all FEN positions from a file. I don't think it should because that's not what tablebase is designed for.
However, there's nothing stopping you from constructing all possible FENs. You know from the file name you have four pawns in the endgame. All you need to is:
- Use
python-chess package
- Generate all possible FENs
- For each FEN, use the Python package for probing
Please take a look at:
http://talkchess.com/forum/viewtopic.php?start=0&t=61003&topic_view=flat
for FEN generation. Sven Schüle is an experienced engine programmer, so please study his code and adjust it if necessary.
// Usage example: fengen.exe [-m|--mirror] Q r n 2p
// See http://www.talkchess.com/forum/viewtopic.php?t=61003
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <vector>
// definitions for chess board representation
typedef int Color;
enum { White = 0, Black, Empty };
typedef int Piece;
enum { NoPiece = 0, Pawn, Knight, Bishop, Rook, Queen, King };
typedef int Square;
enum {
A1 = 0,B1,C1,D1,E1,F1,G1,H1,
A2, B2,C2,D2,E2,F2,G2,H2,
A3, B3,C3,D3,E3,F3,G3,H3,
A4, B4,C4,D4,E4,F4,G4,H4,
A5, B5,C5,D5,E5,F5,G5,H5,
A6, B6,C6,D6,E6,F6,G6,H6,
A7, B7,C7,D7,E7,F7,G7,H7,
A8, B8,C8,D8,E8,F8,G8,H8,
FF = 0xff
};
Color opponent(Color c) { return c ^ Black; }
Square makeSquare(int file, int rank) { return 8 * rank + file; }
struct Board {
Color color[64];
Piece piece[64];
bool isPiece(Square s, Color c, Piece p) const { return color[s] == c && piece[s] == p; }
void set(Square s, Color c, Piece p) { color[s] = c; piece[s] = p; }
void clear(Square s) { set(s, Empty, NoPiece); }
Board() { for (Square s = A1; s <= H8; s++) clear(s); }
void printFEN()
{
int nEmpty = 0;
for (int r = 7; r >= 0; r--) {
for (int f = 0; f <= 7; f++) {
Square s = makeSquare(f, r);
if (color[s] == Empty) {
++nEmpty;
} else {
if (nEmpty > 0) {
fputc('1' + nEmpty - 1, stdout);
nEmpty = 0;
}
static char const pieceSym[] = ".pnbrqk";
if (color[s] == White) {
fputc(toupper(pieceSym[piece[s]]), stdout);
} else {
fputc(tolower(pieceSym[piece[s]]), stdout);
}
nEmpty = 0;
}
}
if (r > 0) {
if (nEmpty > 0) {
fputc('1' + nEmpty - 1, stdout);
nEmpty = 0;
}
fputc('/', stdout);
}
}
fputs(" w ", stdout);
if (isPiece(E1, White, King) && isPiece(H1, White, Rook)) fputc('K', stdout);
if (isPiece(E1, White, King) && isPiece(A1, White, Rook)) fputc('Q', stdout);
if (isPiece(E8, Black, King) && isPiece(H8, Black, Rook)) fputc('k', stdout);
if (isPiece(E8, Black, King) && isPiece(A8, Black, Rook)) fputc('q', stdout);
fputs(" - 0 1\n", stdout);
}
};
// definitions needed to set up the initial position
// usually more simple than that but we need to iterate over each group of pieces of same type
struct PieceInitDescr {
int nPieces;
Square initSqr[8];
};
PieceInitDescr pieceInitDescr[2][1+6] = {
{
{ 0, { FF,FF,FF,FF,FF,FF,FF,FF } },
{ 8, { A2,B2,C2,D2,E2,F2,G2,H2 } },
{ 2, { B1,G1,FF,FF,FF,FF,FF,FF } },
{ 2, { C1,F1,FF,FF,FF,FF,FF,FF } },
{ 2, { A1,H1,FF,FF,FF,FF,FF,FF } },
{ 1, { D1,FF,FF,FF,FF,FF,FF,FF } },
{ 1, { E1,FF,FF,FF,FF,FF,FF,FF } },
},
{
{ 0, { FF,FF,FF,FF,FF,FF,FF,FF } },
{ 8, { A7,B7,C7,D7,E7,F7,G7,H7 } },
{ 2, { B8,G8,FF,FF,FF,FF,FF,FF } },
{ 2, { C8,F8,FF,FF,FF,FF,FF,FF } },
{ 2, { A8,H8,FF,FF,FF,FF,FF,FF } },
{ 1, { D8,FF,FF,FF,FF,FF,FF,FF } },
{ 1, { E8,FF,FF,FF,FF,FF,FF,FF } },
},
};
// data related to command line parameters
int missing[2][1+6] = {
{ 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0 },
};
bool mirror = false;
template <bool Mirror>
void enumerate(Board & b, Color c, Piece p)
{
Color cMiss = (Mirror ? opponent(c) : c);
Color cStop = (Mirror ? White : Black);
PieceInitDescr const & d = pieceInitDescr[c][p];
// setup initial pieces of given color and type
for (int i = 0; i < d.nPieces; i++) {
b.set(d.initSqr[i], c, p);
}
if (p == King && c == cStop) {
b.printFEN();
} else {
// generate all permutations of missing pieces for the given color and piece type
int nPresent = d.nPieces - missing[cMiss][p];
std::vector<bool> v(d.nPieces);
std::fill(v.end() - nPresent, v.end(), true);
do {
// remove missing pieces
for (int i = 0; i < d.nPieces; i++) {
if (!v[i]) {
b.clear(d.initSqr[i]);
}
}
// recursive call
Color cNext = (p == King) ? opponent(c) : c;
Piece pNext = (p == King) ? Pawn : p + 1;
enumerate<Mirror>(b, cNext, pNext);
// restore removed pieces
for (int i = 0; i < d.nPieces; i++) {
if (!v[i]) {
b.set(d.initSqr[i], c, p);
}
}
} while (std::next_permutation(v.begin(), v.end()));
}
// clear initial pieces
for (int i = 0; i < d.nPieces; i++) {
b.clear(d.initSqr[i]);
}
}
int main(int argc, char * argv[])
{
// scan parameters (illegal parameters are ignored for simplicity)
for (int i = 1; i < argc; i++) {
char const * arg = argv[i];
if (strcmp(arg, "-m") == 0 || strcmp(arg, "--mirror") == 0) {
mirror = true;
} else
if (strlen(arg) <= 2) {
int number = (strlen(arg) == 1) ? 1 : arg[0] + 1 - '1';
char p = (strlen(arg) == 1) ? arg[0] : arg[1];
Color color = (p == toupper(p)) ? White : Black;
Piece piece = NoPiece;
switch (tolower(p)) {
case 'p': piece = Pawn; break;
case 'n': piece = Knight; break;
case 'b': piece = Bishop; break;
case 'r': piece = Rook; break;
case 'q': piece = Queen; break;
// king must not be missing
default: break;
}
if (piece != NoPiece && number >= 1 && number <= pieceInitDescr[color][piece].nPieces) {
missing[color][piece] = number;
}
}
}
// enumerate combinations of missing pieces
Board b;
enumerate<false>(b, White, Pawn);
if (mirror) {
enumerate<true>(b, Black, Pawn);
}
return 0;
}