summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJustin Worthe <justin@worthe-it.co.za>2018-08-09 22:08:16 +0200
committerJustin Worthe <justin@worthe-it.co.za>2018-08-09 22:08:16 +0200
commit52c4dc1dd7bbe6546e0a2b3eeb4b5ec78d3fb582 (patch)
treea8c5fd40b0b41abd6036888ad78b5b5083f0f66e /src
parentb2cbd720858d482257da98839a5c8ee8c85c6b62 (diff)
Updated point representation to better match my heavy bitfield usage
Diffstat (limited to 'src')
-rw-r--r--src/engine/bitwise_engine.rs18
-rw-r--r--src/engine/command.rs4
-rw-r--r--src/engine/geometry.rs76
-rw-r--r--src/input/json.rs15
4 files changed, 40 insertions, 73 deletions
diff --git a/src/engine/bitwise_engine.rs b/src/engine/bitwise_engine.rs
index 40a8562..0cfd5fc 100644
--- a/src/engine/bitwise_engine.rs
+++ b/src/engine/bitwise_engine.rs
@@ -85,13 +85,13 @@ impl BitwiseGameState {
pub fn unoccupied_opponent_cell_count(&self) -> usize { self.opponent_buildings.occupied.count_zeros() as usize }
pub fn location_of_unoccupied_player_cell(&self, i: usize) -> Point {
let bit = find_bit_index_from_rank(self.player_buildings.occupied, i as u64);
- let point = Point::new(bit%SINGLE_MAP_WIDTH, bit/SINGLE_MAP_WIDTH);
+ let point = Point { index: bit };
debug_assert!(point.to_either_bitfield() & self.player_buildings.occupied == 0);
point
}
pub fn location_of_unoccupied_opponent_cell(&self, i: usize) -> Point {
let bit = find_bit_index_from_rank(self.opponent_buildings.occupied, i as u64);
- let point = Point::new(FULL_MAP_WIDTH - bit%SINGLE_MAP_WIDTH - 1, bit/SINGLE_MAP_WIDTH);
+ let point = Point { index: bit };
debug_assert!(point.to_either_bitfield() & self.opponent_buildings.occupied == 0);
point
}
@@ -222,7 +222,7 @@ impl BitwiseGameState {
// This is used internally. I should not be making
// invalid moves!
debug_assert!(player_buildings.buildings[0] & bitfield == 0);
- debug_assert!(p.x < FULL_MAP_WIDTH && p.y < MAP_HEIGHT);
+ debug_assert!(p.x() < FULL_MAP_WIDTH && p.y() < MAP_HEIGHT);
debug_assert!(player.energy >= price);
debug_assert!(b != BuildingType::Tesla ||
player_buildings.count_teslas() < TESLA_MAX);
@@ -314,20 +314,20 @@ impl BitwiseGameState {
player.energy -= TESLA_FIRING_ENERGY;
tesla.cooldown = TESLA_COOLDOWN;
- let flipped_pos = tesla.pos.flip_x();
-
- if flipped_pos.x >= SINGLE_MAP_WIDTH - 1 {
+ if tesla.pos.to_either_bitfield() & RIGHT_COL_MASK != 0 {
opponent.health = opponent.health.saturating_sub(TESLA_DAMAGE);
}
- let missed_cells = ((SINGLE_MAP_WIDTH - flipped_pos.x) as u32).saturating_sub(2);
+ let x = tesla.pos.x();
+ let y = tesla.pos.y();
+ let missed_cells = ((SINGLE_MAP_WIDTH - x) as u32).saturating_sub(2);
- let top_row = if tesla.pos.y == 0 { 0 } else { tesla.pos.y - 1 };
+ let top_row = y.saturating_sub(1);
let top_row_mask = 255u64 << (top_row * SINGLE_MAP_WIDTH);
let mut destroy_mask = top_row_mask.wrapping_shl(missed_cells) & top_row_mask;
let mut hits = 0;
- for _ in 0..(if tesla.pos.y == 0 || tesla.pos.y == MAP_HEIGHT-1 { 2 } else { 3 }) {
+ for _ in 0..(if y == 0 || y == MAP_HEIGHT-1 { 2 } else { 3 }) {
hits |= destroy_mask & opponent_buildings.buildings[0];
destroy_mask &= !hits;
destroy_mask = destroy_mask << SINGLE_MAP_WIDTH;
diff --git a/src/engine/command.rs b/src/engine/command.rs
index 3ea0fbe..da7e1e0 100644
--- a/src/engine/command.rs
+++ b/src/engine/command.rs
@@ -12,8 +12,8 @@ impl fmt::Display for Command {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
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),
+ Command::Build(p, b) => write!(f, "{},{},{}", p.x(), p.y(), b as u8),
+ Command::Deconstruct(p) => write!(f, "{},{},3", p.x(), p.y()),
}
}
}
diff --git a/src/engine/geometry.rs b/src/engine/geometry.rs
index de9d95a..bfa59da 100644
--- a/src/engine/geometry.rs
+++ b/src/engine/geometry.rs
@@ -5,45 +5,36 @@ use engine::constants::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Point {
- pub x: u8,
- pub y: u8
+ pub index: u8
}
impl Point {
pub fn new(x: u8, y: u8) -> Point {
- Point { x, y }
- }
- pub fn move_left(&self) -> Option<Point> {
- self.x.checked_sub(1).map(|x| Point {
- x,
- ..*self
- })
- }
- pub fn move_right(&self, size: &Point) -> Option<Point> {
- if self.x + 1 >= size.x {
- None
+ let flipped_x = if x >= SINGLE_MAP_WIDTH {
+ FULL_MAP_WIDTH - x - 1
} else {
- Some(Point {
- x: self.x + 1,
- ..*self
- })
+ x
+ };
+ Point {
+ index: y * SINGLE_MAP_WIDTH + flipped_x
}
}
- pub fn wrapping_move_left(&mut self) {
- self.x = self.x.wrapping_sub(1);
+ pub fn new_double_bitfield(x: u8, y: u8, is_left_player: bool) -> (u64, u64) {
+ let bitfield = Point::new(x, y).to_either_bitfield();
+ if (x >= SINGLE_MAP_WIDTH) == is_left_player {
+ (0, bitfield)
+ } else {
+ (bitfield, 0)
+ }
}
- pub fn wrapping_move_right(&mut self) {
- self.x = self.x.wrapping_add(1);
+
+ pub fn x(&self) -> u8 {
+ self.index % SINGLE_MAP_WIDTH
}
- pub fn flip_x(&self) -> Point {
- let flipped_x = if self.x >= SINGLE_MAP_WIDTH {
- FULL_MAP_WIDTH - self.x - 1
- } else {
- self.x
- };
- Point::new(flipped_x, self.y)
+ pub fn y(&self) -> u8 {
+ self.index / SINGLE_MAP_WIDTH
}
}
@@ -57,31 +48,8 @@ impl Point {
* This involves mirroring the x dimension for the opponent's side
*/
-
- pub fn to_bitfield(&self) -> (u64, u64) {
- (self.to_left_bitfield(), self.to_right_bitfield())
- }
-
- pub fn to_left_bitfield(&self) -> u64 {
- if self.x >= SINGLE_MAP_WIDTH {
- 0
- } else {
- let index = self.y * SINGLE_MAP_WIDTH + self.x;
- 1 << index
- }
- }
-
- pub fn to_right_bitfield(&self) -> u64 {
- if self.x < SINGLE_MAP_WIDTH {
- 0
- } else {
- let index = self.y * SINGLE_MAP_WIDTH + FULL_MAP_WIDTH - self.x - 1;
- 1 << index
- }
- }
-
pub fn to_either_bitfield(&self) -> u64 {
- self.to_left_bitfield() | self.to_right_bitfield()
+ 1u64 << self.index
}
}
@@ -95,8 +63,6 @@ impl PartialOrd for Point {
}
impl Ord for Point {
fn cmp(&self, other: &Point) -> Ordering {
- let a = self.flip_x();
- let b = other.flip_x();
- a.y.cmp(&b.y).then(a.x.cmp(&b.x))
+ self.index.cmp(&other.index)
}
}
diff --git a/src/input/json.rs b/src/input/json.rs
index 3927a96..4aebcfa 100644
--- a/src/input/json.rs
+++ b/src/input/json.rs
@@ -73,11 +73,12 @@ impl State {
for building in &cell.buildings {
let building_type = building.convert_building_type();
- let (mut bitwise_buildings, bitfield) = if building.player_type == 'A' {
- (&mut player_buildings, point.to_left_bitfield())
+ let mut bitwise_buildings = if building.player_type == 'A' {
+ &mut player_buildings
} else {
- (&mut opponent_buildings, point.to_right_bitfield())
+ &mut opponent_buildings
};
+ let bitfield = point.to_either_bitfield();
bitwise_buildings.occupied |= bitfield;
if building.construction_time_left >= 0 {
@@ -108,11 +109,11 @@ impl State {
}
}
for missile in &cell.missiles {
- let bitfields = point.to_bitfield();
- let (mut bitwise_buildings, mut left, mut right) = if missile.player_type == 'A' {
- (&mut player_buildings, bitfields.0, bitfields.1)
+ let (mut left, mut right) = engine::geometry::Point::new_double_bitfield(cell.x, cell.y, missile.player_type == 'A');
+ let mut bitwise_buildings = if missile.player_type == 'A' {
+ &mut player_buildings
} else {
- (&mut opponent_buildings, bitfields.1, bitfields.0)
+ &mut opponent_buildings
};
for mut tier in bitwise_buildings.missiles.iter_mut() {