Artificial Intelligence: Bystanders
November 18, 2016
A thief has just been discovered hidden among the guests at a ritzy party. What do the guests do? What does security do? And what does the poor thief do? Those were some of the questions that I set out to answer this week when I started developing the various artificial intelligence systems needed for my upcoming Robyn HUD computer game.
In Robyn HUD the player takes on the role of a hacker working from a remote location to help a master thief infiltrate and rob various locations in the game world. Set against these two protagonists are the myriad other characters populating the environments, who need to react in different ways when they encounter the thief. The party scenario from the game design stood out as one that would allow me to determine many of the needs of the artificial intelligence for the game.
When I sat down to think through the problem, I knew I wanted a general framework in place that would handle the responses of agents – the party guests, the guards, the thief – in a generic way. At the same time, I also wanted those responses to be easily customizable. For example, a party guest might go to get refreshments, she might admire a piece of art on display at the party, she might go and have a conversation with another party guest, or she might call for security if she detects the thief.
In considering the three different types of agents in the game, the party guests (or more generically, bystanders) seemed like the easiest to handle. Taking the path of least resistance, I started with them for the AI work.
The first step was to determine a system that would allow for those customized actions without being overly onerous to develop. Put another way, I was looking for a system that would allow me to treat getting a drink, admiring art, and talking to other agents all as if they were the same action. Fortunately, my work on the Sleuthhounds series of point-n-click adventure games was a great asset here.
In the Sleuthhounds games every action that the player can make gives some sort of custom response. The action may be something like constructing a periscope, interrogating a suspect, or just general observing of the environment. Regardless of the case, all actions are built up from a very small set of instructions: a character walks to a specific spot, a character says a specific line of dialog, or a character runs a specific animation. With just a small set of basic instructions like that, it’s possible to compose a great number of seemingly very complex actions.
With that concept in mind, I realized that all the actions that a guest might do at a party in the Robyn HUD game could be similarly broken down. Admiring a painting, for example, would involve a guest walking to the painting and then saying a line about that painting. Talking to another guest would involve walking to that guest and saying a line of dialog to them. Getting a drink means walking to where the drinks are available and running a drink taking animation.
From there it was easy to build a basic system whereby, if the guest is not alerted to the presence of the thief, she will choose an action from her repertoire and wander off to perform the specific basic instructions that make up that action. Currently this choice is purely random, but a bit more intelligence could be built in my tracking how thirsty the guest is, for example, to weight the “get a drink” action to have a higher probability of occurring than the other actions.
It’s not a very complex or sophisticated system for handling the basic “attending a party” actions, but it’s more than sufficient for the needs of the Robyn HUD game. Of course, this system assumes that the agent has not been alerted to the presence of the thief. It’s when that assumption gets violated that things start to become interesting.
When thinking about how I wanted the guests to respond to the thief, I first thought about how real people might respond as opposed to the technical programming side of things. I felt that if a guest saw something strange, such as another guest unobtrusively taking an item of some value, that they would become a little more suspicious. If that guest witnessed another such disturbance they might then call for help. And if things got really serious, the guest might get scared and panic and run away from the source of the disturbance.
As with most stealth based games, I went the route of giving my agents various levels of awareness. As a starting point, which may evolve over time, I currently have four levels of awareness for each of my agents:
- Unaware – The agent hasn’t observed anything suspicious in the environment around them. They can go about with their business as normal. If the thief walks past them but isn’t doing anything suspicious the agent will pay the thief no heed.
- Suspicious – If the agent observes the thief stealing something at a distance or they hear a far off alarm ring they will move from the unaware state to the suspicious state. If the thief walks past a suspicious agent that agent still won’t respond to the thief but they’re getting close.
- Alert – If the agent is at the suspicious state and another disturbance occurs then the agent will go to the alert state. Here’s where the fun begins. If an alert agent sees the thief then she will respond to the thief’s presence. If the agent doesn’t see the thief then she’ll still go about her business as usual.
- Crisis – The agent has become aware of and can either currently or has very recently seen the thief. Here the agent gets to decide how to respond to the thief directly. This may mean calling for security if there are no guards currently coming after the thief, or it may mean fleeing from the thief, or perhaps just crouching and cowering in place. Regardless of the decision, again each of these actions is made up of the basic instructions of walk somewhere, say something, and/or run some animation.
A cooldown period allows the agent to fall back from the crisis level of awareness to the alerted level. However, the agent doesn’t forget who the thief is, so if the thief should happen to wander by again, the agent will once more rise to the crisis level.
Bystanders have simple decision trees. While they can have any number of unique, custom actions to choose from, those actions are fundamentally treated the same way. They’re all made up of combinations of instructions from the basic instruction set.
Guards, on the other hand, require a bit more sophistication. But that’s a discussion for next week.