You can share your feedback and strategies for the Summer Challenge 2026 - back track king here
Hi, thanks to codingame for this contest. I wanted to know if this challenge will be accessible in the future?
Hi, in principle, yes, just like with the other competitions.
Rails and soup
My approach is quite similar to what JOiy described (i.e. no-search policy-net during inference, trained via PPO), which you can read here:
Main Differences:
- 77 input planes + 16 scalars, ~135k weights 5bit weight encoding, Quantum aware training QAT
- 6 ResNets instead of 5
- receptive field was only 13x13 for my bot
- 32 channels
- gamma = 1 for the best net
Influence of Coding Agents
Coding agents are very double-edged. I was relying heavily on Anthropic models, mainly claude-opus-5 and claude-fable-5-1. This led to me investing much much less time than usual during a contest. But this combined with the chosen approach also led me to not really engage with the actual game. Usually, I have a lot of ideas to try out and to improve the bot, but this time this was diminished.
Donāt get me wrong, I think what the current generation of LLM-based agents can do is amazing and it would have taken me weeks to reproduce what they are doing in hours. They taught me why my bot was having trouble learning the early game (gamma was too small, so the terminal-only reward didnāt propagate back to the beginning).
However, I think the main downside for me relying so heavily on them is that it encourages me to stop thinking on my own. This also means I stop learning and understanding what we are actually building. As a consequence of me not understanding I can contribute less. I have recently learned that this is called āCognitive surrenderā (see here for example: Cognitive Surrender | AddyOsmani.com)
In a weird way I was both disappointed and super happy that fable-5.1 could not just win the game on its own and still needed me for overall guidance and ideas.
The thing with the soup
One technique that improved my NN enough to beat the gold boss was taught to me by the agents: soup. I was waking up and had the agents work the entire night on monitoring and improving the PPO approach. One prompt I found myself using a lot was
I have to be afk for ~8h. you have my full trust and I give you full autonomy to develop and improve approach further. Make printsure to offload work as much as possible to subagents so that you can keep the overview and protect your own context.
My agents run in a hands-brain-split setup (see Scaling Managed Agents: Decoupling the brain from the hands \ Anthropic) with an egress that only allows very few domains for outbound network traffic so I can still sleep well if I grant so much autonomy.
One morning I woke up and found the TUI full of the word soup. I didnāt know what was going on so I asked the agents and they explained to me that one problem of my training setup is the noise and that is why I only saw NULL results for a long time. However, underlying apparently there was an improvement trend. So what the agent did is taking many recent weight snapshots and averaged per weight. This smoothed out the noise and measurably improved the performance of the net.
I am sharing that here since I simply didnāt know so that others in the future may know as well ![]()
Closing thoughts
Where are my manners? ![]()
Thanks to CG for organizing the contest and congratulations to all the winners! Like always some very impressive bots were cooked.
Let us hope that LLMs stay dumb enough that we as humans still can contribute at least a little bit and the next contest is not a simple ā/goal Win this contest, make no mistakesā ![]()
Ranked 1st
I am an Amadeus employee (explicit in my profile) and it was our former challenge. It was also a perfect fit for a RL pipeline, and I started mine a year before this Amadeus challenge.
Historically, I started with a Muesli implementation (AlphaZero, MuZero, Muesli. The current standard is Muzero, Muesli is one of the numerous variations). Using Ray for the pipeline, without Ray RLib. But I had troubles to fit it inside a CG VM, and I made plenty of simplifications. Eventually, it was the shadow of what it should have been.
Came the snake challenge. My implementation never achieved cooperation, and I ended at low legend. That was the trigger to start a new algorithm, better fit to a CodinGame environment. I chose Q-Learning because of its massive toolbox, starting with the so-standard Rainbow. Eventually, it evolved a lot and my current implementation is almost a BTR (Beyond The Rainbow), with a KataGo network (grid-based, cylindric, size-agnostic). My primary focuses were a faithful implementation of the literature, and multi-actions (my shortcomings during the snake challenge).
No āsearchā: Prediction is the whole purpose of a RL Network (through the Bellman equation). Instead, I spend my extra budget into a more advanced observation. The idea is to suggest strategies to the network, then it decides what is useful or not. Moreover, for tiny networks, width outperforms depth. As I provide long range features, I can prune a few residual blocks for more channels.
My reward is āterminal + delta_delta_scoreā (over turns and players). I reshaped my score in order to have a less delayed reward: āfinal CG score, assuming ink-all, every turnā. The score dominates early game, and the terminal part dominates late game.
On top of the standard state channels (owner, terrain, region borders, ā¦), my observation is a product of adjacency * cells * feature:
Adjacencies (you have access to scipy for these Dijkstra calls):
- Std: Default map
- Alt: With penalty 2*ink to enter a cell (to anticipate the on-going disruptions)
Cells (AC is one desired link, town to town, oriented):
- āBestā cells: cells belonging to at least one shortest path (i.e. the triangular inequality is an equality, AB + BC ā AC = 0)
- āGoodā cells: cells which would be āBestā if I build them: AB + BC ā AC <= cost(B)
- āPathā: the one path, abiding to the priorities. It is a dfs over āBestā using the priorities (I didnāt manage to vectorize that one)
Features:
- āCountā: sum-aggregation of a boolean
- āYieldā: sum-aggregation of (me - foe)
- āStabilityā: 4 - ink, min-aggregated
- āProspectā: Stability*Yield, sum-aggregated
- āUrgencyā: Turns to completion, assuming all-in, min-aggregated
Then, my channels are std_best_count, alt_good_yield, ⦠If you are in doubt, you just send everything, and prune the unused channels afterward. For example, it looks like āGoodā is more useful than āBestā (not intuitive).
My network has two heads: Ink and Build.
-
One ink action is the full zone (mean-aggregated). This head is ādenseā, which means that I compute the Q-Value for all zones and brute-force everything I need afterward.
-
One build action is the whole 3 actions quota. A river counts twice, a mountain thrice. From a mathematical perspective, thatās called āknapsackā. It is theoretically NP-complete, but pragmatically, for such a low quota, you will find easy exact solutions. Cannot be brute-forced as the cardinality is 1~8M valid actions.
And my selection is a simple max. No randomness (in the CG VM), no heuristic, nothing. I just ink the zone and build the selected triplet.
Everything is printable, but still using the standard tricks: minification, encoding, zipping.
Iād like to thank my brother and a colleague who helped me a lot over this project. Their support was invaluable.
And congratulations to the CG team for this original challenge. It is simple and elegant. Maybe not human-friendly because of the scoring, but that also makes it special.
:
: Here is my PM, finished 3rd https://github.com/Pduhard/back-track-king-postmortem
I didnāt know that there are libraries with pathfinding algorithms. Do they exist in other languages too? Could you maybe suggest some article or some public project where I could see how minification, encoding, zipping would look like in practice?
Only for some languages. In Python you have Numpy (1.X with BLAS support. Itās very old, but still superior to anything you can implement from a CG VM, whatever the language. It means float32 for your network. No access to the modern int facilities), Scipy and Panda.
In scipy, you want to use the graph tools (sparse matrices, and graph manipulations like Dijkstra).
For the āminification, encoding, zippingā, thereās no specific trick. When you deliver your code (i.e. out of the CG VM): pickle>lzma>encode(UTF-16). And you do the opposite inside the VM. The code is minified. Itās just a bit easier in Python because most tools are built-in.
look at Red Blob Games. It has everything you need to know about pathfinding
4th place solution
Hi everyone!
First of all, I would like to thank Codingame and everyone I had the chance to talk to during the challenge. The rivalry between the Smurfs and the Gargamels was a lot of fun (although, sadly, Indrill and the Smurf team came out on top!).
Here is my approach :
Step 1 : Build a Graph Neural Network using PPO :
164 778 parameters: a 48-channel, 4-layer message-passing trunk over the grid graph (dilated neighbourhoods, zone edges), with six heads:
- policy : one logit map per action unit (3 rail cursors + 1 disrupt cursor), decoded sequentially under legality masks
- value
- enemy head : predicts the opponentās four actions (cross-entropy under his mask)
- multi-horizon heads : which rails/zones will be active or inked at t+k
- active head : which of my rails will be on an active path at t+5
- a tiny deep-sets leaf distilled from the critic for the search (39 aggregates : value, int8).
My network didnāt start from scratch. I first trained it with behavioral cloning on my best heuristic bot to give it a strong starting point and avoid spending days before getting decent PPO results.
Step 2 : Build a smitsimax search algorithm :
Thatās probably the most interesting part of my post-mortem. Without it, my GNN was around 7th/8th rank in the leaderboard, it added a lot.
One tree per player, one selection per action unit:
score(a) = Q(a) + C_campĀ·āln nĀ·(v+1)^-1 + WĀ·Ļ^dĀ·prior(a)Ā·(v+1)^-0.5, with Q backed up from a leaf = deep-sets critic + simulated revenue over an 8-ply horizon, priors from the policy head (our side) and the enemy head (their side), a root list of the top-6 cells for us and top-16 for the opponent, 32 candidates in depth, with around 1 700 iterations per turn on CG.
Two findings shaped it:
- Part of the search advantage came from self-exploitation. Locally, search versus vanilla looked like a +20 point improvement, but the first ladder results suggested otherwise: my vanilla model was actually better. The search was extremely good at predicting our own network. Making it play against exploiters and tuning the opponent exploration constant (C_ADV = 2.5, later increased as the game progressed) fixed most of the issue and eventually brought the bot to #1 on the leaderboard for about a day (before Indrill crushed us again
). - Restricting our own root list (K = 6) beat wider lists: the networkās top-6 was already good, extra candidates diluted visits.
Credits :
- Before working on this challenge, I tried this PPO + search approach on other challenges, especially Snakebyte, and Sheesh / sZoom helped me a lot on discord to answer my questions. My first PPO used a U-Net architecture, following an approach that Sheesh had successfully used in several previous challenges, before I eventually switched to a GNN.
- Shoutout to the Gargamel team, especially pduhard. We gave it our best shot against the smurfs, and even though we didnāt manage to beat them, the journey was what mattered most !
Hello all, I missed this contest, can you tell me the name of it on ā/multiplayer/bot-programmingā ?
I donāt find it, it on codingame.com, isnāt it āBack Track Kingā ?
Thanks
Itās not yet in multis, probably will be within days or weeks.
Seems it just appeared now⦠pretty precise timing
Hi @Indrill congratulations for your win and thanks for sharing your strategy. I suppose itā a great feeling to see the result of all the efforts youāve made to get here.
Could you share some more information on your path in becoming a CodinGame contest champion. Like what education background you have, which are the top learning resources that made you the best impression, do you have related professional background and so on.
Also could you share your time management strategy for this contest. How much time did you spend on this contest per day/week?
I believe that such information will help us, the other CodinGamers to improve further ![]()
About my profile, I will only state that RL is not part of my professional duties (I would love it). Industry standards are closer to a spaghetti plate.
About the learning path, essentially based on the errors I did:
- The arduous part is motivation: the initial implementation takes a lot of time
- You learn the theory and read the reference papers. The first paper will break the ice and give you confidence. Itās not that difficult.
- You start small and standard
- You have tests. Itās compulsory if you want to move forward.
- AI is your friend, but you need to be careful:
- You must not forfeit ownership of the core engine. You can explain every line.
- You challenge every bug. The AI very easily concludes that your problem is within noise. No, it isnāt
- You ask the AI to link strong reference implementations. Very often, the AI will notice that nobody does it that way, for good reasons.
- You can implement first, and decide after. That requires regular refactoring