From 86b39fff39abb43729ab7cb133a36db1de526907 Mon Sep 17 00:00:00 2001 From: Peter Klooster Date: Wed, 4 Oct 2023 20:14:27 +0200 Subject: [PATCH 1/2] Fixed resolver traversing graph for node with false condition without actions that can turn it true. Fixes #75 --- .../GraphResolverJob.cs | 26 ++++++++ .../UnitTests/GraphResolverTests.cs | 65 +++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/Package/Runtime/CrashKonijn.Goap.Resolver/GraphResolverJob.cs b/Package/Runtime/CrashKonijn.Goap.Resolver/GraphResolverJob.cs index d1a2f005..e2d40723 100644 --- a/Package/Runtime/CrashKonijn.Goap.Resolver/GraphResolverJob.cs +++ b/Package/Runtime/CrashKonijn.Goap.Resolver/GraphResolverJob.cs @@ -97,6 +97,12 @@ public void Execute() closedSet.TryAdd(currentNode.Index, currentNode); openSet.Remove(currentNode.Index); + // If this node has a condition that is false and has no connections, it is unresolvable + if (this.HasUnresolvableCondition(currentNode.Index)) + { + continue; + } + foreach (var conditionIndex in this.NodeConditions.GetValuesForKey(currentNode.Index)) { if (runData.ConditionsMet[conditionIndex]) @@ -114,6 +120,7 @@ public void Execute() var newG = currentNode.G + this.RunData.Costs[neighborIndex]; NodeData neighbor; + // Current neighbour is not in the open set if (!openSet.TryGetValue(neighborIndex, out neighbor)) { neighbor = new NodeData @@ -127,6 +134,7 @@ public void Execute() continue; } + // This neighbour has a lower cost if (newG < neighbor.G) { neighbor.G = newG; @@ -167,5 +175,23 @@ private void RetracePath(NodeData startNode, NativeHashMap closed currentNode = closedSet[currentNode.ParentIndex]; } } + + private bool HasUnresolvableCondition(int currentIndex) + { + foreach (var conditionIndex in this.NodeConditions.GetValuesForKey(currentIndex)) + { + if (this.RunData.ConditionsMet[conditionIndex]) + { + continue; + } + + if (!this.ConditionConnections.GetValuesForKey(conditionIndex).MoveNext()) + { + return true; + } + } + + return false; + } } } \ No newline at end of file diff --git a/Package/Tests/CrashKonijn.Goap.Tests/UnitTests/GraphResolverTests.cs b/Package/Tests/CrashKonijn.Goap.Tests/UnitTests/GraphResolverTests.cs index fc2c77e4..2e173f93 100644 --- a/Package/Tests/CrashKonijn.Goap.Tests/UnitTests/GraphResolverTests.cs +++ b/Package/Tests/CrashKonijn.Goap.Tests/UnitTests/GraphResolverTests.cs @@ -485,5 +485,70 @@ public void Resolve_ShouldNotResolve_CompletedCondition() result.Should().HaveCount(2); result.Should().Equal(incompleteAction, rootAction); } + + [Test] + public void Resolve_ShouldNotResolve_ActionWithFalseConditionWithoutConnections() + { + var rootConnection = new TestConnection("Root"); + var availableConnection = new TestConnection("Available"); + var unavailableConnection = new TestConnection("Unavailable"); + + var goal = new TestAction("goal") + { + Conditions = new ICondition[] { rootConnection } + }; + + var expensiveAction = new TestAction("expensiveAction") + { + Effects = new IEffect[] { rootConnection }, + }; + + var unavailableAction = new TestAction("subAction") + { + Effects = new IEffect[] { rootConnection }, + Conditions = new ICondition[] { unavailableConnection, availableConnection } + }; + + var shouldNotResolveAction = new TestAction("shouldNotResolveAction") + { + Effects = new IEffect[] { availableConnection }, + }; + + var actions = new IAction[] { goal, expensiveAction, unavailableAction, shouldNotResolveAction }; + var resolver = new GraphResolver(actions, new TestKeyResolver()); + + var executableBuilder = resolver.GetExecutableBuilder(); + executableBuilder + .SetExecutable(expensiveAction, true) + .SetExecutable(unavailableAction, false) + .SetExecutable(shouldNotResolveAction, true); + + var positionBuilder = resolver.GetPositionBuilder(); + var costBuilder = resolver.GetCostBuilder(); + costBuilder.SetCost(expensiveAction, 100f); + + var conditionBuilder = resolver.GetConditionBuilder(); + + + // Act + var handle = resolver.StartResolve(new RunData + { + StartIndex = 0, + IsExecutable = new NativeArray(executableBuilder.Build(), Allocator.TempJob), + Positions = new NativeArray(positionBuilder.Build(), Allocator.TempJob), + Costs = new NativeArray(costBuilder.Build(), Allocator.TempJob), + ConditionsMet = new NativeArray(conditionBuilder.Build(), Allocator.TempJob), + DistanceMultiplier = 1f + }); + + var result = handle.Complete(); + + // Cleanup + resolver.Dispose(); + + // Assert + result.Should().HaveCount(1); + result.Should().Equal(expensiveAction); + } } } \ No newline at end of file From 1fa0d09f0337a1dd0955d093d82fee25e23df94d Mon Sep 17 00:00:00 2001 From: Peter Klooster Date: Wed, 4 Oct 2023 20:15:56 +0200 Subject: [PATCH 2/2] Update GraphResolverTests.cs --- .../Tests/CrashKonijn.Goap.Tests/UnitTests/GraphResolverTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Package/Tests/CrashKonijn.Goap.Tests/UnitTests/GraphResolverTests.cs b/Package/Tests/CrashKonijn.Goap.Tests/UnitTests/GraphResolverTests.cs index 2e173f93..6bfa1a7e 100644 --- a/Package/Tests/CrashKonijn.Goap.Tests/UnitTests/GraphResolverTests.cs +++ b/Package/Tests/CrashKonijn.Goap.Tests/UnitTests/GraphResolverTests.cs @@ -529,7 +529,6 @@ public void Resolve_ShouldNotResolve_ActionWithFalseConditionWithoutConnections( var conditionBuilder = resolver.GetConditionBuilder(); - // Act var handle = resolver.StartResolve(new RunData {