grid_sim/world/builder/
mod.rs

1pub mod designs;
2use self::designs::Design;
3use world::{Cell, CellState};
4extern crate rand;
5use std::str::FromStr;
6use rand::Rng;
7
8//TODO: Generalize procedural starting grid states
9//TODO: Center prefabs
10#[derive(Clone)]
11pub enum InitialState {
12    Blank(CellState),
13    Random,
14    Ordered(Vec<(u64, u64)>),
15    Library(Design),
16    Lambda,
17}
18impl FromStr for InitialState {
19    type Err = ();
20    fn from_str(s: &str) -> Result<InitialState, ()> {
21        match s {
22            //procedural
23            "Random" => Ok(InitialState::Random),
24            "Blank" => Ok(InitialState::Blank(CellState::Dead)),
25            "Filled" => Ok(InitialState::Blank(CellState::Live)),
26            //prefab
27            "Eureka" => Ok(InitialState::Library(Design::Eureka)),
28            _ => Err(()),
29        }
30    }
31}
32pub struct WorldBuilder {
33    width: usize,
34    height: usize,
35    init: InitialState,
36}
37impl WorldBuilder {
38    pub fn new(width: usize, height: usize, init: InitialState) -> Self {
39        WorldBuilder { 
40            width: width,
41            height: height,
42            init: init,
43        }
44    }
45    fn gen_index(&self, x: u64, y: u64) -> usize {
46        x as usize + y as usize * self.width as usize
47    }
48    fn add_cells(&self, grid_ref: &mut Vec<Cell>, w: usize, h: usize) {
49        //fill grid by x and y with new cells
50        for y in 0..h {
51            for x in 0..w {
52                let cell = Cell::new((x as u64,y as u64), CellState::Uninitialized);
53                grid_ref.push(cell);
54            }
55        }
56    }
57    pub fn build(&self, grid_ref: &mut Vec<Cell>) {
58        self.add_cells(grid_ref, self.width, self.height);
59
60        //match InitialState and make it so
61        match self.init {
62            InitialState::Blank(ref state) => WorldBuilder::populate_all(grid_ref, state.clone()),
63            InitialState::Random => WorldBuilder::populate_random(grid_ref),
64            InitialState::Ordered(ref coords) => {
65                self.populate_ordered(grid_ref, coords);
66            },
67            InitialState::Library(ref design) => {
68                self.populate_library(grid_ref, design);
69            },
70            //InitialState::Lambda(f) => WorldBuilder::populate_lambda(grid_ref, f),
71            InitialState::Lambda => (),
72        }
73    }
74    fn populate_all(grid_ref: &mut Vec<Cell>, state: CellState) {
75        for cell in grid_ref.iter_mut() {
76            cell.set_state(state.clone());
77        }
78    }
79    fn populate_random(grid_ref: &mut Vec<Cell>) {
80        let mut rng = rand::thread_rng();
81        for cell in grid_ref.iter_mut() {
82            match rng.gen() {
83                true => cell.set_state(CellState::Live),
84                false => cell.set_state(CellState::Dead),
85            };
86        }
87    }
88    fn populate_ordered(&self, grid_ref: &mut Vec<Cell>, coords: &Vec<(u64, u64)>) {
89        WorldBuilder::populate_all(grid_ref, CellState::Dead);
90        for coord in coords.iter() {
91            match grid_ref.get_mut(self.gen_index(coord.0, coord.1)) {
92                Some(cell) => {
93                    cell.set_state(CellState::Live);
94                },
95                None => panic!("invalid init coord"),
96            }
97        }
98    }
99    fn populate_library(&self, grid_ref: &mut Vec<Cell>, design: &Design) {
100        let data = design.get_data();
101        self.populate_ordered(grid_ref, &data);
102    }
103    //fn populate_lambda(grid_ref: &mut Vec<Cell>, mut f: Box<FnMut(&Cell)->CellState>) {
104    //    for cell in grid_ref.iter_mut() {
105    //        let new_state = f(cell);
106    //        cell.set_state(new_state);
107    //    }
108    //}
109}