The artificial intelligence in stealth games has always had the edge over conventional action shooters. When you have actors that live for more than 7 seconds on average, you have more behavior-time to play with!
Thief pioneered the first-person sneaker genre, and is a cornerstone of single player action games in general. It made my list of Top 10 Most Influential AI Games because of it. The game is an interesting blend of suspense and strategy, and provides hours of entertainment — especially for AI developers!
In this week’s technical review, you’ll learn about the best parts of the artificial intelligence: things to steal as well as what to avoid.
Any decision making system is only as good as the information it gets. As the saying goes: “Garbage in, garbage out.” The AI logic itself in Thief is not much different from other games, but it stands out nevertheless thanks to good information.
This article is the basis for the analysis of the sensory system:
Building an AI Sensory System: Examining The Design of Thief: The Dark Project Tom Leonard http://www.gamasutra.com/gdc2003/features/20030307/leonard_01.htm Game Developer's Conference Proceedings, 2003
1) Focus on Seeing and Hearing
First, before designing your sensory system, you need to realize that there are only two senses that are important: audio and visual. So you’re really building an A/V system to cover 99% of all the necessary gameplay elements.
In most games in fact, vision is much more important than audio too, so you can save time by developing that first. It’s also a good idea to get the line-of-sight queries in as soon as possible, as they’ll require a lot of tweaking.
Screenshot 1: Two guards waiting in a room from Thief.
2) Support ‘Extra’ Senses
Even if you focus on seeing and hearing, because you’ve built an artificial sensory system you’ll be able to trick it when necessary — for example by faking sounds if the story needs a reaction from an actor.
In the context of Half-life’s sensory system, here’s an example Tom Leonard brings up:
“The AI ‘hears’ pseudo-sounds, fictional smells emanating from nearby corpses.”
Ultimately, a sensory system is a pipeline for managing information about events that occur in the game. If you implement this right, it shouldn’t be limited to any of the human senses. You can easily fake any kind of sensation by pushing information into the pipeline at the right place.
3) Calculate Sensory Intensity as a Continuous Value
There are many factors that are taken into account when sensing:
For vision, awareness depends on the lighting, size and exposure of the object, distance from other objects, etc.
For sounds, you must consider the intensity of the sound, the fall-off based on distance and geometry.
Ultimately, though, you’ll need to boil down all these factors into a single floating-point value that can be used to determine the level of awareness.
4) Use Discrete Levels of Awareness in the Logic
When it comes to game logic, it’s often a best to use discrete values rather than continuous ones. For the sensory system, you should convert the awareness level into a discrete value: low, medium or high awareness.
The process of deciding on a discrete value of awareness can also include more factors:
Ramp-up delays, used to simulate reaction times.
Cool-down capacitors, which fake short-term memory.
Additionally, the brain has a separate level of alertness which can affect the levels of awareness.
5) Use Configurable View Cones
In Thief, multiple cones are attached to each actor’s position and orientation. The cones can be used to determine if an actor is capable of sensing another object. This models the primary field of view, peripheral vision, and even a sixth sense so that actors know when they’re being followed.
Each of these cones has an angle and maximum distance. They can also be configured differently to provide more or less accurate information, for example the main view cone would be very accurate while the peripheral vision only gives hints.
Screenshot 2: Sneaking up in Thief 3: Deadly Shadows.
6) Context Sensitive Alertness
Each cone has a measure of relevance that depends on the “alertness” of the actor’s AI. This allows the senses of actors to become heightened when something terrible goes wrong — which it inevitably does.
“The alertness state of the AI is fed back into the sensory system in various ways to alter the behavior of the system.”
7) Level of Quality Information
Each of the view cones also supports a set of parameters describing both general acuity and sensitivity to types of stimuli (e.g., motion versus light).
When sensory events are created, they are annotated with different information based on the properties of the cone. So an AI that heard something in the distance will know less about what happened than if it happened in near proximity.
8) Actors with Selective Vision
From a gameplay point of view, it’s frustrating for the players to get attacked by an actor that came out of nowhere. To fix this problem, it can be a good idea to only allow actors to see the players when they’re ready.
As Tom says about Half-life’s implementation:
“Most interesting is the snippet that restrains the AI’s ability to see the player until seen by the player, which is purely for coordinating the player’s entertainment.”
With such an ambitious sensory system in place, Thief needs quite a few techniques to make sure the implementation was up to the challenge.
9) Decouple Sensory System and Decision Making
Using the concept of a sensory system in the software is a good excuse to setup a modular implementation. By making it a separate module, you can decouple the process of gathering of information from the decision making — which will reduce the complexity of the whole system.
The module at the end of the pipeline does not really care how the information was acquired. The only shared dependency is the storage itself, specifically implemented using sense links. These links can be used to communicate sensory events, each filled with the necessary information about what happened.
As a side note, this separation of concerns and the decoupling using a pipeline is ideal for multi-threading architectures, though it’s not used in Thief.
10) Optimize for Player Proximity and Importance
A sensory system can be rather expensive on the computation budget, even if it’s setup to use different threads. Thief includes basic level-of-detail logic to reduce the need for sensory checks when the player is far away.
Intuitively speaking, most of the important action is around the player, so why spend too much computation on other parts of the level?
11) Setup Event Filters in the Most Efficient Order
The sensory pipeline performs a variety of conditional checks before the event information is left to pass through. Each of these conditions has a different complexity, varying from fully-blown 3D raycasts to distance checks.
Since these checks are used to filter out events from the pipeline, it makes sense to use the cheapest checks first to make sure that no more processing is done if the event would be discarded anyway.
On top of the industrial strength sensory system, Thief uses pretty much standard AI logic (a finite state machine). But an interesting twist is that the behaviors are used very cleverly to support the gameplay.
12) Easily Understandable Actors
Since Thief is a first-person sneaker game, there’s lots of interaction between the players and the AI actors. It’s important for the player to understand what’s going on in the mind of each actor, particularly in the process of sneaking through a room or hiding in the shadows.
Thief uses voice recordings to explain to the player what each actor is doing. Things like:
“What was that noise?”
“Must have been the wind.”
The down-side of Thief’s approach is that it provides almost too much information. The human brain is great at assuming things, and by giving the player less (but important) information, you can use the power of imagination to help. On top of that, it’s frustrating to hear the actors talking constantly. More recent games use less explicit sounds like radio signals, which is much cooler than a guard talking to himself.
13) Use Predictable Behaviors
Making it easy for the player to understand the current state of actors is also important because it helps to predict the next move. If it’s necessary to sneak up on a guard, he must have a very regular and predictable patrol route to make it fun for the player.
Each of the idle behaviors of the characters have a regular pattern to them, yet they have a certain amount of variation thrown in to make the behaviors a bit more interesting. The game is a bit more challenging too if you’re not playing against a “robotic” AI.
14) Actors that Are Fun to Watch
People watching is fun. In a stealth game, it’s part of the gameplay; you have observe actors to pick your moment to sneak up on them.
The actors don’t have to be very intelligent, as being watched is a one-way, non reactive behavior. So you can script that easily. Remember to use a bit of humor to make it more entertaining, not just a boring routine!
Next week’s review on AiGameDev.com looks into a different style of game, perhaps something even more strategic.