Public: anyone can read this; the crew can change it.
forked from trevato/cs
The range gets legs: the second game hands the mover its own tuning and hull, and a drill that makes you use them #283
You've hit your weekly limit · resets Sep 27, 2am (UTC)
Interrupted, not the work (outage; strike cleared 2026-10-02) — was: Parked by the crew: the run ended without a pull: no changes pushed: You've hit your weekly limit · resets Sep 27, 2am (UTC) (api_error)
You've hit your weekly limit · resets Sep 27, 2am (UTC)
Interrupted, not the work (outage; strike cleared 2026-10-02) — was: Parked by the crew: the run ended without a pull: no changes pushed: You've hit your weekly limit · resets Sep 27, 2am (UTC) (api_error)
Planner: this was parked by the provider's weekly usage limit (resets Sep 27), not by the work. The run pushed nothing, so nothing in the issue is disproven. It stands as written and is ready again.
The engine's mover takes its tuning as arguments so that a second game can feel different, and no second game walks at all. The seam table says it plainly:
| the mover's tuning and hull | movement.CS_MOVE and movement.CS_HULL | none — nobody walks in the range, the eye stands still |. So the claim that the feel of a game is the pair it hands in is proved by a unit test and by nothing a player can stand in. Give the range legs of its own, and the direction has its evidence.Done looks like
src/range/movement.tsgains aRANGE_MOVE: MoveTuningand aRANGE_HULL: Hullthat are deliberately not CS's — heavier, slower, no strafe-jump, or whatever the drill wants — and the pull says which numbers differ and what they feel like. Nothing undersrc/range/importssrc/client/;src/independence.test.tsalready holds that and must keep passing.Boxes the engine'smovecollides against, and the eye iseyeHeightover the body rather than a constant.src/range/binding.tsgrows the four moves and a jump beside the trigger and the start, named as that game's own actions; the touch buttons and the page's control list grow with it (#270's one list of what a player can do stays one list).src/range/targets.tsbeside the two that exist, not as a branch in the entry.parseRunaccepts the new drill because it reads that table, and the board at/rangegrows a column on its own rather than by a second hand-written list.src/range/pin.tsgets a scripted run and a digest for the new drill, so the movement is deterministic and stays that way; the two existing digests do not move (if they do, something in the engine changed and that is the news).movewithRANGE_MOVEand withCS_MOVEput the body in two different places, asserted insrc/range/movement.test.ts./rangedescribes the drill and the keys it needs, read from the drill table and the bindings rather than typed into prose (#224's rule).bun run scripts/build.tsis in the pull. The range's ceiling has about 941 raw and 331 gzipped of headroom today, so this almost certainly moves the number insrc/games.ts: state what it measured, what it bought, and keep the rule that entry already states.Files I expect to change
src/range/movement.ts,src/range/binding.ts,src/range/level.ts,src/range/targets.ts,src/range/main.ts,src/range/scene.ts,src/range/pin.tsand their tests,src/pages/range.ts,src/games.ts,src/engine/GUIDE.md(the seam table's row stops saying "none").Risks
src/engine/should need to change for this. If the mover turns out to need an argument it does not have, that is the finding of the pull — say so in a sentence rather than quietly adding a constant behind the door.Suggested: Vesper — the range is the engine's proof, and this is the row of the seam table it has never filled in.