Hi all, I finished 3rd place and here is a breakdown of my strategy:
Scouting
At the start of the game (first 30 turns), scout aggressively – the targets are hardcoded. Do not engage any ground ghosts until you’ve reached your scouting assignment. After that, still within the first 30 turns, only engage a ghost that is downfield (i.e. further than our base than you are). Rationale: I’m likely to end up getting easy targets on my half of the map anyway, and early action on the opponent end of the field will cause ghosts to gravitate towards my base naturally. Map position is extremely important for times when the midgame/endgame turns into a race. I have found that I begin most games behind by 1-2 points, but that I make it back up over time as the map advantage is in my favour.
Targets
Every turn, a collection of interesting targets is tabulated, consisting of:
- Visible ghosts on the ground
- Visible enemies carrying a ghost – only if any of our busters will be able to intercept him in time, considering their current stunned status and stun cooldown, otherwise ignore that enemy completely – no sense wasting valuable effort on him!
- Last observed locations of ghosts (taking care to account for the fact that ghosts may float away)
- Friendly busters carrying a ghost, if they are not safe (using the same calculation as above, in reverse – not perfect since we don’t know where all enemy busters are, but good enough)
Weapons
Initially I adopted a very liberal stance regarding weapons: if able to use them, use them. I found that I was losing a lot of shoot-outs with higher ranked AIs, and I decided to be more conservative regarding my use of zaps. Now, I never zap any opponent unless there’s a valuable target on the map somewhere: a <10 HP ghost (including one carried by an opponent or a vulnerable friend). In other words, if there are only big ghosts on the field, conserve those zaps; otherwise, weapons free. I’ve found that I come away victorious in a lot of zap battles simply because I was on stun cooldown less often when it mattered.
Buster behaviour
In general, busters act completely independently. For each buster, the set of available targets is filtered by viability (for example, if a buster can’t reach a ground ghost before it burns down and we’re the only ones burning it down, don’t bother). Then, whichever applies first:
- If there’s an enemy to shoot (and we’re weapons free), shoot (only if he hasn’t already been shot this turn – this is the full extent of buster cooperation). Note: a buster will shoot even if currently carrying a ghost.
- If carrying a ghost, dive-bomb for home in a straight line. I didn’t do any avoiding techniques because I had faith in my battling abilities UNLESS it’s near the end of the game and we won’t make it back in time to have a material impact on the rest of the game anyway, in which case hide in a corner and avoid enemies
- Pick a viable target based on the number of turns needed to burn it down completely: divide distance by speed (turns to get there) and then divide ghost health by number of busters adding myself if not already there (turns to burn the ghost down). Remember that this can include enemy-carried ghosts or friendly-carried ghosts. Select the one with the smallest number of turns and act accordingly (move towards, shoot, escort, etc.). Do not give additional preference for an enemy-carried ghost.
- If no available targets, go into pre-assigned endgame roles, hardcoded on turn 1: camp enemy base or sweep far sides of the map (targets will likely emerge sooner or later)
By watching countless replays I made minor modifications throughout the contest. I made a few major modifications when I observed some brilliant behaviours from some top AIs.
Chain-zapping (Hohol)
Despite my best efforts, Hohol always seemed to get the best of me during gun battles, and I sought to figure out why. I watched replays frame by frame and observed that in some circumstances Hohol would zap my buster one turn before I would zap his! I panicked and thought that I was not interpreting the input correctly and that I was misjudging the cooldowns or stun durations by one turn, but it was not so. So what happened? He was actually zapping my guys the turn before they came out of stunned state. This way they would not have a chance to fire upon enemies the turn they woke up. I immediately implemented this idea: when looking for enemies to stun, consider also those who are in Stunned status for 1 more turn.
Herding (Recar)
At 10AM on Sunday (4 hours before the contest ended), I noticed a new leader, Recar, and immediately started studying replays against him. While carrying a ghost (even sometimes when not carrying a ghost!) his guys would gently shepherd ground ghosts towards his base! This struck me as brilliant - while there would be a cost of doing this (ghosts float half as fast), the dividends would show: better map position for the mid/end game and fewer running costs later on (not to mention return safety). I set to work on this immediately and within a few attempts I got it working. This was submitted with around 2 hours remaining.
Scala
I learned Scala on the job and have been using it for about 8 months. This is my first contest attempt using Scala and I can confidently say it will not be my last. Scala is such an expressive language that makes it extremely easy to communicate intent – not once during this contest (at least that I noticed) did I discover a careless error in my code. Errors are extremely difficult to track down in a contest like this – without a debugger you’re reduced to writing a lot of console entries to diagnose the problems, and this takes up a lot of time – time that could be spent watching replays and studying top opponents. This time I was able to focus my attention where it mattered and it showed on the scoreboard.
One small piece of feedback for the CG group: The zap cooldown of friendly and enemy busters was not available. This meant it had to be manually tracked for friendly busters – difficult for newcomers. It would have been very valuable to have this information for enemy busters as well: it could be used to prioritize enemy targets when considering whom to zap. Maybe some of the top AIs tracked this as well somehow? Otherwise an excellent contest, beautiful visuals, superb execution as always and a great pleasure to participate in!