From 0e3548c13634e078b71c022ac49a3cea7e0c420d Mon Sep 17 00:00:00 2001 From: Justin Worthe Date: Thu, 27 Jun 2019 18:07:28 +0200 Subject: Implemented bomb attacks --- src/constants.rs | 24 ++++++++++++++++++ src/game.rs | 70 ++++++++++++++++++++++++++++++++++++++++++----------- src/geometry/vec.rs | 2 +- 3 files changed, 81 insertions(+), 15 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index dcda1d5..fd1263a 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -1,3 +1,5 @@ +use crate::geometry::Vec2d; + pub const MAP_SIZE: usize = 33; pub const MAP_ROW_SIZE: [MapRow; MAP_SIZE] = [ MapRow { start_bit: 0, x_offset: 11 }, @@ -46,4 +48,26 @@ impl MapRow { pub fn len(&self) -> usize { MAP_SIZE - 2 * self.x_offset } + + pub fn is_empty(&self) -> bool { + self.len() == 0 + } } + + +pub const BOMB_DAMAGED_SPACES: usize = 13; +pub const BOMB_DAMAGES: [(Vec2d, i32); BOMB_DAMAGED_SPACES] = [ + (Vec2d::new(0, -2), 7), + (Vec2d::new(2, 0), 7), + (Vec2d::new(0, 2), 7), + (Vec2d::new(-2, 0), 7), + (Vec2d::new(1, -1), 11), + (Vec2d::new(1, 1), 11), + (Vec2d::new(-1, 1), 11), + (Vec2d::new(-1, -1), 11), + (Vec2d::new(0, -1), 13), + (Vec2d::new(0, -1), 13), + (Vec2d::new(0, -1), 13), + (Vec2d::new(0, -1), 13), + (Vec2d::new(0, 0), 20) +]; diff --git a/src/game.rs b/src/game.rs index a08fff2..d3d6636 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,6 +1,7 @@ use crate::geometry::*; use crate::command::{Command, Action}; use crate::json; +use crate::constants::*; mod player; use player::*; @@ -96,22 +97,29 @@ impl GameBoard { } pub fn update(&mut self, json: json::State) { + // Much of this becomes easier if this issue is implemented: https://github.com/EntelectChallenge/2019-Worms/issues/44 + for w in &json.my_player.worms { if let Some(worm) = self.players[0].find_worm_mut(w.id) { worm.health = w.health; worm.position = Point2d::new(w.position.x, w.position.y); + worm.bombs = w.banana_bombs.as_ref().map(|b| b.count).unwrap_or(0); } } for w in json.opponents.iter().flat_map(|o| &o.worms) { if let Some(worm) = self.players[1].find_worm_mut(w.id) { worm.health = w.health; worm.position = Point2d::new(w.position.x, w.position.y); + // TODO: How to update opponent worm bombs? } } self.players[0].moves_score = json.my_player.score - json.my_player.health_score(); self.players[1].moves_score = json.opponents[0].score - json.opponents[0].health_score(); + self.players[0].select_moves = json.my_player.remaining_worm_selections; + self.players[1].select_moves = json.opponents[0].remaining_worm_selections; + self.powerups = json.map.iter().flatten().filter_map(|c| { c.powerup.as_ref().map(|p| Powerup { position: Point2d::new(c.x, c.y), @@ -253,17 +261,52 @@ impl GameBoard { for player_index in 0..actions.len() { if let Action::Bomb(p) = actions[player_index] { - if let Some(worm) = self.players[player_index].active_worm_mut() { - debug_assert!(worm.bombs > 0, "Worm is throwing a bomb it doesn't have"); - debug_assert!((worm.position - p).magnitude_squared() < 6*6); // max range is 5, but it's 5 after rounding down - - worm.bombs = worm.bombs.saturating_sub(1); - - let damage_radius = 2; - // damage as per https://forum.entelect.co.za/uploads/default/original/2X/8/89e6e6cf35791a0448b5a6bbeb63c558ce41804a.jpeg - - // TODO: Clear up dirt and give points - // TODO: Hurt all worm and give / remove points + if self.map.at(p).is_some() { + if let Some(worm) = self.players[player_index].active_worm_mut() { + debug_assert!(worm.bombs > 0, "Worm is throwing a bomb it doesn't have"); + debug_assert!((worm.position - p).magnitude_squared() < 6*6); // max range is 5, but it's 5 after rounding down + + worm.bombs = worm.bombs.saturating_sub(1); + + // damage as per https://forum.entelect.co.za/uploads/default/original/2X/8/89e6e6cf35791a0448b5a6bbeb63c558ce41804a.jpeg + + for &(damage_offset, weapon_damage) in BOMB_DAMAGES.iter() { + let target = p + damage_offset; + + if self.map.at(target) == Some(true) { + self.map.clear(target); + // TODO: How does this score get assigned if both players lobbed a banana? + self.players[player_index].moves_score += 7; + } + + let target_own_worm: Option<&mut Worm> = self.players[player_index] + .worms.iter_mut() + .find(|w| w.position == target); + + if let Some(target_worm) = target_own_worm { + target_worm.health -= weapon_damage; + if target_worm.health <= 0 { + self.players[player_index].moves_score -= 40; + self.occupied_cells.remove(&target_worm.position); + } else { + self.players[player_index].moves_score -= weapon_damage * 2; + } + } + + let target_opponent_worm: Option<&mut Worm> = self.players[GameBoard::opponent(player_index)] + .worms.iter_mut() + .find(|w| w.position == target); + if let Some(target_worm) = target_opponent_worm { + target_worm.health -= weapon_damage; + if target_worm.health <= 0 { + self.players[player_index].moves_score += 40; + self.occupied_cells.remove(&target_worm.position); + } else { + self.players[player_index].moves_score += weapon_damage * 2; + } + } + } + } } } } @@ -299,8 +342,7 @@ impl GameBoard { self.players[player_index].moves_score -= 40; self.occupied_cells.remove(&target_worm.position); } else { - // TODO: Review these points - self.players[player_index].moves_score -= 20; + self.players[player_index].moves_score -= weapon_damage * 2; } continue 'players_loop; } @@ -314,7 +356,7 @@ impl GameBoard { self.players[player_index].moves_score += 40; self.occupied_cells.remove(&target_worm.position); } else { - self.players[player_index].moves_score += 20; + self.players[player_index].moves_score += weapon_damage * 2; } continue 'players_loop; diff --git a/src/geometry/vec.rs b/src/geometry/vec.rs index ab2210d..c99cf5e 100644 --- a/src/geometry/vec.rs +++ b/src/geometry/vec.rs @@ -17,7 +17,7 @@ macro_rules! impl_vector { } impl $VecN { - pub fn new($($field: T),+) -> $VecN { + pub const fn new($($field: T),+) -> $VecN { $VecN { $($field),+ } } } -- cgit v1.2.3