Implemented shooting teslas in the same order as the game engine
authorJustin Worthe <justin@worthe-it.co.za>
Sun, 15 Jul 2018 20:05:19 +0000 (22:05 +0200)
committerJustin Worthe <justin@worthe-it.co.za>
Sun, 15 Jul 2018 20:05:19 +0000 (22:05 +0200)
Order by age

src/engine/bitwise_engine.rs
src/engine/expressive_engine.rs
src/input/json.rs
tests/expressive_to_bitwise_comparison.rs
tests/live_comparison.rs

index 87b7f0f..a70d5e2 100644 (file)
@@ -40,7 +40,8 @@ pub struct UnconstructedBuilding {
 pub struct TeslaCooldown {
     pub active: bool,
     pub pos: Point,
-    pub cooldown: u8
+    pub cooldown: u8,
+    pub age: u16
 }
 
 
@@ -164,12 +165,14 @@ impl BitwiseGameState {
             if !tesla.active {
                 tesla.pos = Point::new(0,0);
                 tesla.cooldown = 0;
+                tesla.age = 0;
             }
         }
         for tesla in self.opponent_buildings.tesla_cooldowns.iter_mut() {
             if !tesla.active {
                 tesla.pos = Point::new(0,0);
                 tesla.cooldown = 0;
+                tesla.age = 0;
             }
         }
 
@@ -267,6 +270,7 @@ impl BitwiseGameState {
                     tesla_cooldown.active = true;
                     tesla_cooldown.pos = pos;
                     tesla_cooldown.cooldown = 0;
+                    tesla_cooldown.age = 0;
                 }
                 
                 buildings_len -= 1;
@@ -279,14 +283,11 @@ impl BitwiseGameState {
     }
 
     fn fire_teslas(player: &mut Player, player_buildings: &mut PlayerBuildings, opponent: &mut Player, opponent_buildings: &mut PlayerBuildings) {
-
-        #[cfg(debug_assertions)]
-        {
-            player_buildings.tesla_cooldowns.sort_by_key(|b| (!b.active, b.pos));
-            opponent_buildings.tesla_cooldowns.sort_by_key(|b| (!b.active, b.pos));
-        }
+        player_buildings.tesla_cooldowns.sort_by(|a, b| b.age.cmp(&a.age));
+        opponent_buildings.tesla_cooldowns.sort_by(|a, b| b.age.cmp(&a.age));
 
         for tesla in player_buildings.tesla_cooldowns.iter_mut().filter(|t| t.active) {
+            tesla.age += 1;
             if tesla.cooldown > 0 {
                 tesla.cooldown -= 1;
             } else if player.energy >= TESLA_FIRING_ENERGY {
@@ -314,6 +315,7 @@ impl BitwiseGameState {
         }
 
         for tesla in opponent_buildings.tesla_cooldowns.iter_mut().filter(|t| t.active) {
+            tesla.age += 1;
             if tesla.cooldown > 0 {
                 tesla.cooldown -= 1;
             } else if opponent.energy >= TESLA_FIRING_ENERGY {
@@ -491,7 +493,8 @@ impl TeslaCooldown {
         TeslaCooldown {
             active: false,
             pos: Point::new(0,0),
-            cooldown: 0
+            cooldown: 0,
+            age: 0
         }
     }
 }
index aa9448b..557e0fa 100644 (file)
@@ -38,7 +38,8 @@ pub struct Building {
     pub weapon_speed: u8,
     pub weapon_cooldown_time_left: u8,
     pub weapon_cooldown_period: u8,
-    pub energy_generated_per_turn: u16
+    pub energy_generated_per_turn: u16,
+    pub age: u16
 }
 
 #[derive(Debug, Clone, PartialEq)]
@@ -193,11 +194,12 @@ impl ExpressiveGameState {
     fn fire_teslas(player: &mut Player, player_buildings: &mut Vec<Building>, player_unoccupied_cells: &mut Vec<Point>, opponent: &mut Player, opponent_buildings: &mut Vec<Building>, opponent_unoccupied_cells: &mut Vec<Point>,settings: &GameSettings) {
         #[cfg(debug_assertions)]
         {
-            player_buildings.sort_by_key(|b| b.pos);
-            opponent_buildings.sort_by_key(|b| b.pos);
+            player_buildings.sort_by(|a, b| b.age.cmp(&a.age).then(a.pos.cmp(&b.pos)));
+            opponent_buildings.sort_by(|a, b| b.age.cmp(&a.age).then(a.pos.cmp(&b.pos)));
         }
         
         for tesla in player_buildings.iter_mut().filter(|b| b.weapon_damage == 20) {
+            tesla.age += 1;
             if tesla.weapon_cooldown_time_left > 0 {
                 tesla.weapon_cooldown_time_left -= 1;
             } else if player.energy >= 100 {
@@ -222,6 +224,7 @@ impl ExpressiveGameState {
         }
 
         for tesla in opponent_buildings.iter_mut().filter(|b| b.weapon_damage == 20) {
+            tesla.age += 1;
             if tesla.weapon_cooldown_time_left > 0 {
                 tesla.weapon_cooldown_time_left -= 1;
             } else if opponent.energy >= 100 {
@@ -382,7 +385,8 @@ impl UnconstructedBuilding {
             weapon_speed: self.weapon_speed,
             weapon_cooldown_time_left: 0,
             weapon_cooldown_period: self.weapon_cooldown_period,
-            energy_generated_per_turn: self.energy_generated_per_turn
+            energy_generated_per_turn: self.energy_generated_per_turn,
+            age: 0
         }
     }
 }
@@ -396,7 +400,8 @@ impl Building {
             weapon_speed: blueprint.weapon_speed,
             weapon_cooldown_time_left: 0,
             weapon_cooldown_period: blueprint.weapon_cooldown_period,
-            energy_generated_per_turn: blueprint.energy_generated_per_turn
+            energy_generated_per_turn: blueprint.energy_generated_per_turn,
+            age: 0
         }
     }
     
index 72c964d..c3d8474 100644 (file)
@@ -97,7 +97,7 @@ struct GameCell {
 #[serde(rename_all = "camelCase")]
 struct BuildingState {
     health: u8,
-    construction_time_left: i8,
+    construction_time_left: i16,
     //price: u16,
     weapon_damage: u8,
     weapon_speed: u8,
@@ -181,22 +181,23 @@ impl State {
                             bitwise_buildings.energy_towers |= bitfield;
                             engine_player.energy_generated += building.energy_generated_per_turn;
                         }
-                        if building_type == command::BuildingType::Attack {
+                        else if building_type == command::BuildingType::Attack {
                             for cooldown_tier in 0..MISSILE_COOLDOWN + 1 {
                                 if building.weapon_cooldown_time_left == cooldown_tier as u8 {
                                     bitwise_buildings.missile_towers[cooldown_tier] |= bitfield;
                                 }
                             }
                         }
-                        if building_type == command::BuildingType::Tesla {
+                        else if building_type == command::BuildingType::Tesla {
                             let ref mut tesla_cooldown = if bitwise_buildings.tesla_cooldowns[0].active {
-                                bitwise_buildings.tesla_cooldowns[1]
+                                &mut bitwise_buildings.tesla_cooldowns[1]
                             } else {
-                                bitwise_buildings.tesla_cooldowns[0]
+                                &mut bitwise_buildings.tesla_cooldowns[0]
                             };
                             tesla_cooldown.active = true;
                             tesla_cooldown.pos = point;
                             tesla_cooldown.cooldown = building.weapon_cooldown_time_left;
+                            tesla_cooldown.age = building.construction_time_left.abs() as u16;
                         }
                     }
                 }
@@ -312,6 +313,7 @@ impl BuildingState {
             weapon_cooldown_time_left: self.weapon_cooldown_time_left,
             weapon_cooldown_period: self.weapon_cooldown_period,
             energy_generated_per_turn: self.energy_generated_per_turn,
+            age: self.construction_time_left.abs() as u16
         }
     }
 
index ac2cbf0..6a72748 100644 (file)
@@ -188,21 +188,24 @@ fn build_bitwise_from_expressive(expressive: &expressive_engine::ExpressiveGameS
     let null_tesla = bitwise_engine::TeslaCooldown {
         active: false,
         pos: Point::new(0,0),
-        cooldown: 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
+            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
+            cooldown: b.weapon_cooldown_time_left,
+            age: b.age,
         });
     bitwise_engine::BitwiseGameState {
         status: expressive.status,
index 2fcc8b5..23beaec 100644 (file)
@@ -30,6 +30,8 @@ fn test_from_replay(replay_folder: &str, length: usize) {
         state.simulate(&settings, player, opponent);
         state.sort();
         expected_state.sort();
+
+        println!("State {}: {:?}", i+1, state);
         assert_eq!(state, expected_state, "\nFailed on state {}\n", i+1);
     }
 }