mod utils; use std::fmt; use wasm_bindgen::prelude::*; extern crate js_sys; // When the `wee_alloc` feature is enabled, use `wee_alloc` as the global // allocator. #[cfg(feature = "wee_alloc")] #[global_allocator] static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; #[wasm_bindgen] extern { fn alert(s: &str); } #[wasm_bindgen] 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 new_random() -> Universe { let width = 64; let height = 64; let cells = (0..width * height) .map(|_i| { if js_sys::Math::random() < 0.5 { Cell::Alive } else { Cell::Dead } }) .collect(); Universe { width, height, cells, } } pub fn render(&self) -> String { self.to_string() } pub fn width(&self) -> u32 { self.width } pub fn height(&self) -> u32 { self.height } pub fn cells(&self) -> *const Cell { self.cells.as_ptr() } } 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 { '◼' }; write!(f, "{}", symbole)?; } write!(f, "\n")?; } Ok(()) } }