Spring Challenge 2026 (Troll Farm) - Feedback & Strategies

Yes, it should be available in the multiplayer bot programming section in the next few days.

1 Like

Absolutely impressed by @delineate— definitely a well-deserved 1st place.

#8th Legend

Thanks to TrollerPact and codingame for the contest. This was one of the most enjoyable CG games I played: many viable strategies, new disruptive tactical ideas almost daily, and enough chaos to make it engaging right up to the last hour. I have to admit I invested way more time than I expected in this challenge, especially during the last few nights.

Bot was written in Rust. I would describe it as a mission-based planner with task-level lookahead, a lot of map classification, and strategic choices that influenced both training investment and tactical play.

## General strategy

The final bot had three main profiles:

  • **Max Build-Up**: the default economy mode. Train, build a local fruit/banana engine, then convert into wood/score.

  • **Hard Disruptor**: used mostly on tight contested maps with good iron access. On those maps, if the opponent could also get chop power quickly, a normal build-up setup was vulnerable.

  • **Resource Raid**: a selective raid mode. I am not very proud of this part, but it worked well against farmers/builders on maps where their build-up usually depended on planting lemons near the shack. The goal was to disturb that setup before it became stable.

The selector was based on map shape: shack distance, contested resources, fruit access, iron access, opponent lemon access, and some opponent-signal ideas, trying to infer whether the opponent wanted to play a build-up style or a more aggressive chopping style.

The bias was to keep the same strategy end-to-end once selected, because switching between styles was hard to optimize due to different training goals and role profiles. Still, I needed fallback logic to move from build-up into harder disruption on maps where I could not build a good setup because of enemy pressure.

## Design

The bot was built around missions.

A mission was something like “harvest this tree and bring the fruit home”, “chop this tree and drop the wood”, or “collect the missing resources for the next training”. Jobs were evaluated with completion time and projected payoff.

After selecting the best individual jobs for each troll, I used a small DFS assignment step to pick the highest-scoring compatible set of jobs for the whole team.

I experimented with beam and GA. They never became the main bot. While the design felt promising initially, optimizing mission plans over a long horizon often produced “fantasy” scenarios: plans that looked good according to the scoring function, but were too brittle once collisions, opponent interference, training delays, and small tempo losses appeared in the real game.

##Training

Training was mostly hard-coded,The bot estimated whether key resources were reachable fast enough and adjusted the macro plan when the next troll no longer looked realistic.

A lot of bad games came from staying in “train rush” behavior for too long. Once training became hopeless, the bot needed to immediately switch into building/scoring mode instead of continuing to pick resources for a train that would never happen, or would happen too late to have good ROI.

## Banana / wood economy

The late-game economy was mostly about turning renewable fruit into wood, building a banana engine near the shack: harvest bananas, replant them on good nearby cells, keep enough trees alive to sustain the loop, chop surplus trees when the wood ROI was better than keeping them as fruit production, and eventually go into full cash-out mode.

A lot of time went into tuning the engine: maintaining enough banana trees to keep production alive, deciding when to switch from harvesting/replanting to chopping for wood, assigning planter/harvester/chopper roles, and preventing 4-5 trolls from blocking each other around the shack.

This part was probably over-engineered. I even built a small sandbox to simulate better ways to build, sustain, and cash out the banana engine. But it was also the most fun part to play with. Many improvements came from watching replays and noticing trolls wasting tempo.

## Workflow

Tooling-wise, I had a local Rust referee for speed, which was extremely useful for iteration. I also kept a set of sparring partners derived from my own current bot, but locked into different styles: economy-only, hard disruptor, resource raid, previous submissions, etc. This helped avoid optimizing only against one opponent’s personality and made regressions much easier to spot.

Congrats to everyone, and thanks again to the organizers.

8 Likes

3rd - Legend
Here is my postmortem : https://www.yannmoisan.com/spring-challenge-2026-postmortem.html

9 Likes

Congrats to the winners!

The podium has been added here: https://www.trollerpact.com/

I had fun testing this challenge and working with @eulerscheZahl and others on the problem. Thanks to CG for making this contest possible! :smiley:

4 Likes

Finished at #23.
I pick a random troll and generate 2 macro actions (e.g. move to a cell and plant there), with some bias, for instance planting on cells close to shack/water is more likely. The game then gets simulated with a depth of 15 turns. Here I also generate move actions for the next turn resolve movement collisions on the fly, over and over for every new plan I try. If the score improves, I keep the actions. Repeat assigning random tasks to a troll until I run out of time.
TRAIN is hardcoded regarding the amount of trolls I want to train as well as their skills (having a lower bar, but allowing for stronger trolls if the starting resources are high enough). The best plan gets saved and is used as the initial solution in the following turn. And that’s what I had before the contest started, about 900 lines of code.
During the contest I spent another 5 hours or so analyzing replays and tweaking the scoring function, but my final submission is still close to testing code, with some modifications:

  • reward trees of each type close to the own shack, but with less weight for each additional tree
  • keep palms next to shack alive in late game and have dedicated planter trolls
  • change minimum talent requirements for TRAIN, initially I didn’t go for carryCapacity = 4
  • some detection of an aggressive opponent to TRAIN sooner, as it would get hard to train at all otherwise.

