Tablebase suggestion

Discussion of anything and everything relating to chess playing software and machines.

Moderator: Ras

syzygy
Posts: 5991
Joined: Tue Feb 28, 2012 11:56 pm

Re: Tablebase suggestion

Post by syzygy »

It also seems to work for chess and more than 2 piece types:

Code: Select all

from symmetry_indexer import SymmetryIndexer

def sq_index(r, c):
    return 8 * r + c

def sq_coord(i):
    return divmod(i, 8)

def make_chess_D4():
    transforms = [
        lambda r, c: (r, c),              # identity
        lambda r, c: (c, 7 - r),          # rotate 90
        lambda r, c: (7 - r, 7 - c),      # rotate 180
        lambda r, c: (7 - c, r),          # rotate 270
        lambda r, c: (r, 7 - c),          # vertical mirror
        lambda r, c: (7 - r, c),          # horizontal mirror
        lambda r, c: (c, r),              # main diagonal
        lambda r, c: (7 - c, 7 - r),      # anti-diagonal
    ]

    perms = []

    for f in transforms:
        p = [0] * 64
        for i in range(64):
            r, c = sq_coord(i)
            rr, cc = f(r, c)
            p[i] = sq_index(rr, cc)
        perms.append(p)

    return perms


if __name__ == "__main__":
    # colors:
    # 0 = empty
    # 1 = white piece
    # 2 = black piece
    idx = SymmetryIndexer(
        n_squares=64,
        perms=make_chess_D4(),
        n_colors=4,
    )

    print("orbit sizes:", [len(b["orbit"]) for b in idx.blocks])
    print("orbits:")
    for b in idx.blocks:
        print(b["orbit"])

    total = idx.count(target_counts=(1, 1, 2))
    print("count for 1+1+2 pieces:", total)

    pos = [0] * 64
    pos[sq_index(0, 0)] = 1
    pos[sq_index(1, 2)] = 2
    pos[sq_index(4, 5)] = 3
    pos[sq_index(7, 7)] = 3

    r = idx.rank(pos, target_counts=(1, 1, 2))
    print("rank:", r)

    pos2 = idx.unrank(r, target_counts=(1, 1, 2))
    print("unranked:", pos2)

    print("roundtrip ok:", tuple(idx.canonicalize(pos)) == pos2)
So (1,1,2) corresponds to a KNNvK (where the Ks may be on adjacent squares):

Code: Select all

$ python example_chess.py 
orbit sizes: [4, 4, 4, 4, 8, 8, 8, 8, 8, 8]
orbits:
[0, 7, 56, 63]
[9, 14, 49, 54]
[18, 21, 42, 45]
[27, 28, 35, 36]
[1, 6, 8, 15, 48, 55, 57, 62]
[2, 5, 16, 23, 40, 47, 58, 61]
[3, 4, 24, 31, 32, 39, 59, 60]
[10, 13, 17, 22, 41, 46, 50, 53]
[11, 12, 25, 30, 33, 38, 51, 52]
[19, 20, 26, 29, 34, 37, 43, 44]
count for 1+1+2 pieces: 953666
rank: 949116
unranked: (0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0)
roundtrip ok: True
953666 is correct. The rank 949116 is a bit surprisingly close to that number, perhaps because (0,0) is one of the squares.

Unforunately picking different squares returns an error. There seems to be a bug, which ChatGPT now claims to have fixed. I'll try again tomorrow.