Xenon 2

Autopilot · write-up

Level 2 offline strategy

xenondoc/LEVEL2_STRATEGY.MD · 20 KB · updated 2026-09-24

Date: 2026-08-24

Level 2 is no longer treated as a sequence of unrelated reactive frames. Its static mission is compiled from the complete resident tile map into assets/xenon_level2_strategy.json. Runtime code selects the current phase and fixed encounter gate from world coordinates. Exact object prediction remains a separate safety service and is invoked only when a concrete moving hazard can invalidate the cached action plan.

Control split

complete Level-2 map + known persistent anchors
                    |
                    v
       offline mission strategy asset
       - full-level route backbone
       - encounter phases
       - boss target order
       - five homing staging gates
                    |
                    v
       stable phase / goal / movement region
                    |
                    v
   live wall validation + short safety revalidation
                    |
          unsafe cached action?
             /             \
           no               yes
           |                 |
    execute cached plan   bounded space-time search

The offline strategy never claims that a stored polyline is safe for the ship's current banked sprite. It supplies the mission and corridor choice. The live configuration-space map validates the current collision hull and connects the ship back to that mission after an avoidance detour.

Fixed phases

All phase boundaries use world Y. Screen coordinates are used only for the desired reaction band; camera motion cannot change the selected phase.

Phase Player world Y Policy
Entry corridors 5000..3100 Stay in the lower-middle reaction band, follow the full-map backbone, destroy wall shooters and formations before allowing ordinary forward progress.
Three-eye boss 3100..2500 Route to the left upper eye, the right upper eye, then the lower main eye. Enter the left-side junction before approaching the first eye, so the first worm train remains on the opposite side. A missing eye is already complete and is skipped. Generic combat does not replace the eye route.
Post-shop crossfire 2500..1900 Prioritize wall shooters, serialize scroll-triggered waves with bounded backscroll, and never select a pacing destination outside the backbone corridor.
Homing gauntlet 1900..1400 Prepare at one known emitter gate, stop activating further encounters while its ring exists, then release the next gate.
Lower labyrinth 1400..376 Follow the fixed right-to-left backbone and commit to its left corridor. The route intentionally reaches the right side around world Y 1300 before crossing left near world Y 1110; a visually nearer cul-de-sac is not a new mission. Nearby sine swarms move the ship into its lower reaction lane instead of interrupting the route with a premature upward escape.
Final arena below 376 Latch the left-corridor entry and activate the spider from the upper-left. Descend to world Y 385, cross below the rebuilding web, and aim the route at X 192 so the forward cannon and missiles hit the head. Wait for a downward centre-lane shot before crossing it. At the firing station, press DOWN near the bottom edge to backscroll and increase projectile dodge space. Keep firing through the web during the post-kill cash sweep.

The native C run xenon_tools/run_logs/l2-spider-front-lower-20260924-r3.validation/l2-spider-front-lower-20260924-r3.x2events started from the pre-spider frame-14681 checkpoint and reached the next shop at frame 15344. Shield stayed at 19, the spider died after its health declined from 75 to 2 by frame 15234, and cash grew from 2100 to 3550 before the shop bonus. The camera scroll rose from about 185 to 288 while the ship remained at screen Y 176, confirming that DOWN moved the view backward and opened room below the spider. The post-kill sweep collected 1450 cash. Both AVI views and 150-frame checkpoints are in that validation directory. The route target X 192 produced actual player X near 190 at the firing station; earlier X 172 left the forward weapons outside the head's hit lane.

The earlier-checkpoint repeat xenon_tools/run_logs/l2-spider-front-earlier-20260924-r1.validation/l2-spider-front-earlier-20260924-r1.x2events started at frame 14530, killed the spider at frame 15235, and reached the shop at frame 15343. Shield remained 19 and lives remained 3. It again collected 1450 cash before the shop opened (2100 to 3550); the shop then showed 4450. Both AVI files decode with ffprobe as 640x400 PNG video.

