summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJustin Worthe <justin@worthe-it.co.za>2018-08-27 21:48:26 +0200
committerJustin Worthe <justin@worthe-it.co.za>2018-08-27 21:48:26 +0200
commitdbc008ad4d16072d181e0ac6949fab09a9c05801 (patch)
treea1e6cee3cfe705a7902b218ba48c6810bb20a53a /src
parentc90898da21e92da5f6c874eea9ed3aedf5330195 (diff)
Removed branching around energy limiting heuristics
Diffstat (limited to 'src')
-rw-r--r--src/engine/bitwise_engine.rs60
-rw-r--r--src/engine/constants.rs2
-rw-r--r--src/input/json.rs2
-rw-r--r--src/strategy/monte_carlo.rs59
4 files changed, 16 insertions, 107 deletions
diff --git a/src/engine/bitwise_engine.rs b/src/engine/bitwise_engine.rs
index f8af86d..628fefc 100644
--- a/src/engine/bitwise_engine.rs
+++ b/src/engine/bitwise_engine.rs
@@ -34,8 +34,6 @@ pub struct Player {
pub iron_curtain_available: bool,
pub iron_curtain_remaining: u8,
-
- pub energy_towers_with_heuristics: u64,
}
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -75,9 +73,6 @@ impl BitwiseGameState {
BitwiseGameState::update_iron_curtain(&mut self.player, self.round);
BitwiseGameState::update_iron_curtain(&mut self.opponent, self.round);
- self.player.update_energy_towers_with_heuristics();
- self.opponent.update_energy_towers_with_heuristics();
-
self.round += 1;
self.update_status();
@@ -436,7 +431,6 @@ impl Player {
tesla_cooldowns: ArrayVec::new(),
iron_curtain_available: false,
iron_curtain_remaining: 0,
- energy_towers_with_heuristics: 0
}
}
@@ -459,58 +453,4 @@ impl Player {
debug_assert!(point.to_either_bitfield() & self.occupied == 0);
point
}
-
- pub fn update_energy_towers_with_heuristics(&mut self) {
- self.energy_towers_with_heuristics = self.occupied;
- for y in 0..MAP_HEIGHT {
- let mask = 255u64 << (y*SINGLE_MAP_WIDTH);
- let isolated_row = self.energy_towers & mask;
- let row_count = isolated_row.count_ones();
- self.energy_towers_with_heuristics |= if row_count >= ENERGY_MAX_IN_ROW {
- mask
- } else {
- 0
- };
- }
- }
-
- pub fn unoccupied_energy_cell_count(&self) -> usize {
- self.energy_towers_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_towers_with_heuristics, i as u64);
- let point = Point { index: bit };
- debug_assert!(point.to_either_bitfield() & self.occupied == 0);
- point
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn energy_occupied_marks_empty_rows_appropriately() {
- let mut player = Player::empty();
- player.energy_towers = 0;
- player.occupied = 0;
- player.update_energy_towers_with_heuristics();
-
- let expected = 0;
- let actual = player.energy_towers_with_heuristics;
-
- assert_eq!(expected, actual);
- }
- #[test]
- fn energy_occupied_marks_full_first_row_appropriately() {
- let mut player = Player::empty();
- player.energy_towers = 0x00_07; //3 energy towers in first row, don't build more
- player.occupied = 0x07_07; //3 more towers in second row, can still build by them
- player.update_energy_towers_with_heuristics();
-
- let expected = 0x07_ff;
- let actual = player.energy_towers_with_heuristics;
-
- assert_eq!(expected, actual);
- }
}
diff --git a/src/engine/constants.rs b/src/engine/constants.rs
index 71d937d..9ece36d 100644
--- a/src/engine/constants.rs
+++ b/src/engine/constants.rs
@@ -26,8 +26,6 @@ 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 = 3;
-
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/input/json.rs b/src/input/json.rs
index 6c83563..843f228 100644
--- a/src/input/json.rs
+++ b/src/input/json.rs
@@ -137,8 +137,6 @@ impl State {
}
}
}
- player.update_energy_towers_with_heuristics();
- opponent.update_energy_towers_with_heuristics();
bitwise_engine::BitwiseGameState::new(
player, opponent,
diff --git a/src/strategy/monte_carlo.rs b/src/strategy/monte_carlo.rs
index 27caea8..7672dff 100644
--- a/src/strategy/monte_carlo.rs
+++ b/src/strategy/monte_carlo.rs
@@ -2,6 +2,7 @@ use engine::command::*;
use engine::status::GameStatus;
use engine::bitwise_engine::{Player, BitwiseGameState};
use engine::constants::*;
+use engine::geometry::*;
use std::fmt;
@@ -18,7 +19,7 @@ use time::{Duration, PreciseTime};
use rayon::prelude::*;
//TODO Rethink / adjust these?
-#[cfg(feature = "energy-cutoff")] pub const ENERGY_PRODUCTION_CUTOFF: u16 = 100;
+#[cfg(feature = "energy-cutoff")] pub const ENERGY_PRODUCTION_CUTOFF: u16 = 50;
#[cfg(feature = "energy-cutoff")] pub const ENERGY_STORAGE_CUTOFF: u16 = 100;
pub fn choose_move(state: &BitwiseGameState, start_time: PreciseTime, max_time: Duration) -> Command {
@@ -162,30 +163,17 @@ fn simulate_to_endstate<R: Rng>(command_score: &mut CommandScore, state: &Bitwis
fn random_move<R: Rng>(player: &Player, rng: &mut R) -> Command {
let free_positions_count = player.unoccupied_cell_count();
- let unoccupied_energy_cell_count = player.unoccupied_energy_cell_count();
- let open_energy_spot = unoccupied_energy_cell_count > 0;
let open_building_spot = free_positions_count > 0;
- let all_buildings = sensible_buildings(player, open_building_spot, open_energy_spot);
+ let all_buildings = sensible_buildings(player, open_building_spot);
let iron_curtain_count = if player.can_build_iron_curtain() { 5 } else { 0 };
let nothing_count = 1;
let building_choice_index = rng.gen_range(0, all_buildings.len() + nothing_count + iron_curtain_count);
- let choice_is_building = building_choice_index < all_buildings.len();
- let choice_is_energy = choice_is_building && all_buildings[building_choice_index] == BuildingType::Energy;
-
- if choice_is_energy {
- 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 choice_is_building {
+ if building_choice_index < all_buildings.len() {
let position_choice = rng.gen_range(0, free_positions_count);
Command::Build(
player.location_of_unoccupied_cell(position_choice),
@@ -223,18 +211,6 @@ impl CommandScore {
}
}
- fn with_seeded_stalemate(command: Command) -> CommandScore {
- CommandScore {
- command,
- victories: 0,
- defeats: 0,
- draws: 0,
- stalemates: 0,
- attempts: 1,
- next_seed: INIT_SEED
- }
- }
-
fn add_victory(&mut self, next_seed: [u8; 16]) {
self.victories += 1;
self.attempts += 1;
@@ -264,14 +240,13 @@ impl CommandScore {
}
fn init_command_scores(state: &BitwiseGameState) -> Vec<CommandScore> {
- 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 open_building_spot = unoccupied_cells.len() > 0;
- let open_energy_spot = unoccupied_energy_cells.len() > 0;
+ let unoccupied_cells_count = state.player.unoccupied_cell_count();
+ let unoccupied_cells = (0..unoccupied_cells_count)
+ .map(|i| state.player.location_of_unoccupied_cell(i));
+ let open_building_spot = unoccupied_cells_count > 0;
- let all_buildings = sensible_buildings(&state.player, open_building_spot, open_energy_spot);
+ let all_buildings = sensible_buildings(&state.player, open_building_spot);
let building_command_count = unoccupied_cells.len()*all_buildings.len();
@@ -281,11 +256,9 @@ impl CommandScore {
commands.push(CommandScore::new(Command::IronCurtain));
}
- 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)));
+ for position in unoccupied_cells {
+ for &building in &all_buildings {
+ commands.push(CommandScore::new(Command::Build(position, building)));
}
}
@@ -301,7 +274,7 @@ impl fmt::Display for CommandScore {
#[cfg(not(feature = "energy-cutoff"))]
-fn sensible_buildings(player: &Player, open_building_spot: bool, open_energy_spot: bool) -> ArrayVec<[BuildingType;4]> {
+fn sensible_buildings(player: &Player, open_building_spot: bool) -> ArrayVec<[BuildingType;4]> {
let mut result = ArrayVec::new();
if !open_building_spot {
return result;
@@ -313,7 +286,7 @@ fn sensible_buildings(player: &Player, open_building_spot: bool, open_energy_spo
if MISSILE_PRICE <= player.energy {
result.push(BuildingType::Attack);
}
- if ENERGY_PRICE <= player.energy && open_energy_spot {
+ if ENERGY_PRICE <= player.energy {
result.push(BuildingType::Energy);
}
if TESLA_PRICE <= player.energy && !player.has_max_teslas() {
@@ -324,7 +297,7 @@ fn sensible_buildings(player: &Player, open_building_spot: bool, open_energy_spo
}
#[cfg(feature = "energy-cutoff")]
-fn sensible_buildings(player: &Player, open_building_spot: bool, open_energy_spot: bool) -> ArrayVec<[BuildingType;4]> {
+fn sensible_buildings(player: &Player, open_building_spot: bool) -> ArrayVec<[BuildingType;4]> {
let mut result = ArrayVec::new();
if !open_building_spot {
return result;
@@ -339,7 +312,7 @@ fn sensible_buildings(player: &Player, open_building_spot: bool, open_energy_spo
if MISSILE_PRICE <= player.energy {
result.push(BuildingType::Attack);
}
- if ENERGY_PRICE <= player.energy && open_energy_spot && needs_energy {
+ if ENERGY_PRICE <= player.energy && needs_energy {
result.push(BuildingType::Energy);
}
if TESLA_PRICE <= player.energy && !player.has_max_teslas() {