GAI
Gumpian AI: a heritable genome of tendencies, a utility layer that picks an intent, and a behaviour tree that executes it. Signals give it duration, squads share intent, and evolution breeds the next generation.
Abstract
GAI — Gumpian AI — is a hybrid architecture for game agents. A heritable genome of continuous tendencies scores the actions available to an agent; a softmax selects an intent; a deterministic behaviour tree executes it. Leaky-integrator signals give the agent perceptual inertia, a gene-derived decision cadence gives it temporal commitment, a squad layer broadcasts a leader’s intent as a bias rather than a command, and a gene pool breeds the next generation from measured outcomes. The design is engine-agnostic: a dependency-free JavaScript runtime and a mirrored C# port.
The authoring problem
Two approaches dominate game agent design, and both encode behaviour directly.
Behaviour trees are explicit and legible. They are also fragile: a graph that reads well at ten nodes becomes unmaintainable at a thousand, and every new game context requires a new graph. Utility systems are more flexible, but they accumulate into archives of hand-tuned behaviours that are difficult to audit and harder to transfer. In both cases the expensive artifact is not the first behaviour. It is the thousandth, and the cost of changing any of them without breaking the rest.
Neither approach separates what an agent can do from how it decides to do it. That separation is the premise of GAI.
The four layers
GAI is not a toolkit of independent techniques. It is a single decision loop with four layers, and each layer exists because the others need it.
Genome. A vector of named tendencies in [0, 1]. Not stats, not roles. The core set has eleven genes; a game may append its own. The genome is data, not a class: it serialises to JSON, hashes to a stable seed, and can be averaged, compared, and bred without touching the runtime.
Utility. Scores every available action by a gene term, a sensed demand, a local smell, a personal circumstance term, and an optional bias. The score vector is multi-channel — one score per action, not a single scalar preference — and a softmax turns it into a sampled intent.
Behaviour tree. Executes the chosen intent. One tree per action. The tree sequences, gates, waits, and cools down; it never re-scores the action set. Sequences and selectors remember which child was running and resume there, which is what makes a move-then-wait sequence actually wait.
Signals. Leaky integrators with gene-derived time constants. A mood builds and fades. The same stimulus produces a different duration of thought in different agents.
Two optional layers sit above them. A squad shares one intent across agents. A gene pool breeds the next generation from measured outcomes.
leadership gene sets the order; teamwork decides how hard it pulls. The berserker has low teamwork and will chase a contact instead of holding the objective. Open full screen.The five invariants
- Genes are tendencies, not roles. A gene biases a choice. It never assigns a class.
- Utility picks the intent; the tree executes it. The utility layer answers “what should I be doing?”. The tree answers “how do I do it?”.
- The pick is a softmax, not an argmax. Temperature is the diversity knob.
- Signals are leaky integrators. A mood should build and fade. The time constant is gene-derived.
- A genome is deterministic. The same genome and seed produce the same brain.
A port that breaks one will still compile, and it will still feel wrong.
The scoring core
For an action with gene g, the score is:
score = (0.05 + 2.2 × g) × pull × personal × bias
pull = 0.5 + 0.55 × order + 0.4 × smell + 0.2 × demandorder is the squad bias, non-zero only for the action the leader chose; smell is a local sensed pressure; demand is a squad- or colony-level pressure. All three are clamped to [0, 1]. A gate that returns false sets the score to zero exactly.
The gene term is deliberately wide. With a plain g × pull, the gene is a [0, 1] multiplier on a [0, 2] pull, and the softmax washes the difference out. The 0.05..2.25 expansion makes the genome the dominant term, which is the point of a genetic agent.
The softmax is:
P(i) = exp(score_i / T) / Σ exp(score_j / T)The working temperature is 0.10 – 0.18. Below 0.08 the population becomes a monoculture; above 0.30 the genes stop predicting behaviour.
Commitment and stability
A common critique of continuous utility systems is that they chatter: if two actions have nearly equal scores, the agent can alternate between them on consecutive frames. GAI is not a single-neuron preference that is thresholded into a verb. The utility layer is multi-channel: one score per action, and the softmax turns the whole vector into a distribution over verbs. There is no single neuron whose sign flips.
Multi-channel output removes the single-neuron failure mode, but it does not by itself remove the temporal one. The architecture therefore pairs the score vector with a commitment policy:
- Decision cadence. The utility layer re-scores on a gene-derived interval,
Δd = 0.08 + (1 − patience) × 0.18. Between decisions, the current intent and its tree are held. The maximum switch rate is1 / Δd, between 3.8 and 12.5 switches per second in the working range. - Perceptual inertia. Signals add hysteresis on the input side. An agent that has been under fire for three seconds has a high threat signal even if the current frame is quiet.
- Execution commitment. The tree is reset only when the chosen action changes. While the action is stable, the tree’s running index, cooldowns, and waits persist.
- Rate limiting. A
Cooldownnode fails while hot, so a selector moves on. AWaitnode returnsrunninguntil its time elapses.
When the score surface is noisy, a game can add an explicit interrupt threshold and minimum dwell. The reference implementation relies on the multi-channel vector, the cadence, the signals, the tree state, and the cooldowns; the threshold policy is a temporal refinement for games whose score noise is larger than the gap between the top two channels.
The squad layer
A squad is a shared intent, not a second brain. The living agent with the highest leadership gene thinks first and sets the intent. Every other agent receives that intent as ctx.order, which is the strongest single bias in the utility function. Teamwork decides how hard the order pulls:
orderStrength = 0.35 + 0.65 × teamworkThe order is a bias, never a leash. A high-curiosity grunt may still peel off to check a corridor, and that is the point: the squad has a plan, and the individuals have tendencies. If a designer wants a leash, the action can be gated on ctx.order, but that should be a deliberate choice, because a squad that cannot disagree is a squad that cannot discover.
The general model also admits a decentralised variant: every agent projects a scalar state into a local register, peers ingest the broadcast as a sensor input, and leadership emerges from the field rather than from a named leader. It is attractive for dense swarms because it has no leader-election step and no single point of failure; it is harder to inspect. The reference implementation chooses the soft hierarchy because it is cheaper, deterministic, and easy to debug.
Evolution
Fitness is a weighted sum of measured outcomes, floored at zero:
F = max(0, Σ w_k × stat_k)Negative weights are allowed and are how a designer punishes friendly fire, team killing, or camping. The weights are the most important design document in the evolution layer: a population will optimise exactly what they measure, including the parts the designer did not intend.
Breeding keeps the single best genome unchanged, culls the bottom share, and fills the next generation by crossing a survivor with a donor drawn from the top alphas. Each gene is blended independently, so a child can inherit its mother’s patience and its father’s aggression. A per-gene mutation chance then nudges a fraction of the genes by a bounded step. Horizontal transfer from an enemy alpha is optional and off by default, because it is the fastest way to collapse two factions into one.
Determinism
A genome hashes to a seed, and the seed drives every random draw the agent makes. The hash is FNV-1a over the gene ids and the gene values rounded to four decimal places. The PRNG is Mulberry32. The same genome and seed produce the same brain, the same tie-breaks, and the same “occasional second-best” choices.
The gene order is part of the contract. Reorder the spec list and every lineage gets a new brain. That is why the spec list is versioned and why a saved genome from an older build is migrated rather than merged.
Implementation
The reference runtime is one dependency-free ES module, src/gump.js. It runs in a browser, in Node, and as the reference for the C# port. It exports the maths helpers, the deterministic PRNG, the gene and signal specs, the genome operations, the signal bank, the utility brain, the behaviour-tree nodes, the agent, the squad, the gene pool, and the presets.
The Unity port mirrors the JavaScript names in plain C#. The brain is a class, not a MonoBehaviour; a thin GumpAgentBehaviour owns one and ticks it. The context is a struct plus a small action interface, which keeps the per-tick allocation down and the engine at arm’s length. A GumpTuning ScriptableObject holds the knobs, and a HaloSquadDirector owns the squad.
The package ships with five runnable examples, four documentation guides, a single-file agent skill, and a verification harness: 58 behaviour checks against the reference runtime, a DOM harness that drives every example, a local link checker, and a headless C# type-check against minimal UnityEngine stubs.
What GAI is not
It is not a trained black box. The genome is a low-dimensional vector of tendencies, evolved rather than trained, and small enough to inspect.
It is not a language-model wrapper, and it does not call out to a service at runtime. It is not a game engine, a renderer, or an entity store. It does not own the game loop. It is not a behaviour-tree editor, and it does not require one.
It does not plan. It selects among a known, authored action set. That is a deliberate restriction: the architecture targets the common case where the interesting question is not “which sequence of primitives reaches this goal?” but “which of these six things should I be doing, given who I am and what I can sense?”.
Evidence and limits
The current evidence is a working reference implementation, a mirrored C# port, five runnable examples, and a verification harness. The scoring formula, the softmax distribution, the signal integrator, the decision cadence, the squad bias, and the breeding operators are covered by the reference smoke test. The examples are driven by a DOM harness that asserts the behaviour each page advertises. The C# runtime and the Halo example type-check against minimal Unity stubs. Every local link resolves. The same genome and context sequence produce the same decisions.
What is not verified: there is no formal benchmark of the core at swarm scale, no head-to-head comparison against commercial middleware on a shared task, no user study of authoring effort, and no long-horizon study of evolution across many generations and varied tasks. The architecture was distilled from three projects by the same author, which is an implementation bias. The examples are synthetic and small. The tuning ranges are empirical, not derived. The comparison table in the technical report is structural, not statistical.
A reader should treat the report as a design argument with a working reference implementation, not as an empirical result.
Purpose
GAI is a substrate, not a genre. The same architecture is meant to serve a single boss, a squad of soldiers, and a colony of ants without changing the decision model, only the verbs, the sensors, and the fitness pressure. Flexibility is the design goal; the layers are how it is achieved.