Tavla‑1.6K 🎲
A real, trained backgammon (tavla) value network with 1,601 parameters. TD‑Gammon style: it taught itself by playing against itself, on a CPU, in numpy, in 95 minutes. The whole model is 6.6 KB. It fits in a tweet's attachment, or in a very long tweet.
▶ Play it in your browser: https://tiny-models.anil-oz.workers.dev/tavla (ONNX Runtime Web; tr/de/es/fr under /xx/tavla)
💻 Site source: https://github.com/hocestnonsatis/coinflip-ai
Model
| Input | 198 features, Tesauro encoding (per point and side: ≥1, ≥2, ≥3, (n−3)/2 · bar/2 · off/15 · 2 turn units) |
| Hidden | 8 sigmoid units |
| Output | 1 sigmoid: P(win) for the player who just moved |
| Parameters | 1,601 = 198·8 + 8 + 8·1 + 1 |
| ONNX | tavla-1.6k.onnx, 6,786 bytes, opset 17, input x [N,198] → output p [N,1] |
Move selection is 1‑ply: generate every legal play, encode each resulting position, score them all in one session.run, play the argmax. No gammon outputs, no doubling cube.
Training
- TD(λ) self‑play, λ = 0.7, learning rate linearly 0.2 → 0.02, weights init N(0, 0.1²), seed 4
- 381,954 self‑play games in 95 minutes on one CPU core (pure numpy, no GPU harmed)
- 8 hyper‑parameter configs were trained in parallel for 95 min each. Checkpoints were screened against a heuristic bot, and the final checkpoint of this run won.
- Rules engine (
train/bg.py): bar entry, hitting, bearing off (including higher‑die bear‑off from the highest point), must‑use‑both‑dice / larger‑die rule, doubles. The site's TypeScript port produces identical legal‑move sets on 1,500 random positions.
Evaluation
Held-out evaluation with fresh seeds (not the seeds used for selection), 5,000 games per opponent. The first player is chosen at random:
| Opponent | Wins | Win rate |
|---|---|---|
| Random legal‑move player | 4,986 / 5,000 | 99.7% |
| Pip‑count heuristic bot (race + blots + made points) | 3,766 / 5,000 | 75.3% |
These are single‑game wins. Gammons are not counted. It has never met a human at a coffee house. Results there may vary.
Usage
pip install onnxruntime numpy
python example.py
import onnxruntime as ort, numpy as np, sys
sys.path.insert(0, 'train'); from bg import start, legal, encode_batch
sess = ort.InferenceSession('tavla-1.6k.onnx')
plays = legal(start(), 3, 1) # {resulting board: steps}
p = sess.run(None, {'x': encode_batch(list(plays))})[0][:, 0]
print(list(plays.values())[int(np.argmax(p))]) # → 8/5 6/5, the textbook 3‑1
Boards are always seen from the side to move: b[0..23] are points (mine > 0, opponent < 0, I move toward index 0), b[24]/b[25] are my/opponent's bar, and b[26]/b[27] are borne off.
Files
tavla-1.6k.onnx: the modeltavla-1.6k.safetensors,tavla-1.6k.npz: the same weights (W1198×8,b18,W28×1,b21)example.py: encode → win probability → pick a move, plus a self‑play gametrain/:bg.py(rules + encoding),net.py,td.py(TD(λ) trainer:python td.py d 0.2 0.02 0.7 4 95),eval.py(vs random / heuristic),players.py,play.py,fixtures.py(cross-check data),export_onnx.py
Limitations
- No doubling cube, no match play, no gammon/backgammon outputs.
- 1‑ply search with 8 hidden units: solid against casual play, not expert level (TD‑Gammon used 40–80 hidden units plus deeper search).
- Evaluation is only against a random player and a simple heuristic bot. There is no GNU Backgammon benchmark.
Türkçe
Tavla‑1.6K, 1.601 parametreli, gerçekten eğitilmiş bir tavla ağı: 198 girdi (Tesauro kodlaması) → 8 sigmoid nöron → 1 çıktı (kazanma olasılığı). TD(λ=0,7) ile kendine karşı 381.954 oyun oynayarak, tek CPU çekirdeğinde 95 dakikada öğrendi. Rastgele oyuncuya karşı %99,7 (4986/5000), pip sayan sezgisel bota karşı %75,3 (3766/5000) kazanıyor. Katlama küpü yok, usta değil, ama hamlesini milisaniyede yapar. Tarayıcıda oyna: https://tiny-models.anil-oz.workers.dev/tr/tavla
License
MIT · © Anıl ÖZ