Repository navigation
Speedrun: calculate a sheet's time headless — node runner and a Calculate button (#509) - #511
Merged
Merged
Conversation
…rowser (#509) `npm run speedrun -w taoot -- --headless` plays a sheet in node with the workbench's own driver over a stand-in window. From a cold boot, seed 20, all 361 lines of the sheet came out the same in-game time in node and in the browser (2:45 in 17 s against 3:36). What it took, beyond the runner: - a standing watch is asked by the session on every pass and halts the game on the pass it rises; only the watch's action moves it until done - the watchdog's quarter-second tick no longer holds up the next line - the runner does not look at the game while it waits on a file - headless frames give each callback its own task, as a browser does - budgets count the headless run's own frames, not the wall Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
A Calculate button plays the open sheet from a cold boot in a worker, headless and at full CPU speed, with a progress bar, and ends in either the sheet's in-game time and frames or the line it stopped at, how far in, and a button that puts the editor on that line. - the headless driver moves into the engine (speedrun/headless.ts), shared by the node runner and the worker; Titanic's input routing into src - budgets count only frames in which the game could run: not while a file loads, not while a standing watch has halted it - the save verb says why the engine refused a save Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The purser leaving opens maino1.mov, his office with the cargo manifest, on the very pass he goes. On a sheet's clock (#508) `say` saw that film before it saw the conversation end, took it between parked frames (no regions) for an inline clip, and pressed ESC at it: the office shut and Frank stood in the corridor. A conversation is now over once its puppet has closed, whatever is on screen; a film over a puppet still open is still skipped as an inline clip. With this the full sheet plays to the end again (seed 20: 6:30.4 in-game, headless). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
`hammer(startfence)` asks `aim` every pass whether the fencing bout's start button is back, and an answer of "not there" was a sweep of the whole screen: twelve thousand hit tests, about 50 ms, 743 times in one bout, 39 s of CPU against 41 s of game. Over a DreamFactory 4 flat with the room away a hit is one of the flat's buttons or a drawn prop, so a name no drawn prop carries is searched for only inside its button's rectangle (`flatWhere`, shared by both drivers). The fencing split: 40.9 s in-game unchanged, 41.7 s -> 2.6 s headless; the full sheet 1:10 -> 40.6 s. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
#509) The driver calls `win.setTimeout(…)`, and a browser's (a worker's) own setTimeout refuses a `this` that is not its global: "Illegal invocation" at the first standing watch's poll, line 867 of the full sheet. Node does not check, so headless runs never showed it. The full sheet now calculates to the end in the worker (6:31.5 in-game, unseeded, 52 s). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This was referenced Oct 6, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
This was referenced Oct 6, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Closes #509.
What it does
npm run speedrun -w taoot -- --headlessplays a sheet in node, with no browser and no drawing. It uses the workbench's own driver over a stand-in window, so every gesture is the same code.Same numbers as the browser
From a cold boot with seed 20, all 361 lines up to the sheet's then-failure point gave the same in-game time, to the millisecond, in node and in Playwright (2:45.4 in both runners). The smokestack → end leg matches pass for pass (1:25.1). Now the full sheet: 6:30.4 in-game in 40.6 s headless. Calculate takes about 52 s in the worker.
To get there, these engine and runner rules changed (they hold for every runner, not just headless):
watchFor) is checked by the session on every pass and stops the game on the pass it comes true. Only the watch's own action moves the game until it is done. Before, the ESC landed some passes late, and how many depended on the machine.Fixes found on the way
say: a film after the puppet has closed belongs to the room. The purser leaving opens his office (maino1.mov) on the same pass, andsaypressed ESC at it, which left Frank in the corridor. It came in with Speedrun clock: in-game time, the same on any machine and any connection (#508) #510. With it fixed, the full sheet runs to the end again.aimsearches only where the thing can be hit.hammer(startfence)swept the whole screen 743 times per fencing bout (39 s of CPU); now 2.6 s.saveverb says why the engine refused a save.Known
Tests
Session tests for the watch halt and the load rule, the
sayroom-film and inline-clip cases, and a node suite that plays the sheet's opening twice and needs identical numbers. The full suite passes apart from the known 30 s timeouts (container-refspuppets,sets.ts).🤖 Generated with Claude Code