summaryrefslogtreecommitdiff
path: root/src/game.rs
diff options
context:
space:
mode:
authorJustin Worthe <justin@worthe-it.co.za>2019-04-26 19:43:59 +0200
committerJustin Worthe <justin@worthe-it.co.za>2019-04-26 19:43:59 +0200
commitebe7d5cd5cc42d8f3f02ca926f4b920ada03765f (patch)
treea139c6b65182f1fc10d7dcea7eec45a234491048 /src/game.rs
parent3e4f70ff90471120818cfb38a6dbde4952c11b8f (diff)
Refactored game map to use less memory
Diffstat (limited to 'src/game.rs')
-rw-r--r--src/game.rs104
1 files changed, 66 insertions, 38 deletions
diff --git a/src/game.rs b/src/game.rs
index 8fd9153..be2dcce 100644
--- a/src/game.rs
+++ b/src/game.rs
@@ -1,10 +1,11 @@
use crate::geometry::*;
use crate::command::Command;
use crate::json;
+use crate::constants::*;
use arrayvec::ArrayVec;
-#[derive(Debug, PartialEq, Eq, Clone)]
+#[derive(Clone)]
pub struct GameBoard {
pub players: [Player; 2],
pub powerups: ArrayVec<[Powerup; 2]>,
@@ -31,18 +32,9 @@ pub enum Powerup {
Health(Point2d<i8>, i32)
}
-#[derive(Debug, PartialEq, Eq, Clone)]
+#[derive(Clone)]
pub struct Map {
- pub size: u8,
- /// This is 2d, each row is size long
- pub cells: ArrayVec<[CellType; 2048]>
-}
-
-#[derive(Debug, PartialEq, Eq, Clone, Copy)]
-pub enum CellType {
- Air,
- Dirt,
- DeepSpace,
+ pub cells: [u64; MAP_U64S]
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
@@ -78,20 +70,22 @@ impl GameBoard {
weapon_range: commando_range
}).collect()
};
+
+ let mut map = Map {
+ cells: [0; MAP_U64S]
+ };
+ for cell in json.map.iter().flatten() {
+ if cell.cell_type == json::CellType::Dirt {
+ map.set(Point2d::new(cell.x, cell.y))
+ }
+ }
GameBoard {
players: [player, opponent],
powerups: json.map.iter().flatten().filter_map(|c| {
c.powerup.clone().map(|p| Powerup::Health(Point2d::new(c.x, c.y), p.value))
}).collect(),
- map: Map {
- size: json.map_size,
- cells: json.map.iter().flatten().map(|c| match c.cell_type {
- json::CellType::Air => CellType::Air,
- json::CellType::Dirt => CellType::Dirt,
- json::CellType::DeepSpace => CellType::DeepSpace,
- }).collect()
- }
+ map
}
}
@@ -112,7 +106,7 @@ impl GameBoard {
let damage = 20;
- debug_assert_eq!(Some(CellType::Air), self.map.at(Point2d::new(x1, y1)));
+ debug_assert_eq!(Some(false), self.map.at(Point2d::new(x1, y1)), "Movement target wasn't empty, ({}, {})", x1, y1);
// Worms have a 50% chance of swapping places
// here. I'm treating that as an edge case that I
// don't need to handle for now.
@@ -123,13 +117,14 @@ impl GameBoard {
_ => {
for player_index in 0..moves.len() {
if let Command::Move(x, y) = moves[player_index] {
- debug_assert_eq!(Some(CellType::Air), self.map.at(Point2d::new(x, y)));
+ debug_assert_eq!(Some(false), self.map.at(Point2d::new(x, y)), "Movement target wasn't empty, ({}, {})", x, y);
let worm = self.players[player_index].active_worm_mut();
debug_assert!(
(worm.position.x - x).abs() <= 1 &&
- (worm.position.y - y).abs() <= 1
+ (worm.position.y - y).abs() <= 1,
+ "Tried to move too far away, ({}, {})", x, y
);
worm.position.x = x;
@@ -141,19 +136,18 @@ impl GameBoard {
for player_index in 0..moves.len() {
if let Command::Dig(x, y) = moves[player_index] {
- println!("Player {} is digging {}, {}", player_index, x, y);
debug_assert!(
- Some(CellType::Dirt) == self.map.at(Point2d::new(x, y)) ||
- Some(CellType::Air) == self.map.at(Point2d::new(x, y))
+ Some(true) == self.map.at(Point2d::new(x, y)) ||
+ (player_index == 1 && moves[0] == Command::Dig(x, y)),
+ "Tried to dig through air, ({}, {})", x, y
);
debug_assert!{
(self.players[player_index].active_worm().position.x - x).abs() <= 1 &&
- (self.players[player_index].active_worm().position.y - y).abs() <= 1
+ (self.players[player_index].active_worm().position.y - y).abs() <= 1,
+ "Tried to dig too far away, ({}, {})", x, y
};
- if let Some(c) = self.map.at_mut(Point2d::new(x, y)) {
- *c = CellType::Air;
- }
+ self.map.clear(Point2d::new(x, y));
}
}
@@ -174,7 +168,7 @@ impl GameBoard {
for distance in 1..=range {
let target = center + diff * distance;
match self.map.at(target) {
- Some(CellType::Air) => {
+ Some(false) => {
let target_worm: Option<&mut Worm> = self.players.iter_mut()
.flat_map(|p| p.worms.iter_mut())
.find(|w| w.position == target);
@@ -233,19 +227,53 @@ impl Player {
}
impl Map {
- pub fn at(&self, p: Point2d<i8>) -> Option<CellType> {
- if p.y < 0 || p.x < 0 || p.y as u8 >= self.size || p.x as u8 >= self.size {
+ pub fn at(&self, p: Point2d<i8>) -> Option<bool> {
+ if p.y < 0 || p.y as usize >= MAP_SIZE {
None
} else {
- Some(self.cells[p.y as usize * self.size as usize + p.x as usize])
+ let row_data = &MAP_ROW_SIZE[p.y as usize];
+ if p.x < row_data.x_offset as i8 || p.x as usize >= row_data.x_offset + row_data.len() {
+ None
+ } else {
+ let global_bit = row_data.start_bit + p.x as usize - row_data.x_offset;
+ let integer = global_bit / 64;
+ let bit = global_bit % 64;
+ let mask = 1 << bit;
+ Some(self.cells[integer] & mask != 0)
+ }
}
}
- fn at_mut(&mut self, p: Point2d<i8>) -> Option<&mut CellType> {
- if p.y < 0 || p.x < 0 || p.y as u8 >= self.size || p.x as u8 >= self.size {
- None
+ fn set(&mut self, p: Point2d<i8>) {
+ if p.y < 0 || p.y as usize >= MAP_SIZE {
+ debug_assert!(false, "Tried to set an out of bounds bit, {:?}", p);
} else {
- Some(&mut self.cells[p.y as usize * self.size as usize + p.x as usize])
+ let row_data = &MAP_ROW_SIZE[p.y as usize];
+ if p.x < row_data.x_offset as i8 || p.x as usize >= row_data.x_offset + row_data.len() {
+ debug_assert!(false, "Tried to set an out of bounds bit, {:?}", p);
+ } else {
+ let global_bit = row_data.start_bit + p.x as usize - row_data.x_offset;
+ let integer = global_bit / 64;
+ let bit = global_bit % 64;
+ let mask = 1 << bit;
+ self.cells[integer] |= mask;
+ }
+ }
+ }
+ fn clear(&mut self, p: Point2d<i8>) {
+ if p.y < 0 || p.y as usize >= MAP_SIZE {
+ debug_assert!(false, "Tried to set an out of bounds bit, {:?}", p);
+ } else {
+ let row_data = &MAP_ROW_SIZE[p.y as usize];
+ if p.x < row_data.x_offset as i8 || p.x as usize >= row_data.x_offset + row_data.len() {
+ debug_assert!(false, "Tried to set an out of bounds bit, {:?}", p);
+ } else {
+ let global_bit = row_data.start_bit + p.x as usize - row_data.x_offset;
+ let integer = global_bit / 64;
+ let bit = global_bit % 64;
+ let mask = !(1 << bit);
+ self.cells[integer] &= mask;
+ }
}
}
}