use crate::BRIGHTNESS; use crate::G; use crate::HEIGHT; use crate::K1; use crate::K2; use crate::Q; use crate::WIDTH; #[derive(PartialEq)] pub struct Cell { pub x: u32, pub y: u32, pub state: u32, } #[derive(PartialEq)] enum StateOp { Types, States, } impl Cell { fn neighbor_count(&self, grid: &Vec>, operation: StateOp) -> (u32, u32) { let mut infected: u32 = 0; let mut states: u32 = 0; let mut sum: u32 = 0; let mut ill: u32 = 0; for j in -1..=1 { for i in -1..=1 { if i == 0 && j == 0 && operation == StateOp::Types { continue; } let nx = (self.x as i32 + i + WIDTH as i32) % WIDTH as i32; let ny = (self.y as i32 + j + HEIGHT as i32) % HEIGHT as i32; let next = &grid[ny as usize][nx as usize]; let state = next.state; if operation == StateOp::Types { if state > 1 && state < Q - 1 { infected += 1; } else if state == Q - 1 { ill += 1; } } else { sum += state; if state == 1 && next != self { states += 1; } } } } if operation == StateOp::Types { return (infected, ill); } else { return (sum, states); } } } pub fn init_grid(option: Option<&Vec>>) -> Vec> { let mut grid: Vec> = Vec::new(); for j in 0..HEIGHT { let mut row: Vec = Vec::new(); for i in 0..WIDTH { let mut value = rand::random::() % Q; if let Some(g) = option { value = g[j as usize][i as usize].state; } row.push(Cell { x: i, y: j, state: value, }); } grid.push(row); } grid } fn map_num(n: usize, s: usize, e: usize, a: usize, b: usize) -> usize { (a as f64 + (n as f64 - s as f64) * (b as f64 - a as f64) / (e as f64 - s as f64)) as usize } pub fn display_grid(grid: &Vec>) { for j in 0..HEIGHT { for i in 0..WIDTH { let x = i as usize; let y = j as usize; let state = grid[y][x].state as usize; let index = map_num(state, 0, Q as usize, 0, BRIGHTNESS.len()); print!("{}", BRIGHTNESS.chars().nth(index).unwrap()); } println!(); } } pub fn update_grid(grid: &mut Vec>) { let mut new_gen = init_grid(Some(grid)); for j in 0..HEIGHT { for i in 0..WIDTH { let x = i as usize; let y = j as usize; let current = &grid[y][x]; let next = &mut new_gen[y][x]; if current.state == Q - 1 { next.state = 0; } else if current.state == 0 { let (inf, ill) = current.neighbor_count(&grid, StateOp::Types); next.state = inf / K1 + ill / K2; } else { let (sum, states) = current.neighbor_count(&grid, StateOp::States); next.state = sum / (9 - states) + G; } if next.state >= Q { next.state = Q - 1; } } } *grid = new_gen; }