finished simulated controller
This commit is contained in:
parent
aaf717bd8d
commit
5d723ae9f8
10 changed files with 73 additions and 46 deletions
16
Cargo.lock
generated
16
Cargo.lock
generated
|
@ -234,26 +234,16 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rs48"
|
||||
version = "1.1.0"
|
||||
version = "1.2.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"rand",
|
||||
"rs48_lib 1.1.0",
|
||||
"rs48_lib",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rs48_lib"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2da34dd2475597325c46db60df6c4f27cdf773f2acba50d96668471ead6bd61c"
|
||||
dependencies = [
|
||||
"rand",
|
||||
"termion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rs48_lib"
|
||||
version = "1.1.1"
|
||||
version = "1.2.0"
|
||||
dependencies = [
|
||||
"rand",
|
||||
"termion",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "rs48"
|
||||
version = "1.1.0"
|
||||
version = "1.2.0"
|
||||
edition = "2021"
|
||||
description = "A game of 2048 that plays in the terminal as a TUI with a lot of configurability."
|
||||
license = "GPL-3.0"
|
||||
|
@ -9,6 +9,6 @@ repository = "https://github.com/MajorBarnulf/rs48"
|
|||
homepage = "https://github.com/MajorBarnulf/rs48"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "3.1", features = ["derive"] }
|
||||
rs48_lib = "1.1"
|
||||
rand = "*"
|
||||
clap = { version = "3.2", features = ["derive"] }
|
||||
rs48_lib = { path = "../rs48_lib" }
|
||||
rand = "0.8"
|
||||
|
|
|
@ -83,11 +83,10 @@ fn main() -> Result<(), GameError> {
|
|||
let controller = match arguments.controller {
|
||||
ControllerParam::Player => PlayerController::new().into_box(),
|
||||
ControllerParam::Random => RandomController::new().into_box(),
|
||||
ControllerParam::Simulated => todo!(),
|
||||
ControllerParam::Simulated => SimulatedController::new(80, 50).into_box(),
|
||||
};
|
||||
let mut managed = GameManager::new(game_rules, manager_rules, controller);
|
||||
let err = managed.play_all();
|
||||
println!("color seed: {color_seed}");
|
||||
err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "rs48_lib"
|
||||
version = "1.1.1"
|
||||
version = "1.2.0"
|
||||
edition = "2021"
|
||||
description = "components of rs48"
|
||||
license = "MIT"
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use rand::{distributions::Standard, prelude::Distribution};
|
||||
|
||||
use super::grid::Grid;
|
||||
use crate::game::Game;
|
||||
use std::{error::Error, fmt::Display};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Move {
|
||||
LEFT,
|
||||
RIGHT,
|
||||
|
@ -11,6 +11,12 @@ pub enum Move {
|
|||
DOWN,
|
||||
}
|
||||
|
||||
impl Move {
|
||||
pub fn all() -> [Self; 4] {
|
||||
[Self::LEFT, Self::RIGHT, Self::UP, Self::DOWN]
|
||||
}
|
||||
}
|
||||
|
||||
impl Distribution<Move> for Standard {
|
||||
fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> Move {
|
||||
match rng.gen_range(0..4) {
|
||||
|
@ -39,7 +45,7 @@ impl Display for ControllerError {
|
|||
impl Error for ControllerError {}
|
||||
|
||||
pub trait Controller {
|
||||
fn next_move(&mut self, grid: &Grid) -> Result<Move, ControllerError>;
|
||||
fn next_move(&mut self, game: &Game) -> Result<Move, ControllerError>;
|
||||
|
||||
fn into_box(self) -> Box<dyn Controller>
|
||||
where
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::io::{stdin, stdout};
|
|||
use termion::{event::Key, input::TermRead, raw::IntoRawMode};
|
||||
|
||||
use super::{Controller, ControllerError, Move};
|
||||
use crate::grid::Grid;
|
||||
use crate::game::Game;
|
||||
|
||||
pub struct PlayerController;
|
||||
|
||||
|
@ -13,7 +13,7 @@ impl PlayerController {
|
|||
}
|
||||
|
||||
impl Controller for PlayerController {
|
||||
fn next_move(&mut self, _grid: &Grid) -> Result<Move, ControllerError> {
|
||||
fn next_move(&mut self, _game: &Game) -> Result<Move, ControllerError> {
|
||||
let stdin = stdin();
|
||||
let mut _stdout = stdout()
|
||||
.into_raw_mode()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use rand::random;
|
||||
|
||||
use super::{Controller, ControllerError, Move};
|
||||
use crate::grid::Grid;
|
||||
use crate::game::Game;
|
||||
|
||||
pub struct RandomController;
|
||||
|
||||
|
@ -12,7 +12,7 @@ impl RandomController {
|
|||
}
|
||||
|
||||
impl Controller for RandomController {
|
||||
fn next_move(&mut self, _grid: &Grid) -> Result<Move, ControllerError> {
|
||||
fn next_move(&mut self, _game: &Game) -> Result<Move, ControllerError> {
|
||||
let movement = random();
|
||||
Ok(movement)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::grid::Grid;
|
||||
use crate::{game::Game, prelude::RandomController};
|
||||
|
||||
use super::{Controller, ControllerError, Move};
|
||||
|
||||
|
@ -8,27 +8,53 @@ pub enum Objective {
|
|||
}
|
||||
|
||||
pub struct SimulatedController {
|
||||
_simulations_per_move: usize,
|
||||
_length_of_simulation: usize,
|
||||
_objective: Objective,
|
||||
simulations_per_move: usize,
|
||||
length_of_simulation: usize,
|
||||
}
|
||||
|
||||
impl SimulatedController {
|
||||
pub fn new(
|
||||
_simulations_per_move: usize,
|
||||
_length_of_simulation: usize,
|
||||
_objective: Objective,
|
||||
) -> Self {
|
||||
pub fn new(simulations_per_move: usize, length_of_simulation: usize) -> Self {
|
||||
Self {
|
||||
_simulations_per_move,
|
||||
_length_of_simulation,
|
||||
_objective,
|
||||
simulations_per_move,
|
||||
length_of_simulation,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Controller for SimulatedController {
|
||||
fn next_move(&mut self, _grid: &Grid) -> Result<Move, ControllerError> {
|
||||
todo!()
|
||||
fn next_move(&mut self, game: &Game) -> Result<Move, ControllerError> {
|
||||
let initial_score = game.get_score();
|
||||
|
||||
let mut scores: Vec<_> = Move::all()
|
||||
.into_iter()
|
||||
.map(|initial_move| {
|
||||
let sim_scores = (0..self.simulations_per_move).map(|_| {
|
||||
let mut game = game.clone();
|
||||
game.turn(initial_move.clone()).ok();
|
||||
let mut controller = RandomController::new();
|
||||
for _ in 1..self.length_of_simulation {
|
||||
let movement = controller.next_move(&game).ok();
|
||||
let result = movement.and_then(|movement| game.turn(movement).ok());
|
||||
if result.is_none() {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
game.get_score() - initial_score
|
||||
});
|
||||
|
||||
let mut res = 0;
|
||||
let mut it = 0;
|
||||
for score in sim_scores {
|
||||
it += 1;
|
||||
res += score;
|
||||
}
|
||||
|
||||
(initial_move, res / it)
|
||||
})
|
||||
.collect();
|
||||
scores.sort_by(|(_, a), (_, b)| a.cmp(b));
|
||||
|
||||
let (m, _) = scores.last().unwrap();
|
||||
Ok(m.clone())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ use super::{
|
|||
grid::Grid,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Rules {
|
||||
size: usize,
|
||||
spawn_per_turn: usize,
|
||||
|
@ -60,6 +61,7 @@ pub struct Game {
|
|||
score: usize,
|
||||
turn_index: usize,
|
||||
spawn_per_turn: usize,
|
||||
rules: Rules,
|
||||
}
|
||||
|
||||
impl Game {
|
||||
|
@ -67,13 +69,14 @@ impl Game {
|
|||
let Rules {
|
||||
size,
|
||||
spawn_per_turn,
|
||||
} = rules;
|
||||
} = rules.clone();
|
||||
|
||||
Self {
|
||||
board: Grid::new(size),
|
||||
score: 0,
|
||||
turn_index: 0,
|
||||
spawn_per_turn,
|
||||
rules,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,13 +88,16 @@ impl Game {
|
|||
self.score
|
||||
}
|
||||
|
||||
pub fn get_rules(&self) -> &Rules {
|
||||
&self.rules
|
||||
}
|
||||
|
||||
pub fn get_turn_index(&self) -> usize {
|
||||
self.turn_index
|
||||
}
|
||||
|
||||
pub fn turn(&mut self, movement: Move) -> Result<(), GameError> {
|
||||
let move_score = self.perform_move(movement);
|
||||
self.score += move_score;
|
||||
self.perform_move(movement);
|
||||
for _ in 0..self.spawn_per_turn {
|
||||
self.spawn_random()?;
|
||||
}
|
||||
|
@ -156,6 +162,7 @@ impl Game {
|
|||
}
|
||||
}
|
||||
};
|
||||
self.score += move_score;
|
||||
move_score
|
||||
}
|
||||
|
||||
|
|
|
@ -119,8 +119,7 @@ impl GameManager {
|
|||
}
|
||||
|
||||
fn game_turn(&mut self) -> Result<(), GameError> {
|
||||
let board = self.game.get_board();
|
||||
let movement = self.controller.next_move(board)?;
|
||||
let movement = self.controller.next_move(&self.game)?;
|
||||
self.game.turn(movement)?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue