feat: add Ctrl+Shift+0 crazy mode with ten extra balls

Pressing Ctrl+Shift+0 during a game drops ten balls at fixed points
spread over the open playfield (CRAZY_BALL_POSITIONS): two near the top
bumpers, a row in the middle, and four above the slingshots. Repeated
presses add another ten each time.

The original engine is a faithful two-slot reconstruction (primary and
secondary ball) whose claw, lock-hole, special-hole, and effect-seven
rules all assume at most two balls. Rather than generalising that
engine, crazy balls live in a separate Game::crazy_balls list with a
reduced step:

- gravity, speed clamp, and the same static record ranges as the main
  scan (walls, passive circles, bumpers, flippers);
- wall and bumper rules, so they score, light banks, and kick normally;
- flipper kicks and nudge impulses;
- no sensors, holes, magnets, claw, or ball-to-ball collisions.

A crazy ball that leaves the board, hits the drain, or comes to rest on
the shooter stop is removed. When the primary ball drains (and no
secondary or special respawn takes priority), a crazy ball is promoted
into the primary slot, so the turn only ends once every ball is gone.
The promoted ball then runs the full original rules.

Because the mode is effectively a cheat, Game records that it was used
and the browser build skips the online high-score submission for that
game; the local table still records the score.

The App suppresses the nudge that releasing Shift would otherwise fire
after the combo. Ctrl also raises the left flipper while held, which
is left as is. Browsers may reserve Ctrl+Shift+0 for themselves.

A new `crazy` simulation scenario starts a game with crazy balls.

Test Plan:
- cargo test: new tests check every drop point is clear of all static
  records, that the balls move, score, and eventually drain without
  costing a ball, that a primary drain promotes a crazy ball, and that a
  finished game rejects the mode.
- Manual: start a game, press Ctrl+Shift+0, release Shift, and confirm
  ten balls appear and no nudge/tilt sound plays.
This commit is contained in:
ddidderr committed 2026-10-10 10:48:50 +02:00
1 parent 3fc1096500
commit 139e641005
6 files changed
+266 -7

No files matched your search

+8 -1
View File
@@ -60,7 +60,7 @@ cargo run -- --simulate claw-6 --at 0.15 \
Use `--step N` instead of `--at SECONDS` to reproduce one exact update. The
available scenarios are `loading`, `attract`, `highscores`, `name-entry`,
`effect-7`, `autoplay`, `launcher`, `flippers`, `panel`, `targets`, `claw-1`, `claw-6`,
`claw-7`, and `claw-18`; `--seed N` fixes random choices.
`claw-7`, `claw-18`, and `crazy`; `--seed N` fixes random choices.
`autoplay` charges each ball and operates the flippers from live ball position
for long end-to-end validation runs.
@@ -77,6 +77,13 @@ for long end-to-end validation runs.
| Settings | `TDKPIN.INI` before launch | F10 opens the portable settings screen |
| High scores | Automatic when a player finishes | F9 opens the portable table viewer |
| Sound | F12 | - |
| Crazy mode: drop 10 extra balls | - | Ctrl+Shift+0 |
Crazy mode is a modern addition. Its balls bounce off walls, bumpers, and
flippers and score through them, but skip sensors, holes, and the claw. When
the main ball drains, a crazy ball takes its place before the turn ends. Scores
from games that used crazy mode are not submitted to the online high-score
table.
The five original speed choices remain available in settings. Physics now uses
the original invariant 100 Hz millipixel substep, batched as 5/4/3/2/1 steps on