caesuric / mountain-goap

A GOAP (Goal Oriented Action Planning) AI library, written in C#.
Other
86 stars 12 forks source link

Multi-goal #32

Open ray2k opened 2 months ago

ray2k commented 2 months ago

Multiple goals should be supported, right?

When I have this happiness-increaser based example it runs until it hits 25 as expected:

public static void RunBasicExample()
{
    var ag = new GoapAgent(
        name: "Happiness Agent",
        state: new()
        {
            { "happiness", 0 },
            { "complete", false }
        },
        goals: new()
        {
            new Goal(
                name: "Acquire Max Happiness",
                desiredState: new()
                {
                    { "happiness", 25 }
                })
        },
        sensors: new()
        {
            new Sensor(CheckComplete)
        },
        actions: new()
        {
            new MountainGoap.Action(
                name: "Increase Happiness",
                executor: IncreaseHappiness,
                arithmeticPostconditions: new()
                {
                    { "happiness", 1 }
                })                    
        });

    while ((bool)ag.State["complete"] == false)
        ag.Step(StepMode.AllActions);
}

        private static void CheckComplete(GoapAgent agent)
        {
            if ((int)agent.State["happiness"] >= 25)
                agent.State["complete"] = true;
        }

        private static ExecutionStatus IncreaseHappiness(GoapAgent agent, MountainGoap.Action action)
        {
            Console.WriteLine("Happiness is at {0} - Increasing!", agent.State["happiness"]);
            return ExecutionStatus.Succeeded;
        }

But that's pretty contrived as it's basically a goap version of a while-loop. Whenever I add an additional goal + action, it gets an IndexOutOfBounds exception related to A*- this setup should be solvable though, right?

 public static void RunAdvancedExample()
 {
     var ag = new GoapAgent(
         name: "Phase 1",
         state: new()
         {
             { "happiness", 0 },
             { "complete", false },
             { "anotherThingDone", false }
         },
         goals: new()
         {
             new Goal(
                 name: "Acquire Max Happiness",
                 desiredState: new()
                 {
                     { "happiness", 25 }                            
                 }),
             new Goal(
                 name: "Do the other thing",
                 desiredState: new()
                 {
                     { "anotherThingDone", true }
                 })
         },
         sensors: new()
         {
             new Sensor(CheckComplete)
         },
         actions: new()
         {
             new MountainGoap.Action(
                 name: "Increase Happiness",
                 executor: IncreaseHappiness,
                 arithmeticPostconditions: new()
                 {
                     { "happiness", 1 }
                 }),
             new MountainGoap.Action(
                 name: "Do the other thing",
                 executor: DoAnotherThing,
                 postconditions: new()
                 {
                     { "anotherThingDone", true }
                 })
         });

     while ((bool)ag.State["complete"] == false)
         ag.Step(StepMode.AllActions);

    // not shown: update to CheckComplete to also consider anotherThingDone == true
 }

        private static ExecutionStatus DoAnotherThing(GoapAgent agent, MountainGoap.Action action)
        {
            Console.WriteLine("Doing the other thing");
            return ExecutionStatus.Succeeded;
        }

Tried:

Is it because they are booleans? Is this even supported? What am I missing?

caesuric commented 2 months ago

Multiple goals do work. Usually when I've seen it spin and then die, it's because it finds one or more goals impossible and no limits have been set on how far to search for completing the goal. The code above, at first glance, looks like it should work though. I'll try to replicate on my end and get back to you when I figure it out.