8th May 2020 – Perry
“Caverns mode has posed a particular challenge in developing the AI, since from one test to the next, something entirely different happens.“
In previous blogs we’ve written about the nuances of the spider AI and goblin warrior AI, but we haven’t talked much about the AI in general.
First of all, what do I mean by AI? In this case, it is the code that controls the behaviour of ally and enemy units, and to a degree the player’s units too. For the player, it simply controls the units priorities (when they’re not being controlled manually). As an example, a miner will work on mining tiles within their allocated instruction zone, unless they’re hungry or tired in which case they will take a break and go for a meal or a rest instead. Ally or enemy AI however must also define where these instructions go, and what buildings to build, and where.
In the campaign, ally AI is mostly scripted, so the map defines what they do and where, and we can be careful not to create scenarios that are confusing for the AI. This is not the case for caverns mode however, which is a randomly generated environment, so anything can and will happen. In this case, the AI must be an agent, that interacts with a world that we can’t predict or ‘hard-code’. Instead of scripting locations to work on, it must decide for itself where the best locations to mine, forage and build are.
Caverns mode has posed a particular challenge in developing the AI, since from one test to the next, something entirely different happens. During playtests, when I discover the AI has gotten stuck or experienced a bug, I can reason easily enough how to fix it, but I can never be sure whether I have or not, since the next time I test it it’s an entirely different scenario.
As an added complication, the environment is (almost) fully destructible, and has class-specific obstructions that prevent access to either resources or enemies. That rules out certain assumptions I can make about whether a unit can reach its target. It might not be able to now, but a few seconds later, maybe it can. To add to this issue, all the entities in the game are determined through properties that can be modified either through scripts or even in-game (the intention is for modded content eventually). This means I can’t assume anything about a particular entity, I can only see what its properties are. All of this together means the AI can get confused in very specific circumstances, and it’s not always clear-cut what those are or how to solve them.
There are still a couple of scenarios that I don’t really know the answer to yet. One such scenario is when there’s an enemy across a river. When an AI agent encounters an enemy, dealing with them takes priority over other work, which makes sense in your usual scenario. However, when there’s an obstruction in the way, like a river, this causes two enemy units to stand by the river’s edge and yell curses at each other all day, instead of working.
Although I can tell the units to ignore an enemy if they can’t reach them, how do I know when to stop ignoring them? Due to the destructible environment, it could be seconds or hours before there’s an accessible path, and it may be an entirely different route to the one that was obstructing them in the first place. My present solution is to simply wait a number of seconds before considering dealing with a particular enemy again. This will take some refinement however, since it’s unclear how many seconds will a) allow the unit to be productive with work, and b) not make the unit exploitable by ignoring an enemy for too long. Only time (and lots of playtesting) will tell if this is an effective solution.
As for new developments in the AI, I will save that for a future blog. I believe the game will see a small update soon (mostly with bug-fixes), so stay tuned for that. Until next time, keep your helmets on and your axes sharp!