From be4401b216f1b4ed61ab850f0192a2be805a38a2 Mon Sep 17 00:00:00 2001 From: Silas Peters <69711739+SilasPeters@users.noreply.github.com> Date: Thu, 4 Apr 2024 13:16:34 +0200 Subject: [PATCH] fix: update heuristics properly (#32) * fix: update heuristics properly * fix: rename CurrentHeuristics to DetermineCurrentHeuristics This better conveys the meaning that the heuristisc will be re-calculated * fix: remove moq from the act section in the unit test --- Aplib.Core/Desire/Goals/Goal.cs | 18 ++++++------------ Aplib.Core/Desire/Goals/IGoal.cs | 4 ++-- Aplib.Tests/Desire/GoalTests.cs | 25 ++++++++++++++++++++++++- Aplib.Tests/Tools/TestGoalBuilder.cs | 3 +-- 4 files changed, 33 insertions(+), 17 deletions(-) diff --git a/Aplib.Core/Desire/Goals/Goal.cs b/Aplib.Core/Desire/Goals/Goal.cs index 0b87c911..7dfc5012 100644 --- a/Aplib.Core/Desire/Goals/Goal.cs +++ b/Aplib.Core/Desire/Goals/Goal.cs @@ -40,7 +40,7 @@ public class Goal : IGoal public CompletionStatus Status { get; protected set; } /// - /// The goal is considered to be completed, when the distance of the is below + /// The goal is considered to be completed, when the distance of the is below /// this value. /// protected double _epsilon { get; } @@ -51,18 +51,13 @@ public class Goal : IGoal /// protected HeuristicFunction _heuristicFunction; - /// - /// The backing field of . - /// - private Heuristics? _currentHeuristics; - /// /// Creates a new goal which works with . /// /// The tactic used to approach this goal. /// The heuristic function which defines whether a goal is reached /// - /// The goal is considered to be completed, when the distance of the is below + /// The goal is considered to be completed, when the distance of the is below /// this value. /// /// @@ -88,7 +83,7 @@ public Goal /// The tactic used to approach this goal. /// The heuristic function (or specifically predicate) which defines whether a goal is reached /// - /// The goal is considered to be completed, when the distance of the is below + /// The goal is considered to be completed, when the distance of the is below /// this value. /// /// @@ -106,19 +101,18 @@ public Goal(ITactic tactic, Func predicate, double /// Gets the of the current state of the game. /// /// If no heuristics have been calculated yet, they will be calculated first. - public virtual Heuristics CurrentHeuristics(TBeliefSet beliefSet) - => _currentHeuristics ??= _heuristicFunction.Invoke(beliefSet); + public virtual Heuristics DetermineCurrentHeuristics(TBeliefSet beliefSet) => _heuristicFunction.Invoke(beliefSet); /// /// Tests whether the goal has been achieved, bases on the and the - /// . When the distance of the heuristics is smaller than , + /// . When the distance of the heuristics is smaller than , /// the goal is considered to be completed. /// /// An enum representing whether the goal is complete and if so, with what result. /// public virtual CompletionStatus GetStatus(TBeliefSet beliefSet) { - Status = CurrentHeuristics(beliefSet).Distance < _epsilon + Status = DetermineCurrentHeuristics(beliefSet).Distance < _epsilon ? CompletionStatus.Success : CompletionStatus.Unfinished; return Status; diff --git a/Aplib.Core/Desire/Goals/IGoal.cs b/Aplib.Core/Desire/Goals/IGoal.cs index ca50f615..ef7db90b 100644 --- a/Aplib.Core/Desire/Goals/IGoal.cs +++ b/Aplib.Core/Desire/Goals/IGoal.cs @@ -20,11 +20,11 @@ public interface IGoal : ICompletable /// Gets the of the current state of the game. /// /// If no heuristics have been calculated yet, they will be calculated first. - Heuristics CurrentHeuristics(TBeliefSet beliefSet); + Heuristics DetermineCurrentHeuristics(TBeliefSet beliefSet); /// /// Tests whether the goal has been achieved, based on the and the - /// . When the distance of the heuristics is smaller than + /// . When the distance of the heuristics is smaller than /// , the goal is considered to be completed. /// /// An enum representing whether the goal is complete and if so, with what result. diff --git a/Aplib.Tests/Desire/GoalTests.cs b/Aplib.Tests/Desire/GoalTests.cs index d6ad476a..faa3f292 100644 --- a/Aplib.Tests/Desire/GoalTests.cs +++ b/Aplib.Tests/Desire/GoalTests.cs @@ -2,7 +2,7 @@ using Aplib.Core.Desire.Goals; using Aplib.Core.Intent.Actions; using Aplib.Core.Intent.Tactics; -using Aplib.Tests.Tools; +using Aplib.Core.Tests.Tools; using FluentAssertions; using Moq; @@ -112,6 +112,29 @@ public void Goal_WhereEvaluationIsPerformed_DoesNotInfluenceBelieveSet() beliefSetMock.Verify(beliefSetMock => beliefSetMock.UpdateBeliefs(), Times.Never); } + /// + /// Given a valid goal with heuristics + /// when the goal's heuristic function's result will be different in the next frame + /// the most recent heuristics are used + /// + [Fact] + public void Goal_WhereHeuristicsChange_UsesUpdatedHeuristics() + { + // Arrange + IBeliefSet beliefSetMock = Mock.Of(); + bool shouldSucceed = false; + Goal goal = new TestGoalBuilder().WithHeuristicFunction(_ => shouldSucceed).Build(); + + // Act + CompletionStatus stateBefore = goal.GetStatus(beliefSetMock); + shouldSucceed = true; // Make heuristic function return a different value on next invoke + CompletionStatus stateAfter = goal.GetStatus(beliefSetMock); + + // Assert + stateBefore.Should().Be(CompletionStatus.Unfinished); + stateAfter.Should().Be(CompletionStatus.Success); + } + /// /// Given the Goal's different constructors have been called with semantically equal arguments /// when the Evaluate() method of all goals are used, diff --git a/Aplib.Tests/Tools/TestGoalBuilder.cs b/Aplib.Tests/Tools/TestGoalBuilder.cs index 792088e7..d2fc9bf6 100644 --- a/Aplib.Tests/Tools/TestGoalBuilder.cs +++ b/Aplib.Tests/Tools/TestGoalBuilder.cs @@ -1,10 +1,9 @@ -using Aplib.Core; using Aplib.Core.Belief; using Aplib.Core.Desire.Goals; using Aplib.Core.Intent.Tactics; using Moq; -namespace Aplib.Tests.Tools; +namespace Aplib.Core.Tests.Tools; internal sealed class TestGoalBuilder {