Added new tower type and deconstruct action
authorJustin Worthe <justin@worthe-it.co.za>
Mon, 25 Jun 2018 15:37:14 +0000 (17:37 +0200)
committerJustin Worthe <justin@worthe-it.co.za>
Mon, 25 Jun 2018 15:37:14 +0000 (17:37 +0200)
src/engine/command.rs
src/engine/mod.rs
src/engine/settings.rs
src/input/json.rs
src/input/mod.rs
src/input/textmap.rs [deleted file]
tests/live-comparison.rs

index b350d65..7a2594d 100644 (file)
@@ -5,6 +5,7 @@ use super::geometry::Point;
 pub enum Command {
     Nothing,
     Build(Point, BuildingType),
+    Deconstruct(Point)
 }
 
 impl fmt::Display for Command {
@@ -12,6 +13,7 @@ impl fmt::Display for Command {
         match *self {
             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),
         }
     }
 }
@@ -22,18 +24,18 @@ pub enum BuildingType {
     Defence = 0,
     Attack = 1,
     Energy = 2,
+    Tesla = 4,
 }
 
 impl BuildingType {
-    pub fn all() -> [BuildingType; 3] {
+    pub fn all() -> [BuildingType; 4] {
         use self::BuildingType::*;
-        [Defence, Attack, Energy]
+        [Defence, Attack, Energy, Tesla]
     }
 
-    fn count() -> u8 { BuildingType::Energy as u8 + 1 }
     pub fn from_u8(id: u8) -> Option<BuildingType> {
         use std::mem;
-        if id < Self::count() { Some(unsafe { mem::transmute(id) }) } else { None }
+        if id < 4 && id != 3 { Some(unsafe { mem::transmute(id) }) } else { None }
     }
 
 }
index 739dd85..2a334d5 100644 (file)
@@ -122,6 +122,8 @@ impl GameState {
         GameState::update_construction(&mut self.player_unconstructed_buildings, &mut self.player_buildings, &mut self.player);
         GameState::update_construction(&mut self.opponent_unconstructed_buildings, &mut self.opponent_buildings, &mut self.opponent);
 
+        GameState::fire_teslas(&mut self.player_buildings, &mut self.opponent_buildings);
+
         GameState::add_missiles(&mut self.player_buildings, &mut self.player_missiles);
         GameState::add_missiles(&mut self.opponent_buildings, &mut self.opponent_missiles);
 
@@ -161,6 +163,22 @@ impl GameState {
                 let to_remove_index = unoccupied_cells.iter().position(|&pos| pos == p).unwrap();
                 unoccupied_cells.swap_remove(to_remove_index);
             },
+            Command::Deconstruct(p) => {
+                let to_remove_index = buildings.iter().position(|&pos| pos == p);
+                if let Some(i) = to_remove_index {
+                    buildings.swap_remove(i);
+                }
+                let unconstructed_to_remove_index = unconstructed_buildings.iter().position(|&pos| pos == p);
+                if let Some(i) = unconstructed_to_remove_index {
+                    unconstructed_buildings.swap_remove(i);
+                }
+                
+                debug_assert!(to_remove_index.is_some() || unconstructed_to_remove_index.is_some());
+                    
+                player.energy += 5;
+                
+                unoccupied_cells.push(p);
+            },
         }
     }
 
@@ -179,6 +197,15 @@ impl GameState {
         unconstructed_buildings.truncate(buildings_len);
     }
 