Diff says that I removed 61 lines and added 110, compared to Default AI.

Probably some more potential with a better crafted scoring function, but I felt like I shouldn’t climb any higher on the leaderboard and let those without an unfair advantage battle it out.

6 Likes

Thanks for the awesome write-up !

18-27 own troll: movement, carry cap, harvest, chop, carried resources

I’m guessing these are the active troll’s stats & inventory for which you’re running inference ?

If so, which opponent troll do you keep in these next channels ?

28-37 same for opponent troll

Edit: I think I got it after posting the question, you’re actually describing the entire team for each player but setting the values to 0 if a troll is not present in the cell

Observation Planes (104 x 11 x 22)

That’s 104 channels for each cell on the grid. And while each cell only knows its own trolls, the network as a whole has full information of all trolls, trees, …

Yes, exactly right. And then the active troll plane tells the network which troll is the one we’re querying right now.

In earlier attempts I had tried other things, like running one inference for all trolls and having all the different movement actions in each troll’s output cells. That also sort of worked, but it seems to have trouble with some basic path finding. Given I was using so little time of the 50ms and had decided I probably wasn’t going to try any search, I then went to this architecture. It still has some trouble with basic path finding at times.

24th - Legend

First of all, thanks to all organizers for the great contest.

Approach

My approach was to use a genetic algorithm (GA) to find a sequence of tasks (harvest, chop, plant, mine) that maximizes an evaluation function. There are two distinct phases: training and “normal” phase.

Algorithm

The GA itself is relatively standard - tournament selection, steady-state population, mutation and crossover.

An individual is represented by a sequence of tasks for each of my trolls (n_trolls x n_tasks, with n_tasks = 6). There are four possible task types:

  • Harvest <tree coords>
  • Chop <tree coords>
  • Plant <coords> - here I use a precomputed list of candidates rated by distance to my/enemy shacks and being next to water
  • Mine - this always mines the ore closest to the troll

Drop action is hardcoded and done if inventory capacity is full. Movement and pathfinding is handled during simulation.

Harvest and chop actions - apart from existing trees - can use coordinates of a tree that is going to be planted. This is supposed to allow the bot to take into account future resource gain from a planted tree. I’m not sure whether it’s a good idea, but it worked well in a few cases.

Mutation is done by changing a task to a random one or by swapping two tasks with each other. This is applied to every task in a sequence. I used an uniform crossover - each task is selected randomly from either parent.

The population is persisted between turns, if I don’t train any trolls. Past individuals are fixed - actions that are now done/invalid are removed and replaced with random ones. I also try to detect and ignore some invalid/noop actions during simulation.

Evaluation

Individuals are scored by running game simulation - 50 turns during training and 20 otherwise - and then evaluating the game state. Evaluation function depends heavily on the game phase:

  1. During training the aim was to train 2 trolls with hardcoded stats as quickly as possible. Thus evaluation takes into account number of required resources, turns to train the troll, and penalizes no lemon and plum tree near the shack.

  2. After training I evaluate discounted score, troll inventories and trees on the map - by distance to my and enemy shack, and by being next to water.

During simulation I use a basic opponent model - if the troll is close to my shack and on top of a tree I assume he will be chopping it. I don’t assume any other opponent’s actions, like move or harvest.

As I couldn’t quite make fully planting bot to work the resulting gameplay is quite aggressive - it tends to steal trees from other players, which works well when the enemy is close, but is problematic when he’s further away.

Another limitation is having just 3 trolls - looking at the statistics I’m the highest ranked player who does that - better bots either aim for 4+ trolls or use only 2.

6 Likes

Legend - #6 - C++

There’s 2 phases HARVEST/TRAIN then PLANT/CHOP (mostly banana trees).

Training is hardcoded for 4 trolls (with round limits). As well as the number of trees needed close to the shack for each type (especially lemon, to increase the score faster).
Each troll has a purpose harvest/plant or chop (it can change as the round increases).

Each turn I search a solution with 2 components :

  1. A role for each troll : HARVEST , PLANT_FROM_SHACK_SEED , PLANT_FROM_HARVESTED_SEED (for each fruit type), CHOP_TREE_AT , DROP , MINE , STEAL_OPPONENT_CHOP (which is chop a tree being chopped by the opponent, except all the trolls can do it).
  2. A priority order (id5 executes its move first, then id1…) to handle cell’s conflicts.

