#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 ) 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.