The reusable xenon_tools/validate_level2_boss_checkpoints.py accepts --boss spider or --boss three-eye. Its spider defaults are four dormant checkpoints from l2-first-shop-c-shop-boss-20260923-r9: frames 14230, 14380, 14530, and 14681. The script verifies the source arena timer is negative before accepting a spider checkpoint. All four visible native C continuations in E:/xenon_runs/l2-spider-four-dormant-20260924-r2.md defeated the spider, reached the shop, retained shield 19, and gained 1400–1450 cash before the shop. Both AVIs from each run passed ffprobe. Frame 14831 was excluded even though the spider still had full health: its arena timer was already 340, so the encounter had begun. An earlier dormant frame 14079 included a separate 8-point corridor hit and later stalled; it is retained in E:/xenon_runs/l2-spider-five-preboss-20260924-r2.md as an approach failure, not a spider-fight validation.

An earlier crossing at world Y 365 was rejected: run l2-spider-front-lower-20260924-r2 took a hit at frame 14937 and stalled at X 122 against the rebuilding web. The safe side-shot fallback from l2-spider-side-restored-full-20260923-r1 also reached the shop without damage, but only collected 250 spider cash.

The generated backbone contains 36 smoothed world-space waypoints. It is derived at four-pixel configuration-map resolution with the neutral $6906 ship hull and a twelve-pixel reserve. Its source map SHA-256 is stored in the asset, making a stale strategy detectable when the captured map changes.

Three-eye boss worm lane

The Level 2 C-only capture native-l2-predictive-worm-lane-20260918-r129 starts from a Level 2 checkpoint at frame 11554 with the camera fixed at world Y 2528. Across 906 recorded frames in the follow-up C-only capture native-l2-worm-lower-lane-20260918-r130, Level 2 formation objects with update routine $508D0 and statuses $0114/$0118/$011C occupied screen X 0..319 and screen Y -4..191. This rules out treating either the top or bottom of the screen as a universally safe static lane. The ship's legal vertical limit was about screen Y 192, so the requested screen-Y-220 lower lane was unreachable. In r130 the ship stayed at screen Y 176 and world Y 2713..2716 near the bottom limit, cycling down/neutral inputs without reaching an eye attack station; it took no shield damage during that short capture.

In native-l2-reachable-eye-stage-20260918-r131, the selected eye was already visible at screen (4,164) while the ship was at (199,176). The mission sent the ship into screen Y 152..168 before routing toward the eye's firing station near X=72. At frame 11877, a deterministic formation leader at (221,141) hit the ship; its bounds overlapped the ship hull by one pixel vertically, reducing shield from 39 to 31. The eye remained intact. The extra middle staging route is now skipped for visible eyes; the mission routes directly to their weapon-specific firing station and waits at its current reachable position when a predicted worm path blocks the next leg. Screen Y 168..184 is a staging range, not a universal safety guarantee, so the direct route remains under live validation. Interpret routine addresses from a Level 2 RAM capture: overlay addresses can name different routines on other levels.

The C-only capture native-l2-worm-refuge-split-horizon-20260918-r137 confirmed that the map-derived upper-right pocket can be reached without shield loss, but the ship reversed there during each outbound attempt. R138 tried pausing mid-route; it lost one life to five consecutive worm-segment hits at frames 12479..12483 near screen (88..98, 46..61). That showed the waiting point itself can be inside the worm lane. The current policy waits in the refuge until the complete route to the eye station is predicted clear, then commits to that crossing instead of stopping mid-lane. This full-route timing change still needs a live check. The native mission checkpoint mirror in native_mission.py must match the C Level 2 state layout.

Homing gauntlet

Canonical Level 2 recordings expose five persistent ring-emitter anchors, in forward order:

Gate Emitter (x, worldY) Staging anchor (x, worldY)
1 (32, 1776) (152, 1888)
2 (256, 1728) (160, 1840)
3 (256, 1584) (176, 1696)
4 (32, 1536) (152, 1648)
5 (80, 1456) (160, 1568)

Staging anchors are computed from the full configuration map, not copied from the ship position in one successful recording. Preparation begins up to 192 world pixels before a gate. The controller descends into its lower reaction band, centres on the gate anchor, then releases DOWN so automatic forward scrolling activates that one emitter.

