grid_sim/world/rules/
mod.rs

1pub mod input_cells;
2use self::input_cells::InputCells;
3use world::CellState;
4use std::str::FromStr;
5use std::collections::HashMap;
6
7type RulesetType = HashMap<(CellState, CellState), Vec<(usize, CellState)>>;
8
9#[derive(Clone)]
10pub enum Rulesets {
11    Custom,
12    Conway,
13    ConwayEasy,
14    ConwayVeryEasy,
15    Decay,
16}
17#[derive(Clone)]
18pub struct Ruleset {
19    pub input_cells: InputCells,
20    pub rules: Rulesets,
21}
22impl FromStr for Rulesets {
23    type Err = ();
24    fn from_str(s: &str) -> Result<Rulesets, ()> {
25        match s {
26            "Conway" => Ok(Rulesets::Conway),
27            "ConwayEasy" => Ok(Rulesets::ConwayEasy),
28            "ConwayVeryEasy" => Ok(Rulesets::ConwayVeryEasy),
29            "Decay" => Ok(Rulesets::Decay),
30            _ => Err(()),
31        }
32    }
33}
34impl Rulesets {
35    pub fn get_data(&self) -> DSLRuleset {
36        use self::CellState::{Dead, Live};
37        match *self {
38            //Custom will use yet-formalized DSL that will be used for config files
39            Rulesets::Custom => {
40                let mut ruleset = DSLRuleset::new();
41                ruleset.add_cases(Dead, Live, vec![(3, Live)]);
42                ruleset
43            },
44            Rulesets::Conway => {
45                let mut ruleset = DSLRuleset::new();
46                ruleset.add_cases(Dead, Live, vec![(3, Live)]);
47                ruleset.add_cases(Live, Live, vec![
48                    (0, Dead), (1, Dead), (4, Dead), (5, Dead),
49                    (6, Dead), (7, Dead), (8, Dead), (9, Dead),
50                ]);
51                ruleset
52            },
53            Rulesets::ConwayEasy => {
54                let mut ruleset = DSLRuleset::new();
55                ruleset.add_cases(Dead, Live, vec![(3, Live)]);
56                ruleset.add_cases(Live, Live, vec![
57                    (0, Dead), (1, Dead), (2, Live), (3, Live), 
58                    (4, Dead), (5, Dead), (6, Dead), (7, Live), (8, Dead), 
59                ]);
60                ruleset
61            },
62            Rulesets::ConwayVeryEasy => {
63                let mut ruleset = DSLRuleset::new();
64                ruleset.add_cases(Dead, Live, vec![
65                    (3, Live), (4, Live),
66                ]);
67                ruleset.add_cases(Live, Live, vec![
68                    (0, Dead), (1, Dead), (4, Dead), (5, Dead),
69                    (6, Dead), (7, Live), (8, Dead), (9, Dead),
70                ]);
71                ruleset
72            },
73            Rulesets::Decay => {
74                let mut ruleset = DSLRuleset::new();
75                ruleset.add_cases(Dead, Live, vec![(3, Live), (4, Live)]);
76                ruleset.add_cases(Live, Live, vec![
77                    (0, Dead), (1, Live), (2, Dead), (3, Dead), 
78                    (4, Live), (5, Dead), (6, Dead), (7, Dead), (8, Dead), 
79                ]);
80                ruleset
81            },
82        }
83    }
84}
85pub struct DSLRuleset {
86    data: RulesetType,
87}
88impl DSLRuleset {
89    pub fn new() -> Self {
90        DSLRuleset {
91            data: HashMap::new(),
92        }
93    }
94    pub fn add_cases(&mut self,
95                 identity_state: CellState,
96                 for_state: CellState,
97                 cases: Vec<(usize, CellState)>
98        ) {
99        let key = (identity_state, for_state);
100
101        self.data.insert(key, cases);
102    }
103    pub fn compute(&mut self,
104               identity_state: CellState,
105               input_states: Vec<(CellState, usize)>
106        ) -> CellState {
107
108        let mut return_state = identity_state.clone();
109
110        let mut key = (identity_state, CellState::Uninitialized);
111        //loop through list of amounts of each state from neighbor states
112        for &(ref state, ref amt) in input_states.iter() {
113            //reuse identity_state
114            key.1 = state.clone();
115
116            match self.data.get(&key) {
117                Some(vec) => {
118                    for &(ref trigger_amt, ref result_state) in vec {
119                        if trigger_amt == amt {
120                            return_state = result_state.clone();
121                        }
122                    }
123                },
124                None => (),
125            }
126        }
127
128        return_state
129    }
130}