# Escort / mission state from guest RAM — every entity's hull **Status:** ✅ CONFIRMED (2026-07-30). Capture: `tools/re-capture/mission_state.py`, session `tools/re-capture/escort_session.sh`, Stage 02 from save slot 01, 240 s of flight, 240 samples at 1 Hz → [`captures/mission-state-stage02.jsonl`](captures/mission-state-stage02.jsonl). Screenshot evidence: [`captures/escort-stage02-hud.png`](captures/escort-stage02-hud.png). ## The question `own_state.py` found the **player's** hull by anchoring on a solved definition field — an undamaged craft carries its definition's `HP` (+0x054), so the live counter is the copy of that number that falls. Result: `hull = position + 0x154` ([autopilot](autopilot-memory-driven.md)). Stage 02 is an **escort**, and it is lost when the ACROPOLIS sinks, not when the player dies: a 240 s run hit `GAME OVER` with our own hull at 1500/1500. Scoring that objective needs *someone else's* hull. So: is `+0x154` a property of the **entity class**, or of the player object? ## Finding — it is class-wide At the first sample of the run, before this session's fighting had touched them, `pos+0x154` equals the entity's own definition `HP` across **seven classes and five distinct HP values**: | Class | radius | definition `HP` | `pos+0x154` at t=0 | |---|---|---|---| | `UN_e007_ADAN_Turret` | 22 | 100 | 100.0 (all 60 instances) | | `UN_e010_ADAN_Attacker_S` | 100 | 500 | 500.0 (all 19) | | `UN_f106_TCAF_Destroyer` | 2000 | 10000 | 10000.0 | | `UN_e106_ADAN_Destroyer` | 2100 | 10000 | 10000.0 | | `UN_f105_TCAF_Cruiser` | 3800 | 30000 | 30000.0 | | `UN_e105_ADAN_Cruiser` | 3800 | 30000 | 30000.0 | | **`UN_f101_TCAF_Acropolis`** | 1400 | **25000** | **25000.0** | Of the 18 capital ships present at t=0, 13 sat exactly at their `HP`; the other 5 sat *slightly below* it (9800/10000, 29933.3/30000, 9725/10000, 9950/10000, 9750/10000) — the battle is already in progress when the player launches, so those five had already been shot at. **Nothing read above its `HP`, and nothing read an unrelated number**, which is what a coincidental offset would produce. The value behaves like a live counter, not a copy of the definition: - it **falls under fire** — 780 distinct damage events were logged across the run; - it **goes negative at death** and the entity then disappears from the heap (`UN_f106_TCAF_Destroyer` → `-30.0` of 10000, another → `-0.0`, a third GONE); - the drops match what the HUD draws — the screenshot shows the ACROPOLIS and the destroyer *CHARON* each with their own health bar, CHARON's already red. So **`hull = position + 0x154` for every entity**, and the escort objective is directly scoreable: read the protected ship's hull, normalise by its definition's `HP`, done. No new anchor, no value scan. ## The escort asset, measured `UN_f101_TCAF_Acropolis`, one instance, `HP` 25000, collision radius 1400. Its hull over the 240 s run (pilot chasing the nearest hostile fighter, the current `pilot.py` behaviour): ``` t= 0..150s 25000.0 untouched t= 180.1s 24779.5 t= 210.1s 24149.5 t= 239.1s 23038.2 -1961.8 total, ≈ -600 HP/min once it starts ``` Two useful consequences: 1. **The attack on the asset starts late** (~t≈170 s here) and then runs at roughly 600 HP/min, i.e. ~40 min to sink from full. The earlier `GAME OVER` run therefore did not lose because the loss is fast — it lost because nothing was defending. 2. **The asset is not in danger for the first ~2–3 minutes**, so an escort policy has time to spend on offence early and should tighten later. ## Also captured - Hostile population fell 147 → 118 over the run (the pilot fired on 435 of 1913 engage frames; most of the remainder it was manoeuvring with the target outside the 9° firing cone). - Two friendly destroyers were lost while the pilot was elsewhere. - The HUD's `REMAINING OB` read **012** at t≈240 s while 118 ADAN entities were alive, so that counter is **objectives, not hostiles** — its RAM address is still unknown (❔ open). ## Reimplementation notes - Defeat conditions for an escort stage are readable as: protected-asset `hull ≤ 0`, or player `hull ≤ 0`. - Every unit's effective HP is the definition's `HP`, confirmed live for 7 classes — the same field the [unit struct](structures/unit-struct-runtime.md) already solves statically, so disc data and runtime agree. - Entity removal on death is observable (the object leaves the heap), which gives a clean lifetime signal for anything modelling spawn/despawn.