re: AIParams disc-wide, and a correction to my own last entry

CORRECTION FIRST.  Last iteration I recorded sub_8233C368 as unblocking a
NEEDS-HUMAN item -- "the corpus carries the AI tail of Maneuver as
NEEDS-HUMAN/runtime; it is statically reachable after all."  That was wrong.
stage-mission-tables.md already documents AIParams_S02.tbl as exact original
values obtained by static RE, directly portable, listing all 20 field names and
both shapes.  I grepped FiringLength and saw the file but did not read the
section.  Finding the owning doc is not reading it.  The only genuinely new part
was the loader's name.

What is new: the census generalises Stage 02 to the disc.  23 AIParams objects,
identical in all six GP_MAIN_GAME_* paks, sharing ONE declared-name set of 34
profiles; 782 profile records = 23 x 34; 0 declared names without a record in
their own object.  So "34 AI profiles" is not a Stage-02 fact -- every stage
carries the same 34 and only the values move.  The roster is declared by an
Enumerate_AIs record whose field names are the profile names, the same
declaration-table mechanism that closed DefTables.

Type predicts the field count with exactly two exceptions: Fleet -> 6 fields is
253/253 zero partials; Squad -> 20 fields is 483/529.  The 46-record residual in
full: AI_Test and AI_CraftSquadron_Test, both Type = Squad with only the six base
fields, in all 23 objects.  No profile's shape varies between objects.

New regenerator aiparams_census.py, 45-line artefact, byte-identical across two
runs; the other fourteen verify unchanged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PMRJjbxLqZtsb5Vb7KunPE
This commit is contained in:
Claude (auto)
2026-08-27 21:57:24 +00:00
parent 5c672b11e0
commit 91ba488d47
6 changed files with 230 additions and 10 deletions

View File

@@ -226,15 +226,15 @@ substructures (`sub_823479B8` → `ParentStructureID`), and six camera/fog reade
(`sub_825F2CF0`, `sub_825F2F88`, `sub_8247DFC0`, `sub_823B2620`, `sub_82222E70`,
`sub_822C7480`).
**🔑 The find: `sub_8233C368` reads the AI behaviour table.** `r28`, base
`0x8208583C`, 20 names — **`Enumerate_AIs`**, `FiringLength`, `GuardLength`,
`AutoGuardLength`, `CounterLength`, `MusterLength`, … [[stage-mission-tables]]
owns those *field* names on the data side; **`Enumerate_AIs` appears in no
document, and no reader was known** — the corpus carries the AI tail of
`Maneuver` as 🟡 NEEDS-HUMAN/runtime. It is statically reachable after all.
The same base `0x8208583C` also serves `sub_82338EE0` (97 names,
`Weapon TargetType SpecialWeaponType ReticleType IsCharging …`) — the **weapon**
datasheet loader, likewise not previously named.
**🔑 The find: `sub_8233C368` is the `AIParams` loader.** `r28`, base
`0x8208583C`, 20 names — `Enumerate_AIs`, `FiringLength`, `GuardLength`,
`AutoGuardLength`, `CounterLength`, `MusterLength` and the 14 manoeuvre weights.
⚠️ **Corrected:** I first wrote that this unblocked a NEEDS-HUMAN item.
[[stage-mission-tables]] already had `AIParams` as ✅ static and directly
portable, with every field name; **only the loader was unnamed.** The disc-wide
census that followed is in that document. The same base `0x8208583C` also serves
`sub_82338EE0` (97 names, `Weapon TargetType SpecialWeaponType ReticleType
IsCharging …`) — the **weapon** datasheet loader, likewise not previously named.
**Other unowned blocks the index surfaces** (measured, not investigated):
`sub_822215D0` (205/206, `PGHUD_*` / `PGREMAIN_NUM%d` / `PGTIMER_NUM%d` — HUD

View File

@@ -132,6 +132,52 @@ e.g. `AI_ADAN_CraftSquadron_Ace` fires at 3000.0, guards at 10000.0, musters at
These are exact original values obtained by static RE, so they are usable in the
port directly.
## ✅ `AIParams` across the whole disc, and its loader (2026-08-27)
- **Regenerate:** `python3 tools/re-capture/aiparams_census.py` → [`../data/aiparams-census.txt`](../data/aiparams-census.txt)
The section above measured Stage 02. The disc holds **23** `AIParams` objects,
identically in all six `GP_MAIN_GAME_*` paks, and they share **one roster**:
| | |
|---|---:|
| `AIParams` objects per pak | **23** |
| distinct declared-name sets across them | **1** |
| profiles per object | **34** |
| profile records total | **782** = 23 × 34 |
| declared names with no record in their own object | **0** |
✅ So "34 AI profiles" is not a Stage-02 fact — **every stage carries the same 34
profiles and only the values move.** 🔑 The roster is declared the same way
`DefTables` names its tables: an **`Enumerate_AIs` record whose field names are
the profile names** (see [[archive-naming]] route 2).
### ⚠️ `Type` predicts the field count — with exactly two exceptions
| | |
|---|---|
| `Type = Fleet` → 6 fields | **253 / 253**, zero partials |
| `Type = Squad` → 20 fields | **483 / 529** |
The 46-record residual, in full: **`AI_Test` and `AI_CraftSquadron_Test`** — both
`Type = Squad` but carrying only the six base fields, in all 23 objects
(2 × 23 = 46). They are the family's `_Test` templates, the same trap the stage
tables sprang before. **No profile's shape varies between objects (0).**
### ✅ The loader: `sub_8233C368`
Found by the base-solver ([[player-tuning-tables]]): `r28`, base `0x8208583C`,
20 names — `Enumerate_AIs`, `FiringLength`, `GuardLength`, `AutoGuardLength`,
`CounterLength`, `MusterLength` and the 14 manoeuvre weights. That is exactly the
field set above, so the loader names the whole schema and nothing else.
> ⚠️ **Correcting my own note from the previous iteration.** I recorded this as
> "the AI behaviour table, which the corpus carried as NEEDS-HUMAN/runtime, is
> statically reachable". **Wrong** — this document already had `AIParams` as ✅
> *"exact original values obtained by static RE, directly portable"*, with all
> 20 field names. The only thing that was actually missing is the **loader's
> name**, plus the disc-wide generalisation above.
## What is still open
* **The phase advance condition.** The stage record declares `Phase_1..3` and