Spring Challenge 2022 - Feedbacks & Strategies

Legend 158

Thank you to CodinGame for running this competition! I’ve been looking forward to this for a year.

My strategy was to gather resources close to the mob spawn locations for the first 50 moves of the game and then switch to one defender and two attackers.

My defender would run simulations 12 moves into the future to decide whether a mob could be killed or whether WIND was needed. There was also some logic for self-shielding, for forcing enemies away, and for attempting to eject mobs off the map if there were too many of them. My heroes would move to an intercept location when heading towards a mob to minimize the number of turns it would take to attack it. This worked even if the intercept point was after the mob was redirected upon entering my base.

My attackers would seek to redirect 4 mobs to the edge of the enemy base and then WIND plus double WIND them into the enemy base as quickly as possible. I had my bot output some graphics locally while I was building this which I think illustrate the math nicely. Basically for each mob I looked to see if there was a point on a circle 2200 pixels (WIND distance) from the mob that was within 2700 pixels (2200 * 2 + 300 or guaranteed damage distance) of the enemy base and also within 1280 pixels (WIND spell radius) of at least 2 of my heroes. Since this results in a line, I’d pick the point closest to the edge of the map. This allowed me to guarantee a goal so long as my opponent didn’t interfere.


Overall this was a very fun competition. The thing I liked least is how overloaded the servers seemed to constantly be throughout the competition, and especially during league promotions. I know servers cost money and the competition is free, and I don’t know how scalable CG’s infrastructure is, but in the future I’d love to see more computational power even if it means crowdfunding the costs or bringing on corporate sponsors.

This game wasn’t deterministic and didn’t have perfect information, so I wasted the first 5 days trying to build a search using several different algorithms. The more I replaced searches with heuristics, the stronger my bot got. Congrats to anyone who placed well with a true search.


Hello all. I just write to thank CodinGame for hosting again a bot programming contest. The long submit times proves bot contests are really popular :wink: It was very fun and I greatly appreciate CG for hosting it and I hope you keep doing a couple of this a year.

Nothing special about my bot. I ended up bottom legend with a heuristics bot, strategy similar to yamo, but the devil is in the details. I am glad i made it to legend a little while after it opened, i’ve suffered the gold boss in previous contests and it’s so frustrating ! I coded the game engine and wanted to try a smitsimax or GA but didn’t have time to do so.

I see many C++ at the top legend so I assume sim searches ended up winning, but heuristics bots also did very good and dominated during most the event.

Thanks again and I hope to see you all in the next contest.


Language: C++
League: Legend
Rank: 256

I have two defenders and 1 attacker. In the first 40 turns, the attacker is just farming mana, and after that he goes to patrol the outskirts of the enemy base trying to WIND in monsters and once they’re in, shield them (avoid shielding a monster if there already is another shielded monster within 800 range of it). That’s really it for my attacker.
For my defense, I just send my heroes to fight the nearest threat.
I use WIND incase the mob is about to score or to counter a predicted wind from the opponent.

When a hero selects a monster as a target, he will look in a radius of 800 around the target to see from which spot it can hit most monsters while still hitting it’s target.

If a hero wants to hit a monster and it doesn’t need to move in order to do so, it checks to see if it might be useful to cast a spell at another monster/Hero (CONTROL or SHIELD).

It was a lot of fun, and I finally reached Legend for the first time. Thanks for organizing it, already looking forward to the next one!


#73 in legend.

My bot was just a crap heuristics with 2.500 lines of code… 2 defenders and 1 attacker…

But my PM is not about strategy, but about feedback…

The publish at the last 3 days is very frustrating…
Why not accept the help of the community to increase the number of processors?
I’m here for 4 year, and all the contests we have the same issue…

How many processors do you have to process the queues?
One processor at the aws for one week is $5 dollars…
Why not accept donations to increase the number of processors?

Why not create a paid service costing $10 for players that want to reserve a processor to process her queue and rent 2 processor, one for him, and one for the community? Everyone wins… the community, the player, and the codingame… and while the player that rent the processor is idle you can use it for the community…

The last 3 days of the competition is always very frustrating… I’m sure that a lot of players can pay $5 or $10 to increase the competition experience for everyone…


Upper legend here. (68th after rerun)

General feedback

First of all, thanks for the contest. I put more hours into it than I probably should have.

