From 52c4dc1dd7bbe6546e0a2b3eeb4b5ec78d3fb582 Mon Sep 17 00:00:00 2001 From: Justin Worthe Date: Thu, 9 Aug 2018 22:08:16 +0200 Subject: Updated point representation to better match my heavy bitfield usage --- src/engine/bitwise_engine.rs | 18 +++++------ src/engine/command.rs | 4 +-- src/engine/geometry.rs | 76 ++++++++++++-------------------------------- src/input/json.rs | 15 +++++---- 4 files changed, 40 insertions(+), 73 deletions(-) (limited to 'src') 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 { - self.x.checked_sub(1).map(|x| Point { - x, - ..*self - }) - } - pub fn move_right(&self, size: &Point) -> Option { - 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() { -- cgit v1.2.3