Engineering methods
A Portable C++20 Runtime for NPC Decision Making
Keep behavior selection local and testable while the host engine owns navigation, animation and physical side effects. Inspect the boundary with a deterministic replay.

Separate a decision from its physical execution
A simulated actor can decide to investigate a sound without owning the pathfinding or animation system that carries out the action. That separation makes the decision layer easier to test and reuse. The host engine supplies observations; a behavior runtime selects an intent; a narrow adapter translates that intent into host operations.
Rootcastle NPC AI is a public C++20 SDK built around this boundary. Its documented scope is behavior selection, not a complete physics engine, built-in navigation system, LLM or finished plugin for every game engine.
Define what crosses the boundary
Useful inputs include actor identity, position and orientation, health, faction relationships and time-stamped sensory events. The host must define how observations are obtained. A line-of-sight flag supplied to a runtime does not prove that a raycast was performed correctly.
Outputs should describe an intent, a target or a destination using stable identifiers and explicit semantics. The host adapter can then validate the command against its own world state. Keep irreversible or game-specific side effects outside a generic utility-scoring function.
The public SDK's basic interface is illustrated by this abbreviated example from its documented API. Setup, build instructions and the complete runnable examples remain in the source repository.
#include "rootcastle/npc.hpp"
using namespace rootcastle::npc;
World world;
Config civilian;
civilian.id = 1001;
civilian.personality.courage = 0.1f;
civilian.personality.aggression = 0.1f;
world.add(civilian, {{0, 0, 0}, {1, 0, 0}, 1});
world.submit(1001, {1, StimulusKind::HostileSight, 900,
{4, 0, 0}, 1.0f});
world.tick(1.0f / 60.0f);
// Consume world.changes() and translate decisions through the host adapter.Make temporal behavior testable
Memory expiry, event ordering and decision hysteresis all affect an actor's behavior. Use a fixed timestep and a versioned event sequence when constructing a replay test. Assert meaningful properties, such as whether a decision changes after a threat appears or whether an expired observation stops affecting a decision.
Hysteresis helps avoid switching intents on every small score change, but it can also delay a necessary transition. Test threshold crossings and recovery paths. A stable actor identifier and a recorded sequence number make it possible to compare decision streams between revisions.
Deterministic replay should be scoped to the supported build, platform and floating-point environment. The current public SDK does not promise cross-architecture network lockstep. A local repeatability test is useful evidence without being a universal determinism guarantee.
Keep task hooks bounded
A task hook can validate, rewrite or reject a symbolic task before it reaches the host. It should have a clear execution bound and avoid silently mutating the runtime's ownership model. Prefer explicit return values and narrow command data to an unrestricted callback that can change any world state.
The host still owns navigation, collision, animation, weapon logic and other side effects. Test those adapters separately with invalid targets, missing navigation results and actor removal. A correct behavior decision can still fail at the integration boundary.
Build an evidence set rather than a showcase claim
Start with the supplied console and adapter demonstrations. Preserve the build configuration and an input-event corpus, then compare the resulting task stream after a change. Include events at boundary times and repeated observations. Avoid interpreting one visually plausible scene as proof that an entire engine integration is complete.
Practical checklist and source
- Does each input have an explicit owner and time interpretation?
- Are observations validated by the host before they reach the runtime?
- Is every decision consumed at the intended timestep?
- Are hysteresis, expiry and transition boundaries tested?
- Do host adapters validate targets and own all physical side effects?
Inspect the public C++20 repository and build instructions, including its console examples, task bridge and C ABI notes. For an integration discussion, contact Rootcastle with the host-engine boundary and the behavior you need to reproduce.
Explore Rootcastle engineering tools → · Public profiles and publications


