Analysis and reimplementation of Railroad Tycoon 3


The old executable is at ./rt3_wineprefix/drive_c/rt3/RT3.exe

Our first task is to understand the executable's high-level control loops and subsystem boundaries well
enough to choose good rewrite targets. As we go, we document evidence, keep a curated function map,
and stand up Rust tooling that can validate artifacts and later host replacement code.

The long-term direction is still a DLL we can inject into the original executable, patching in
individual functions as we build them out. The active implementation milestone is now a headless
runtime rehost layer that can execute deterministic world work, compare normalized state, and grow
subsystem breadth without depending on the shell or presentation path. The current packed-event
frontier is broader real grouped-descriptor coverage on top of the existing save-slice, snapshot,
overlay-import, compact-control, and symbolic company-target workflows. The runtime already carries
selected-company and controller-role context through overlay imports, and real descriptors `2`
`Company Cash`, `13` `Deactivate Company`, and `16` `Company Track Pieces Buildable` now parse and
execute through the ordinary runtime path, and descriptor `1` `Player Cash` now joins that batch
through the same service engine. Synthetic packed records still exercise the same runtime without a
parallel packed executor. The first grounded condition-side unlock now exists for negative-sentinel
`raw_condition_id = -1` company scopes, and the first ordinary nonnegative condition batch now
executes too: numeric-threshold company finance, company track, aggregate territory track, and
company-territory track rows can import through overlay-backed runtime context. Exact
named-territory binding now executes, and the runtime now also carries the minimal event-owned
train roster and opaque economic-status lane needed for real descriptors `8` `Economic Status`, `9`
`Confiscate All`, and `15` `Retire Train` to execute through the same path. Descriptor `3`
`Territory - Allow All` remains the explicit parity-only descriptor frontier. Mixed
supported/unsupported real rows still stay parity-only. The PE32 hook remains useful as capture and
integration tooling, but it is no longer the main execution milestone.

## Project Docs

Bootstrap design and workflow documents live in `docs/`.

- `docs/README.md`: handbook index and target hashes
- `docs/control-loop-atlas.md`: compatibility index for the split atlas
- `docs/control-loop-atlas/`: canonical atlas section files
- `docs/setup-workstation.md`: toolchain baseline and local setup
- `docs/re-workflow.md`: repeatable reverse-engineering workflow
- `docs/function-map.md`: canonical function-map schema and conventions

The first committed exports for the canonical 1.06 executable live in `artifacts/exports/rt3-1.06/`.

## Rust Workspace

The Rust workspace is split into focused crates:

- `rrt-model`: shared types for addresses, function-map rows, and control-loop concepts
- `rrt-runtime`: headless runtime state, stepping, normalized event service, and persistence-facing
  runtime types
- `rrt-fixtures`: fixture schemas, loading, normalization, and diff helpers for rehost validation
- `rrt-cli`: validation, runtime fixture execution, state-diff tools, and repo-health checks
- `rrt-hook`: minimal Windows DLL scaffold for low-risk in-process loading, capture, and later
  integration experiments under Wine

For the current headless runtime smoke path, use `cargo run -p rrt-cli -- runtime summarize-fixture
fixtures/runtime/minimal-world-step-smoke.json` or one of the broader runtime fixtures under
`fixtures/runtime/`.

For the current hook smoke test, run `tools/run_hook_smoke_test.sh`. It builds the PE32 proxy,
copies it into the local RT3 install, launches the game briefly under Wine with
`WINEDLLOVERRIDES=dinput8=n,b`, and expects `rrt_hook_attach.log` to appear.
