Merge owned systems into one addon while preserving resource identities. Gate player admission on the replicated prison scene, restore the original framed door, and hold enemy AI until escape. Correct scenario branding and author metadata, include publishing assets, and retain regression and native verification evidence.
5.2 KiB
T8 — HQ memory: belief, not a 2-minute cache
Read docs/living-island/README.md first, including the rules section.
This task is in the ai addon. Depends on T5.
The problem
ERR_HQ.Tick() deletes every contact older than ERR_MissionRules.ContactFresh
(120 s), and m_Contacts is a flat array capped at 64. After two quiet minutes
HQ knows nothing. There is no record that a break happened, no last known
heading, no memory of which ground has already been searched. Velocity
extrapolation between two reports under 30 s apart is the only inference in the
system.
A commander's main asset is an accumulated picture. HQ currently has a sliding window. Everything that makes the enemy feel like a thinking opponent — sweeping outward from a last sighting, cutting off a route, giving up on cleared ground — is impossible without this task.
What to build
addons/ai/Scripts/Game/ERR/ERR_HQBelief.c, with the usual split: a pure rule
class and the service that applies it.
class ERR_HQBeliefRules
{
static float Confidence(float ageSeconds, float halfLife); // decays, never deletes
static float Radius(float ageSeconds, float growthPerSecond, float floor);
static bool Supersedes(float newConfidence, float oldConfidence, float distance);
static bool Actionable(float confidence, float radius); // worth tasking against
static int SweepCell(...); // next unsearched cell, nearest-first outward
}
class ERR_HQBelief { ... }
Contacts decay, they do not vanish
Replace deletion with decay. A belief holds position, observation time, confidence, an estimated heading, and the report that produced it.
- Confidence falls on a half-life (
beliefHalfLifeSeconds, default 600). - Uncertainty grows into a radius. A contact 4 minutes old is not a point —
it is a circle the target could have reached, expanding at
beliefRadiusGrowth(default 1.2 m/s, roughly walking pace, faster if the last sighting was in a vehicle). This single value is what lets HQ search an area instead of chasing a stale pixel. - Beliefs become useless by growing wide and faint, not by being deleted. Retire one only when its radius exceeds a cap (default 2000 m) or a newer belief supersedes it.
- Cap at 64 beliefs; merge rather than duplicate when a new report lands inside an existing belief's radius.
Searched ground
A coarse coverage grid, 500 m cells, each holding "last swept at" and "swept by".
A unit that completes a search waypoint marks its cells. HQ uses this to sweep
outward from a last sighting instead of re-walking ground it already cleared.
Cells decay back to unswept over coverageDecaySeconds (default 900) — ground
cleared twenty minutes ago is not cleared now.
Objective threat
Per objective, a standing threat score from nearby beliefs plus route inference: escapists need a radio and then a helicopter, so the radio station and the helipad carry standing weight even with no contacts at all. This is the plot of the mission, and HQ is allowed to know its own doctrine — it is not allowed to know where the players are.
The fairness rule, enforced in code
Belief is fed only by reports delivered through the radio network. Never by
player positions, never by a dormant record, never by a direct world query.
Write the ingest path so there is exactly one entry point and it takes a
delivered ERR_HQReport. If a report never arrives because its carrier was
killed, HQ never learns it — that is the whole design.
Wiring
ERR_HQowns the belief service and feeds it fromAccept().Assign()(T5) tasks against beliefs rather than raw contacts.- The journal writes belief changes at a coarse level: new belief, superseded, retired, area swept. Not every decay tick.
Acceptance criteria
- Ten minutes after the last sighting, HQ still knows roughly where to look and its search area has grown accordingly — it does not behave as though nothing ever happened.
- A unit that sweeps an area marks it; the next search order goes to adjacent unswept ground, not the same cells.
- With no contacts at all, the radio station and helipad still carry threat and still attract garrisons.
- Killing the reporting unit's radio operator prevents the belief from ever forming — verified, not assumed.
- Belief count stays capped and merges correctly under a burst of reports.
python3 tools/check.pypasses.
Tests to write
tests/test_hq_belief.py:
Confidencehalves over the configured half-life and never returns negative.Radiusat t=0 equals the floor and grows linearly; a vehicle sighting grows faster.Supersedesprefers a fresh nearby report over a stale wide one, and refuses to replace a high-confidence belief with a distant low-confidence one.SweepCellreturns nearest-first outward and never returns a cell swept within the decay window.Actionablerefuses a belief whose radius has outgrown the cap.
Do not
- Do not delete beliefs on a timer. Decay is the mechanism.
- Do not let anything except a delivered report write into belief.
- Do not run belief decay per frame; recompute confidence and radius on read from the stored timestamp. There is no decay tick at all.