Files
jakub cab998fb64 Combine Workshop addon and fix prison startup
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.
2026-09-20 16:42:52 +02:00

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_HQ owns the belief service and feeds it from Accept().
  • 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

  1. 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.
  2. A unit that sweeps an area marks it; the next search order goes to adjacent unswept ground, not the same cells.
  3. With no contacts at all, the radio station and helipad still carry threat and still attract garrisons.
  4. Killing the reporting unit's radio operator prevents the belief from ever forming — verified, not assumed.
  5. Belief count stays capped and merges correctly under a burst of reports.
  6. python3 tools/check.py passes.

Tests to write

tests/test_hq_belief.py:

  • Confidence halves over the configured half-life and never returns negative.
  • Radius at t=0 equals the floor and grows linearly; a vehicle sighting grows faster.
  • Supersedes prefers a fresh nearby report over a stale wide one, and refuses to replace a high-confidence belief with a distant low-confidence one.
  • SweepCell returns nearest-first outward and never returns a cell swept within the decay window.
  • Actionable refuses 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.