AI Rework – EmotionController

So, I may have skipped ahead a little in the previous post. We need a system to control which emotion is currently strongest in a creature, and what they do as a result.

Before we go into that though, let me introduce you to the Other Most Important Node in BehaviorTrees. The first one was the “Sequence” node, which we originally discussed back here.

The second one is the “Selector“. It’s basically an inverted Sequence:

– A Sequence runs though the nodes in it’s purview, advancing to the next one when the previous one succeeds, and Failing if one fails.
– A Selector does the opposite: it runs through the nodes in it’s purview, advancing to the next one if the previous on fails and Succeeding if any of them succeed.

This is brilliant for when you have multiple ways of achieving the same goal: it means that if the first method fails, they can fall back to the second, then the third and so on. For example, for an omnivore that prefers meat:

selector

The selector would start the Hunt behavior. If Hunt failed, maybe because there was no prey to be found or the would-be prey had really big, scary teeth, it would advance to Scavenge. If Scavenge also failed, it would advance to Eat Tree, and so on.

Only when one of these food-finding strategies succeeded would the ‘Seek Food‘ selector as a whole succeed.

Selectors are rarer than Sequences, but no less important: without them, the tree wouldn’t be capable of ‘intelligent’ decision making.

Okay, now that you’re familiar with that concept, let me introduce you to “EmotionController“.

controller

This is a unique composite node near the top of the tree. It has six “Emotion” nodes.

Each Emotion is a Selector, and will be filled with ways of sating that emotion: the ‘Seek Food‘ selector above would belong with the Hunger emotion. At this point it becomes closer to a cause-and-effect Needs system rather than a fuzzier Emotion one. I’m okay with this: it makes the creature’s behavior a bit more understandable.

It was this structure that lead to me requiring a way for creatures to respond to Pain, which lead to the implementation of Sleep, as discussed in the last post.

The EmotionController itself isn’t a selector though: it’s behavior is a lot more complicated. I’ll explain it as best I can…

Each Emotion has a Value, determined from a constantly evaluated Base equation (for example, hunger is always inversely proportional to energy), and a more dynamic Floating one (for example, being attacked triggers a flash of fear which fades over time). This value determines the current priority of the emotion.

very placeholder such art

very placeholder such art

When any emotion succeeds or fails, the creature will reassess the urgency of all it’s emotions and act on the strongest. The concept is similar to a Repeat node, except with a variety of options to choose from depending on the strongest emotion at the time.

At this stage, the design makes the creature’s very single-minded. If they start seeking food, they will continue seeking food until they either find it or exhaust every possible food-seeking strategy (or die a horrifying death, but that’s a given). This is a good strategy in general, but it makes no concessions to interruptions. Waiting to finish your meal before reacting to the Murderus deathicus that is currently tearing your limbs off is not the model of intelligence that I was going for.

So I introduced an interrupt mechanism to the EmotionController. If an emotion exceeds the Currently-Being-Acted-Upon emotion (I may need to work out a more concise name for that), the creature will immediately fail the previous emotion (and any child routines that happen to be running) and begin acting on the new one.

This strategy is better, but it has a major problem: it leads to behavior loops, where a creature gets stuck between two states. Imagine a creature with low Energy and Health: it eats for a frame to raise Energy, then interrupts to pain, sleeps for a frame to raise Health, and interrupts back to hunger. Rinse and repeat.

The solution I’m using for this is an urgency threshold for each emotion, specifically for interrupts. Fear and Anger, for instance, have a very low threshold: if they exceed the currently prioritised emotion, the creature will react *immediately* and flee or fight whatever triggered the interruption. Pain, hunger, discomfort and amorousness all have much larger modifiers: to interrupt hunger and cause sleep, pain needs to exceed hunger plus a large modifier.

This doesn’t actually prevent loops: it just lengthens them. Hypothetically, a hungry creature on the edge of a strong temperature gradient like a lava-field could venture into the field to eat, only to be interrupted by discomfort, retreat back to the comfortable area, and interrupt back to hunger again. But with a sufficiently high urgency threshold on the relevant emotions, this behavior is likely to be much rarer.

It’s not particularly unrealistic either: biological organisms get stuck in loops all the time…

Loop
Source: http://xkcd.com/1411/

I’ve been spending quite a bit of time tweaking the emotional systems, to the point that it now works reasonably well. Some emotions require unique attributes to ensure correct behavior: for instance, “discomfort“, “pain” and “fear” have no maximum, so that in extreme situations (spreading lava, for instance) they will be prioritised even if other, more limited emotions (like hunger or amorousness) are near 100%.

Even with very basic placeholder behaviors (the ones implemented so far are “eat tree“, “wander“, “sleep” (idle + healing) and “move to more comfortable area“*), the system is proving its worth. We can plonk down a temperature device and watch the creatures respond to the added discomfort and flee. Plus there’s signs of improvement in their life cycle: rather than the uncontrolled randomness of before, new creatures act sanely: they seek food initially, then sleep to convert that food to health, which they can use to begin a pregnancy and produce babies.

Additionally, if they manage to gather food well enough to reach a “well fed and healed” state, they then start to act on the lower-priority emotions: discomfort and amorousness.

Finally, the new system is much more communicable. The debug method for showing their priority emotion at the moment is simply printing text above their head, which looks terrible above crowds, but “hungry: seeking food” and “exhausted: sleeping” are infinitely more interesting than “approaching tree because REASONS” and “attacking own offspring because SHUT UP THAT’S WHY“. I’ll need to find a way to communicate that information, because it really adds to the sense of character you get from the creatures.

It’s rapidly becoming apparent that this update is going to have some far-reaching consequences on the game as a whole. And, as always, I have no way of predicting what they’ll be. It’s as much a process of discovery for me as anyone!

I love this job.

*footnote: I really need a more concise term for “move to a more comfortable area”. A term for travelling to a more hospitable climate… oh, of course! “Migrate“!

… and I’ve implemented a much-requested feature without realising it again, haven’t I?

Advertisements
  1. #1 by Robert Rendell on November 11, 2014 - 11:07 am

    Do you plan to make the behaviour tree itself subject to evolution? For example, the order the emotions are evaluated by the EmotionController could be different for each creature, encoded in the genome and randomly mutated occasionally. The “urgency thresholds” for each emotion could likewise be encoded in a creature’s genes.

  2. #2 by ququasar on November 11, 2014 - 12:30 pm

    Creatures will still have personality genes, probably manifesting as a multiplier for each emotion (lessee, we’ve got gluttony, wrath, sloth and lust… I suppose the other two would be cowardice and… mobility? Damit discomfort, you’re messing up my analogy). So rather than reacting when fear is lower, the multiplier will make it go higher. The effect will be the same, but it’ll be more communicative in the User Interface.

    As far as adjusting the tree itself based on genes goes, I’ll be trying to keep things as intuitive as possible, and in many cases that means reducing the number of genes. For instance, “preferred food” and “dietary needs” could be two seperate genes, but having certain creatures do poorly because of the invisible “preferred food” gene would be unintuitive. So what they prefer to eat (and thus what order they pick food strategies in) will be rationally decided based on their diet genes rather than independant behavioral ones.

  3. #3 by Christiaan Bakker (@AniCator) on November 11, 2014 - 1:13 pm

    These recent posts about behavior trees have been a very interesting read. I kinda wish you’d put up more videos of the code in action. Like a before/after video maybe with some arrows pointing at the magic of behavior trees in action.

  1. AI Rework – Hunting | Species Development Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: