Implemented most of the iron curtain changes
authorJustin Worthe <justin@worthe-it.co.za>
Sat, 11 Aug 2018 21:02:35 +0000 (23:02 +0200)
committerJustin Worthe <justin@worthe-it.co.za>
Sat, 11 Aug 2018 21:02:35 +0000 (23:02 +0200)
Still need to
- set it active
- make the random move selection choose it
- test against real engine

src/engine/bitwise_engine.rs
src/engine/command.rs
src/engine/constants.rs
src/input/json.rs

index 3dbd7fb..e9c1b0a 100644 (file)
@@ -35,7 +35,10 @@ pub struct PlayerBuildings {
     pub firing_tower: usize,
     
     pub missiles: [(u64, u64); MISSILE_MAX_SINGLE_CELL],
-    pub tesla_cooldowns: ArrayVec<[TeslaCooldown; TESLA_MAX]>
+    pub tesla_cooldowns: ArrayVec<[TeslaCooldown; TESLA_MAX]>,
+
+    pub iron_curtain_available: bool,
+    pub iron_curtain_remaining: u8,
 }
 
 #[derive(Debug, Clone, PartialEq, Eq)]
@@ -60,6 +63,9 @@ impl BitwiseGameState {
 
         BitwiseGameState::update_construction(&mut self.player_buildings);
         BitwiseGameState::update_construction(&mut self.opponent_buildings);
+
+        BitwiseGameState::update_iron_curtain(&mut self.player_buildings);
+        BitwiseGameState::update_iron_curtain(&mut self.opponent_buildings);
         
         BitwiseGameState::fire_teslas(&mut self.player, &mut self.player_buildings, &mut self.opponent, &mut self.opponent_buildings);
 
@@ -255,6 +261,14 @@ impl BitwiseGameState {
                 }
                 player_buildings.tesla_cooldowns.retain(|t| t.pos != p);
                 player_buildings.occupied &= deconstruct_mask;
+            },
+            Command::IronCurtain => {
+                debug_assert!(player_buildings.iron_curtain_available);
+                debug_assert!(player.energy >= IRON_CURTAIN_PRICE);
+
+                player.energy -= IRON_CURTAIN_PRICE;
+                player_buildings.iron_curtain_available = false;
+                player_buildings.iron_curtain_remaining = IRON_CURTAIN_DURATION;
             }
         }
     }
@@ -295,6 +309,11 @@ impl BitwiseGameState {
         player_buildings.unconstructed.truncate(buildings_len);
     }
 
+    fn update_iron_curtain(player_buildings: &mut PlayerBuildings) {
+        //TODO: Get in current round and set available to true
+        player_buildings.iron_curtain_remaining -= 1;
+    }
+    
     fn fire_teslas(player: &mut Player, player_buildings: &mut PlayerBuildings, opponent: &mut Player, opponent_buildings: &mut PlayerBuildings) {
         BitwiseGameState::fire_single_players_teslas_without_cleanup(player, player_buildings, opponent, opponent_buildings);
         BitwiseGameState::fire_single_players_teslas_without_cleanup(opponent, opponent_buildings, player, player_buildings);
@@ -309,6 +328,9 @@ impl BitwiseGameState {
             tesla.age += 1;
             if tesla.cooldown > 0 {
                 tesla.cooldown -= 1;
+            } else if player.energy >= TESLA_FIRING_ENERGY && opponent_buildings.iron_curtain_remaining > 0 {
+                player.energy -= TESLA_FIRING_ENERGY;
+                tesla.cooldown = TESLA_COOLDOWN;
             } else if player.energy >= TESLA_FIRING_ENERGY {
                 player.energy -= TESLA_FIRING_ENERGY;
                 tesla.cooldown = TESLA_COOLDOWN;
@@ -351,7 +373,7 @@ impl BitwiseGameState {
         let mut damaging = 0;
         for _ in 0..MISSILE_SPEED {
             for missile in player_missiles.iter_mut() {
-                let swapping_sides = missile.0 & RIGHT_COL_MASK;
+                let swapping_sides = if opponent_buildings.iron_curtain_remaining > 0 { 0 } else { missile.0 & RIGHT_COL_MASK };
                 let about_to_hit_opponent = missile.1 & LEFT_COL_MASK;
 
                 missile.0 = (missile.0 & !RIGHT_COL_MASK) << 1;
@@ -426,7 +448,9 @@ impl PlayerBuildings {
             missile_towers: [0; MISSILE_COOLDOWN_STATES],
             firing_tower: 0,
             missiles: [(0,0); MISSILE_MAX_SINGLE_CELL],
-            tesla_cooldowns: ArrayVec::new()
+            tesla_cooldowns: ArrayVec::new(),
+            iron_curtain_available: false,
+            iron_curtain_remaining: 0
         }
     }
 
index da7e1e0..e6dbedf 100644 (file)
@@ -5,7 +5,8 @@ use super::geometry::Point;
 pub enum Command {
     Nothing,
     Build(Point, BuildingType),
-    Deconstruct(Point)
+    Deconstruct(Point),
+    IronCurtain
 }
 
 impl fmt::Display for Command {
@@ -14,6 +15,7 @@ impl fmt::Display for Command {
             Command::Nothing => write!(f, ""),
             Command::Build(p, b) => write!(f, "{},{},{}", p.x(), p.y(), b as u8),
             Command::Deconstruct(p) => write!(f, "{},{},3", p.x(), p.y()),
+            Command::IronCurtain => write!(f, "0,0,5")
         }
     }
 }
index 458251f..11afa29 100644 (file)
@@ -18,7 +18,7 @@ pub const TESLA_MAX: usize = 2;
 pub const TESLA_COOLDOWN: u8 = 10;
 pub const TESLA_FIRING_ENERGY: u16 = 100;
 pub const TESLA_DAMAGE: u8 = 20;
-pub const TESLA_PRICE: u16 = 300;
+pub const TESLA_PRICE: u16 = 100;
 pub const TESLA_CONSTRUCTION_TIME: u8 = 10;
 
 pub const ENERGY_GENERATED_BASE: u16 = 5;
@@ -26,6 +26,10 @@ pub const ENERGY_GENERATED_TOWER: u16 = 3;
 pub const ENERGY_PRICE: u16 = 20;
 pub const ENERGY_CONSTRUCTION_TIME: u8 = 1;
 
+pub const IRON_CURTAIN_PRICE: u16 = 100;
+pub const IRON_CURTAIN_UNLOCK_INTERVAL: u8 = 30;
+pub const IRON_CURTAIN_DURATION: u8 = 6;
+
 pub const DECONSTRUCT_ENERGY: u16 = 5;
 
 pub const MAX_CONCURRENT_CONSTRUCTION: usize = 6; //2 teslas, and 3 of anything else, 1 extra because it's push here then update construction times
index 4aebcfa..32f98d0 100644 (file)
@@ -31,6 +31,8 @@ struct Player {
     player_type: char,
     energy: u16,
     health: u8,
+    iron_curtain_available: bool,
+    active_iron_curtain_lifetime: i16
 }
 
 #[derive(Deserialize)]
@@ -63,10 +65,28 @@ struct MissileState {
 
 impl State {
     fn to_bitwise_engine(&self) -> bitwise_engine::BitwiseGameState {
-        let player = self.player().to_bitwise_engine();
-        let opponent = self.opponent().to_bitwise_engine();
+        let json_player = self.player();
+        let player = json_player.to_bitwise_engine();
+        let json_opponent = self.opponent();
+        let opponent = json_opponent.to_bitwise_engine();
         let mut player_buildings = bitwise_engine::PlayerBuildings::empty();
         let mut opponent_buildings = bitwise_engine::PlayerBuildings::empty();
+
+        // TODO roll the player into the playerbuildings and remove this duplication
+        player_buildings.iron_curtain_available = json_player.iron_curtain_available;
+        player_buildings.iron_curtain_remaining = if json_player.active_iron_curtain_lifetime < 0 {
+            0
+        } else {
+            json_player.active_iron_curtain_lifetime as u8
+        };
+        opponent_buildings.iron_curtain_available = json_opponent.iron_curtain_available;
+        opponent_buildings.iron_curtain_remaining = if json_opponent.active_iron_curtain_lifetime < 0 {
+            0
+        } else {
+            json_opponent.active_iron_curtain_lifetime as u8
+        };
+
+        
         for row in &self.game_map {
             for cell in row {
                 let point = engine::geometry::Point::new(cell.x, cell.y);