gol_core/board/
standard.rs

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}