1use crate::{AutomataRules, Method, Rule};
28use std::hash::Hash;
29use std::ops::{Add, Sub};
30use std::default::Default;
31use std::collections::HashMap;
32
33#[cfg(feature = "rayon")]
34use rayon::prelude::*;
35
36#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
40pub struct Vec2 { x: usize, y: usize }
41
42pub struct Automaton {
44 rules: AutomataRules,
45 bounds: Vec2,
46 cells: HashMap<Vec2, u8>
47}
48
49impl Vec2 {
52 pub fn new(x: usize, y: usize) -> Vec2 { Vec2 { x, y } }
54}
55
56impl Add for Vec2 {
57 type Output = Vec2;
58 fn add(self, rhs: Vec2) -> Vec2 {
59 Vec2 {
60 x: self.x + rhs.x,
61 y: self.y + rhs.y
62 }
63 }
64}
65
66impl Sub for Vec2 {
67 type Output = Vec2;
68 fn sub(self, rhs: Vec2) -> Vec2 {
69 Vec2 {
70 x: self.x - rhs.x,
71 y: self.y - rhs.y
72 }
73 }
74}
75
76impl Default for Vec2 {
77 fn default() -> Vec2 { Vec2 { x: 0, y: 0 } }
78}
79
80impl Automaton {
81 pub fn new(rules: AutomataRules, bounds: Vec2, start_cells: Vec<Vec2>) -> Result<Automaton, u8> {
85 let other_rules = rules.clone();
86 let mut a = Automaton { rules, bounds, cells: HashMap::new() };
87
88 let max_neighbors: u8 = match a.rules.neighbor_method {
89 Method::Moore => 8,
90 Method::VonNeumann => 4
91 };
92
93 match other_rules.to_survive {
94 Rule::Single(s) => if s > max_neighbors { return Err(max_neighbors) },
95 Rule::Range(r) => if r.start > max_neighbors || r.end > max_neighbors { return Err(max_neighbors) },
96 Rule::Many(m) => for s in m {
97 if s > max_neighbors { return Err(max_neighbors) }
98 }
99 }
100
101 match other_rules.to_be_born {
102 Rule::Single(s) => if s > max_neighbors { return Err(max_neighbors) },
103 Rule::Range(r) => if r.start > max_neighbors || r.end > max_neighbors { return Err(max_neighbors) },
104 Rule::Many(m) => for s in m {
105 if s > max_neighbors { return Err(max_neighbors) }
106 }
107 }
108
109 for x in 0..a.bounds.x {
110 for y in 0..a.bounds.y {
111 let v = Vec2::new(x, y);
112
113 if start_cells.contains(&v) {
114 a.cells.insert(v, a.rules.cell_states - 1);
115 } else {
116 a.cells.insert(v, 0);
117 }
118 }
119 }
120
121 Ok(a)
122 }
123
124 pub fn tick(&mut self) {
126 let neighbor_counts = self.cells.iter().map(|(v, _)| {
127 let mut count = 0;
128 let mut poss_neighbors = Vec::new();
129
130 poss_neighbors.push(Vec2::new(v.x, v.y - 1));
132 poss_neighbors.push(Vec2::new(v.x, v.y + 1));
133 poss_neighbors.push(Vec2::new(v.x - 1, v.y));
134 poss_neighbors.push(Vec2::new(v.x + 1, v.y));
135
136 if let Method::Moore = self.rules.neighbor_method {
138 poss_neighbors.push(Vec2::new(v.x - 1, v.y - 1));
139 poss_neighbors.push(Vec2::new(v.x - 1, v.y + 1));
140 poss_neighbors.push(Vec2::new(v.x + 1, v.y - 1));
141 poss_neighbors.push(Vec2::new(v.x + 1, v.y + 1));
142 }
143
144 for poss_neighbor in poss_neighbors {
145 if let Some(s) = self.cells.get(&poss_neighbor) {
146 if s > &0 {
147 count += 1;
148 }
149 }
150 }
151
152 (v.clone(), count)
153 }).collect::<HashMap<Vec2, u8>>();
154
155 self.cells.iter_mut().for_each(|(v, s)| {
156 if s == &0 {
157 match self.rules.to_be_born {
159 Rule::Single(ref goal) => {
160 if let Some(neighbor_count) = neighbor_counts.get(v) {
161 if neighbor_count == goal {
162 *s = self.rules.cell_states - 1;
164 }
165 }
166 },
167 Rule::Range(ref goal_range) => {
168 if let Some(neighbor_count) = neighbor_counts.get(v) {
169 if goal_range.contains(neighbor_count) {
170 *s = self.rules.cell_states - 1;
172 }
173 }
174 },
175 Rule::Many(ref goals) => {
176 if let Some(neighbor_count) = neighbor_counts.get(v) {
177 if goals.contains(neighbor_count) {
178 *s = self.rules.cell_states - 1;
180 }
181 }
182 }
183 }
184 } else if s == &(self.rules.cell_states - 1) {
185 match self.rules.to_survive {
187 Rule::Single(ref goal) => {
188 if let Some(neighbor_count) = neighbor_counts.get(v) {
189 if neighbor_count != goal {
190 *s -= 1;
192 }
193 } else {
194 *s = 0;
196 }
197 },
198 Rule::Range(ref goal_range) => {
199 if let Some(neighbor_count) = neighbor_counts.get(v) {
200 if !goal_range.contains(neighbor_count) {
201 *s -= 1;
203 }
204 } else {
205 *s = 0;
207 }
208 },
209 Rule::Many(ref goals) => {
210 if let Some(neighbor_count) = neighbor_counts.get(v) {
211 if !goals.contains(neighbor_count) {
212 *s -= 1;
214 }
215 } else {
216 *s = 0;
218 }
219 }
220 }
221 } else {
222 *s -= 1;
224 }
225 });
226 }
227
228 #[cfg(feature = "rayon")]
230 pub fn par_tick(&mut self) {
231 let neighbor_counts = self.cells.par_iter().map(|(v, _)| {
232 let mut count = 0;
233 let mut poss_neighbors = Vec::new();
234
235 poss_neighbors.push(Vec2::new(v.x, v.y - 1));
237 poss_neighbors.push(Vec2::new(v.x, v.y + 1));
238 poss_neighbors.push(Vec2::new(v.x - 1, v.y));
239 poss_neighbors.push(Vec2::new(v.x + 1, v.y));
240
241 if let Method::Moore = self.rules.neighbor_method {
243 poss_neighbors.push(Vec2::new(v.x - 1, v.y - 1));
244 poss_neighbors.push(Vec2::new(v.x - 1, v.y + 1));
245 poss_neighbors.push(Vec2::new(v.x + 1, v.y - 1));
246 poss_neighbors.push(Vec2::new(v.x + 1, v.y + 1));
247 }
248
249 for poss_neighbor in poss_neighbors {
250 if let Some(s) = self.cells.get(&poss_neighbor) {
251 if s > &0 {
252 count += 1;
253 }
254 }
255 }
256
257 (v.clone(), count)
258 }).collect::<HashMap<Vec2, u8>>();
259
260 self.cells.par_iter_mut().for_each(|(v, s)| {
261 if s == &0 {
262 match self.rules.to_be_born {
264 Rule::Single(ref goal) => {
265 if let Some(neighbor_count) = neighbor_counts.get(v) {
266 if neighbor_count == goal {
267 *s = self.rules.cell_states - 1;
269 }
270 }
271 },
272 Rule::Range(ref goal_range) => {
273 if let Some(neighbor_count) = neighbor_counts.get(v) {
274 if goal_range.contains(neighbor_count) {
275 *s = self.rules.cell_states - 1;
277 }
278 }
279 },
280 Rule::Many(ref goals) => {
281 if let Some(neighbor_count) = neighbor_counts.get(v) {
282 if goals.contains(neighbor_count) {
283 *s = self.rules.cell_states - 1;
285 }
286 }
287 }
288 }
289 } else if s == &(self.rules.cell_states - 1) {
290 match self.rules.to_survive {
292 Rule::Single(ref goal) => {
293 if let Some(neighbor_count) = neighbor_counts.get(v) {
294 if neighbor_count != goal {
295 *s -= 1;
297 }
298 } else {
299 *s = 0;
301 }
302 },
303 Rule::Range(ref goal_range) => {
304 if let Some(neighbor_count) = neighbor_counts.get(v) {
305 if !goal_range.contains(neighbor_count) {
306 *s -= 1;
308 }
309 } else {
310 *s = 0;
312 }
313 },
314 Rule::Many(ref goals) => {
315 if let Some(neighbor_count) = neighbor_counts.get(v) {
316 if !goals.contains(neighbor_count) {
317 *s -= 1;
319 }
320 } else {
321 *s = 0;
323 }
324 }
325 }
326 } else {
327 *s -= 1;
329 }
330 });
331 }
332
333 pub fn get_cells(&self) -> HashMap<Vec2, u8> {
335 self.cells.clone()
336 }
337}