#AI stuff

1 messages · Page 1 of 1 (latest)

robust cape
#

Lemme make a thread so that we don't eat up too much space

#

I guess that it's got a bit of utility AI left in it

humble lily
#

Thanks, great idea. I always forget these nifty discord features

robust cape
#

So the planner system works like this:

#

First, it gathers up all of the entity's actions, facts, and goals

#

Actions are things the entity can do.

#

Facts are things that are currently true (I don't have a way to remove facts or test for facts not existing right now)

#

Goals are things the entity wants to achieve

#

Actions have precondition facts that must be satisfied to perform the action. They also have postcondition facts that become true when you perform the action.

#

Goals just have precondition facts.

#

Here's an example of a valid plan.

#

The goals are sorted by score, and then we try to make a plan for each goal.

#

Each box in this diagram is a planner state.

#

A planner state contains a set of facts that are currently true, as well as facts that it desires to be true.

#

We start in the goal state. It wants the goal's facts.

#

At this point, we do A*!

#

I go through all of the actions and pick ones that would satisfy a desire.

#

Here, I picked PlannerObjectiveAction

#

It's a bit abstract: it just represents completing an objective

#

My objective system can tell you what facts need to be true to complete the objective. In this case, it says "the lever must be interacted with"

#

So we do it again, looking for an action that satisfies at least part of those desires.

humble lily
#

Wow. Is this your own design or did you learn it from somewhere? Very interesting

robust cape
#

This is the main objective; it has a single sub-objective, which is...

#

...this guy

#

The sub-objective says that it'll succeed if we interact with a lever

#

and we can interact with the lever if we move towards it

robust cape
#

although it deals with much simpler world state

#

like, it doesn't plan "i'm going to shoot that guy"; it just figures out "i can shoot a guy"

robust cape
#

I then resolve the list of planner actions into brain actions -- things the AI character can actually do

#
using Pursuit.Brains;
using Pursuit.Entities;
using UnityEngine;

public class PlannerMoveToEntityAction : PlannerAction
{
    private Entity target;
    private float distance;

    public override float Cost => base.Cost * Mathf.InverseLerp(0, Level.Instance.levelScale, distance);

    public PlannerMoveToEntityAction(Entity target, float distance)
    {
        this.target = target;
        this.distance = distance;
    }

    public override void ApplyAction(PlannerState state)
    {
        state.Satisfy(new EntityProximityFact(target, distance));
    }

    public override bool TryResolve(out BrainAction result)
    {
        result = new BrainMoveToEntityAction(target, distance);
        return true;
    }

    public override bool SatisfiesGoal(PlannerState state)
    {
        return state.Wants(new EntityProximityFact(target, distance));
    }

    public override string FriendlyName => "Move to: " + target.Label.GetLocalizedString();
}
#
using Pursuit.Entities;
using UnityEngine;

namespace Pursuit.Brains
{
    public class BrainMoveToEntityAction : BrainAction
    {
        protected Entity target;
        protected float distance;

        public BrainMoveToEntityAction(Entity target, float distance)
        {
            this.target = target;
            this.distance = distance;
        }

        public override void Engage(Brain brain)
        {
            base.Engage(brain);

            UpdatePath();
        }

        void UpdatePath()
        {
            Perception perception = brain.entity.GetPrimePerception(target);

            if (perception == null)
            {
                Fail();
            }
            else
            {
                brain.entity.agent.SetDestination(perception.DispersedLocation);

                if (Vector3.Distance(brain.entity.transform.position, perception.DispersedLocation) < distance)
                {
                    Succeed();
                }
            }
        }

        public override void Tick()
        {
            base.Tick();

            UpdatePath();
        }

        public override string GetDisplayString()
        {
            return "Move: " + target.name;
        }

        public override bool HasLookTarget => true;
        public override Vector3 LookTarget
        {
            get
            {
                Perception perception = brain.entity.GetPrimePerception(target);

                if (perception != null)
                    return perception.DispersedLocation;
                else
                    return target.transform.position;
            }
        }
    }
}
#

for example

#

in this case it's a pretty obvious 1:1 mapping

#

I am exploring more complicated things, though

#

like one planner action expanding into multiple brain actions

#

This is where I am thinking of inserting behavior trees, actually 😁

#

GOAP is great for high-level planning, but it's not so good for fine-tuning

#

suppose I were to create a new "Taunt" action that the entity is allowed to perform whenever it wants

#

that could create a huge number of states to dig through

#

and oh boy can it get really bad

#

this is what happened when I asked it to solve this objective:

#
  • Win game by:
    • Pull lever
    • Pull lever
    • Pull lever
#

It explored every way to pull three levers

#

including some bogus ideas, like walking to lever 1, then 2, then 3 before pulling lever 1

humble lily
#

Wow, yea. This is scary

humble lily
robust cape
#

I'm still figuring out what to do about that

#

I don't want it to tell the AI to just complete single random objectives

#

I want it to complete objectives because doing all of them will make them win

#

I think my solution was to just make sub-objectives inherit the post-conditions of their parents

#

so every "pull lever" objective pinky-swears you'll win if you complete it

#

You can lie to the AI 😉

humble lily
#

I'll read that paper you sent too but wow, yea thanks for explaining everything

#

Was just resarching it as we speak

robust cape
#

that would be nonsense, since it could be infinitely large

#

we're doing A*

#

you're probably used to the idea of A* for pathfinding

#

where you have a fixed graph that you're exploring

#

but all A* needs is a set of unexplored nodes and a way to find the neighbors of a node

robust cape
#

by default, you just give each action a cost of 1

#

so you're trying to find the shortest series of actions possible

#

I'm playing with giving actions variable costs.

#

This can cause problems for A*, though

#

You use a heuristic to decide which node to explore next (that's what makes it more efficient than Djikstra's: it picks nodes that look like they're closer to the goal)

#

my heuristic is the number of unsatisfied facts

#

As long as the heuristic never over-estimates the cost of reaching the goal, it's "admissible".

For pathfinding, it's super easy: the distance to the goal can't be more than the distance you travel to reach it

#

but it's kind of broken already before even adding variable costs

#

if an action satisfies two facts, then the cost to take it is 1, but the heuristic estimated that we're 2 away from the goal

humble lily
#

What is the ultimate goal of your AI?

robust cape
#

and if the cost of an action goes below 1, you'll always be breaking the rule

robust cape
#

focusing on one major threat

humble lily
robust cape
#

but I'm using this AI for every entity in the game

humble lily
#

You can do it defintely, but explains the in-depth research

robust cape
#

The system works great, but it's way too sterile right now

#

i'm looking for ways to add some more interesting behavior (not just bumrushing the player as soon as they're aware of you)

humble lily
#

Or some sort of uncertainty system

robust cape
#

I have uncertainty -- there's a whole perception system that gives partial information

#

although I should think about making the AI also respond less aggressively to weak information

#

it'll aggressively investigate a weak, poorly defined perception

robust cape
#

The problem is that you want to keep trying new plans

#

so that the AI doesn't let the player walk straight past just because they're currently doing a random wander plan

#

that means that random noise will cause flapping: going back and forth between different plans

#

I might make it so that the random noise only updates after a plan is completed or failed

humble lily
#

Fen, do you mind if I respond to this thread later too?

#

Since a lot of research awaits me lmao

robust cape
#

sure thing!

humble lily
#

And I wanted to ask some questions, but it'd be better if I had some more fundemental understanding of GOAP

robust cape
humble lily
#

Thanks, really appericate it

robust cape
#

as for your original question, behavior trees are probably sufficient for a capture-the-flag game

#

with a state machine (one per character, with some shared information the whole team can see) to switch trees

#

imagine a character giving up on chasing the flag carrier because they're out of ammo, so they switch out of the chase state

#

which prompts other characters to switch into the chasing state