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