MountainGoap 0.3.1

There is a newer version of this package available.
See the version list below for details.
dotnet add package MountainGoap --version 0.3.1                
NuGet\Install-Package MountainGoap -Version 0.3.1                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="MountainGoap" Version="0.3.1" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add MountainGoap --version 0.3.1                
#r "nuget: MountainGoap, 0.3.1"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install MountainGoap as a Cake Addin
#addin nuget:?package=MountainGoap&version=0.3.1

// Install MountainGoap as a Cake Tool
#tool nuget:?package=MountainGoap&version=0.3.1                

<img src="https://github.com/caesuric/mountain-goap/raw/main/logo.png" alt="Mountain GOAP logo" title="Mountain GOAP" align="right" height="180" />

Mountain GOAP

Generic C# GOAP (Goal Oriented Action Planning) library for creating AI agents to be used in games. GOAP is a type of an AI system for games popularized by the F.E.A.R. AI paper. GOAP agents use A* pathfinding to plan paths through a series of sequential actions, creating action sequences that allow the agent to achieve its goals.

Mountain GOAP favors composition over inheritance, allowing you to create agents from a series of callbacks. In addition, Mountain GOAP's agents support multiple weighted goals and will attempt to find the greatest utility among a series of goals.

  1. Quickstart
    1. Using distributable
    2. Using distributable in Unity
    3. Using NuGet package
    4. Using as a Unity package
    5. Using the code directly
    6. Using the library after installation
  2. Concepts & API
    1. Agents
      1. Agent state
    2. Goals
    3. Actions
    4. Sensors
    5. Future features - permutation selectors
  3. Events
    1. Agent events
    2. Action events
    3. Sensor events
  4. Logger
  5. Examples
  6. Project structure
  7. Roadmap
  8. Other open source GOAP projects
  9. License Acknowledgements

Quickstart

Using distributable

Download the release, unzip, and include the DLL in your project. In Visual Studio, you can do this by right-clicking on "Dependencies" in the Solution Explorer, then clicking "Add COM Reference," clicking "Browse," and browsing to the DLL.

Using distributable in Unity

Download the release, unzip to a folder, and drag the folder into your Unity project.

Using NuGet package

If you are not using Unity, you can download and use MountainGoap as a NuGet package.

Right click your package and click "Manage NuGet Packages," then search for "MountainGoap" and install the package.

Using as a Unity package

In the works.

Using the code directly

Clone the repo and copy the code in the MountainGoap folder to your repo.

Using the library after installation

No matter which method of installation you use, you can access MountainGoap by using the MountainGoap namespace as a prefix to the library classes, or by including the following line in your code:

using MountainGoap;

Concepts & API

Agents

Agents are indivdual entities that act within your game or simulated world. The simplest example of instantiating an agent is this: Agent agent = new Agent();

In practice, you will want to pass the agent constructor various things it needs to make a functional agent. Read on to understand what kinds of objects you should pass your agents.

When you want your agent to act, just call the following: agent.Step();

What kind of timeframe is represented by a "step" will vary based on your engine. In a turn based game, a step might be one turn. In a realtime engine like Unity, you might call agent.Step() on every Update() cycle.

Agent state

The agent stores a dictionary of objects called its state. This state can include anything, but simple values work best with goals and actions. If you need to reference complex game state, however, this is not a problem -- sensors, covered below, can be used to translate complex values like map states into simpler ones, like booleans. More on that below.

State can be passed into the agent constructor, like so:

Agent agent = new Agent(
    state: new Dictionary<string, object> {
        { "nearOtherAgent", false },
        { "otherAgents", new List<Agent>() }
    }
);

Goals

Goals dictate the state values that the agent is trying to achieve. Goals have relatively simple constructors, taking just a dictionary of keys and values the agent wants to see in its state and a weight that indicates how important the goal is. The higher the weight, the more important the goal.

Goals can be passed into the agent constructor, like so:

Goal goal = new Goal(
    desiredState: new Dictionary<string, object> {
        { "nearOtherAgent", true }
    },
    weight: 2f
);
Agent agent = new Agent(
    goals: new List<Goal> {
        goal
    }
);

Actions

Actions dictate arbitrary code the agent can execute to affect the world and achieve its goals. Each action, when it runs, will execute the code passed to it, which is called the action executor. Actions can also have preconditions, state values required before the agent is allowed to execute the action, and postconditions, which are values the state is expected to hold if the action is successful. Finally, each action has a cost, which is used in calculating the best plan for the agent.

