1use crate::neighbors::util::{MarginPrimInt, PointPrimInt};
2use crate::{
3 util::grid_util::Shape2D, Board, BoardCallback, BoardCallbackManager, BoardNeighborManager,
4 BoardSpaceManager, BoardStateManager, BoardStrategyManager, EvolutionStrategy, Grid,
5 GridFactory, GridPoint1D, GridPoint2D, GridPoint3D, GridPointND, IndexedDataOwned,
6 NeighborMoore, NeighborMooreDonut, NeighborsGridDonut, NeighborsGridSurround,
7 SharedStrategyManager, SparseStates,
8};
9use num_traits::{CheckedDiv, FromPrimitive, PrimInt, Unsigned};
10use rayon;
11use std::collections::HashMap;
12use std::hash::Hash;
13
14pub struct StandardBoardFactory {}
15
16pub struct StandardBoard<T, CI, I>
17where
18 T: Send + Sync,
19 CI: Send + Sync,
20 I: Iterator<Item = CI>,
21{
22 space_manager: Box<dyn BoardSpaceManager<CI, I, rayon::vec::IntoIter<CI>>>,
23 neighbor_manager: Box<dyn BoardNeighborManager<CI, I>>,
24 state_manager: Box<dyn BoardStateManager<T, CI, rayon::vec::IntoIter<IndexedDataOwned<CI, T>>>>,
25 strategy_manager:
26 Box<dyn BoardStrategyManager<CI, T, std::vec::IntoIter<IndexedDataOwned<CI, T>>>>,
27 callback_manager: BoardCallbackManager<T, CI, rayon::vec::IntoIter<IndexedDataOwned<CI, T>>>,
28}
29
30impl<T, CI, I> Board<T, CI, I> for StandardBoard<T, CI, I>
31where
32 T: 'static + Send + Sync + Clone,
33 CI: 'static + Send + Sync + Clone,
34 I: Iterator<Item = CI>,
35{
36 fn space_manager(&self) -> &dyn BoardSpaceManager<CI, I, rayon::vec::IntoIter<CI>> {
37 &*self.space_manager
38 }
39
40 fn neighbor_manager(&self) -> &dyn BoardNeighborManager<CI, I> {
41 &*self.neighbor_manager
42 }
43
44 fn state_manager(
45 &self,
46 ) -> &dyn BoardStateManager<T, CI, rayon::vec::IntoIter<IndexedDataOwned<CI, T>>> {
47 &*self.state_manager
48 }
49
50 fn state_manager_mut(
51 &mut self,
52 ) -> &mut dyn BoardStateManager<T, CI, rayon::vec::IntoIter<IndexedDataOwned<CI, T>>> {
53 &mut *self.state_manager
54 }
55
56 fn strategy_manager(
57 &self,
58 ) -> &dyn BoardStrategyManager<CI, T, std::vec::IntoIter<IndexedDataOwned<CI, T>>> {
59 &*self.strategy_manager
60 }
61
62 fn callback_manager(
63 &mut self,
64 ) -> &mut BoardCallbackManager<T, CI, rayon::vec::IntoIter<IndexedDataOwned<CI, T>>> {
65 &mut self.callback_manager
66 }
67}
68
69impl<T, CI, I> StandardBoard<T, CI, I>
70where
71 T: 'static + Send + Sync + Clone,
72 CI: 'static + Send + Sync + Clone,
73 I: Iterator<Item = CI>,
74{
75 pub fn new(
76 space_manager: Box<dyn BoardSpaceManager<CI, I, rayon::vec::IntoIter<CI>>>,
77 neighbor_manager: Box<dyn BoardNeighborManager<CI, I>>,
78 state_manager: Box<
79 dyn BoardStateManager<T, CI, rayon::vec::IntoIter<IndexedDataOwned<CI, T>>>,
80 >,
81 strategy_manager: Box<
82 dyn BoardStrategyManager<CI, T, std::vec::IntoIter<IndexedDataOwned<CI, T>>>,
83 >,
84 callbacks: Vec<BoardCallback<T, CI, rayon::vec::IntoIter<IndexedDataOwned<CI, T>>>>,
85 ) -> Self {
86 Self {
87 space_manager,
88 neighbor_manager,
89 state_manager,
90 strategy_manager,
91 callback_manager: BoardCallbackManager::new(callbacks),
92 }
93 }
94}
95
96impl StandardBoardFactory {
97 pub fn new_standard_nd_grid<T, U, S, I>(
98 shape: I,
99 default_state: T,
100 neighbor_margin: S,
101 initial_states: HashMap<GridPointND<U>, T>,
102 strategy: Box<
103 dyn EvolutionStrategy<
104 GridPointND<U>,
105 T,
106 std::vec::IntoIter<IndexedDataOwned<GridPointND<U>, T>>,
107 >,
108 >,
109 callbacks: Vec<
110 BoardCallback<
111 T,
112 GridPointND<U>,
113 rayon::vec::IntoIter<IndexedDataOwned<GridPointND<U>, T>>,
114 >,
115 >,
116 is_donut: bool,
117 ) -> StandardBoard<T, GridPointND<U>, std::vec::IntoIter<GridPointND<U>>>
118 where
119 T: 'static + Send + Sync + Clone + PartialEq,
120 U: 'static + Hash + PrimInt + CheckedDiv + std::convert::TryFrom<S> + PointPrimInt,
121 S: 'static + FromPrimitive + MarginPrimInt,
122 I: Iterator<Item = S>,
123 {
124 let shape: Vec<S> = shape.collect();
125 let space_manager = Grid::<GridPointND<U>>::new(shape.clone().into_iter());
126 let neighbor_manager = if is_donut {
127 Box::new(NeighborsGridDonut::new(neighbor_margin, shape.into_iter()))
128 as Box<dyn BoardNeighborManager<GridPointND<U>, std::vec::IntoIter<GridPointND<U>>>>
129 } else {
130 Box::new(NeighborsGridSurround::new(neighbor_margin))
131 as Box<dyn BoardNeighborManager<GridPointND<U>, std::vec::IntoIter<GridPointND<U>>>>
132 };
133 let state_manager = SparseStates::new(default_state, initial_states);
134 let strategy_manger = SharedStrategyManager::new(strategy);
135 StandardBoard::new(
136 Box::new(space_manager),
137 neighbor_manager,
138 Box::new(state_manager),
139 Box::new(strategy_manger),
140 callbacks,
141 )
142 }
143
144 pub fn new_standard_3d_grid<T, U, S>(
145 shape: (S, S, S),
146 default_state: T,
147 neighbor_margin: S,
148 initial_states: HashMap<GridPoint3D<U>, T>,
149 strategy: Box<
150 dyn EvolutionStrategy<
151 GridPoint3D<U>,
152 T,
153 std::vec::IntoIter<IndexedDataOwned<GridPoint3D<U>, T>>,
154 >,
155 >,
156 callbacks: Vec<
157 BoardCallback<
158 T,
159 GridPoint3D<U>,
160 rayon::vec::IntoIter<IndexedDataOwned<GridPoint3D<U>, T>>,
161 >,
162 >,
163 is_donut: bool,
164 ) -> StandardBoard<T, GridPoint3D<U>, std::vec::IntoIter<GridPoint3D<U>>>
165 where
166 T: 'static + Send + Sync + Clone + PartialEq,
167 U: 'static + Hash + PrimInt + CheckedDiv + std::convert::TryFrom<S> + PointPrimInt,
168 S: 'static + Unsigned + FromPrimitive + MarginPrimInt,
169 {
170 let shape = vec![shape.0, shape.1, shape.2];
171 let space_manager = Grid::<GridPoint3D<U>>::new(shape.clone().into_iter());
172 let neighbor_manager = if is_donut {
173 Box::new(NeighborsGridDonut::new(neighbor_margin, shape.into_iter()))
174 as Box<dyn BoardNeighborManager<GridPoint3D<U>, std::vec::IntoIter<GridPoint3D<U>>>>
175 } else {
176 Box::new(NeighborsGridSurround::new(neighbor_margin))
177 as Box<dyn BoardNeighborManager<GridPoint3D<U>, std::vec::IntoIter<GridPoint3D<U>>>>
178 };
179 let state_manager = SparseStates::new(default_state, initial_states);
180 let strategy_manger = SharedStrategyManager::new(strategy);
181 StandardBoard::new(
182 Box::new(space_manager),
183 neighbor_manager,
184 Box::new(state_manager),
185 Box::new(strategy_manger),
186 callbacks,
187 )
188 }
189
190 pub fn new_standard_2d_grid<T, U, S>(
191 shape: (S, S),
192 default_state: T,
193 neighbor_margin: S,
194 initial_states: HashMap<GridPoint2D<U>, T>,
195 strategy: Box<
196 dyn EvolutionStrategy<
197 GridPoint2D<U>,
198 T,
199 std::vec::IntoIter<IndexedDataOwned<GridPoint2D<U>, T>>,
200 >,
201 >,
202 callbacks: Vec<
203 BoardCallback<
204 T,
205 GridPoint2D<U>,
206 rayon::vec::IntoIter<IndexedDataOwned<GridPoint2D<U>, T>>,
207 >,
208 >,
209 is_donut: bool,
210 ) -> StandardBoard<T, GridPoint2D<U>, std::vec::IntoIter<GridPoint2D<U>>>
211 where
212 T: 'static + Send + Sync + Clone + PartialEq,
213 U: 'static + Hash + PrimInt + CheckedDiv + std::convert::TryFrom<S> + PointPrimInt,
214 S: 'static + Unsigned + FromPrimitive + MarginPrimInt,
215 {
216 let (width, height) = shape;
217 let shape = vec![width, height];
218 let space_manager = Grid::<GridPoint2D<U>>::new(shape.clone().into_iter());
219 let neighbor_manager = if is_donut {
220 if neighbor_margin == S::one() {
221 Box::new(NeighborMooreDonut::new(Shape2D::new(
222 width.to_usize().unwrap(),
223 height.to_usize().unwrap(),
224 )))
225 } else {
226 Box::new(NeighborsGridDonut::new(neighbor_margin, shape.into_iter()))
227 as Box<
228 dyn BoardNeighborManager<
229 GridPoint2D<U>,
230 std::vec::IntoIter<GridPoint2D<U>>,
231 >,
232 >
233 }
234 } else {
235 if neighbor_margin == S::one() {
236 Box::new(NeighborMoore::new())
237 } else {
238 Box::new(NeighborsGridSurround::new(neighbor_margin))
239 as Box<
240 dyn BoardNeighborManager<
241 GridPoint2D<U>,
242 std::vec::IntoIter<GridPoint2D<U>>,
243 >,
244 >
245 }
246 };
247 let state_manager = SparseStates::new(default_state, initial_states);
248 let strategy_manger = SharedStrategyManager::new(strategy);
249 StandardBoard::new(
250 Box::new(space_manager),
251 neighbor_manager,
252 Box::new(state_manager),
253 Box::new(strategy_manger),
254 callbacks,
255 )
256 }
257
258 pub fn new_standard_1d_grid<T, U, S>(
259 shape: S,
260 default_state: T,
261 neighbor_margin: S,
262 initial_states: HashMap<GridPoint1D<U>, T>,
263 strategy: Box<
264 dyn EvolutionStrategy<
265 GridPoint1D<U>,
266 T,
267 std::vec::IntoIter<IndexedDataOwned<GridPoint1D<U>, T>>,
268 >,
269 >,
270 callbacks: Vec<
271 BoardCallback<
272 T,
273 GridPoint1D<U>,
274 rayon::vec::IntoIter<IndexedDataOwned<GridPoint1D<U>, T>>,
275 >,
276 >,
277 is_donut: bool,
278 ) -> StandardBoard<T, GridPoint1D<U>, std::vec::IntoIter<GridPoint1D<U>>>
279 where
280 T: 'static + Send + Sync + Clone + PartialEq,
281 U: 'static + Hash + PrimInt + CheckedDiv + std::convert::TryFrom<S> + PointPrimInt,
282 S: 'static + Unsigned + FromPrimitive + MarginPrimInt,
283 {
284 let shape = vec![shape];
285 let space_manager = Grid::<GridPoint1D<U>>::new(shape.clone().into_iter());
286 let neighbor_manager = if is_donut {
287 Box::new(NeighborsGridDonut::new(neighbor_margin, shape.into_iter()))
288 as Box<dyn BoardNeighborManager<GridPoint1D<U>, std::vec::IntoIter<GridPoint1D<U>>>>
289 } else {
290 Box::new(NeighborsGridSurround::new(neighbor_margin))
291 as Box<dyn BoardNeighborManager<GridPoint1D<U>, std::vec::IntoIter<GridPoint1D<U>>>>
292 };
293 let state_manager = SparseStates::new(default_state, initial_states);
294 let strategy_manger = SharedStrategyManager::new(strategy);
295 StandardBoard::new(
296 Box::new(space_manager),
297 neighbor_manager,
298 Box::new(state_manager),
299 Box::new(strategy_manger),
300 callbacks,
301 )
302 }
303}