Making decisions with goal-oriented behaviors

Goal-oriented behaviors are a set of techniques aimed at giving agents not only a sense of intelligence, but also a sense of free will, once a goal is defined, and given a set of rules to choose from.

Imagine that we're developing a trooper agent that needs to only reach the endpoint of capturing the flag (the main goal), while taking care of its life and ammo (the inner goals for reaching the first). One way of implementing it is by using a general-purpose algorithm for handling goals, so the agent develops something similar to free will.

Getting ready

We will learn how to create a goal-based action selector that chooses an action considering the main goal, avoids unintentional actions with disrupting effects, and takes an action's duration into account. Just like the previous recipe, this requires the modeling of goals in terms of numerical values.

How to do it...

Along with the action chooser, we will create base classes for actions and goals:

  1. Create the base class for modeling actions:
    using UnityEngine;
    using System.Collections;
    
    public class ActionGOB : MonoBehaviour
    {
        public virtual float GetGoalChange(GoalGOB goal)
        {
            return 0f;
        }
    
        public virtual float GetDuration()
        {
            return 0f;
        }
    }
  2. Create the GoalGOB parent class with member functions:
    using UnityEngine;
    using System.Collections;
    
    public class GoalGOB
    {
        public string name;
        public float value;
        public float change;
    }
  3. Define the proper functions to handle discontentment and change over time:
    public virtual float GetDiscontentment(float newValue)
    {
        return newValue * newValue;
    }
    
    public virtual float GetChange()
    {
        return 0f;
    }
  4. Define the ActionChooser class:
    using UnityEngine;
    using System.Collections;
    
    public class ActionChooser : MonoBehaviour
    {
    }
  5. Implement the function for handling unintentional actions:
    public float CalculateDiscontentment(ActionGOB action, GoalGOB[] goals)
    {
        float discontentment = 0;
        foreach (GoalGOB goal in goals)
        {
            float newValue = goal.value + action.GetGoalChange(goal);
            newValue += action.GetDuration() * goal.GetChange();
            discontentment += goal.GetDiscontentment(newValue);
        }
        return discontentment;
    }
  6. Implement the function for choosing an action:
    public ActionGOB Choose(ActionGOB[] actions, GoalGOB[] goals)
    {
        ActionGOB bestAction;
        bestAction = actions[0];
        float bestValue = CalculateDiscontentment(actions[0], goals);
        float value;
        // next steps
    }
  7. Pick the best action based on which one is least compromising:
    foreach (ActionGOB action in actions)
    {
        value = CalculateDiscontentment(action, goals);
        if (value < bestValue)
        {
            bestValue = value;
            bestAction = action;
        }
    }
  8. Return the best action:
    return bestAction;

How it works...

The discontentment functions help avoid unintended actions, depending on how much a goal's value changes, in terms of an action and the time it takes to be executed. Then, the function for choosing an action is taken care of by computing the most promising one in terms of the minimum impact (discontentment).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.16.212.217