hive/engine/
grid.rs

1use std::{
2  collections::HashMap,
3  fmt::{Display, Formatter},
4};
5
6use crate::engine::grid::{
7  coordinate::hex::Hex,
8  piece::{Piece, PieceColor},
9};
10use serde::{Deserialize, Serialize};
11
12pub mod coordinate;
13pub mod piece;
14
15#[cfg(test)]
16#[path = "../tests/grid_tests.rs"]
17mod grid_tests;
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct Grid {
21  pub grid: HashMap<Hex, Vec<Piece>>,
22}
23
24impl Grid {
25  pub fn new() -> Grid {
26    let grid: HashMap<Hex, Vec<Piece>> = HashMap::new();
27
28    Grid { grid }
29  }
30
31  pub fn place_piece_to_hex(&mut self, piece: Piece, hex: Hex) {
32    let mut pieces: Vec<Piece> = match self.grid.get(&hex) {
33      None => Vec::new(),
34      Some(v) => v.to_vec(),
35    };
36    pieces.push(piece);
37    self.grid.insert(hex, pieces);
38  }
39
40  pub fn remove_top_piece_from_hex(&mut self, hex: Hex) -> Option<Piece> {
41    let mut pieces: Vec<Piece> = match self.grid.get(&hex) {
42      None => Vec::new(),
43      Some(v) => v.to_vec(),
44    };
45    let piece = pieces.pop();
46    self.grid.insert(hex, pieces);
47
48    piece
49  }
50
51  pub fn move_piece_from_to(&mut self, from: Hex, to: Hex) {
52    let removed_piece = self.remove_top_piece_from_hex(from);
53    if let Some(p) = removed_piece {
54      self.place_piece_to_hex(p, to)
55    };
56  }
57
58  pub fn find_top_piece(&self, hex: &Hex) -> Option<&Piece> {
59    if self.is_hex_occupied(hex) {
60      match self.grid.get(hex) {
61        Some(v) => v.last(),
62        None => None,
63      }
64    } else {
65      None
66    }
67  }
68
69  pub fn is_hex_surrounded(&self, hex: &Hex) -> bool {
70    let neighbors = hex.neighbors();
71
72    let mut is_surrended = true;
73
74    for neighbor in &neighbors {
75      let pieces = self.grid.get(neighbor);
76      is_surrended = is_surrended
77        && match pieces {
78          Some(p) => !p.is_empty(),
79          None => false,
80        }
81    }
82
83    is_surrended
84  }
85
86  pub fn is_hex_neighbor_of(&self, hex: &Hex, of: &Hex) -> bool {
87    let mut is_neighbor = false;
88
89    for neighbor in hex.neighbors() {
90      is_neighbor = is_neighbor || neighbor == *of;
91    }
92
93    is_neighbor
94  }
95
96  pub fn is_hex_occupied(&self, hex: &Hex) -> bool {
97    let pieces = self.grid.get(hex);
98
99    match pieces {
100      Some(p) => !p.is_empty(),
101      None => false,
102    }
103  }
104
105  pub fn is_hex_alone(&self, hex: &Hex) -> bool {
106    let neighbors = hex.neighbors();
107
108    let mut is_alone = true;
109
110    for neighbor in neighbors {
111      is_alone = is_alone && !self.is_hex_occupied(&neighbor);
112    }
113
114    is_alone
115  }
116
117  pub fn is_hex_of_color(&self, hex: &Hex, piece_color: &PieceColor) -> bool {
118    let piece = self.find_top_piece(hex);
119
120    match piece {
121      Some(p) => p.p_color == *piece_color,
122      None => false,
123    }
124  }
125
126  pub fn is_hex_neighbors_only_piece_color(&self, hex: &Hex, piece_color: &PieceColor) -> bool {
127    let mut is_hex_surrounded_by_piece_color = true;
128
129    if !self.is_hex_alone(hex) {
130      for neighbor in hex.neighbors() {
131        if self.is_hex_occupied(&neighbor) && !self.is_hex_of_color(&neighbor, piece_color) {
132          is_hex_surrounded_by_piece_color = false;
133        }
134      }
135    } else {
136      is_hex_surrounded_by_piece_color = false;
137    }
138
139    is_hex_surrounded_by_piece_color
140  }
141
142  pub fn number_of_pieces(&self) -> usize {
143    let mut count = 0;
144    for vec in self.grid.values() {
145      count += vec.len()
146    }
147
148    count
149  }
150}
151
152impl Default for Grid {
153  fn default() -> Self {
154    Self::new()
155  }
156}
157
158impl Display for Grid {
159  fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
160    let mut initialized = false;
161    let mut min_q = 0;
162    let mut max_q = 0;
163    let mut min_r = 0;
164    let mut max_r = 0;
165
166    for key in self.grid.keys() {
167      if !initialized {
168        min_q = key.q;
169        max_q = key.q;
170        min_r = key.r;
171        max_r = key.r;
172        initialized = true;
173      } else {
174        if min_q > key.q {
175          min_q = key.q;
176        } else if max_q < key.q {
177          max_q = key.q;
178        }
179
180        if min_r > key.r {
181          min_r = key.r;
182        } else if max_r < key.r {
183          max_r = key.r;
184        }
185      }
186    }
187
188    let mut count_r = -1;
189
190    write!(f, "GRID START")?;
191    for r in min_r..=max_r {
192      for m in 1..=2 {
193        writeln!(f)?;
194
195        if m % 2 == 1 {
196          count_r += 1;
197        }
198
199        for _i in 0..count_r {
200          write!(f, "    ")?;
201        }
202
203        for q in min_q..=max_q {
204          let hex = Hex::new(q, r);
205
206          let occupied = self.is_hex_occupied(&hex);
207
208          if occupied {
209            if m % 2 == 0 {
210              write!(f, "{}", hex)?;
211            } else {
212              let piece = self.find_top_piece(&hex);
213              match piece {
214                Some(p) => write!(f, " {} ", p)?,
215                None => write!(f, " NA ")?,
216              }
217            }
218          } else if m % 2 == 1 {
219            write!(f, "   __   ")?;
220          } else {
221            write!(f, "{}", hex)?;
222          }
223        }
224      }
225    }
226
227    write!(f, "\nGRID END")
228  }
229}