htn_planner README

The project's README from github.com/urosidoki/htn_planner. As one markdown file: README.md.

HTN Planner

HTN Planner is a C++ hierarchical task network planner for game AI. Domains are written in a small declarative language and translated ahead of time into native C. The runtime executes the generated planner directly and does not parse domain source during gameplay.

Project status

HTN Planner is under active development. Published releases are tested, while the public API, domain language and generated-code ABI continue to evolve.

Before upgrading, review the release notes for compatibility changes and migration instructions. Some updates require regenerating domains and rebuilding the integration.

Feedback, bug reports and integration experiences are welcome.

Overview

The repository includes:

Version 2.0.4 removes native method/task recursion from generated planners, extends callterm error reporting and fixes axiom output assignments/backtracking. It changes the public callterm error API and generated/runtime bridge ABIs despite the patch version. Migrate client configuration, regenerate domains and rebuild the host, libraries and domain DLLs together. See the 2.0.4 release notes and migration guide. When upgrading from 2.0.2 or earlier, also follow the 2.0.3 migration guide.

Domain example

(:domain GuardNPC top_level_domain

    (:method (run) top_level_method
        (patrol
            (and
                (guard_on_duty)
            )
            (
                (!move_to "checkpoint")
                (!scan_area)
            )
        )
    )
)

A successful decomposition returns a plan containing the primitive tasks !move_to and !scan_area. The engine assigns meaning to those tasks and decides when they start, complete or fail.

Choosing an integration pattern

See Planner use cases for NPC behavior, active-plan validation, squad coordination and AI Director integration flows. The client owns action execution, scheduling and cancellation.

Requirements

Premake, SDL, Dear ImGui, GoogleTest and the remaining development dependencies are included in the repository.

Build and run the visual demo

Generate the Visual Studio solution from the repository root:

GenerateProjectFiles.bat

Build HTN.sln for x64. Use Debug to include generated decomposition capture and the visual debugger. Use Release for an optimized runtime build without debugger instrumentation.

Run:

bin/<configuration>-windows-x86_64/HTNDemo/HTNDemo.exe

The generated-only HTNDemo provides three views:

The demo loads world-state data for inspection, but its domain definitions are already compiled into native generated planners.

Compiler pipeline

flowchart LR
    Source[".domain source"] --> Lexer["Compiler lexer and tokens"]
    Lexer --> AST["Compiler AST"]
    AST --> Validation["Validation and linking"]
    Validation --> IR["Compiler IR"]
    IR --> Generator["C code generator"]
    Generator --> Native["Native generated planner"]
  1. HTNCompilerDomainLexer creates tokens and source ranges.
  2. HTNCompilerDomainSyntaxParser creates the compiler-owned AST.
  3. Validation and linking resolve declarations, includes, overrides and references.
  4. HTNCompilerIRBuilder lowers the linked domain into compiler IR.
  5. HTNCCodeGenerator emits C source and static metadata.
  6. The client build compiles that C source into the game or a domain module.

The AST and IR are build-time representations. Generated runtime execution does not retain or depend on them. See Compiler pipeline and IR boundary.

Translate a domain

Build HTNTranslator, then validate a domain without producing output:

HTNTranslator.exe --check path\to\npc.domain

Generate C for an exported entry point:

HTNTranslator.exe path\to\npc.domain CreateNpcHTN generated

The generated source exports:

extern "C" const HTNGeneratedPlannerDefinition* CreateNpcHTN_GetDefinition(void);

Useful translation options are:

--backtracking-policy=fixed-with-overflow|fixed-capacity
--backtracking-capacity=<positive integer>
--runtime-backtracking-support=disabled|enabled

Compile generated C with the same configuration definitions and ABI as the runtime. Regenerate domain source whenever the generated planner ABI changes.

Integrate with a C++ engine

The simplest integration uses HTNIntegration, which supplies HTNPlannerHook, HTNPlanningUnit and HTNDatabaseHook:

#include "HTNIntegration.h"

extern "C" const HTNGeneratedPlannerDefinition* CreateNpcHTN_GetDefinition(void);

HTNDatabaseHook Database;
HTNCallTermRegistry CallTerms;
HTNPlannerHook Planner(Database.GetWorldState(), CallTerms);

if (!Planner.SetGeneratedPlannerDefinition(CreateNpcHTN_GetDefinition()))
    return false;

HTNPlanningUnit Unit(Database, Planner, HtnSymbol::sGetSymbol("run"));
Unit.GetExecutionContext().MissingCallTermPolicy = HTNMissingCallTermPolicy::FailSilently;
const HTNDecompositionStatus Status = Unit.DecomposeTopLevelMethod();

The example explicitly chooses silent failure for missing callterms. To report them through your own diagnostics, configure Report and a callback as described in Missing callterm policy.

After a successful decomposition, use ResolveCurrentPrimitiveTask() and GetCurrentPrimitiveTask() to inspect the next action. Call CompleteCurrentPrimitiveTask() after the engine finishes that action. The engine owns action dispatch, replanning policy, scheduling and world-state updates.

Call terms connect domain expressions to engine functions through HTNCallTermRegistry and HTNCallTermBindingContext. The packaged IntegrationConsumer and CoreConsumer examples demonstrate the optional integration layer and the lower-level runtime API respectively.

Generated execution debugger

Instrumented builds can capture generated execution without changing planner logic:

#ifdef HTN_DEBUG_DECOMPOSITION
HTNGeneratedDebugger Debugger;
Debugger.SetEnabled(true);
Unit.SetGeneratedDebugger(&Debugger);
#endif

