AI is a huge topic, and it can range from if-then-else to incredibly complicated systems, meshing different techniques together to create the ultimate autonomous agents. There are plenty of choices out there, some more suitable than others. Suitability really depends on the game genre, the agents that we want simulate, how smart should they be, how capable should they be, how much emergent gameplay can they facilitate, etc.
- In Age of Transcendence, as in most RPGs/roguelikes, most enemies are not around for long. So, incredible development effort on AI will most likely be wasted. You can’t see how smart the angry hungry wolf is, if it’s there for 5 turns! So, Keep It Simple for standard enemies.
- In The Future, when I add NPC adventurers into the game, because they need to survive for far longer, they’ll need better AI than run-of-the-mill monsters.
- Different monsters need to behave differently, to have some variation. A wolf attacks with its pack, an archer will try to shoot you from afar, a zombie will come to smash your face from up close. Dnd 4th edition has this lovely breakdown of monster roles (here’s a nice write-up).
This is by all means not a complete list, just a few I know and I’ve contemplated using one time or another:
- If-then-else. The basics! We need to start from here, AI 101, the zombie: If character in sight, then if in melee distance, attack, else move towards melee distance.
- (H)FSM. Tempting approach due to its simplicity, but when things get complex, it becomes a nightmare to edit/maintain.
- GOAP. Well-used approach, typically for real-time games. As long as we abstract our game logic into the things GOAP needs (world state, available actions, action cost, action preconditions and effects), then we can request action plans (a list of sequential actions) that can be used to achieve a goal (e.g. kill all visible threats)
- Behavior trees. Another well-used approach, they became very popular, but their popularity has been in steady decline. There’s a recent article that advocate them being used more for agent actuation (executing a plan) rather than decision making
- Utility AI. This is another relatively recent method, that assigns utility value to available actions, and selects the appropriate course of action based on what has the greatest utility. It’s a nice system, but it’s number-sensitive (== a lot of time spent in designing/testing curves)
After testing in toy scenarios all of these techniques, I’m most inclined to start with the venerable if-then-else. In fact, because it’s so simple, I’ve already implemented 2 basic enemy behaviours, the “basic melee” and the “basic ranged”.
The basic melee enemy wanders until they see the player. When they see the player, they plan a path towards them, and when they get in melee distance, they attack.
The basic ranged enemy wanders until they see the player. When they see the player, if the range is appropriate, they perform a ranged attack. If the player is too close, they flee using an appropriate flee map. The flee map is the well-described variation of Dijkstra map, inverted, scaled and rescanned.
Because it’s such a common scenario, I’ve added the ability for creatures to be able to open doors if their intelligence is high enough, so that they can flee/chase more effectively.
Where to go from here? The first few steps:
- Instead of using the default attacks, try and use any available abilities
- Occasionally use any consumables
- Start forming AI archetypes like dnd4’s monster roles.
- The enemy FoV and planned path can be visualized with a hotkey
- When enemies swap positions (they can), a cooldown needs to pass before they can swap again, otherwise they can be perpetually swap while trying to get to the player
- Dead creatures dump their inventory
- Enchantments are now color-coded based on if they are beneficial or not (green vs red)
Here’s a video that shows all the above