4

This is a programming question related to chess syzygy endgame tables. I believe that it is better suited on chess stack exchange than on SO because it is too specific to chess and asks for a recommendation. Also I noticed that there are enough people with a lot of programming knowledge here.


I have a syzygy WDL endgame table (just for example I uploaded the file KPPPPvK.rtbw) and for my own purposes I need to iterate over all FENs in this table and see the results for each position.

Is there a library (preferably with python interface) to do this? Most of the libraries that I have seen so far only allows to probe a table.

6

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; 
}
2
  • wow really thanks for an answer. I know that this not what the table was designed for, I just hoped that it is possible to extract this data somehow. Sep 17 '17 at 7:42
  • @SalvadorDali I don't think so, at least I haven't seen anything like that.
    – SmallChess
    Sep 17 '17 at 7:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.