This weekend, in Project Skyring, we’re going to start shifting our enemy behavior to a fuzzy logic system versus the more straightforward state behavior we’ve been using so far. This should help the enemies feel more natural and prevent the player from finding easy exploits in enemy AI behavior.
But what do we mean by fuzzy logic? In this case, we’re referring to a buffer between states that adds a question mark for players as to when an enemy state change will occur.
State changes, such as the enemy going from pursuing a random target to pursuing the player are currently handled with a fairly black & white method. A distance is calculated, and if the player is within range, the enemy switches to the attack state. And while the distance required for the enemy to give up the attack is a larger one to avoid an obvious on/off behavior, it is still a constant value. Smart players could eventually figure out just how far to run to “turn the enemies off”, an exploit players often use to kill tougher enemies in action games.
One example that comes to mind from personal experience (and with viewer DecentScrimp’s shared experience) is the old game Legacy of Kain game, Blood Omen 2. There were extremely tough to kill Sarafan guard enemies, but an easy way to dispatch them was to run up, get a backstab, then run out of their pursuit range until they gave up the chase, only to run in and get another stab. (It helped that they were slow to turn around…)
While even with the current state system we have kicking in Project Skyring, it wouldn’t be that cut and dry, it still leaves the enemies feeling a bit mechanical if the player can feel out their ranges. That’s where fuzzy logic will come in for us.
What we want to do is make the state change gradual. If the player is within a certain range, we’ll start adding a small random-ranged value to their “attack meter” that, when full, changes their state from passive to aggressive. We can also add calculations to speed or slow this incrementing process based on how far away the player is. We can also drain this meter by a small random-ranged value if the player is out of range. If we pull it off, it should mean there are no distinct ranges the player can detect because they won’t know which moment the enemy will finally switch states.
Imagine a stealth game, where the player is mostly hidden in shadow, but an enemy is approaching. Rather than having an arbitrary range for when the enemy switches from normal to alert to aggressive, we could fuzz the numbers a bit to keep the player guessing. Of course, too much fuzz means the player doesn’t know what to expect and loses control, which is no good. But too little fuzz, and the game goes from feeling tense to feeling like a puzzle game with clear right and wrong answers.
For a real life example, imagine a snake charmer trying to wow his audience by sweeping his hand near the snake but narrowly avoiding the strike. If the snake only lunged at exactly 15.67cm, for example, there would be no risk, and therefore no drama. But the fact that sometimes the snake doesn’t bother lunging until the charmer’s hand gets to 10cm, other times it only lunges if the hand has been sitting near its face for a few seconds, and other times it lunges right away, the charmer needs to pay attention to the subtle hints that it’s time to get that hand out of the way. (A poor night’s sleep and a little distraction could get the poor entertainer killed.)
Another, less dangerous real life example is something like: “I’ll turn the heater on when it gets cold.” Every human being has a different definition of “cold”, which is further complicated by conditions like how much clothing they have on, whether they just drank a cup of coffee, etc. but even without all that, there’s the moment of decision itself: “It’s a bit chilly, but do I really want to get up off the sofa I warmed to turn the heat on at this moment or wait just a bit longer…?”
When used well, fuzzy logic is also an excellent way to keep enemies fresh. Unless the game is a pixel-perfect platformer (Super Mario Brothers, etc.), a precision skill-based reflex action game (Devil May Cry, etc.), or a pattern-based action game (Psyvariar, etc.) defeating the same enemy can start to feel less and less like a test of skill and more like a chore. Do A, B, C, rinse and repeat. However, even if enemies don’t get to the level of a human opponent, if they are somewhat unpredictable, no situation will ever play out quite the same way twice. On a macro level, the player has an understanding of what behaviors (states) an enemy has and what kind of player behaviors trigger them, but on a micro level they’re not sure exactly when those states will change and have to be prepared for when they do.
Skyring Fuzzy Logic State Changes
enemy chase -> passive
enemy passive -> chase
enemy anchor chase -> player chase
enemy player chase -> anchor chase
enemy player chase -> swarm
enemy ground -> air
enemy air -> ground