ae_position/
position.rs

1use crate::delta::{Delta, CARDINAL_DELTAS, ORDINAL_DELTAS};
2
3/// Represents the location of something on a 2D grid
4#[derive(Clone, Eq, PartialEq, Hash, Debug)]
5pub struct Position {
6    pub x: i32,
7    pub y: i32,
8}
9
10impl Position {
11    /// Combine with a Delta to get a new position relative to the old position
12    pub fn add_delta(&self, delta: &Delta) -> Position {
13        let new_x = self.x + delta.x as i32;
14        let new_y = self.y + delta.y as i32;
15
16        Position { x: new_x, y: new_y }
17    }
18
19    /// Get a vector of all four positions surrounding a position on the grid
20    pub fn cardinal_positions(&self) -> Vec<Position> {
21        CARDINAL_DELTAS
22            .iter()
23            .map(|delta| self.add_delta(delta))
24            .collect()
25    }
26
27    /// Get a vector of all four ordinal surrounding a position on the grid
28    pub fn ordinal_positions(&self) -> Vec<Position> {
29        ORDINAL_DELTAS
30            .iter()
31            .map(|delta| self.add_delta(delta))
32            .collect()
33    }
34}
35
36#[cfg(test)]
37mod tests {
38    use ae_direction::{Cardinal, Direction, Ordinal};
39
40    use super::*;
41
42    #[test]
43    fn add_delta() {
44        let pos = Position { x: 1, y: 1 };
45        assert_eq!(pos, Position { x: 1, y: 1 });
46
47        let pos = pos.add_delta(&Delta::from(Direction::Cardinal(Cardinal::North)));
48        assert_eq!(pos, Position { x: 1, y: 0 });
49
50        let pos = pos.add_delta(&Delta::from(Direction::Cardinal(Cardinal::East)));
51        assert_eq!(pos, Position { x: 2, y: 0 });
52
53        let pos = pos.add_delta(&Delta::from(Direction::Ordinal(Ordinal::Southwest)));
54        assert_eq!(pos, Position { x: 1, y: 1 });
55    }
56
57    #[test]
58    fn cardinal_positions() {
59        let pos = Position { x: 5, y: 5 };
60
61        let cardinal_positions = pos.cardinal_positions();
62
63        assert!(cardinal_positions.contains(&Position { x: 5, y: 4 }));
64        assert!(cardinal_positions.contains(&Position { x: 5, y: 6 }));
65        assert!(cardinal_positions.contains(&Position { x: 4, y: 5 }));
66        assert!(cardinal_positions.contains(&Position { x: 6, y: 5 }));
67    }
68
69    #[test]
70    fn ordinal_positions() {
71        let pos = Position { x: 5, y: 5 };
72
73        let cardinal_positions = pos.ordinal_positions();
74
75        assert!(cardinal_positions.contains(&Position { x: 6, y: 4 }));
76        assert!(cardinal_positions.contains(&Position { x: 6, y: 6 }));
77        assert!(cardinal_positions.contains(&Position { x: 4, y: 4 }));
78        assert!(cardinal_positions.contains(&Position { x: 4, y: 6 }));
79    }
80}