From a network that could not tell its own four tokens apart to a 587K-parameter graph transformer that beats the strongest models before it, and six tests that say what is left between it and perfect play is mostly the dice. Including what didn’t work.
587Kparameters. A single-frame graph transformer, a fifth the size of the model it replaced
52.7%against V13.5, the model it replaced, over 2,000 games (and 52.6% against V13.6, the strongest CNN)
68.4%against MCTS, the strongest scripted player (an opponent, not part of the model)
~85%the ceiling against scripted bots. 6 tests say the rest is dice
84.7% → 76.8%V16: a better internal picture of danger, and worse play
Trained by imitating the previous best model, then by self-play with a reward of win or lose and nothing else. No search, no history, no sampling at play time.
Most gains came from the input, not the network: each step that helped made the encoding more honest about the game’s symmetry.
01The problem
Ludo is a race decided by dice. Two players here, four tokens each, one roll a turn. Luck decides what you roll; the game is what you do with it: which token to move, when to break a stack, when to run and when to sit on a safe square.
That makes it hard to measure, not only hard to play. Between two strong players a single game is mostly luck, so almost every result on this page is thousands of games deep, with its standard error next to it. The question the project ended on was not how to get stronger, but whether any skill was left to find. The ceiling section is the answer.
02The approach
AlphaLudo borrows the AlphaGo recipe almost wholesale: one network predicts both the best move and its own chance of winning, trained first by imitating a strong teacher, then by playing against itself.
Almost everything interesting happened in two places: what the network is shown (the encoder) and what it is rewarded for. The optimiser stayed boring on purpose; every run uses PPO. Most of what follows is the story of those two choices, including the ones that were wrong. Dead ends are documented here, not hidden.
03The model
The model you play is V15.2, a single-frame graph transformer with 587,306 parameters. Earlier versions looked at the board the way a camera does, as a stack of images. This one treats it as a graph: every one of the 225 cells is a node, and attention decides which cells should inform which.
What it sees. A single frame: for each of the 225 cells of the 15×15 board, 3 numbers (its own tokens there, the opponent’s tokens there, and whether the square is safe), from the side of the player to move. The dice and the scores ride in four reserved cells. No history, no hand-computed hints, and no identity for individual tokens.
How it mixes. Each cell becomes a token, plus one summary token (CLS). 4 transformer layers of width 128 let every cell attend to every other, with a learned bias for each kind of connection on the board: a dice step forward, a step back, the turn into the home stretch.
What it says. A 225-way distribution over the cells a token could move from, and, from the summary token, its own chance of winning. That is the number shown live while you play.
What it doesn’t do. Search, sample or remember. It plays the top-scored legal move, one forward pass per turn, about 13ms in a laptop browser.
Figure 1The shipped model, V15.2. 587,306 parameters in a 2.8MB file. The lit cells on the policy board and the needle on the value bar are illustrative, not a recorded position. Source: Training journal, Exp 58 (17–19 Jun 2026)
Three properties matter more than the size. It sees one frame: earlier experiments with eight turns of history and with two frames did not beat single-frame models, so history was dropped. It has no idea which token is which: the input counts tokens per cell and the policy scores cells, so the four tokens are interchangeable by construction (why that matters is in Looking inside). And it runs no search: when we bolted a lookahead onto it, it did not get better (test 3).
04How it learns
A generation is made in five stages. The last two are where the project changed its mind.
01Bootstrapscripted bots play each other
02Imitatecopy the previous best model
03Self-playagainst itself and past champions
04Win/loss onlyGAE spreads the one signal
05Head to headthousands of games vs the old best
↺ The winner of step 05 becomes the teacher in step 02 for the next generation.
Figure 2How a generation is made. Five stages, each feeding the next. Step 04 is the change that finally worked, and it was the one that removed things. Sources: Training journal, Exp 55b (16 Jun 2026) · Training journal, Exp 58 (17–19 Jun 2026)
Bootstrap. Millions of practice games between scripted bots (heuristic, aggressive, defensive, expert). The network starts by learning what they do.
Imitate the best teacher. The student copies the previous best AlphaLudo until it plays about as well.
Self-play. It plays itself and a pool of earlier champions, adjusting toward whatever wins. For V15.2 the pool was all neural: V13.2 40%, V13.5 (imitation stage) 30%, V13.6 10%, itself 20%.
Take the training wheels off. For most of the project we shaped behaviour with hand-tuned rewards: bring a token out, don’t ignore the laggard, don’t walk into capture range. The pipeline that finally worked drops all of it. The only reward is winning or losing, and GAE (λ = 0.95) spreads that one signal back across every move. Applied to the V13.6 champion, this alone beat it 54.4% (544 to 456), the first real improvement over a champion the project had seen. The bad habits we had been penalising disappeared on their own: they were artifacts of the crutches, not the game.
The honest test. Against scripted bots, win rate saturates around ~85% and stops being informative. Versions are compared head to head instead, thousands of games, with the same dice for both sides where possible.
Stage 5 is not a formality. Across six snapshots of one run, the checkpoint with the best score against the bots (82.8%) finished last in head-to-head play (48.6%). Past a point, the bot score doesn’t just flatten; it can point the wrong way. Source: Training journal, Exp 49 (13 Jun 2026)
05The generations
Version numbers in this project skipped and branched, so we won’t pretend there is a clean count. What there is: a line from a network that could not tell its own tokens apart to the one you play, and each step on it is a logged run. The shape of the line is the main lesson. Most gains came from making the input more honest about the game, not from making the network bigger.
Oct2025NovDecJan2026FebMarAprMayJunJulAug
V1 – V5, Oct 2025 → Feb 2026
V6 – V1173–77%, Dec 2025 → Mar 2026
V12 – V12.282.65%, Mar 2026
V13.252.4%, Apr 2026
V13.551.7%, May 2026
V13.654.4%, Jun 2026
V15.252.7%, June 2026 · deployed
V1684.7% → 76.8%, Aug 2026 · backfired
Figure 3From V1 to V15.2, and one step past it. Each bar is an era of work, by month; the first two overlapped. The number is what that era is remembered by. Amber marks the model you play; the hatched bar is the experiment that made it worse. Each era below names the training journal entries its result comes from.
V1 – V5Oct 2025 → Feb 2026
Eight stacked maps
The board arrived as eight black-and-white layers, and the network could not tell its own four tokens apart — they collapsed into one blob, so it was guessing which piece to move.
Danger maps, capture opportunities and safe-landing squares, all computed by hand and fed in as extra channels. It helped, then stalled: the V6 run plateaued at 73–77% against scripted opponents, and the wider and attention-based successors through V11 crept only to about 79%.
An attention layer over the eight tokens themselves, not the board cells, so the network could reason about each of its pieces as a separate thing. V12 was the first model past 80% against scripted opponents (81.00%, once); V12.2 was the first to stay there, three evaluations running, peaking at 82.65%.
82.65%first to hold 80%+ against scripted opponents
Most of the hand-engineered features came back out: mostly raw positions plus three static board hints (safe cells, home stretches). It beat V12.2, the model with months of hand-tuning behind it, 52.4% over 10,000 games.
Every encoder until now gave each of the four own-tokens its own channel, forcing the network to learn from scratch that the rules treat them identically. V13.5 collapsed them into a single count-per-cell view: 51.7% over 3,000 games vs V13.2, and 90.4% vs the competing temporal experiment.
Every shaped reward removed: win or lose, nothing else, with GAE spreading that one signal back over the game. Fine-tuned this way from the reigning champion, it beat it 54.4% (544 to 456), the first real improvement over a champion the project had seen. The strongest of the CNNs, at 1.05M parameters.
54.4%vs the champion it started from
Source: Training journal, Exp 55b
V15.2June 2026 · deployed
The board is a graph
225 cells as nodes, three numbers each, attention along the real movement routes, and a 225-way "move from this cell" policy. 587K parameters — a fifth of V13.5 — and it beats it 52.7% over 2,000 games. This is the model you play against.
52.7%vs V13.5 over 2,000 games
Source: Training journal, Exp 58
V16Aug 2026 · backfired
Two properties per connection
A second property per connection, routed so a tactical objective could shape it without touching the weights that play. The mechanism worked exactly as designed and the play got worse: 84.7% → 76.8%.
84.7% → 76.8%champion vs V16, same start
Sources: Training journal, V16 · Interpretability notes, V16 summary
Two branches are missing from the line because they lost. V13.4, a transformer over eight turns of history, won only 9.6% of 2,000 games against V13.5 (192 wins); it lost 90.4%. The V15 and V15.1 graph transformers, with eight and two frames of history, tied V13.5. Dropping history entirely, in V15.2, is what made the graph version win.
06The tournament
Before shipping V15.2 we played the four strongest players in the project against each other: the previously deployed V13.5, V13.6 (the strongest of the CNNs), V15.2, and MCTS, the strongest scripted player we have. V15.2 beat all three. Against V13.5, the model it replaced, it won 52.7% (1,054 of 2,000); against V13.6, 52.6% (1,051 wins); against MCTS, 68.4% (1,367 wins).
Win rate of each row model against each column model, 2,000 games per pair, with raw win–loss counts.
Row beats column
vs V13.5
vs V13.6
vs V15.2
vs MCTS
Average
V13.5
—
48.3%965–1,035
47.3%946–1,054
65.8%1,315–685
53.8%
V13.6
51.8%1,035–965
—
47.5%949–1,051
65.6%1,311–689
54.9%
V15.2 shipped
52.7%1,054–946
52.6%1,051–949
—
68.4%1,367–633
57.9%
MCTS scripted
34.3%685–1,315
34.5%689–1,311
31.7%633–1,367
—
33.5%
Figure 4The tournament, in full. Round-robin, 2,000 games per pair, half from each seat, with mirrored dice seeds; no draws. Each cell is the row model’s win rate, computed from the raw counts beneath it. One standard error at this size is ±1.1pp. A same-run check, V15.2 best against V15.2 latest, came out 1,005–995. Source: Training journal, Exp 58, the four-way tournament (19 Jun 2026)
Margins this size need care. Each of the two neural wins is about 2.4 standard errors above 50%, and they corroborate each other. They are not large, and an earlier, separate 2,000-game match against V13.6 came out 50.8%, a statistical tie. We read that as the noisy low end of the same small edge, which is also the point of the next section.
MCTS in this table is the opponent, not part of the model. The shipped network runs no search at all.
ParametersTournament average
V13.5parameters: 3.0Mtournament average: 53.8%
V13.6parameters: 1.05Mtournament average: 54.9%
V15.2parameters: 587Ktournament average: 57.9%
50%60%
Figure 5Smaller and stronger. V15.2 is about a fifth the size of V13.5 and 56% the size of V13.6, and it has the best average against the other three. Sources: Training journal, Exp 58 (19 Jun 2026) · Interpretability notes, V13.5 summary
07The ceiling
The strongest models all settle around ~85% against the scripted pool. Is that a skill ceiling or a luck ceiling? If there were skill left, something should be able to find it. We tried six independent ways.
40%50%60%
1Head-to-head across one runExp 49Six snapshots of a single run, from 764K games in to its last, played round-robin.40%50%60%All within 4.2pp of 50%
2Human play-testingExp 58A human played V15.2 looking for the flaws earlier models had.no number to plot17 games, no repeatable flaw
3Search at play timeExp 592-ply expectimax on top of the policy, against the raw policy, paired dice.40%50%60%49.8% over 2,000 games
4A dedicated exploiterExp 60A copy trained for 110K games with one goal: beat frozen V15.2.40%50%60%45.4% (363 of 800)
5Per-decision equity lossExp 61For 250 decisions, double-sampled rollouts score every legal move; how much equity did the chosen move give up?-3pp0+3pp−0.80 ± 0.61pp, about zero
6Retrain with a richer value targetExp 62A candidate retrained on λ-return value targets for 106K games, then paired-dice A/B.40%50%60%50.9% (611 of 1,200)
Figure 6Six tests, one answer. Win rates are on a 40–60% scale around a coin flip; whiskers are one standard error as the journal reports it. Test 1 plots each of the six snapshots' overall head-to-head score. Test 5 is on its own scale: equity given up per decision, in percentage points, where zero means no measurable loss. Source: Training journal, Exps 49 and 58–62 (13–21 Jun 2026)
Every test came back the same. 1.7M more games of training bought nothing measurable. An exploiter trained for 110K games to beat V15.2, and nothing else, lost to it. In a dice game, a single game between near-optimal players is mostly luck: ~85% against the pool is the ceiling, and the rest is variance, not weakness. Knowing when to stop is a result too.
08Lessons
Five things the journal taught us that we would not unlearn.
Failed
“Mathematically clean” rewards can be poison
Potential-based reward shaping, elegant on paper, quietly leaked a tiny negative reward every turn. Over ~145 moves it summed to about −0.22, a fifth of a loss, and the model decided every game was unwinnable. It took 155,000 games to notice.
In long games, tiny systematic biases compound. Check what the reward looks like end to end.
Revised
Loud rewards helped, until they didn’t
Early on, quieting the shaped rewards cut the win rate against a random opponent from 67% to 33%. The dice noise drowned the signal, so loud rewards looked like the answer. The real answer came months later: no shaping at all, with GAE doing the credit assignment.
Shaped rewards are a way to survive dice noise, not the way to beat it.
Worked
The encoder was the bottleneck, not the model
A CNN with attention, a plain CNN and a transformer over eight turns of history all stalled at about the same level. V13.5 moved past it by changing the input, collapsing four per-token channels into one count per cell. V15.2 finished the thought by erasing token identity entirely.
When different architectures hit the same ceiling, look upstream of the architecture.
Worked
The best-scoring checkpoint was the weakest player
Of 6 snapshots of one run, the one with the highest score against scripted bots (82.8%) came last head to head (48.6%). Its peak was a lucky roll of the evaluation dice.
Past a point, a benchmark against weak opponents can rank models backwards.
Newest
Separating gradients doesn’t separate function
V16 gave two objectives their own property on every connection, with gradients routed so they never touched. The routing was exact. The interference happened anyway, because one property still scales the other in the forward pass.
For a second objective to be independent it has to be additive and orthogonal, not multiplicative and aligned. The numbers.
09Looking inside
A sister project, AlphaLudo-MechInterp, asks what the networks have actually learned. Only findings we could trace to a logged run are on this page. Several figures from older versions of this site are not, because we could not source them.
The first finding explains why V15.2 exists at all. V13.5 and V13.6 picked a token through a rank-indexed routing that interpretability showed was mechanically real: removing the rank channels changed the policy by 0.60–0.76 KL. That routing fixed the older models' confusion about which token was which, and then became V13.6’s flaw: a particular token, usually the one furthest behind, could be systematically under-weighted. V15.2 removed the routing altogether.
V15.2 · play-test
Every token is the same token
The policy scores board CELLS, not pieces, so it is permutation-symmetric over your four tokens. When they are genuinely interchangeable it assigns them equal probability — literally 0.250 each. The laggard-neglect flaw of earlier models was a token-identity artifact of rank-indexed encoding; a cell-based policy structurally cannot represent that bias.
Source: Training journal, Exp 58, play-test (19 Jun 2026)
V15.2 · the flip side
And that is also the weakness
When two of your tokens sit on the same cell but one is genuinely the better move — breaking a stack, or one step from safety — a cell-based policy has no way to tell them apart, and picks arbitrarily. The same property that removed the old flaw creates this one. It is the natural place to sharpen the architecture.
Source: Training journal, Exp 58, play-test (19 Jun 2026)
Exp 59 · null result
One step, not a plan
Bolting 2-ply expectimax search onto the deployed model at play time scored 49.8% against it — a tie. The search cannot out-rank the policy it reads. Whatever the network is doing, it is a single forward pass over the current board, and looking further ahead with the same evaluator adds nothing.
Source: Training journal, Exp 59 (20 Jun 2026)
V16 · Aug 2026
Danger, almost perfectly readable
Give every connection a second property routed to a tactical objective and capture risk becomes near-perfectly decodable from the summary node — 0.8739 to 0.9985 AUC. Remove that property and it collapses to 0.7666, below the champion, while control concepts do not move. The information went exactly where it was aimed. The model still played worse.
Figure 7Four findings, drawn on the board. These are illustrations of each finding, not the model’s attention weights. The real policy is over 225 cells and its attention is high-dimensional; each board draws the route structure a finding is about, so the claim can be read in the space it applies to.
Where the decision happens is the other clear result. In V15.1, removing the first or last layer changes the policy a lot and removing the third barely at all; stopping after layer 3 already agrees with the final move 92.3% of the time, but layer 4 alone changes about 18% of late-game decisions. Early moves are decided at once; the endgame uses the full depth.
Knock the layer out: policy change (KL)Stop after it: agrees with the final move
Layer 1knockout KL: 0.169agreement with the final move: 85.7%
Layer 2knockout KL: 0.042agreement with the final move: 89.0%
Layer 3knockout KL: 0.009agreement with the final move: 92.3%
Layer 4knockout KL: 0.129agreement with the final move: 100.0%
Figure 8What each layer does, in V15.1 (V15.2’s two-frame sibling, 587,690 parameters), over 600 sampled positions. Layers are counted from one. Layers 1 and 4 carry the weight; layer 3 barely moves the policy when removed. Source: Interpretability notes, V15.1 summary, Exps 7 and 9
10V16: representation and behaviour came apart
V16 gave every connection a second property, owned by a second objective. The first property is trained by reinforcement learning as usual. The second is trained only by an auxiliary loss on tactical events (is a token in danger, is a capture available), and the gradients were routed so the two never touch. It worked. The model got worse.
Champion (V15.2)V16V16, second property removed (b = 0)
What the summary node encodes probe AUC, 0.6–1.0
in dangerchampion 0.8739V16 0.9985V16 with b = 0 0.7666
capture availablechampion 0.7826V16 0.9505V16 with b = 0 0.6913
tokens out (control)champion 0.8991V16 0.9192V16 with b = 0 0.9494
my progress (control)champion 0.9441V16 0.9699V16 with b = 0 0.9583
0.60.70.80.91.0
How it plays eval win rate, 2,000 vs Expert + Heuristic
Shared starting checkpoint79.6%
Champion, from that start84.7%+5.1
V16 at its best (60,001 games)80.8%+1.2
V16 at 210,000 games76.8%−2.8
74%78%82%86%
Figure 9Representation up, behaviour down. Top: how well a linear probe reads four concepts from the summary node (6,000 states from real 2-player self-play · 5-fold CV logistic probes · AUC; base rates in-danger 29.0% · capture-available 5.8%). The two controls are greyed. Bottom: both runs started from the same checkpoint on the same pipeline. The champion reached 84.7% from it; V16 peaked early and never beat its peak in the 155,238 games after. Sources: Interpretability notes, V16 summary, Exps 13 and 14 · Training journal, V16 (4–6 Aug 2026)
The tactical information landed exactly where it was aimed. Danger went from 0.8739 to 0.9985 AUC, almost perfectly readable, and capture from 0.7826 to 0.9505. Remove the second property and danger decodability falls 23 points to 0.7666, below even the champion, while the two controls do not move. And yet over 2,000 vs Expert + Heuristic, the champion wins 84.7% and V16 wins 76.8%. The representation was fixed almost completely, and the play got worse.
That also falsifies an earlier hypothesis: that the champion was limited by how poorly it encoded capture risk. The mechanism is visible in the weights. The second property owns 15.5% of all weight change, concentrates on the largest weights the first objective made load-bearing (correlation +0.5148), and zeroing it flips 25% of decisions, mostly late in the game. Separating gradients does not separate function. The routing is exact in the backward pass, but b still scales a in the forward pass, so the objectives compose multiplicatively.
What is not established: whether the damage came from the routing, the auxiliary objective, or the two-property architecture itself. The control run that separates them was pre-registered and scripted, and has not been run.
11The bug log
None of these is a modelling idea. Each one cost real time, and several could have quietly changed results.
01
The best checkpoint that never was
best_eval_wr was not restored on resume, so every restart made the first evaluation trivially "best" and overwrote model_best.pt. Harmless on a stable VM; destructive under power cuts.
Source: Training journal, V16 (Aug 2026)
02
A lock held by a process that no longer existed
The training lock tested liveness with kill(0), but a reboot recycles PIDs — so a stale lock read as LIVE forever and silently refused every restart. Cost about 40 minutes before anyone looked at the PID.
Source: Training journal, V16 (Aug 2026)
03
A probe measuring nothing
The stratified state sampler bucketed game phase by the current player’s tokens only, so 71% of collected states had zero opponent tokens on the board. Every tactical probe run on it had a capture base rate of 0.0% — measuring a situation that could not occur.
Source: Training journal, V16 (Aug 2026)
04
A learning rate of zero
The supervised stage annealed its learning rate to exactly 0, saved that into the checkpoint, and the RL trainer restored it. An overnight run of 161K games, with a "peak" of 76.8%, never changed a weight: every movement in the curve was evaluation noise. The earlier V6.3 run shows the same flat signature, so part of that era’s plateau may be this bug.
The base-square coordinates were listed in reading order for every seat, so after the per-seat rotation the four base slots came out mirror-flipped between the two players. Every model from V6 to V12.2 saw two mirrored versions of the same positions. It surfaced only because the AI, playing the second seat, always brought out the "wrong" token first.
What AlphaLudo borrowed, in the order it was published, and the one idea it parked.
1992
The first dice game
TD-Gammon Tesauro · IBM
The original result: a neural network that taught itself a dice game to world-class level, written when most of the modern field did not exist yet. AlphaLudo spent months relearning its hardest question: how to get credit to the right move when the only real signal is who won. For a long time the answer looked like shaped rewards. In the end it was the plainer one: win or lose, spread across the game.
The whole project started here. AlphaLudo borrows the recipe almost wholesale: one network that predicts both the best move and its own chance of winning, trained first by imitating a strong teacher and then by playing itself. If you have never seen the documentary, it is still the best feature-length explanation of why this field exists.
The full recipe (start from a random network, generate self-play games with deep search at every move, distil the search-improved policy back into the network) was parked for compute, not doubted. We tried a shallow version: 2-ply search over the model we were trying to improve, distilled into a student. The student lost 89.6% to 10.4% against its teacher over 25K games. Search over the same network doesn’t make strong enough targets. Test 3 of the ceiling found the same wall from the other side.
Reasoning about a set, such as your four tokens, without caring about their order. One experiment built a far smaller network on it with no convolutions at all. It hit the same ceiling as the bigger models, an early sign that the model was not the limit. The idea came back properly in V13.5 and V15.2, which treat the four tokens as interchangeable.
The reinforcement-learning algorithm in every run. Boring, reliable, well understood, and deliberately left alone: the interesting part of AlphaLudo is what goes into the optimiser, not how the weights are updated.
AlphaLudo V15.2 587K graph transformer · no search
A single-frame graph transformer over the board’s 225 cells. It sees one frame, runs no search, and plays its single best move.
Also used, and worth reading: GAE, the advantage estimator that spreads the win/loss signal (Schulman et al., 2015), and the transformer itself (Vaswani et al., 2017).
13What’s settled, what’s open
Every line here comes from a logged run in the training journal.
Settled
V15.2 is the endpoint for two-player Ludo. Six independent tests say the gap to perfect play is dice, not skill.
History doesn’t help. An eight-turn temporal model won 9.6% against the stateless V13.5; multi-frame graph models tied it.
Search doesn’t help this network. 2-ply lookahead at play time scored 49.8%, a tie.
Shaped rewards were scaffolding. Win/loss only, spread by GAE, beat every shaped scheme we built.
Parked
Full AlphaZero from a random network. Compute-bound, not refuted. The shallow version’s student lost 89.6% to 10.4% against its teacher.
Four-player Ludo. The only lever left that might leave room for a stronger agent. Out of scope for now.
Open
Why V16 got worse. Routing, objective, or architecture? The pre-registered control, plus a third arm with the auxiliary loss switched off, would separate them.
The stacked-token blind spot. Can a cell-based policy learn to tell apart two tokens on the same cell when one is the better move?
Is the third layer needed? In V15.1 it barely moves the policy. A three-layer model has not been trained.
Older interpretability claims about opponent-dependent concepts, until they are re-run on real self-play positions.
14How to cite
If this page is useful in your own work, cite it as:
Sumit Pal. “How a small network got strong.” AlphaLudo V15.2: a 587K-parameter graph transformer for two-player Ludo, 2026. alphaludo.in/research/
BibTeX
@misc{pal2026alphaludo,
author = {Pal, Sumit},
title = {How a small network got strong},
year = {2026},
url = {https://alphaludo.in/research/},
note = {AlphaLudo V15.2, a 587K-parameter graph
transformer for two-player Ludo}
}
The code is open: the engine, training pipeline and journal, and the interpretability studies. Source lines under each figure name the journal entry or interpretability note a claim comes from. Journal entries up to Exp 45 are in the public repository and link from this page; the later entries and the V13.5, V15.1 and V16 interpretability summaries are not published yet, so those citations are plain text for now.