screeps/local/room_xy/
extra_math.rs

1//! Math utilities on `RoomXY` which don't exist in the Screeps API
2//! proper.
3
4use std::ops::{Add, Sub};
5
6use super::RoomXY;
7use crate::constants::Direction;
8
9impl RoomXY {
10    /// Returns a new position offset from this position by the specified x
11    /// coords and y coords.
12    ///
13    /// Unlike [`Position::offset`], this function operates on room coordinates,
14    /// and will panic if the new position overflows the room.
15    ///
16    /// To return a new position rather than modifying in place, use `pos + (x,
17    /// y)`. See the implementation of `Add<(i8, i8)>` for
18    /// [`RoomXY`] further down on this page.
19    ///
20    /// # Panics
21    ///
22    /// Will panic if the new position overflows the room.
23    ///
24    /// # Example
25    ///
26    /// ```
27    /// # use screeps::RoomXY;
28    ///
29    /// let mut pos = RoomXY::checked_new(21, 21).unwrap();
30    /// pos.offset(5, 5);
31    /// assert_eq!(pos, RoomXY::checked_new(26, 26).unwrap());
32    ///
33    /// let mut pos = RoomXY::checked_new(21, 21).unwrap();
34    /// pos.offset(-5, 5);
35    /// assert_eq!(pos, RoomXY::checked_new(16, 26).unwrap());
36    /// ```
37    ///
38    /// [`Position::offset`]: crate::local::Position::offset
39    #[inline]
40    #[track_caller]
41    pub fn offset(&mut self, x: i8, y: i8) {
42        *self = *self + (x, y);
43    }
44}
45
46impl Add<(i8, i8)> for RoomXY {
47    type Output = RoomXY;
48
49    /// Adds an `(x, y)` pair to this position's coordinates.
50    ///
51    /// # Panics
52    ///
53    /// Will panic if the new position is outside standard room bounds.
54    ///
55    /// # Example
56    ///
57    /// ```
58    /// # use screeps::RoomXY;
59    ///
60    /// let pos1 = RoomXY::checked_new(42, 42).unwrap();
61    /// let pos2 = pos1 + (7, 7);
62    /// assert_eq!(pos2, RoomXY::checked_new(49, 49).unwrap());
63    /// ```
64    #[inline]
65    #[track_caller]
66    fn add(self, (x, y): (i8, i8)) -> Self {
67        self.checked_add((x, y)).unwrap()
68    }
69}
70
71impl Add<Direction> for RoomXY {
72    type Output = RoomXY;
73
74    /// Adds a `Direction` to this position's coordinates.
75    ///
76    /// # Panics
77    ///
78    /// Will panic if the new position is outside standard room bounds.
79    ///
80    /// # Example
81    ///
82    /// ```
83    /// # use screeps::{RoomXY, Direction};
84    ///
85    /// let pos1 = RoomXY::checked_new(49, 40).unwrap();
86    /// let pos2 = pos1 + Direction::Top;
87    /// assert_eq!(pos2, RoomXY::checked_new(49, 39).unwrap());
88    /// ```
89    #[inline]
90    #[track_caller]
91    fn add(self, direction: Direction) -> Self {
92        self.checked_add_direction(direction).unwrap()
93    }
94}
95
96impl Sub<(i8, i8)> for RoomXY {
97    type Output = RoomXY;
98
99    /// Subtracts an `(x, y)` pair from this position's coordinates.
100    ///
101    /// # Panics
102    ///
103    /// Will panic if the new position is outside standard room bounds.
104    ///
105    /// # Example
106    ///
107    /// ```
108    /// # use screeps::RoomXY;
109    ///
110    /// let pos1 = RoomXY::checked_new(49, 40).unwrap();
111    /// let pos2 = pos1 - (49, 0);
112    /// assert_eq!(pos2, RoomXY::checked_new(0, 40).unwrap());
113    /// ```
114    #[inline]
115    #[track_caller]
116    fn sub(self, (x, y): (i8, i8)) -> Self {
117        self.checked_add((-x, -y)).unwrap()
118    }
119}
120
121impl Sub<Direction> for RoomXY {
122    type Output = RoomXY;
123
124    /// Subtracts a `Direction` from this position's coordinates.
125    ///
126    /// # Panics
127    ///
128    /// Will panic if the new position is outside standard room bounds.
129    ///
130    /// # Example
131    ///
132    /// ```
133    /// # use screeps::{RoomXY, Direction};
134    ///
135    /// let pos1 = RoomXY::checked_new(49, 40).unwrap();
136    /// let pos2 = pos1 - Direction::Top;
137    /// assert_eq!(pos2, RoomXY::checked_new(49, 41).unwrap());
138    /// ```
139    #[inline]
140    fn sub(self, direction: Direction) -> Self {
141        self.checked_add_direction(-direction).unwrap()
142    }
143}
144
145impl Sub<RoomXY> for RoomXY {
146    type Output = (i8, i8);
147
148    /// Subtracts the other position from this one, extracting the
149    /// difference as the output.
150    ///
151    /// # Example
152    ///
153    /// ```
154    /// # use screeps::RoomXY;
155    ///
156    /// let pos1 = RoomXY::checked_new(40, 40).unwrap();
157    /// let pos2 = RoomXY::checked_new(0, 20).unwrap();
158    /// assert_eq!(pos1 - pos2, (40, 20));
159    ///
160    /// let pos3 = RoomXY::checked_new(45, 45).unwrap();
161    /// assert_eq!(pos1 - pos3, (-5, -5));
162    /// ```
163    #[inline]
164    fn sub(self, other: RoomXY) -> (i8, i8) {
165        let dx = self.x.u8() as i8 - other.x.u8() as i8;
166        let dy = self.y.u8() as i8 - other.y.u8() as i8;
167        (dx, dy)
168    }
169}