mons_rust/models/
location.rs1use 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}