Checked liveness before investing this time (animating, max_delta=254) and the run was real: 823 distinct speeds, hull 1500->1485, escort 100%->30.7%, ADAN population 127->89 (38 destroyed) over ~1064s, no GUEST FROZEN banner. The phase mirror stayed 0 throughout. But this still does not test the prediction. The claim is that phase 1 clears when ADN110/111/112 -- 27 specific Turrets -- die; what was measured is that 38 enemies of some kind died. SYLPH_PREFER biases target choice but the pilot went to DEFEND and spent the run on e010_ADAN_Attacker_S protecting the escort. The missing instrument is per-squadron liveness: nothing maps a live craft back to its roster squadron, the same gap roster-to-craft-link.md records as unsolved. So 'no advance after 38 kills' is compatible with both 'the condition is wrong' and 'the right 27 were never killed'. The decisive experiment is blocked on attribution, not on flying time.
13 KiB
Which squadrons fly in which phase — and the ~300 craft are ~150
Status: ✅ the phase map, read out of Route_S<NN>.tbl record names;
✅ the 387-vs-300 gap explained — the live-craft probe double-counts;
❔ what advances a phase (nothing static encodes it).
✅ The phase map is in the route names
stage\Route_S02.tbl has 121 records: 120 routes + 1 roster, and every route
name matches Route_<squadron>_p<N><kind> — 120/120:
Route_ADN101_p1F Route_TCN003_p2S Route_ADS351_p3M
The phase lives in the name and nowhere else; a route record's only named
field is FrameCount. So the squadron→phase mapping was on the disc all along,
one string-parse away, in a table that was being read for fly-in geometry.
108 of 111 S02 squadrons match a route name exactly. The three that do not —
TCN207, TCN208, TCS252 — are typos in the route table (Route_TCT207_p2S,
Route_TCT208_p2S, Route_TCN252_p2F), plus two orphan routes naming no
squadron (Route_ADS352_p3F, Route_kichi_p3F). All three near-misses are
phase 2, so phase 1 is unaffected.
Phase partition of Stage 02 (Σn = 387 overall):
| phase set | squadrons | Σn |
|---|---|---|
| {1} | 33 | 142 |
| {2} | 31 | 110 |
| {3} | 39 | 118 |
| {1,3} | 2 | 5 |
| {2,3} | 1 | 1 |
| {1,2,3} | 2 | 4 |
| none (the 3 typos) | 3 | 7 |
| per phase | 37 / 34 / 44 | 151 / 115 / 128 |
✅ The 387-vs-~300 gap: the probe counts each craft TWICE
roster-to-craft-link records four failed attempts to explain how the roster becomes "~300 live craft". The premise was wrong — there were never 300 craft.
Phase 1's member-level n multiset against the measured craft-per-record
fan-in (41 records, 300 craft):
phase-1 members (42): n=1 x25 n=2 x1 n=4 x4 n=9 x12 sum 151
observed craft/record: 2 x24 4 x1 8 x4 18 x12 sum 300
observed / 2: 1 x24 2 x1 4 x4 9 x12 sum 150
Every bucket matches shape for shape. The only discrepancy is 24 vs 25 records
at the bottom — the already-documented 41-vs-42 off-by-one, and it is an n=1
record. So 300 = 2 × (151 − 1). Unit type corroborates independently: the 12
records showing 18 craft are all UN_e007_ADAN_Turret, and phase 1 has exactly
12 turret squadrons at n=9.
✅ The factor of 2 is an artifact of the probe, not real units
Two static arguments, and the second is decisive because it is a hard capacity bound:
-
Named pilots. Phase 1's eight
f001members all haven=1and carry distinct identities —Character_Player_Test, ELLEN, RAYMOND, GENE, SANDRA, BILLY, ANTONIUS, CARL. A 2× reading means 16 Delta Sabers for 8 named people. -
Formation slots. Squadrons cannot exceed their formation's
FrameCount(see unit-group-table):reading violations among the 37 phase-1 squadrons Σn ≤ FrameCount(1×)0 2·Σn ≤ FrameCount(2×)20 Including 16 squadrons on
Formation_1_only— one slot,n=1— which a 2× reading would have placing two craft in a one-slot formation.
So the true phase-1 population is ~150, and the 296 / 298 / 300 spread is 2 × a 148 / 149 / 150 population after kills. That all three measurements are even is a further tell a 1:1 count would not produce half the time.
Best explanation of the missing 42nd record: the player's own tuple
(TCN001 member 0, Character_Player_Test), which plausibly is not in the
AI-craft pool the +0x130 def-pointer scan walks. That makes the chain exact:
300 = 2 × (151 − 1 player).
⚠️ This is a static argument about a dynamic measurement. It says the probe's number cannot mean what it was taken to mean; it does not identify what the probe is double-counting. That needs a run — the counting rule in the craft scan is the place to look, not the game.
🔴 Refuted along the way
UnitGroupcarries no phase, spawn time or arrival delay. The raw field dump accounts for every slot:1019 = sum(Count)·4 + 5·111, with positional entries tagged by sequential index (0x0,0x1,0x2,…), not hashes. There is no spare field.DisableIntervalcannot explain Stage 02 — it isNofor all 111 squadrons. Corpus-wide its 31Yesrecords sit in just two stages, S04 (5) and S14 (26), all onGNN***squadrons.stage\EnumSquadron_Test.tbldoes not exist (0x213f4a7eis not in the TOC). It was listed as a candidate for the arrival-interval values; it is dead.AIParams_S02.tblis keyed by AI profile, not squadron, and carries only combat tuning.SUBObjectiveSettings_S02.tblis keyedSUBOBJ_005..014with only points/unlock/HUD strings — no squadron, phase or trigger.
✅ Bonus: the UnitGroup record key, confirmed corpus-wide
A squadron record's key is tag_hash(squadron_id) — 1160/1160 across all 28
stages (ADN101 → 0x659aff47). Same hash as
idxd-tag-hash; this is an independent
confirmation of it on a second kind of table.
❔ Still open: what advances a phase
Nothing static encodes a trigger. Swept the stage record and every table it
names — Route, AIParams, SUBObjectiveSettings, FormationSet, nameplate,
EnumUnit, EnumCharacter, EnumLocalString, EnumWeapon — plus the
message\ family, for field names matching
interval|time|phase|delay|wave|spawn|arrival|trigger|start|appear|event|condition.
The only hits anywhere are FrameCount and PresetMessage_Phase1/2/3 in
message\UnitMessageSet_S02.tbl. The trigger is almost certainly in the
executable, not the data.
Falsifiable predictions for the next run
- Per-record craft counts, in probe units (2×): 4 records at 8 =
ADS151, ADT102, ADT107, ADT113(allUN_e010_ADAN_Attacker_S); 1 record at 4 =TCN105(UN_f106_TCAF_Destroyer); 24 records at 2 = the remaining phase-1n=1members. - A phase advance should move the deployed set toward phase 2: 34 squadrons,
36 members, Σ
n115 (≈230 in probe units). TCN207,TCN208andTCS252may fail to arrive in phase 2, because their routes are misnamed.
🟡 2026-08-25 — first long live observation: no phase advance, and a GAME OVER
Flew Stage 02 with an actively hunting pilot for 936 s while polling the
runtime phase mirror [*(0x828F35F8) + 236] every 3 s (phase_probe.py).
The mirror never left 0. That is what the static work predicts rather than a
contradiction: CScriptInterpreter::ChangePhase (opcode 995) is only posted when
the ordinal is > 1 (the guard in mission-bytecode opcode 0x83), so a run
that stays in phase 1 never writes the mirror. It does mean the mirror is
useless as a "which phase am I in" readout for phase 1 — it reads 0, not 1.
[ScriptMission+40] is the real counter and needs a debugger.
The run ended in GAME OVER — and the pilot's hull was still 1500/1500,
so the player did not die. A script lose-branch fired, and the pilot log says
which one is likely: the tracked asset fell from 100.8 % to 23.4 %, with
ASSET-HIT events logged, while the pilot repeatedly AVOIDed
f101_TCAF_Acropolis — a friendly capital ship — 2588 times.
So the escort was being destroyed throughout, and the mission failed with the player untouched. "Escort lost" is now a measured candidate rather than a guess, though the final asset value was 23.4 %, not 0, so the exact threshold (or whether a different unit's loss ended it) is not established.
So a phase advance still has not been observed. Two runs now — 530 s and
936 s — neither reached phase 2. Combined with the static reading that phase 1
polls unit_state on ADN110/ADN111/ADN112, the likeliest explanation is that
those three squadrons were never destroyed; the pilot hunts whatever is nearest,
not the objective. Next: bias the pilot at those squadrons' craft and re-run.
🔴 Refuted: sub_8226D740 does not read the flag register file
Chasing what reads the 32-entry flag file at [phase+120], the promising hit
was three addi rN, r31, 120 inside sub_8226D740, the per-frame engine→script
trigger edge. It is not the flag file. In that function r31 is a local
trigger-record buffer whose fields are handed to sub_8226E220 as
out-parameters (+80, +84, +88, +92, +112, +120), and lfd f1,120(r31) reads a
double from the record. The phase is in r26/r29.
Offsets 88 and 120 are far too common (2091 and 5228 instructions image-wide,
mostly stack frames) for an offset search to isolate the register files.
Who reads the flags is still unknown, so the chain
set_flag(8) → … → END_PHASE has a gap in the middle.
✅ 2026-08-25 — Stage 02 phase 1: destroy 27 Turrets (ADN110/111/112)
Resolving the three squadrons the phase-1 condition polls
(isl-builtins, unit_state at 0xF524) against
the roster:
| squadron | phases | AI | unit | n |
|---|---|---|---|---|
| ADN110 | 1 | AI_ADAN_CraftSquadron_Rookie |
UN_e007_ADAN_Turret |
9 |
| ADN111 | 1 | AI_ADAN_CraftSquadron_Veteran |
UN_e007_ADAN_Turret |
9 |
| ADN112 | 1 | AI_ADAN_CraftSquadron_Rookie |
UN_e007_ADAN_Turret |
9 |
All three are phase 1 (from the Route_S02 name map), all fly the same
craft, all n = 9 — so the condition watches 27 Turrets, and all three
squadrons share Formation_ADAN_Turret09_30.
Three independent layers agree here, which is the point worth recording: the
route names say these are phase-1 squadrons, the roster says what they
fly and how many, and the script polls exactly these three before latching
set_flag(8).
✅ Confirms "Turret" is a craft type, not ship AA
The user's correction stands on the data: UN_e007_ADAN_Turret is flown by
AI_ADAN_CraftSquadron_Rookie/_Veteran — a craft squadron AI, in a
30-slot craft formation — never AI_Structure. It is an enemy the player fights,
not a gun bolted to a capital ship.
🔴 2026-08-25 — the Turret-biased run was VOID: the guest was frozen
Ran it: SYLPH_PREFER=Turret, escort intact (ast=100.0%), 1070 s. The phase
field read 0 throughout and the pilot logged 4029 Turret-targeting
samples. That looked like a clean negative — "hunting the objective squadrons
does not advance the phase" — and it is worthless.
frozen.py says max_pixel_delta=0: the guest was frozen, and the pilot's
very first sample at t=0.0 already shows spd=0 with the same yaw, pitch,
target and d=7186 that it still had at 1070 s. The mission froze on entry to
flight; nothing was ever shot. screen_id said flight the whole time, which is
precisely the trap mission-freeze-resume-spin
documents.
I was one step from writing this up as a result about the game. What saved it was running the freeze test rather than trusting a plausible-looking log — the same lesson that note already carries, arrived at again from the other side.
✅ Fixed so it cannot recur silently
phase_probe.py now calls frozen.py every 60 s and prints
*** GUEST FROZEN *** inline, so a dead-world reading is labelled in the data
rather than discovered afterwards. ⚠️ frozen.frozen() returns a tuple
(is_frozen, max_delta) — testing it directly is always truthy and would have
made the witness fire on every check; it must be unpacked. Verified against the
frozen guest: the banner fires, and the unpacked value is (True, 0).
The pilot log is itself a witness and was not being read as one: identical yaw/pitch/target across thousands of samples means a dead world, not a patient pilot.
🟡 2026-08-25 — Turret-biased run, VERIFIED LIVE: still no phase advance
Re-ran it with the freeze witness armed, and checked liveness before
investing in the run this time (frozen.py → animating, max_delta=254).
This one was real: 823 distinct speeds logged, the player's hull moved
1500 → 1485, the escort fell 100 % → 30.7 %, and the ADAN population dropped
127 → 89 — 38 enemies destroyed over ~1064 s. The probe printed no
GUEST FROZEN banner.
The phase mirror stayed 0 throughout. So: 38 enemy losses, escort still alive, no advance.
🔴 But this still does not test the prediction
The prediction is that phase 1 clears when ADN110/ADN111/ADN112 — 27
specific Turrets — are destroyed. What was measured is that 38 enemies of some
kind died. SYLPH_PREFER=Turret biases target choice, but the pilot switched to
DEFEND and spent most of the run on e010_ADAN_Attacker_S, protecting the
escort.
The missing instrument is per-squadron liveness. Nothing currently maps a
live craft back to its roster squadron — that is the same gap
roster-to-craft-link records as unsolved. Until a
craft can be attributed to ADN110, a kill count cannot say whether the
condition was met, and "no advance after 38 kills" is compatible with both
"the condition is wrong" and "the right 27 were never killed".
Honest state: three live-run attempts, no phase advance observed, and the decisive experiment is still blocked on attribution rather than on flying time.
🟡 The prediction to test
If phase 1 clears on those three squadrons dying, then destroying 27 Turrets
while the escort survives should push [ScriptMission+40] to 2 and make
ChangePhase write the mirror at [*(0x828F35F8)+236]. Two runs so far killed
whatever was nearest and never advanced.