use crate::game::{Action, Controllable, Game}; use crate::playfield::{Matrix, PlayField}; use crate::tetromino::{Tetromino, TetrominoType}; use rand::rngs::SmallRng; pub mod genetic; pub mod qlearning; #[derive(Hash, PartialEq, Eq, Clone, Debug)] pub struct State { matrix: Matrix, active_piece: Option, held_piece: Option, line_clears: u32, } impl From for State { fn from(game: Game) -> Self { (&game).into() } } impl From<&Game> for State { fn from(game: &Game) -> Self { let mut state: State = game.playfield().clone().into(); state.line_clears = game.line_clears; state } } impl From for State { fn from(playfield: PlayField) -> Self { Self { matrix: playfield.field().clone(), active_piece: playfield.active_piece, held_piece: playfield.hold_piece().map(|t| t.clone()), line_clears: 0, } } } pub trait Actor { fn get_action(&self, rng: &mut SmallRng, game: &Game, legal_actions: &[Action]) -> Action; fn dbg(&self); } pub trait Predictable { fn get_next_state(&self, action: Action) -> Self; } impl Predictable for Game { /// Expensive, performs a full clone. fn get_next_state(&self, action: Action) -> Self { let mut game = self.clone(); match action { Action::Nothing => (), Action::MoveLeft => game.move_left(), Action::MoveRight => game.move_right(), Action::SoftDrop => game.move_down(), Action::HardDrop => game.hard_drop(), Action::Hold => game.hold(), Action::RotateLeft => game.rotate_left(), Action::RotateRight => game.rotate_right(), }; game } } pub fn apply_action_to_game(action: Action, game: &mut Game) { match action { Action::Nothing => (), Action::MoveLeft => game.move_left(), Action::MoveRight => game.move_right(), Action::SoftDrop => game.move_down(), Action::HardDrop => game.hard_drop(), Action::Hold => game.hold(), Action::RotateLeft => game.rotate_left(), Action::RotateRight => game.rotate_right(), } }