Decode RTINIT providers 17 and 52

This commit is contained in:
gamer147
2026-07-23 16:54:39 -04:00
parent 90c7874190
commit 8574673d53
7 changed files with 88 additions and 23 deletions

View File

@@ -445,7 +445,7 @@ empty reserved banks. Structural and consumer-proven meanings live in `vm-map/gl
parameter names remain as raw provenance while each RTN_M/RTN_B consumer proves its tagged schema.
The provider-specific join now covers
RTN_M001/003/004/005/006/007/008/010/011/012/013/014/015/051: 858 movement steps, 974 semantically
RTN_M001/003/004/005/006/007/008/010/011/012/013/014/015/017/051/052: 1,027 movement steps, 974 semantically
consumed populated parameters, thirteen explicit zero defaults, and three authored-but-unread
parameter cells. RTN_M005/011/012 read banks 2/3 as
`destination_tile_x` / `destination_tile_y` and approach that exact map tile, incrementing the current
@@ -516,6 +516,11 @@ target tile's movement cost to fit current FS, ranks candidates by descending re
with randomized ties, and accepts the first candidate for which SETROUTE constructs a path. Success
advances progress and returns state 1, so FIELD performs movement rather than battle.
RTN_M017 is the low-HP finisher variant of M003. It uses the same normal-attack, MVSEEK, SETMVWORK,
current-FS, and SETROUTE eligibility pipeline, but orders the surviving foreign targets by ascending
current HP instead of descending remaining-route score. It attempts routes in that order and returns
movement state 1 for the first target that yields a path.
RTN_M051 is a parameterless immediate-attack selector. ATSEEK supplies a one-based range band for each
enemy tile; CALCSCOPE supplies the normal-attack/equipped-skill bits and their attack elements at each
band. M051 keeps active foreign targets for which at least one allowed action has positive effectiveness
@@ -525,6 +530,12 @@ the effective actions in the tracked closest band, writing zero for a normal att
id. Success stores `target_entity_index` and `entity_selected_action_ids[acting_entity_index]`, advances
progress, and returns state 2 so FIELD enters battle without producing a movement route.
RTN_M052 is M051's low-HP immediate-attack variant. It applies the same active-foreign-target,
range-mask, target-defense-element, and positive-effectiveness tests, but keeps only targets tied at the
lowest current HP and randomizes among those ties. After choosing the target, it reloads that target's
actual ATSEEK range band, randomizes among the effective normal attack/equipped skills enabled at that
band, stores the target and action, and returns immediate-battle state 2 without movement.
MVSEEK's mode contract is also now explicit. Mode 0 replaces the input coordinate with the current
entity tile and seeds the origin with movement+1, producing the movement-limited reachability grid.
Modes 1/2 retain the caller coordinate and seed it with 9999, producing a broad target-distance grid;
@@ -536,9 +547,9 @@ by M006/007/015.
`movement_parameter_1..4`, and top-level `movement_provider_parameter_schemas` records the reusable
mapping, target-selection rules, zero/unwritten behavior, and authored fields proven unread by their
provider. All 977 populated movement-parameter cells are now accounted for: 974 semantic inputs and
three explicit residue cells. The five used providers still without schemas
(M002/009/017/052/061) have no populated parameter cells, so their remaining work is behavior
decoding rather than column semantics. The supporting runtime joins are now curated too:
three explicit residue cells. The three used providers still without schemas (M002/009/061) have no
populated parameter cells, so their remaining work is behavior decoding rather than column semantics.
The supporting runtime joins are now curated too:
`entity_runtime_flags`,
`entity_faction_ids`, `entity_tile_x`/`entity_tile_y`, the fourteen-column `entity_effective_stats`,
current HP/SP/FS, `stage_object_runtime_flags`, `movement_search_mode`,
@@ -597,10 +608,10 @@ The v1 map labels *shapes and tables*; the next increments add *meaning*, cheape
machine-readable investigation surfaces and semantic joins; EBINIT's populated schema is fully named,
STINIT's joined object/enemy payloads are decoded, and CCINIT's 71 class-change rules expose predicates
and effects. SCINIT closes the progression decision-to-scene join, and RTINIT's twenty movement/battle
banks are structurally decoded with every populated movement-parameter cell classified. Next decode
the five remaining behavior-only RTN_M providers by evidence density, beginning with the closely
related M017 and M052; never assign one universal meaning to a parameter bank whose
meaning varies by provider selector.
banks are structurally decoded with every populated movement-parameter cell classified and 1,027 of
1,043 movement steps joined to provider behavior. Next close the tiny behavior-only RTN_M002/009/061
tail; never assign one universal meaning to a parameter bank whose meaning varies by provider
selector.
2. **Extend message-table joins beyond the completed ITMES/SKMES pair** (`VIMES`, other id dispatchers, …)
and fold in other `set-string`/`copy-to-global` writers not covered by the `*INIT` set.
3. **Label 2D record tables by their readers** — cross-reference which scripts read each

View File

@@ -788,14 +788,15 @@ resolved and the full overwrite history retained. RTINIT is now the seventh shap
1000-by-20 banks produce 172 routine sets, 1,043 movement steps, and fourteen battle steps with RTN_M/RTN_B
provider joins, activation/progress/story gates, six explicit reserved banks, and complete overwrite
history. Provider-tagged decoding now covers movement providers 1, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13,
14, 15, and 51: progress-only steps, stage-object slots, coordinate destinations (including M012's
14, 15, 17, 51, and 52: progress-only steps, stage-object slots, coordinate destinations (including M012's
foreign-entity route mask), enemy/ally and Magic Pillar searches, resource-gated Healing Feather
selection, cyclic waypoints, faction-traversable terrain, retreat, normal-attack routing, and immediate
element-effective target/action selection. This covers 858 steps and classifies every one of the 977
element-effective target/action selection, including low-current-HP variants of both attack paths. This
covers 1,027 steps and classifies every one of the 977
authored movement-parameter cells: 974 are semantic inputs, while the three cells attached to M001/M008
are retained as provider-unread residue; thirteen unwritten zero defaults are projected separately. The
five remaining used providers (M002/009/017/052/061) are behavior-only in the shipped table. Decode the
closely related M017/M052 pair next.
three remaining used providers (M002/009/061) are behavior-only in the shipped table and account for
only sixteen movement steps. Close that tiny tail next.
Once the natural spine and first gameplay loop are trustworthy, broaden in independent tracks:

View File

@@ -100,15 +100,15 @@ movement banks consumed by MVRTN/RTN_M providers and ten battle banks consumed b
The generated 172 routine-set records assemble 1,043 movement steps and fourteen battle steps, join
provider selectors to script names, retain all 29 overwritten cells, and keep the six reserved empty
banks visible. Selector-specific schemas now cover
RTN_M001/003/004/005/006/007/008/010/011/012/013/014/015/051: progress-only steps, stage-object slots,
RTN_M001/003/004/005/006/007/008/010/011/012/013/014/015/017/051/052: progress-only steps, stage-object slots,
coordinate destinations, enemy/ally and Magic Pillar searches, resource-threshold Healing Feather
search, cyclic waypoints, faction-traversable terrain, retreat, reachable normal-attack routing, and
immediate element-effective target/action selection. The generated join covers 858 steps and accounts
for all 977 authored movement parameters: 974 semantic inputs plus three M001/M008 cells proven unread
by their providers. Thirteen
immediate element-effective target/action selection, including low-current-HP variants of both attack
paths. The generated join covers 1,027 steps and accounts for all 977 authored movement parameters:
974 semantic inputs plus three M001/M008 cells proven unread by their providers. Thirteen
unwritten zero defaults are projected separately while the structurally named raw banks remain intact.
The remaining five used providers have no populated parameter cells and therefore need behavior
decoding, not additional column semantics.
The remaining three used providers (M002/009/061, sixteen steps total) have no populated parameter
cells and therefore need behavior decoding, not additional column semantics.
### Message/string tables (`*MES`)
`ITMES` (64 KB — item text), `VIMES` (43 KB), `EIMES` (37 KB), `SKMES` (31 KB — skill

View File

@@ -55,7 +55,7 @@ All opcode knowledge (ABI, semantics, provenance, `depends_on`) is hand-edited *
|---|---|---|---|
| `extract_phase2.py` | Batch: disassembly + text corpora for every script. | `extract_phase2.py` | corpus → `build/disasm/*.asm`, `build/text/{dialogue.jsonl,strings.jsonl,*.strings.txt}`, `build/manifest.json` |
| `extract_message_table.py` | Discover a repeated global-id dispatch chain such as ITMES/SKMES, reconstruct player-facing title/description lines (including furigana surface text and readings), and emit an ID-keyed message table with bytecode provenance. | `extract_message_table.py <MES> [OUTNAME]` | `<MES>.BIN``build/data/<OUTNAME>.json` |
| `extract_init.py` | Parse a `*INIT` data source (auto-detects name / numeric / footer / mixed / rules / dispatch / banked shape). Name tables infer their reserved record span, preserve sparse one-based runtime ids, distinguish lookup bases from first written cells, statically evaluate direct and negative-value writes, and separate parallel `fields` from linked row-major `record_fields`; when flat global ranges overlap, a parallel base established by other records wins over a coincidental row-table cell calculation. Mixed tables recover selector-dispatched records, condition strings, scalars, preallocated buffer cells, consumer-confirmed strides, and length-prefixed footer arrays; STINIT additionally assembles confirmed buffers into `object_placements` and `enemy_spawns`, joins object type names and available descriptions from OBINIT, and exposes consumer-proven tagged payloads (teleport, treasure, card, initial faction, non-triggering hazard/barrier faction, and OBINIT-gated initial object state), preserves engine-dead type-27 writes under `ignored_payload_fields`, and exposes reinforcement schedules and first-clear-only enemy gates. Rules mode decodes CCINIT's source-ordered class-change predicates and output accumulators, joining EBINIT unit names, SKINIT skill names, titles, named stat bonuses, cost deltas, and applied-state slots. Dispatch mode decodes SCINIT's paired decision-to-packed-scene and authored-chapter arrays, preserving source-order overwrites, resolving SYS4INI script names, and cross-checking chapter tags against decoded SCJUMP paths. Banked mode decodes RTINIT's twenty parallel 1000-by-20 movement/battle routine banks, retains all assignments and overwrites, assembles final per-slot steps, resolves provider selectors to RTN_M/RTN_B scripts, and applies selector-scoped schemas where proven. Current schemas cover RTN_M001/003/004/005/006/007/008/010/011/012/013/014/015/051, including progress-only, object-slot, coordinate, enemy/ally and Magic Pillar search, Healing Feather, waypoint, faction-terrain, retreat, reachable normal-attack routing, and immediate target/action-selection behavior. Behavior-only schemas such as M003/M051 publish an empty `parameter_fields` mapping while still joining `provider_behavior`, target selection, action selection, and completion rules. Provider defaults such as M004's unwritten slot 0, M010's zero/HP resource index, and M013's any-foreign-faction filter are projected explicitly and counted separately from populated source cells. Authored cells proven unread by M001/M008 remain under per-step `ignored_movement_parameters` and contribute to top-level `ignored_movement_parameter_count`; they are not silently discarded or assigned invented meanings. Raw provider banks remain intact, and top-level `movement_provider_parameter_schemas` documents the projection. ITINIT and SKINIT join ITMES/SKMES messages. Top-level `field_semantics` maps raw keys to canonical global/column names, while each record's `semantic_fields` is the generated name-keyed join; complete footer copies map to a row and expose its values without the raw provenance wrapper. Raw keys and unresolved tagged payload cells remain provenance. OUTNAME accepts a stem or one `.json` suffix and rejects paths. Refreshes the generated data index. | `extract_init.py <TABLE> [OUTNAME] [--mode …]` | `<TABLE>.BIN` plus EBINIT/SKINIT for CCINIT, OBINIT for STINIT, `build/callscript-names.json` for RTINIT/SCINIT, `build/scjump-decisions.json` for SCINIT, matching `<MES>.BIN` when supported, and `build/globals.json``build/data/<OUTNAME>.json`, `build/data/README.md` |
| `extract_init.py` | Parse a `*INIT` data source (auto-detects name / numeric / footer / mixed / rules / dispatch / banked shape). Name tables infer their reserved record span, preserve sparse one-based runtime ids, distinguish lookup bases from first written cells, statically evaluate direct and negative-value writes, and separate parallel `fields` from linked row-major `record_fields`; when flat global ranges overlap, a parallel base established by other records wins over a coincidental row-table cell calculation. Mixed tables recover selector-dispatched records, condition strings, scalars, preallocated buffer cells, consumer-confirmed strides, and length-prefixed footer arrays; STINIT additionally assembles confirmed buffers into `object_placements` and `enemy_spawns`, joins object type names and available descriptions from OBINIT, and exposes consumer-proven tagged payloads (teleport, treasure, card, initial faction, non-triggering hazard/barrier faction, and OBINIT-gated initial object state), preserves engine-dead type-27 writes under `ignored_payload_fields`, and exposes reinforcement schedules and first-clear-only enemy gates. Rules mode decodes CCINIT's source-ordered class-change predicates and output accumulators, joining EBINIT unit names, SKINIT skill names, titles, named stat bonuses, cost deltas, and applied-state slots. Dispatch mode decodes SCINIT's paired decision-to-packed-scene and authored-chapter arrays, preserving source-order overwrites, resolving SYS4INI script names, and cross-checking chapter tags against decoded SCJUMP paths. Banked mode decodes RTINIT's twenty parallel 1000-by-20 movement/battle routine banks, retains all assignments and overwrites, assembles final per-slot steps, resolves provider selectors to RTN_M/RTN_B scripts, and applies selector-scoped schemas where proven. Current schemas cover RTN_M001/003/004/005/006/007/008/010/011/012/013/014/015/017/051/052, including progress-only, object-slot, coordinate, enemy/ally and Magic Pillar search, Healing Feather, waypoint, faction-terrain, retreat, reachable normal-attack routing, and immediate target/action-selection behavior, with low-current-HP variants of both attack paths. Behavior-only schemas such as M003/M017/M051/M052 publish an empty `parameter_fields` mapping while still joining `provider_behavior`, target selection, action selection, and completion rules. Provider defaults such as M004's unwritten slot 0, M010's zero/HP resource index, and M013's any-foreign-faction filter are projected explicitly and counted separately from populated source cells. Authored cells proven unread by M001/M008 remain under per-step `ignored_movement_parameters` and contribute to top-level `ignored_movement_parameter_count`; they are not silently discarded or assigned invented meanings. Raw provider banks remain intact, and top-level `movement_provider_parameter_schemas` documents the projection. ITINIT and SKINIT join ITMES/SKMES messages. Top-level `field_semantics` maps raw keys to canonical global/column names, while each record's `semantic_fields` is the generated name-keyed join; complete footer copies map to a row and expose its values without the raw provenance wrapper. Raw keys and unresolved tagged payload cells remain provenance. OUTNAME accepts a stem or one `.json` suffix and rejects paths. Refreshes the generated data index. | `extract_init.py <TABLE> [OUTNAME] [--mode …]` | `<TABLE>.BIN` plus EBINIT/SKINIT for CCINIT, OBINIT for STINIT, `build/callscript-names.json` for RTINIT/SCINIT, `build/scjump-decisions.json` for SCINIT, matching `<MES>.BIN` when supported, and `build/globals.json``build/data/<OUTNAME>.json`, `build/data/README.md` |
| `init_table_profile.py` | Build the static investigation surface for an extracted name/numeric/mixed/rules/dispatch/banked table: per-scalar/string/array-cell/footer-array population and value distributions, representative records, and direct opcode/script consumers. Name tables also report message coverage; rule tables summarize covered units, titled and level-independent rules, threshold/slot distributions, and skill awards; dispatch tables summarize assignments, overwrites, script-name resolution, and SCJUMP chapter agreement; banked tables summarize populated/reserved banks, movement/battle steps and providers, selector-specific semantic coverage, and overwrite conflicts. `--message-query REGEX` shows every matching name/message beside all populated fields for semantic correlation. Findings are evidence only; confirmed meanings go in `vm-map/globals.toml`. | `init_table_profile.py <TABLE> [--build] [--limit N] [--message-query REGEX]` | `build/data/<TABLE>.json` + corpus → stdout; with `--build`, `build/data/<TABLE>-field-profile.{json,md}` |
| `test_extract_init.py`, `test_init_table_profile.py` | Regression checks for sparse one-based, mixed selector-dispatched, CCINIT rule, SCINIT dispatch, and RTINIT banked extraction; MES reconstruction/joins; footer-array accounting and semantic projection; EBINIT/SKINIT/OBINIT definition joins; STINIT object/enemy joins and tagged-payload behavior; overwrite/provider joins; and field/message/rule/dispatch/banked profiling. | run each directly | — |
| `global_map.py` | Build the partial global-variable name map from static evidence. | `global_map.py` | corpus + `build/data/``build/global-var-map.{json,md}` |

View File

@@ -57,9 +57,9 @@
- [x] **2.3 — Extract `STINIT`'s 74 sparse stage records.** The mixed mode identifies the dominant `scjump_progress_a` dispatch, recovers 29 preallocated buffer layouts (including six consumer-confirmed row strides), and keeps four condition strings, six scalars, fixed-buffer writes, and all 1,396 footer-array copies separated by stage id. Profiles supply population/value and direct-consumer evidence. Header/map semantics cover conditions, BGM, turn/replay/clear-reward settings, and map texture overrides. The object join assembles 2,312 placements with type/position/gates, OBINIT names and available descriptions, 604 reinforcement schedules, and typed initial-faction, teleport, treasure, card-list, non-triggering-faction, and initial-object-state payloads; FIELD's dedicated special-spawn path proves the final three populated type-27 tagged writes are engine-dead, so they remain visible as ignored provenance rather than unresolved semantics. The 30-cell enemy family contributes 1,378 joined spawns with unit/faction, placement, difficulty/story gates, level scaling, weighted selection, difficulty-specific movement/battle routine sets, and 485 first-clear-only gates. Raw address views remain alongside generated `semantic_fields`.
- [x] **2.3a — Extract `CCINIT`'s 71 class-change rules.** Rules mode preserves source-order guards and detects the unit id, minimum level, clear applied-state slot, selected title/level, deployment-cost delta, named fourteen-stat bonuses, awarded SKINIT skills, and state slot set by each rule. EBINIT/SKINIT definition joins and the common global semantic projection coexist with raw addresses. CALCCC/ADDEXP establish the apply/report ABI; EVOLVE explains the two level-independent empty-title Lily rules. The generated profile covers 33 units, 69 titled rules, 30 skill awards, three used promotion slots, and 19 populated output fields.
- [x] **2.3b — Extract `SCINIT`'s scene-dispatch registry.** Dispatch mode recognizes 2,179 alternating writes to two 10,000-cell arrays, preserves all 710 overwritten decision ids, and emits 1,209 final rows. The primary column maps decisions to 135 packed SYS4INI ids, all resolved to numbered SC scripts; the parallel column is authored chapter metadata. All 847 live SCJUMP decisions join to rows and 844 final chapter tags agree with the independently decoded paths; three legacy/stale mismatches remain explicit.
- [x] **2.3c — Extract `RTINIT`'s routine-step banks.** Banked mode recognizes twenty parallel 1000-by-20 tables and emits 172 sparse routine-set rows with all 3,336 source assignments and 3,307 final cells. Movement banks join 1,043 steps to 19 used RTN_M providers (22 dispatchable); battle banks join fourteen steps to all four RTN_B providers. Activation percentages, progress gates, and required/forbidden story flags are consumer-proven; six empty banks remain explicit. RTN_M001/003/004/005/006/007/008/010/011/012/013/014/015/051 add selector-specific progress, object-slot, coordinate, enemy/ally and object search, Healing Feather, waypoint, faction-terrain, retreat, normal-attack routing, and target/action selection semantics to 858 steps. All 977 populated movement-parameter cells are classified: 974 semantic inputs and three M001/M008 cells proven unread; thirteen unwritten defaults are projected separately while the generic raw banks remain intact.
- [x] **2.3c — Extract `RTINIT`'s routine-step banks.** Banked mode recognizes twenty parallel 1000-by-20 tables and emits 172 sparse routine-set rows with all 3,336 source assignments and 3,307 final cells. Movement banks join 1,043 steps to 19 used RTN_M providers (22 dispatchable); battle banks join fourteen steps to all four RTN_B providers. Activation percentages, progress gates, and required/forbidden story flags are consumer-proven; six empty banks remain explicit. RTN_M001/003/004/005/006/007/008/010/011/012/013/014/015/017/051/052 add selector-specific progress, object-slot, coordinate, enemy/ally and object search, Healing Feather, waypoint, faction-terrain, retreat, normal-attack routing, and target/action selection semantics—including low-current-HP variants of both attack paths—to 1,027 steps. All 977 populated movement-parameter cells are classified: 974 semantic inputs and three M001/M008 cells proven unread; thirteen unwritten defaults are projected separately while the generic raw banks remain intact.
- [x] **2.4 — Partial global-var map BUILT + wired into the disassembler.** `tools/global_map.py``build/global-var-map.{json,md}` (16,354/49,435 globals labelled: string tables, `*INIT` field arrays, 122 record tables w/ strides, current-entity index pointers). `sys4load` renders the labels inline (`=rec[s30]`, `=current-entity-index?`). See `docs/name-resolution.md`.
- [ ] **2.5 — Grow the global-var map (future, incremental).** Static first: with RTINIT's populated movement-parameter tail and high-use M003/M051 behavior now closed, decode behavior-only M002/009/017/052/061 (starting with the related M017/M052 pair), fold in remaining `*MES` writers, and label other 2D record tables by their reader scripts. Then Frida to name *which stat* each unresolved field is. Full detail: `docs/name-resolution.md` → "Future step — growing the map". Packed `call-script` ids and SCJUMP decision-to-scene dispatch are resolved; see `docs/name-resolution.md` #1 and `docs/scjump-progression.md`.
- [ ] **2.5 — Grow the global-var map (future, incremental).** Static first: with RTINIT's populated movement-parameter tail plus M003/M017/M051/M052 attack behavior now closed, decode the tiny behavior-only M002/009/061 tail (sixteen used steps total), fold in remaining `*MES` writers, and label other 2D record tables by their reader scripts. Then Frida to name *which stat* each unresolved field is. Full detail: `docs/name-resolution.md` → "Future step — growing the map". Packed `call-script` ids and SCJUMP decision-to-scene dispatch are resolved; see `docs/name-resolution.md` #1 and `docs/scjump-progression.md`.
## Phase 3 — Name the unnamed opcodes *(top ~20 BEFORE Phase 4; the rest on demand)*

View File

@@ -367,6 +367,24 @@ MOVEMENT_PROVIDER_PARAMETER_SCHEMAS = {
"Pillar exists within the configured route-step radius"
),
},
17: {
"behavior": "route_toward_lowest_hp_reachable_normal_attack_target",
"parameter_fields": {},
"target_selection": (
"require a usable normal attack, build the acting entity's "
"movement-limited reach grid, and retain active foreign-faction "
"entities whose occupied tile remains element-effective after "
"SETMVWORK filtering and costs no more than current FS; sort by "
"current HP ascending, preserving source order among ties, then "
"use the first candidate for which SETROUTE produces "
"a route"
),
"completion": (
"advance the current step's progress counter and produce movement "
"result state 1 after routing toward the lowest-current-HP "
"reachable normal-attack target"
),
},
51: {
"behavior": "select_effective_attack_target_and_action",
"parameter_fields": {},
@@ -391,6 +409,29 @@ MOVEMENT_PROVIDER_PARAMETER_SCHEMAS = {
"movement route is produced"
),
},
52: {
"behavior": "select_lowest_hp_effective_attack_target_and_action",
"parameter_fields": {},
"target_selection": (
"require a usable nonzero attack-range band, scan active foreign-"
"faction entities inside the ATSEEK range grid, and retain only "
"the equal-lowest-current-HP targets for which at least one "
"allowed normal-attack/equipped-skill element has positive "
"effectiveness against the target's defense element; choose "
"randomly among those HP ties"
),
"action_selection": (
"reload the chosen target's actual ATSEEK range band, collect the "
"effective actions enabled there (0 means normal attack; nonzero "
"values are equipped skill ids), choose randomly, and store both "
"the target entity and selected action"
),
"completion": (
"advance the current step's progress counter and produce immediate-"
"battle result state 2 when a target/action pair is selected; no "
"movement route is produced"
),
},
}
UNIT_STAT_COLUMNS = (

View File

@@ -371,8 +371,8 @@ def test_real_routine_banks() -> None:
and len(meta["used_battle_provider_selectors"]) == 4
and len(meta["record_field_columns"]) == 117,
"RTINIT assembles every populated movement and battle step")
check(meta["decoded_movement_provider_count"] == 14
and meta["decoded_movement_step_count"] == 858
check(meta["decoded_movement_provider_count"] == 16
and meta["decoded_movement_step_count"] == 1027
and meta["decoded_movement_parameter_count"] == 974
and meta["decoded_movement_defaulted_parameter_count"] == 13
and meta["ignored_movement_parameter_count"] == 3,
@@ -498,6 +498,18 @@ def test_real_routine_banks() -> None:
== "select_effective_attack_target_and_action"
and "movement_parameter_1" not in provider_51,
"RTINIT joins RTN_M051's parameterless attack-selection behavior")
provider_17 = by_id[3]["movement_steps"][2]
check(provider_17["movement_provider_selector"] == 17
and provider_17["provider_behavior"]
== "route_toward_lowest_hp_reachable_normal_attack_target"
and "movement_parameter_1" not in provider_17,
"RTINIT joins RTN_M017's low-HP attack-route behavior")
provider_52 = by_id[3]["movement_steps"][0]
check(provider_52["movement_provider_selector"] == 52
and provider_52["provider_behavior"]
== "select_lowest_hp_effective_attack_target_and_action"
and "movement_parameter_1" not in provider_52,
"RTINIT joins RTN_M052's low-HP attack-selection behavior")
undecoded_movement = by_id[2]["movement_steps"][1]
check(undecoded_movement["movement_provider_selector"] == 2
and "provider_behavior" not in undecoded_movement