This week things get more technical as we shine a light on the Artifical Intelligence, or AI, that controls opponents in the game.
If you’ve played the later scenarios of the combat demo, you may have found the AI serviceable already. Once we have all the core mechanics of the game in place and things won’t change around all the time anymore, we’ll invest more work into the AI in order to have it actually stand out. Let’s find out how it works exactly.
Our goals
As we stated before, our goal is to have different enemies feel distinct to fight against. We don’t want enemies to differ merely in a few stats, such as having more or less hitpoints. There are two ways to achieve this, as we see it; the first one is having unique skills that give enemies tools to challenge the player in different ways, and that require the player to formulate different tactics to overcome. The second one is having enemies behave differently, as determined by their AI.
With the AI we take a simulationist approach, meaning that we try to tailor the behavior of enemies to simulate a behavior befitting what they are in the context of the game world.
Zombies, for example, have an intentionally gimped AI. They don’t care if they’re stuck in swamp, have a height disadvantage or are outnumbered. They’ll just charge into the nearest opponent and won’t even make use of the more specialized skills of their weapons. In other words, they’re stupid. By being this stupid, however, they also feel more unique an opponent and more like you would expect the typical zombie to behave. If you play your cards right, you can outsmart a group of zombies much larger than your group.
On the other hand there are skeletons, their undead relatives. We decided that skeletons should have more of a cold and efficient intelligence, governed by faded memories of long gone battles and military exercise. Skeletons do care about the terrain they are on and about height advantages. They also make full use of their equipment; they form a shieldwall if pelted with arrows from afar or if outnumbered, they use axes to split shields if they can not hit their opponents otherwise, they use their shields to knock down opponents from elevated positions to claim them for themselves, and they might even decide to hold a defensible position instead of charging into the fray.
What skeletons don’t do is lying in ambush or do long-winded flanking maneuvers. Such tactics, for us, don’t really fit the undead. Instead, it will be the living opponents who’ll employ them. Goblins, for example, will put great emphasis on setting up ambushes and doing hit-and-run tactics.
How it works
Battle Brothers has a utility-based AI with relative utility. I’ll explain what the hell that means below, but if you’re really interested in the technical details, I can recommend this great presentation from Kevin Dill and Dave Mark explaining the concept in detail.
Every type of enemy has a bunch of potential behaviors to choose from whenever it is his turn to act. As an example, let us consider this hypothetical scenario: We are a skeleton, armed with an axe and a shield, and face a Battle Brother who has his shield up.
For simplicity’s sake, we can choose between the following three behaviors:
- Doing a Chop attack to injure or kill our opponent
- Using Split Shield to get rid of our opponent’s shield
- Using Shieldwall for protection
So what behavior do we choose? We’ll look at each possible behavior to determine how much sense it makes to use it in this very situation, how useful it is to us, or in other words, how high its utility is. All these considerations need to be quantified so that we can compare between numbers. For the sake of this example, let us rate any behavior in our situation on a scale of 1 to 10. This number is our relative utility.
Do we do the chop attack?
The higher the chance to hit and the more damage we can do, the more we want to just attack. On the other hand, if our chances to score a hit are low, then we aren’t that enthusiastic about doing an attack. We have a low chance to hit our opponent here because his shield is up, so the utility score of an attack would be relatively low, let’s say 3.
Do we split our opponent’s shield in two?
The harder our opponent is to hit, the more we want to get rid of his shield. If his shield is poor or battered already, that’s even more reason to get it out of the way. On the other hand, if we have but a small hatchet and our opponent has a knightly shield, attempting to split his shield may be a waste of time. Because here our opponent has his shield up and makes it difficult to hit his body, the utility of destroying his shield and thereby increasing our chance to hit with following attacks is high, let’s say a 9.
Do we use shieldwall?
If we are at any kind of disadvantage, whether because of terrain or because we are outnumbered, we want to give ourselves more protection. Using shieldwall is helpful in our little duel, but we could just as well do another attack instead – we’ll give it an average score of 5.
In reality, there are a lot more considerations going on, of course, but this is the basic idea. As you probably already figured out, there isn’t just one single behavior that viably applies to our situation. In fact, often there isn’t even one behavior that can be said to be the best for a given situation.
After all possible behaviors have been considered and given a utility score like above, they’re entered into a pool. Everything with a utility of 2 or lower is thrown out so that we don’t pick a behavior that really makes little to no sense in our situation. Then, we pick one by weighted random. Every behavior in the pool could be picked, but the higher the utility, the more likely it is to be picked. Think of throwing a dart on the pie chart below; it’s most likely to hit the Split Shield part, but you could hit any of the other two as well.
This way, we always have an element of unpredictability in how the AI behaves. The AI won’t always do the same in every situation, and it can on occasion surprise you. But it will attempt to do what are the most sensible things to do in the very specific situation it is in.
There is more?
Yes, quite a lot in fact. This part covered the basics and should give an idea on how the AI works on a basic level and why it doesn’t do the same thing all the time. In a possible later article we may look in more detail at specific parts of the AI and how they contribute to enemies that feel unique to fight against.
Very interesting stuff. I wonder how a more sophisticated enemy’s utility chart ends up looking like!
Interesting. If you do it like that though, it will probably be a bit hard to tweak if you want intelligent surrounding and ambushing tactics with that system because for strategy you have to think a few turns ahead, with this model, you’ll only be able to include short-term tactics rather than a strategy.
We’ve found that often the tactical situation changes so much within a single round that it necessitates a complete reassessment of the situation anyway. Generally speaking, the gameplay seems to favor an AI that makes intelligent short-term decisions over long-term decisions because of how easily individual characters can die. This is amplified by our simulationist approach of having every opponent have his own AI, with its own limited knowledge, as opposed to a single central AI aggregating all the knowledge of all the AI entities. That said, the article covers only a very basic example. There are a number of behaviors that relate to positioning and engaging opponents that take into consideration, among other things, the relative positioning of allies and opponents, terrain chokepoints and persistency to pursue a behavior over several turns. Those integrate into the utility-based system and allow for executing a plan over several turns based on how the tactical situation is likely to look in the near future. Still, like you said, there’s a lot of tweaking necessary for this to balance out and for diserable behaviors to emerge naturally.
Thanks for the article; good stuff.
Much as I expected, too. If I understand correctly; the AI doesn’t really think “formations”, except as dictated by the utility functions. That seems like it could potentially be a weakness.
Does it do any sort of evaluation based on whether an ally is in a better position? E.g., Enemies A and B are facing X, and about to go in that order. B is much stronger than A, and only one of them can attack X. The smart thing to do in that situation is for A to perform a support action or attempt to outflank, allowing B to perform an attack. An AI that only considers the individual moves would have A go in the way of B.
For your intelligent foes, at least, that would seem a less than ideal situation (for zombies, of course, it would be natural).
All in all, though, I’m fairly impressed with the AI in the game. Seems like you have tuned your utility functions pretty well. Gives me hope for myself. :-D