Making guards search in a stealth game (MaskedDetecitve Devblog #2)
Hi, I'm working on a stealth game were you play a comicbook detective who uses superpowers to sneak, spy, steal, and escape. It's been a productive time since my first blog post about this project, and I want to talk a bit about the AI in the game, particularly thoughts on searching behaviour both from the perspective of design and programming.
What have I done since last time?
A short video of the this very early Alpha, extremely subject to changes.
Since last time I finished some work on the AI around things like searching and their simple punch attacks. I also worked on a very early version of the memory-erase ability.
Game Design is often about push and pull; finding that sweet spot where the player feels they can influence their destiny, while still feeling contention from the game. For my memory-erasing gameplay I need the player to experience a simple loop:
- Being discovered
Sneaking and being discovered should be the easy parts, it's balancing the evasion and hunting steps that matters. First, I need the memory-erase ability to actually require "hunting". I decided to make it a short-distance ability that works only on enemies facing away from you. This means you can't just run up to an enemy and get them; you need to carefully stalk them.
Additionally, it means you can't immediately use it after discovery; you have to lose them first. That's the evasion step.
To help get the balance on this right, the NPCs run very fast if they can see you, go at a medium speed for a bit after losing you, but then slow down again a short while later as they're combing around for you. This way you're not having to chase an enemy who is always sprinting. The player is faster than the NPCs, but has a stamina pool that becomes visible after 20% depletion; this gives you a window of time to lose the NPCs.
The memory-erase ability causes the NPCs to become stunned for a period of time. This time period effectively acts as a soft-window in which you likely need to get all currently alert NPCs, otherwise they will just re-alert each other when they leave the stun. Getting the balance on that correct may prove challenging, but that'll be a future task. I suspect I may end up with a secondary memory-erase ability that is resource limited but a bit more flexible, to help with some of the stickier situations with multiple NPCs. The search behaviour tries to spread the NPCs out, which is both believable and gives the player a helping hand.
I expect this area of the design to need a lot of iteration as I develop the game, find new problems, try to make it more interesting, or try to find ways to keep it fresh. But for now, it works, and it's already a little challenging. So I'm hopeful that I'll be able to get something interesting as I refine it and flesh it out more.
Searching presents a number of interesting challenges to designers and programmers. It influences how players feel about the NPCs because it's very easy to write search behaviour that feels very stupid; in Thief for example the guards quite often search around in ways that have them mostly staring at walls from a point-blank distance. But on the other hand, if you make it too smart you actually create a problem.
About a decade ago I hit on this exact issue with a little Guard AI test I programmed for a top-down game. I wanted guards that felt like they were actually intelligent, and therefore made escaping from them feel special.
Rather than picking random near points to wander to a better approach seemed pretty obvious: when the AI loses sight of the player, track the space they could possibly be. I did this by dividing the world into a grid, and the AI knows the player had to start from that grid position. From there, you have the AI expand the possibility space in the grid at roughly the running speed of the player. You remove spots they can see from the possibility space, and obviously make the space only expand into grid positions that can actually be walked through (so not into walls).
This way, if the AI sees the player run down a dead end corridor, and has sight of the only exit/entrance, they'll know the player can only be in the corridor. From there, searching is as simple as picking a point in the possibility space (generally the oldest) and sending the NPC to go look at it. I recently learned that this approach appears to be quite similar to the one used by Dishonored 2.
Too Smart For Its Own Good
This works extremely well, and isn't too crazy for a computer to compute. But I had a problem: now the guards were too good at finding the player. The game requires the chance that you can get away, and AI that perfectly determines where the player can and can't be often lowers that chance too much! Giving the player powerful means of evasion can help counter this, but I found it difficult to do so in that old prototype without giving the player too much power. It seems particularly hard to balance evasion.
This is part of my reason for picking the memory-erasing idea. For my game the push-and-pull is more around the pressure to erase memories before time runs out, rather than the pressure to not be found. This means I can make the player pretty good at evasion, as they have to actively put themselves back into danger in order to erase memories.
So, I used a similar search approach for this prototype. However, rather than a grid, I used the points of the navigation mesh, and rather than slowly expanding the area, I simply give every near nav-point a score based on its proximity to the player's starting point. When the NPCs see a point they mark it as low-score, and the scores grow back up as long as they aren't being looked at. A key difference is this means the search area is never actually fully erased, and if they check every where they simply will start to re-check everything.
As with everything, there's a likelyhood of me tweaking this more later, but for now I'm quite happy with the approach.
So what's next? The near-term goals at this stage are:
- Get a few powers in
- Make a test level
Obviously that second one is easier said than done. I'll also probably do other small tweaks and additions as I feel like it. In the next three weeks I'll make another blog post about my thoughts on designing this test level, and how it's going. I expect to be a bit of a mid-way progress report.
You can follow this project via RSS (Don't know RSS?), or by following me on Mastodon. And of course feel free to contact me via email, or Mastodon with any comments or questions.