diff --git a/src/lib.rs b/src/lib.rs index 362b489..b5ef3d5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ mod utils; +use std::fmt; use wasm_bindgen::prelude::*; // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global @@ -17,3 +18,104 @@ extern { pub fn greet(name: &str) { alert(&format!("Hello, {name}!", name=name)) } + +#[wasm_bindgen] +#[repr(u8)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Cell { + Dead = 0, + Alive = 1, +} + +#[wasm_bindgen] +pub struct Universe { + width: u32, + height: u32, + cells: Vec, +} + +impl Universe{ + 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 i = self.get_index(neighbor_row, neighbor_col); + count += self.cells[i] as u8; + } + } + count + } +} + +#[wasm_bindgen] +impl Universe { + pub fn tick(&mut self) { + let mut next = self.cells.clone(); + + for row in 0..self.height{ + for col in 0..self.width{ + let i = self.get_index(row, col); + let cell = self.cells[i]; + let live_neighbor = self.live_neighbor_count(row, col); + let next_cell = match (cell, live_neighbor){ + (Cell::Alive, x) if x < 2 => Cell::Dead, + (Cell::Alive, 2) | (Cell::Alive, 3) => Cell::Alive, + (Cell::Alive, x) if x > 3 => Cell::Dead, + (Cell::Dead, 3) => Cell::Alive, + (other, _) => other, + }; + next[i] = next_cell; + } + } + self.cells = next; + } + + pub fn new() -> Universe { + let width = 64; + let height = 64; + + let cells = (0..width * height) + .map(|i| { + if i % 2 == 0 || i % 7 == 0 { + Cell::Alive + } else { + Cell::Dead + } + }) + .collect(); + + Universe { + width, + height, + cells, + } + } + + pub fn render(&self) -> String { + self.to_string() + } +} + +impl fmt::Display for Universe { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + for line in self.cells.as_slice().chunks(self.width as usize) { + for &cell in line { + let symbole = if cell == Cell::Dead { ' ' } else { 'x' }; + write!(f, "{}", symbole)?; + } + write!(f, "\n")?; + } + + Ok(()) + } +}