summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Cargo.toml11
-rw-r--r--Makefile7
-rw-r--r--benches/engine.rs164
-rw-r--r--src/bin/perf-test.rs46
-rw-r--r--src/strategy/monte_carlo.rs24
-rw-r--r--tests/bigstate.json1
7 files changed, 44 insertions, 210 deletions
diff --git a/.gitignore b/.gitignore
index cadf2dd..93caa35 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,4 @@ Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
/perf.data
+/perf.data.old
diff --git a/Cargo.toml b/Cargo.toml
index 264b2a9..92a7ad4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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 = []
diff --git a/Makefile b/Makefile
index a87c095..6391c1f 100644
--- 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
index 1f6c125..0000000
--- a/benches/engine.rs
+++ /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);
diff --git a/src/bin/perf-test.rs b/src/bin/perf-test.rs
index 835267e..03da160 100644
--- a/src/bin/perf-test.rs
+++ b/src/bin/perf-test.rs
@@ -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);
}
diff --git a/src/strategy/monte_carlo.rs b/src/strategy/monte_carlo.rs
index b7025c5..fe0462f 100644
--- a/src/strategy/monte_carlo.rs
+++ b/src/strategy/monte_carlo.rs
@@ -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
index 0000000..dd15670
--- /dev/null
+++ b/tests/bigstate.json
@@ -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"}]]}