Skip to content

Instantly share code, notes, and snippets.

@tropicbliss
Last active February 8, 2022 03:38
Show Gist options
  • Save tropicbliss/8d6ad9552560b276ad93ae69644e83ff to your computer and use it in GitHub Desktop.
Save tropicbliss/8d6ad9552560b276ad93ae69644e83ff to your computer and use it in GitHub Desktop.
Double buffered game of life impl
use fixedbitset::FixedBitSet;
pub struct Universe {
width: usize,
height: usize,
active_cell: FixedBitSet,
passive_cell: FixedBitSet,
cell_delta: Vec<usize>,
}
impl Universe {
pub fn new(width: usize, height: usize) -> Self {
let rng = fastrand::Rng::new();
let size = width * height;
let mut active_cell = FixedBitSet::with_capacity(size);
for idx in 0..size {
active_cell.set(idx, rng.bool())
}
let passive_cell = FixedBitSet::with_capacity(size);
Self {
width,
height,
active_cell,
passive_cell,
cell_delta: Vec::new(),
}
}
pub fn tick(&mut self) {
self.cell_delta.clear();
let mut idx = 0;
for row in 0..self.height {
for col in 0..self.width {
let cell = self.active_cell[idx];
let live_neighbours = self.live_neighbour_count(row, col);
let new = match (cell, live_neighbours) {
(true, x) if x < 2 => false,
(true, 2 | 3) => true,
(true, x) if x > 3 => false,
(false, 3) => true,
(otherwise, _) => otherwise,
};
self.passive_cell.set(idx, new);
if cell != new {
self.cell_delta.push(idx);
}
idx += 1;
}
}
std::mem::swap(&mut self.active_cell, &mut self.passive_cell);
}
pub fn get_cell_delta(&self) -> &Vec<usize> {
&self.cell_delta
}
pub fn toggle_cell(&mut self, idx: usize) {
self.active_cell.toggle(idx);
}
fn get_index(&self, row: usize, column: usize) -> usize {
row * self.width + column
}
fn live_neighbour_count(&self, row: usize, column: usize) -> usize {
let mut count = 0;
let north = if row == 0 { self.height - 1 } else { row - 1 };
let south = if row == self.height - 1 { 0 } else { row + 1 };
let west = if column == 0 {
self.width - 1
} else {
column - 1
};
let east = if column == self.width - 1 {
0
} else {
column + 1
};
let nw = self.get_index(north, west);
count += self.active_cell[nw] as usize;
let n = self.get_index(north, column);
count += self.active_cell[n] as usize;
let ne = self.get_index(north, east);
count += self.active_cell[ne] as usize;
let w = self.get_index(row, west);
count += self.active_cell[w] as usize;
let e = self.get_index(row, east);
count += self.active_cell[e] as usize;
let sw = self.get_index(south, west);
count += self.active_cell[sw] as usize;
let s = self.get_index(south, column);
count += self.active_cell[s] as usize;
let se = self.get_index(south, east);
count += self.active_cell[se] as usize;
count
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment