Tighten event condition target scope mapping

This commit is contained in:
Jan Petykiewicz 2026-04-06 01:11:06 -07:00
commit c1010458f8
9 changed files with 757 additions and 17 deletions

View file

@ -4,6 +4,10 @@ This atlas is the high-level map for RT3 1.06. It is intentionally broader than
each section explains who owns a loop, where it starts, what dispatches it, which state blocks
anchor it, and where control is handed to neighboring subsystems.
Subsystem notes now live under [docs/atlas](/home/jan/projects/rrt/docs/atlas/README.md) for
faster navigation. The longform atlas remains the canonical narrative reference during this
transition.
## CRT and Process Startup
- Roots: `entry` at `0x005a313b`, CRT helpers in the `0x005a2d..0x005ad4..` range, and
@ -938,11 +942,11 @@ anchor it, and where control is handed to neighboring subsystems.
placing a new site. The previously vague side family at `0x006cfcb4` is tighter too: current
evidence now bounds it as a small auxiliary route-entry tracker collection with an allocator at
`0x004a42b0`, a refcount or destroy path at `0x004a4340`, a direct route-entry group-id setter
at `0x00489f80`, a boolean-latch refresh or owner-notify path at `0x00494fb0`, and a
two-endpoint merge or bind helper at `0x00494f00`. That bind side is tighter now too: the
trackers group route entries only when a route-key-like value from `0x0048aa70`, the route-entry
signature word `+0x22e`, and the boolean latch derived from byte `+0x44` all agree. The deeper
handoff under that lane is no longer anonymous either:
at `0x00489f80`, an endpoint-membership probe at `0x00494ed0`, a boolean-latch refresh or
owner-notify path at `0x00494fb0`, and a two-endpoint merge or bind helper at `0x00494f00`.
That bind side is tighter now too: the trackers group route entries only when a route-key-like
value from `0x0048aa70`, the route-entry signature word `+0x22e`, and the boolean latch derived
from byte `+0x44` all agree. The deeper handoff under that lane is no longer anonymous either:
`route_entry_collection_search_path_between_entry_or_coord_endpoints` `0x0049d380` is now
bounded as the internal search core that runs the first candidate sweep, quality gates, and the
later route-extension fallbacks before returning one resolved route-entry id or `-1`. The first
@ -989,14 +993,108 @@ anchor it, and where control is handed to neighboring subsystems.
one linked site's route-entry anchor and display-name buffer. That path is tighter now than just
“bind anchor then touch `0x006cfcb4`”: after the literal-policy-`2` rebuild succeeds it
re-enters `aux_route_entry_tracker_collection_refresh_route_entry_group_membership` `0x004a45f0`,
which can repartition adjacent route-entry tracker groups around the refreshed anchor, rewrite
compatible endpoint slots through `0x004950f0`, and refresh one nearby cached-match payload band
through `0x00495020` before the helper resumes the name-buffer work. The remaining display-name
side still matches the earlier
which can now be described more concretely. Its early prepass at `0x004a4380` can split one
mismatching adjacent subchain into a fresh tracker group; its later helper at `0x004a4ce0` can
transfer one compatible adjacent chain between neighboring groups; and the repair-side helper at
`0x004a4ff0` can reseed a whole route-entry component into a fresh tracker when the old group id
is missing or invalid. The regrouping pass also still rewrites compatible endpoint slots through
`0x004950f0` and refreshes one nearby cached-match payload band through `0x00495020` before the
helper resumes the name-buffer work. The remaining display-name side still matches the earlier
grounded text family: copy the resolved city name when available, append civic suffixes
`Township`, `New`, `Modern`, or `Renaissance`, append `Service Tower` or `Maintenance Facility`
on the linked-instance class branches, and otherwise fall back through the older
`Junction`..`Center` and `Anytown` text families.
The higher owner-refresh side of that same tracker family is tighter now too. The reusable gate
at `0x004a4c00` no longer looks like a stray predicate: it explicitly requires both route-entry
trackers to keep matching cached fields `+0x18/+0x1c/+0x1d/+0x1e` and both route entries to keep
their special side fields `+0x20e/+0x222` unset before adjacent-chain transfer is allowed. The
collection-wide traversal sweep at `0x004a5fc0` is bounded now as the connected-component refresh
owner over tracker field `+0x0c`, with a temporary queue at `[this+0x94]` and direct fallback
into the reseed helper `0x004a4ff0` whenever one neighboring route entry has lost valid tracker
ownership. Above both of those sits `aux_route_entry_tracker_collection_refresh_owner_adjacent_compatible_group_links`
`0x004a6360`, which now reads as the owner-side latch-change refresher invoked from
`0x00494fb0`: it starts from one owner route-entry id, confirms both bound endpoint entries agree
on the boolean class state implied by route-entry byte `+0x44`, and then probes both endpoint
sides for adjacent route-entry groups that can be absorbed through the `0x004a4c00 -> 0x004a4ce0`
gate-and-transfer pair. The sibling query side is bounded now too:
`aux_route_entry_tracker_collection_query_component_label_by_tracker_id` `0x004a6320` is the
dirty-aware accessor for tracker field `+0x0c`, while
`aux_route_entry_tracker_dispatch_route_entry_pair_metric_query` `0x004a65b0` is the remaining
mode-switched lower metric dispatcher beneath the heavier chooser at `0x004a6630`, forwarding
fixed route-entry-pair candidate sets into either `0x004a5280` or `0x004a5900` depending on the
shared hundredths-scaled build-version query
`runtime_query_hundredths_scaled_build_version` `0x00482e00` over `0x006cec74`. The current
caller thresholds `>= 0x67`, `>= 0x68`, `>= 0x69`, and `>= 0x6a` now line up with executable
build values `1.03`, `1.04`, `1.05`, and `1.06`, so this split is no longer best-read as a
time- or era-side cutover at all. That lower split is tighter now too:
`0x004a5280` is the weighted recursive branch with heuristic ordering, per-tracker best-cost
cache `0x006cfcac`, and prune threshold `0x006cfcb0`, while `0x004a5900` is the alternate
recursive neighbor-walk branch that stays within compatible component labels through
`0x004a62c0` and accumulates step and mismatch penalties over route-entry links
`+0x206/+0x20a/+0x20e`. Above both of them,
`aux_route_entry_tracker_query_best_route_entry_pair_metric_with_endpoint_fallbacks`
`0x004a6630` is now bounded as the real chooser: direct fixed-pair query when both entries pass
`0x0048b870`, otherwise endpoint-pair fallback across the two tracker groups.
The adjacent route-style rebuild side is tighter now too: the same build-version family reaches
`placed_structure_rebuild_route_style_candidate_scores_and_peer_links` `0x004101e0`, where build
`1.04+` keeps one `Recycling Plant` stem-specific compatibility branch alive and build `1.05+`
skips one older descriptor-side attenuation fallback. There is also one neighboring world-side
compatibility lane now bounded below the same family: `placed_structure_collect_connected_component_tile_bounds_with_version_gate`
`0x004160c0` skips one older recursive component-bounds walk through `0x00415f20` on build
`1.03+` when scenario field `[0x006cec78+0x46c38]` is already active. The wrapper above that
path is bounded now too: `placed_structure_map_tile_range_to_connected_component_records_with_optional_bounds_refresh`
`0x00416170` walks the caller rectangle, maps tile keys into the component table rooted at
`0x0062ba7c`, and only re-enters `0x004160c0` when the current owner still has no cached bounds
and the local world or scenario suppressors stay clear. The higher neighboring raster side is
tighter too. `world_grid_refresh_projected_rect_sample_band_and_flag_mask` `0x00418610` is the
shared projected-rectangle helper above `world_grid_refresh_flagged_region_float_extrema_and_mean`
`0x00415020`: it refreshes the temporary sample band at `0x0062b7d0`, publishes the surviving
rectangle through `0x0044d410`, and on the single-sample path re-enters
`world_grid_toggle_flagged_mask_bit0_for_nonsentinel_rect_samples` `0x004185a0` to flip mask bit
`0x01` for the corresponding non-sentinel cells. Current grounded callers for `0x00418610` are
the neighboring placed-structure local-runtime helper `0x00418be0` and the heavier placement
validator `0x004197e0`, so this adjacent family now reads more like projected placement or local
raster prep than an unowned generic world-grid scan. The higher owner split is tighter now too.
`placed_structure_build_local_runtime_record_from_candidate_stem_and_projected_scratch`
`0x00418be0` is the broader construction or rebuild lane: resolve one candidate id from a stem,
build projected scratch through `0x00416ec0`, then publish the projected rectangle and validate
its side windows through `placed_structure_publish_projected_runtime_rect_globals_and_validate_side_windows`
`0x00416620`. That publish pass is bounded now too: it stages `0x0062b308/0x0062b30c/0x0062b310`,
validates the rectangle against route-entry coverage through
`route_entry_collection_query_rect_window_passes_entry_type_gate` `0x00494240`, can branch into
the special projected-slot picker `placed_structure_try_select_projected_rect_profile_slot`
`0x00415570`, and refreshes the compact per-cell side tables through
`world_grid_refresh_projected_rect_surface_and_region_byte_tables` `0x00414e10` before the
finished scratch is copied into one queued runtime record and the new record re-enters
`0x00416170` when its rectangle is valid. The smaller sibling
`placed_structure_clone_template_local_runtime_record_for_subject_and_refresh_component_bounds`
`0x00418a60` now reads as the current-subject clone path above the same connected-component and
mask-refresh helpers, returning the cloned local runtime record later stored into `[site+0x24e]`
by `placed_structure_refresh_cloned_local_runtime_record_from_current_candidate_stem`
`0x0040e450`. The higher wrapper above that clone path is bounded now too:
`placed_structure_collection_refresh_local_runtime_records_and_position_scalars` `0x004133b0`
first drains the temporary site-id queue rooted at `0x0062ba64/0x0062ba6c/0x0062ba70` through
`placed_structure_local_runtime_site_id_queue_count` `0x00414480` and
`placed_structure_local_runtime_site_id_queue_pop_next` `0x00413f50`, rebuilding one cloned
local-runtime record per queued placed structure through `0x0040e450`, and only then sweeps all
live placed structures through the side refresh helper
`placed_structure_refresh_local_runtime_position_triplet_and_linked_anchor_followon` `0x0040ee10`.
The last lower side reads are tighter now too. `0x0040e450` first seeds the projected-slot cache
through `placed_structure_cache_projected_rect_profile_slot_id` `0x00414470` before it re-enters
`0x00418a60`, and the broader stem-based builder at `0x00418be0` now has one named optional side
renderer instead of an anonymous callsite:
`placed_structure_render_local_runtime_overlay_payload_from_projected_bounds` `0x00418040`.
The side refresh split is bounded now too. `0x0040ee10` publishes one local position or scalar
triplet through the shared setter `0x00530720`, then tails into
`placed_structure_refresh_linked_site_anchor_position_triplet_for_local_runtime` `0x0040e360`;
that smaller follow-on only runs on the current subtype-`1`, class-`3`, linked-site branch, and
recomputes one local-runtime triplet from the linked peer's route-entry anchor when that anchor
is still live. The heavier sibling above that side refresh is bounded now too:
`placed_structure_set_world_coords_and_refresh_local_runtime_side_state` `0x0040eba0` is the
world-coordinate mutation helper that recomputes `[site+0x388]` and `[site+0x38c]`, rewrites the
world-grid owner mapping through `0x0042c9f0` and `0x0042c9a0`, updates the subtype-`4`
proximity-bucket family when needed, rebuilds the same local position or scalar triplet, and
then tails into the linked-site anchor follow-on at `0x0040e360`.
The sibling policy-`1` side is tighter now too. The constructor lane no longer stops at “one
linked site id at `[site+0x2a8]`”: the subtype-`1` branch in
`placed_structure_construct_entry_from_candidate_and_world_args` `0x0040f6d0` now clearly
@ -1026,7 +1124,14 @@ anchor it, and where control is handed to neighboring subsystems.
fast pass stamps a refresh tick at `[company+0x0d3e]`, clears and repopulates the
placed-structure-side cache cells addressed through `[site+0x5bd][company_id]`, marks the
eligible linked transit sites for that company, allocates one `0x0d`-stride peer table for each
eligible site, and fills those peer rows from the route-side sweep through `0x004a6630`. The
eligible site, and fills those peer rows from
`aux_route_entry_tracker_query_best_route_entry_pair_metric_with_endpoint_fallbacks`
`0x004a6630`. That helper no longer reads as one anonymous route sweep: it either uses the fixed
pair directly or falls back across tracker endpoint combinations before returning the winning
route-entry id, one route-step count, and one companion mismatch count. The fast cache now reads
more cleanly too: peer-record dword `+0x05` stores that step count, while float `+0x09` stores
the normalized continuity share derived from `(steps - mismatches) / max(steps, 1)`, not a raw
delta-per-step ratio. The
adjacent timed wrapper `company_service_linked_transit_site_caches` `0x00409720` now shows the
cadence too: `0x004093d0` is the shorter-interval refresh, while the older heavier sibling at
`0x00407bd0` was only revisited on the longer interval.
@ -1295,8 +1400,94 @@ anchor it, and where control is handed to neighboring subsystems.
diverting the deeper region worker into alternate logic. The `319` lane itself is no longer the
open structural gap; it now clearly owns chairman-profile slot seeding, profile-record
materialization, a shell editor surface over the same local record family, and a separate
live-company presentation path through the company-list window. The remaining gaps on this lane
are therefore narrower than before: the local slot records are rooted at `[world+0x69d8]`,
live-company presentation path through the company-list window. The later interior order of that
same `319` lane is tighter now too: after the route-entry collection refresh on `0x006cfca8` it
refreshes the auxiliary route-entry tracker collection `0x006cfcb4`, then runs
`placed_structure_collection_refresh_local_runtime_records_and_position_scalars` `0x004133b0`,
then a flagged world-grid cleanup sweep through `0x00448af0/0x00533fe0`, and only after that the
later route-entry post-pass at `0x00491c20`. The same later lane now also reaches a separate
event-side runtime branch: the live event collection at `0x0062be18` re-enters
`scenario_event_collection_refresh_runtime_records_from_packed_state` `0x00433130`, which in
turn materializes each live event record through
`scenario_event_refresh_runtime_record_from_packed_state` `0x0042db20`. Current shell-side xrefs
now tighten that event branch too: the first rebuilt linked row family under `0x0042db20` aligns
with the standalone condition list later queried by `EventConditions.win`, while the second
rebuilt family aligns with the four grouped effect lists later deep-copied through
`scenario_event_clone_runtime_record_deep_copy` `0x0042e050` during event duplication and effect
staging. The condition side is tighter now too: the tiny helper cluster
`0x0042df30/0x0042df70/0x0042dfb0/0x0042dff0` is no longer just "some adjacent list scans".
Current evidence bounds it as four predicates over the standalone `0x1e`-row condition list,
testing class bits `0x01`, `0x02`, `0x04`, or any of those bits in the static table
`0x005f3e04 + id*0x81`, with special fallback checks through event fields `[event+0x7f9]`,
`[event+0x7fa]`, and `[event+0x7f0] == 0x63`. The shell side is tighter too: vtable slot
`0x005d0cd8` now binds `shell_event_conditions_window_handle_message` `0x004d59e0`, and vtable
slot `0x005d0cf8` binds `shell_event_effects_window_handle_message` `0x004d7060`. The effects
side is tighter too: the lower helper trio is no longer anonymous. `0x004d5d00` now reads as the
effect-type selector refresh under control family `0x4fb2`, `0x004d5f50` reads as the selected
effect parameter-row repaint, `0x004d6090` is the heavier staged-effect editor refresh over the
`0x4fc7/0x4fce/0x4ff6/0x4ff9/0x4ffc/0x5041/0x5044/0x5046/0x5047` bands, and `0x004d67f0`
commits the current editor state back into the staged effect row at `[this+0x78]`. The verb side
is tighter now too: `shell_open_event_conditions_modal_and_return_result` `0x004d9dc0` and
`shell_open_event_effects_modal_and_return_result` `0x004d9e40` are the shared modal openers
above the two editor windows; `0x004da640`, `0x004da700`, and `0x004d9ed0` now read as the add,
edit, and remove verbs for standalone condition rows; `0x004da7c0`, `0x004da860`, and
`0x004da920` are the matching add, edit, and remove verbs for grouped effect rows; and
`0x004d8120` is now the heavier condition-row list panel refresh those condition-side verbs
re-enter after mutation. The conditions-side refresh split is tighter too: `0x0042d700`
aggregates standalone condition-list class or modifier flags, `0x0042d740` aggregates grouped
effect-row type flags for one selected grouped list, `0x004d9970` owns the condition-class
summary and grouped-row status bands, `0x004d77b0` owns the grouped summary-band affordance gate
for `0x4fed..0x4ff0` when selector `0x5000` lands on `0x5002`, `0x004d9d10` owns the smaller
grouped-effect territory-target affordance on control `0x500b`, `0x004d9f50` owns the selected-event mode
strip and summary text panels, and `0x004d9390` is the mode-dependent detail-row switch beneath
that strip. `0x004da0f0` is tighter too: selector `0x5001` now has the strongest current
RT3.lng fit as the condition-side `Test against...` mode above `0x004d9970`, while selector
`0x5002` has the strongest current fit as the grouped-effect-side `Apply effects...` mode.
That `0x5002` branch now clearly builds control `0x5014` from RT3.lng `1160..1164` as `to the
company/player/player (i.e. chairman)/territory for which the condition is TRUE` before
enabling the adjacent `0x5005`, `0x500a`, and `0x5014..0x501c` family. The strongest current
RT3.lng fit for the remaining visible target-scope strip is now `0x5015 = to the whole game`,
`0x5016..0x5018 = to all/human/AI companies`, `0x5019 + 0x500b = to territories`, and
`0x501a..0x501c = to all/human/AI players`; the grouped effect-row type mask matches that split
directly through bits `0x08`, `0x01`, `0x04`, and `0x02`. The
selected-event strip is tighter now too: `0x004db120` is the broader selected-event repaint and
navigation refresh above those smaller helpers, `0x004db520` and `0x004db5e0` are the previous
and next selected-event stepping verbs, `0x004db8b0` is the add-or-clone event modal helper,
`0x004dba90` is the rename verb, `0x004d9360` is the delete verb, `0x004db6a0` is the live
selected-event id setter behind control `0x4e84`, and `0x004db6f0` is the callback-binding plus
pending-selection bootstrap path that seeds the strip during window bring-up. The larger
dispatcher at `0x004dbb80` now makes the strip explicit: `0x4e85..0x4e8a` are previous, next,
add blank, clone selected, rename, and delete event, while the later grouped band commits current
summary state through `0x004d8d50` before changing grouped selector `[this+0x9c]` via `0x004dbf93`.
The selection bootstrap side is tighter too: `0x004daf40` is now the placeholder reset helper for
the selected-event summary controls `0x4eaf`, `0x4eac`, `0x4ed9`, `0x4edb`, and `0x4fdf..0x4fe2`.
The grouped target-scope side is tighter too: `0x004d8ea0` now reads as the commit helper for current
selected-event text panels before selection or grouped-action changes, `0x004d8d50` now records
the hidden selector family `0x5006..0x500e -> 0..8`, and `0x004dab60` projects that ordinal
one-to-one onto the visible grouped-effect target-scope display strip `0x5014..0x501c`. That
split is firmer now: `0x5006..0x500e` are the canonical hidden selectors that get stored into
`[event + group + 0x7fb]`, while `0x5014..0x501c` are the visible mirror rows republished from
that same ordinal rather than a second independently named selector family. The grouped row and
stored-summary refresh side is tighter too: `0x004d88f0` is now the selected grouped-effect
row-list renderer for `0x4ed5`, formatting the grouped `0x28`-byte rows through RT3.lng
`1154..1159`, and `0x004da9a0` is the current grouped-summary-state republisher that reloads
`0x500a`, `0x500b`, and visible action selection `0x5014..0x501c` from `[event + group + ...]`
before tailing back into `0x004da0f0`,
`0x004dbfca` as the grouped target-scope mode selector that persists the chosen control id into
`0x00622074`, with `0x5001/0x5002` now strongest-fit as `Test against...` and
`Apply effects...`, `0x004dbeeb` as the pending shared summary-text triplet publish helper for
`0x4eac/0x4ed9/0x4edb`,
`0x004d91e0` as the selected-event summary-header and grouped-mode commit helper above
`0x004d8d50`, and `0x004dbe7a` as the narrower `0x4ec6/0x4ec7` choice-event single-player-only
warning modal branch rooted at RT3.lng `3887`. The remaining gaps on
this lane are narrower again because the grouped-band `0x4dc09c` table now closes one earlier
overclaim: controls `0x5001/0x5002` are the only `0x4fed..0x501c` entries that route into
`0x004dbfca` on the `0xcf` side, while visible rows `0x5014..0x501c` only route to the smaller
`0x004d9d10` affordance path and the rest of `0x4ff1..0x5013` are default no-ops. The open
question is therefore no longer whether those visible target-scope rows are direct selector verbs;
current evidence says they are not.
The local slot records are rooted at
`[world+0x69d8]`,
`[slot+0x01]` polarity and the external role gate at `[world+0x0bc3+slot*9]` are now grounded, and
`[slot+0x03]` now looks like the distinguished primary-human-seat marker because current grounded
writes seed it only on slot zero and later logic moves it solely by whole-record compaction. The