Thursday, 15 November 2007

Unangband monster AI - part six (Conclusions)

Well, what conclusions can I draw from my experience so far with the Unangband monster AI? I'll stick with listing a set of principles that have proved to be a useful guiding framework for anyone else working with roguelike (and other game) AI.

  1. Complex behaviour can emerge from simple rules. There's a great article on swarming behaviour in the New York times that demonstrates the real world rules that ants and other animals use which results in highly sophisticated emergent systems. By adding the MFLAG_PUSH, I was able to get monsters to move in group formations without requiring any global rules. In general, the programmer in you will want to make things complicated. Resist it.
  2. The corollary to the above: Experiment with simple rules first and observe what behaviour emerges. Then see if you can modify the rules to get the desired results and accommodate additional actions. With a simple rule set, it is very easy to determine what underlying monster states result in a particular AI action. The hardest to debug problems I found were where a complex series of tests were used to determine which of a binary choice to select; the easiest where when simple tests were used to determine a range of possible actions.
  3. Monsters are more interesting when they are advancing. In particular, anything that the monster does that threatens the player is perceived as intelligent, be it moving forward, casting spells or shooting arrows. Both the Angband and 4GAI rely primarily on a couple of random checks ('do I try to use a ranged attack?' and 'which ranged attack?') which results in a complex seeming set of behaviours across a range of monster types, by giving each monster a different set of possible choices to make. The underlying algorithms are not sophisticated.
  4. The corrollary: Invest more time in developing AI for monsters when they flee. As soon as a monster stops advancing, you've got the challenge of keeping them interesting and these times will be the point at which the player notices poorly behaved AI routines. I was lucky in this respect that the 4GAI delivers a great platform here, and very little work has been required to improve on it (in fact, I just added bleeding, so that a player can track a wounded monster when it's fled out of sight).
  5. Minimise the number of commands required to control your allies. This was something I decided early on, and it works well. Despite having large numbers of allied monsters, the fact that you don't have to explicitly tell them where to go or what to do means that they feel helpful as opposed to a hindrance. It's not just a matter of having them move out of the way if you walk into them. They should use that as an indication to press forward, or take cover elsewhere. Similarly, if you're shooting at something, maybe they should be shooting at it too.
  6. The corrollary: Have your allies try to do 'the right thing' and do it well. Sure, you can minimise the number of ways of telling them what to do, as long as what they do, they do well. So I deliberately hacked the allied monster AI so that they always fire when they are at the right range (the 'do I use a ranged attack' is always yes), and for a long time, monster vs monster combat never had any misses. Now it's just accelerated so that monsters do double-damage to each other. Monsters should be able to cheat when they fight each other, because the player will get the impression that his allies are effective, while they shouldn't cheat against the player, for the same reason.
  7. Have enemies tell the player what they are doing, ideally, before they do it. And then tell the player what they did. F.E.A.R. is still acclaimed as having some of the best AI of any first person shooter. I was able to take that and expose some pre-existing Angband AI which players may not be aware existed in the game, using the same principles, and added a lot of flavour to combat as a result.
  8. The corollary: If the player doesn't see or hear about it, it didn't happen. Don't waste time on developing a fully featured AI system, where monsters intelligently wander around the dungeon of their own accord. Unless you are developing a stealth-based roguelike, there is little to no chance that the player will see and understand what they are doing. I simultaneously developed a 'living' dungeon generator, where wolves could be found in kennels, warriors in throne rooms, and priests in temples, and this added much more flavour than I could have done by having out of sight monsters talking to each other, trading items or trying to kill each other. In most games, these events are heavily scripted and taken out of the AI realm. In a roguelike, you don't have the control of the game space enough (due to random dungeon generation) to deliver these experiences.
  9. Finally, design monsters with a range of behaviours, and have each behaviour work well with that monster's abilities. It's not good having weak melee monsters advance towards the player, they should stay at range. Similarly, melee monsters should be able to advance - ensure that they can bash through or open doors and other obstacles. The variety of terrain in Unangband is passable by different monsters in a variety of ways. And most monsters should be given a ranged attack along side their melee attacks, even if it is not terribly effective.
  10. The corollary: Ensure that the player has a means of countering each monster attack and defense, or that the attacks are not inexhaustable. Magic using monsters should have a limited mana, archers should run out of arrows or have them destroyed by player acid and fire, summoners should not be able to overwhelm the player in numbers. Each monster should have exploitable weaknesses to keep them interesting.
Well, that's it for the moment. I'll provide an annotated explanation of the code in a further follow-up. Please feel free to ask for additional clarification on anything I've discussed - I've not really done justice to either the 4GAI or Angband's original AI in this series, and I'm sure you have plenty of questions.

6 comments:

James McNeill said...

I've enjoyed reading this series. Thanks for writing it!

When work lets up a bit I'll have to give Unangband a try. I played for about ten minutes a week or two ago but did not make much headway. My primary prior Roguelike experience is with Rogue itself, so the various successors are pretty overwhelming.

Dai Conrad said...

Great blog series on a fascinating topic. My only question is, have you ever considered whether some monsters should avoid powerful characters? For example, should a single rat really run up to a high-level character and basically commit suicide? Should they only attack if they heavily outnumber the character?

I'm not just talking about running away after they've taken some damage, I mean if the monster is overmatched to a sufficient degree, should it attack at all? Or does the monster generation in Unangband ensure that by the time the character is powerful enough, only comparatively powerful monsters are generated? I'd be interested to hear your thoughts on this.

Andrew Doull said...

Dai: There's a couple of mechanics around what you're discussing.

Firstly, Angband will allow monsters from any level less than your own to be generated. So you can run into a rat, just before you take on the final fight, for instance.

However, there is an AI routine to ensure that the rat will always attempt to run away from you and only fight if cornered. It's not very CPU efficient (in fact probably the most expensive CPU-wise of any of the AI), so Leon as a part of the 4GAI improved this .

The reason these exist, is that items dropped by monsters are based on the average of dungeon depth and monster level. So low level monsters exist to allow the player to find still useful low level finds relatively easily. I compensate for this in Unangband by making low level items appear in piles instead - and less frequently.

And the other modification in Unangband is that monsters only appear in a tight range of levels. You'll only find monsters from 5 levels earlier in the dungeon in Unangband. This has significant consequences for the overall power curve. I'll discuss this more in the dungeon generation series of articles.

Christer Nyfält said...

Very informative and useful article series.

Have you improved the AI since you wrote them?

Andrew Doull said...

Not really: there's a lot of code maintenance and rearchitecture tasks in Unangband at the moment, and the AI runs pretty well. Any degenerate cases are primarily around navigating the additional terrain types in Unangband. I can handle that more easily by just generating monsters on the level capable of moving through all the terrain types instead.

dm.Black said...

Usefull information. Thanks.