From 0c1636355918a82df0ec188252c8f90487206c7b Mon Sep 17 00:00:00 2001 From: Justin Worthe Date: Sat, 18 Aug 2018 22:18:01 +0200 Subject: Implemented maximum number of energy buildings in a row --- src/engine/bitwise_engine.rs | 25 +++++++++++++++++++++++++ src/engine/constants.rs | 2 ++ src/strategy/monte_carlo.rs | 26 +++++++++++++++++++------- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/engine/bitwise_engine.rs b/src/engine/bitwise_engine.rs index a4842ec..27c1bd8 100644 --- a/src/engine/bitwise_engine.rs +++ b/src/engine/bitwise_engine.rs @@ -453,4 +453,29 @@ impl Player { debug_assert!(point.to_either_bitfield() & self.occupied == 0); point } + + pub fn energy_occupied_energy_with_heuristics(&self) -> u64 { + let mut result = 0; + for y in 0..MAP_HEIGHT { + let mask = 255 << y*SINGLE_MAP_WIDTH; + let isolated_row = self.energy_towers & mask; + let row_count = isolated_row.count_ones(); + result |= if row_count > ENERGY_MAX_IN_ROW { + mask + } else { + self.occupied & mask + }; + } + result + } + + pub fn unoccupied_energy_cell_count(&self) -> usize { + self.energy_occupied_energy_with_heuristics().count_zeros() as usize + } + pub fn location_of_unoccupied_energy_cell(&self, i: usize) -> Point { + let bit = find_bit_index_from_rank(self.energy_occupied_energy_with_heuristics(), i as u64); + let point = Point { index: bit }; + debug_assert!(point.to_either_bitfield() & self.occupied == 0); + point + } } diff --git a/src/engine/constants.rs b/src/engine/constants.rs index 9ece36d..60e8101 100644 --- a/src/engine/constants.rs +++ b/src/engine/constants.rs @@ -26,6 +26,8 @@ pub const ENERGY_GENERATED_TOWER: u16 = 3; pub const ENERGY_PRICE: u16 = 20; pub const ENERGY_CONSTRUCTION_TIME: u8 = 1; +pub const ENERGY_MAX_IN_ROW: u32 = 2; + pub const IRON_CURTAIN_PRICE: u16 = 100; pub const IRON_CURTAIN_UNLOCK_INTERVAL: u16 = 30; pub const IRON_CURTAIN_DURATION: u8 = 6; diff --git a/src/strategy/monte_carlo.rs b/src/strategy/monte_carlo.rs index f937ea1..6599212 100644 --- a/src/strategy/monte_carlo.rs +++ b/src/strategy/monte_carlo.rs @@ -1,7 +1,6 @@ use engine::command::*; use engine::status::GameStatus; use engine::bitwise_engine::{Player, BitwiseGameState}; -use engine::geometry::*; use engine::constants::*; use std::fmt; @@ -162,13 +161,24 @@ fn simulate_to_endstate(command_score: &mut CommandScore, state: &Bitwis fn random_move(player: &Player, rng: &mut R) -> Command { let all_buildings = sensible_buildings(player); let free_positions_count = player.unoccupied_cell_count(); + let unoccupied_energy_cell_count = player.unoccupied_energy_cell_count(); let nothing_count = if all_buildings.len() > 2 && free_positions_count > 0 { 0 } else { 1 }; let iron_curtain_count = if player.can_build_iron_curtain() { 1 } else { 0 }; let building_choice_index = rng.gen_range(0, all_buildings.len() + nothing_count + iron_curtain_count); - if building_choice_index < all_buildings.len() && free_positions_count > 0 { + if building_choice_index < all_buildings.len() + && all_buildings[building_choice_index] == BuildingType::Energy + && unoccupied_energy_cell_count > 0 { + let position_choice = rng.gen_range(0, unoccupied_energy_cell_count); + Command::Build( + player.location_of_unoccupied_energy_cell(position_choice), + BuildingType::Energy + ) + + } + else if building_choice_index < all_buildings.len() && free_positions_count > 0 { let position_choice = rng.gen_range(0, free_positions_count); Command::Build( player.location_of_unoccupied_cell(position_choice), @@ -249,7 +259,8 @@ impl CommandScore { fn init_command_scores(state: &BitwiseGameState) -> Vec { let all_buildings = sensible_buildings(&state.player); - let unoccupied_cells = (0..state.player.unoccupied_cell_count()).map(|i| state.player.location_of_unoccupied_cell(i)); + let unoccupied_cells = (0..state.player.unoccupied_cell_count()).map(|i| state.player.location_of_unoccupied_cell(i)).collect::>(); + let unoccupied_energy_cells = (0..state.player.unoccupied_energy_cell_count()).map(|i| state.player.location_of_unoccupied_energy_cell(i)).collect::>(); let building_command_count = unoccupied_cells.len()*all_buildings.len(); @@ -259,9 +270,11 @@ impl CommandScore { commands.push(CommandScore::new(Command::IronCurtain)); } - for position in unoccupied_cells { - for &building in &all_buildings { - commands.push(CommandScore::new(Command::Build(position, building))); + for &building in &all_buildings { + let cells = if building == BuildingType::Energy { &unoccupied_energy_cells } else { &unoccupied_cells }; + for position in cells { + + commands.push(CommandScore::new(Command::Build(*position, building))); } } @@ -296,7 +309,6 @@ fn sensible_buildings(player: &Player) -> Vec { result } -//TODO: Heuristic that avoids building the initial energy towers all in the same row? Max energy in a row? #[cfg(feature = "energy-cutoff")] fn sensible_buildings(player: &Player) -> Vec { let mut result = Vec::with_capacity(4); -- cgit v1.2.3