Compressing chess moves for fun and profit
Overall focus
- Discussion centers on how far you can compress chess games beyond PGN by exploiting game structure, non‑uniform move distributions, and engine predictions.
- There’s a recurring tension between “maximal compression” vs “simplicity, speed, and queryability.”
Generic vs domain‑specific compression
- Several suggest trying standard compressors (gzip, zstd, LZW, trained dictionaries) on move lists or sorted game lists as a baseline.
- Others argue general compressors can’t exploit chess‑specific structure (legal moves, board state) as well as custom encodings.
- Some think a good zstd dictionary or columnar formats over positions might get close “for free,” but this remains untested in the thread.
Move- and game-level encodings
- Many propose simple fixed‑width encodings:
- 12–16 bits: source + destination squares (6+6 bits), with promotions/castling inferred or signaled via “impossible” destinations or extra bits.
- Piece-index + relative move pattern, exploiting that each side has at most 16 pieces; schemes reaching ~6–9 bits/move are discussed.
- More advanced schemes:
- Index the chosen move among all legal moves in the current position; with ~n legal moves, you need ~log₂(n) bits; practical estimates are ≲6–8 bits/move.
- Use variable‑length codes (Huffman, arithmetic coding, ANS/rANS, CABAC) with per‑position probability distributions.
- Engine‑guided probabilities (from Stockfish or weaker engines) could, in theory, reach ~3–4 bits/move, possibly lower, but at high CPU cost and with tight coupling to specific engine versions.
- A follow‑up by the article’s author (linked repeatedly) reports ~3.7 bits/move using arithmetic coding and fast move generation.
Positions, indexing, and search
- Several point out that in real databases, storage is often dominated by search indexes, not raw game data.
- Ideas for indexing:
- Zobrist hashing and transposition‑table–style structures.
- Bloom filters or partitioned Bloom filters for existence checks vs full hash tables for O(1) lookup.
- Columnar storage of board states (per‑square “columns”) with standard compression and then referencing positions by offset.
- Techniques for “fuzzy” position search (e.g., Hamming distance on bitboards, MinHash‑like ideas), though practical solutions remain unclear.
Tradeoffs and practical concerns
- Many emphasize that extreme compression can hurt:
- Decoding speed (full move generation, engine calls).
- Random access and complex queries (e.g., opening explorers, endgame pattern search).
- Maintainability; very dense, clever schemes may be hard for future developers to understand.
- Some note that PGN is wasteful but human‑readable; in many real‑world cases, I/O latency and querying strategy matter more than squeezing the last bits out of move storage.