diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fe2ad81..c059c8e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ Unreleased ========== +### Breaking: + +- Simplification of cost matrix types and traits: + - Remove `SparseCostMatrix`, to be moved to `screeps-game-utils` crate + - Remove `LocalCostMatrix::merge_from_dense` / `merge_from_sparse` + - Remove `CostMatrixSet::set_multi` and replace `CostMatrixSet::set` with `set_xy` + - Add `CostMatrixGet` trait with `get_xy` function + - Remove `HasLocalPosition` trait with no implementations + 0.17.0 (2023-11-27) =================== diff --git a/src/local/cost_matrix.rs b/src/local/cost_matrix.rs index 4e6d1150..32c6268c 100644 --- a/src/local/cost_matrix.rs +++ b/src/local/cost_matrix.rs @@ -1,12 +1,11 @@ -use std::{ - collections::HashMap, - iter::IntoIterator, - ops::{Index, IndexMut}, -}; +use std::ops::{Index, IndexMut}; use serde::{Deserialize, Serialize}; -use crate::objects::CostMatrix; +use crate::{ + objects::CostMatrix, + traits::{CostMatrixGet, CostMatrixSet}, +}; use super::{linear_index_to_xy, xy_to_linear_index, Position, RoomXY, ROOM_AREA}; @@ -64,33 +63,6 @@ impl LocalCostMatrix { .enumerate() .map(|(idx, val)| (linear_index_to_xy(idx), val)) } - - // Takes all non-zero entries in `src`, and inserts them into `self`. - // - // If an entry for that position exists already, overwrites it with the new - // value. - pub fn merge_from_dense(&mut self, src: &LocalCostMatrix) { - for i in 0..ROOM_AREA { - let val = unsafe { *src.bits.get_unchecked(i) }; - if val > 0 { - unsafe { - *self.bits.get_unchecked_mut(i) = val; - } - } - } - } - - // Takes all entries in `src` and merges them into `self`. - // - // If an entry for that position exists already, overwrites it with the new - // value. - pub fn merge_from_sparse(&mut self, src: &SparseCostMatrix) { - for (xy, val) in src.iter() { - unsafe { - *self.bits.get_unchecked_mut(xy_to_linear_index(xy)) = val; - } - } - } } impl From for Vec { @@ -147,141 +119,15 @@ impl IndexMut for LocalCostMatrix { } } -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] -#[serde(transparent)] -pub struct SparseCostMatrix { - inner: HashMap, -} - -impl Default for SparseCostMatrix { - fn default() -> Self { - Self::new() +impl CostMatrixSet for LocalCostMatrix { + fn set_xy(&mut self, xy: RoomXY, cost: u8) { + LocalCostMatrix::set(self, xy, cost); } } -impl SparseCostMatrix { - pub fn new() -> Self { - SparseCostMatrix { - inner: HashMap::new(), - } - } - - pub fn get(&self, xy: RoomXY) -> u8 { - *self.inner.get(&xy).unwrap_or(&0) - } - - pub fn set(&mut self, xy: RoomXY, val: u8) { - self.inner.insert(xy, val); - } - - pub fn iter(&self) -> impl Iterator + '_ { - self.inner.iter().map(|(&pos, &val)| (pos, val)) - } - - pub fn iter_mut(&mut self) -> impl Iterator { - self.inner.iter_mut().map(|(&pos, val)| (pos, val)) - } - - // Takes all non-zero entries in `src`, and inserts them into `self`. - // - // If an entry for that position exists already, overwrites it with the new - // value. - pub fn merge_from_dense(&mut self, src: &LocalCostMatrix) { - self.inner.extend(src.iter().filter_map( - |(xy, val)| { - if val > 0 { - Some((xy, val)) - } else { - None - } - }, - )) - } - - // Takes all entries in `src` and merges them into `self`. - // - // If an entry for that position exists already, overwrites it with the new - // value. - pub fn merge_from_sparse(&mut self, src: &SparseCostMatrix) { - self.inner.extend(src.inner.iter()); - } -} - -impl From> for SparseCostMatrix { - fn from(inner: HashMap) -> Self { - SparseCostMatrix { inner } - } -} - -impl From<&HashMap> for SparseCostMatrix { - fn from(map: &HashMap) -> Self { - SparseCostMatrix { inner: map.clone() } - } -} - -impl From<&HashMap> for SparseCostMatrix { - fn from(map: &HashMap) -> Self { - SparseCostMatrix { - inner: map.iter().map(|(&pos, &val)| (pos.into(), val)).collect(), - } - } -} - -impl From<&CostMatrix> for SparseCostMatrix { - fn from(js_matrix: &CostMatrix) -> Self { - let vals: Vec = js_matrix.get_bits().to_vec(); - assert!( - vals.len() == ROOM_AREA, - "JS CostMatrix had length {} instead of {}.", - vals.len(), - ROOM_AREA - ); - - SparseCostMatrix { - inner: vals - .into_iter() - .enumerate() - .filter_map(|(idx, val)| { - // 0 is the same as unset, so filtering it out - if val > 0 { - Some((linear_index_to_xy(idx), val)) - } else { - None - } - }) - .collect(), - } - } -} - -impl From<&LocalCostMatrix> for SparseCostMatrix { - fn from(lcm: &LocalCostMatrix) -> Self { - SparseCostMatrix { - inner: lcm - .iter() - .filter_map(|(xy, val)| if val > 0 { Some((xy, val)) } else { None }) - .collect(), - } - } -} - -impl From for LocalCostMatrix { - fn from(mut scm: SparseCostMatrix) -> Self { - let mut lcm = LocalCostMatrix::new(); - for (pos, val) in scm.inner.drain() { - lcm[pos] = val; - } - lcm - } -} - -impl From<&SparseCostMatrix> for LocalCostMatrix { - fn from(scm: &SparseCostMatrix) -> Self { - let mut lcm = LocalCostMatrix::new(); - for (&pos, &val) in scm.inner.iter() { - lcm[pos] = val; - } - lcm +impl CostMatrixGet for LocalCostMatrix { + fn get_xy(&mut self, xy: RoomXY) -> u8 { + LocalCostMatrix::get(self, xy) } } diff --git a/src/objects/impls/cost_matrix.rs b/src/objects/impls/cost_matrix.rs index 716c8b1e..41f219b5 100644 --- a/src/objects/impls/cost_matrix.rs +++ b/src/objects/impls/cost_matrix.rs @@ -1,7 +1,11 @@ use js_sys::{Array, Object, Uint8Array}; use wasm_bindgen::prelude::*; -use crate::{local::LocalCostMatrix, prototypes::COST_MATRIX_PROTOTYPE}; +use crate::{ + local::{LocalCostMatrix, RoomXY}, + prototypes::COST_MATRIX_PROTOTYPE, + traits::{CostMatrixGet, CostMatrixSet}, +}; #[wasm_bindgen] extern "C" { @@ -81,3 +85,15 @@ impl From for CostMatrix { CostMatrix::new_from_bits(matrix.get_bits()) } } + +impl CostMatrixSet for CostMatrix { + fn set_xy(&mut self, xy: RoomXY, cost: u8) { + CostMatrix::set(self, xy.x.u8(), xy.y.u8(), cost); + } +} + +impl CostMatrixGet for CostMatrix { + fn get_xy(&mut self, xy: RoomXY) -> u8 { + CostMatrix::get(self, xy.x.u8(), xy.y.u8()) + } +} diff --git a/src/traits.rs b/src/traits.rs index b7eb965b..5878347f 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,7 +1,7 @@ //! Traits associated with how specific [game objects] can be used. //! //! [game objects]: crate::objects -use std::{borrow::Borrow, str::FromStr}; +use std::str::FromStr; use enum_dispatch::enum_dispatch; use js_sys::{Array, JsString}; @@ -10,7 +10,7 @@ use wasm_bindgen::prelude::*; use crate::{ constants::*, enums::*, - local::{ObjectId, Position, RawObjectId, RoomName}, + local::{ObjectId, Position, RawObjectId, RoomName, RoomXY}, objects::*, pathfinder::SingleRoomCostResult, prelude::*, @@ -181,56 +181,12 @@ pub trait MaybeHasPosition { fn try_pos(&self) -> Option; } -pub trait HasLocalPosition { - fn x(&self) -> u8; - fn y(&self) -> u8; -} - pub trait CostMatrixSet { - fn set(&mut self, position: P, cost: V) - where - P: HasLocalPosition, - V: Borrow; - - fn set_multi(&mut self, data: D) - where - D: IntoIterator, - B: Borrow<(P, V)>, - P: HasLocalPosition, - V: Borrow; -} - -#[inline] -const fn pos_as_idx(x: u8, y: u8) -> usize { - (x as usize) * ROOM_SIZE as usize + (y as usize) + fn set_xy(&mut self, xy: RoomXY, cost: u8); } -impl CostMatrixSet for CostMatrix { - fn set(&mut self, position: P, cost: V) - where - P: HasLocalPosition, - V: Borrow, - { - CostMatrix::set(self, position.x(), position.y(), *cost.borrow()); - } - - fn set_multi(&mut self, data: D) - where - D: IntoIterator, - B: Borrow<(P, V)>, - P: HasLocalPosition, - V: Borrow, - { - let matrix_buffer = self.get_bits(); - - for entry in data.into_iter() { - let (pos, cost) = entry.borrow(); - - let offset = pos_as_idx(pos.x(), pos.y()); - - matrix_buffer.set_index(offset as u32, *cost.borrow()); - } - } +pub trait CostMatrixGet { + fn get_xy(&mut self, xy: RoomXY) -> u8; } #[enum_dispatch]