All over I think it is was more a strategy challenge rather than crunching complex algorithms and decision trees. That was nice because it felt no language had an advantage. Maybe simulating the game during attack/defense to find the perfect move could have helped (I never tried) but it probably won’t give a huge advantage.

The parameters and game rules were also really well crafted. Every strategy seems to have a counter strategy, both locally (when and where cast what?) and globally (where to defend? how many heroes go forward?). Very well done.

There are two points that could be improved in my opinion:

  1. The wild mana was intransparent. There was no way to know if you are in the lead. I also wonder why just the remaining mana wasn’t the secondary win factor. That would have rewarded energy efficient play.
  2. Minor issue, but it would have really helped if the game viewer had an option to hide entities inside the fog of war. The true experience of a game for a player could not be shown. It was difficult to debug strategies in which I tried to hide just 1 point out of sight.


I went with the 2 defense 1 attacker pattern. I think this was the most common formation as well.
My heroes could have multiple roles depending on the situation.

Hero 1 - the keeper

He will protect the base. If no enemies are around, he will stay and patrol inside the base as well.

The keeper strategy in order of priority:

  • wind out a spider that would kill the base
  • wind out a spider that the hero and an enemy hero can cast spells on
  • find the average position of the first n spiders that can be reached, go there to slash them all at once; maximize n
  • slash the closest spider at the location that is also close to the next incoming spider (to reach next target quickly)
  • move to closest spider

Hero 2 - the defender

He behaves like the keeper but with the following differences:

  • ignore the closest monsters without a shield but start targeting from the first monster with a shield
  • if there are no monsters with shield, run towards enemy attacker if there is one

This will prioritize dangerous shielded monsters and also start to wind monsters near the attacker away.

If no danger is around, he will go farming around the base.

Hero 3 - the attacker

He will farm midfield but if there is 150 mana or more, he will launch an attack.

The attack pattern was simple but effective:

  • go to the top of the map
  • control up to 3 monsters and send them to the upper edge of enemy base (to distract the defense)
  • go to the bottom of the map
  • control up to 3 monsters and send them to the lower edge of enemy base
  • protect with shield and run into lower part of enemy base
  • pull enemy heroes away if possible
  • (around this time bottom monsters arrive)
  • cast shield on monsters that are already halfway in
  • wind any monsters forward that can be targeted
  • abort the attack if mana is too low or no monsters could be controlled in given timeframe

This will often create an impossible to defend situation as the enemy hero(s) are still out of position after slashing monsters from top

The attack was a bit weak against players who defend very far outside the base.

Hero 2/3 - the farmer

If not busy with the main role, hero 2 and 3 will farm with a strategy that I copied from another player:

  • go to a designated farming area and start to slash closest monster
  • if multiple monsters can be slashed, target all by moving to average position
  • follow the monster with more health.

I also added some specialized logic to counter the infamous triple hero attack. I think you can code a quite powerful bot if you analyze opponents pattern and have multiple strategies in your pocket to chose from.


Haven’t checked the final leaderboard but this was the most successful canon implementation I saw. Can win fairly consistently by turn 58/59:

It can be disrupted a bit with one defender hero by following them and pushing using WIND, but takes a lot of mana and still requires some ‘luck’.

Quite a simple strat:

  • Farm with all three heroes until ~120 mana collected. No spells before this.
  • Once 120 mana gathered, cast Control on 2 mobs and target opponents base. This moves at least 2 mobs towards opponent base in case you’re unlucky and there are none already near opp base.
  • Sync all 3 heroes to either search for or target one mob close to the opponent base.
  • If all heroes are not in range, use wind to push the mob to the centre of the 3 heroes (in range of all 3).
  • Else all 3 heroes cast wind targeting enemy base.
  • Repeat last 3 steps.

115th Legend


  • a pleasant contest overall, I would find it great to have them more often
  • interesting game, even though there was overpowered wind stacking
  • please, fix the submits and/or the ranking system, even more, if you plan to have heuristic-friendly games more often.

My goal for that contest was to pass legend and be in the top 100. When I first saw the game rules, the goal became pass legend OR be in the top 100. I’m really bad at heuristic-friendly games :sweat_smile: (by that I mean games where usual search algorithms are not overpowered).

