npc_engine_utils/
coord2d.rs1use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
7
8use rand::Rng;
9
10#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Default)]
12pub struct Coord2D {
13 pub x: i32,
14 pub y: i32,
15}
16impl Coord2D {
17 pub const fn new(x: i32, y: i32) -> Self {
18 Coord2D { x, y }
19 }
20 pub const fn abs(&self) -> Self {
22 Self::new(self.x.abs(), self.y.abs())
23 }
24 pub fn abs_diff(&self, other: &Coord2D) -> Self {
26 (*self - *other).abs()
27 }
28 pub fn shortest_dim_dist(&self, other: &Coord2D) -> i32 {
30 let diff = self.abs_diff(other);
31 diff.x.min(diff.y)
32 }
33 pub fn largest_dim_dist(&self, other: &Coord2D) -> i32 {
35 let diff = self.abs_diff(other);
36 diff.x.max(diff.y)
37 }
38 pub fn max_per_comp(&self, other: Coord2D) -> Self {
40 Self::new(self.x.max(other.x), self.y.max(other.y))
41 }
42 pub fn min_per_comp(&self, other: Coord2D) -> Self {
44 Self::new(self.x.min(other.x), self.y.min(other.y))
45 }
46 pub fn rand_uniform(range: Coord2D) -> Self {
48 let mut rng = rand::thread_rng();
49 let x = rng.gen_range(0..range.x);
50 let y = rng.gen_range(0..range.y);
51 Self::new(x, y)
52 }
53 pub fn manhattan_dist(&self, other: Coord2D) -> i32 {
55 let diff = self.abs_diff(&other);
56 diff.x + diff.y
57 }
58}
59
60impl std::fmt::Display for Coord2D {
61 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62 write!(f, "[{}, {}]", self.x, self.y)
63 }
64}
65
66impl Ord for Coord2D {
67 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
68 self.y.cmp(&other.y).then(self.x.cmp(&other.x))
69 }
70}
71impl PartialOrd for Coord2D {
72 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
73 Some(self.cmp(other))
74 }
75}
76
77impl Add for Coord2D {
78 type Output = Coord2D;
79
80 fn add(self, rhs: Self) -> Self::Output {
81 Coord2D::new(self.x + rhs.x, self.y + rhs.y)
82 }
83}
84
85impl Sub for Coord2D {
86 type Output = Coord2D;
87
88 fn sub(self, rhs: Self) -> Self::Output {
89 Coord2D::new(self.x - rhs.x, self.y - rhs.y)
90 }
91}
92
93impl AddAssign for Coord2D {
94 fn add_assign(&mut self, rhs: Self) {
95 self.x += rhs.x;
96 self.y += rhs.y;
97 }
98}
99
100impl SubAssign for Coord2D {
101 fn sub_assign(&mut self, rhs: Self) {
102 self.x -= rhs.x;
103 self.y -= rhs.y;
104 }
105}
106
107impl MulAssign<i32> for Coord2D {
108 fn mul_assign(&mut self, rhs: i32) {
109 self.x *= rhs;
110 self.y *= rhs;
111 }
112}
113
114impl DivAssign<i32> for Coord2D {
115 fn div_assign(&mut self, rhs: i32) {
116 self.x /= rhs;
117 self.y /= rhs;
118 }
119}
120
121impl Mul<i32> for Coord2D {
122 type Output = Coord2D;
123
124 fn mul(self, rhs: i32) -> Self::Output {
125 Coord2D::new(self.x * rhs, self.y * rhs)
126 }
127}
128
129impl Div<i32> for Coord2D {
130 type Output = Coord2D;
131
132 fn div(self, rhs: i32) -> Self::Output {
133 Coord2D::new(self.x / rhs, self.y / rhs)
134 }
135}
136
137impl Neg for Coord2D {
138 type Output = Coord2D;
139
140 fn neg(self) -> Self::Output {
141 Coord2D::new(-self.x, -self.y)
142 }
143}
144
145#[cfg(test)]
146mod tests {
147 use crate::*;
148
149 #[test]
150 fn cmp() {
151 assert_eq!(Coord2D::new(0, 0), Coord2D::new(0, 0));
152 assert!(Coord2D::new(0, 0) < Coord2D::new(0, 1));
153 assert!(Coord2D::new(0, 0) < Coord2D::new(1, 0));
154 assert!(Coord2D::new(1, 0) < Coord2D::new(0, 1));
155 }
156
157 #[test]
158 fn abs_diff() {
159 assert_eq!(
160 Coord2D::new(3, 2).abs_diff(&Coord2D::new(0, 3)),
161 Coord2D::new(3, 1)
162 );
163 }
164
165 #[test]
166 fn dim_dist() {
167 assert_eq!(Coord2D::new(3, 2).shortest_dim_dist(&Coord2D::new(0, 1)), 1);
168 assert_eq!(Coord2D::new(3, 2).largest_dim_dist(&Coord2D::new(0, 1)), 3);
169 }
170
171 #[test]
172 fn manhattan_dist() {
173 assert_eq!(Coord2D::new(0, 0).manhattan_dist(Coord2D::new(0, 2)), 2);
174 assert_eq!(Coord2D::new(0, 0).manhattan_dist(Coord2D::new(2, 0)), 2);
175 assert_eq!(Coord2D::new(0, 0).manhattan_dist(Coord2D::new(0, -2)), 2);
176 assert_eq!(Coord2D::new(0, 0).manhattan_dist(Coord2D::new(-2, 0)), 2);
177 assert_eq!(Coord2D::new(3, 2).manhattan_dist(Coord2D::new(0, 1)), 4);
178 }
179}