Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/.vscode
/.vs
28 changes: 27 additions & 1 deletion source/PlanningAI.Tests/AgentTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,33 @@ await Assert.ThrowsAsync<InvalidOperationException>(

Assert.Equal(goal1, agent.CurrentGoal);
}
}

[Fact]
public async Task ShouldUseStateConsiderationToChooseBestGoal()
{
var planner = PlannerFactory.CreatePlanner();

DomainState initialState = DomainState.Empty;
initialState = initialState.Set("testState1", 0.2f);
initialState = initialState.Set("testState2", 0.5f);

var agent = new Agent(planner, null, initialState);

var goal1 = new TestGoal { Weight = 1 };
var goal2 = new TestGoal { Weight = 1 };

goal1.AddConsideration(Consideration.FromState("testState1"));
goal2.AddConsideration(Consideration.FromState("testState2"));

agent.AddGoal(goal1);
agent.AddGoal(goal2);

await Assert.ThrowsAsync<InvalidOperationException>(
async () => await agent.RunActionsAsync());

Assert.Equal(goal2, agent.CurrentGoal);
}
}

public abstract class GoalAction : AsyncExecutableActionBase
{
Expand Down
5 changes: 3 additions & 2 deletions source/PlanningAi/Agents/Agent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,18 @@ public partial class Agent : IAgent
private readonly IPlanner _planner;
private readonly ILogger _logger;

public DomainState CurrentState { get; private set; } = DomainState.Empty;
public DomainState CurrentState { get; private set; };
public IAgentGoal CurrentGoal { get; private set; }
public IDomainAction CurrentAction { get; private set; }

public IReadOnlyList<IDomainAction> Actions => _actions;
public IReadOnlyList<IAgentGoal> Goals => _goals;

public Agent(IPlanner planner, ILogger logger = null)
public Agent(IPlanner planner, ILogger logger = null, DomainState initialState = null)
{
_planner = planner ?? throw new ArgumentNullException(nameof(planner));
_logger = logger ?? new DummyLogger();
CurrentState = initialState ?? DomainState.Empty;
}

/// <summary>
Expand Down
8 changes: 7 additions & 1 deletion source/PlanningAi/Agents/Consideration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,11 @@ public static IConsideration FromFunc(Func<DomainState, float> getValueFunc, str
{
return new DelegateConsideration(name ?? "Unnamed", getValueFunc);
}
}

[PublicAPI]
public static IConsideration FromState(string value, string name = null)
{
return new StateConsideration(name ?? "Unnamed", value);
}
}
}
23 changes: 23 additions & 0 deletions source/PlanningAi/Agents/StateConsideration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System;
using PlanningAi.Planning;

namespace PlanningAi.Agents
{
internal sealed class StateConsideration : IConsideration
{
private readonly string _value;

public string Name { get; }

public StateConsideration(string name, string value)
{
Name = name ?? throw new ArgumentNullException(nameof(name));
_value = string.IsNullOrEmpty(value) ? throw new ArgumentNullException(nameof(value)) : value;
}

public float GetValue(DomainState currentState)
{
return currentState.GetValueOrDefault<float>(_value);
}
}
}