fix(game): restore six-state target rotation
Replace the free-running 68x60 wheel animation with the original six-callback 91x90 DAT600 mechanism. Start WAVE 2011 at state one, advance once per selected detail timer, and rotate the five per-player lock contact/item values exactly at state six. Decode the 17x17 DAT600 target image/mask pair and render all six recovered position sets over the correct atlas or overlay-B base. Preserve filled targets in their resting state after rotation and add a deterministic `targets` scenario for trace and framebuffer validation. Test Plan: - `cargo test --all-targets` -- passed, 74 tests - `cargo clippy --all-targets -- -D warnings` -- passed - `rumdl check CHANGELOG.md README.md RECONSTRUCTION.md` -- passed - rendered all six target-rotation states -- visually verified - `git diff --cached --check` -- passed
This commit is contained in:
@@ -17,6 +17,7 @@ pub enum Scenario {
|
||||
Launcher,
|
||||
Flippers,
|
||||
Panel,
|
||||
Targets,
|
||||
Claw1,
|
||||
Claw6,
|
||||
Claw7,
|
||||
@@ -30,6 +31,7 @@ impl Scenario {
|
||||
Self::Launcher => "launcher",
|
||||
Self::Flippers => "flippers",
|
||||
Self::Panel => "panel",
|
||||
Self::Targets => "targets",
|
||||
Self::Claw1 => "claw-1",
|
||||
Self::Claw6 => "claw-6",
|
||||
Self::Claw7 => "claw-7",
|
||||
@@ -43,7 +45,7 @@ impl Scenario {
|
||||
Self::Claw6 => Some(6),
|
||||
Self::Claw7 => Some(7),
|
||||
Self::Claw18 => Some(18),
|
||||
Self::Autoplay | Self::Launcher | Self::Flippers | Self::Panel => None,
|
||||
Self::Autoplay | Self::Launcher | Self::Flippers | Self::Panel | Self::Targets => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,12 +59,13 @@ impl FromStr for Scenario {
|
||||
"launcher" => Ok(Self::Launcher),
|
||||
"flippers" => Ok(Self::Flippers),
|
||||
"panel" => Ok(Self::Panel),
|
||||
"targets" => Ok(Self::Targets),
|
||||
"claw-1" => Ok(Self::Claw1),
|
||||
"claw-6" => Ok(Self::Claw6),
|
||||
"claw-7" => Ok(Self::Claw7),
|
||||
"claw-18" => Ok(Self::Claw18),
|
||||
_ => Err(format!(
|
||||
"unknown scenario {value:?}; expected autoplay, launcher, flippers, panel, claw-1, claw-6, claw-7, or claw-18"
|
||||
"unknown scenario {value:?}; expected autoplay, launcher, flippers, panel, targets, claw-1, claw-6, claw-7, or claw-18"
|
||||
)),
|
||||
}
|
||||
}
|
||||
@@ -146,7 +149,7 @@ fn seconds_to_step(value: &str) -> Result<u64, String> {
|
||||
}
|
||||
|
||||
pub const fn usage() -> &'static str {
|
||||
"Usage:\n tdkpin-rs\n tdkpin-rs --simulate SCENARIO [--at SECONDS | --step N] [--screenshot FILE.png] [--trace FILE.json] [--seed N]\n\nScenarios: autoplay, launcher, flippers, panel, claw-1, claw-6, claw-7, claw-18"
|
||||
"Usage:\n tdkpin-rs\n tdkpin-rs --simulate SCENARIO [--at SECONDS | --step N] [--screenshot FILE.png] [--trace FILE.json] [--seed N]\n\nScenarios: autoplay, launcher, flippers, panel, targets, claw-1, claw-6, claw-7, claw-18"
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, PartialEq)]
|
||||
@@ -202,6 +205,10 @@ impl Simulation {
|
||||
game.panel_frame = Some(0);
|
||||
game.wheel_holes.fill(true);
|
||||
}
|
||||
if scenario == Scenario::Targets {
|
||||
game.target_rotation_state = Some(0);
|
||||
game.wheel_holes = [true, false, true, false, false];
|
||||
}
|
||||
let initial_events = scenario
|
||||
.claw_terminal()
|
||||
.map_or_else(Vec::new, |terminal| game.begin_claw_scenario(terminal));
|
||||
@@ -326,7 +333,12 @@ fn controls_for(scenario: Scenario, step: u64) -> Controls {
|
||||
..Controls::default()
|
||||
}
|
||||
}
|
||||
Scenario::Panel | Scenario::Claw1 | Scenario::Claw6 | Scenario::Claw7 | Scenario::Claw18 => {
|
||||
Scenario::Panel
|
||||
| Scenario::Targets
|
||||
| Scenario::Claw1
|
||||
| Scenario::Claw6
|
||||
| Scenario::Claw7
|
||||
| Scenario::Claw18 => {
|
||||
Controls::default()
|
||||
}
|
||||
}
|
||||
@@ -461,6 +473,20 @@ mod tests {
|
||||
assert_eq!(events.iter().filter(|event| **event == "Sound(2012)").count(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn target_scenario_runs_all_six_rotation_states() {
|
||||
let mut simulation = Simulation::new(Scenario::Targets, 1);
|
||||
simulation.advance_to(4);
|
||||
assert_eq!(simulation.game.target_rotation_state, Some(1));
|
||||
assert_eq!(simulation.trace[4].events, ["Sound(2011)"]);
|
||||
|
||||
simulation.advance_to(22);
|
||||
assert_eq!(simulation.game.target_rotation_state, Some(6));
|
||||
assert_eq!(simulation.game.wheel_holes, [false, true, false, false, true]);
|
||||
simulation.advance_to(26);
|
||||
assert_eq!(simulation.game.target_rotation_state, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn every_claw_scenario_completes_its_seeded_capture() {
|
||||
for scenario in [
|
||||
|
||||
Reference in New Issue
Block a user