At first, I was disappointed that the game was a recycled one with bugs, overpowered wind stacking, and missing/wrong info in the statements. It could be due to my increased expectations after waiting for one year or because I was frustrated to have to deal with my weakness in this long-awaited contest. Even a recycled game is nice to have for a contest and the staff addressed the bugs. Overpowered wind stacking… even though I believe this should not exist, it did not bother me as I did not plan to become a top player in this contest, I ignored them. The wild mana win criteria seemed off to me. As that information was unknown to the players, I thought it forced us to attack the opponent, as players’ HP were known.

Making a contest on some more heuristic-friendly games is not a bad idea. However, this requires a much faster submission. Indeed, we cannot test locally how well our bot performs, so we have to rely on the arena. However, submits took hours to complete, making testing ideas quite hard. Decreasing the number of matches per submits is not the solution: the ranking system is already unstable, even more with a heuristic-friendly game, the situation would be worse with fewer matches to measure a bot performance.

There are many ideas I have not tested, as I knew I would not have time to check if they improved my bot strength. It’s frustrating, but not that much as I was not competing for the top places. Other people may have a different perspective though, as this is a recurring issue for years, and to my knowledge, they are no communication about addressing that particular issue.

I won’t speak much about my strategy, same kind of heuristics other people used, nothing relevant here. Two defenders, keeping an eye on a possible single attacker, and an attacker, tasked with finding nice mobs to send to the enemy base. Heroes were only allowed to use winds, as I never managed to handle controls and shield in a way that actually improved my win rates.

What I would like to share is my plan to pass legend. I was in the gold league with my bronze bot. So I was quite far from the gold boss with a really dumb bot. On my computer, I made a bot version that defends only, another one that defends and farms wild mana with three heroes, another one that uses a hero as a dumb attacker, and two variations of the latest on the defense tactics. For clarity’s sake, we could name those bots DEFEND, FARM, MIXED1, MIXED2, and MIXED3. None of those bots were clearly better than others when tested locally. The code was a mess, adding improvements led to highly variable win rates, I was unsure of what worked and what wasn’t. Here is the method I chose:

  • find a way to structure the code
  • write a 2 defender - 1 idle bot, and measure its strength against the five previous versions
  • once the bot clearly defeats the DEFEND version (so could defend better with only two bots) and has more than 20% win rate against the three mixed versions (resist correctly to a dumb attack with only two heroes to farm/defend), go to the next step
  • implement an actual attacker, test one idea at a time, until the win rates are all above 90% vs DEFEND, FARM, MIXED1, MIXED2, and MIXED3

It was hard at the beginning because I could clearly see that the biggest issue with my arena version was the attack. However, I thought it would be hard to see any improvement with a good attack if I had a weak defense. To this date, I did not implement all the tricks I had in mind for the attack, but they were not necessary to pass legend.

For fun, I decided to submit a borked version of my attacker, as I got some high win rates against all my previous versions. That version passed legend, to my great amusement. I then fixed the attacker on Sunday, as I was too ashamed of watching my bot replays.

Code Structuring
About the code structuring, I finally found something that works best for me. I have a function for defense and one for the attack. Both return the remaining mana, such that I could make sure that I won’t be short when casting winds. The defense function is called first and deals with the last two heroes. That way I prioritize defense when spending mana. Then the attack function is called, with the remaining mana as a parameter, and deals with the first hero.

In each function, I start by collecting data that matters for the decision to take:

  • where are the opponents
  • where are the mobs this turn, next turns, in how many turns they’ll leave the map or reach a base
  • where are my available heroes for the task, filtering out the controlled ones.

Next, I analyze the data to assign a goal to each hero. For example, in defense, I could task a hero with guarding the base, remaining inside it, because there is an attacker nearby. In that case, the other hero would be free to farm if no threat is found or remove the attacker if it becomes too dangerous for mobs I see coming.

Finally, for each hero, I search a way to best implements their goal. For guarding, that would be staying in the base while following the attacker, such that I could intercept mobs sent to my base.

This organization may sound trivial for some, useless for others. However, this organization helped me to overcome the code mess I usually produce when working with heuristics. It was also easier to tune the goal assignment by adding new considerations to the analysis, or improving their implementation (e.g. MC simulations for farming).

Even longer version: my retrospective article


First I really hope you enjoyed the contest!!

225th Legend

