Overview
MIT Battlecode is an annual programming competition run over MIT's Independent Activities Period (IAP) where participants design highly efficient algorithms in Java to control a swarm of robots in a real-time strategy game. Teams write code that makes autonomous decisions for resource collection, combat, and territorial control — all without human intervention. Robot swarms from different teams compete against each other for map and resource domination.
Each robot must execute its logic under strict bytecode limits, which make traditional search algorithms impossible. Additionally, robots can only see the state of the tiles directly surrounding them and there are strict communication limits between robots.
My team, Beaver Bois, competed in three tournaments in Battlecode 2023, including Sprint 1 (Jan. 17), Sprint 2 (Jan. 24) and finally the US Qualifiers (Jan. 30). We didn't make it past the US Qualifiers (placing 25th in the 96-team event), but we learned a ton and had a great time! Our team name is a spin-off from the name of the University of Massachusetts Amherst library, the DuBois library, and MIT's mascot, Tim the Beaver.
The Game
The 2023 game was built around resource collection and island control. Each team started with one to four Headquarters, which were indestructible and served as spawn points and resource depots. Carriers collected Adamantium and Mana from wells on the map and brought them back to HQ, where those resources could be spent on more robots or on Anchors. Launchers were the main combat units. Anchors could be carried to sky islands scattered around the map; controlling islands was one of the main ways to win a match.
Maps also had walls, clouds that limited vision, and currents that pushed robots around. Communication was limited to a shared array of 64 16-bit integers, and robots could only write to it near an Amplifier or Headquarters.
This video is a nice overview of the competition and 2023 game.
Challenges
Battlecode presents many unique challenges:
- Shared Code: Each robot runs the same code independently, making different strategies for robots in the same class difficult. Robots more or less have to execute similar strategies to one another.
- Communication: Communication between robots is extremely limited. There is a shared array of integers that robots can read from. To write to it, robots must be near special robots called Amplifiers or the team spawn point.
- Resource Management: To build more robots you must collect resources, but a balance between resource farming and military strategy is hard to achieve.
- Attack/Defense Strategy: Difficult to make a single strategy that works across different opponents, since the same code is run for all official matches.
- Computational Limits: Strict computational budget bytecode per robot and per turn. If a robot exceeds its bytecode limit in a single turn it dies.
- Different Maps: The maps used in official matches aren't released before the matches start. Strategies and navigation algorithms tend to prefer certain types of maps over others, so when an unexpected map is played, it can throw off team strategy.
Because of all of these challenges, traditional pathfinding algorithms and swarm coordination approaches are not viable. Instead, teams have to come up with simple algorithms that are computationally cheap and scale across many robots. Developing such an algorithm that works across different maps and opponents is even more difficult.
Strategy
Our strategy basically consisted of us throwing stuff at the wall and seeing what stuck. You can take a look at our final code here. There is a mix of resource generation, swarm, attack, and defense tactics in our general strategy.
Communication
Communication between robots is limited to a shared array of 64 16-bit integers, and robots can only write to it when they are near an Amplifier or a Headquarters. We used that array to store HQ locations, discovered wells, spotted enemies, island assignments, and suspected enemy HQ positions so the rest of the swarm could read them.
Battlecode maps are always symmetric (either horizontal, vertical, or rotational), so once we knew our own HQ locations we could compute three possible enemy HQ positions. Launchers would check these coordinates and report back which ones were wrong until the location of enemy HQs was fully determined.
Resources
Headquarters spent most of the early game building Carriers and Launchers. We biased Carrier assignments towards collecting Mana and built Launchers whenever we had enough Mana. We found that combat tended to matter more than healthy resource generation early in the game. Early Carriers scouted toward the center of the map until they found wells, wrote those locations into the shared array for other Carriers to use, and then looped between farming and depositing resources at HQ.
When sky islands were discovered by robots, their locations would be written into the shared array. Later in the game, once we had enough robots on the board, HQs started saving resources to build Anchors. A dedicated island Carrier would pick one up and bring it to the nearest unclaimed sky island. If enemies showed up within a certain radius of the HQ, we stopped the normal build queue and spawned Launchers to attack the threat instead.
Combat
While our Launchers initially moved individually, we later implemented a simple swarm strategy. Launchers would gather near our HQs until a small group formed, then move out together toward a reported enemy or a suspected HQ location. If the pack got too small, they fell back to HQ and regrouped. Once a pack reached an enemy HQ, it tried to overwhelm the HQ by preventing new spawns.
In combat, Launchers prioritized attacking enemy Launchers, then Carriers, then other units, and among equal priorities they targeted the enemy with the lowest health. After attacking an enemy Launcher, the unit would try to step back out of range. Carriers that ran into fighting units mostly ignored them and kept farming, since they usually could not win those fights anyway.
Navigation
Bytecode limits made expensive pathfinding impractical, so robots moved straight toward a target when the path was clear. Whenever they hit a wall or other obstacle, they would use the Bug algorithm: follow the wall until a direct path to the target opened up again. Some maps had Currents in critical pathways, but our robots treated these as impassable since in most cases they would divert the robot from an optimal path. If a robot got stuck in place for multiple turns, it self-destructed so it would not sit idle forever.
Robot Personalities
We wanted to give our robots little personalities, so we made them print out fun messages on their death. Here's a list of the messages that robots may print out when they die:
Wakanda Forever!You are worthless.The cake is a lieWinter is comingThe end has comeLuke I am your fatherTo infinity and beyond!Goodbye cruel worldHello world...Well, nobody's perfect...E.T. phone homeFather I am comingThere's no place like homeWar. War changes peopleI have a dream...DEATH IS A PREFERABLE ALTERNATIVE TO COMMUNISMMommy, I'm coldHelp me...Mama, ooooohhh, I don't wanna dieI sometimes wish I'd never been born at allI like jazzBy all known laws of aviation...Never forgetSweet dreamsThe light, it burns!'Tis but a flesh wound.So dark...Honey, where's my super suit?'Till we meet again!
