feat(testing): add deterministic mechanics capture

Add named launcher, flipper, and claw scenarios that advance at exact 120 Hz steps with stable seeds. Emit per-step JSON state/event traces and optionally capture the logical 640x460 framebuffer at any requested time or step.

Cover parser behavior, deterministic replay, launcher timing, flipper edges, and complete capture/release/idle cycles for all claw terminals.

Test Plan:
- cargo fmt --check
- cargo test
- cargo clippy --all-targets --all-features -- -D warnings
- cargo run -- --simulate claw-6 --at 0.15 --screenshot /tmp/tdkpin-sim-validation/claw-6-after-flush.png --trace /tmp/tdkpin-sim-validation/claw-6.json
- Inspect both generated 640x460 PNGs and JSON traces
- git diff --cached --check
This commit is contained in:
2026-08-22 18:50:25 +02:00
parent 75c2464e72
commit 16c055eec6
6 changed files with 481 additions and 1 deletions
+10 -1
View File
@@ -193,7 +193,7 @@ impl Default for Ball {
}
}
#[derive(Debug)]
#[derive(Clone, Debug)]
pub struct Game {
pub players: Vec<Player>,
pub current_player: usize,
@@ -275,6 +275,15 @@ impl Game {
true
}
pub(crate) fn begin_claw_scenario(&mut self, terminal_frame: u8) -> Vec<Event> {
self.ball.in_launcher = false;
self.ball.position = CLAW_TRIGGER_CENTER;
self.ball.velocity = Vec2::ZERO;
let mut events = Vec::new();
self.begin_claw_capture(terminal_frame, &mut events);
events
}
fn fire_launcher(&mut self) {
let launch_speed = LAUNCH_SPEED_MIN + self.launcher_charge * LAUNCH_SPEED_RANGE;
self.ball.in_launcher = false;