pilot.py gained SYLPH_PREFER, a unit-name substring whose matches get their target score multiplied by 0.05 while everything else is multiplied by 4.0. With SYLPH_PREFER=e010 a clean 320 s run, zero stalls by the witness, killed eight turrets and two Attacker_S. The preference is real -- e010 kills went from roughly one across all previous runs to two in a single run -- but it is weak. Turrets still outnumber attackers four to one in the kill log, because target commitment and simple proximity keep pulling the nose back to them, and phase 1 fields 108 turret craft against 16 attackers. Deployed stayed at 41 throughout, so no phase advance. That quantifies the blocker. Clearing the marked attackers means destroying 16 craft, and at two per 320 s that is about 2560 seconds, roughly 43 minutes of continuous verified-live flight across many chained attaches, against a freeze rate of about two runs in five. This is no longer a reverse-engineering problem. Everything needed to observe the phase advance is built and validated -- the roster-to-craft link, the liveness read, the stall witness, chained attaches and the discard rule. What is missing is a pilot good enough to complete the mission objective, which is game-playing work with an uncertain payoff. The choice is recorded rather than made, because it is about how much effort one confirmation is worth rather than a technical unknown: invest in the pilot, accept the static answer where only the trigger is inferred rather than observed, or attempt one very long chained run betting against the freeze rate.
136 lines
6.0 KiB
Markdown
136 lines
6.0 KiB
Markdown
# The mission script in plain English — and why phase 1 never completed
|
||
|
||
Status: ✅ the localised string tables are decoded and readable; ✅ the phase
|
||
structure is confirmed narratively *and* by roster composition; 🟡 a concrete,
|
||
testable reason the phase never advanced in any run.
|
||
|
||
## ✅ `IXUD` — the localised string container
|
||
|
||
`language\*_local_string.tbl` (the prefix is `language\`, a third convention
|
||
after `stage\` and `message\`) is **not** IDXD. Magic is `IXUD`, and its strings
|
||
are **UTF-16 big-endian**. That is why every earlier ASCII-oriented dump of these
|
||
files produced garbage.
|
||
|
||
Reading them is immediate once the encoding is known, and it makes the mission
|
||
design directly legible instead of inferred.
|
||
|
||
## ✅ Stage 02's nine sub-objectives, in words
|
||
|
||
| id | text |
|
||
|---|---|
|
||
| `SUBOBJ_005` | You rescued the ally destroyer! |
|
||
| `SUBOBJ_006` | You destroyed all enemy fighters! |
|
||
| `SUBOBJ_007` | You sunk all enemy warships! |
|
||
| `SUBOBJ_008` | You rescued the ally cruiser, Amalthea! |
|
||
| `SUBOBJ_010` | The ally cruiser CALIBAN took no damage! |
|
||
| `SUBOBJ_011` | You sunk the enemy destroyer targeting the ACROPOLIS! |
|
||
| `SUBOBJ_013` | You destroyed all enemy cruise missiles! |
|
||
| `SUBOBJ_014` | You destroyed all enemy missiles and units! |
|
||
|
||
(`SUBOBJ_009` has no text.) 91 objectives are defined across the game.
|
||
|
||
## ✅ The three phases, confirmed twice over
|
||
|
||
The guide script reads as three distinct acts, and each matches the per-phase
|
||
roster composition found independently in
|
||
[mission-phase-deployment.md](mission-phase-deployment.md):
|
||
|
||
| phase | script | roster |
|
||
|---|---|---|
|
||
| 1 | *"The attackers with the orange markers, right?"*, *"Protect the ACROPOLIS!"* | turrets, attackers, fighters |
|
||
| 2 | *"destroy the ship's engine"*, *"destroy that ship's weapons"*, *"take out the enemy's shield projector"* | destroyers, frigates, cruisers |
|
||
| 3 | *"start by taking out that missile"*, *"Concentrate on destroying the missiles one by one"* | **`UN_e201_ADAN_ISCMissile` ×9** |
|
||
|
||
Phase 3's nine cruise missiles against `SUBOBJ_013` *"You destroyed all enemy
|
||
cruise missiles!"* is an exact match between two files decoded on different days
|
||
by different routes.
|
||
|
||
## 🟡 Why phase 1 never advanced: the pilot killed the wrong things
|
||
|
||
The phase-1 objective is stated outright — **destroy the marked attackers**:
|
||
|
||
> *"Rhinos, prepare for combat. Are you all clear on your targets?"*
|
||
> *"The attackers with the orange markers, right? Roger that!"*
|
||
> *"Katana, those attackers are our targets!"*
|
||
|
||
Those are `UN_e010_ADAN_Attacker_S`, of which phase 1 fields four squadrons.
|
||
|
||
**The hunting pilot targeted turrets almost exclusively.** Every loss line in the
|
||
run logs reads `UN_e007_ADAN_Turret`, with `UN_e010_ADAN_Attacker_S` appearing
|
||
only twice across all runs — unsurprising, since `SYLPH_HUNT` was built to make
|
||
turrets targets and `SYLPH_KEEPOUT` was tuned for them. So 42 kills were
|
||
overwhelmingly the *wrong* 42.
|
||
|
||
That gives a mundane explanation for the whole run of null results, and it does
|
||
not require the frames reading or event-gating to be settled first.
|
||
|
||
**Prediction:** destroying the phase-1 `UN_e010_ADAN_Attacker_S` squadrons should
|
||
advance the phase, which is directly observable as `deployed` jumping from 41
|
||
toward the phase-2 roster.
|
||
|
||
**Test:** a pilot that prioritises `e010` over `e007` — a target-preference knob,
|
||
not new decoding — and the existing probe watching `deployed`.
|
||
|
||
This is 🟡, not ✅: the objective text is certain, but that *this particular
|
||
objective* gates the phase advance is inference from the script's structure.
|
||
|
||
---
|
||
|
||
# The target-preference knob works, and the blocker is now combat, not RE (2026-08-24)
|
||
|
||
## ✅ `SYLPH_PREFER` added and measured
|
||
|
||
`pilot.py` gained a target-preference knob: a unit-name substring whose matches
|
||
get their target score multiplied by 0.05 and everything else by 4.0. With
|
||
`SYLPH_PREFER=e010`, one clean 320 s run (witness: **0 stalls**):
|
||
|
||
| killed | count |
|
||
|---|---|
|
||
| `UN_e007_ADAN_Turret` | 8 |
|
||
| `UN_e010_ADAN_Attacker_S` | **2** |
|
||
|
||
The preference is real — `e010` kills went from about one *across all previous
|
||
runs* to two in a single run — but it is **weak**: turrets still outnumber
|
||
attackers 4:1 in the kill log. Target commitment (`COMMIT_MAX`, `COMMIT_DROP`)
|
||
and simple proximity keep pulling the nose back to turrets, which are far more
|
||
numerous.
|
||
|
||
`deployed` stayed at **41** throughout. No phase advance.
|
||
|
||
## 🚧 The blocker, quantified
|
||
|
||
Phase 1's roster, by craft rather than by squadron:
|
||
|
||
| unit | members | craft (`sum(n)`) |
|
||
|---|---|---|
|
||
| `UN_e007_ADAN_Turret` | 12 | **108** |
|
||
| `UN_e106_ADAN_Destroyer` | 7 | 7 |
|
||
| `UN_f001_TCAF_DeltaSaber_T` | 7 | 7 |
|
||
| **`UN_e010_ADAN_Attacker_S`** | **4** | **16** |
|
||
|
||
Clearing the marked attackers means destroying **16 craft**. At the measured rate
|
||
of 2 per 320 s that is **~2560 s — roughly 43 minutes** of continuous
|
||
verified-live flight, across many chained attaches, with a freeze rate of about
|
||
two runs in five.
|
||
|
||
**This is no longer a reverse-engineering problem.** Everything needed to observe
|
||
the phase advance is built and validated: the roster link, the liveness read, the
|
||
stall witness, chained attaches, the discard rule. What is missing is a pilot
|
||
good enough to actually complete the mission objective, and that is game-playing
|
||
work with an uncertain payoff.
|
||
|
||
## The choice, which is the user's to make
|
||
|
||
1. **Invest in the pilot** — better target selection, missiles, using the
|
||
marker/lock the script keeps referring to. Uncertain, potentially several
|
||
iterations, and drifts away from RE.
|
||
2. **Accept the static answer.** The phase structure, per-phase rosters, route
|
||
paths and objective texts are all decoded and cross-confirmed. Only the
|
||
*trigger* is inferred rather than observed, and it is inferred from the game's
|
||
own guide script naming the objective outright.
|
||
3. **One very long run** — 40+ minutes of chained attaches — betting against the
|
||
freeze rate.
|
||
|
||
Recorded rather than chosen, because it is a question about how much effort this
|
||
one confirmation is worth, not a technical unknown.
|