diff --git a/docs/name-resolution.md b/docs/name-resolution.md index 6852fb0..a2c997e 100644 --- a/docs/name-resolution.md +++ b/docs/name-resolution.md @@ -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 diff --git a/docs/phase-b-framework.md b/docs/phase-b-framework.md index f5af8b6..e740434 100644 --- a/docs/phase-b-framework.md +++ b/docs/phase-b-framework.md @@ -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: diff --git a/docs/script-inventory.md b/docs/script-inventory.md index b5d13e0..63c4439 100644 --- a/docs/script-inventory.md +++ b/docs/script-inventory.md @@ -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 diff --git a/docs/tools-reference.md b/docs/tools-reference.md index cd3027b..cdc59a8 100644 --- a/docs/tools-reference.md +++ b/docs/tools-reference.md @@ -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 [OUTNAME]` | `.BIN` → `build/data/.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 [OUTNAME] [--mode …]` | `
.BIN` plus EBINIT/SKINIT for CCINIT, OBINIT for STINIT, `build/callscript-names.json` for RTINIT/SCINIT, `build/scjump-decisions.json` for SCINIT, matching `.BIN` when supported, and `build/globals.json` → `build/data/.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
[OUTNAME] [--mode …]` | `
.BIN` plus EBINIT/SKINIT for CCINIT, OBINIT for STINIT, `build/callscript-names.json` for RTINIT/SCINIT, `build/scjump-decisions.json` for SCINIT, matching `.BIN` when supported, and `build/globals.json` → `build/data/.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
[--build] [--limit N] [--message-query REGEX]` | `build/data/
.json` + corpus → stdout; with `--build`, `build/data/
-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}` | diff --git a/docs/vm-mapping-plan.md b/docs/vm-mapping-plan.md index e871858..3c4188d 100644 --- a/docs/vm-mapping-plan.md +++ b/docs/vm-mapping-plan.md @@ -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)* diff --git a/tools/extract_init.py b/tools/extract_init.py index 72a6018..004f2c9 100644 --- a/tools/extract_init.py +++ b/tools/extract_init.py @@ -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 = ( diff --git a/tools/test_extract_init.py b/tools/test_extract_init.py index fcf77b2..c1519a1 100644 --- a/tools/test_extract_init.py +++ b/tools/test_extract_init.py @@ -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