Case Study: Back Track King
A hand-written bot finished CodinGame's Back Track King contest in Gold. Five weeks later a self-play network built on top of it ranked near the top of the Legend league, and nothing tried after that moved it further. This page follows the author's lab records in order and turns each step into something to do in your own lab: the measurements that misled, the rebuild from the winners' write-ups, the 917,630 games it took to reach Legend, and the point where live noise was bigger than any gain left to find.
- Check your own lab for the three measurement traps that cost this one days: a yardstick that mirrors to 0–0, maps reused between picking a version and testing it, and a promotion gate that only plays the bot's own ancestors.
- Turn a winner's write-up into a list of testable changes, each credited to the player who described it.
- Read a live score against the spread of identical resubmissions before you decide a change helped.
- Decide when to stop: when the ranks above you are several noise bands away and nothing you have tried has left the band.
01A hand-written bot finishes in Gold
Back Track King was CodinGame's Summer Challenge 2026, a two-week contest from September 7 to 21, 2026. Of the 16,581 people who registered, 1,595 finished on the leaderboard, spread over six leagues: two Wood leagues, then Bronze, Silver, Gold and Legend, where 28 players ended up.[1] Each turn both players get three paint points for laying train track on a shared grid, and one disruption point that pushes a region toward being washed away. A connection between two towns pays each player a point per turn for every piece of its track that player owns, and the higher score after 100 turns wins.[2]
The author entered with a bot written by hand: rules for picking routes and a score for each candidate plan, with no learning anywhere. Everything in this case study grows out of that one file.
From the author's lab
Final contest record, read from CodinGame's API on October 15: the Gold league. The source, 65,978 bytes, was then frozen byte for byte. Every experiment below measures against it, or against something that descends from it.[3]
By the middle of the contest the usual way of testing had stopped working. Every tuning constant in the bot had been chosen by one rule: play the new version against one older version and keep it if it wins. Then a counterplay option, which predicted the opponent's next move with the bot's own logic and played against that prediction, beat the saved older bot 95–5. Against the current default version it went 348–334–2 over 684 games, well within what two equal bots produce. The 95–5 had measured how well the option exploited one old bot's habits.[3]
The replacement was a panel ladder: a round robin in which the current bot, its older versions and a few deliberately different playing styles all play each other on the same 342 maps, in both seats. The results are turned into ratings two ways, with TrueSkill[4] and with a Bradley–Terry fit on the Elo scale. The panel also held a twin, the current bot entered a second time under a different random seed. Any rating gap between two copies of the same program is noise, and over three repeats the twin's gap came out at −2.4, −3.8 and +2.2 Elo.
From the author's lab
Panel ladder, September 16: 12 members, 342 maps, both seats, 45,144 games per repeat. Rule adopted from the twin's spread: a change counts only if it beats the default by more than 15 Elo (about a 52–48 edge) in every repeat, with its 95% interval excluding zero. The panel's first runs found a setting that the old head-to-head rule had rejected, worth +41 Elo on its own.[3]
In your lab: measure every change against a panel of different opponents, and keep a twin of your current bot in it to show the noise floor. A big win against one old version can be a gain against that version alone.
Covered in: Measuring Bot Strength (panels, the twin, and strength that isn't transitive).
02Three learners and a 61% that meant nothing
When the contest closed, Back Track King stayed open as a permanent multiplayer puzzle and the bot kept its place in Gold: since 2020 CodinGame has moved every contest's players into the permanent arena in their own leagues.[5] The first attempts at machine learning, from October 10 to 13, all built on the hand-written bot.
That bot already proposed a shortlist of candidate plans every turn and scored them. The first learner was trained with PPO, the self-play method taught in Self-Play Reinforcement Learning, to re-rank that shortlist. The second read the board through route features taken from the winner's write-up and started as a copy of the hand-written bot. The third was a Q-learner, which learns a value for each possible action instead of a probability, and it went back to re-ranking the bot's own plans.
From the author's lab
October 10, PPO re-ranking the bot's own plans. After 310 iterations and 4,960 games, the two learners scored 48.5% and 51.0% of the points against the original on 100 fresh maps in both seats; both intervals included 50%. Learner A had looked strong on the 12 maps it was picked on, 18 wins, 2 draws and 4 losses, and lost that edge on fresh maps.
October 11, a network with the winner's route features. It matched the hand-written bot's choice on 41.5% of held-out decisions and had trained with PPO for only 12 games. Against the original on 64 fresh maps it won 4 games and lost 124.
October 13, a Q-learner re-ranking the bot's plans, after repairs. 1,167 wins, 166 draws and 715 losses over 2,048 games on 1,024 fresh maps: 61.0% of the points. It was promoted.[6]
The 61% came from the yardstick. Two copies of the hand-written bot see the same map and, because the bot is deterministic, paint the same cells on the same turns. The rules make a track that both players place on the same cell in the same turn neutral, and neutral track pays nobody, so the original against itself ends 0–0 every time.[2] That's a . A near-copy that changes a single placement owns track the original doesn't, so it wins. Against an aggressive and a defensive variant of the same bot, the network that scored 61% showed no gain.[6]
A common question at this stage: you've read how first place did it, so why isn't your bot improving? Here the answer had two parts. The design was capped. Two of the three learners could only reorder plans the hand-written bot had already proposed, and the one that scored 61% was a network of about 17,700 adjustable numbers doing exactly that, so it could never find a move the old bot wouldn't consider. And the benchmark was broken: its one opponent couldn't tell a stronger bot from a different one. Ideas from the winner's post couldn't show up in the results until both were fixed.
In your lab: play your original against a copy of itself before you trust any score against it. Check that it measures .5 with draws counted as half a point, and look at how it gets there: if every game is a 0–0 draw, your game mirrors, and any near-copy will beat the original without being stronger. Keep score against other opponents too, and give a learner the full board instead of your old bot's shortlist.
Covered in: Measuring Bot Strength (the mirror), Neural Networks for Game Bots (what the network sees), When to Use Machine Learning.
03The rebuild from the winners' write-ups
After a contest many of the best players write up how their bots worked, in a on the forum or on GitHub. The Back Track King write-ups described a different design from the lab's: a network that reads the whole board and makes every one of a turn's decisions itself, trained by playing against copies of itself.
On October 13 and 14 the lab rebuilt its pipeline around what those write-ups said. Only the prose was used: no other player's code, weights or training scripts were read.[7] Each borrowed idea became one component with a check of its own. The table credits each idea to the write-up it came from, with the corrections a careful reading needs.
| Idea | Credited write-up | What the lab built |
|---|---|---|
| A fast simulator that matches the official referee exactly, running many games at once | Pduhard (3rd)[8]; JOiy (13th)[9] also trains on 512 games at once | A Rust engine: 2,540 official-referee games, about 210,000 turns, zero mismatches |
| A convolutional network over the whole board, with an average of every channel added back to every cell | JOiy calls it a "board summary"; Pduhard calls it "KataGo's global pooling", and Indrill (1st) built "a KataGo network"[10] | A residual network of 104,820 parameters as exported, reading 62 input planes |
| A turn as three placement slots plus one disruption slot, decided in order | JOiy; Pduhard and RamzaBeoulve (4th) describe the same split | The network's decoder |
| Route planes: the best, good and path cells for each connection under two cost maps | Indrill | 30 of the 62 input planes |
| Start from a clone of a hand-written bot | RamzaBeoulve[11] | Behavior cloning on 12,000 games of the author's bot and two variants of it |
| PPO self-play with 512 games at once, half of them against past versions, drawing the ones that beat you more often | Pduhard | The trainer's opponent pool |
| A penalty for drifting from the starting policy, and held-out maps for every gate | JOiy | Anchor weight .02; validation maps never used in training |
| Reward: the result plus a running estimate of the final score | Indrill: "final CG score, assuming ink-all, every turn" | A projected-score reward, the lab's own reconstruction (no write-up gives a formula) |
| Average many checkpoints | Pduhard (averages of hundreds); putibuzu ("soup")[12] | An exponential moving average of the weights, a variant of their uniform averages |
| Train through 5-bit quantization | putibuzu | 5-bit quantization-aware training |
| Compress the weights into the source file | Indrill: pickle, then lzma, then UTF-16 | An adaptive range coder; the first export was 98,673 characters |
Some terms from the table, in one line each. Behavior cloning trains the network to predict the hand-written bot's moves, so self-play starts from a competent player. The anchor is a KL penalty that grows as the network's move probabilities drift away from the clone's. Quantization-aware training lets the network practise with its weights rounded to the 5 bits they are shipped in, and the range coder squeezes those weights into a source file under CodinGame's 100,000-character limit.
The write-ups don't agree on everything, and a rebuild has to choose. The winner, Indrill, didn't use PPO at all. He trained a deep Q-learner, in his words "almost a BTR (Beyond The Rainbow), with a KataGo network", and played its top choice with no search: "my selection is a simple max".[10] Pduhard, RamzaBeoulve, JOiy and putibuzu describe PPO, and the lab used PPO. On rewards, Indrill trained on the result plus a per-turn estimate of the final score, Pduhard paid the income gap of each turn, plus 30 to the winner and minus 30 to the loser at the end, and JOiy reports that "The reward that produced every good bot is terminal-only", the result and nothing else.[8][9] On search, Pduhard's small search on top of his network won 0.839 of its games against the same network without it, while RamzaBeoulve found that part of his search's local gain was "self-exploitation": the search predicted his own network too well. Locally it looked about 20 points better than his plain network, but his first ladder results favoured the plain one, until playing against exploiters and retuning fixed most of the difference.[11]
In your lab: write each claim in a write-up as a change you can test, with the player's handle next to it. Where write-ups disagree, test both sides on your own panel. Read the prose and leave the code alone.
Covered in: Learning from the Leaderboard, Referees and Simulators (the bit-exact engine), Behavior Cloning, Self-Play Reinforcement Learning, Shipping a Network in 100,000 Characters.
04917,630 games to a Legend network
The rebuilt pipeline ran overnight from October 13 to 14 on one desktop GPU, starting from the clone. Training moves in iterations: in each one, 512 games advance 32 turns, then the network updates on what happened in them.[7] By the next morning the network had beaten every fixed opponent the lab owned.
From the author's lab
Iteration 3,350, reached after 917,630 self-play games (82.4 million training samples) and 11.7 hours on one RTX 3080 Ti. Against the official referee, on 256 maps it had never seen, in both seats: 500 wins, 0 draws and 12 losses against the hand-written bot; 500–0–12 against its aggressive variant; 504–0–8 against the defensive one; 508–0–4 against the October 13 Q-learner. Its export took at most 28 ms a turn locally, against a limit of 50 ms.
The author reported that this network reached Legend on the permanent ladder. The first Legend ranking in the records is from October 19, for the network from iteration 23,750.[13]
The 500–0–12 lines don't say where the network would rank. They say it beat every fixed yardstick the lab had, on fresh maps, from both seats, which is the evidence worth having before a first submission. How many games that takes depends on the game. This one needed about 900,000 games, roughly half a day on one consumer GPU, for the first network the author reported in Legend; treat it as one data point.
In your lab: before a first submission, beat every fixed opponent you have on fresh maps from both seats. Write down how many games and hours it took, so the next contest's budget starts from a number instead of a guess.
Covered in: Self-Play Reinforcement Learning (how many games), Building the Trainer (games per hour, checkpoints).
05Better at home, worse on the ladder
Training kept running from October 14 to 24. Every 50 iterations the current network played the reigning champion on held-out maps, and a candidate that beat it by a clear enough margin took its place: 101 promotions in all. Each promotion said the network had beaten its own recent past. None said anything about the six players at the top of the Legend league.
From the author's lab
Live games against the six strongest Legend players, ranked battles and test games pooled on October 24: networks from iterations 25,850 to 42,800 scored .37 of the points (198 games), 47,250 to 55,000 scored .49 (305 games), and 58,700 to 71,100 scored .35 (244 games).
The 71,100 champion scored .53 against 47,250 in 800 local games (400 maps, both seats). Live it finished 0.98 points below the lowest run of 47,250, and in its ranked games against the same opponents 47,250 had faced it scored 0.13 points per game less than 47,250 (p = .031, before correcting for the four such comparisons made).[14]
That pattern is . Every opponent in the gate was a past version of the same network, so a promotion meant the new network had found a way to beat its ancestors, which can come from exploiting their habits as easily as from playing better. DeepMind's AlphaStar paper describes the same trap: self-play "may chase cycles (for example, where A defeats B, and B defeats C, but A loses to C) indefinitely without making progress".[15] The players at the top played styles the lineage never met. Replaying 1,223 recorded live games through the engine showed some of them: in its first five turns Indrill put 63% of its track in town regions that can't be disrupted, against the lab's 52%, and in turns 0 to 9 it hit regions holding the lab's scoring track 28.5% of the time, against 10% the other way.[14]
A common request at a plateau is to read the research papers and find a better way to train. It was tried here. On October 23 a review of 21 papers, on reward shaping, league training, population methods, distillation and quantization among others, turned into eight follow-up experiments and a 149-stage campaign to run them. The campaign would have taken about three weeks and judged every result locally, against the same lineage, so it was stopped before any of its stages ran. The two experiments that did run, each compared with an unchanged control on 512 maps, found nothing: giving 15% of the games to frozen champions moved the points by −.008 (95% interval −.038 to .022), and a lower learning rate by +.018 (−.013 to .049).[14] The table lists everything tried in the plateau's last days. Nothing that reached the ladder scored above the noise band of the next section. Live results in the table count points from the bottom of that band.
| Change tried, October 23–26 | Result |
|---|---|
| 15% of training games against frozen champions | −.008 points against the control; interval includes zero |
| A lower learning rate | +.018; interval includes zero |
| League fork: 40% of games against four frozen champions | Live +0.69 and +0.28: inside the band |
| A reward on the per-turn income gap, the signal Pduhard trained on | Live +0.46: inside the band |
| The same reward with a smaller weight on the final result | Live −1.20: below the band |
| A one-turn search around the 47,250 network | Live +1.23 (the best rank) and +1.20: inside the band |
| An exploiter trained only against 47,250 | Found nothing: .46 to .51 against 47,250 |
| Cloned stand-ins of the top players, as local opponents | Agreed with the real players on 7–12% of turns; ranked the lab's networks unlike the ladder did |
| Distilling the search back into the network | Agreement with the search rose from .11 to .20, but the network played worse |
| A Q-learning fine-tune of the network | Failed its pre-registered local rule |
| Sampled instead of greedy moves | Within noise |
| A wider network, 48 channels instead of 32 | .44 to .46 against 47,250 when it was stopped |
Papers supply ideas, and an idea from a paper is a hypothesis like any other. What limited this lab was measurement: the local tests could only compare the network with its own past, and one live submission could only resolve differences of about a point. Every idea in the table ran into one of those two limits.
In your lab: keep strong outside opponents in your gates, either frozen copies of bots that play differently or the ladder itself through a pre-registered live panel, and read a promotion as "better than my own past" and nothing more. Test an idea from a paper on the same panel as everything else.
Covered in: Measuring Bot Strength (gates and live panels), Self-Play Reinforcement Learning (opponent pools and drift), Learning from the Leaderboard (fingerprints from replays), Networks Inside Search (the one-turn search).
06Six submissions of one bot
From October 24 the lab used the ladder itself as the test. A submission plays about 154 ranked games in 30 to 60 minutes, and its final score is a direct reading of how it does against the real field. To know what a difference in that score means, you need to know how far it moves when nothing changes. Between October 22 and 26 the same network, iteration 47,250, went up six times.
From the author's lab
Six submissions of identical 47,250 code, scored in points above the lowest of them, finished in order at +1.62 (the author's reading of the first run near its peak; no final was recorded), +0.78, 0, +0.28, +0.28 and +0.67. Range 1.62 points, mean +0.6, all six near the top of the Legend table. A seventh run stood at +0.82 with 32% of its ranking games played when work stopped.[16]
That spread is the for one submission of this bot: a single live score resolves differences of about a point, and the ranks inside the band shuffle by luck. The widget puts every scored submission of that week against it.
A question that comes up near the top: the bot is a few places from first, so is there anything left to tweak? In this lab, nothing that could be measured. No change of the last three days scored above the band, and the version with the best rank, a one-turn search at +1.23, sat inside it with the rest. Whatever the late changes gained was smaller than the band, so no single submission could show it.
And the question behind every resubmission: realistically, is there any chance of moving up, and what are the odds the new version is actually better? Compare the gap with the band. During October 24 the three players just above the lab's bot scored between +1.17 and +1.36, inside the band, so luck alone could reorder them.[14] On October 26 the two players at the top, Indrill and gaha, sat about 7 and 4 points above the band's top: several band widths. A resubmission can swap places inside the band. Closing a gap of several widths takes a stronger bot, and nothing tried in the last ten days had produced one.[16]
In your lab: before you resubmit to test a change, submit the unchanged bot a few times and write down the spread. A single live score that lands inside it is no evidence either way. For a smaller difference, plan a live panel: the same opponents and seeds for both versions, with the pass rule written down first.
Covered in: How Bot Contests Work (how the ladder rates you), Measuring Bot Strength (live panels).
07The decision to stop
All Back Track King work stopped on October 26. By then the position fitted in three numbers: identical code spans 1.6 points, every version submitted since October 19 landed inside that span or below it, and the two players above sat 4 and 7 points over its top.
The first number says the ranks near the bot are decided by luck. The second says that ten days of changes, several of them wins in local tests, hadn't produced a better bot on the ladder. The third says the ranks above call for a different bot, and tuning this one had stopped producing gains. None of the three gets better with another week of local tests. The last submission, a seventh run of 47,250, was left live, and the bots, records and training state were kept so the work could resume.[16]
The lesson for your own lab is about timing. The lab's rule for stopping came at the end, after days spent measuring which of two nearly equal bots was slightly better. Write yours before the campaign starts, in the same terms the records use: for example, stop when three pre-registered variants in a row land inside the identical-code band, or when the next rank you care about is more than twice the band's width away and nothing has left the band in a week.
In your lab: write the stop rule down before you start, and when you stop, leave the best-known bot live and record why.
Covered in: Capstone: Build the Lab (the live loop and when to stop).
08Mistakes the records make visible
Each of these cost the lab time on Back Track King, and each has a check you can run in an afternoon.
09What's next
Back Track King is the lab's network story. By the end of October 30 the lab had played nine CodinGame games and reached Legend in eight of them: three with self-play networks (Back Track King, Fantastic Bits and Spring Challenge 2022) and five with search or rule-based bots.[17] Case Study: Five Legends by Search covers those five, one game at a time, with the post-mortems each one drew on, and the games where search stalled.
10Sources
First-hand numbers come from the author's lab records, which are private; each note names the files. Leaderboard figures are dated, because they change.
- CodinGame, 2026. Back Track King (Summer Challenge 2026), contest page and final leaderboard. Dates (September 7–21, 2026), 16,581 registrations, 1,595 ranked players, six leagues, 28 in Legend; read on 2026-10-30.
- CGjupoulton, 2026. SummerChallenge2026, the official referee and statement on GitHub. The rules: three paint points and one disruption point a turn, neutral track when both players build on one cell in the same turn, 100 turns; the referee the lab's engine was verified against.
- Author's lab records, 2026 (private repository). Contest-era measurement:
PANEL_LADDER.mdandIMPROVEMENT_REVIEW_20260916.md(contest repository); final contest record inAGENTS.md(October 15 API check) anddocs/provenance.md. - Ralf Herbrich, Tom Minka, Thore Graepel, 2006. TrueSkill: A Bayesian Skill Rating System, NIPS 19. The rating model the panel ladder used alongside Bradley–Terry.
- [CG]Thibaud, 2020. Competitive CodinGame Is Back with a Bang, CodinGame blog (Internet Archive copy). Since 2020, contest players move into the permanent multiplayer arena in their leagues when a contest ends.
- Author's lab records, 2026 (private repository). The first learners:
experiments/selfplay-20261010.json,winner-training-20261011.json,decision-repair-20261013.json, and the October 13–14 review inAGENTS.md. - Author's lab records, 2026 (private repository). The rebuild:
docs/provenance.md(sources read, ideas borrowed, no third-party bot code),docs/nn-training.md,experiments/runs/nn-main/config.json, and the engine verification noted inAGENTS.mdandREADME.md. - Pduhard, 2026. back-track-king-postmortem (README), 3rd place. PPO self-play with 512 games at once and a pool of past versions; the income-gap reward with ±30 at the end; checkpoint averaging; KataGo's global pooling; a small search worth a 0.839 win rate against the same network.
- JOiy, 2026. JOiy's bot: Summer challenge 2026 (GitHub gist posted by tcordel; Legend, 13th on the leaderboard). The whole-board network with a pooled "board summary", the KL anchor to the starting policy, held-out maps for gates, and terminal-only reward.
- Indrill, 2026. Post #5 in "Summer Challenge 2026 feedback & strategies", CodinGame forum, 1st place; and post #8. Deep Q-learning ("almost a BTR") on a KataGo-style network, no search, route planes, the projected-score reward, and weights packed with pickle, lzma and UTF-16.
- RamzaBeoulve, 2026. Post #10 in the same thread, 4th place. Behavior cloning from his best heuristic bot as a warm start, and the warning that a search tested against its own network overstates its gain.
- putibuzu, 2026. Post #4 in the same thread (20th on the leaderboard; he states no placement). 5-bit quantization-aware training and averaging many recent weight snapshots, which he calls soup.
- Author's lab records, 2026 (private repository). The main run:
experiments/runs/nn-main/metrics.jsonl,evaluations.jsonlandstatus.json; the October 14 final test inexperiments/nn-final-20261014.json; the October 19 ladder check inexperiments/h2h-20261019.json. - Author's lab records, 2026 (private repository). The plateau:
experiments/live-submissions/summer-challenge-2026-back-track-king/comparison-20261024.jsonandopponents-20261025.json; the live screen underexperiments/live-tests/summer-challenge-2026-back-track-king/screen-20261024/;experiments/plateau-research-20261023.json,research-campaign-20261024.jsonandruns/plateau-ab-20261023/assessment.json; the October 24–26 entries inAGENTS.md. - Oriol Vinyals et al., 2019. Grandmaster level in StarCraft II using multi-agent reinforcement learning, Nature 575 (author manuscript). Self-play can chase cycles; league training against a mixture of past opponents.
- Author's lab records, 2026 (private repository). Live submissions:
experiments/live-submissions/summer-challenge-2026-back-track-king/submitted.jsonlandevaluations-20261024.json; the stop on October 26 inAGENTS.md. - Author's lab records, 2026 (private repository). The nine games:
experiments/live-submissions/*/rankings.jsonland the October 30 entries inAGENTS.md.