summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Worthe <justin@worthe-it.co.za>2019-06-27 18:07:28 +0200
committerJustin Worthe <justin@worthe-it.co.za>2019-06-27 18:07:28 +0200
commit0e3548c13634e078b71c022ac49a3cea7e0c420d (patch)
treeb4959173d6b1ec95af94d8efa2a7949b7b6d6417
parentb7e5273627c1b6db9faf8e29e2445bdbba802453 (diff)
Implemented bomb attacks
-rw-r--r--src/constants.rs24
-rw-r--r--src/game.rs70
-rw-r--r--src/geometry/vec.rs2
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<i8>, 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<T> $VecN<T> {
- pub fn new($($field: T),+) -> $VecN<T> {
+ pub const fn new($($field: T),+) -> $VecN<T> {
$VecN { $($field),+ }
}
}