Skip to content

Commit

Permalink
Feature: turn GetFirstEnabledActions into GetAction
Browse files Browse the repository at this point in the history
  • Loading branch information
Tboefijn committed Mar 17, 2024
1 parent f401280 commit 0eb063c
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 32 deletions.
11 changes: 7 additions & 4 deletions Aplib.Core/Tactics/AnyOfTactic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,19 @@ public AnyOfTactic(List<Tactic> subTactics)
public AnyOfTactic(List<Tactic> subTactics, Func<bool> guard) : this(subTactics) => Guard = guard;

/// <inheritdoc/>
public override List<PrimitiveTactic> GetFirstEnabledActions()
public override Action? GetAction()
{
List<PrimitiveTactic> primitiveTactics = new();
List<Action> actions = new();

foreach (Tactic subTactic in SubTactics)
{
primitiveTactics.AddRange(subTactic.GetFirstEnabledActions());
Action? action = subTactic.GetAction();

if (action is not null)
actions.Add(action);
}

return primitiveTactics;
return actions[ThreadSafeRandom.Next(actions.Count)];
}
}
}
8 changes: 4 additions & 4 deletions Aplib.Core/Tactics/FirstOfTactic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ public FirstOfTactic(List<Tactic> subTactics, Func<bool> guard) : base(subTactic
}

