Split The code is public; the app answers only to the crew.
Choose how hard the bots are, before the match and during it #64
Check · Review · Land · Live done — Landed and live in production.
Pushed. Here's the summary for the pull:
shipped merged
Merged main into this branch and pushed. main had brought in a bomb-blast rework, a loop.ts extraction with real match-pausing (world stops ticking while an overlay or a hidden tab is up), forge-identity-signed results, and several new modules (limit.ts, player.ts, who.ts) — none of that touched the difficulty logic itself, so it merged cleanly via git for every file except README.md, where both sides had added a paragraph to Playing right after the same sentence; I kept both (the Difficulty explanation followed by the new "Paused means paused" one). bun test is green at 311 tests (up from 260, all the new main-branch tests included).
Pushed. Here's the summary for the pull:
Bots now come in three skill bands instead of one fixed curve.
bots.tsmaps each bot's id into aDifficultyband (easy0–0.35,normal0.25–1,hard0.55–1) viaskillFor, so every setting still runs a side from fodder to uncomfortable — bots.ts remains the only place that knows what a difficulty means numerically.createWorldtakes an optionaldifficultyargument (defaulting tonormal, added last so every existing caller andsrc/rl/arena.tsis unaffected) and stores it onWorld;startRoundre-skills every existing bot brain in place each round via the newrestyleBrain, preserving path, plan, memory and target — only the hands (skill,reaction,aimSpeed,aimError) change.setDifficulty(world, next)just queues the value onworld.pendingDifficulty;startRoundis the only place that applies it, so a change made mid-fight can't retune a bot between one shot and the next — it takes effect from the following round, as the pause overlay now says.settings.tspersistsdifficultybeside mute/volume/sensitivity, validated the same way (parseSettingsfalls back to"normal"for anything missing, malformed, or not one of the three names). The menu gets a Difficulty select beside Side; the pause overlay gets a matching one wired the same way sensitivity already is (change there updates settings and, if a match is running, queues the next-round change). The in-canvas scoreboard now opens with a "Difficulty: X" line above the player rows.Left out: nothing server-side changed (no request payload,
result.ts,db.tsor leaderboard touched, per the issue), andpolicy.ts/weights are untouched — skill stays a pure handicap on the hands.Tested:
bun test(260 pass, 8 new: band mapping, easy-vs-hard hands,createWorldproducing brains inside their band at each setting, the mid-match change waiting forstartRound,restyleBrainpreserving path/plan, andparseSettingsfor missing/garbage/unknown/valid difficulty). Also booted the server and fetched the page to confirm both selects render and the bundled client parses. README's Playing and The bots sections, and thesettingsline in Shape, now describe the setting.Closes #38