WIP: feat(scripts): a pipeline tour that plays the game for the tour's pipeline state list #2048

Draft
hckrman101 wants to merge 12 commits from hckrman101/scripts/pipeline-tour into main
hckrman101 commented 2026-11-11 01:04:50 +00:00 (Migrated from github.com)

Releases ship a pipeline list so the first start builds pipelines before the title instead of in play, but the tour's source (assets/pipeline_states/tour.bin.xz) needs someone to play the whole game. This adds a script that plays it unattended.

What it does. scripts/pipeline_tour.py starts the game with no save and, through the live input file (HOS_INPUT_LIVE) and the Debug tab's !cheat actions, goes through the title, New Game and the opening. It then gives Link the items and opens the pause menu's pages. Then it visits every Teleport destination as child and as adult: it turns the camera all around and, at chosen stops, uses the sword, the shield and an item picked from the pause menu. It moves on once no new pipeline appears. tour runs parts (opening, child overworld, dungeons, adult overworld) at once in reflinked copies of the game folder and merges them. --publish writes tour.bin.xz and tour.md through nx2/pipeline_states.py tour, filling in the GPU, build, settings and route from the runs' logs. No controller is opened (HOS_NO_SDL) and nothing is sent to the desktop. Waits and presses count game frames, so it runs faster than real time: 640x360, the game's own upscaler at 50%, the cap at 240 with every frame a 60th of a second of game time.

host/hos_main.c gets one debug-only action, !cheat 998 (no menu row sends it). It logs the map, whether an event is playing or a map is loading, and Link's age. The tour waits on it for control after the opening and for each map change.

How to run (Linux):

python -I scripts/pipeline_tour.py tour --game <game folder copy> --out <dir> --name play --publish
python -I scripts/pipeline_tour.py run --game <game folder> --out <dir> --part child-overworld --first "Market" --stops 3 --skip-opening
python -I scripts/pipeline_tour.py run --game x --out <dir> --dry-run      # the route, without the game

Measured (RTX 3090, Linux, partial runs on a busy PC):

  • 6677 pipelines over 3183 programs merged from the partial runs, against 1258 / 974 in one player's list.
  • Each overworld area still adds 75 to 620 pipelines no other area has.
  • Headless: 1.8x real time at about 107 fps; a stop takes 12 to 20 s.
  • One game holds 5 to 9 GB (the 9809 MB guest memory; HOS_MEMORY_MB=6144 does not boot).

Known gaps. No run has gone through the whole route yet. Still to do: dungeon rooms past the entrance, boss arenas, diving, Game Over, weather, and songs (the ocarina isn't driven). Story items (medallions, stones, songs) aren't given, because they trigger scenes that wait for the player. Sacred Forest Meadow as adult is left out because Sheik's lesson starts there.

Follow-ups: the record format change (HKSTATE2) will need the tour's list made again; this script's merge goes through nx2/pipeline_states.py, so it needs no change.

Tested: tests/test_pipeline_tour.py (the actions' numbers against the source, the route, the presses, the merge and --publish with synthetic lists), python -I -B tests/run_all.py, and the runs above.

Releases ship a pipeline list so the first start builds pipelines before the title instead of in play, but the tour's source (`assets/pipeline_states/tour.bin.xz`) needs someone to play the whole game. This adds a script that plays it unattended. **What it does.** `scripts/pipeline_tour.py` starts the game with no save and, through the live input file (`HOS_INPUT_LIVE`) and the Debug tab's `!cheat` actions, goes through the title, New Game and the opening. It then gives Link the items and opens the pause menu's pages. Then it visits every Teleport destination as child and as adult: it turns the camera all around and, at chosen stops, uses the sword, the shield and an item picked from the pause menu. It moves on once no new pipeline appears. `tour` runs parts (opening, child overworld, dungeons, adult overworld) at once in reflinked copies of the game folder and merges them. `--publish` writes `tour.bin.xz` and `tour.md` through `nx2/pipeline_states.py tour`, filling in the GPU, build, settings and route from the runs' logs. No controller is opened (`HOS_NO_SDL`) and nothing is sent to the desktop. Waits and presses count game frames, so it runs faster than real time: 640x360, the game's own upscaler at 50%, the cap at 240 with every frame a 60th of a second of game time. `host/hos_main.c` gets one debug-only action, `!cheat 998` (no menu row sends it). It logs the map, whether an event is playing or a map is loading, and Link's age. The tour waits on it for control after the opening and for each map change. **How to run** (Linux): ```sh python -I scripts/pipeline_tour.py tour --game <game folder copy> --out <dir> --name play --publish python -I scripts/pipeline_tour.py run --game <game folder> --out <dir> --part child-overworld --first "Market" --stops 3 --skip-opening python -I scripts/pipeline_tour.py run --game x --out <dir> --dry-run # the route, without the game ``` **Measured** (RTX 3090, Linux, partial runs on a busy PC): - 6677 pipelines over 3183 programs merged from the partial runs, against 1258 / 974 in one player's list. - Each overworld area still adds 75 to 620 pipelines no other area has. - Headless: 1.8x real time at about 107 fps; a stop takes 12 to 20 s. - One game holds 5 to 9 GB (the 9809 MB guest memory; `HOS_MEMORY_MB=6144` does not boot). **Known gaps.** No run has gone through the whole route yet. Still to do: dungeon rooms past the entrance, boss arenas, diving, Game Over, weather, and songs (the ocarina isn't driven). Story items (medallions, stones, songs) aren't given, because they trigger scenes that wait for the player. Sacred Forest Meadow as adult is left out because Sheik's lesson starts there. **Follow-ups:** the record format change (HKSTATE2) will need the tour's list made again; this script's merge goes through `nx2/pipeline_states.py`, so it needs no change. Tested: `tests/test_pipeline_tour.py` (the actions' numbers against the source, the route, the presses, the merge and `--publish` with synthetic lists), `python -I -B tests/run_all.py`, and the runs above.
Commenting is not possible because the repository is archived.
No description provided.