The debugger records methods, branches, conditions, axioms, tasks, results, source ranges and scoped values. Its data model is independent of ImGui; an engine can render the captured nodes in its own editor. HTNDemo includes an ImGui reference view.

The application owns the debugger object. Instrumented generated domains and their host runtime must use matching ABI definitions. See Generated execution debugger.

SDK package

To build and validate all supported SDK variants:

BuildAndValidateSDK.bat

This command:

  1. Generates HTNSDK.sln.
  2. Builds the eight CRT, configuration and instrumentation variants.
  3. Creates a versioned directory and ZIP under dist.
  4. Extracts the package outside the source tree.
  5. Builds and runs its core, integration and dynamic-domain consumers.

To generate only the SDK solution:

GenerateSDKProjectFiles.bat

The package exports CMake targets for HTNFramework, HTNIntegration, HTNRuntimeBridge and HTNTranslator. Choose an SDK variant that matches the engine's CRT and instrumentation settings. See SDK variants and SDK distribution.

Repository layout

Path Purpose
HTNFramework Core data types, world state, compiler frontend, IR, code generator and generated runtime.
HTNIntegration Optional C++ engine integration and active-plan handling.
HTNRuntimeBridge Optional bridge for dynamically loaded generated domain modules.
HTNTranslator Command-line domain validator and C source generator.
HTNDemo SDL and ImGui generated planner demo.
HTNHotReloadDemo Example generated-domain DLL compilation and hot reload flow.
HTNEditor Domain authoring tool.
HTNLanguageServer Diagnostics and language tooling backend.
HTNVSCode VS Code extension client.
HTNTest Runtime, compiler, integration and regression tests.
HTNBenchmark Generated planner benchmarks.
Domains Example domains, includes and inheritance hierarchies.
WorldStates Example world-state inputs used by demos and tests.
SDK Packaging, CMake configuration and external consumer validation.
docs Architecture, debugger, SDK distribution and release documentation.

Validation

Build HTNTest and run its executable from the HTNTest directory so relative test assets resolve correctly:

..\bin\Release-windows-x86_64\HTNTest\HTNTest.exe

The test suite covers compiler diagnostics, AST and IR behavior, generated planning, backtracking, includes, overrides, call terms, lists, ABI validation, dynamic modules, concurrency and the public integration API.

See CI validation for the repository build matrix.

Documentation

The documentation index links the compiler architecture, generated debugger, SDK distribution and release guides. See CONTRIBUTING.md for development workflow and CHANGELOG.md for release history.

Contributors

The generated planner, compiler pipeline and public release are developed and maintained by Jose Antonio Escribano. The shared 2023 foundation retained in the core, parsing, world-state and integration layers was co-authored with Sandra Alvarez.

See CONTRIBUTORS.md and NOTICE.md for contributor credits and formal copyright attribution.

Third-party software

Applicable notices are included when producing an SDK package.

References

License

Licensed under the MIT License. See copyright and attribution and third-party notices before redistributing binaries or SDK packages.

Variable declarations

Use (= ?value expression) to declare and initialize a fresh local variable. The compiler rejects destinations already declared or used in the same path. == remains equality comparison; implicit (?value (call ...)) binding is rejected. See assignment syntax and migration.

htn_planner (urosidoki/htn_planner)

debugger
Searching Database…

What is this?HTN Planner is a C++ hierarchical task network planner for game AI: domains are written in a small declarative language and translated ahead of time into native C, so the runtime executes generated code directly without parsing domain source during gameplay.
Is this a runtime library or does it also include a compiler and tooling?It's both: HTNFramework provides the core runtime, HTNTranslator compiles domain source into C, and the repo also ships an editor, language server, VS Code extension, demo app and benchmarks.
How do I get it running?Generate the Visual Studio solution from the repository root and build HTN.sln for x64 (Debug for the visual debugger, Release for an optimized build), then run the generated HTNDemo.
What do I need installed before building it?Windows x64 with Visual Studio 2022 (Desktop development with C++ workload), MSVC v143, a Windows SDK, and CMake 3.25+ if consuming the packaged SDK via CMake.
Is it safe to just drop in a new version?No — the public API, domain language and generated-code ABI are still evolving, so upgrading can require regenerating domains and rebuilding the host, libraries and domain DLLs together per the release migration guide.
Who is this aimed at?C++ game developers who need in-engine NPC behavior planning, such as squad coordination or AI Director systems, rather than a scripting-only solution.
Does it run on Mac or Linux too?No, the project currently only targets Windows x64 with MSVC.
How does a game actually run a plan generated by this?After decomposition, the engine calls ResolveCurrentPrimitiveTask() and GetCurrentPrimitiveTask() to get the next action, then CompleteCurrentPrimitiveTask() once it finishes; the engine owns action dispatch, scheduling and replanning.
Can I see why the planner picked a certain path?Instrumented builds include a generated execution debugger that records methods, branches, conditions, axioms, tasks and bound variables, with an ImGui reference viewer included in the demo.
What extra tools come with the SDK besides the runtime?The repo includes a domain editor, an HTNLanguageServer for diagnostics, a VS Code extension client, an SDL/ImGui demo, a hot-reload example, a test suite and benchmarks.
How do call terms connect domain logic to my game code?HTNCallTermRegistry and HTNCallTermBindingContext bind domain expressions to engine functions, and you can configure a Report callback instead of silently failing on missing callterms.
What are similar projects?MonoGame, cppinsights, bgfx, zenc, SFML, spinel, GATE, rust-analyzer
Creator
urosidoki
Size
10.4 MB
Stars
369
Age
28d
Commits · 90 Days