re: survey all 28 mission scripts -- kill counters are dead game-wide
All 28 StageNN.ssb decoded: 2,085,628 bytes, 25,705 call sites, 108 of 147 built-ins used. Verified the survey independently -- 33=0, 34=0, 108 distinct, hp_pct_test 1955, unit_state 1271, all exact. global_counter0/1 have ZERO call sites in all 28 stages. The handlers exist and are wired; no mission calls them. So 'does a wave start after N kills?' is answered for the whole game, not just Stage 02: no mission counts kills. Two idioms change how the counts read. hp_pct_test(unit, 0.0) IS a destruction test -- 1786 of 1955 calls (91%) pass 0.0, and the handler's zero path additionally requires state == 4 -- so unit_state and hp_pct_test(...,0) are interchangeable and stages just pick one. And squad_survival_pct is a boolean, not a percentage: an integer divwu before the x100 means it can only be 0 or 100, and all 29 sites pass a friendly TCAF squadron with threshold 99.9, making it 'has this escort lost anybody'. The game has no destroy-N%-of-a-squadron objective. Outliers: S18-S23 (tutorials) have no flag/trigger machinery at all -- linear lessons; S16 has no unit predicates, only a descending player-gauge ladder. Not settled: group_ratio_pct takes two unit indices (blob+4 and blob+12) and its numerator lookup was not read to the bottom, so it is not being labelled 'percent killed by the player'. isl.py's UNIT_ARG omitted 71/72.
This commit is contained in:
80
docs/re/mission-objective-vocabulary.md
Normal file
80
docs/re/mission-objective-vocabulary.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# What the missions actually test — all 28 scripts surveyed
|
||||
|
||||
Status: ✅ corpus-wide counts, verified independently; ✅ two idioms identified
|
||||
that change how the numbers read; 🟡 one built-in's semantics only partly read.
|
||||
|
||||
All 28 `Stage\StageNN.ssb` scripts decoded with `tools/re-capture/isl.py`:
|
||||
**2,085,628 bytes, 25,705 built-in call sites, 108 of the 147 built-ins ever
|
||||
used.** Nothing failed to parse. Re-checked here against the survey: `33=0`,
|
||||
`34=0`, `108` distinct, `hp_pct_test` 1955, `unit_state` 1271 — all exact.
|
||||
|
||||
## ✅ The kill-counter primitives are DEAD, game-wide
|
||||
|
||||
`global_counter0` / `global_counter1` (built-ins 33/34) have **zero call sites in
|
||||
all 28 stages**. Their handlers exist and are wired — they read
|
||||
`[0x828F35C4]+8` and `+12` into the int result register — and **no mission ever
|
||||
calls them**.
|
||||
|
||||
That settles the "does a wave start after N kills?" question far beyond Stage 02:
|
||||
**no mission in the game counts kills.** 39 built-ins are never called at all,
|
||||
including `timer_start`, `deploy_and_wait`, `camera_at`, `play_voice` and
|
||||
`screen_fade`.
|
||||
|
||||
## ✅ `hp_pct_test(unit, 0.0)` *is* a destruction test
|
||||
|
||||
**1786 of 1955 `hp_pct_test` calls (91 %) pass threshold `0.0`** — 107 of
|
||||
Stage 02's 109 resolvable sites. Built-in 20's handler (`0x8226AB78`) explains
|
||||
it: above zero it returns `pct ≤ threshold`, but at exactly `0.0` it takes a
|
||||
separate path that *also* requires the unit's state field `[unit+16] == 4`.
|
||||
|
||||
So **`unit_state` and `hp_pct_test(…, 0)` are interchangeable "is it destroyed"
|
||||
tests**, and stages simply pick an idiom. Real damage thresholds are the
|
||||
minority: 50 (57×), 30 (19×), 70 (18×), 40 (14×), then a thin tail.
|
||||
|
||||
This matters for reading the counts: a stage with no `unit_state` is not
|
||||
necessarily testing something different — S14 has none, and 25 of its 34
|
||||
`hp_pct_test` calls pass `0.0`.
|
||||
|
||||
## ✅ `squad_survival_pct` is a boolean, not a percentage
|
||||
|
||||
29 sites, in S06/S07/S08/S09/S15, and **every one passes a friendly TCAF
|
||||
squadron and the threshold 99.9**. The handler divides current by initial member
|
||||
count with an **integer `divwu`** before multiplying by 100.0, so the value can
|
||||
only be **100 or 0**.
|
||||
|
||||
At a 99.9 threshold that makes every site the predicate *"has this friendly
|
||||
squadron lost anybody at all?"* — an escort-casualty test. **The game has no
|
||||
"destroy N% of a squadron" objective.**
|
||||
|
||||
## ✅ The condition vocabulary, and the outliers
|
||||
|
||||
| pattern | stages |
|
||||
|---|---|
|
||||
| `unit_state` + `hp_pct_test` + `dist_lt` + `unit_relation` | the story stages |
|
||||
| `squad_survival_pct` (escort intact?) | S06, S07, S08, S09, S15 |
|
||||
| `group_ratio_pct` | **S01 only**, 13 sites, always `(TCN001, <ADAN squadron>)` |
|
||||
| player gauges 132/133/134 | **S16 only** — 11 + 2 + 2 sites |
|
||||
| `is_engaged` | **S05 only**, 3 sites, all on `TCN004` |
|
||||
|
||||
**S18–S23, the tutorials, are the outliers by a distance.** No flag/trigger
|
||||
machinery at all — zero `read_freg`, `clear_flag`, `push_trigger`,
|
||||
`named_event`, `MARK_LAST_PHASE`, `FORCE_END_PHASE`, and none of the timer
|
||||
family. One `set_flag` and one `END_PHASE` each. They are linear scripted
|
||||
lessons, not missions.
|
||||
|
||||
**S16 has no unit predicates whatsoever** — its symbol table 2 holds three
|
||||
entries, and its conditions are a descending player-gauge ladder
|
||||
(75/50/25/10/0). A player-state set piece.
|
||||
|
||||
## 🟡 Not settled
|
||||
|
||||
* **`group_ratio_pct` (72)** takes **two** unit indices — blob+4 and blob+12 —
|
||||
and its numerator comes from a pair-keyed lookup through `[phase+328]` that
|
||||
was not read to the bottom. The natural reading (a per-squadron ratio credited
|
||||
to the player's flight) fits S01's usage, but is **not** established, so it is
|
||||
not being called "percent killed by the player".
|
||||
* `isl.py`'s `UNIT_ARG` omitted 71 and 72, so their second unit operand printed
|
||||
as a bare integer. Noted in the tool; 56 may be the same shape, unverified.
|
||||
* The timer names in `isl.BUILTIN` look mismatched: 73 `timer_start` has **zero**
|
||||
sites while 123/124 carry the traffic, and their handlers are the run/stop
|
||||
pair. Flagged, not renamed.
|
||||
Reference in New Issue
Block a user