I came in second, which is becoming a habit. Thank you very much to the creators, sponsors and organisers of this competition. As ever on CG, it was very smoothly run. Congratulations to @karliso on a great win. Going into the final hour, I knew I was winning 70-80% against all the top published bots; but karliso’s last minute entry blew me away.
The trap meta
I’m going to spend most of this post talking about the meta around traps, the most interesting/difficult/important part of the game, and how my bot fitted with that. To do that, I’m going to go through strategies around traps, working from the simplest strategy through the various counters and counter-counters.
1. Mine ore, ignore traps
There’s not much to be said here. The first iteration of my bot, and probably most bots, placed radar, mined ore, and never thought about traps. This quickly becomes untenable.
2. Place random traps
If you place random traps, opponents who ignore them will blow up their robots. This is a devastating thing to happen. You lose 20% of your mining power for the whole game - this is usually decisive.
I went through a phase of doing this. I found it effective for reaching the top ten (very early on), but you can avoid digging up traps by detecting them. There are at least two ways to achieve this:
- Avoid any square your opponent’s robot has paused next to, which has a hole.
- More sophisticated, only avoid squares which robots have stopped on after pausing on the HQ.
- This can be countered by robots holding traps visiting HQ briefly. However, this is easily detected - your opponents score doesn’t increase, so you know something funny is going on.
I did these methods of trap detection. This allowed me to perfectly avoid traps, when I wanted to.
3. Suicide on traps
Here, you dig up a place you know (or suspect) is a trap, to take out two of your opponents robots for one of yours. When I did traps, I did this.
This is avoided simply by never having two of your robots next to an enemy trap, or chain of traps. However, by the end chains were so rare that I only considered single traps, to improve pathfinding.
4. Stashes
This is where things get interesting. Around Thursday of last week, a new meta emerged. @The_Duck was the best at this for a long time, though I don’t know where it originated. The idea was:
- Pause your robot on spawn, but don’t pick up a trap.
- Dig a square with more than 1 ore. The opponent will think it might be a trap.
- Leave (stash) the rest of the ore for later. When ore goes short, go back for the easy pickings.
In the high level meta, most or all bots were using this by the end. I was, whenever I expected to dig a 2 ore square early in the game. I started picking up stashes at a hardcoded turn, or when the nearest ore to HQ got far enough away.
5. Stash detection/guesswork
Stashing is so effective that countering it became (I believe) the key to the high-level meta at the end of the competition. I tried multiple methods to detect enemy stashes. Having done this, you can dig them up safely.
- Entity IDs. Traps and radar get IDs which are sequential, shared between opponents, and set when the item is buried. This means that if you place IDs n and n+1, nothing buried between those placements is a trap. This is the only certain method in this section; the rest is guesswork.
- Obvious radar. If there are no possible radar anywhere near the item buried, it’s a radar. If multiple holes dug after it is buried would be invisible without this item, it’s a radar.
- Two enemy robots next to a square, when we have a robot nearby. This uses point 3 - the enemy wouldn’t take that risk. To avoid this being used against me, I avoided having two robots next to my own stashes at once.
- Late traps. Very few good bots placed traps after around the halfway point in a match, so it was often worth the risk. This risk almost certainly ended up costing me the win - karliso did this much more, and many of my losses to them came from late traps.
I tracked the expected result of the game, and took more of these risks when behind. Also, if there is an enemy robot next to a stash/trap, I dig it. If it’s a trap, it’s a one for one swap.
Other aspects
To pathfind, I guessed which ore each miner would go for. Then they got to select routes, starting with the one closest to their target. These routes were planned so that we’d never end up with two robots next to a trap/stash on this or a future turn. Within that restriction, I prioritised being close to enemy stashes but not my own.
My first few radar are hardcoded, except that I skip the risky second and third radar if the first doesn’t turn up enough ore (so that I don’t run out). After that, I mostly place them opportunistically as I mine, which is a very effective technique.
There’s lots of other code in my bot, but none of it stands out as particularly interesting or important.
Final evaluation
This section is a tad salty, so let me preface this by saying that I was beaten by a great bot, and by again expressing my thanks to everyone who had a part in the making of this great contest.
In the final evaluation, karliso and I had very comparable results against lower bots; perhaps mine are slightly stronger; the bulk of the gap between us comes from our head-to-head record. This record was 54-37. That is within the range of normal outcomes from a fair coin toss. For future contests, particularly with significant prizes, I think that there should be more games run in the evaluation; I think there is a 10% probability I would have won the contest in this case (and if the evaluation had been closer, this chance could be much higher!).
Again, karliso is a worthy winner, I have no bitter taste from this contest, and I hope to play many more CG contests in the future.
EDIT: @Neumann pointed out that not all the games in the final evaluation are on CGStats, because there is some maximum number tracked and they get forgotten over time. So the actual sample size is larger than I quoted here, and this the evaluation is more rigorous than I thought.