It’s been a very long time since I did a pure heuristic AI as I wasn’t much inspired for simulation based startegies. I ended up having a lot of fun with my heuristics.
I spent most of the contest going back and forth between my defensive heroes and my offensive one. Here are the headlines:


  • Check if I’m about to lose life (either by monsters moving into my base or the opponent winding them in) → wind out
  • Optimize my farming (trying to hit several spiders at once (simple algo: get the center of the rectangle containing spiders and my hero’s current position and check that they all points are within a 800-unit distance), prioritizing spiders closest to my base (always targetting at least the closest to my base)
  • If I have some extra mana, control spiders to go to the opponent base (not very well done actually)
  • Roam around the base (with 4 checkpoints)


  • roam on the opponent base radius
  • push spiders then protect them by controlling the defending hero (if more than 1 hero I just let them alone and go back roaming) → better during early game
  • shield spiders that have a good chance of surviving all the way to the base → better during late game
  • control spiders outside of opponent base (almost insignificant)

Worthy of notice: I track spiders going back into the fog, making them move and applying my winds, then removing those outside of base or truncating coordinates if inside base radius (quite efficient for a simplistic approach)

My biggest weakness is against offensive heroes that control my heroes (I do shield them sometimes but far from enough)

I mainly worked on my AI during the last night, during which I completely rewrote bot my defensive and offensive startegy, so I ended with a quite straightforward AI, with some spaghetti code coming back at the end.
Code structure is … well I’m not particularly proud of it… tens of duplicated Java streams (I would have won so much time writing them once and for all… such counter-productive lazyness! mainly due to the fact I had little time to commit to the challenge so everytime I logged in I wanted to improve my AI behavior in as little time as possible), distance computations and sorted performed so many times, but as a heuristic algo, performance is irrelevent.

Overall it was fun, glad to have made it to Legend (1st time!!)


FYI, we have removed 10 bots from the Legend league:

  • 5 bots from the Inetum team which had the same code
  • 5 alts from Legend league players

The results are now official. They will be shared officially by email and on social media tomorrow


No PM from me, just wanted to say thank you for the contest, I think I speak for many of us when I say we really miss them! Great to see some familiar faces around again and have meaningful chat :slight_smile:


Thank you for this contest!
Inetum team, not banned :wink: I could only make it to the Bronze League. But I had fun, and I made new friends in my company. I hope they will participate again, now that they could learn the rules (the hard way).
Thanks again!


Gold 300

During the contest I saw that everyone was playing with at least one attacker, so I tried to make a fully defensive bot.

General strategies

  • Attack optimization if there are enemies close to the hero principal target
  • Each spider get a priority score. Spiders with higher priority score are targeted first
  • Optimized attack repartition : each bot attack the closest target which is not attacked (exception for shielded spider that can’t be handled by one attacker)


If there are no attackers in the enemy team, I have one defender staying not too far away from the base and 2 scout that can go in half the map in order to farm mana. It’s pretty efficient and I could get up to 1100 wild mana with this strategy


Once an enemy attacker is detected my bot switch to

  • 1 tracker per attacker
  • others are defenders

The tracker follow the attacker and wind spider that could be used as ammo.
The defenders defend the base and attack spider that could be used as ammo in priority.

What can be improved

  • My scouting need to be polished
  • I need to keep tracking hero I winded
  • I’m really weak against disturbing attackers that control my heroes, I could use shield in this case.
  • I defend canons with more than one hero, which is not efficient.
  • Sometimes my trackers don’t use wind even if they can avoid some canon shot
  • The fact that I don’t anticipate spider movement and just move to their current position

Why it didn’t make me a legend

I don’t know if you can get to legend without attacking. With the improvement above maybe it would be possible.

But I’m not sur if I can avoid loosing some of my game because I had to defend hard and didn’t get enough wild mana


Thanks CG for the challenge !
I’m really interested in any feedback on how I could improve this exotic strategy ! I’m also curious how it went for you, fellow defenders, did one of us go to legend ?


#2 Legend

My bot starts with a simple if/else which assigns a role to each hero; the three main roles are gatherer, attacker, defender. Roughly until I reach 210 mana for the first time (or earlier, in some cases), all three heroes are gatherers camping at the 3 spider spawn locations around my base (with 1 of them occassionally switching to the defender role). After that, one hero permanently becomes a defender, and the other 2 become attackers, controlling spiders towards the opponent’s base, trying to use wind combos to damage it, and using control on enemy defenders. When ( if :slight_smile: ) I run out of mana, the attackers become gatherers for a while, then become attackers again.

All the roles work in a similar way - I consider several thousand possible points in the 800 range to move to, assign a value to each of them with an evaluation function and choose the best one; then there’s also a similar evaluation of spell usage (hundreds of angles for control/wind). If spellEval(spell) + moveEval(current position) - mana usage penalty > moveEval(best move), I use a spell. For example, the function that evaluates attacker’s moves rewards being in wind/sight range of spiders’ future positions, moving towards ~4500-6500 range of the enemy base, and setting up wind combos; it discourages attacking spiders and staying in defenders’ wind radius.

You might be wondering how to calculate whether a move “sets up a wind combo”, especially if it’s more than 1 turn deep; however, the idea is very simple: for t = 0,1,2… and for every spider I check whether it is possible to set up double/triple wind with my attackers (just a distance check between my heroes and the spider’s position after t turns) that yeets the spider close enough to the opponent’s base. When I find the earliest/closest/healthiest (weigh those however you want) spider, I remember the areas where I want my heroes after t turns, and the evaluation function rewards moves after which I can still get to those areas in t-1 turns.

That’s all; the rest of this PM will about the meta. There’s no advanced-ish geometry (yes, analytical geometry formulas for attacking 2 spiders at once are cute, but it doesn’t help at all when I’m attacking an enemy base with a train of 8 spiders against 2 defenders), no search (technically, I do simulate spiders’ movement up to depth 50, but I suppose that’s not what people imagined when I said in the chat that I do sim), just if/else and a couple of big cycles. This was supposed to be a relatively low-effort cheese bot that would require people to add some ifs to their code to beat it, but ultimately wouldn’t rank too high, so I didn’t go for anything too fancy. I submitted it in silver, got to rank 1 for a day, and I expected people to adapt quickly and make this strategy completely useless.

However, to my surprise, people had trouble with consistently defending against my strategy, even though it has one (at least to me) painfully obvious flaw: it requires me to move spiders to the enemy base along the edge of the map, where they are vulnerable to getting wind-ed out of the map. What’s even worse is that my opponents could track my mana to know when exactly to get the defender in position, because I need to stop farming mana (I don’t want to damage spiders I’m leading tot he opponent’s base) and I need to start using control. And yet, when the legend league opened, I was still consistently near the top of the leaderboard, often first, and I had not seen anyone defend like that once. Instead, I saw more and more people copying my strategy instead. And every one of them was easily counterable; e.g. early in the legend league, I tested this defense against kouin’s bot and most games went like this.

So I kept this defense hidden; in one of my legend submits I used it for about 50 games, and the day after I saw KawattaTaido push my spider train off the map, so maybe they had seen my games or someone finally realized that it’s possible. Still, it didn’t become widespread and I decided to see how far can I get with this joke of a strategy. I had a solution for bots that use 2 attackers; 3 attackers aren’t really that consistent to consider them a threat at the very top of the leaderboard; having no designated attackers might be theoretically optimal but it’s a very impractical way to play, because you need to be consistent against every cheese out there to climb the leaderboard, while I only had to come up with one. That meant I had to optimize against players who used only 1 attacker.

The problem appeared to be that 1 defender can’t defend against 1 attacker’s doublewind or control efficiently. Sure, I could keep shield on and wind away monsters, but then I would take longer to gather mana for the attack, and I would give my opponents more opportunities to damage my base in ways I couldn’t prevent just because of fog of war; another less obvious problem is that if I execute the 2 attacker push later, opponent’s defenders will be closer to their base because it’s simply no longer possible to kill spiders close to the spawns as their hp increases with time - and if my opponent’s defenders are already in place and shielded, ready to push both the spiders and my attackers back (not necessarily out of the map), there’s at most 30% chance for the attack to succeed. #1 managed to win about 75% of the games against me mostly because he pre-positioned his defenders (it’s not overfitting against me if it works…) even though his winds blew in a wrong direction.

The best way to defend against 1 attacker was to not let the spiders that target my base to get there - and use wind or control if I can’t do it only with attacks (each gatherer was placed at one of the 3 nearby spawns, as I wrote earlier, and took care of spiders that spawned there); I also used a simple prediction of the attacker’s movement to estimate which spiders will be seen by the opponent and I stopped only those spiders that the attacker will see or that will enter my base, and I didn’t care about losing hp due to my heroes getting controlled - better than delaying the attack by being overly cautious, and it costs quite a bit of mana that might be missing in defense later. I took damage quite often, but I rarely lost before I could launch my attack.

I submitted my final version about 12 hours before the end of the contest (I didn’t want to risk because of recent ISP outages, so instead I just submitted early and watched some games to make sure my final version didn’t have some huge bugs) and I was first at the time; I was no longer hiding that I could defend against 2 attackers, some players saw the “counter strategy” and used it against me. The wind has turned against… the edge of the map. However, even if I had kept it hidden, I believe I wouldn’t have beaten bowwowforeach - he managed to refute my unsound attack even without it. Maybe some of the players came up with it on their own (I hope they did), and it didn’t help that much, because people couldn’t just dramatically rewrite their defense in the last few hours of the contest (and I also imagine they had better things to do than countering my bot last-minute).

What probably would have let me win the contest is abusing bugs, as seen in this replay; considering that the game was made, like, 4 years ago and it has been used before for private teambuildings/hackathons/whatevertheycallits, one would expect no gamebreaking bugs or wrong input, but… well, the game was nice, I liked that it tried to promote playing actively over turtling, and if it’s ever used again it will also be sufficiently tested.


Language: C++
League: Legend 282nd global (1st national)

I only created my CodinGame account a month ago because a friend from an informatics olympiad camp invited me to join this challenge. I don’t regret joining. This is a very new and unique experience compared to competitive programming I’m used to in Informatics Olympiads.

I’m very new to bot programming and my resources are limited. Hence, my final strategy is simple without any heuristics whatsoever other than hardcoded values.

Final Code Main Idea

I split the game into two phases: farming phase and attacking phase. My three heroes farm for mana for the first (approximately 50) turns, specifically after X mana has been collected. In my final code, X is 160. I’m not sure what a better number would be. The farming phase consists of two heroes roaming in the middle of the map and a hero making sure that the base is safe from attacks. The farming phase is simply “I see monster I catch”. I’m sure my solution is very suboptimal in this phase as other codes gather mana in a faster pace.

The next turns, the two roaming heroes come to a spot near the base, controlling up to 5 monsters with them. The monsters are controlled to a spot 1040 units to the back of the heroes. The spot where the monsters will be, the spot where the heroes will be, and the opponent base should be colinear. The controlled monsters should be guaranteed to reach their positions before the heroes to avoid mana wasting. After a monster has reached the designated spot, two turns are used: one soft wind spell and two hard wind spells, pushing the monster 6600 units away to the enemy base. Then, the heroes patiently wait until a monster outside the enemy’s base is in CONTROL radius, and the process repeats. The other one hero does a classic defending operation using WIND spells; probably similar to the codes in wood 1 league.

Clearly in my strategy, the attacking side is way more powerful than the defending side. Hence, I gave the offense a mana usage priority. I precalculated the amount of mana the offense will be using for the next 2 turns (in case of soft + hard attack) and prevent the defense to waste mana. I also added a mana cap to make sure that the defense does not use too much mana by using health as a parameter. The less health you have, the more dangerous it is, so the defense is allowed to use spells even if mana is low. The less health opponent’s health is, the better the state of the game is to our side, so the defense is allowed to use spells when mana is lower. I could give more priority to our health over opponent’s health considering how weak the defense is, but without such optimization my code reached legend league, so I didn’t bother

Here is my strategy in action

What to improve

There are a lot of things to improve that I didn’t implement either because I was buzy or because I was lazy:

  • Dynamic attack movement: Don’t just stay at one specific point.
  • Accurate value calculation: There are a lot of things I can say here:

    I only eyeballed the spell vectors. I only did things like “SPELL WIND opponent_base_x opponent_base_y”.
    I disregarded the vector movement of monsters and I just straight up do “MOVE monster_x monster_y” which I’m sure is far from effective

  • Defense: Yes. A bronze league strategy in legend league. Very funny.
  • Farming: As stated, my farming strategy didn’t yield mana as fast as others.
  • Monster tracking: After speedreading through some of the comments here, I just realised that monsters can be tracked due to the symmetrical nature of the game.

Final Words

It was a very fun experience. Before the challenge, I tried mad pod racing and spring challenge 2021 and reached only gold league. I was glad to made it to legend for the first time.

The game is very luck and meta based in my opinion. I don’t think there are perfect strategies that can counter every other strategy. When I submit my code in the arena, I try to reroll until the initial 10 battles have at most one loss. This is because the lower ranks have implemented counter strategies to the above ranks, which was a little bit annoying to deal with.

There are times (especially few hours before a new league was going to be opened) where the arena runs slow. That would be understandable, as I get how heavy the computation of the games are. I’m already used to long queues from other competitive programming sites haha.

I also wrote a blog that tells my whole experience joining this, including my flow of thinking starting from wood 2 to legend. That would be published probably few days after the challenge is imported to the problem list.

Thank you for the challenge!


That’s a very nice bug you got there :smiley: I checked for it so I’m not sure how I missed it, I thought wind didn’t affect mobs outside the map :frowning:
Well, now I know what I should try when the challenge opens as a bot battle.

I even explicitly added checks to not wind mobs before they enter the map…

after I decided not to hide, I reported it and it was fixed… on Tuseday or Wednesday


Thanks for the challenge, it was pretty fun.

Although, in the end I had a very mitigated results (middle of the silver league), I’m pretty happy with the code I produced.

I didn’t see anybody tried to solve it how I did in the comments, so, I’ll describe my solution.

Overall objectives

My objectives were pretty simple, to find a scoring method to determine a few key aspect of the game state via:

  • a danger score
  • a scout score
  • an opportunity score

I managed to get a pretty good danger score, but not the other one. That means I was able to defend but nothing more.

Having the danger score at turn t, the turn resolution is simple: simulate every possible and sensible solution for the next turn, recalculate the danger score at turn t+1, and pick the best options.

This work pretty well for my 3 heroes in a defensive stance, being able to use the wind right when needed.

However, it’s pretty bad at winning the game, as, having not implemented a scouting score, my heroes stayed pretty much near my base and I usually loose to not having enough mana.

This also failed against more aggressive player, that disrupted my defensive formation.

And finally, this is quite a greedy solution and it fails to give answer in time some times. So implementing more score/decision in the process would have required a bit of optimization/refactoring.


**Legend #90 **

1) Data Structure:
I have an array of monsters for each player separately based on the threat_for variable. This helps me to focus on the threat monsters first and neutral monsters later.

