Implemented maximum number of energy buildings in a row
authorJustin Worthe <justin@worthe-it.co.za>
Sat, 18 Aug 2018 20:18:01 +0000 (22:18 +0200)
committerJustin Worthe <justin@worthe-it.co.za>
Sat, 18 Aug 2018 20:18:01 +0000 (22:18 +0200)
src/engine/bitwise_engine.rs
src/engine/constants.rs
src/strategy/monte_carlo.rs

index a4842ec..27c1bd8 100644 (file)
@@ -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
+    }
 }
index 9ece36d..60e8101 100644 (file)
@@ -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;
index f937ea1..6599212 100644 (file)
@@ -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<R: Rng>(command_score: &mut CommandScore, state: &Bitwis
 fn random_move<R: Rng>(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<CommandScore> {
         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::<Vec<_>>();
+        let unoccupied_energy_cells = (0..state.player.unoccupied_energy_cell_count()).map(|i| state.player.location_of_unoccupied_energy_cell(i)).collect::<Vec<_>>();
 
         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<BuildingType> {
     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<BuildingType> {
     let mut result = Vec::with_capacity(4);