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
+21
View File
@@ -5,6 +5,7 @@ use crate::{
table::BUMPERS,
};
use macroquad::prelude::*;
use std::path::Path;
const WIDTH: f32 = 640.0;
const HEIGHT: f32 = 460.0;
@@ -82,6 +83,26 @@ impl App {
self.present();
}
pub fn set_simulation_game(&mut self, game: Game) {
self.game = Some(game);
self.screen = Screen::Playing;
}
pub fn render_simulation(&self) {
self.draw_logical();
}
pub fn export_simulation_png(&self, path: &Path) -> Result<(), String> {
let path = path
.to_str()
.ok_or_else(|| format!("screenshot path is not valid UTF-8: {}", path.display()))?;
self.render_target
.texture
.get_texture_data()
.export_png(path);
Ok(())
}
fn handle_global_input(&mut self) {
if is_key_pressed(KeyCode::F12) {
self.saved.settings.sounds = !self.saved.settings.sounds;