summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorJustin Worthe <justin@worthe-it.co.za>2018-08-09 13:10:14 +0200
committerJustin Worthe <justin@worthe-it.co.za>2018-08-09 13:10:14 +0200
commitf41255a8dda9e2c6a18c32564a30e63eed58f6b3 (patch)
tree0f3a334c71c2d88d397ac6c8058488570fc85def /tests
parent72a86bb4c043b6316e5c5f163cdd1e66cb99229f (diff)
Removed expressive engine
Refocus on the bitwise idea. It's faster, and has more potential for speed. Also, it works well as a way of thinking on the puzzle as a whole.
Diffstat (limited to 'tests')
-rw-r--r--tests/expressive_to_bitwise_comparison.rs256
1 files changed, 0 insertions, 256 deletions
diff --git a/tests/expressive_to_bitwise_comparison.rs b/tests/expressive_to_bitwise_comparison.rs
deleted file mode 100644
index 72b5731..0000000
--- a/tests/expressive_to_bitwise_comparison.rs
+++ /dev/null
@@ -1,256 +0,0 @@
-extern crate zombot;
-
-#[macro_use] extern crate proptest;
-extern crate rand;
-
-use zombot::input;
-use zombot::engine::command::{Command, BuildingType};
-use zombot::engine::geometry::Point;
-use zombot::engine::settings::GameSettings;
-use zombot::engine::{GameState, GameStatus, Player};
-
-use zombot::engine::expressive_engine;
-use zombot::engine::bitwise_engine;
-use zombot::engine::constants::*;
-
-use proptest::prelude::*;
-
-use rand::{Rng, XorShiftRng, SeedableRng};
-
-
-const STATE_PATH: &str = "tests/state0.json";
-
-#[test]
-fn reads_into_bitwise_correctly() {
- test_reading_from_replay("tests/after_200", 64);
-}
-
-fn test_reading_from_replay(replay_folder: &str, length: usize) {
- for i in 0..length {
- let state_file = format!("{}/Round {:03}/state.json", replay_folder, i);
-
- let (_, expressive_state) = input::json::read_expressive_state_from_file(&state_file).expect("Failed to load expressive state");
- let (_, bitwise_state) = input::json::read_bitwise_state_from_file(&state_file).expect("Failed to load bitwise state");
-
- assert_eq!(build_bitwise_from_expressive(&expressive_state), bitwise_state.clone(), "\nFailed on state {}\n", i);
- }
-}
-
-
-proptest! {
- #[test]
- fn follows_the_same_random_game_tree(seed in any::<[u32;4]>()) {
- let mut rng = XorShiftRng::from_seed(seed);
-
- let (settings, mut expressive_state) = input::json::read_expressive_state_from_file(STATE_PATH).expect("Failed to load expressive state");
- let (_, mut bitwise_state) = input::json::read_bitwise_state_from_file(STATE_PATH).expect("Failed to load bitwise state");
-
- expressive_state.sort();
-
- let mut expected_status = GameStatus::Continue;
- while expected_status == GameStatus::Continue {
- let player_command = random_player_move(&settings, &expressive_state, &bitwise_state, &mut rng);
- let opponent_command = random_opponent_move(&settings, &expressive_state, &bitwise_state, &mut rng);
- println!("Player command: {}", player_command);
- println!("Opponent command: {}", opponent_command);
-
- expected_status = expressive_state.simulate(&settings, player_command, opponent_command);
- let actual_status = bitwise_state.simulate(&settings, player_command, opponent_command);
-
- expressive_state.sort();
-
- assert_eq!(&expected_status, &actual_status);
- assert_eq!(build_bitwise_from_expressive(&expressive_state), bitwise_state.sorted());
- }
- }
-}
-
-fn random_player_move<R: Rng, GSE: GameState, GSB: GameState>(settings: &GameSettings, expressive_state: &GSE, bitwise_state: &GSB, rng: &mut R) -> Command {
- assert_eq!(expressive_state.player_has_max_teslas(), bitwise_state.player_has_max_teslas());
- let all_buildings = sensible_buildings(settings, &expressive_state.player(), expressive_state.player_has_max_teslas());
- random_move(&all_buildings, rng, expressive_state.unoccupied_player_cell_count(), |i| expressive_state.location_of_unoccupied_player_cell(i), |i| bitwise_state.location_of_unoccupied_player_cell(i))
-}
-
-fn random_opponent_move<R: Rng, GSE: GameState, GSB: GameState>(settings: &GameSettings, expressive_state: &GSE, bitwise_state: &GSB, rng: &mut R) -> Command {
- assert_eq!(expressive_state.player_has_max_teslas(), bitwise_state.player_has_max_teslas());
- let all_buildings = sensible_buildings(settings, &expressive_state.opponent(), expressive_state.opponent_has_max_teslas());
- random_move(&all_buildings, rng, expressive_state.unoccupied_opponent_cell_count(), |i| expressive_state.location_of_unoccupied_opponent_cell(i), |i| bitwise_state.location_of_unoccupied_opponent_cell(i))
-}
-
-fn random_move<R: Rng, FE:Fn(usize)->Point, FB:Fn(usize)->Point>(all_buildings: &[BuildingType], rng: &mut R, free_positions_count: usize, get_point_expressive: FE, get_point_bitwise: FB) -> Command {
- let building_command_count = free_positions_count*all_buildings.len();
- let nothing_count = 1;
-
- let number_of_commands = building_command_count + nothing_count;
-
- let choice_index = rng.gen_range(0, number_of_commands);
-
- if choice_index == number_of_commands - 1 {
- Command::Nothing
- } else {
- let expressive_point = get_point_expressive(choice_index/all_buildings.len());
- let bitwise_point = get_point_bitwise(choice_index/all_buildings.len());
- assert_eq!(expressive_point, bitwise_point);
- Command::Build(
- expressive_point,
- all_buildings[choice_index%all_buildings.len()]
- )
- }
-}
-
-fn sensible_buildings(settings: &GameSettings, player: &Player, has_max_teslas: bool) -> Vec<BuildingType> {
- let mut result = Vec::with_capacity(4);
- for b in BuildingType::all().iter() {
- let building_setting = settings.building_settings(*b);
- let affordable = building_setting.price <= player.energy;
- let is_tesla = *b == BuildingType::Tesla;
- if affordable && (!is_tesla || !has_max_teslas) {
- result.push(*b);
- }
- }
- result
-}
-
-fn build_bitwise_from_expressive(expressive: &expressive_engine::ExpressiveGameState) -> bitwise_engine::BitwiseGameState {
- let player_unconstructed = expressive.player_unconstructed_buildings.iter()
- .map(build_bitwise_unconstructed_from_expressive)
- .collect();
- let opponent_unconstructed = expressive.opponent_unconstructed_buildings.iter()
- .map(build_bitwise_unconstructed_from_expressive)
- .collect();
-
- let player_energy = expressive.player_buildings.iter()
- .filter(|b| identify_building_type(b.weapon_damage, b.energy_generated_per_turn) == BuildingType::Energy)
- .fold(0, |acc, next| acc | next.pos.to_left_bitfield());
- let opponent_energy = expressive.opponent_buildings.iter()
- .filter(|b| identify_building_type(b.weapon_damage, b.energy_generated_per_turn) == BuildingType::Energy)
- .fold(0, |acc, next| acc | next.pos.to_right_bitfield());
-
- let mut player_buildings_iter = (0..DEFENCE_HEALTH as u8)
- .map(|i| expressive.player_buildings.iter()
- .filter(|b| b.health > i*MISSILE_DAMAGE)
- .fold(0, |acc, next| acc | next.pos.to_left_bitfield())
- );
- let mut opponent_buildings_iter = (0..DEFENCE_HEALTH as u8)
- .map(|i| expressive.opponent_buildings.iter()
- .filter(|b| b.health > i*MISSILE_DAMAGE)
- .fold(0, |acc, next| acc | next.pos.to_right_bitfield())
- );
-
- let player_occupied = expressive.player_buildings.iter()
- .fold(0, |acc, next| acc | next.pos.to_left_bitfield()) |
- expressive.player_unconstructed_buildings.iter()
- .fold(0, |acc, next| acc | next.pos.to_left_bitfield());
- let opponent_occupied = expressive.opponent_buildings.iter()
- .fold(0, |acc, next| acc | next.pos.to_right_bitfield()) |
- expressive.opponent_unconstructed_buildings.iter()
- .fold(0, |acc, next| acc | next.pos.to_right_bitfield());
-
- let mut player_attack_iter = (0..MISSILE_COOLDOWN_STATES as u8)
- .map(|i| expressive.player_buildings.iter()
- .filter(|b| identify_building_type(b.weapon_damage, b.energy_generated_per_turn) == BuildingType::Attack)
- .filter(|b| b.weapon_cooldown_time_left == i)
- .fold(0, |acc, next| acc | next.pos.to_left_bitfield())
- );
- let mut opponent_attack_iter = (0..MISSILE_COOLDOWN_STATES as u8)
- .map(|i| expressive.opponent_buildings.iter()
- .filter(|b| identify_building_type(b.weapon_damage, b.energy_generated_per_turn) == BuildingType::Attack)
- .filter(|b| b.weapon_cooldown_time_left == i)
- .fold(0, |acc, next| acc | next.pos.to_right_bitfield())
- );
-
- let empty_missiles: [(u64,u64);MISSILE_COOLDOWN_STATES] = [(0,0),(0,0),(0,0),(0,0)];
- let player_missiles = expressive.player_missiles.iter()
- .fold(empty_missiles, |acc, m| {
- let (mut left, mut right) = m.pos.to_bitfield();
- let mut res = acc.clone();
- for mut tier in res.iter_mut() {
- let setting = (!tier.0 & left, !tier.1 & right);
- tier.0 |= setting.0;
- tier.1 |= setting.1;
- left &= !setting.0;
- right &= !setting.1;
- }
- res
- });
- let opponent_missiles = expressive.opponent_missiles.iter()
- .fold(empty_missiles, |acc, m| {
- let (mut left, mut right) = m.pos.to_bitfield();
- let mut res = acc.clone();
- for mut tier in res.iter_mut() {
- let setting = (!tier.0 & right, !tier.1 & left);
- tier.0 |= setting.0;
- tier.1 |= setting.1;
- right &= !setting.0;
- left &= !setting.1;
- }
- res
- });
-
- let null_tesla = bitwise_engine::TeslaCooldown {
- active: false,
- pos: Point::new(0,0),
- cooldown: 0,
- age: 0
- };
- let mut player_tesla_iter = expressive.player_buildings.iter()
- .filter(|b| identify_building_type(b.weapon_damage, b.energy_generated_per_turn) == BuildingType::Tesla)
- .map(|b| bitwise_engine::TeslaCooldown {
- active: true,
- pos: b.pos,
- cooldown: b.weapon_cooldown_time_left,
- age: b.age,
- });
- let mut opponent_tesla_iter = expressive.opponent_buildings.iter()
- .filter(|b| identify_building_type(b.weapon_damage, b.energy_generated_per_turn) == BuildingType::Tesla)
- .map(|b| bitwise_engine::TeslaCooldown {
- active: true,
- pos: b.pos,
- cooldown: b.weapon_cooldown_time_left,
- age: b.age,
- });
- bitwise_engine::BitwiseGameState {
- status: expressive.status,
- player: expressive.player.clone(),
- opponent: expressive.opponent.clone(),
- player_buildings: bitwise_engine::PlayerBuildings {
- unconstructed: player_unconstructed,
- buildings: [player_buildings_iter.next().unwrap(), player_buildings_iter.next().unwrap(), player_buildings_iter.next().unwrap(), player_buildings_iter.next().unwrap()],
- occupied: player_occupied,
- energy_towers: player_energy,
- missile_towers: [player_attack_iter.next().unwrap(), player_attack_iter.next().unwrap(), player_attack_iter.next().unwrap(), player_attack_iter.next().unwrap()],
- firing_tower: 0,
- missiles: player_missiles,
- tesla_cooldowns: [player_tesla_iter.next().unwrap_or(null_tesla.clone()),
- player_tesla_iter.next().unwrap_or(null_tesla.clone())]
- },
- opponent_buildings: bitwise_engine::PlayerBuildings {
- unconstructed: opponent_unconstructed,
- buildings: [opponent_buildings_iter.next().unwrap(), opponent_buildings_iter.next().unwrap(), opponent_buildings_iter.next().unwrap(), opponent_buildings_iter.next().unwrap()],
- occupied: opponent_occupied,
- energy_towers: opponent_energy,
- missile_towers: [opponent_attack_iter.next().unwrap(), opponent_attack_iter.next().unwrap(), opponent_attack_iter.next().unwrap(), opponent_attack_iter.next().unwrap()],
- firing_tower: 0,
- missiles: opponent_missiles,
- tesla_cooldowns: [opponent_tesla_iter.next().unwrap_or(null_tesla.clone()),
- opponent_tesla_iter.next().unwrap_or(null_tesla.clone())]
- }
- }
-}
-
-fn build_bitwise_unconstructed_from_expressive(b: &expressive_engine::UnconstructedBuilding) -> bitwise_engine::UnconstructedBuilding {
- bitwise_engine::UnconstructedBuilding {
- pos: b.pos,
- construction_time_left: b.construction_time_left,
- building_type: identify_building_type(b.weapon_damage, b.energy_generated_per_turn)
- }
-}
-
-fn identify_building_type(weapon_damage: u8, energy_generated_per_turn: u16) -> BuildingType {
- match (weapon_damage, energy_generated_per_turn) {
- (MISSILE_DAMAGE, _) => BuildingType::Attack,
- (TESLA_DAMAGE, _) => BuildingType::Tesla,
- (_, ENERGY_GENERATED_TOWER) => BuildingType::Energy,
- _ => BuildingType::Defence
- }
-}