Moved away from special benchmarking suite
authorJustin Worthe <justin@worthe-it.co.za>
Tue, 15 May 2018 22:01:27 +0000 (00:01 +0200)
committerJustin Worthe <justin@worthe-it.co.za>
Tue, 15 May 2018 22:01:27 +0000 (00:01 +0200)
Just using normal monte carlo. More iterations -> better.

.gitignore
Cargo.toml
Makefile
benches/engine.rs [deleted file]
src/bin/perf-test.rs
src/strategy/monte_carlo.rs
tests/bigstate.json [new file with mode: 0644]

index cadf2dd..93caa35 100644 (file)
@@ -9,3 +9,4 @@ Cargo.lock
 # These are backup files generated by rustfmt
 **/*.rs.bk
 /perf.data
+/perf.data.old
index 264b2a9..92a7ad4 100644 (file)
@@ -11,16 +11,9 @@ rand = "0.4.2"
 time = "0.1.4"
 rayon = "1.0.1"
 
-[dev-dependencies]
-criterion = "0.2"
-lazy_static = "1.0"
-
-[[bench]]
-name = "engine"
-harness = false
-
 [profile.release]
 debug = true
 
 [features]
-benchmarking = []
\ No newline at end of file
+benchmarking = []
+single-threaded = []
index a87c095..6391c1f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -4,8 +4,11 @@ build:
 test:
        cargo test --release
 
+bench:
+       cargo run --release --features "benchmarking" --bin perf-test
+
 profile:
-       cargo build --release --features "benchmarking"
+       cargo build --release --features "benchmarking single-threaded"
        mkdir -p target/profile
        sudo perf record -F 1000 -a -g target/release/perf-test
        sudo perf script > target/profile/out.perf
@@ -16,4 +19,4 @@ clean:
        cargo clean
 
 
-.PHONY: build test profile clean
+.PHONY: build test bench profile clean
diff --git a/benches/engine.rs b/benches/engine.rs
deleted file mode 100644 (file)
index 1f6c125..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-#[macro_use]
-extern crate criterion;
-use criterion::Criterion;
-
-#[macro_use]
-extern crate lazy_static;
-
-extern crate zombot;
-use zombot::engine::{GameState, Player, GameStatus, Building, Missile};
-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: (0..player_missiles).map(|_| create_missile(settings)).collect(),
-        opponent_missiles: (0..opponent_missiles).map(|_| create_missile(settings)).collect()
-    }
-}
-
-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 create_missile(settings: &GameSettings) -> Missile {
-    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 mut rng = thread_rng();
-    let position = rng.choose(&all_positions).unwrap();
-
-    Missile {
-        pos: *position,
-        damage: 5,
-        speed: 1
-    }
-}
-
-
-fn full_simulation_benchmark(c: &mut Criterion) {
-    let settings = create_example_settings();
-    let state = create_example_state(&settings, 5, 5, 5, 5);
-    
-    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()));
-}
-
-fn full_simulation_benchmark_against_number_of_missiles(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, 2, 5, i*2, i*2))
-                .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 missiles 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,
-                 full_simulation_benchmark_against_number_of_missiles);
-criterion_main!(benches);
index 835267e..03da160 100644 (file)
@@ -3,35 +3,20 @@ extern crate time;
 use time::{PreciseTime, Duration};
 
 use zombot::*;
-use zombot::engine::command::Command;
-
-use std::error::Error;
 
 const STATE_PATH: &str = "tests/state0.json";
+const STATE_BIG_PATH: &str = "tests/bigstate.json";
 
-const COMMAND_PATH: &str = "command.txt";
-
-use std::fs::File;
-use std::io::prelude::*;
 use std::process;
 
-fn choose_move(settings: &engine::settings::GameSettings, state: &engine::GameState, start_time: &PreciseTime) -> Command {
-    let max_time = Duration::milliseconds(1950);
-    strategy::monte_carlo::choose_move(settings, state, start_time, max_time)
-}
-
-
-fn write_command(filename: &str, command: Command) -> Result<(), Box<Error> > {
-    let mut file = File::create(filename)?;
-    write!(file, "{}", command)?;
-    Ok(())
+fn main() {
+    normal_state();
+    big_state();
 }
 
-
-fn main() {
+fn normal_state() {
+    println!("Normal size state file");
     let start_time = PreciseTime::now();
-    
-    println!("Reading in state.json file");
     let (settings, state) = match json::read_state_from_file(STATE_PATH) {
         Ok(ok) => ok,
         Err(error) => {
@@ -39,15 +24,20 @@ fn main() {
             process::exit(1);
         }
     };
-    let command = choose_move(&settings, &state, &start_time);
+    let max_time = Duration::milliseconds(1950);
+    strategy::monte_carlo::choose_move(&settings, &state, &start_time, max_time);
+}
 
-    match write_command(COMMAND_PATH, command) {
-        Ok(()) => {}
+fn big_state() {
+    println!("Big state file");
+    let start_time = PreciseTime::now();
+    let (settings, state) = match json::read_state_from_file(STATE_BIG_PATH) {
+        Ok(ok) => ok,
         Err(error) => {
-            println!("Error while writing command file: {}", error);
+            println!("Error while parsing JSON file: {}", error);
             process::exit(1);
         }
-    }
-
-    println!("Elapsed time: {}", start_time.to(PreciseTime::now()));
+    };
+    let max_time = Duration::milliseconds(1950);
+    strategy::monte_carlo::choose_move(&settings, &state, &start_time, max_time);
 }
index b7025c5..fe0462f 100644 (file)
@@ -8,19 +8,29 @@ const MAX_MOVES: u16 = 400;
 
 use time::{Duration, PreciseTime};
 
+#[cfg(not(feature = "single-threaded"))]
 use rayon::prelude::*;
 
 pub fn choose_move(settings: &GameSettings, state: &GameState, start_time: &PreciseTime, max_time: Duration) -> Command {
-    println!("Using MONTE_CARLO strategy");
-    
     let mut command_scores = CommandScore::init_command_scores(settings, state);
 
     loop {
-        command_scores.par_iter_mut()
-            .for_each(|score| {
-                let mut rng = thread_rng();
-                simulate_to_endstate(score, settings, state, &mut rng);
-            });
+        #[cfg(feature = "single-threaded")]
+        {
+            command_scores.iter_mut()
+                .for_each(|score| {
+                    let mut rng = thread_rng();
+                    simulate_to_endstate(score, settings, state, &mut rng);
+                });
+        }
+        #[cfg(not(feature = "single-threaded"))]
+        {
+            command_scores.par_iter_mut()
+                .for_each(|score| {
+                    let mut rng = thread_rng();
+                    simulate_to_endstate(score, settings, state, &mut rng);
+                });
+        }
         if start_time.to(PreciseTime::now()) > max_time {
             break;
         }
diff --git a/tests/bigstate.json b/tests/bigstate.json
new file mode 100644 (file)
index 0000000..dd15670
--- /dev/null
@@ -0,0 +1 @@
+{"gameDetails":{"round":0,"mapWidth":20,"mapHeight":10,"roundIncomeEnergy":5,"buildingPrices":{"ENERGY":20,"ATTACK":30,"DEFENSE":30},"buildingsStats":{"ENERGY":{"health":5,"constructionTime":2,"price":20,"weaponDamage":0,"weaponSpeed":0,"weaponCooldownPeriod":0,"energyGeneratedPerTurn":3,"destroyMultiplier":1,"constructionScore":1},"ATTACK":{"health":5,"constructionTime":2,"price":30,"weaponDamage":5,"weaponSpeed":1,"weaponCooldownPeriod":3,"energyGeneratedPerTurn":0,"destroyMultiplier":1,"constructionScore":1},"DEFENSE":{"health":20,"constructionTime":4,"price":30,"weaponDamage":0,"weaponSpeed":0,"weaponCooldownPeriod":0,"energyGeneratedPerTurn":0,"destroyMultiplier":1,"constructionScore":1}}},"players":[{"playerType":"A","energy":20,"health":100,"hitsTaken":0,"score":0},{"playerType":"B","energy":20,"health":100,"hitsTaken":0,"score":0}],"gameMap":[[{"x":0,"y":0,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":1,"y":0,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":2,"y":0,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":3,"y":0,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":4,"y":0,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":5,"y":0,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":6,"y":0,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":7,"y":0,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":8,"y":0,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":9,"y":0,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":10,"y":0,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":11,"y":0,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":12,"y":0,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":13,"y":0,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":14,"y":0,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":15,"y":0,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":16,"y":0,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":17,"y":0,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":18,"y":0,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":19,"y":0,"buildings":[],"missiles":[],"cellOwner":"B"}],[{"x":0,"y":1,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":1,"y":1,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":2,"y":1,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":3,"y":1,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":4,"y":1,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":5,"y":1,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":6,"y":1,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":7,"y":1,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":8,"y":1,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":9,"y":1,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":10,"y":1,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":11,"y":1,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":12,"y":1,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":13,"y":1,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":14,"y":1,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":15,"y":1,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":16,"y":1,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":17,"y":1,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":18,"y":1,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":19,"y":1,"buildings":[],"missiles":[],"cellOwner":"B"}],[{"x":0,"y":2,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":1,"y":2,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":2,"y":2,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":3,"y":2,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":4,"y":2,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":5,"y":2,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":6,"y":2,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":7,"y":2,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":8,"y":2,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":9,"y":2,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":10,"y":2,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":11,"y":2,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":12,"y":2,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":13,"y":2,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":14,"y":2,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":15,"y":2,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":16,"y":2,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":17,"y":2,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":18,"y":2,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":19,"y":2,"buildings":[],"missiles":[],"cellOwner":"B"}],[{"x":0,"y":3,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":1,"y":3,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":2,"y":3,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":3,"y":3,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":4,"y":3,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":5,"y":3,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":6,"y":3,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":7,"y":3,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":8,"y":3,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":9,"y":3,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":10,"y":3,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":11,"y":3,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":12,"y":3,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":13,"y":3,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":14,"y":3,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":15,"y":3,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":16,"y":3,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":17,"y":3,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":18,"y":3,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":19,"y":3,"buildings":[],"missiles":[],"cellOwner":"B"}],[{"x":0,"y":4,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":1,"y":4,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":2,"y":4,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":3,"y":4,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":4,"y":4,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":5,"y":4,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":6,"y":4,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":7,"y":4,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":8,"y":4,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":9,"y":4,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":10,"y":4,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":11,"y":4,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":12,"y":4,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":13,"y":4,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":14,"y":4,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":15,"y":4,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":16,"y":4,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":17,"y":4,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":18,"y":4,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":19,"y":4,"buildings":[],"missiles":[],"cellOwner":"B"}],[{"x":0,"y":5,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":1,"y":5,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":2,"y":5,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":3,"y":5,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":4,"y":5,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":5,"y":5,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":6,"y":5,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":7,"y":5,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":8,"y":5,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":9,"y":5,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":10,"y":5,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":11,"y":5,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":12,"y":5,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":13,"y":5,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":14,"y":5,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":15,"y":5,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":16,"y":5,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":17,"y":5,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":18,"y":5,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":19,"y":5,"buildings":[],"missiles":[],"cellOwner":"B"}],[{"x":0,"y":6,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":1,"y":6,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":2,"y":6,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":3,"y":6,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":4,"y":6,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":5,"y":6,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":6,"y":6,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":7,"y":6,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":8,"y":6,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":9,"y":6,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":10,"y":6,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":11,"y":6,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":12,"y":6,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":13,"y":6,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":14,"y":6,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":15,"y":6,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":16,"y":6,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":17,"y":6,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":18,"y":6,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":19,"y":6,"buildings":[],"missiles":[],"cellOwner":"B"}],[{"x":0,"y":7,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":1,"y":7,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":2,"y":7,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":3,"y":7,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":4,"y":7,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":5,"y":7,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":6,"y":7,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":7,"y":7,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":8,"y":7,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":9,"y":7,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":10,"y":7,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":11,"y":7,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":12,"y":7,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":13,"y":7,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":14,"y":7,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":15,"y":7,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":16,"y":7,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":17,"y":7,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":18,"y":7,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":19,"y":7,"buildings":[],"missiles":[],"cellOwner":"B"}],[{"x":0,"y":8,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":1,"y":8,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":2,"y":8,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":3,"y":8,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":4,"y":8,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":5,"y":8,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":6,"y":8,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":7,"y":8,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":8,"y":8,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":9,"y":8,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":10,"y":8,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":11,"y":8,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":12,"y":8,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":13,"y":8,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":14,"y":8,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":15,"y":8,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":16,"y":8,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":17,"y":8,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":18,"y":8,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":19,"y":8,"buildings":[],"missiles":[],"cellOwner":"B"}],[{"x":0,"y":9,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":1,"y":9,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":2,"y":9,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":3,"y":9,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":4,"y":9,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":5,"y":9,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":6,"y":9,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":7,"y":9,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":8,"y":9,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":9,"y":9,"buildings":[],"missiles":[],"cellOwner":"A"},{"x":10,"y":9,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":11,"y":9,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":12,"y":9,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":13,"y":9,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":14,"y":9,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":15,"y":9,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":16,"y":9,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":17,"y":9,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":18,"y":9,"buildings":[],"missiles":[],"cellOwner":"B"},{"x":19,"y":9,"buildings":[],"missiles":[],"cellOwner":"B"}]]}