The game is not globally deterministic at encounter allocation. In the live Level 2 overlay, Level2_SpawnController_Update at $50DE6 calls Next_random at $50E74/$50E80 and seeds a spawned direction at $50FC8 with random & 7. This is now annotated in the /level2-live/mydumpat0 ReVa program. Once a homing member is allocated, its observed world position, age and direction follow the deterministic $50798 transition model. Consequently:

  • the route, staging gate and encounter serialization are offline;
  • the concrete spawn state is captured live;
  • near-term movement is predicted deterministically from that state; and
  • uncertainty before allocation is represented by the emitter envelope, not by a guessed member trajectory.

When online search is allowed

The controller follows and cheaply revalidates a cached action sequence. A new space-time search is allowed only when one of these events occurs:

  1. A new hostile object is allocated.
  2. The cached ship path intersects a live or conservatively predicted collision hull.
  3. Wall collision replay or a camera transition invalidates the expected ship state.
  4. Damage/life state changes unexpectedly.
  5. The offline mission phase or homing gate changes.

The search is a safety layer, not a tactic selector. It may temporarily leave the backbone, but safe alternatives are ranked by how well they retain the current offline mission. It cannot activate the next homing gate merely because that gives more short-term clearance.

Files and regeneration

  • xenon_tools/build_level2_strategy.py builds the policy.
  • xenon_tools/level2_strategy.py loads it as typed immutable data.
  • assets/xenon_level2_strategy.json is the generated runtime asset.
  • xenon_tools/test_level2_strategy.py verifies regeneration, topology, gate order, wall clearance and world-coordinate phase selection.

Regenerate after replacing the resident Level 2 map:

python xenon_tools\build_level2_strategy.py

The Python UI displays L2 STRATEGY with the current phase, owned homing gate and number of cleared gates. Trace JSON records the same phase and gate so strategy transitions can be reviewed without inferring them from the low-level tactic string.

Replay validation against level2-model-v13-0824-03.x2events retained the homing_gauntlet phase while bounded backscroll crossed world Y 1900, advanced gate ownership from ring 1 to ring 2 and then ring 3, and kept shield 35 through the former damage frame 33142 and the end of the recording at frame 33240.

The explicit lower-labyrinth and final-arena policy was validated on 2026-08-24. The normal-speed acceptance run level2-left-route-boss-shop-acceptance-0824-05.x2events followed the fixed left corridor, survived both lower swarms without damage, entered the arena through the left passage, destroyed the moving final eye, completed the shop, and stopped on the first playable Level-3 frame (37901). It retained Side Shot, bought the permanent Laser for 4,000 cash, and skipped temporary Super Nashwan Power. The long boss engagement still cost one life to four $4180 horizontal-projectile hits; this is a remaining combat-quality issue, not a route, boss-completion, or shop-policy failure. Both authentic and sprite-stream AVIs cover the complete acceptance run.

Retrospective: a parallel, unsuccessful attempt at the same final-arena tactic

Date: 2026-09-24. Branch claude_level2_spider, working from the same user-described plan independently and in parallel with the work above (descend below the web after activating the spider, cross to the firing column, switch to the forward weapon). It reached the same core insight — forward-weapon damage once correctly positioned is dramatic — but never produced a clean kill, and the iteration history is a useful record of what specifically goes wrong when this tactic is implemented without the safeguards above.

What was built

A four-phase final_boss_phase state machine in level2_choose_final_boss_python_parity (xenon_autopilot_level2.c): APPROACH (unchanged: pull world_y down to the one-time <=176 trigger), WEB_CLEAR (descend below the temporary web), CENTER_APPROACH (cross to the real firing column), MAIN (hold position, forward weapon). Structurally close to FRONT_DESCEND/FRONT_CROSS/FRONT_FIRE above, arrived at through several rounds of live telemetry review rather than in one pass.

