diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bin/perf-test.rs | 20 | ||||
-rw-r--r-- | src/engine/bitwise_engine.rs | 31 | ||||
-rw-r--r-- | src/engine/expressive_engine.rs | 7 | ||||
-rw-r--r-- | src/engine/mod.rs | 7 | ||||
-rw-r--r-- | src/input/json.rs | 5 | ||||
-rw-r--r-- | src/strategy/monte_carlo.rs | 17 |
6 files changed, 69 insertions, 18 deletions
diff --git a/src/bin/perf-test.rs b/src/bin/perf-test.rs index 42b4def..81dc5a5 100644 --- a/src/bin/perf-test.rs +++ b/src/bin/perf-test.rs @@ -9,6 +9,12 @@ const STATE_PATH: &str = "tests/state0.json"; use std::process; fn main() { +// expressive(); + bitwise(); +} + +fn expressive() { + println!("Running expressive engine"); let start_time = PreciseTime::now(); let (settings, state) = match input::json::read_expressive_state_from_file(STATE_PATH) { Ok(ok) => ok, @@ -20,3 +26,17 @@ fn main() { let max_time = Duration::milliseconds(1950); strategy::monte_carlo::choose_move(&settings, &state, &start_time, max_time); } + +fn bitwise() { + println!("Running bitwise engine"); + let start_time = PreciseTime::now(); + let (settings, state) = match input::json::read_bitwise_state_from_file(STATE_PATH) { + Ok(ok) => ok, + Err(error) => { + println!("Error while parsing JSON file: {}", error); + process::exit(1); + } + }; + let max_time = Duration::milliseconds(1950); + strategy::monte_carlo::choose_move(&settings, &state, &start_time, max_time); +} diff --git a/src/engine/bitwise_engine.rs b/src/engine/bitwise_engine.rs index e3ca4c6..31040bf 100644 --- a/src/engine/bitwise_engine.rs +++ b/src/engine/bitwise_engine.rs @@ -53,8 +53,6 @@ pub struct TeslaCooldown { } -const EMPTY: [Point; 0] = []; - impl GameState for BitwiseGameState { fn simulate(&mut self, settings: &GameSettings, player_command: Command, opponent_command: Command) -> GameStatus { BitwiseGameState::perform_command(settings, &mut self.player, &mut self.player_buildings, player_command); BitwiseGameState::perform_command(settings, &mut self.opponent, &mut self.opponent_buildings, opponent_command); @@ -82,8 +80,33 @@ impl GameState for BitwiseGameState { fn opponent(&self) -> &Player { &self.opponent } fn player_has_max_teslas(&self) -> bool { self.player_buildings.count_teslas() >= MAX_TESLAS } fn opponent_has_max_teslas(&self) -> bool { self.opponent_buildings.count_teslas() >= MAX_TESLAS } - fn unoccupied_player_cells(&self) -> &[Point] { &EMPTY } //TODO - fn unoccupied_opponent_cells(&self) -> &[Point] { &EMPTY } //TODO + + fn unoccupied_player_cell_count(&self) -> usize { self.player_buildings.occupied.count_zeros() as usize } + fn unoccupied_opponent_cell_count(&self) -> usize { self.opponent_buildings.occupied.count_zeros() as usize } + fn location_of_unoccupied_player_cell(&self, i: usize) -> Point { + let mut current = 0; + for bit in 0..64 { + let is_free = (1 << bit) & self.player_buildings.occupied == 0; + if is_free && current == i{ + return Point::new(bit%SINGLE_MAP_WIDTH, bit/SINGLE_MAP_WIDTH); + } else if is_free { + current += 1; + } + } + panic!("Didn't find indicated free bit for player"); + } + fn location_of_unoccupied_opponent_cell(&self, i: usize) -> Point { + let mut current = 0; + for bit in 0..64 { + let is_free = (1 << bit) & self.opponent_buildings.occupied == 0; + if is_free && current == i{ + return Point::new((bit%SINGLE_MAP_WIDTH) + SINGLE_MAP_WIDTH, bit/SINGLE_MAP_WIDTH); + } else if is_free { + current += 1; + } + } + panic!("Didn't find indicated free bit for opponent"); + } } impl BitwiseGameState { diff --git a/src/engine/expressive_engine.rs b/src/engine/expressive_engine.rs index 0640d58..b7d7bf2 100644 --- a/src/engine/expressive_engine.rs +++ b/src/engine/expressive_engine.rs @@ -89,8 +89,11 @@ impl GameState for ExpressiveGameState { fn opponent(&self) -> &Player { &self.opponent } fn player_has_max_teslas(&self) -> bool { self.count_player_teslas() >= 2 } fn opponent_has_max_teslas(&self) -> bool { self.count_opponent_teslas() >= 2 } - fn unoccupied_player_cells(&self) -> &[Point] { &self.unoccupied_player_cells } - fn unoccupied_opponent_cells(&self) -> &[Point] { &self.unoccupied_opponent_cells } + + fn unoccupied_player_cell_count(&self) -> usize { self.unoccupied_player_cells.len() } + fn unoccupied_opponent_cell_count(&self) -> usize { self.unoccupied_opponent_cells.len() } + fn location_of_unoccupied_player_cell(&self, i: usize) -> Point { self.unoccupied_player_cells[i] } + fn location_of_unoccupied_opponent_cell(&self, i: usize) -> Point { self.unoccupied_opponent_cells[i] } } impl ExpressiveGameState { diff --git a/src/engine/mod.rs b/src/engine/mod.rs index 39a5f26..d36d0e9 100644 --- a/src/engine/mod.rs +++ b/src/engine/mod.rs @@ -15,8 +15,11 @@ pub trait GameState: Clone + Sync { fn opponent(&self) -> &Player; fn player_has_max_teslas(&self) -> bool; fn opponent_has_max_teslas(&self) -> bool; - fn unoccupied_player_cells(&self) -> &[Point]; - fn unoccupied_opponent_cells(&self) -> &[Point]; + + fn unoccupied_player_cell_count(&self) -> usize; + fn unoccupied_opponent_cell_count(&self) -> usize; + fn location_of_unoccupied_player_cell(&self, i: usize) -> Point; + fn location_of_unoccupied_opponent_cell(&self, i: usize) -> Point; } #[derive(Debug, Clone, Copy, PartialEq, Eq)] diff --git a/src/input/json.rs b/src/input/json.rs index bebb5be..6f0d5e8 100644 --- a/src/input/json.rs +++ b/src/input/json.rs @@ -19,14 +19,15 @@ pub fn read_expressive_state_from_file(filename: &str) -> Result<(engine::settin Ok((engine_settings, engine_state)) } -pub fn read_bitwise_state_from_file(filename: &str) -> Result<bitwise_engine::BitwiseGameState, Box<Error>> { +pub fn read_bitwise_state_from_file(filename: &str) -> Result<(engine::settings::GameSettings, bitwise_engine::BitwiseGameState), Box<Error>> { let mut file = File::open(filename)?; let mut content = String::new(); file.read_to_string(&mut content)?; let state: State = serde_json::from_str(content.as_ref())?; + let engine_settings = state.to_engine_settings(); let engine_state = state.to_bitwise_engine(); - Ok(engine_state) + Ok((engine_settings, engine_state)) } #[derive(Deserialize)] diff --git a/src/strategy/monte_carlo.rs b/src/strategy/monte_carlo.rs index 19e663d..3dc94eb 100644 --- a/src/strategy/monte_carlo.rs +++ b/src/strategy/monte_carlo.rs @@ -81,17 +81,16 @@ fn simulate_to_endstate<R: Rng, GS: GameState>(command_score: &mut CommandScore, fn random_player_move<R: Rng, GS: GameState>(settings: &GameSettings, state: &GS, rng: &mut R) -> Command { let all_buildings = sensible_buildings(settings, &state.player(), state.player_has_max_teslas()); - random_move(&state.unoccupied_player_cells(), &all_buildings, rng) + random_move(&all_buildings, rng, state.unoccupied_player_cell_count(), |i| state.location_of_unoccupied_player_cell(i)) } fn random_opponent_move<R: Rng, GS: GameState>(settings: &GameSettings, state: &GS, rng: &mut R) -> Command { let all_buildings = sensible_buildings(settings, &state.opponent(), state.opponent_has_max_teslas()); - random_move(&state.unoccupied_opponent_cells(), &all_buildings, rng) + random_move(&all_buildings, rng, state.unoccupied_opponent_cell_count(), |i| state.location_of_unoccupied_opponent_cell(i)) } -fn random_move<R: Rng>(free_positions: &[Point], all_buildings: &[BuildingType], rng: &mut R) -> Command { - - let building_command_count = free_positions.len()*all_buildings.len(); +fn random_move<R: Rng, F:Fn(usize)->Point>(all_buildings: &[BuildingType], rng: &mut R, free_positions_count: usize, get_point: F) -> Command { + let building_command_count = free_positions_count*all_buildings.len(); let nothing_count = 1; let number_of_commands = building_command_count + nothing_count; @@ -102,7 +101,7 @@ fn random_move<R: Rng>(free_positions: &[Point], all_buildings: &[BuildingType], Command::Nothing } else { Command::Build( - free_positions[choice_index/all_buildings.len()], + get_point(choice_index/all_buildings.len()), all_buildings[choice_index%all_buildings.len()] ) } @@ -163,13 +162,15 @@ impl CommandScore { fn init_command_scores<GS: GameState>(settings: &GameSettings, state: &GS) -> Vec<CommandScore> { let all_buildings = sensible_buildings(settings, &state.player(), state.player_has_max_teslas()); - let building_command_count = state.unoccupied_player_cells().len()*all_buildings.len(); + let unoccupied_cells = (0..state.unoccupied_player_cell_count()).map(|i| state.location_of_unoccupied_player_cell(i)); + + let building_command_count = unoccupied_cells.len()*all_buildings.len(); let nothing_count = 1; let mut commands = Vec::with_capacity(building_command_count + nothing_count); commands.push(CommandScore::new(Command::Nothing)); - for &position in state.unoccupied_player_cells() { + for position in unoccupied_cells { for &building in &all_buildings { commands.push(CommandScore::new(Command::Build(position, building))); } |