Xenon 2

Autopilot · write-up

Native map observation sessions (ABI 83)

xenondoc/AUTOPILOT_NATIVE_MAP_SESSION.MD · 6 KB · updated 2026-09-17

ABI 84 update: native driving and optional Python world views remove mandatory population reconstruction, with 35–47% lower recorded driving-processing time in the measured samples.

The C path now maintains persistent terrain from canonical C wall observations. It no longer exports wall draws into Python WallTile/Rect objects merely to repack them for C, seeds no Python MapCell dictionary for ordinary driving, and does not export embedded tile codes just to reconstruct the native seed.

Structure and API

xenon_autopilot_map_session.c owns session rules and scalar status. It keeps identity/run/frame continuity, selects the embedded level, computes viewport bands, updates persistent cells and maintains revision/bounds/solid totals. Existing xenon_autopilot_map_state.c retains cell-level observation and destruction rules. xenon_autopilot_observation.c provides the canonical native tile draws directly.

The standalone C sequence is:

  1. xap_world_observe prepares the captured world, including wall draws.
  2. xap_map_session_observe updates the persistent map using that world, the level and the draw-pass scroll. It returns a small XapMapSessionView containing the borrowed map handle and scalar status, not cell arrays.
  3. Feed its map/revision/bounds to the existing native environment cache and driver.

Create/free sessions with xap_map_session_create/xap_map_session_free. xap_map_session_clone explicitly copies cell state and renderer history for a checkpoint. Native map/environment/driver operations require serialized access.

The session reseeds on level, namespace or run changes and on frame rewind. Reading the same captured frame twice does not count as two destruction observations. Viewport intervals retain the allocated 16-row border on both ends of a level. Static walls stay monotonic; destructible cells still require two complete renderer absences. This migration does not reinterpret absence as proof of destruction for ordinary walls.

xap_map_session_sync_ram applies snapshot RAM to destructible map words directly in C. It validates eligible addresses before mutation, excludes boss-arena scratch groups, maintains group/solid totals, and preserves ownership rather than exporting and reseeding cells through Python. Full copies and full solid recounts occur only on explicit checkpoints, initial seeding or RAM restoration, not each frame.

Python compatibility and replay

native_map_session.py owns the C lifetime and publishes compact metadata. PersistentWorldMap.cells and embedded resident metadata are lazy compatibility views. Cell dictionaries are created only when an existing Python consumer requests them. Per-cell observation timestamps are not maintained on this native path; exported first_frame is a compatibility placeholder using the current capture frame. Requests needing historical cell detail should retain the reference/detail mode.

CapturedWalls materializes wall geometry only on iteration/indexing. It retains the source capture records rather than an expiring C pointer, so saved views remain valid after the canonical world advances. A count query requires no conversion.

Replay now selects native map assets and disables historical cell-detail tracking when using the C kernel, matching live configuration. Previously its default map silently retained the Python path. Replay checkpoints clone native map sessions; they do not copy thousands of Python map cells. Optional displayed map/wall views remain available. Driver metrics identify map_backend=c-session or compatibility.

Custom resident maps, detail tracking, unsupported capture paths and explicit Python map edits retain the compatibility path. Switching away from a native session materializes its current cells before dropping ownership, preserving destruction evidence. XENON_NATIVE_MAP_SESSION=0 selects the previous map orchestration.

Validation and measurements

Standalone C build; 288 native tests, 575 forced-native reference-policy tests, 67 planner tests, 24 replay tests and 15 resident-map tests pass (969 tests). New checks forbid Python map seeding, resident asset export and wall-object iteration while driving all five levels. They cover lazy inspection, native checkpoint copies, RAM restoration, invalid-RAM non-mutation, duplicate observations, identity resets, backend fallback, and agreement with retained map cells.

An actual recording's backward/forward cached seek (105 → 96 → 105) preserved controls, the selected maneuver path and the native map's solid count.

Fresh-process, CPU-pinned recorded comparisons with two reversed-order repeats:

Sample Previous map path Native session Reduction
Level 1, 2367–3367 1.038 ms 0.957 ms 7.8%
Level 3, 49751–50020 1.542 ms 1.462 ms 5.2%
Level 5 barriers, 90160–90459 1.592 ms 1.504 ms 5.5%

All compared decisions match. These are recorded processing times, including replay work, rather than live TCP timings. Reports are in xenon_tools/run_logs/native-map-session-{level1,level3,level5}-0913-final/. Use comparison variants c-map-session-old,c. Earlier reports without the -final suffix predate the replay configuration fix and do not exercise the new map session. No new live campaign or WASM profiling was run for this stage.

Remaining independence work

The map-observation half of orchestration is now native. Python still packs the protocol capture, constructs the object-world compatibility view, derives some captured capability/scalar headers, and coordinates the calls. The next substantial step is to remove mandatory object-world export and connect capture to driving with only the required scalar inputs and optional diagnostic views. Lifecycle, shops, fire scheduling and the final in-memory capture/control adapter remain afterwards. No Hatari build integration was added.