Actions return an ExecutionStatus enum to say if they succeeded or not. If they succeed, the postconditions will automatically be set to the values passed to the action constructor.

Actions can be passed into the agent constructor, like so:

Action giveHugAction = new Action(
    executor: (Agent agent, Action action) => {
        Console.WriteLine("hugged someone");
        return ExecutionStatus.Succeeded;
    },
    preconditions: new Dictionary<string, object> {
        { "nearOtherAgent", true }
    },
    postConditions: new Dictionary<string, object> {
        { "wasHugged", true }
    },
    cost: 0.5f
);
Agent agent = new Agent(
    actions: new List<Action> {
        giveHugAction
    }
);

Sensors

Sensors allow an agent to distill information into their state, often derived from other state values. Sensors execute on every Step() call, and use a sensor handler to execute code. Sensors can be passed into the agent constructor, like so:

Sensor agentProximitySensor = new Sensor(
    (Agent agent) => {
        if (AgentNearOtherAgent(agent)) agent.State["nearOtherAgent"] = true;
        else agent.State["nearOtherAgent"] = false;
    }
);
Agent agent = new Agent(
    sensors: new List<Sensor> {
        agentProximitySensor
    }
);

Future Feature - Permutation Selectors

Finally, actions can be constructed with permutation selectors, which will instantiate multiple copies of the action with different parameters for purposes such as target selection. The library comes with some default permutation selectors, or you can write your own as callbacks. For instance, if you want an action to be evaluated separately with each member of a list as a potential parameter, you would construct the action as so:

Action myAction = new Action(
    permutationSelectors: new Dictionary<string, PermutationSelectorCallback> {
        { "target1", PermutationSelectorGenerators.SelectFromCollectionInState<Agent>("otherAgents") },
        { "target2", PermutationSelectorGenerators.SelectFromCollectionInState<Agent>("otherAgents") }
    },
    executor: (Agent agent, Action action) => {
        Console.WriteLine(action.GetParameter("target1").ToString());
        Console.WriteLine(action.GetParameter("target2").ToString());
    }
);

The code above will create an action that when evaluated for execution in an agent plan will be considered once for every pair combination of elements in the "otherAgents" collection of the agent state, one for target1, and one for target2. Note that while this feature has many potential uses down the road, it is not particularly helpful in agent planning until the utility of an action can be calculated via a custom callback function that can be based on action parameters.

Events

Mountain GOAP features a simple event system that allows you to subscribe to events that occur during the agent's planning and execution process.

Agent events

The following events are available on agents:

  • OnAgentActionSequenceCompleted: Called when the agent has finished executing its plan.
    • Example usage: Agent.OnAgentActionSequenceCompleted += (Agent agent) => { Console.WriteLine("Agent finished executing its plan."); };
  • OnAgentStep: Called when the agent executes a step of work.
    • Example usage: Agent.OnAgentStep += (Agent agent) => { Console.WriteLine("Agent is working."); };
  • OnPlanningStarted: Called when the agent begins planning.
    • Example usage: Agent.OnPlanningStarted += (Agent agent) => { Console.WriteLine("Agent started planning."); };
  • OnPlanningFinished: Called when the agent finishes planning.
    • Example usage: Agent.OnPlanningFinished += (Agent agent, Goal? goal, float utility) => { Console.WriteLine("Agent finished planning."); };
  • OnPlanningFinishedForSingleGoal: Called when the agent finishes planning for a single goal.
    • Example usage: Agent.OnPlanningFinishedForSingleGoal += (Agent agent, Goal goal, float utility) => { Console.WriteLine("Agent finished planning for a single goal."); };

Action events

The following events are available on actions:

  • OnBeginExecuteAction: Called when the agent begins executing an action.
    • Example usage: Action.OnBeginExecuteAction += (Agent agent, Action action, Dictionary<string, object> parameters) => { Console.WriteLine("Agent started executing an action."); };
  • OnFinishExecuteAction: Called when the agent finishes executing an action.
    • Example usage: Action.OnFinishExecuteAction += (Agent agent, Action action, ExecutionStatus status, Dictionary<string, object> parameters) => { Console.WriteLine("Agent finished executing an action."); };

Sensor events

The following events are available on sensors:

  • OnSensorRun: Called when the agent runs a sensor.
    • Example usage: Sensor.OnSensorRun += (Agent agent, Sensor sensor) => { Console.WriteLine("Agent ran a sensor."); };

Logger

Mountain GOAP contains a default logger implementation that can be used to examine agent behavior. After including the MountainGoapLogger code, you can enable the logger using the following code:

_ = new MountainGoapLogger.DefaultLogger(
    logToConsole: true,
    loggingFile: "agents.log"
);

Examples

Examples documentation.

  1. Happiness Maximizer Example
  2. RPG Example

Project Structure

File or folder Description
/Examples/ Examples of how to use the library
/Examples/RpgExample/ RPG grid-based example.
/Examples/RpgExample/RpgCharacterFactory.cs Static methods for creating character agents.
/Examples/RpgExample/RpgExample.cs Main RPG example entrypoint.
/Examples/RpgExample/RpgMonsterFactory.cs Static methods for creating enemy agents derived from the base character agent.
/Examples/RpgExample/Utils.cs RPG example utility functions.
/Examples/examples.md Examples documentation.
/Examples/HappinessIncrementer.cs Happiness incrementer example.
/Examples/Program.cs Examples entrypoint.
/MountainGoap/ The main library folder
/MountainGoap/CallbackDelegates/ Function signatures for callbacks.
/MountainGoap/CallbackDelegates/ExecutorCallback.cs Function signature for a callback that executes an action.
/MountainGoap/CallbackDelegates/PermutationSelectorCallbacks.cs Function signature for a callback that selects a list of options for an action parameter.
/MountainGoap/CallbackDelegates/SensorRunCallback.cs Function signature for a callback that runs a sensor.
/MountainGoap/Internals/ Internal classes that external applications using the library will not need directly.
/MountainGoap/Internals/ActionAStar.cs Class that calculates AStar for an action graph.
/MountainGoap/Internals/ActionGraph.cs Class that represents an action graph.
/MountainGoap/Internals/ActionNode.cs Class that represents a node in an action graph.
/MountainGoap/Internals/CopyDictionaryExtensionMethod.cs Convenience extension method for copying a dictionary.
/MountainGoap/Internals/Planner.cs Planning class used by agents.
/MountainGoap/Action.cs An action that can be made available to agents.
/MountainGoap/Agent.cs An agent that can figure out plans to execute.
/MountainGoap/ExecutionStatus.cs An enum defining the execution status of an action.
/MountainGoap/Goal.cs A goal that agents can attempt to accomplish.
/MountainGoap/PermutationSelectorGenerators.cs Generators for lambda functions that return a list of options for an action parameter.
/MountainGoap/Sensor.cs A sensor that generates data for use by an agent.
/MountainGoapLogging/DefaultLogger.cs Example logger implementation that can be used to inspect agent behavior.

Roadmap

  • full API documentation (auto gen if possible)
  • Tests
  • Custom action cost override based on parameters
  • Examples - general and Unity

Other open source GOAP projects

  • ReGoap - C# GOAP library with more direct Unity support, providing Unity Components that can be attached to GameObjects.

License Acknowledgements

Priority Queue Implementation

The MIT License (MIT)

Copyright (c) 2013 Daniel "BlueRaja" Pflughoeft

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.1

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.1.1 1,184 5/25/2024
1.0.1 123 5/23/2024
1.0.0 115 5/22/2024
0.16.0 118 5/22/2024
0.14.0 528 1/3/2024
0.13.0 129 1/3/2024
0.12.0 151 1/2/2024
0.11.4 138 12/23/2023
0.11.3 151 12/18/2023
0.10.0 265 9/17/2023
0.9.1 117 9/17/2023
0.9.0 122 9/13/2023
0.8.0 131 9/11/2023
0.7.1 126 9/7/2023
0.7.0 166 6/5/2023
0.6.8 131 6/2/2023
0.6.7 129 6/1/2023
0.6.5 156 4/17/2023
0.6.3 558 3/18/2023
0.6.2 211 3/16/2023
0.6.1 198 3/15/2023
0.5.0 336 10/30/2022
0.4.1 334 10/30/2022
0.3.2 379 10/10/2022
0.3.1 376 10/10/2022
0.2.0 392 10/10/2022
0.1.6 382 10/8/2022
0.1.5 376 10/8/2022
0.1.4 378 10/8/2022
0.1.1 377 10/6/2022

Initial release.