Skip to content

Commit

Permalink
fix: apply Tactic fix (#19)
Browse files Browse the repository at this point in the history
* fix: apply tactic fix

* fix: processed feedback

* fix: typo

* fix: removed redundant qualifier

Co-authored-by: Quake <74355598+QuakeEye@users.noreply.github.com>

---------

Co-authored-by: Quake <74355598+QuakeEye@users.noreply.github.com>
  • Loading branch information
SilasPeters and QuakeEye authored Mar 20, 2024
1 parent 826ae60 commit 56f23ae
Show file tree
Hide file tree
Showing 16 changed files with 106 additions and 104 deletions.
13 changes: 13 additions & 0 deletions Aplib.Core/Believe/BeliefSet.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace Aplib.Core.Believe
{
/// <summary>
/// This is a summary
/// </summary>
public class BeliefSet
{
/// <summary>
/// This is merely here to allow some unit test
/// </summary>
public string State = "kaas";
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Aplib.Core.Believe;
using System;

namespace Aplib.Core.Desire
namespace Aplib.Core.Desire.Goals
{
/// <summary>
/// Contains helper methods to generate commonly used heuristic functions.
Expand All @@ -15,13 +16,13 @@ public static class CommonHeuristicFunctions
/// </param>
/// <returns>A heuristic function which wraps around the boolean-based heuristic function.</returns>
public static Goal.HeuristicFunction Boolean(Func<bool> heuristicFunction)
=> () => Heuristics.BooleanHeuristic(heuristicFunction.Invoke());
=> _ => Heuristics.Boolean(heuristicFunction.Invoke());

/// <summary>
/// A <see cref="Goal.HeuristicFunction"/> which always returns <see cref="Heuristics"/> with the same distance.
/// </summary>
/// <param name="distance">The distance which the heuristic function must always return.</param>
public static Goal.HeuristicFunction Constant(float distance) => () => new Heuristics { Distance = distance };
public static Goal.HeuristicFunction Constant(float distance) => _ => new Heuristics { Distance = distance };

/// <summary>
/// Returns a heuristic function which always, at all times, and forever, returns a value indicating the state
Expand Down
42 changes: 16 additions & 26 deletions Aplib.Core/Desire/Goal.cs → Aplib.Core/Desire/Goals/Goal.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using Aplib.Core.Believe;
using Aplib.Core.Intent.Tactics;
using System;

namespace Aplib.Core.Desire
namespace Aplib.Core.Desire.Goals
{
/// <summary>
/// A goal effectively combines a heuristic function with a tactic, and aims to meet the heuristic function by
Expand All @@ -14,15 +16,16 @@ public class Goal
/// The abstract definition of what is means to test the Goal's heuristic function. Returns <see cref="Heuristics"/>, as
/// they represent how close we are to matching the heuristic function, and if the goal is completed.
/// </summary>
/// <seealso cref="Goal.Evaluate"/>
public delegate Heuristics HeuristicFunction();
/// <seealso cref="IsCompleted"/>
public delegate Heuristics HeuristicFunction(BeliefSet beliefSet);


/// <summary>
/// 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 => _currentHeuristics ??= _heuristicFunction.Invoke();
public virtual Heuristics CurrentHeuristics(BeliefSet beliefSet)
=> _currentHeuristics ??= _heuristicFunction.Invoke(beliefSet);

/// <summary>
/// The name used to display the current goal during debugging, logging, or general overviews.
Expand All @@ -45,15 +48,14 @@ public class Goal
/// The concrete implementation of this Goal's <see cref="HeuristicFunction"/>. Used to test whether this goal is
/// completed.
/// </summary>
/// <seealso cref="Evaluate"/>
/// <seealso cref="IsCompleted"/>
protected HeuristicFunction _heuristicFunction;

/// <summary>
/// The <see cref="Tactic"/> used to achieve this <see cref="Goal"/>, which is executed during every iteration
/// The <see cref="Intent.Tactics.Tactic"/> used to achieve this <see cref="Goal"/>, which is executed during every iteration
/// of the BDI cycle.
/// </summary>
/// <seealso cref="Iterate()"/>
private readonly Tactic _tactic;
public Tactic Tactic { get; private set; }

/// <summary>
/// The backing field of <see cref="Heuristics"/>.
Expand All @@ -73,7 +75,7 @@ public class Goal
/// </param>
public Goal(Tactic tactic, HeuristicFunction heuristicFunction, string name, string description, double epsilon = 0.005d)
{
_tactic = tactic;
Tactic = tactic;
_heuristicFunction = heuristicFunction;
Name = name;
Description = description;
Expand All @@ -84,41 +86,29 @@ public Goal(Tactic tactic, HeuristicFunction heuristicFunction, string name, str
/// Creates a new goal which works with boolean-based <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="predicate">The heuristic function (or specifically predicate) which defines whether a goal is reached</param>
/// <param name="name">The name of this goal, used to quickly display this goal in several contexts.</param>
/// <param name="description">The description of this goal, used to explain this goal in several contexts.</param>
/// <param name="epsilon">
/// The goal is considered to be completed, when the distance of the <see cref="CurrentHeuristics"/> is below
/// this value.
/// </param>
public Goal(Tactic tactic, Func<bool> heuristicFunction, string name, string description, double epsilon = 0.005d)
public Goal(Tactic tactic, Func<bool> predicate, string name, string description, double epsilon = 0.005d)
{
_tactic = tactic;
_heuristicFunction = CommonHeuristicFunctions.Boolean(heuristicFunction);
Tactic = tactic;
_heuristicFunction = CommonHeuristicFunctions.Boolean(predicate);
Name = name;
Description = description;
_epsilon = epsilon;
}

/// <summary>
/// Performs the next steps needed to be taken to approach this goal. Effectively this means that one BDI
/// cycle will be executed.
/// </summary>
public void Iterate()
{
_tactic.IterateBdiCycle();
}

/// <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"/>,
/// the goal is considered to be completed.
/// </summary>
/// <returns>A boolean representing whether the goal is considered to be completed.</returns>
/// <seealso cref="_epsilon"/>
public bool Evaluate()
{
return CurrentHeuristics.Distance < _epsilon;
}
public bool IsCompleted(BeliefSet beliefSet) => CurrentHeuristics(beliefSet).Distance < _epsilon;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Aplib.Core.Desire
namespace Aplib.Core.Desire.Goals
{
/// <summary>
/// Contains all information on how close the associated state is to its goal.
Expand All @@ -17,6 +17,6 @@ public class Heuristics
/// </summary>
/// <param name="value">True if completed, False if not completed.</param>
/// <returns></returns>
public static Heuristics BooleanHeuristic(bool value) => new() { Distance = value ? 0f : 1f };
public static Heuristics Boolean(bool value) => new() { Distance = value ? 0f : 1f };
}
}
17 changes: 0 additions & 17 deletions Aplib.Core/Desire/Tactic.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System;

namespace Aplib.Core
namespace Aplib.Core.Intent.Actions
{
/// <summary>
/// Describes an action that can be executed and guarded.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System;

namespace Aplib.Core
namespace Aplib.Core.Intent.Actions
{
/// <summary>
/// Describes an action that can be executed and guarded with a query that stores the result of the guard.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
using System;
using System.Collections.Generic;
using Action = Aplib.Core.Intent.Actions.Action;

namespace Aplib.Core.Tactics
namespace Aplib.Core.Intent.Tactics
{
/// <summary>
/// Represents a tactic that executes any of the provided sub-tactics.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using Action = Aplib.Core.Intent.Actions.Action;

namespace Aplib.Core.Tactics
namespace Aplib.Core.Intent.Tactics
{
/// <summary>
/// Represents a tactic that executes the first enabled action from a list of sub-tactics.
Expand All @@ -25,7 +25,7 @@ public FirstOfTactic(Func<bool> guard, params Tactic[] subTactics) : base(guard,
{
}

/// <inheritdoc/>
/// <inheritdoc />
public override Action? GetAction()
{
foreach (Tactic subTactic in SubTactics)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
using System;
using System.Collections.Generic;
using Action = Aplib.Core.Intent.Actions.Action;

namespace Aplib.Core.Tactics
namespace Aplib.Core.Intent.Tactics
{
/// <summary>
/// Represents a primitive tactic in the Aplib.Core namespace.
/// Represents a primitive tactic
/// </summary>
public class PrimitiveTactic : Tactic
{
Expand All @@ -23,7 +23,7 @@ public class PrimitiveTactic : Tactic
/// Initializes a new instance of the <see cref="PrimitiveTactic"/> class with the specified action and guard.
/// </summary>
/// <param name="action">The action of the primitive tactic.</param>
/// <param name="guard">The guard of the tactic.</param>
/// <param name="guard">The guard of the primitive tactic.</param>
public PrimitiveTactic(Action action, Func<bool> guard) : base(guard) => Action = action;

/// <inheritdoc/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
using System;
using Action = Aplib.Core.Intent.Actions.Action;

namespace Aplib.Core.Tactics
namespace Aplib.Core.Intent.Tactics
{
/// <summary>
/// Represents a tactic in the Aplib.Core namespace.
/// Tactics are the real meat of <see cref="Desire.Goals.Goal"/>s, as they define how the agent can approach the goal in hopes
/// of finding a solution which makes the Goal's heuristic function evaluate to being completed. A tactic represents
/// a smart combination of <see cref="Action"/>s, which are executed in a Believe Desire Intent Cycle.
/// </summary>
/// <seealso cref="Desire.Goals.Goal"/>
/// <seealso cref="Intent.Actions.Action"/>
public abstract class Tactic
{
/// <summary>
Expand Down
4 changes: 2 additions & 2 deletions Aplib.Tests/Core/ActionTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using Aplib.Core;
using Action = Aplib.Core.Action;
using Aplib.Core.Intent.Actions;
using Action = Aplib.Core.Intent.Actions.Action;

namespace Aplib.Tests.Core;

Expand Down
15 changes: 9 additions & 6 deletions Aplib.Tests/Core/Tactics/TacticTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Aplib.Core.Tactics;
using FluentAssertions;
using Action = Aplib.Core.Action;
using Aplib.Core.Intent.Tactics;
using Action = Aplib.Core.Intent.Actions.Action;

namespace Aplib.Tests.Core.Tactics;
public class TacticTests
Expand All @@ -14,7 +13,7 @@ public class TacticTests
private static bool FalseGuard() => false;

/// <summary>
/// Given a parent of type <see cref="TacticType.FirstOf"/> with two subtactics,
/// Given a parent of type <see cref="FirstOfTactic"/> with two subtactics,
/// When getting the next tactic,
/// Then the result should be the first subtactic.
/// </summary>
Expand All @@ -30,11 +29,12 @@ public void GetAction_WhenTacticTypeIsFirstOf_ReturnsEnabledPrimitiveTactics()
Action? enabledAction = parentTactic.GetAction();

// Assert
Assert.NotNull(enabledAction);
Assert.Equal(_emptyAction, enabledAction);
}

/// <summary>
/// Given a parent of type <see cref="TacticType.FirstOf"/> with two subtactics and a guard that is true,
/// Given a parent of type <see cref="FirstOfTactic"/> with two subtactics and a guard that is true,
/// When getting the next tactic,
/// Then the result should be the first subtactic.
/// </summary>
Expand All @@ -50,11 +50,12 @@ public void GetAction_WhenTacticTypeIsFirstOfAndGuardEnabled_ReturnsEnabledPrimi
Action? enabledAction = parentTactic.GetAction();

// Assert
Assert.NotNull(enabledAction);
Assert.Equal(_emptyAction, enabledAction);
}

/// <summary>
/// Given a parent of type <see cref="TacticType.AnyOf"/> with two subtactics,
/// Given a parent of type <see cref="AnyOfTactic"/> with two subtactics,
/// When getting the next tactic,
/// Then the result should contain all the subtactics.
/// </summary>
Expand All @@ -70,6 +71,7 @@ public void GetAction_WhenTacticTypeIsAnyOf_ReturnsEnabledPrimitiveTactics()
Action? enabledAction = parentTactic.GetAction();

// Assert
Assert.NotNull(enabledAction);
Assert.Equal(_emptyAction, enabledAction);
}

Expand All @@ -88,6 +90,7 @@ public void GetAction_WhenTacticTypeIsPrimitiveAndActionIsActionable_ReturnsEnab
Action? enabledAction = tactic.GetAction();

// Assert
Assert.NotNull(enabledAction);
Assert.Equal(_emptyAction, enabledAction);
}

Expand Down
Loading

0 comments on commit 56f23ae

Please sign in to comment.