From d41a080a2c9de8d9cb46c5b9ef91270d2981a4a3 Mon Sep 17 00:00:00 2001 From: Justin Worthe Date: Thu, 31 May 2018 22:43:05 +0200 Subject: Tweaking move missiles to be more efficient --- src/engine/geometry.rs | 7 ++++++ src/engine/mod.rs | 58 ++++++++++++++++++++++++++++++-------------------- 2 files changed, 42 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/engine/geometry.rs b/src/engine/geometry.rs index bd0ae25..44ce9fe 100644 --- a/src/engine/geometry.rs +++ b/src/engine/geometry.rs @@ -24,6 +24,13 @@ impl Point { }) } } + + pub fn wrapping_move_left(&mut self) { + self.x = self.x.wrapping_sub(1); + } + pub fn wrapping_move_right(&mut self) { + self.x = self.x.wrapping_add(1); + } } use std::cmp::Ord; diff --git a/src/engine/mod.rs b/src/engine/mod.rs index 2ad9a73..13cb596 100644 --- a/src/engine/mod.rs +++ b/src/engine/mod.rs @@ -6,7 +6,7 @@ use self::command::{Command, BuildingType}; use self::geometry::Point; use self::settings::{GameSettings, BuildingSettings}; -use std::ops::Fn; +use std::ops::FnMut; use std::cmp; #[derive(Debug, Clone, PartialEq)] @@ -123,12 +123,14 @@ impl GameState { GameState::add_missiles(&mut self.player_buildings, &mut self.player_missiles); GameState::add_missiles(&mut self.opponent_buildings, &mut self.opponent_missiles); - GameState::move_missiles(&mut self.player_missiles, |p| p.move_right(&settings.size), + GameState::move_missiles(&mut self.player_missiles, |p| p.wrapping_move_right(), &mut self.opponent_buildings, &mut self.opponent, - &mut self.unoccupied_opponent_cells); - GameState::move_missiles(&mut self.opponent_missiles, |p| p.move_left(), + &mut self.unoccupied_opponent_cells, + &settings); + GameState::move_missiles(&mut self.opponent_missiles, |p| p.wrapping_move_left(), &mut self.player_buildings, &mut self.player, - &mut self.unoccupied_player_cells); + &mut self.unoccupied_player_cells, + &settings); GameState::add_energy(&mut self.player); GameState::add_energy(&mut self.opponent); @@ -192,39 +194,37 @@ impl GameState { } } - fn move_missiles(missiles: &mut Vec, move_fn: F, opponent_buildings: &mut Vec, opponent: &mut Player, unoccupied_cells: &mut Vec,) - where F: Fn(Point) -> Option { + fn move_missiles(missiles: &mut Vec, mut wrapping_move_fn: F, opponent_buildings: &mut Vec, opponent: &mut Player, unoccupied_cells: &mut Vec, settings: &GameSettings) + where F: FnMut(&mut Point) { for missile in missiles.iter_mut() { for _ in 0..missile.speed { - match move_fn(missile.pos) { - None => { - let damage = cmp::min(missile.damage, opponent.health); - opponent.health -= damage; + wrapping_move_fn(&mut missile.pos); + if missile.pos.x >= settings.size.x { + let damage = cmp::min(missile.damage, opponent.health); + opponent.health -= damage; + missile.speed = 0; + } + else { + // TODO latest game engine may be checking building health here + if let Some(mut hit) = opponent_buildings.iter_mut().find(|b| b.pos == missile.pos) { + let damage = cmp::min(missile.damage, hit.health); + hit.health -= damage; missile.speed = 0; - }, - Some(point) => { - missile.pos = point; - // TODO latest game engine may be checking building health here - if let Some(mut hit) = opponent_buildings.iter_mut().find(|b| b.pos == point) { - let damage = cmp::min(missile.damage, hit.health); - hit.health -= damage; - missile.speed = 0; - } } } - + if missile.speed == 0 { break; } } } - missiles.retain(|m| m.speed > 0); + swap_retain(missiles, |m| m.speed > 0); for b in opponent_buildings.iter().filter(|b| b.health == 0) { unoccupied_cells.push(b.pos); opponent.energy_generated -= b.energy_generated_per_turn; } - opponent_buildings.retain(|b| b.health > 0); + swap_retain(opponent_buildings, |b| b.health > 0); } fn add_energy(player: &mut Player) { @@ -360,3 +360,15 @@ impl Building { } +fn swap_retain(v: &mut Vec, mut pred: F) + where F: FnMut(&T) -> bool +{ + let mut new_len = v.len(); + for i in (0..v.len()).rev() { + if !pred(&v[i]) { + new_len -= 1; + v.swap(i, new_len); + } + } + v.truncate(new_len); +} -- cgit v1.2.3