ID:53808
 
Keywords: ai, devtalk

How many times have you played a game where you had to sneak past a guard? Probably a few. There are two ways this is usually done, and they both could use improvement. The first way is to have the guard only notice you if you're in the line of sight, but unless the guard is deaf, he's going to miss obvious cues like when you pull out a weapon behind his back. Another way is to have the guard always notice you, which you usually see if you haven't acquired some item or other or you have to sneak around him some other way. But a well-trained guard should notice any suspicious sights or sounds--not necessarily everything, but just about anything. They may also yell for help if they think something is hinky or they're under attack. You can add this level of realism to your game and improve it drastically.

It doesn't take much to add this concept. Just think about it like this: Every time any action happens, it can be sensed by anything capable of perceiving it. It may be visible, audible, maybe tactile, or even have a smell. In a fantasy game, otherworldly sensations like a sudden fear in the presence of evil may also apply. Try adding a few procs like this:

atom
// src causes the event; loop through all viewers, hearers, etc.
proc/SightEvent(brightness, movement)
proc/SoundEvent(soundname, range, volume)
proc/SmellEvent(smellname, range, intensity)

// src takes notice of the event
proc/NoticeSight(atom/A, brightness, movement)
proc/NoticeSound(atom/A, soundname, range, volume)
proc/NoticeSmell(atom/A, smellname, range, intensity)

A sight event is a change in brightness or some appearance of movement. If you're in the dark for instance, your movement might not be easy to see except for monsters gifted with that sense, but shining a flashlight or walking into the room with a lantern will alert them right away. A sound event consists of the sound effect you want to play, the range where it can be heard, and the maximum volume. A smell can be assumed to spread quickly in a given area, have a certain level of intensity, and then dissipate, unless it's something stuck to your clothes (more on that later).

The sight event might work like this, for example:

atom
proc/SightEvent(brightness, movement)
for(var/mob/M in viewers(src))
NoticeSight(src, brightness, movement)

In each case, you would call ___Event() for the object which caused the event. If you draw a weapon, either you or the weapon should be src calling SightEvent() and SoundEvent(). Then each of these procs should loop through any mobs who might see or hear them, and those mobs would in turn run NoticeSight() and NoticeSound(). Picture this scenario: You've taken an invisibility potion to sneak past a guard. You start walking toward him, but with each step he hears you move and he turns around to look. He sees nothing but his alertness level goes up. So you start tiptoeing forward, until finally he seems to relax and turns around. Getting up close, you draw your sword--but he hears the noise and swings his weapon around, dealing you damage! Even though he can't see you, he's aware something must be there so he starts slashing wildly around. Oh, and he calls his buddy a few rooms away, and his voice carries far enough that the other guard can hear it and come to his aid.

Suddenly the stealth factor in the game has gotten a whole lot more important--and more interesting. I've used this technique myself in Scream of the Stickster Volume II. If you're invisible the Stickster won't see you, but if you make a sound he'll come after you.

You can also have attributes, not events, that could be sensed. If for instance you crawled into the castle through the toilet chute, you might not be generating active smell events every time you move (that could get excessive), but every so often the guard could sniff and notice something smelling funny, and keep sniffing more and more as he got more suspicious. If he happened to bump into you, you would be in trouble. (Also, better hope you wiped your feet, or your footprints could be a dead giveaway.) Or maybe he's hearing a faint high-pitched whine from your enchanted shield. In this case what you would use is sort of the opposite of an event.

atom
proc/Look()
proc/Listen()
proc/Sniff()

Every so often the active NPCs would call these procs to find out if anything was going on that was more of a steady thing, like a light where there shouldn't be one or an unusual odor. This would work especially well for guard dogs, who can smell you before they can see or hear you. Whenever one of these procs latches onto something, they would just call NoticeSight() or what have you to trigger the behavior change.

For the most part, all you really have to do is handle stuff like NoticeSight(), NoticeSound(), and so on to make your AI a little more interesting. Attach all this to a few personality traits like alertness, fear, hunger, aggressiveness, curiosity, etc. and you have the basis for some really smart NPCs. Simple enemies (and friends) can make for good gameplay, but adding just a pinch of depth will really make your game stand out.