/// <inheritdoc/>
public override List<PrimitiveTactic> GetFirstEnabledActions()
public override Action? GetAction()
{
foreach (Tactic subTactic in SubTactics)
{
List<PrimitiveTactic> firstOfTactics = subTactic.GetFirstEnabledActions();
Action? action = subTactic.GetAction();

if (firstOfTactics.Count > 0)
return firstOfTactics;
if (action is not null && action.IsActionable())
return action;
}

return new();
Expand Down
2 changes: 1 addition & 1 deletion Aplib.Core/Tactics/PrimitiveTactic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class PrimitiveTactic : Tactic
public PrimitiveTactic(Action action, Func<bool> guard) : base(guard) => Action = action;

/// <inheritdoc/>
public override List<PrimitiveTactic> GetFirstEnabledActions() => IsActionable() ? new() { this } : new();
public override Action? GetAction() => IsActionable() ? Action : null;

/// <inheritdoc/>
public override bool IsActionable() => base.IsActionable() && Action.IsActionable();
Expand Down
7 changes: 3 additions & 4 deletions Aplib.Core/Tactics/Tactic.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;

namespace Aplib.Core.Tactics
{
Expand Down Expand Up @@ -27,10 +26,10 @@ protected Tactic()
protected Tactic(Func<bool> guard) => Guard = guard;

/// <summary>
/// Gets the first enabled primitive actions.
/// Gets the enabled action.
/// </summary>
/// <returns>A list of primitive tactics that are enabled.</returns>
public abstract List<PrimitiveTactic> GetFirstEnabledActions();
/// <returns>An action that is enabled.</returns>
public abstract Action? GetAction();

/// <summary>
/// Determines whether the tactic is actionable.
Expand Down
32 changes: 32 additions & 0 deletions Aplib.Core/ThreadSafeRandom.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;
using System.Threading.Tasks;

internal static class ThreadSafeRandom
{
[ThreadStatic]
private static Random? _local;
private static readonly Random _global = new();

private static Random _instance
{
get
{
if (_local is null)
{
int seed;
lock (_global)
{
seed = _global.Next();
}

_local = new Random(seed);
}

return _local;
}
}

public static int Next() => _instance.Next();

public static int Next(int maxValue) => _instance.Next(maxValue);
}
39 changes: 20 additions & 19 deletions Aplib.Tests/Core/Tactics/TacticTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
namespace Aplib.Tests.Core.Tactics;
public class TacticTests
{
private readonly Action _emptyAction = new(() => { });
private readonly Action _emptyAction = new(effect: () => { });
private static string _result = "abc";
private readonly Action _filledAction = new(effect: () => _result = "def");

private static bool TrueGuard() => true;

Expand All @@ -16,18 +18,18 @@ public class TacticTests
/// Then the result should be the first subtactic.
/// </summary>
[Fact]
public void GetFirstEnabledActions_WhenTacticTypeIsFirstOf_ReturnsEnabledPrimitiveTactics()
public void GetAction_WhenTacticTypeIsFirstOf_ReturnsEnabledPrimitiveTactics()
{
// Arrange
PrimitiveTactic tactic1 = new(_emptyAction);
PrimitiveTactic tactic2 = new(_emptyAction);
PrimitiveTactic tactic2 = new(_filledAction);
FirstOfTactic parentTactic = new([tactic1, tactic2]);

// Act
List<PrimitiveTactic> enabledActions = parentTactic.GetFirstEnabledActions();
Action? enabledAction = parentTactic.GetAction();

// Assert
Assert.Contains(tactic1, enabledActions);
Assert.Equal(_emptyAction, enabledAction);
}

/// <summary>
Expand All @@ -36,18 +38,18 @@ public void GetFirstEnabledActions_WhenTacticTypeIsFirstOf_ReturnsEnabledPrimiti
/// Then the result should be the first subtactic.
/// </summary>
[Fact]
public void GetFirstEnabledActions_WhenTacticTypeIsFirstOfAndGuardEnabled_ReturnsEnabledPrimitiveTactics()
public void GetAction_WhenTacticTypeIsFirstOfAndGuardEnabled_ReturnsEnabledPrimitiveTactics()
{
// Arrange
PrimitiveTactic tactic1 = new(_emptyAction);
PrimitiveTactic tactic2 = new(_emptyAction);
PrimitiveTactic tactic2 = new(_filledAction);
FirstOfTactic parentTactic = new([tactic1, tactic2], TrueGuard);

// Act
List<PrimitiveTactic> enabledActions = parentTactic.GetFirstEnabledActions();
Action? enabledAction = parentTactic.GetAction();

// Assert
Assert.Contains(tactic1, enabledActions);
Assert.Equal(_emptyAction, enabledAction);
}

/// <summary>
Expand All @@ -56,19 +58,18 @@ public void GetFirstEnabledActions_WhenTacticTypeIsFirstOfAndGuardEnabled_Return
/// Then the result should contain all the subtactics.
/// </summary>
[Fact]
public void GetFirstEnabledActions_WhenTacticTypeIsAnyOf_ReturnsEnabledPrimitiveTactics()
public void GetAction_WhenTacticTypeIsAnyOf_ReturnsEnabledPrimitiveTactics()
{
// Arrange
PrimitiveTactic tactic1 = new(_emptyAction);
PrimitiveTactic tactic2 = new(_emptyAction);
AnyOfTactic parentTactic = new([tactic1, tactic2]);

// Act
List<PrimitiveTactic> enabledActions = parentTactic.GetFirstEnabledActions();
Action? enabledAction = parentTactic.GetAction();

// Assert
Assert.Contains(tactic1, enabledActions);
Assert.Contains(tactic2, enabledActions);
Assert.Equal(_emptyAction, enabledAction);
}

/// <summary>
Expand All @@ -77,16 +78,16 @@ public void GetFirstEnabledActions_WhenTacticTypeIsAnyOf_ReturnsEnabledPrimitive
/// Then the result should contain the primitive tactic.
/// </summary>
[Fact]
public void GetFirstEnabledActions_WhenTacticTypeIsPrimitiveAndActionIsActionable_ReturnsEnabledPrimitiveTactic()
public void GetAction_WhenTacticTypeIsPrimitiveAndActionIsActionable_ReturnsEnabledPrimitiveTactic()
{
// Arrange
PrimitiveTactic tactic = new(_emptyAction, TrueGuard);

// Act
List<PrimitiveTactic> enabledActions = tactic.GetFirstEnabledActions();
Action? enabledAction = tactic.GetAction();

// Assert
Assert.Contains(tactic, enabledActions);
Assert.Equal(_emptyAction, enabledAction);
}

/// <summary>
Expand All @@ -95,16 +96,16 @@ public void GetFirstEnabledActions_WhenTacticTypeIsPrimitiveAndActionIsActionabl
/// Then the result should be an empty list.
/// </summary>
[Fact]
public void GetFirstEnabledActions_WhenTacticTypeIsPrimitiveAndActionIsNotActionable_ReturnsEmptyList()
public void GetAction_WhenTacticTypeIsPrimitiveAndActionIsNotActionable_ReturnsEmptyList()
{
// Arrange
PrimitiveTactic tactic = new(_emptyAction, FalseGuard);

// Act
List<PrimitiveTactic> enabledActions = tactic.GetFirstEnabledActions();
Action? enabledAction = tactic.GetAction();

// Assert
Assert.Empty(enabledActions);
Assert.Null(enabledAction);
}

/// <summary>
Expand Down

0 comments on commit 0eb063c

Please sign in to comment.