Battlecode is an excellent annual AI competition held in January. I compete under a personal team called vvvvv, occasionally with a couple friends.
The competition itself is always about writing a bot to fight a 1v1 RTS-like game. However, a consistent theme is that bots are compartmentalized, so unlike an RTS, you couldn’t control every bot with global knowledge – rather, bots must make decisions with very limited information. Despite this notable difference, many mechanics and units can be compared to Starcraft, and throughout this writeup, I’ll be making these comparisons constantly. The competition is split up into several tournaments, with scrims being run between each tournament.
The 2019 competition was called Crusade; my first year of competition. The units consisted of:
- Castles: 1-3 buildings that spawned units and are the victory condition
- Churches: constructable buildings that could also spawn units
- Pilgrims: drones that could harvest resources and construct buildings
- Crusaders: melee zealots
- Prophets: ranged shooters
- Preachers: close-ranged AOE nukers
Each unit required karbonite to build and fuel to move and shoot, which were the resources mined by pilgrims. Notably, this year did not have ranked scrims, leading to a slightly staler metagame for me. I wrote my bot in native JS, so I didn’t have to deal with the transpiling issues that other teams had.
The first thing that I did was write pathfinding and pilgrim mining code, some of the absolute fundamentals to a game like this. Since bots have such limited information, I initially struggled with writing communication protocols, leading to the beginning of a mess of bugs relating to units not knowing what they should be doing. I saw that prophet lattices (many prophets in a checkerboard pattern) were an effective strategy, so I put in a quick implementation of a lattice for Sprint and submitted my bot in. As expected, the bot didn’t do so hot – at this time, castles were extremely vulnerable to various types of rushes, so I got rushed down rather quickly.
Seeding and Beyond
After the sprint tournament, the devs introduced the ability for castles to shoot, greatly changing the rush meta. The prophet lattice was the meta strat, and I jumped straight on the meta, building an ok lattice strategy. It was similar to many of the other lattices going around. I figured that if I had generally better micro with pathing, prophet logic, and church building, I could edge out the competition. To that end, I wrote code to build churches to colonize resource nodes and, more importantly, some defensive preacher logic that would build preachers when enemy units get close to the castle and suicide into the enemy castle afterward. This last bit of code is particularly notable because it lead to my favorite moment in all of Battlecode:
definitely intentional strat btw (JamesX2’s bot was so much better than mine)
Despite this work, it turns out that better micro is not enough to win against any truly good teams. I did mediocre in the seeding tournament, made some bugfixes and went on to do ok in the qualifying and high school tournaments. I wasn’t able to do any cool pivots into more interesting strategies, as I had been amassing huge amounts of tech debt since the moment I started writing code. My helper functions, especially in regards to pathfinding, were insanely buggy, leading to a bug at the wrong time snowballing into an instant loss. I also had everything in one file, slowing down development significantly. I resolved that next time, I would be more organized and try harder to not just follow the meta, but also do my own innovations.
Code for 2019 can be found here