grid_sim/world/
mod.rs

1pub mod cell;
2use self::cell::{Cell, CellState};
3pub mod builder;
4use self::builder::{InitialState, WorldBuilder};
5pub mod return_types;
6use self::return_types::{StepResult, StepError};
7pub mod rules;
8use self::rules::{DSLRuleset, Rulesets};
9use self::rules::input_cells::InputCells;
10
11#[derive(Clone)]
12pub struct WorldOptions {
13    pub width: usize,
14    pub height: usize,
15    pub init: InitialState,
16    pub input_cells: InputCells,
17    pub rules: Rulesets,
18}
19impl WorldOptions {
20    pub fn new() -> Self {
21        WorldOptions {
22            width: 0,
23            height: 0,
24            init: InitialState::Random,
25            input_cells: InputCells::Neighbors,
26            rules: Rulesets::Conway,
27        }
28    }
29}
30
31pub struct World {
32    time: u64,
33    width: usize,
34    height: usize,
35    grid: Vec<Cell>,
36    input_cells: InputCells,
37    rules: DSLRuleset,
38}
39impl World {
40    pub fn new(options: WorldOptions) -> Self {
41        let (w, h) = (options.width, options.height);
42
43        let mut grid = Vec::with_capacity(w as usize * h as usize);
44
45        let wb = WorldBuilder::new(w, h, options.init);
46        //FIXME: worldbuilder should NOT take init as parameter,
47        //init should be passed in to build() after world builder
48        //is created.
49        
50        //build world
51        wb.build(&mut grid);
52
53        let rules = options.rules.get_data();
54
55        World {
56            time: 0,
57            width: w, height: h,
58            grid: grid,
59            input_cells: options.input_cells,
60            rules: rules,
61        }
62    }
63
64    fn set_cell_state(&mut self, index: usize, new: CellState) {
65        if let Some(cell) = self.grid.get_mut(index) {
66            cell.set_state(new)
67        }
68    }
69
70    fn get_cell_state(&self, xy: (u64, u64)) -> CellState {
71        let index = xy.0 + self.width as u64 * xy.1;
72
73        match self.grid.get(index as usize) {
74            Some(cell) => cell.get_state().clone(),
75            None => CellState::OOB,
76        }
77    }
78
79    fn get_neighbor_states(&self, xy: (u64, u64)) -> Vec<(CellState, usize)> {
80        let (x, y) = xy;
81        //get neighbor states
82        let neighbor_states = self.input_cells.get_data().iter().map(|rule| {
83            let x = x as i64 + rule.0 as i64;
84            let y = y as i64 + rule.1 as i64;
85            if (x < 0) | (y < 0) | (x > self.width as i64) | (y > self.height as i64) {
86                CellState::OOB
87            } else {
88                let coords = (x as u64, y as u64);
89                self.get_cell_state(coords)
90            }
91        }).collect::<Vec<_>>();
92
93        //format neighbor states for input to ruleset (Amount, ResultState)
94        let mut output_vector = Vec::new();
95        use self::cell::CellState::{Dead, Live};
96        for state in vec![Dead, Live].iter() {
97            let num = neighbor_states.iter().filter(|x| x == &state).count();
98            output_vector.push( (state.clone(), num) );
99        }
100
101        output_vector
102    }
103
104    //map through all cells, applying rules and returning computed next grid state
105    fn process_cells(&mut self) -> Vec<CellState> {
106
107        let mut neighbor_states = Vec::new();
108        for cell in self.grid.iter() {
109            neighbor_states.push(self.get_neighbor_states(cell.get_xy()));
110        }
111        let mut processed = Vec::new();
112        for (index, cell) in self.grid.iter().enumerate() {
113            if let Some(nb_states) = neighbor_states.get(index) {
114                processed.push(
115                    self.rules.compute(cell.get_state().clone(), nb_states.clone())
116                );
117            }
118        }
119
120        processed
121    }
122
123    //appy changes produced by process_cells() and return statistics
124    fn apply_state_changes(&mut self, new_state: Vec<CellState>) -> StepResult {
125        for (index, new) in new_state.into_iter().enumerate() {
126            self.set_cell_state(index, new);
127        }
128        StepResult {
129            steps: 10,
130            updated_cells: 100,
131        }
132    }
133
134    pub fn step(&mut self) -> Result<StepResult, StepError> {
135        self.time = self.time + 1;
136        //get list of state changes according to rules
137        let changes = self.process_cells();
138
139        //apply state changes to grid and return step statistics
140        let sr = self.apply_state_changes(changes);
141
142        Ok(sr)
143    }
144
145    pub fn return_grid(&self) -> &Vec<Cell> {
146        &self.grid
147    }
148
149    pub fn return_width(&self) -> usize {
150        self.width as usize
151    }
152}