2) Sorting
Sort all my monsters based on distance to my base
Sort all enemy monsters based on distance to his base
Sort all neutral monsters based on distance to my base
Sort all enemy heroes based on distance to his base

3) Art of Defence - 2 Defenders

Both my defenders guard two points GUARD1 and GUARD2

GUARD1 = Point(3600.0, 6500.0);
GUARD2 = Point(6800.0, 2000.0);

if (turn > 20) { #be slightly more defensive after 20 turns
	GUARD1 = Point(3600.0, 5500.0);
	GUARD2 = Point(5800.0, 1000.0);
  • Intercepting monsters - not chasing - This makes a huge difference at gold as this increases the win rate drastically especially against players with equal strategy.

  • Keep the guard - Always keep both defenders closer to either GUARD1 or GUARD2 (by 2200 distance) or closer to the base (9000 distance). Allocating 1 hero to each GUARD is not possible in the late game since monsters health is huge and they appear randomly and 1 defender cannot kill all the monsters coming towards a GUARD. They have to often go to the other hero’s GUARD either to kill the 1st closest monster to the base or the 2nd closest monster to the base and work as a team.

  • Focus on killing the first monster - Always let the closest defender (I call him the 1st defender) go after the first monster as it’s the most dangerous monster that could cost us a life. Use the next defender to either go after another monster or GUARD based on the danger level of this first monster.

  • CONTROL for defence - I’m kidding. I never use CONTROL for my defence. 1) It’s not an AOE spell, 2) It’s push distance is very less 3) It’s not effective in the immediate turn. The only time we would need a CONTROL is when the monster is going to damage our base and there is no way to kill the monster and the monster is out off range for using WIND. The chance for this was less than 1% and it never happened in any of my games even though I’ve this case programmed.

  • WIND only on the first monster - WIND is the only defense that’s actually required to defend our base and it’s always effective if we use it only on the first monster. If the monster is shielded there is no use in WINDING other monsters because we should use the time in killing the shielded monster than using WIND on another monster.

  • Always attacking - less walking - Our defenders should always be farming and walking less. Watching more replays and fixing team work among defenders helped me improve on this part. To avoid a hero going too far from his current position, I ignore defending with the 2nd defender when the 2nd defender is too far from the monster (say 3000 distance)

  • Knowing when to give up If I can neither intercept a monster nor use CONTROL spell on it’s time to give up on that monster. I assume it’s dead and ignore it.

  • Parallel farming There are cases when the two closest monsters are very close to each other (i.e. < 1600 distance) in this cases positioning both our defenders in between these monsters will do 2 damage per turn for each monster by each defender. i.e. 8 damage per turn which is nice.

