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}