diff options
Diffstat (limited to 'src/types/mod.rs')
-rw-r--r-- | src/types/mod.rs | 504 |
1 files changed, 0 insertions, 504 deletions
diff --git a/src/types/mod.rs b/src/types/mod.rs deleted file mode 100644 index d417e873d8ca..000000000000 --- a/src/types/mod.rs +++ /dev/null @@ -1,504 +0,0 @@ -#![allow(clippy::unit_arg)] -#![allow(clippy::identity_conversion)] - -use std::cmp::max; -use std::cmp::Ordering; -use std::ops; -use std::rc::Rc; - -pub mod collision; -pub mod command; -pub mod direction; -pub mod entity_map; -pub mod menu; - -pub use collision::Collision; -pub use direction::Direction; -pub use direction::Direction::*; -use proptest_derive::Arbitrary; -use termion::cursor; - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Arbitrary)] -pub struct Dimensions { - #[proptest(strategy = "std::ops::Range::<u16>::from(0..100)")] - pub w: u16, - - #[proptest(strategy = "std::ops::Range::<u16>::from(0..100)")] - pub h: u16, -} - -pub const ZERO_DIMENSIONS: Dimensions = Dimensions { w: 0, h: 0 }; -pub const UNIT_DIMENSIONS: Dimensions = Dimensions { w: 1, h: 1 }; - -impl Default for Dimensions { - fn default() -> Self { - Dimensions { w: 80, h: 20 } - } -} - -impl ops::Sub<Dimensions> for Dimensions { - type Output = Dimensions; - fn sub(self, dims: Dimensions) -> Dimensions { - Dimensions { - w: self.w - dims.w, - h: self.h - dims.h, - } - } -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Arbitrary)] -pub struct BoundingBox { - pub dimensions: Dimensions, - pub position: Position, -} - -impl BoundingBox { - pub fn at_origin(dimensions: Dimensions) -> BoundingBox { - BoundingBox { - dimensions, - position: ORIGIN, - } - } - - pub fn from_corners( - top_left: Position, - lower_right: Position, - ) -> BoundingBox { - BoundingBox { - position: top_left, - dimensions: Dimensions { - w: (lower_right.x - top_left.x) as u16, - h: (lower_right.y - top_left.y) as u16, - }, - } - } - - pub fn lr_corner(self) -> Position { - self.position - + (Position { - x: self.dimensions.w as i16, - y: self.dimensions.h as i16, - }) - } - - pub fn ll_corner(self) -> Position { - self.position - + (Position { - x: 0, - y: self.dimensions.h as i16, - }) - } - - /// Returns a bounding box representing the *inside* of this box if it was - /// drawn on the screen. - pub fn inner(self) -> BoundingBox { - self + UNIT_POSITION - UNIT_DIMENSIONS - UNIT_DIMENSIONS - } - - /// Moves the top right corner of the bounding box by the offset specified - /// by the given position, keeping the lower right corner in place - pub fn move_tr_corner(self, offset: Position) -> BoundingBox { - self + offset - - Dimensions { - w: offset.x as u16, - h: offset.y as u16, - } - } -} - -impl ops::Add<Position> for BoundingBox { - type Output = BoundingBox; - fn add(self, pos: Position) -> BoundingBox { - BoundingBox { - position: self.position + pos, - ..self - } - } -} - -impl ops::Sub<Dimensions> for BoundingBox { - type Output = BoundingBox; - fn sub(self, dims: Dimensions) -> BoundingBox { - BoundingBox { - dimensions: self.dimensions - dims, - ..self - } - } -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Arbitrary, Hash, Ord)] -pub struct Position { - /// x (horizontal) position - #[proptest(strategy = "std::ops::Range::<i16>::from(0..100)")] - pub x: i16, - - #[proptest(strategy = "std::ops::Range::<i16>::from(0..100)")] - /// y (vertical) position - pub y: i16, -} - -pub fn pos(x: i16, y: i16) -> Position { - Position { x, y } -} - -pub const ORIGIN: Position = Position { x: 0, y: 0 }; -pub const UNIT_POSITION: Position = Position { x: 1, y: 1 }; - -impl Position { - /// Returns true if this position exists within the bounds of the given box, - /// inclusive - pub fn within(self, b: BoundingBox) -> bool { - (self > b.position - UNIT_POSITION) && self < (b.lr_corner()) - } - - /// Returns a sequence of ASCII escape characters for moving the cursor to - /// this Position - pub fn cursor_goto(self) -> cursor::Goto { - // + 1 because Goto is 1-based, but position is 0-based - cursor::Goto(self.x as u16 + 1, self.y as u16 + 1) - } - - /// Converts this position to the number of `Tiles` away from the origin it - /// represents. Usually done after subtracting two positions. Gives distance - /// as the crow flies - pub fn as_tiles(self) -> Tiles { - Tiles(max(self.x.abs(), self.y.abs()).into()) - } -} - -impl PartialOrd for Position { - fn partial_cmp(&self, other: &Position) -> Option<Ordering> { - if self.x == other.x && self.y == other.y { - Some(Ordering::Equal) - } else if self.x > other.x && self.y > other.y { - Some(Ordering::Greater) - } else if self.x < other.x && self.y < other.y { - Some(Ordering::Less) - } else { - None - } - } -} - -/// Implements (bounded) addition of a Dimension to a position. -/// -/// # Examples -/// -/// ``` -/// let pos = Position { x: 1, y: 10 } -/// -/// let left_pos = pos + Direction::Left -/// assert_eq!(left, Position { x: 0, y: 10 }) -/// -/// let right_pos = pos + Direction::Right -/// assert_eq!(right_pos, Position { x: 0, y: 10 }) -/// ``` -#[allow(clippy::suspicious_arithmetic_impl)] -impl ops::Add<Direction> for Position { - type Output = Position; - fn add(self, dir: Direction) -> Position { - match dir { - Left => { - if self.x > std::i16::MIN { - Position { - x: self.x - 1, - ..self - } - } else { - self - } - } - Right => { - if self.x < std::i16::MAX { - Position { - x: self.x + 1, - ..self - } - } else { - self - } - } - Up => { - if self.y > std::i16::MIN { - Position { - y: self.y - 1, - ..self - } - } else { - self - } - } - Down => { - if self.y < std::i16::MAX { - Position { - y: self.y + 1, - ..self - } - } else { - self - } - } - UpLeft => self + Up + Left, - UpRight => self + Up + Right, - DownLeft => self + Down + Left, - DownRight => self + Down + Right, - } - } -} - -impl ops::Add<Position> for Position { - type Output = Position; - fn add(self, pos: Position) -> Position { - Position { - x: self.x + pos.x, - y: self.y + pos.y, - } - } -} - -impl ops::Sub<Position> for Position { - type Output = Position; - fn sub(self, pos: Position) -> Position { - Position { - x: self.x - pos.x, - y: self.y - pos.y, - } - } -} - -impl Positioned for Position { - fn position(&self) -> Position { - *self - } -} - -pub trait Positioned { - fn x(&self) -> i16 { - self.position().x - } - - fn y(&self) -> i16 { - self.position().y - } - - fn position(&self) -> Position { - Position { - x: self.x(), - y: self.y(), - } - } -} - -pub trait PositionedMut: Positioned { - fn set_position(&mut self, pos: Position); -} - -// impl<A, I> Positioned for A where A : Deref<Target = I>, I: Positioned { -// fn position(&self) -> Position { -// self.position() -// } -// } - -impl<T: Positioned> Positioned for Box<T> { - fn position(&self) -> Position { - (**self).position() - } -} - -impl<'a, T: Positioned> Positioned for &'a T { - fn position(&self) -> Position { - (**self).position() - } -} - -impl<'a, T: Positioned> Positioned for &'a mut T { - fn position(&self) -> Position { - (**self).position() - } -} - -impl<'a, T: Positioned> Positioned for Rc<T> { - fn position(&self) -> Position { - (**self).position() - } -} - -impl<'a, T: PositionedMut> PositionedMut for &'a mut T { - fn set_position(&mut self, pos: Position) { - (**self).set_position(pos) - } -} - -#[macro_export] -macro_rules! positioned { - ($name:ident) => { - positioned!($name, position); - }; - ($name:ident, $attr:ident) => { - impl $crate::types::Positioned for $name { - fn position(&self) -> $crate::types::Position { - self.$attr - } - } - }; -} - -#[macro_export] -macro_rules! positioned_mut { - ($name:ident) => { - positioned_mut!($name, position); - }; - ($name:ident, $attr:ident) => { - impl crate::types::PositionedMut for $name { - fn set_position(&mut self, pos: $crate::types::Position) { - self.$attr = pos; - } - } - }; -} - -/// A number of ticks -#[derive(Clone, Copy, Debug, PartialEq, Eq, Arbitrary)] -pub struct Ticks(pub u16); - -/// A number of tiles -/// -/// Expressed in terms of a float to allow moving partial tiles in a number of -/// ticks -#[derive(Clone, Copy, Debug, PartialEq, Arbitrary)] -pub struct Tiles(pub f32); - -/// The speed of an entity, expressed in ticks per tile -#[derive(Clone, Copy, Debug, PartialEq, Eq, Arbitrary, Deserialize)] -#[serde(transparent)] -pub struct Speed(pub u32); - -impl Speed { - /// Returns the number of tiles that would be moved in the given number of - /// ticks at this speed - pub fn ticks_to_tiles(self, ticks: Ticks) -> Tiles { - Tiles(f32::from(ticks.0) / self.0 as f32) - } - - /// Returns the number of ticks required to move the given number of tiles - /// at this speed - pub fn tiles_to_ticks(self, tiles: Tiles) -> Ticks { - Ticks(tiles.0 as u16 * self.0 as u16) - } -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Arbitrary)] -pub struct Neighbors<A> { - pub top_left: A, - pub top: A, - pub top_right: A, - pub left: A, - pub right: A, - pub bottom_left: A, - pub bottom: A, - pub bottom_right: A, -} - -impl Neighbors<Position> { - fn of_position(pos: Position) -> Self { - Neighbors { - top_left: pos + Direction::UpLeft, - top: pos + Direction::Up, - top_right: pos + Direction::UpRight, - left: pos + Direction::Left, - right: pos + Direction::Right, - bottom_left: pos + Direction::DownLeft, - bottom: pos + Direction::Down, - bottom_right: pos + Direction::DownRight, - } - } -} - -impl<A> Neighbors<A> { - /// it's a functor, yo - pub fn map<B, F: Fn(&A) -> B>(&self, f: F) -> Neighbors<B> { - Neighbors { - top_left: f(&self.top_left), - top: f(&self.top), - top_right: f(&self.top_right), - left: f(&self.left), - right: f(&self.right), - bottom_left: f(&self.bottom_left), - bottom: f(&self.bottom), - bottom_right: f(&self.bottom_right), - } - } -} - -impl<A> Neighbors<Vec<A>> { - pub fn mapmap<B, F: Fn(&A) -> B>(&self, f: &F) -> Neighbors<Vec<B>> { - self.map(|xs| xs.iter().map(f).collect()) - } -} - -#[cfg(test)] -mod tests { - #![allow(clippy::unnecessary_operation)] - use super::*; - use proptest::prelude::*; - - proptest! { - #[test] - fn position_partialord_lt_transitive( - a: Position, - b: Position, - c: Position - ) { - if a < b && b < c { - assert!(a < c) - } - } - - #[test] - fn position_partialord_eq_transitive( - a: Position, - b: Position, - c: Position - ) { - if a == b && b == c { - assert!(a == c) - } - } - - #[test] - fn position_partialord_gt_transitive( - a: Position, - b: Position, - c: Position, - ) { - if a > b && b > c { - assert!(a > c) - } - } - - #[test] - fn position_partialord_antisymmetric(a: Position, b: Position) { - if a < b { - assert!(!(a > b)) - } else if a > b { - assert!(!(a < b)) - } - } - - #[test] - fn test_position_plus_dimension_as_tiles_monoid_action( - pos: Position, - dir: Direction, - ) { - prop_assume!(pos.y > 0 && pos.x > 0); - assert_eq!(((pos + dir) - pos).as_tiles(), Tiles(1.0)); - } - } - - #[test] - fn test_position_as_tiles() { - assert_eq!(pos(0, 0).as_tiles(), Tiles(0.0)); - assert_eq!(pos(1, 1).as_tiles(), Tiles(1.0)); - assert_eq!(pos(1, 2).as_tiles(), Tiles(2.0)); - } -} |