Skip to content

Commit

Permalink
Merge branch 'master' into fix/toggle-config-in-graph-viewer
Browse files Browse the repository at this point in the history
  • Loading branch information
crashkonijn authored Dec 5, 2024
2 parents 08e7451 + 659546c commit 9c73d1e
Show file tree
Hide file tree
Showing 25 changed files with 1,007 additions and 161 deletions.
112 changes: 102 additions & 10 deletions Package/Runtime/CrashKonijn.Agent.Runtime/ActionBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,39 +8,64 @@ public abstract class AgentActionBase<TActionData, TActionProperties>
{
private IActionDisabler disabler;

/// <summary>
/// Gets the action data.
/// </summary>
/// <returns>The action data.</returns>
public IActionData GetData()
{
return this.CreateData();
}

/// <summary>
/// Creates a new instance of action data.
/// </summary>
/// <returns>The created action data.</returns>
public virtual TActionData CreateData()
{
return new TActionData();
}

/// <summary>
/// Gets the action properties.
/// </summary>
public abstract TActionProperties Properties { get; }

/// <summary>
/// Called when the action is created.
/// </summary>
public virtual void Created() { }

/// <summary>
/// Called when the action is started (when it is assigned to an agent).
/// </summary>
/// <param name="agent">The agent.</param>
/// <param name="data">The action data.</param>
public void Start(IMonoAgent agent, IActionData data) => this.Start(agent, (TActionData) data);

/// <summary>
/// Called when the action is started (when it is assigned to an agent).
/// </summary>
/// <param name="agent">The agent.</param>
/// <param name="data">The action data.</param>
public virtual void Start(IMonoAgent agent, TActionData data) { }

/// <summary>
/// Determines whether the action is enabled. This is used by the planner.
/// </summary>
/// <param name="agent">The action receiver.</param>
/// <returns>True if the action is enabled, otherwise false.</returns>
public bool IsEnabled(IActionReceiver agent)
{
return this.IsEnabled(agent, agent.Injector);
}

public void Enable()
{
this.disabler = null;
}

public void Disable(IActionDisabler disabler)
{
this.disabler = disabler;
}

/// <summary>
/// Determines whether the action is enabled. This is used by the planner.
/// </summary>
/// <param name="receiver">The action receiver.</param>
/// <param name="references">The component references.</param>
/// <returns>True if the action is enabled, otherwise false.</returns>
public virtual bool IsEnabled(IActionReceiver receiver, IComponentReference references)
{
if (this.disabler == null)
Expand All @@ -56,30 +81,97 @@ public virtual bool IsEnabled(IActionReceiver receiver, IComponentReference refe
return true;
}

/// <summary>
/// Enables the action.
/// </summary>
public void Enable()
{
this.disabler = null;
}

/// <summary>
/// Disables the action.
/// </summary>
/// <param name="disabler">The action disabler.</param>
public void Disable(IActionDisabler disabler)
{
this.disabler = disabler;
}

/// <summary>
/// Called once before performing the action. Don't override this method, override the other BeforePerform method
/// instead.
/// </summary>
/// <param name="agent">The agent.</param>
/// <param name="data">The action data.</param>
public void BeforePerform(IMonoAgent agent, IActionData data) => this.BeforePerform(agent, (TActionData) data);

/// <summary>
/// Called once before performing the action. Override this method to implement custom logic.
/// </summary>
/// <param name="agent">The agent.</param>
/// <param name="data">The action data.</param>
public virtual void BeforePerform(IMonoAgent agent, TActionData data) { }

/// <summary>
/// Performs the action. Don't override this method, override the other Perform method instead.
/// </summary>
/// <param name="agent">The agent.</param>
/// <param name="data">The action data.</param>
/// <param name="context">The action context.</param>
/// <returns>The action run state.</returns>
public IActionRunState Perform(IMonoAgent agent, IActionData data, IActionContext context) => this.Perform(agent, (TActionData) data, context);

/// <summary>
/// Performs the action with the specified action data. Use this method to implement custom logic.
/// </summary>
/// <param name="agent">The agent.</param>
/// <param name="data">The action data.</param>
/// <param name="context">The action context.</param>
/// <returns>The action run state.</returns>
public abstract IActionRunState Perform(IMonoAgent agent, TActionData data, IActionContext context);

/// <summary>
/// Called when the action ends. This is called after the action is completed or stopped.
/// </summary>
/// <param name="agent">The agent.</param>
/// <param name="data">The action data.</param>
public virtual void End(IMonoAgent agent, TActionData data) { }

/// <summary>
/// Called when the action is stopped. Don't override this method, override the other Stop method instead.
/// </summary>
/// <param name="agent">The agent.</param>
/// <param name="data">The action data.</param>
public void Stop(IMonoAgent agent, IActionData data)
{
this.Stop(agent, (TActionData) data);
this.End(agent, (TActionData) data);
}

/// <summary>
/// Called when the action is stopped. Use this method to implement custom logic.
/// </summary>
/// <param name="agent">The agent.</param>
/// <param name="data">The action data.</param>
public virtual void Stop(IMonoAgent agent, TActionData data) { }

/// <summary>
/// Called when the action is completed. Don't override this method, override the other Complete method instead.
/// </summary>
/// <param name="agent">The agent.</param>
/// <param name="data">The action data.</param>
public void Complete(IMonoAgent agent, IActionData data)
{
this.Complete(agent, (TActionData) data);
this.End(agent, (TActionData) data);
}

/// <summary>
/// Called when the action is completed. Use this method to implement custom logic.
/// </summary>
/// <param name="agent">The agent.</param>
/// <param name="data">The action data.</param>
public virtual void Complete(IMonoAgent agent, TActionData data) { }
}
}
20 changes: 20 additions & 0 deletions Package/Runtime/CrashKonijn.Agent.Runtime/AgentBehaviour.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ private void Update()
this.Run();
}

