summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJustin Worthe <justin@worthe-it.co.za>2018-06-09 10:27:29 +0200
committerJustin Worthe <justin@worthe-it.co.za>2018-06-09 10:27:29 +0200
commit088f0aeb23789ace5e9b77e75d5c23f5442e4cdc (patch)
tree9efefffa9ba20fce137c17f4f688ca7f572c9978 /src
parent9f0838006905fd039c4e0d87a69338f33e75246d (diff)
Added pruning of buying energy buildings behind a feature flag
Diffstat (limited to 'src')
-rw-r--r--src/engine/mod.rs59
-rw-r--r--src/strategy/mod.rs1
-rw-r--r--src/strategy/monte_carlo.rs6
-rw-r--r--src/strategy/sample.rs40
4 files changed, 31 insertions, 75 deletions
diff --git a/src/engine/mod.rs b/src/engine/mod.rs
index a649453..28583a1 100644
--- a/src/engine/mod.rs
+++ b/src/engine/mod.rs
@@ -8,6 +8,9 @@ use self::settings::{GameSettings, BuildingSettings};
use std::ops::FnMut;
+#[cfg(feature = "energy-cutoff")] pub const ENERGY_PRODUCTION_CUTOFF: f32 = 2.;
+#[cfg(feature = "energy-cutoff")] pub const ENERGY_STORAGE_CUTOFF: u16 = 10;
+
#[derive(Debug, Clone, PartialEq)]
pub struct GameState {
pub status: GameStatus,
@@ -259,24 +262,6 @@ impl GameState {
}
result
}
-
- pub fn player_affordable_buildings(&self, settings: &GameSettings) -> Vec<BuildingType> {
- GameState::affordable_buildings(self.player.energy, settings)
- }
-
- pub fn opponent_affordable_buildings(&self, settings: &GameSettings) -> Vec<BuildingType> {
- GameState::affordable_buildings(self.opponent.energy, settings)
- }
-
- fn affordable_buildings(energy: u16, settings: &GameSettings) -> Vec<BuildingType> {
- let mut result = Vec::with_capacity(3);
- for b in BuildingType::all().iter() {
- if settings.building_settings(*b).price <= energy {
- result.push(*b);
- }
- }
- result
- }
}
impl GameStatus {
@@ -293,21 +278,33 @@ impl Player {
energy_generated: settings.energy_income + buildings.iter().map(|b| b.energy_generated_per_turn).sum::<u16>()
}
}
-
- pub fn can_afford_all_buildings(&self, settings: &GameSettings) -> bool {
- self.can_afford_attack_buildings(settings) &&
- self.can_afford_defence_buildings(settings) &&
- self.can_afford_energy_buildings(settings)
- }
- pub fn can_afford_attack_buildings(&self, settings: &GameSettings) -> bool {
- self.energy >= settings.attack.price
- }
- pub fn can_afford_defence_buildings(&self, settings: &GameSettings) -> bool {
- self.energy >= settings.defence.price
+ #[cfg(not(feature = "energy-cutoff"))]
+ pub fn sensible_buildings(&self, settings: &GameSettings) -> Vec<BuildingType> {
+ let mut result = Vec::with_capacity(3);
+ for b in BuildingType::all().iter() {
+ if settings.building_settings(*b).price <= self.energy {
+ result.push(*b);
+ }
+ }
+ result
}
- pub fn can_afford_energy_buildings(&self, settings: &GameSettings) -> bool {
- self.energy >= settings.energy.price
+
+ #[cfg(feature = "energy-cutoff")]
+ pub fn sensible_buildings(&self, settings: &GameSettings) -> Vec<BuildingType> {
+ let mut result = Vec::with_capacity(3);
+ let needs_energy = self.energy_generated as f32 >= ENERGY_PRODUCTION_CUTOFF * settings.max_building_price as f32 &&
+ self.energy >= ENERGY_STORAGE_CUTOFF * settings.max_building_price;
+
+ for b in BuildingType::all().iter() {
+ let building_setting = settings.building_settings(*b);
+ let affordable = building_setting.price <= self.energy;
+ let energy_producing = building_setting.energy_generated_per_turn > 0;
+ if affordable && (!energy_producing || needs_energy) {
+ result.push(*b);
+ }
+ }
+ result
}
}
diff --git a/src/strategy/mod.rs b/src/strategy/mod.rs
index 9630c48..5b6e779 100644
--- a/src/strategy/mod.rs
+++ b/src/strategy/mod.rs
@@ -1,2 +1 @@
-pub mod sample;
pub mod monte_carlo;
diff --git a/src/strategy/monte_carlo.rs b/src/strategy/monte_carlo.rs
index c2f3561..0d813d3 100644
--- a/src/strategy/monte_carlo.rs
+++ b/src/strategy/monte_carlo.rs
@@ -75,12 +75,12 @@ fn simulate_to_endstate<R: Rng>(command_score: &mut CommandScore, settings: &Gam
}
fn random_player_move<R: Rng>(settings: &GameSettings, state: &GameState, rng: &mut R) -> Command {
- let all_buildings = state.player_affordable_buildings(settings);
+ let all_buildings = state.player.sensible_buildings(settings);
random_move(&state.unoccupied_player_cells, &all_buildings, rng)
}
fn random_opponent_move<R: Rng>(settings: &GameSettings, state: &GameState, rng: &mut R) -> Command {
- let all_buildings = state.opponent_affordable_buildings(settings);
+ let all_buildings = state.opponent.sensible_buildings(settings);
random_move(&state.unoccupied_opponent_cells, &all_buildings, rng)
}
@@ -151,7 +151,7 @@ impl CommandScore {
}
fn init_command_scores(settings: &GameSettings, state: &GameState) -> Vec<CommandScore> {
- let all_buildings = state.player_affordable_buildings(settings);
+ let all_buildings = state.player.sensible_buildings(settings);
let mut commands = Vec::with_capacity(state.unoccupied_player_cells.len()*all_buildings.len()+1);
commands.push(CommandScore::new(Command::Nothing));
diff --git a/src/strategy/sample.rs b/src/strategy/sample.rs
deleted file mode 100644
index 370df2f..0000000
--- a/src/strategy/sample.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-use engine;
-use engine::command::*;
-
-use rand::{thread_rng, Rng};
-
-pub fn choose_move(settings: &engine::settings::GameSettings, state: &engine::GameState) -> Command {
- let mut rng = thread_rng();
-
- if state.player.can_afford_defence_buildings(settings) {
- for y in 0..settings.size.y {
- if is_under_attack(state, y) {
- let p_options = state.unoccupied_player_cells_in_row(y);
- if let Some(&p) = rng.choose(&p_options) {
- return Command::Build(p, BuildingType::Defence);
- }
- }
- }
- }
-
- if state.player.can_afford_all_buildings(settings) {
- let option = rng.choose(&state.unoccupied_player_cells);
- let buildings = [BuildingType::Attack, BuildingType::Defence, BuildingType::Energy];
- let building = rng.choose(&buildings);
- match (option, building) {
- (Some(&p), Some(&building)) => Command::Build(p, building),
- _ => Command::Nothing
- }
- }
- else {
- Command::Nothing
- }
-}
-
-fn is_under_attack(state: &engine::GameState, y: u8) -> bool {
- let attack = state.opponent_buildings.iter()
- .any(|b| b.pos.y == y && b.weapon_damage > 0);
- let defences = state.player_buildings.iter()
- .any(|b| b.pos.y == y && b.health > 5);
- attack && !defences
-}