Then, for each board state, 2 functions are applied :

  • The first constructs a real move from the role (find and cache the best target for harvesting, planting…)
  • The second constructs the next round move, avoiding cell conflicts. The priority order is applied (so a “harvesting move” can be changed into a “moving move” if a troll with a highest priority has already moved to its cell). DROP are done first (to avoid a troll blocking the shack by harvesting/dropping next to it).

The simulations go on until all the roles are done. Then the board is evaluated.

So first I find the best roles in the natural order. Then for the remaining time I switch roles, try randomly other role… (each time the score for all the possible priority permutations is computed to find the best one).

There’s some additionnal heuristic tweaks :

  • If the opponent destroys our plants during training => stop planting them
  • During chopping, keep a banana tree close to shack to harvest.

Thanks to CodinGame and all the codingamers who made this contest possible. It was cool, fun and different.

PS: I miss Fog Of Wars :grin:

8 Likes

Here is my post-mortem for my alter-ego trlr1990, which I nerfed late on Sunday evening.

6 Likes

Legend - #21

Approach

A state machine with different roles based on stats. Mainly heuristics, I use simulations on first turn to find best TRAIN profiles.

Strategy

Two different strategies: quick chop and banana farm

  • The first one is used on small maps or maps with trees very far away. The goal is to quickly train a troll and CHOP trees aggressively. The first troll plant all fruits from the shack and chop in a loop (day one strat before map generation fix)

  • Banana farm: I try to TRAIN 3 trolls, then I use 2 trolls to PLANT and 2 trolls to CHOP. The PLANTER prioritizes bananas because they are easier to CHOP.

End game : every trolls CHOP the map

Code

The code is a state machine with different roles: HARVEST, HARVEST_IRON, PLANT, CHOP, etc. When a troll has a goal, it reserves the cell and tries to stick with it unless an opponent tries to CHOP a tree too close.

The state machine differs depending on whether I use the Farm strat or the Aggressive strat. Roles are determined mostly by stats. My first troll will HARVEST then PLANT, whereas the second trained troll, with better stats, will harvest iron because he can carry more.

Reacting to the opponent

I have a few heuristics to change scoring functions if the opponent is aggressive. My trolls will PLANT a bit further from my spawn if the opponent steals my trees.

First turn

On big maps, I simulate 300 turns with different TRAIN profiles to find the best combination. If the iron is too far, it is better to have less chop power, etc. Then I use it for the rest of the game.

I didn’t have time to use the simulation during the game to improve decision-making.

Work process

Watching replays to see what went wrong, like in an RTS game. No local simulation. Claude Code helps me write quick and dirty code.

Conclusion

A very good challenge, so fun to watch the different strategies.
Congrats to the winners ! Thanks a lot to eulerscheZahl and CodingGame for the challenge.

7 Likes

My best result so far: 132th of 2022 players (63rd Gold)

When I participate in a contest I pursue two main dreams of mine: Reaching Legend league and/or top 100.

This time I was so close…

First I tried training 4 trolls as fast as possible, then start chopping the closest trees to the enemy shack. This worked quite well.

Then I decided to try to build economy of trees around my shack and then attack.
With this strategy I was promoted directly in the silver league when it was opened. From the replays I saw that the top player @FinkPloyd was using similar strategy. I’ve asked him for an advice and he was kind enough to respond and told me that he finds the best paths for the trolls to their targets one by one, to prevent collisions. I’ve added such logic for my bot. And this boost me to the 23rd place! My excitement went over the roof, for first time I saw double digit place during a contest.

Then the aggro strategies came and I wasn’t able to hold my position. I tried to implement aggro bot myself, but I failed miserably.

For first time I didn’t drawn in implementing Game State simulation and testing future moves. I relied entirely on pure heuristics. Which seems suitable for this contest. Using Claude Code I was able to iterate quickly different ideas, but I haven’t managed to dive and polish the strategies. Also for first time I was able to setup cg-brutaltester, psyleague and cgarena and I enjoyed using them.

I consider the whole experience a success even though I wasn’t able to accomplish a dream of mine… https://www.youtube.com/watch?v=oJH5AsNr_nM&list=RDoJH5AsNr_nM&start_radio=1

4 Likes

Many thanks to the creators and to codingame for this great game !

My best result in a challenge up to now. A little bit disappointed the last minutes to have been ejected from the top100. But I finally reached Legend today without submitting anything else.

My strategy was to create 2 specialized trolls : 1 to harvest and 1 to chop.
Then :
Chopper troll targets enemy part.
Basic troll (starting troll) plants and chops near my base.
Harvester troll becomes a basic troll as soon as there is enough fruits in inventory.