Lummox JR is the author of the strategy game Incursion, the dungeon crawl Runt, and the action-oriented Scream of the Stickster games. He has been part of the BYOND community since 2001, but is also a professional programmer with experience in C++, Java, and Perl, among other languages. Currently he works full-time as a developer for BYOND.

Perfect article that can be used to improve countless games, definitely a plus for BYOND.
In my unfinished game A Vampire's Solstice I used something similar to this, tied in a sound that is generated with every action, and if it was powerful enough they could track you by that, and by sight and such. Though my system was a lot messier than this design.
While discussing Guard NPCs with Mobius, he suggested other interesting characteristics that could go pretty well with these systems.

Say if your guard NPC was on a patrol around a secured area, they'd turn around at random intervals and make sure nothing was behind them. And seeing as guard duty is considerably boring, they'd occasionally do something to entertain themselves, such as kick/throw a rock.

It would certainly add a challenge. Especially if your a spy or something, and your task is to gain access to secret documents without raising any alarms at all.
Yeah that is a good idea, also maybe falling asleep if he has not moved for awhile, and if you make a loud enough noise he would wake back up.
The way I do the alert levels is if the guards find something suspicious and they are on alert levels, they will call for a lockdown of the area and they will start patrolling every square inch. If they find something suspicious when they aren't on alert, then they will go into alert mode. Anything they find after they will lockdown. Alert mode lasts for a minute and they try to fix whatever alerted them such as a flicked light switch.
Very good article, gonna implement something like this now.
It reminds me of Metal Gear Solid; the guards would follow your footprints in the snow (even if you were invisible), hear the noises you made and react and patrol like Smokey Joe described.
The thing about this is that it isnt just for stealth it means you could attract enemies to certain places enabling you to lay traps etc. Say you plant an old fashioned ticking time bomb, the noise attracts the guards, they go to diffuse it and walk onto a trip mine or something. :D
Scream of the Stickster was actually inspired by a game I used to play, typed in BASIC out of a computing magazine, where you were being followed by a monster who would chase your footprints. To get all the treasures and avoid dying in a dead end, you'd have to lure him down side corridors and then rush by when he was down there.
I like that idea Lyndon, in one of my games I had the player able to whistle to attract attention for ambushes like what you described. Also I had the players able to make noises of a common animal in the area to decrease suspicion.
The AI on "Behind enemy lines" if anyone has ever played it was somewhat similar to what people are describing.

Although I'd classify it as a strategy game, you had to either silently kill the guards and drop their corpses where they wouldn't be seen (or where they would be seen) in order to avoid the alarms being set off making the level harder.

The idea was strategy. Get in, accomplish your mission, and reach the rescue point without being killed or captured.

You'd kill some lone guard, and place the corpse in another patrol guards area to distract him and either sneak up behind and kill him or cut across his patrol path.

It was a very fun and intense game.
I never managed to finish a mission in "Behind enemy lines" Tiberath, the AI was far too good for me (this was quite a few years ago though but I am sure I'd still find it hard :P).
You can view that as a bad point but you can also view it as a good one, it means the player has think more and in a way that is on par with the game as opposed to winging it and going in guns blazing.
Although the AI was indeed hard. I finished a few levels before I moved onto the next big game on that time.

I tend to think the harder the game is, the better. That's why games that wont allow you to choose the hardest difficulty from the beginning bug me.
So far I have made something that uses a vision system like this and simple sound system. I have NPCs that are blind following the sound of your footsteps, Sentries that yell at you when they see or hear you and ones that turn when they hear a sound and chase you when they see you :D

The best thing about this system is that it is quite modular :D I have yet to implement a proper sound dampening system based on sounds becoming quieter over distance but I am sure that will be fun. When done I will probably base any AI in my projects on it :)
Combining this with Lummox JR's other post on AI and ignorance might be interesting :D