diff --git a/MountainGoap/Action.cs b/MountainGoap/Action.cs index 546c53d..3453d36 100644 --- a/MountainGoap/Action.cs +++ b/MountainGoap/Action.cs @@ -134,15 +134,20 @@ public float GetCost() { /// Executes a step of work for the agent. /// /// Agent executing the action. - internal void Execute(Agent agent) { + /// The execution status of the action. + internal ExecutionStatus Execute(Agent agent) { OnBeginExecuteAction(agent, this, parameters); if (IsPossible(agent.State)) { var newState = executor(agent, this); if (newState == ExecutionStatus.Succeeded) ApplyEffects(agent.State); ExecutionStatus = newState; OnFinishExecuteAction(agent, this, ExecutionStatus, parameters); + return newState; + } + else { + OnFinishExecuteAction(agent, this, ExecutionStatus.NotPossible, parameters); + return ExecutionStatus.NotPossible; } - else OnFinishExecuteAction(agent, this, ExecutionStatus.NotPossible, parameters); } /// diff --git a/MountainGoap/Agent.cs b/MountainGoap/Agent.cs index 87c4b98..2c31109 100644 --- a/MountainGoap/Agent.cs +++ b/MountainGoap/Agent.cs @@ -163,8 +163,8 @@ private void Execute() { List> cullableSequences = new(); foreach (var sequence in CurrentActionSequences) { if (sequence.Count > 0) { - sequence[0].Execute(this); - sequence.RemoveAt(0); + var executionStatus = sequence[0].Execute(this); + if (executionStatus != ExecutionStatus.Executing) sequence.RemoveAt(0); } else cullableSequences.Add(sequence); } diff --git a/MountainGoapTest/ActionContinuationTests.cs b/MountainGoapTest/ActionContinuationTests.cs new file mode 100644 index 0000000..545b1b8 --- /dev/null +++ b/MountainGoapTest/ActionContinuationTests.cs @@ -0,0 +1,54 @@ +namespace MountainGoapTest { + using System.Collections.Generic; + + public class ActionContinuationTests { + [Fact] + public void ItCanContinueActions() { + var timesExecuted = 0; + var agent = new Agent( + state: new() { + { "key", false }, + { "progress", 0 } + }, + goals: new List { + new Goal( + desiredState: new() { + { "key", true } + } + ) + }, + actions: new List { + new Action( + preconditions: new() { + { "key", false } + }, + postconditions: new() { + { "key", true } + }, + executor: (Agent agent, Action action) => { + timesExecuted++; + if (agent.State["progress"] is int progress && progress < 3) { + agent.State["progress"] = progress + 1; + return ExecutionStatus.Executing; + } + else return ExecutionStatus.Succeeded; + } + ) + } + ); + agent.Step(StepMode.OneAction); + if (agent.State["key"] is bool value) Assert.False(value); + else Assert.False(true); + agent.Step(StepMode.OneAction); + if (agent.State["key"] is bool value2) Assert.False(value2); + else Assert.False(true); + agent.Step(StepMode.OneAction); + if (agent.State["key"] is bool value3) Assert.False(value3); + else Assert.False(true); + agent.Step(StepMode.OneAction); + if (agent.State["key"] is bool value4) Assert.True(value4); + else Assert.False(true); + Assert.Equal(4, timesExecuted); + } + } +}