summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Worthe <justin@worthe-it.co.za>2018-05-13 19:09:26 +0200
committerJustin Worthe <justin@worthe-it.co.za>2018-05-13 19:09:26 +0200
commitdd78789f242814bc750d886cc2d0c8f0877ade7c (patch)
tree049e9f24ec0b00c585fb21033525adb168b39405
parent02256124fbd57d88effd02c046093ecaf73b77e3 (diff)
Added initial benchmarks
There's a lot of room for improvement here. Specifically, I should separate the internal representation from the test interface. Have it provide functionality for creating random valid states.
-rw-r--r--Cargo.toml10
-rw-r--r--benches/engine.rs130
-rw-r--r--src/engine/mod.rs2
3 files changed, 140 insertions, 2 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 7703fc6..01abf5d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,4 +8,12 @@ serde = "1.0.43"
serde_json = "1.0.16"
rand = "0.4.2"
-time = "0.1.4" \ No newline at end of file
+time = "0.1.4"
+
+[dev-dependencies]
+criterion = "0.2"
+lazy_static = "1.0"
+
+[[bench]]
+name = "engine"
+harness = false \ No newline at end of file
diff --git a/benches/engine.rs b/benches/engine.rs
new file mode 100644
index 0000000..129d687
--- /dev/null
+++ b/benches/engine.rs
@@ -0,0 +1,130 @@
+#[macro_use]
+extern crate criterion;
+use criterion::Criterion;
+
+#[macro_use]
+extern crate lazy_static;
+
+extern crate zombot;
+use zombot::engine::{GameState, Player, GameStatus, Building};
+use zombot::engine::settings::{GameSettings, BuildingSettings};
+use zombot::engine::geometry::Point;
+use zombot::engine::command::{Command, BuildingType};
+
+extern crate rand;
+use rand::{thread_rng, Rng};
+
+fn create_example_state(settings: &GameSettings,
+ player_buildings: usize, opponent_buildings: usize,
+ _player_missiles: usize, _opponent_missiles: usize
+) -> GameState {
+ GameState {
+ status: GameStatus::Continue,
+ player: Player {
+ energy: 30,
+ health: 100
+ },
+ opponent: Player {
+ energy: 30,
+ health: 100
+ },
+ player_buildings: (0..player_buildings).map(|_| create_player_building(settings)).collect(),
+ opponent_buildings: (0..opponent_buildings).map(|_| create_player_building(settings)).collect(),
+ player_missiles: Vec::new(),
+ opponent_missiles: Vec::new()
+ }
+}
+
+fn create_example_settings() -> GameSettings {
+ GameSettings {
+ size: Point::new(10,10),
+ energy_income: 5,
+ energy: BuildingSettings {
+ price: 20,
+ health: 5,
+ construction_time: 1,
+ weapon_damage: 0,
+ weapon_speed: 0,
+ weapon_cooldown_period: 0,
+ energy_generated_per_turn: 3
+ },
+ defence: BuildingSettings {
+ price: 20,
+ health: 5,
+ construction_time: 1,
+ weapon_damage: 0,
+ weapon_speed: 0,
+ weapon_cooldown_period: 0,
+ energy_generated_per_turn: 3
+ },
+ attack: BuildingSettings {
+ price: 20,
+ health: 5,
+ construction_time: 1,
+ weapon_damage: 0,
+ weapon_speed: 0,
+ weapon_cooldown_period: 0,
+ energy_generated_per_turn: 3
+ }
+ }
+}
+
+fn create_player_building(settings: &GameSettings) -> Building {
+ let all_positions = (0..settings.size.y)
+ .flat_map(|y| (0..settings.size.x/2).map(|x| Point::new(x, y)).collect::<Vec<_>>())
+ .collect::<Vec<_>>();
+ let all_buildings = BuildingType::all();
+
+ let mut rng = thread_rng();
+ let position = rng.choose(&all_positions).unwrap();
+ let building = rng.choose(&all_buildings).unwrap();
+ let blueprint = settings.building_settings(*building);
+
+ Building::new(*position, blueprint)
+}
+
+fn create_opponent_building(settings: &GameSettings) -> Building {
+ let all_positions = (0..settings.size.y)
+ .flat_map(|y| (settings.size.x/2..settings.size.x).map(|x| Point::new(x, y)).collect::<Vec<_>>())
+ .collect::<Vec<_>>();
+ let all_buildings = BuildingType::all();
+
+ let mut rng = thread_rng();
+ let position = rng.choose(&all_positions).unwrap();
+ let building = rng.choose(&all_buildings).unwrap();
+ let blueprint = settings.building_settings(*building);
+
+ Building::new(*position, blueprint)
+}
+
+
+
+fn full_simulation_benchmark(c: &mut Criterion) {
+ let settings = create_example_settings();
+ let state = create_example_state(&settings, 5, 5, 0, 0);
+
+ let player_command = Command::Build(Point::new(0,0),BuildingType::Defence);
+ let opponent_command = Command::Build(Point::new(4,4),BuildingType::Energy);
+ c.bench_function("full simulation", move |b| b.iter(|| state.simulate(&settings, player_command, opponent_command)));
+}
+
+fn full_simulation_benchmark_against_number_of_buildings(c: &mut Criterion) {
+ let settings = create_example_settings();
+
+ lazy_static! {
+ static ref STATES: Vec<GameState> = {
+ let settings = create_example_settings();
+ (0..10)
+ .map(|i| create_example_state(&settings, i*2, 0, 0, 0))
+ .collect::<Vec<_>>()
+ };
+ }
+
+ let player_command = Command::Build(Point::new(0,0),BuildingType::Defence);
+ let opponent_command = Command::Build(Point::new(4,4),BuildingType::Energy);
+
+ c.bench_function_over_inputs("player buildings variable", move |b, &state_index| b.iter(|| STATES[state_index].simulate(&settings, player_command, opponent_command)), (0..STATES.len()));
+}
+
+criterion_group!(benches, full_simulation_benchmark, full_simulation_benchmark_against_number_of_buildings);
+criterion_main!(benches);
diff --git a/src/engine/mod.rs b/src/engine/mod.rs
index 41acb23..7b6db30 100644
--- a/src/engine/mod.rs
+++ b/src/engine/mod.rs
@@ -240,7 +240,7 @@ impl Player {
}
impl Building {
- fn new(pos: Point, blueprint: &BuildingSettings) -> Building {
+ pub fn new(pos: Point, blueprint: &BuildingSettings) -> Building {
Building {
pos: pos,
health: blueprint.health,