Decode RTINIT movement providers 4 6 and 15

This commit is contained in:
gamer147
2026-07-23 15:43:27 -04:00
parent 52780d92a0
commit c55c5ada4c
10 changed files with 183 additions and 33 deletions

View File

@@ -91,6 +91,27 @@ ROUTINE_BANK_ROLES = (
)
MOVEMENT_PROVIDER_PARAMETER_SCHEMAS = {
4: {
"behavior": "approach_stage_object_slot",
"parameter_fields": {
"movement_parameter_1": "stage_object_slot_index",
},
"parameter_defaults": {
"movement_parameter_1": 0,
},
"parameter_notes": {
"stage_object_slot_index": (
"zero-based index into the current stage's object arrays; "
"shipped explicit values are 1 or 2, with three unwritten "
"cells using the zero/slot-0 default"
),
},
"completion": (
"advance the current step's progress counter after reaching the "
"selected object's tile (or, for a type-6 stage object, its linked "
"exit tile)"
),
},
5: {
"behavior": "approach_destination_tile",
"parameter_fields": {
@@ -102,6 +123,29 @@ MOVEMENT_PROVIDER_PARAMETER_SCHEMAS = {
"destination tile (or its linked type-6 stage-object exit tile)"
),
},
6: {
"behavior": "approach_nearest_enemy",
"parameter_fields": {
"movement_parameter_1": "maximum_target_route_steps",
},
"parameter_notes": {
"maximum_target_route_steps": (
"inclusive route-step radius from the acting entity after "
"SETMVWORK applies offensive-action eligibility; shipped "
"values are 1..7, 10, or 20"
),
},
"target_selection": (
"nearest active entity of another faction within the route-step "
"radius; choose randomly among ties, then approach a reachable "
"tile nearest that enemy; execution also requires the normal-"
"attack bit in offensive_action_scope_masks[0]"
),
"completion": (
"advance the current step's progress counter after producing a "
"valid movement destination toward the selected enemy"
),
},
7: {
"behavior": "approach_injured_ally",
"parameter_fields": {
@@ -197,6 +241,27 @@ MOVEMENT_PROVIDER_PARAMETER_SCHEMAS = {
"destination tile (or its linked type-6 stage-object exit tile)"
),
},
15: {
"behavior": "approach_foreign_magic_pillar",
"parameter_fields": {
"movement_parameter_1": "maximum_target_route_steps",
},
"parameter_notes": {
"maximum_target_route_steps": (
"inclusive route-step radius; shipped values are 2..6"
),
},
"target_selection": (
"nearest active stage object of OBINIT type 2, 3, or 4 (small, "
"medium, or large Magic Pillar) whose runtime state/faction differs "
"from the acting entity; require it to be within the route-step "
"radius, then approach a reachable tile nearest that object"
),
"completion": (
"produce a movement result only when a foreign-controlled Magic "
"Pillar exists within the configured route-step radius"
),
},
}
UNIT_STAT_COLUMNS = (

View File

@@ -371,10 +371,10 @@ 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"] == 5
and meta["decoded_movement_step_count"] == 292
and meta["decoded_movement_parameter_count"] == 758
and meta["decoded_movement_defaulted_parameter_count"] == 7,
check(meta["decoded_movement_provider_count"] == 8
and meta["decoded_movement_step_count"] == 508
and meta["decoded_movement_parameter_count"] == 971
and meta["decoded_movement_defaulted_parameter_count"] == 10,
"RTINIT reports selector-specific semantic coverage")
check([
layout["bank_index"]
@@ -434,6 +434,26 @@ def test_real_routine_banks() -> None:
and provider_12["destination_tile_x"] == 11
and provider_12["destination_tile_y"] == 68,
"RTINIT joins RTN_M012's route-mode destination semantics")
provider_4 = by_id[5]["movement_steps"][0]
check(provider_4["movement_provider_selector"] == 4
and provider_4["provider_behavior"] == "approach_stage_object_slot"
and provider_4["stage_object_slot_index"] == 1,
"RTINIT joins RTN_M004's stage-object slot semantics")
provider_4_default = by_id[17]["movement_steps"][1]
check(provider_4_default["movement_provider_selector"] == 4
and provider_4_default["stage_object_slot_index"] == 0
and "movement_parameter_1" not in provider_4_default,
"RTINIT projects RTN_M004's implicit stage-object slot zero")
provider_6 = by_id[6]["movement_steps"][0]
check(provider_6["movement_provider_selector"] == 6
and provider_6["provider_behavior"] == "approach_nearest_enemy"
and provider_6["maximum_target_route_steps"] == 5,
"RTINIT joins RTN_M006's enemy-search radius")
provider_15 = by_id[2]["movement_steps"][0]
check(provider_15["movement_provider_selector"] == 15
and provider_15["provider_behavior"] == "approach_foreign_magic_pillar"
and provider_15["maximum_target_route_steps"] == 3,
"RTINIT joins RTN_M015's foreign Magic Pillar search radius")
check("provider_behavior" not in movement
and "destination_tile_x" not in movement,
"RTINIT does not leak provider-specific meanings onto undecoded selectors")

View File

@@ -33,6 +33,11 @@ def test_load_and_lint():
check(entries[0xaba96]["name"] == "pathfinding_remaining_route_steps"
and entries[0xcc9f1]["name"] == "movement_search_mode",
"movement-search reachability state is curated")
check(entries[0xbf6fe]["name"] == "pathfinding_filtered_route_scores"
and entries[0xcc9f4]["name"] == "offensive_action_scope_masks",
"movement target filtering and offensive scope are curated")
check(entries[0xaba64]["name"] == "stage_object_runtime_flags",
"stage-object targeting flags are curated")
check(entries[0xb240e]["name"] == "pathfinding_movement_costs",
"movement-cost work grid is curated")
# lint clean against a permissive address universe (curated addrs are self-consistent)