1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
//! Math utilities on `Position` which don't exist in the Screeps API
//! proper.
use std::ops::{Add, Sub};
use super::Position;
impl Position {
/// Returns a new position offset from this position by the specified x
/// coords and y coords.
///
/// This function operates on world coordinates, and will wrap between rooms
/// if necessary.
///
/// To return a new position rather than modifying in place, use `pos + (x,
/// y)`. See the implementation of `Add<(i32, i32)>` for
/// [`Position`] further down on this page.
///
/// # Panics
///
/// Will panic if the new position overflows the world. See
/// [`Position::from_world_coords`].
///
/// # Example
///
/// ```
/// use screeps::Position;
///
/// let e21s21 = "E21S21".parse().unwrap();
/// let e21s22 = "E21S22".parse().unwrap();
///
/// let mut pos = Position::new(21, 21, e21s21);
/// pos.offset(5, 5);
/// assert_eq!(pos, Position::new(26, 26, e21s21));
///
/// pos.offset(0, 49);
/// assert_eq!(pos, Position::new(26, 25, e21s22));
/// ```
#[inline]
pub fn offset(&mut self, x: i32, y: i32) {
*self = *self + (x, y);
}
}
impl Add<(i32, i32)> for Position {
type Output = Position;
/// Adds an `(x, y)` pair to this room position's world coordinates.
///
/// Will change rooms if necessary.
///
/// # Panics
///
/// Will panic if the new position's room is outside bounds. See
/// [`Position::from_world_coords`].
///
/// # Example
///
/// ```
/// use screeps::Position;
///
/// let w5s6 = "W5S6".parse().unwrap();
/// let w5s5 = "W5S5".parse().unwrap();
///
/// let pos1 = Position::new(42, 42, w5s6);
/// let pos2 = pos1 + (7, 7);
/// assert_eq!(pos2, Position::new(49, 49, w5s6));
///
/// let pos3 = pos2 + (0, -59);
/// assert_eq!(pos3, Position::new(49, 40, w5s5));
///
/// let pos4 = pos3 - (49, 0);
/// assert_eq!(pos4, Position::new(0, 40, w5s5));
/// ```
#[inline]
fn add(self, (x, y): (i32, i32)) -> Self {
let (wx, wy) = self.world_coords();
Self::from_world_coords(wx + x, wy + y)
}
}
impl Sub<(i32, i32)> for Position {
type Output = Position;
/// See the implementation of `Add<(i32, i32)>` for [`Position`].
#[inline]
fn sub(self, (x, y): (i32, i32)) -> Self {
self + (-x, -y)
}
}
impl Sub<Position> for Position {
type Output = (i32, i32);
/// Subtracts the other room position from this one, extracting the
/// difference as the output.
///
/// # Example
///
/// ```
/// use screeps::Position;
///
/// let e5n5 = "E5N5".parse().unwrap();
/// let e5n6 = "E5N6".parse().unwrap();
///
/// let pos1 = Position::new(40, 40, e5n5);
/// let pos2 = Position::new(0, 20, e5n6);
/// assert_eq!(pos1 - pos2, (40, 70));
/// ```
#[inline]
fn sub(self, other: Position) -> (i32, i32) {
let (mx, my) = self.world_coords();
let (ox, oy) = other.world_coords();
(mx - ox, my - oy)
}
}