Public: anyone can read this; the crew can change it.

forked from trevato/cs · proposes · 4 behind

The range gets a second drill: moving plates, chosen before the run and pinned by its own digest #121

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

The range has two drills now, and which one you are playing is one entry in a table rather than a branch anywhere in the game.

shipped production is serving it deploy ae07c2d

opened this

The range has two drills now, and which one you are playing is one entry in a table rather than a branch anywhere in the game.

DRILLS in src/range/targets.ts holds the spawn rate, the lifetime, the depth and height bands, the speed range and the scoring of each kind of run; createRun(seed, drill) takes which one, and a third drill is one more row plus a name in DrillName. pop-up is the run the range shipped with, unchanged in every number — its speed is zero and its seed salt is zero, so pin.test.ts's RANGE digest is exactly where it was. tracking stands two plates up at a time, nearer and longer-lived, each sliding across the lane at 90 to 260 units a second until its lifetime or its lane runs out, worth 100 to 160 for the distance plus a third of a point for every unit a second it is crossing at.

The tick boundary is written down in targets.ts's header and held to by tests: a plate moves at the top of a tick and the bullet leaves at the end of one, so the trace, the draw and the digest all read the same box on the same tick. targets.test.ts shoots at where a plate was (miss) and where the tick left it (hit), and scene.test.ts walks a real tracking run 200 ticks comparing every instance with the box the trace would use. The tracking drill has a digest of its own, played from the same seed through the same seventeen ticks re-aimed at its own lane: 14 of 17, 2,534 points. The two lanes share no second of the thirty — that is what the drill's salt is for.

<kbd>T</kbd> or the touch button switches drill between runs; setDrill refuses a live run outright, and the panel names the drill, keeps a best per drill and only offers the switch when a run is not in progress. What I chose not to do: the touch button for drill took reload's place rather than becoming a seventh button that could wrap off the bottom of the stage on a phone — reload does nothing in this game and the key still reports it. I also left the range's ceiling alone: the bundle is 28,813 raw / 12,246 gzipped against 29,400 / 12,700, which fits, but with the thinnest headroom on the page — the next thing the range gains will want it raised. bun test is 586 green, and /range answers in about 6 ms.

To try it in the preview: press <kbd>T</kbd> before pressing <kbd>Enter</kbd>, and watch the plates slide — then try switching mid-run and see the panel carry on unchanged.

🤖 Generated with Claude Code

Closes #88

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs