One of the biggest hurdles I’ve had to face with BattleGrid is the AI. How do you teach a computer to play a strategy game? It’s obviously been done plenty of times, but I don’t have the expertise or experience that developers behind big-name RTS games have.
In general, I try to go simple when developing. The simpler the code, the less error-prone it is, and the easier it is to fix problems or add new functionality. I thought my first attempts at AI for BattleGrid were pretty simple. I had narrowed the number of things an AI might do to 5 categories: attack, defend, capture, expand, or extract (claim bitstreams). There was a lot of overlap between the 5 categories, but implementing each one was difficult, and they could conflict with each other easily.
I recently decided to try simplifying the AI further. I trimmed the 5 categories to 3 (expand, extract, and build), and then further to a single goal: build. Once I made the switch, the AI worked almost flawlessly – it never broke and even seemed to be playing intelligently at times. With this single objective – build – I could focus the AI on the important parts – selecting what and where to build. When something goes wrong (can’t build in the desired location, can’t afford the desired structure), it’s easy to abort and start over, letting the AI pick something new to build.
The AI’s thinking goes something like this:
- Pick a structure to build.
- Pick a location to build the structure.
- Wait until I can afford to build the structure.
- Build the structure.
It’s a simple process, and the first two steps are the important ones.
When selecting a structure, the AI uses several factors. First, if there are bitstreams in their territory that don’t have extractors, they choose to build an extractor (as any player should). If not, they look at all the structures they can build and choose one based on their aggression and the effectiveness of the unit against their enemies. If the AI’s aggression is low, they’re more likely to select a defensive structure like shields, factories, or artillery – structures effective when turtling. If it’s high, they’re more likely to choose missile turrets, blaster turrets, or outposts – structures effective for quick expansion and harassment. The second factor – effectiveness – makes an AI more likely to choose the best structure to counter an enemy. If you have shields, they’re more likely to pick factories (units can enter the shield) or blasters (bonus vs shields). If you have artillery, they’re more likely to build a shield. Between the two, the AI can make a fair decision on what would be best to build.
When placing a structure, the AI uses one factor primarily – fragility. This is a new value I added that tells the AI how “fragile” the unit is, which basically translates to whether the structure should be placed on the “inside” of their territory (closer to outposts) or on the edge. It’s probably not the most accurate term, since it’s different from the structure’s health or strength – the blaster, for instance, has low health but a fragility of 0, telling the AI to build it close to the edge of their territory. Shields, factories, and artillery have a higher fragility, telling the AI to put it closer to their outposts or core.
Between the two, I’ve seen some interesting habits. The AI is pretty good about placement of outposts – they usually go on the edge of their territory to provide maximum expansion. Turrets are placed in about the right ranges to counter effectively – missiles are usually placed outside the range of blasters, for example. They’re also more likely to use shields or factories, which is great. Overall, I’m extremely pleased that such a small change – and more importantly a change to a simpler design – has resulted in a fairly dynamic AI that behaves well and is easy to tweak.
More importantly, I’ve started to lose against my own AI. The harder AI cheats a bit (it gets more money than the player), but I’m having a hard time out-maneuvering it. Sometimes the AI is downright brutal, using outposts to box me in and restrict my resource capacity, limiting what I can build and leaving me to build blasters on the edge of my territory in a feeble attempt to fight back. And then the AI builds a new outpost, neutralizing my blasters and leaving me powerless, waiting for my inevitable defeat. Which is a wonderful thing when I’m trying to develop a decent AI to play against. Of course, that means I need to tweak some settings so a come-from-behind victory is possible – especially now that I’m finding myself in that position.