Autopilot · write-up
Level 2 life-loss analysis — October 2, 2026
The two deaths are separate failures. The three-eye transfer forces a route through a predicted worm collision. After Shop 1, ordinary formation holding and the limited escape search leave the ship pinned against the right wall. Both fatal control sequences are also produced by the exact September 23 C sources when given these observations. Later shared combat changes alter the earlier approach, but that does not make either fatal sequence a newly added September 29 boss tactic.
The sections below first describe the original r150 decisions. The local C
repairs and new live validation are recorded at the end of this document.
The corridor-retreat and boss-scope changes are included with the local C
repairs on xenone2-l2.
The Cannon model remains unchanged, as requested by the user.
Recordings and method
| Alias | Recording | Death |
|---|---|---|
| A | E:/xenon_runs/level2-full-lip-retreat-20261002-r150.validation/level2-full-lip-retreat-20261002-r150.x2events |
Three-eye encounter: damage at 10440, 10445, 10449; life lost at 10466. |
| B | E:/xenon_runs/level2-full-lip-retreat-20261002-r150-part2.validation/level2-full-lip-retreat-20261002-r150-part2.x2events |
Ordinary swarm after Shop 1: damage at 13711, 13716, 13719, 13723, 13727; life lost at 13744. |
The live runs used resident C control, visible Release Hatari, both AVIs and
validate_campaign.py native-run. B continues the same emulator after A's
death, restarting its C session from captured RAM. It is not an independent
fresh campaign. The live trace is:
E:/xenon_runs/level2-full-lip-retreat-20261002-r150.trace
For comparison, commit 5c6944a1 (September 23, 18:25) was exported to
work/l2-source-comparison/september23-exact. Its complete native kernel was
compiled with a copy of the official xenon_tools/hatari_dev.ps1 build-kernel
script. The archived Python ctypes declarations came from that same commit.
Python only decodes the recordings and invokes the C session; it does not
choose controls. The production DLL was not replaced by the historical DLL.
work/compare_native_history.py initializes each C session with the
recording's start.ram, advances all preceding observations, and explicitly
exports controls, primary candidate diagnostics and mission state.
Death A: an unsafe transfer overrides collision avoidance
The ship enters this sequence with shield 23. Four earlier directional hits (8904, 8912, 8956 and 9847) already removed 16 shield points. Those earlier problems matter, but restoring that shield would not make the transfer safe.
| Frame | State and decision |
|---|---|
| 10435 | clear_right_worm(4), targeting leader #23275. Player is approximately (101,2704). Live followers remain left of the firing column. |
| 10436 | Leader destruction changes the phase to dash_right_refuge(5), transfer stage LAUNCH(1). Destination is (304,2560), but the next span waypoint is (40,2672), followed by (28,2592): the initial leg goes up-left. |
| 10436 | Primary C evaluation returns verified=0, body-contact reason 6 at candidate frame 27, with an initial Down prefix. The driver replaces it with the route proposal, Up-Left. That prefix is not a fully verified escape, but it is different from the applied route. |
| 10437–10440 | C evaluation now predicts body contact one frame ahead. The driver still applies Up-Left and clears the hazard escape state. |
| 10440 | Segment #23588 deals 8 damage: shield 23 → 15. |
| 10445 | Segment #23582 deals 8 damage: 15 → 7. |
| 10449 | Segment #23585 exhausts the remaining 7 shield points. |
| 10466 | Life lost. |
These are actual emulator collision events, not an overlap inferred from a
Python visualization. Before the leader dies, C's formation grouping links
all three damaging segments to the incoming right-origin leader #23275.
For example, at 10435 #23588 is at screen (88,135) and #23582 at (55,166).
Destroying the leader has not destroyed these followers. The later
collision events independently prove that they remain harmful.
The implementation deliberately bypasses the complete worm-path check when launching this transfer:
level2_eye_start_right_refuge_routeinsrc/autopilot/xenon_autopilot_level2.cacceptsrequire_worm_clearance. The dash calls it with 0.- Its justification assumes the remaining right-origin tail lies ahead in the forward firing lane and will be destroyed. That is not true for the selected up-left map connector.
level2_right_refuge_dashinsrc/autopilot/xenon_autopilot_driver.crestores the mission movement after evaluation/escape selection. It does not requireverifiedand clears the selected escape state.- The launch checks for a fresh left-origin leader, but that condition does not establish that this particular connector is clear of the surviving right-origin tail.
This is primarily an arbitration/route-assumption failure. Prediction sees
the imminent body contact; the phase-specific override disregards it.
The override originated in 5e4944b9 on September 21. The retained span route,
leader-entry check and firing-lane justification were refined in ad49669c
on September 22. They predate the requested September 23 boundary.
The local repair should make the launch geometry and destruction assumption
agree: select an appropriate launch column and validate the actual first
route leg against surviving followers, using the existing combat evaluation
for kills. Only a checked launch may own movement. An imminent body contact
must not be overwritten simply because the state is DASH_RIGHT_REFUGE.
Adding an arbitrary delay or enabling full-route rejection unconditionally
would risk recreating the old missed-transfer-window stall.
Death B: the post-shop holding point becomes a swarm trap
This is not the spider or the three-eye encounter. During this sequence
boss_active=0, wave_active=0 and gate=-1; the controller is using ordinary
corridor/formation logic, not the homing-gate state machine.
| Frame | State and decision |
|---|---|
| 13600 | FORMATION_HOLD, near X=170. The preferred band is screen Y=120–136. C already cannot verify the complete plan because of an anticipated aimed shot. |
| 13638 | Directional projectile #33439 deals 4 damage, 39 → 35. The selected movement is Up-Right. |
| 13650 | Movement remains Right despite the navigation goal near X=168. This is evaluator avoidance movement, not a deliberate new boss target. |
| 13680 | Player is (253,2363), screen Y≈166. Formation holding freezes the preferred X at [249,257]. The primary plan predicts body contact in 29 frames, but selects a stationary prefix. |
| 13700 | Player has reached X=284. Holding now prefers [280,288]. Predicted body contact is four frames away; movement remains neutral. |
| 13703–13709 | C selects Up, including consumed Up at 13708, toward the approaching train. The evaluated fallback is unsafe; its body-contact diagnostic is not a verified escape. |
| 13710 | Body contact is predicted one frame ahead. |
| 13711–13727 | Followers #33645–#33649 repeatedly hit the ship at X=284, reducing shield 35 → 0. |
| 13744 | Life lost. |
xap_mission_formation_hold scans formation forecasts for a member within
48 pixels of the player over the next 24 frames. It then chooses the
current X ±4 and screen Y=120–136. It does not select a safe holding
region outside the approaching train. Repeating this near the right wall
turns the avoidance displacement into the next preferred holding point.
This shared function dates to 6a79e11c, September 13; the Level 2 use and
escape-region guard date to 7df0f563, September 19.
The additional xap_level2_hazard_escape pass is inactive here. Its ordinary
regions cover world Y=3360–4208, 3100–3360, 2500–3100, 1088–1200 and 376–960,
plus the active spider encounter. The post-shop trap around Y=2300 is outside
all of them. It clears the retained escape and returns. The newer planner
search for escapes with several turns is enabled only for its authored
Level 5 corridor, so it also does not repair this Level 2 trap.
A native geometry/camera probe at 13680 establishes that all cardinal one-step moves are terrain-clear. Sixteen Down inputs are terrain-clear too, moving world Y=2363 → 2383 and scroll 2196 → 2208. The initial backward limit is 2212. There is room to retreat; terrain and exhausted backscroll do not force this hold. This is a terrain proof, not a claim that those Down inputs alone avoid every projectile/body.
The local repair should preserve an escape lane before the swarm reaches the right wall: retreat into the available lower space, let the train pass or destroy it from below, and return to the backbone when clear. It needs a checked sequence of movements rather than anchoring every new hold at the latest displaced X. Changes should be confined to this post-shop section; spider tactics do not need to be replaced.
What changed since September 23?
| Change | Level 2 relevance |
|---|---|
5b5b5873, September 23 |
Changed retention of a still-live hazard to require a boss commitment. This also affected ordinary corridor avoidance. |
5c6944a1, September 23 |
Discarded neutral escape retention. Also affected ordinary corridors. Both retention changes are now restricted to active boss encounters in the October 2 repairs. |
0c93605e, September 24 |
Added spider front-attack/cash tactics. These do not apply to either death location. |
e693fefa, September 29 |
Added future Cannon rounds and broader installed-weapon/source attack choices to shared evaluation. These changes affect Level 2, despite the commit's Level 4/5 focus. |
4a03e159, October 1 |
Extended shared future-fire scheduling from 32 frames to the configured horizon. This also affects Level 2. Its multi-turn escape and sprite-hull options remain locally enabled for Level 5. |
| October 2 repairs | Restored ordinary-region retention and preserved the map connector's retreat at the early row-259 lip. Neither new rule applies at the two death positions. |
The future Cannon schedule is known to be too optimistic: it allocates a future round at each two-frame forward intent pulse rather than the attachment's actual four/five-frame firing cadence. Detailed evidence and the user's decision to defer that repair are in FULL_NATIVE_CAMPAIGN_20261001.MD.
There are measurable upstream changes in recording A. Against the exact September 23 kernel, current C differs on 98 of 2548 observations through 10460. The first difference is 8465, before the local lip repair applies: the mission goal is identical, but current C holds and old C moves Up-Right. An isolated diagnostic build omitting only newly forecast Cannon rounds restores that first choice. Restoring only the old fire horizon or old attack selection does not. This confirms a post-September-23 cause of changed early decisions; it does not prove that removing Cannon forecasting fixes the campaign or accounts for all 98 differences.
At the deaths, however, the comparisons give:
| Captured observations | Current versus exact September 23 final controls |
|---|---|
| A, 10320–10460, 141 observations | 0 differences, including the unsafe dash and all three shield hits. |
| B, 10478–13750, 3272 observations | 0 differences, including both shop phases, approach, right-wall hold and death. |
| B, 13415–13750, 336-observation focused window | 0 differences. |
The separately archived September 22 r18 C build also gives identical
controls in both focused death windows. Its captured source differs from
the later end-of-day ad49669c commit, so the exact September 23 build is
used for the primary comparison above.
The recomputed current controls match the following recorded consumed input on all 14 observations at 10436–10449, all 296 at 13415–13710, and all 17 at 13711–13727. This checks that the relevant diagnostics describe the actual resident C movement, rather than a different Python planner.
Assessment: both fatal rules are older defects. The new shared combat changes demonstrably alter the earlier approach and can alter shield level and worm timing when the first defect is reached. Fixed-history replay cannot establish whether an old build would reach the same situation in a complete live run: it does not feed its alternative controls back into the emulator. An earlier-start live A/B trial is necessary for that stronger causal claim. The evidence does not support blaming either death directly on a newly added spider tactic, an invisible worm, or the local lip retreat.
Saved diagnostic evidence
work/l2-source-comparison/r150-death-current.jsonwork/l2-source-comparison/r150-death-september23.jsonwork/l2-source-comparison/r150-part2-death-current.jsonwork/l2-source-comparison/r150-part2-death-september23.jsonwork/l2-source-comparison/r150-full-predeath-current.jsonwork/l2-source-comparison/r150-full-predeath-september23.jsonwork/l2-source-comparison/r150-part2-full-predeath-current.jsonwork/l2-source-comparison/r150-part2-full-predeath-september23.jsonwork/l2-source-comparison/r150-september23-comparison-summary.jsonwork/l2-source-comparison/r150-death-population.jsonwork/l2-source-comparison/r150-postshop-geometry-13680.jsonwork/l2-source-comparison/r150-early-head-no-cannon-rounds.jsonwork/l2-source-comparison/r150-early-head-old-fire.jsonwork/l2-source-comparison/r150-early-head-old-attacks.json
Example reproduction of the focused historical comparison, from the repo root:
python work/compare_native_history.py E:/xenon_runs/level2-full-lip-retreat-20261002-r150.validation/level2-full-lip-retreat-20261002-r150.x2events D:/src/hatari/work/l2-source-comparison/september23-exact/out/build/autopilot-native/libxenon_autopilot.dll work/l2-source-comparison/r150-death-september23.json --bridge D:/src/hatari/work/l2-source-comparison/september23-exact/xenon_tools --first 10320 --last 10460
Local C repairs and checkpoint validation
The three-eye launch now uses the worm's captured hole selector at object
offset $30, written by Level2_SpawnWormFormation at $50330 in the
Level 2 ReVa program /level2-live/mydumpat0. Values 0 and 1 identify
the left and right trains; unrelated minions use -1 in the decoded view.
Classification remains an enum. The native ABI is 99 and the ctypes mirror
has been updated solely for replay observation and tests.
Destroying a leader does not retire its followers. The spawn scheduler at
$50218 tests per-origin bytes $DA3/$DA4, reset by the boss controller and
set by each scripted member at $508D0. It allocates a replacement train
when no scripted member still marks that origin. The bit cleared by the
leader's hit procedure at $50004 is not this spawn gate. A member with
script timer $8000 is a detached straight-moving fragment: it retains
$30 but no longer marks the train active. The decoder excludes those
fragments from origin-based encounter phases, while retaining their bodies
as hazards.
After the incoming right leader is destroyed, keep firing from X=100..108 until a left-origin train is actually departing below its hole (X<80, screen Y>=120) and no member is still waiting inside with a negative script delay. Check the next eight frames of the map route with 6px body clearance before launching. This is a forecast horizon, not a waiting timer. The driver repeats that route check before allowing mission steering to override an escape. A destroyed leader alone cannot trigger an unchecked dash.
The transfer targets the upper-right corner at screen Y=16. A native wall probe confirms the full crossing row X=36..304 is free. In r166 the old Y=32 crossing met a right-origin train at 10596/10597; its movement forecast matched subsequent captured positions. Raising the crossing passes above this turn. This change applies to this transfer and its right refuge; other encounter anchors retain their existing geometry. The climb has a half-step horizontal tolerance to avoid oscillating around an unreachable exact X coordinate.
Local escape forecasts previously checked terrain only on their first step, then scored impossible movement through walls. The three-eye and post-shop forecasts now stop blocked axes, preserving movement along a clear axis. The ship trajectory is prepared once per body/shot cost query instead of once for every enemy. Raw nearest-body steering no longer bypasses these forecasts when the native scripted predictor is available.
The post-shop repair is restricted to Level 2 world Y=2160..2496. Formation holding uses the open central lane X=160..176 and reaction band screen Y=144..164, rather than retaining the X reached by a lateral escape. This section now receives the combined projectile/body escape search. The driver's ordinary corridor guard also restores that central lane before hazard arbitration: without it, the generic planner's Left prefix could keep moving past its route goal toward the left emitter even while the immediate Left step looked clear. Hazard avoidance still has the final choice. Down at the bottom remains available when captured camera limits permit backscroll; it is no longer silently converted to Up into the swarm. Spider tactics and the deferred Cannon model are unchanged.
Validation iterations
Every live run uses validate_campaign.py native-run, resident C input,
visible Release Hatari, fast-forward, both AVIs, Level 2 tracing and retained
checkpoints. Both Hatari and the replay DLL are rebuilt with
xenon_tools/hatari_dev.ps1 after C changes.
E:/xenon_runs/level2-bridge-hold-20261002-r155.validation/level2-bridge-hold-20261002-r155.x2eventsdefeated all three eyes and reached the shop with shield 23 -> 23 and three lives. Both AVI indexes are contiguous and first/last frames decode. This single pass was insufficient to establish checkpoint robustness.E:/xenon_runs/level2-departure-checkpoints-20261002-r156.mdreports 1/5 passed before the live-head and protected-climb corrections. Checkpoints 9990, 10015, 10038, 10059 and 10081 were replayed independently. The failures exposed replacement spawns while only old tails survived, diagonal map crossings that bypassed the protected left pocket, and a cached-route clearance bypass. An additional approach hit occurred at 10036 in the 10015 continuation.- r157..r164 were failed experiments, not validated fixes. Requiring a surviving head or a complete early climb/crossing forecast either missed useful departure windows or held until a later train reached the ship. Those experiments have been removed from the final implementation.
E:/xenon_runs/level2-upper-crossing-20261002-r168-f10038.validation/level2-upper-crossing-20261002-r168-f10038.x2eventspasses from the formerly failing 10038 checkpoint: all three eyes destroyed at 11134, shop at 11192, shield 23 -> 23.- Five-checkpoint repeat:
E:/xenon_runs/level2-upper-crossing-20261002-r169.md: 5/5 passed, shield 23 -> 23, three lives, all eyes destroyed and shop reached. Starts 9990, 10015, 10038, 10059 (restored game frame 10060) and 10081. E:/xenon_runs/level2-postshop-wall-aware-20261002-r167.validation/level2-postshop-wall-aware-20261002-r167.x2eventsremoves the fatal swarm-body collision/life loss in the requested passage, but takes projectile hits at 13626/13633. A later 16-point body hit at 14450 is outside the local repair's world-Y bounds. Further focused post-shop validation is required before claiming this section damage-free.- r165 ended with a lost control connection after 17 captured frames; its AVIs were not finalized. It is not a valid gameplay verdict. The identical build replayed the captured history successfully in the DLL and completed the subsequent r166 live run, so a reproducible runtime failure was not established.
- The completed local validation and exact recording links are in LEVEL2_R150_FIX_VALIDATION_20261002.MD. Post-shop starts 13421 and 13572 clear the requested passage without damage. The earlier 13039 continuation finishes the spider and enters Level 3 with shield 39 -> 39 and no lost lives. The 13421 continuation's later 16-point hit at 13996 is outside the local bounds and is retained as an unresolved incident, rather than being hidden by a scoped verdict.
The focused C tests cover raw origin decoding, a surviving incoming tail,
a blocked bridge retaining zero movement, and post-shop reaction/lane
recovery and the last delayed left-origin tail; the native driver and
session suites are also run. Twenty-seven
targeted tests pass. Validation completed before the user-requested commit
on xenone2-l2.