mons_rust/models/
location.rs

1use crate::*;
2
3#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
4pub struct Location {
5    pub i: i32,
6    pub j: i32,
7}
8
9impl Location {
10    pub fn new(i: i32, j: i32) -> Self {
11        Self { i, j }
12    }
13
14    pub fn valid_range() -> std::ops::Range<i32> {
15        0..Config::BOARD_SIZE
16    }
17
18    pub fn nearby_locations(&self) -> Vec<Location> {
19        self.nearby_locations_with_distance(1)
20    }
21
22    pub fn reachable_by_bomb(&self) -> Vec<Location> {
23        self.nearby_locations_with_distance(3)
24    }
25
26    pub fn reachable_by_mystic_action(&self) -> Vec<Location> {
27        let deltas = [(-2, -2), (2, 2), (-2, 2), (2, -2)];
28        deltas.iter().filter_map(|&(dx, dy)| {
29            let (new_i, new_j) = (self.i + dx, self.j + dy);
30            if Self::valid_range().contains(&new_i) && Self::valid_range().contains(&new_j) {
31                Some(Location::new(new_i, new_j))
32            } else {
33                None
34            }
35        }).collect()
36    }
37
38    pub fn reachable_by_demon_action(&self) -> Vec<Location> {
39        let deltas = [(-2, 0), (2, 0), (0, 2), (0, -2)];
40        deltas.iter().filter_map(|&(dx, dy)| {
41            let (new_i, new_j) = (self.i + dx, self.j + dy);
42            if Self::valid_range().contains(&new_i) && Self::valid_range().contains(&new_j) {
43                Some(Location::new(new_i, new_j))
44            } else {
45                None
46            }
47        }).collect()
48    }
49
50    pub fn reachable_by_spirit_action(&self) -> Vec<Location> {
51        let mut locations = Vec::new();
52        for x in -2i32..=2 {
53            for y in -2i32..=2 {
54                if x.abs().max(y.abs()) == 2 && Self::valid_range().contains(&(self.i + x)) && Self::valid_range().contains(&(self.j + y)) {
55                    locations.push(Location::new(self.i + x, self.j + y));
56                }
57            }
58        }
59        locations
60    }
61
62    pub fn location_between(&self, another: &Location) -> Location {
63        Location::new((self.i + another.i) / 2, (self.j + another.j) / 2)
64    }
65
66    pub fn distance(&self, to: &Location) -> i32 {
67        ((to.i - self.i).abs()).max((to.j - self.j).abs())
68    }
69
70    fn nearby_locations_with_distance(&self, distance: i32) -> Vec<Location> {
71        let mut locations = Vec::new();
72        for x in (self.i - distance)..=(self.i + distance) {
73            for y in (self.j - distance)..=(self.j + distance) {
74                if Self::valid_range().contains(&x) && Self::valid_range().contains(&y) && (x != self.i || y != self.j) {
75                    locations.push(Location::new(x, y));
76                }
77            }
78        }
79        locations
80    }
81}