4) Art of Attack - 1 Attacker

  • Double Wind I didn’t want to complicate my wind calculations by doing a cross pull to keep the monster in vision and do a second push. Instead I move my hero ahead 1279 distance ahead of the monster so that I can use the double wind effectively.

  • Tracking the monster that I wind
    As I’ve only one attacker and I only wind 1 enemy monster at a time, it’s easy for me to track it in the next turn even when it’s not in my vision.

  • Farm with attacker on low mana. NEVER help the enemy
    I never hesitate to farm with my attacker when I’m low on mana. But I made sure that he never ever helps in enemy defense i.e. to damage a monster who can be a potential threat to the enemy. (i.e shielded monsters, monsters with less than 2 health (Killing it reduces the number of threats for enemy).

  • Shileding This is the most OP skill in the game lasting for 12 turns with no counter except by killing it manually using defenders. I use it only when I know this shield lasts until the monster hits the enemy base and also only when 1 defender is not sufficient to defend this SHIELD before this monster kills opponent base making it a killing blow. Making both enemy defenders constantly busy keeps the opponent under pressure and gives them less vision in the map.

  • CONTROL Enemy defender cannot defend for a turn and he will be pushed away. Should I say more?.

5) Customized defense against 2 attackers
When I see two attackers closer to my base I name this opponent as a sneaker and store in a global variable. For this opponent I spam a lot of winds on the enemy attackers and even chase them when they come closer to my base. This did not work well against top level players like Blasterpoard whose attackers CONTROL me the moment they see my defenders. But it worked against most other players with two attackers as they often hesitate to use control or shield themselves as they are usually in less mana.