Iteration history and what each bug actually was

  1. First attempt (runs r25/r26): WEB_CLEAR's descent target was in->maximum_y — the current reachable-view bound — clamped through fmin. This silently capped the descent at world_y≈192, far short of the ~280-380 the real hit-column needed, so the ship ended up north of the boss's hitbox instead of south of it. Forward shots travelled away from the target the whole fight; total damage dealt across two full attempts was 1-2 HP. Root cause: in->maximum_y is not a stable "bottom of the arena" value, it tracks whatever is currently reachable at the live scroll position, and using it as a movement goal (rather than only as a safety clamp on an otherwise-independent goal) silently truncates the real target.
  2. Second attempt (run r27): switched to raw DOWN input relative to the ship's own position (bypassing the pathfinder, matching the pattern already used for the wall crossing), but still capped by a fixed 90-frame budget rather than an actual position check. Tracing proposed vs applied masks frame-by-frame revealed the real blocker for the first time: the hazard-escape dodge system was overriding the phase's DOWN request with UP on essentially every frame (proposed:0x02 applied:0x01, sustained for the full dodge-commit window), because a threat is almost always active right at the point where the spider activates and its web spawns. This was not a scroll or coordinate bug; it was the dodge system doing exactly what it was designed to do — protect the ship — at the one moment this tactic needed to override it.
  3. Third attempt (run r28): added a driver-level arbitration exception letting WEB_CLEAR override the dodge system for its own bounded window. Descent immediately became clean (world_y 180→320 over the 90-frame budget, zero damage taken). But the frame budget still expired before the ship reached a stable position, so the phase handed control back to the dodge system mid-descent, which then pulled the ship back toward the ceiling — reported live as "it keeps moving top" even after the override fix landed.
  4. Fourth attempt (runs r29/r30): replaced the frame budget with an actual world_y target (initially 376, "the bottom of the web," raised to 408 — two ship-hull-heights further — after live review of the recording). Descent became fully reliable. But CENTER_APPROACH (the horizontal crossing) turned out to have the identical problem: traced as proposed:0x08 (RIGHT) applied:0x01 (UP), reported live as "started moving UP instead of right" — the same dodge-override bug, on the same bounded, one-time maneuver, that the earlier fix for WEB_CLEAR never covered.
  5. Fifth attempt (run r31): extended the same override to CENTER_APPROACH. The crossing then completed in about 20 frames (player.x: 14→178), and once the ship was actually in the real firing lane, boss health fell from 74 to 2 within ~140 frames (frames 14884-15027) — closely matching the 75→2 curve reported above for the working implementation. But the ship took five hits over the same window — two during the crossing itself, three more while holding position afterward — and died at boss health 2, two hit points short of an actual kill.

Why the working implementation above did not have this problem

Comparing the two implementations directly:

  • Target column. This attempt aimed the crossing at X=160 (the documented [152,167] true-hitbox midpoint). The working implementation above measured the actual forward-weapon firing lane empirically and used X=192 instead, noting "earlier X 172 left the forward weapons outside the head's hit lane" — the visible hitbox center and the real weapon-effective column are not the same point, and only live measurement caught that.
  • Dodge arbitration. This attempt's fix was a blanket override: for the duration of WEB_CLEAR/CENTER_APPROACH, the dodge system is bypassed entirely, trading away all protection during exactly the highest-risk windows (right at activation, and mid-crossing) to guarantee the maneuver completes. The working implementation's arbitration is more surgical: it pre-seeds the movement mask with the mission's request only when an earlier-stage hazard pass is empty or already agrees with it, and then still runs the full projectile-aware scorer afterward — so genuine dodge protection is never fully switched off. That scorer itself also carries fixes this attempt's parallel dodge system did not have: level2_clamp_escape for camera-edge cases (holding DOWN at the bottom edge only scrolls the camera, it does not move the ship, and treating it as a valid dodge direction is a bug), corrected projectile padding derived from a measured one-pixel sprite/hitbox offset, and a fix for a "neutral, least-risk choice" being wrongly retained as if it were an active dodge (which pins the ship in place and adds a switch penalty to every subsequent frame). This attempt never found or fixed that last class of bug at all; its parallel level2_final_boss_burst_escape function papered over some of the same symptoms with its own separate heuristics (a grace period before clearing a stale commitment, a persistence check before allowing a direction switch, a stuck-position detector) instead of fixing the shared scorer directly.

The net effect: both implementations independently discovered that a correctly-positioned forward-weapon attack does dramatic, fight-ending damage (74→2 HP in under 150 frames, twice, in two unrelated codebases). The difference in outcome — a clean kill with full shield here, versus five hits and a death two HP short of a kill in the parallel attempt — traces almost entirely to how much dodge protection was traded away to make the descent and crossing reliable, not to the high-level shape of the tactic.