+    fn fire_teslas(_player_buildings: &mut Vec<Building>, _opponent_buildings: &mut Vec<Building>) {
+        // TODO all towers try to fire. If there isn't enough energy
+        // to fire multiple, the oldest fires. This seems like an edge
+        // case because you're only allowed two towers in total, and
+        // they're probably only late game towers. The odds of firing
+        // twice at once is slim. Opposing towers can't be stopped
+        // from firing by firing themselves. So fire all, then remove.
+    }
+        
     fn add_missiles(buildings: &mut Vec<Building>, missiles: &mut Vec<Missile>) {
         for building in buildings.iter_mut().filter(|b| b.is_shooty()) {
             if building.weapon_cooldown_time_left > 0 {
index ec62408..3657cb2 100644 (file)
@@ -9,7 +9,8 @@ pub struct GameSettings {
     pub max_building_price: u16,
     pub energy: BuildingSettings,
     pub defence: BuildingSettings,
-    pub attack: BuildingSettings
+    pub attack: BuildingSettings,
+    pub tesla: BuildingSettings,
 }
 
 #[derive(Debug)]
@@ -24,18 +25,19 @@ pub struct BuildingSettings {
 }
 
 impl GameSettings {
-    pub fn new(size: Point, energy_income: u16, energy: BuildingSettings, defence: BuildingSettings, attack: BuildingSettings) -> GameSettings {
+    pub fn new(size: Point, energy_income: u16, energy: BuildingSettings, defence: BuildingSettings, attack: BuildingSettings, tesla: BuildingSettings) -> GameSettings {
         let max_building_price = cmp::max(cmp::max(energy.price, defence.price), attack.price);
         GameSettings {
             size, energy_income, max_building_price,
-            energy, defence, attack
+            energy, defence, attack, tesla
         }
     }
     pub fn building_settings(&self, building: BuildingType) -> &BuildingSettings {
         match building {
             BuildingType::Defence => &self.defence,
             BuildingType::Attack => &self.attack,
-            BuildingType::Energy => &self.energy
+            BuildingType::Energy => &self.energy,
+            BuildingType::Tesla => &self.tesla,
         }
     }
     
index ed00984..95dbd46 100644 (file)
@@ -41,7 +41,8 @@ struct GameDetails {
 struct BuildingStats {
     energy: BuildingBlueprint,
     defense: BuildingBlueprint,
-    attack: BuildingBlueprint
+    attack: BuildingBlueprint,
+    tesla: BuildingBlueprint,
 }
 
 #[derive(Deserialize)]
@@ -116,6 +117,7 @@ impl State {
             self.game_details.buildings_stats.energy.to_engine(),
             self.game_details.buildings_stats.defense.to_engine(),
             self.game_details.buildings_stats.attack.to_engine(),
+            self.game_details.buildings_stats.tesla.to_engine(),
         )
     }
     
index 47f359a..22fdbb3 100644 (file)
@@ -1,2 +1 @@
 pub mod json;
-pub mod textmap;
diff --git a/src/input/textmap.rs b/src/input/textmap.rs
deleted file mode 100644 (file)
index 5481770..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-use std::fs::File;
-use std::io::prelude::*;
-use std::error::Error;
-
-use ::engine::*;
-use ::engine::settings::*;
-use ::engine::geometry::*;
-
-
-pub fn read_state_from_file(filename: &str) -> Result<(GameSettings, GameState), Box<Error>> {
-    let mut file = File::open(filename)?;
-    let mut content = String::new();
-    file.read_to_string(&mut content)?;
-
-    //TODO actually read the right file and parse it?
-
-    let engine_settings = GameSettings::new(
-        Point::new(8,4),
-        5,
-        BuildingSettings {
-            price: 20,
-            health: 5,
-            construction_time: 2-2,
-            weapon_damage: 0,
-            weapon_speed: 0,
-            weapon_cooldown_period: 0,
-            energy_generated_per_turn: 3
-        },
-        BuildingSettings {
-            price: 30,
-            health: 20,
-            construction_time: 4-2,
-            weapon_damage: 0,
-            weapon_speed: 0,
-            weapon_cooldown_period: 0,
-            energy_generated_per_turn: 0
-        },
-        BuildingSettings {
-            price: 30,
-            health: 5,
-            construction_time: 2-2,
-            weapon_damage: 5,
-            weapon_speed: 2,
-            weapon_cooldown_period: 3,
-            energy_generated_per_turn: 0
-        }
-    );
-    let engine_state = GameState::new(
-        Player {
-            energy: 20,
-            health: 100,
-            energy_generated: 5
-        },
-        Player {
-            energy: 20,
-            health: 100,
-            energy_generated: 5
-        },
-        Vec::new(),
-        Vec::new(),
-        Vec::new(),
-        Vec::new(),
-        Vec::new(),
-        Vec::new(),
-        &engine_settings
-    );
-    
-    Ok((engine_settings, engine_state))
-}
index 301f8fc..621c247 100644 (file)
@@ -52,7 +52,11 @@ fn read_opponent_command(filename: &str, settings: &GameSettings) -> Command {
         Command::Build(p, b) => Command::Build(Point::new(
             settings.size.x - p.x - 1,
             p.y
-        ), b)
+        ), b),
+        Command::Deconstruct(p) => Command::Deconstruct(Point::new(
+            settings.size.x - p.x - 1,
+            p.y
+        )),
     }
     
 }