/// <summary>
/// Runs the current action. This is called in the Update method.
/// </summary>
public void Run()
{
if (this.ActionState.Action == null)
Expand Down Expand Up @@ -165,6 +168,12 @@ private bool IsInRange()
return this.ActionState.Action.IsInRange(this, distance, this.ActionState.Data, this.Injector);
}

/// <summary>
/// Sets the action for the agent. This is mostly used by the action provider.
/// </summary>
/// <param name="actionProvider">The action provider.</param>
/// <param name="action">The action to set.</param>
/// <param name="target">The target of the action.</param>
public void SetAction(IActionProvider actionProvider, IAction action, ITarget target)
{
this.ActionProvider = actionProvider;
Expand All @@ -188,6 +197,10 @@ public void SetAction(IActionProvider actionProvider, IAction action, ITarget ta
this.Events.ActionStart(action);
}

/// <summary>
/// Stops the current action.
/// </summary>
/// <param name="resolveAction">Whether to resolve for a new action after stopping.</param>
public void StopAction(bool resolveAction = true)
{
var action = this.ActionState.Action;
Expand All @@ -201,6 +214,10 @@ public void StopAction(bool resolveAction = true)
this.ResolveAction();
}

/// <summary>
/// Completes the current action.
/// </summary>
/// <param name="resolveAction">Whether to resolve for a new action after completing.</param>
public void CompleteAction(bool resolveAction = true)
{
var action = this.ActionState.Action;
Expand All @@ -214,6 +231,9 @@ public void CompleteAction(bool resolveAction = true)
this.ResolveAction();
}

/// <summary>
/// Will trigger try and resolve a new action from the action provider.
/// </summary>
public void ResolveAction()
{
if (this.ActionProvider == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
{
public interface IKeyResolver
{
string GetKey(IConnectable action, ICondition condition);
string GetKey(IConnectable action, IEffect effect);
string GetKey(ICondition condition);
string GetKey(IEffect effect);
bool AreConflicting(IEffect effect, ICondition condition);
void SetWorldData(IWorldData globalWorldData);
}
}
36 changes: 27 additions & 9 deletions Package/Runtime/CrashKonijn.Goap.Resolver/GraphBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ public Graph Build(IEnumerable<IConnectable> actions)
return graph;
}

private void ConnectNodes(INode node, Dictionary<string, List<INode>> effectMap,
Dictionary<string, List<INode>> conditionMap, IGraph graph)
private void ConnectNodes(
INode node, Dictionary<string, List<INode>> effectMap,
Dictionary<string, List<INode>> conditionMap, IGraph graph
)
{
if (!graph.ChildNodes.Contains(node) && !node.IsRootNode)
graph.ChildNodes.Add(node);
Expand All @@ -49,17 +51,19 @@ private void ConnectNodes(INode node, Dictionary<string, List<INode>> effectMap,
if (actionNodeCondition.Connections.Any())
continue;

var key = this.keyResolver.GetKey(node.Action, actionNodeCondition.Condition);
var key = this.keyResolver.GetKey(actionNodeCondition.Condition);

if (!effectMap.ContainsKey(key))
continue;

actionNodeCondition.Connections = effectMap[key].ToArray();
var connections = effectMap[key].Where(x => !this.HasConflictingConditions(node, x)).ToArray();

actionNodeCondition.Connections = connections;

foreach (var connection in actionNodeCondition.Connections)
{
connection.Effects.First(x => this.keyResolver.GetKey(connection.Action, x.Effect) == key)
.Connections = conditionMap[key].ToArray();
connection.Effects.First(x => this.keyResolver.GetKey(x.Effect) == key)
.Connections = conditionMap[key].Where(x => !this.HasConflictingConditions(node, x)).ToArray();
}

foreach (var subNode in actionNodeCondition.Connections)
Expand All @@ -69,6 +73,20 @@ private void ConnectNodes(INode node, Dictionary<string, List<INode>> effectMap,
}
}

private bool HasConflictingConditions(INode node, INode otherNode)
{
foreach (var condition in node.Conditions)
{
foreach (var otherEffects in otherNode.Effects)
{
if (this.keyResolver.AreConflicting(otherEffects.Effect, condition.Condition))
return true;
}
}

return false;
}

private Dictionary<string, List<INode>> GetEffectMap(INode[] actionNodes)
{
var map = new Dictionary<string, List<INode>>();
Expand All @@ -77,7 +95,7 @@ private Dictionary<string, List<INode>> GetEffectMap(INode[] actionNodes)
{
foreach (var actionNodeEffect in actionNode.Effects)
{
var key = this.keyResolver.GetKey(actionNode.Action, actionNodeEffect.Effect);
var key = this.keyResolver.GetKey(actionNodeEffect.Effect);

if (!map.ContainsKey(key))
map[key] = new List<INode>();
Expand All @@ -97,7 +115,7 @@ private Dictionary<string, List<INode>> GetConditionMap(INode[] actionNodes)
{
foreach (var actionNodeConditions in actionNode.Conditions)
{
var key = this.keyResolver.GetKey(actionNode.Action, actionNodeConditions.Condition);
var key = this.keyResolver.GetKey(actionNodeConditions.Condition);

if (!map.ContainsKey(key))
map[key] = new List<INode>();
Expand All @@ -109,4 +127,4 @@ private Dictionary<string, List<INode>> GetConditionMap(INode[] actionNodes)
return map;
}
}
}
}
Loading

0 comments on commit 9c73d1e

Please sign in to comment.