6) Protection against enemy CONTROL (Rare scenario)
When enemy attackers control my hero it’s often pretty scary and most likely lead to monsters damaging the base so I self shield my defenders when I have a large quantity of mana and monsters are threatening my base and the enemy has a good opportunity to CONTROL me.

To sum it up I had 193 if statements in my code and it was fun filled contest. Only feedback to CG is to increase the speed of servers as the submits are often too slow during contests. I say this besides CG being the best platform available for us to learn and test our AI.


Congratulations, especially using scala!
I may already asked you that but how do you avoid JVM warmup?
I tried scala in contests but it ended up in timeout, because either warmup or me using wrong time measuring functions. I switched to go or c++ for simulations.

Top 29 legend.

Really glad to make a good result for the first challenge I play seriously. First I would like to thanks the community (especially the french one) which was really kind to discuss with.

During this challenge, I explored different strategies. First, I quickly understand that farming was key in this challenge. In the early game, I position my heroes on farming points (top and bottom) and I try to select a point damaging multiple spiders. I did not decide to use maths to find the best farming point, I simply tried hundreds points and select the one which is closer from the farming point and hits the biggest number of spiders. To test that bot, I implemented a naive triple wind attack. This strategy was just enough to climb legend.

I then tried to switch the attack with a “blasterpoard” strategy. My lack of organization and practice made it really hard to implement. I finally made something playing good enough (double wind for kill, pass to double wind, control enemies in defense…) to beat blasterpoard bot quite often in practice because my farm was a little better and I managed in most cases to attack faster. But I was only losing against lots of legend bottom players for different reasons.

I didnt have enough time to improve my bot on multiple aspects. My bot has a really bad defence, I did not work a lot on that point. But more importantly, if I don’t win after the attack, the game is lost because my attackers dont go back to farmer mod… I will try to do something better when the multi will be out.

See you in the next challenge !