-
Notifications
You must be signed in to change notification settings - Fork 0
/
lib.rs
101 lines (84 loc) · 2.78 KB
/
lib.rs
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
use wasm_bindgen::prelude::*;
use rand::Rng;
#[wasm_bindgen]
extern {
fn alert(s: &str);
}
#[wasm_bindgen]
pub struct Universe {
width: u32,
height: u32,
cells: Vec<u8>,
}
#[wasm_bindgen]
impl Universe {
pub fn new(width: u32, height: u32) -> Universe {
let mut rng = rand::thread_rng();
let cells = (0..width * height)
.map(|_| if rng.gen_bool(0.5) { 1 } else { 0 })
.collect();
Universe { width, height, cells }
}
pub fn tick(&mut self, birth_threshold: u8, survival_threshold_min: u8, survival_threshold_max: u8) {
let mut next = vec![0; self.width as usize * self.height as usize];
for row in 0..self.height {
for col in 0..self.width {
let idx = self.get_index(row, col);
let cell = self.cells[idx];
let live_neighbors = self.live_neighbor_count(row, col);
next[idx] = match (cell, live_neighbors) {
(1, x) if x < survival_threshold_min => 0,
(1, x) if x > survival_threshold_max => 0,
(0, x) if x == birth_threshold => 1,
(otherwise, _) => otherwise,
};
}
}
std::mem::swap(&mut self.cells, &mut next);
}
pub fn width(&self) -> u32 {
self.width
}
pub fn height(&self) -> u32 {
self.height
}
pub fn cells(&self) -> *const u8 {
self.cells.as_ptr()
}
fn get_index(&self, row: u32, column: u32) -> usize {
(row * self.width + column) as usize
}
fn live_neighbor_count(&self, row: u32, column: u32) -> u8 {
let mut count = 0;
for delta_row in [self.height - 1, 0, 1].iter().cloned() {
for delta_col in [self.width - 1, 0, 1].iter().cloned() {
if delta_row == 0 && delta_col == 0 {
continue;
}
let neighbor_row = (row + delta_row) % self.height;
let neighbor_col = (column + delta_col) % self.width;
let idx = self.get_index(neighbor_row, neighbor_col);
count += self.cells[idx] as u8;
}
}
count
}
pub fn toggle_cell(&mut self, row: u32, column: u32) {
let idx = self.get_index(row, column);
self.cells[idx] = !self.cells[idx];
}
}
impl std::fmt::Display for Universe {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
for line in self.cells.as_slice().chunks(self.width as usize) {
for &cell in line {
let symbol = if cell == 1 { '◼' } else { '◻' };
write!(f, "{}", symbol)?;
}
write!(f, "\n")?;
}
Ok(())
}
}
mod breakout;
pub use breakout::Breakout;