Skip to content

Commit

Permalink
fix: update heuristics properly (#32)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
SilasPeters authored Apr 4, 2024
1 parent e421288 commit be4401b
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 17 deletions.
18 changes: 6 additions & 12 deletions Aplib.Core/Desire/Goals/Goal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public class Goal<TBeliefSet> : IGoal<TBeliefSet>
public CompletionStatus Status { get; protected set; }

/// <summary>
/// The goal is considered to be completed, when the distance of the <see cref="CurrentHeuristics" /> is below
/// The goal is considered to be completed, when the distance of the <see cref="DetermineCurrentHeuristics" /> is below
/// this value.
/// </summary>
protected double _epsilon { get; }
Expand All @@ -51,18 +51,13 @@ public class Goal<TBeliefSet> : IGoal<TBeliefSet>
/// <seealso cref="GetStatus" />
protected HeuristicFunction _heuristicFunction;

/// <summary>
/// The backing field of <see cref="Heuristics" />.
/// </summary>
private Heuristics? _currentHeuristics;

/// <summary>
/// Creates a new goal which works with <see cref="Heuristics" />.
/// </summary>
/// <param name="tactic">The tactic used to approach this goal.</param>
/// <param name="heuristicFunction">The heuristic function which defines whether a goal is reached</param>
/// <param name="epsilon">
/// The goal is considered to be completed, when the distance of the <see cref="CurrentHeuristics" /> is below
/// The goal is considered to be completed, when the distance of the <see cref="DetermineCurrentHeuristics" /> is below
/// this value.
/// </param>
/// <param name="metadata">
Expand All @@ -88,7 +83,7 @@ public Goal
/// <param name="tactic">The tactic used to approach this goal.</param>
/// <param name="predicate">The heuristic function (or specifically predicate) which defines whether a goal is reached</param>
/// <param name="epsilon">
/// The goal is considered to be completed, when the distance of the <see cref="CurrentHeuristics" /> is below
/// The goal is considered to be completed, when the distance of the <see cref="DetermineCurrentHeuristics" /> is below
/// this value.
/// </param>
/// <param name="metadata">
Expand All @@ -106,19 +101,18 @@ public Goal(ITactic<TBeliefSet> tactic, Func<TBeliefSet, bool> predicate, double
/// Gets the <see cref="Heuristics" /> of the current state of the game.
/// </summary>
/// <remarks>If no heuristics have been calculated yet, they will be calculated first.</remarks>
public virtual Heuristics CurrentHeuristics(TBeliefSet beliefSet)
=> _currentHeuristics ??= _heuristicFunction.Invoke(beliefSet);
public virtual Heuristics DetermineCurrentHeuristics(TBeliefSet beliefSet) => _heuristicFunction.Invoke(beliefSet);

/// <summary>
/// Tests whether the goal has been achieved, bases on the <see cref="_heuristicFunction" /> and the
/// <see cref="CurrentHeuristics" />. When the distance of the heuristics is smaller than <see cref="_epsilon" />,
/// <see cref="DetermineCurrentHeuristics" />. When the distance of the heuristics is smaller than <see cref="_epsilon" />,
/// the goal is considered to be completed.
/// </summary>
/// <returns>An enum representing whether the goal is complete and if so, with what result.</returns>
/// <seealso cref="_epsilon" />
public virtual CompletionStatus GetStatus(TBeliefSet beliefSet)
{
Status = CurrentHeuristics(beliefSet).Distance < _epsilon
Status = DetermineCurrentHeuristics(beliefSet).Distance < _epsilon
? CompletionStatus.Success
: CompletionStatus.Unfinished;
return Status;
Expand Down
4 changes: 2 additions & 2 deletions Aplib.Core/Desire/Goals/IGoal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ public interface IGoal<in TBeliefSet> : ICompletable
/// Gets the <see cref="Heuristics" /> of the current state of the game.
/// </summary>
/// <remarks>If no heuristics have been calculated yet, they will be calculated first.</remarks>
Heuristics CurrentHeuristics(TBeliefSet beliefSet);
Heuristics DetermineCurrentHeuristics(TBeliefSet beliefSet);

/// <summary>
/// Tests whether the goal has been achieved, based on the <see cref="Goal{TBeliefSet}._heuristicFunction" /> and the
/// <see cref="Goal{TBeliefSet}.CurrentHeuristics" />. When the distance of the heuristics is smaller than <see cref="Goal{TBeliefSet}._epsilon" />
/// <see cref="Goal{TBeliefSet}.DetermineCurrentHeuristics" />. When the distance of the heuristics is smaller than <see cref="Goal{TBeliefSet}._epsilon" />
/// , the goal is considered to be completed.
/// </summary>
/// <returns>An enum representing whether the goal is complete and if so, with what result.</returns>
Expand Down
25 changes: 24 additions & 1 deletion Aplib.Tests/Desire/GoalTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -112,6 +112,29 @@ public void Goal_WhereEvaluationIsPerformed_DoesNotInfluenceBelieveSet()
beliefSetMock.Verify(beliefSetMock => beliefSetMock.UpdateBeliefs(), Times.Never);
}

/// <summary>
/// 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
/// </summary>
[Fact]
public void Goal_WhereHeuristicsChange_UsesUpdatedHeuristics()
{
// Arrange
IBeliefSet beliefSetMock = Mock.Of<IBeliefSet>();
bool shouldSucceed = false;
Goal<IBeliefSet> 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);
}

/// <summary>
/// Given the Goal's different constructors have been called with semantically equal arguments
/// when the Evaluate() method of all goals are used,
Expand Down
3 changes: 1 addition & 2 deletions Aplib.Tests/Tools/TestGoalBuilder.cs
Original file line number Diff line number Diff line change
@@ -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
{
Expand Down

0 comments on commit be4401b

Please sign in to comment.