use std::time::Duration;
use either::Either;
use falling_tetromino_engine::{
Configuration, ExtDuration, ExtNonNegF64, SoftDropRate, StdPceRot, StdTetGen,
};
use crate::tui_settings::SlotMachine;
#[serde_with::serde_as]
#[derive(
PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, serde::Serialize, serde::Deserialize,
)]
pub struct GameplaySettings {
pub rotsys: StdPceRot,
pub tetgen: StdTetGen,
pub preview: usize,
#[serde_as(as = "serde_with::DurationSecondsWithFrac<f64>")]
pub das: Duration,
#[serde_as(as = "serde_with::DurationSecondsWithFrac<f64>")]
pub arr: Duration,
#[serde_as(as = "Option<serde_with::DurationSecondsWithFrac<f64>>")]
pub dsd: Option<Duration>,
pub sdr: SoftDropRate,
#[serde_as(as = "serde_with::DurationSecondsWithFrac<f64>")]
pub lcd: Duration,
#[serde_as(as = "serde_with::DurationSecondsWithFrac<f64>")]
pub are: Duration,
pub initsys: bool,
#[serde_as(as = "Option<serde_with::DurationSecondsWithFrac<f64>>")]
pub dtapfinesse: Option<Duration>,
}
pub fn gameplay_settings_presets() -> SlotMachine<GameplaySettings> {
let slots = vec![
("Default".to_owned(), GameplaySettings::default()),
("Guideline".to_owned(), GameplaySettings::guideline()),
("Finesse+".to_owned(), GameplaySettings::extra_finesse()),
("NES".to_owned(), GameplaySettings::nes()),
("Gameboy".to_owned(), GameplaySettings::gameboy()),
(
"Elektronika 60".to_owned(),
GameplaySettings::elektronika_60(),
),
];
SlotMachine::with_unmodifiable_slots(slots, "Gameplay".to_owned())
}
impl Default for GameplaySettings {
fn default() -> Self {
let c = Configuration::default();
Self {
rotsys: c.rotation_system,
tetgen: StdTetGen::default(),
preview: c.generate_piece_preview,
das: c.delayed_auto_shift,
arr: c.auto_repeat_rate,
dsd: c.delayed_soft_drop,
sdr: c.soft_drop_rate,
lcd: c.line_clear_duration,
are: c.spawn_delay,
initsys: c.allow_spawn_manipulation,
dtapfinesse: None,
}
}
}
impl GameplaySettings {
pub fn extra_finesse() -> GameplaySettings {
GameplaySettings {
das: Duration::from_millis(110),
arr: Duration::from_millis(0),
sdr: Either::Right(ExtDuration::ZERO),
preview: 6,
..Self::default()
}
}
pub fn guideline() -> GameplaySettings {
GameplaySettings {
rotsys: StdPceRot::Super,
tetgen: StdTetGen::bag(),
preview: 3,
das: Duration::from_millis(167), arr: Duration::from_millis(33), dsd: None,
sdr: Either::Left(ExtNonNegF64::new(20.0).unwrap()), lcd: Duration::from_millis(200), are: Duration::from_millis(50), initsys: true,
dtapfinesse: None,
}
}
pub fn nes() -> GameplaySettings {
GameplaySettings {
rotsys: StdPceRot::ClassicR,
tetgen: StdTetGen::classic(),
das: Duration::from_millis(266), preview: 1,
arr: Duration::from_millis(100), are: Duration::from_millis(250), lcd: Duration::from_millis(333), dsd: Some(Duration::from_millis(50)),
sdr: Either::Right(Duration::from_millis(33).into()), initsys: false,
dtapfinesse: None,
}
}
pub fn gameboy() -> GameplaySettings {
GameplaySettings {
rotsys: StdPceRot::ClassicL,
tetgen: StdTetGen::uniform(),
das: Duration::from_millis(400), preview: 1,
arr: Duration::from_millis(150), are: Duration::from_millis(33), lcd: Duration::from_millis(1500), dsd: None,
sdr: Either::Right(Duration::from_millis(50).into()), initsys: false,
dtapfinesse: None,
}
}
pub fn elektronika_60() -> GameplaySettings {
GameplaySettings {
rotsys: StdPceRot::ClassicL,
tetgen: StdTetGen::uniform(),
das: Duration::from_millis(350), preview: 1,
arr: Duration::from_millis(100), are: Duration::from_millis(0), lcd: Duration::from_millis(400), dsd: Some(Duration::from_millis(350)), sdr: Either::Right(Duration::from_millis(100).into()), initsys: false,
dtapfinesse: None,
}
}
}