Created
December 10, 2023 09:15
-
-
Save SaulDoesCode/374edfc72736faae8c99935196927c5d to your computer and use it in GitHub Desktop.
make a rust version of the game of life that is fractal in the sense of modifying the rules such that when an assemblage of cells get large enough they gain a new fragment of grid inside of themselves which they then lose again if the grouping of similar cells becomes too small (have tiers of this), make the simulation run on its own loop then r…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const GRID_SIZE: usize = 10; // Define a suitable grid size | |
const INNER_GRID_SIZE: usize = 5; // Size of the inner grid | |
const SPAWN_THRESHOLD: usize = 3; // Threshold to spawn inner grid | |
const DESPAWN_THRESHOLD: usize = 1; // Threshold to despawn inner grid | |
#[derive(Clone, Copy)] | |
struct Cell { | |
alive: bool, | |
inner_grid: Option<Box<Grid>>, | |
} | |
impl Cell { | |
fn new(alive: bool) -> Self { | |
Cell { | |
alive, | |
inner_grid: None, | |
} | |
} | |
// Logic to update the cell and its inner grid | |
fn update(&mut self, neighbor_count: usize) { | |
// Update inner grid if it exists | |
if let Some(inner_grid) = &mut self.inner_grid { | |
inner_grid.update(); | |
} | |
// Determine whether to create or remove the inner grid | |
if neighbor_count >= SPAWN_THRESHOLD && self.inner_grid.is_none() { | |
self.inner_grid = Some(Box::new(Grid::new(INNER_GRID_SIZE))); | |
} else if neighbor_count <= DESPAWN_THRESHOLD && self.inner_grid.is_some() { | |
self.inner_grid = None; | |
} | |
} | |
// Render the cell and its inner grid | |
fn render(&self) -> String { | |
if let Some(inner_grid) = &self.inner_grid { | |
format!("[{}]", inner_grid.render()) | |
} else { | |
(if self.alive { '◼' } else { '◻' }).to_string() | |
} | |
} | |
} | |
struct Grid { | |
cells: Vec<Vec<Cell>>, | |
} | |
impl Grid { | |
fn new(size: usize) -> Self { | |
let cells = vec![vec![Cell::new(false); size]; size]; | |
Grid { cells } | |
} | |
fn update(&mut self) { | |
let mut next_state = self.cells.clone(); | |
for y in 0..GRID_SIZE { | |
for x in 0..GRID_SIZE { | |
let alive_neighbors = self.count_alive_neighbors(x, y); | |
let cell = &self.cells[y][x]; | |
let alive = match (cell.alive, alive_neighbors) { | |
(true, 2..=3) => true, | |
(false, 3) => true, | |
_ => false, | |
}; | |
next_state[y][x].alive = alive; | |
next_state[y][x].update(alive_neighbors); | |
} | |
} | |
self.cells = next_state; | |
} | |
fn count_alive_neighbors(&self, x: usize, y: usize) -> usize { | |
let mut count = 0; | |
for i in 0..3 { | |
for j in 0..3 { | |
if i == 1 && j == 1 { | |
continue; // Skip the cell itself | |
} | |
let new_x = x as isize + i - 1; | |
let new_y = y as isize + j - 1; | |
if new_x >= 0 && new_x < GRID_SIZE as isize && new_y >= 0 && new_y < GRID_SIZE as isize { | |
if self.cells[new_y as usize][new_x as usize].alive { | |
count += 1; | |
} | |
} | |
} | |
} | |
count | |
} | |
fn render(&self) -> String { | |
self.cells | |
.iter() | |
.map(|row| row.iter().map(|cell| cell.render()).collect::<String>()) | |
.collect::<Vec<_>>() | |
.join("\n") | |
} | |
} | |
fn main() { | |
let mut grid = Grid::new(GRID_SIZE); | |
// For demonstration, update and render the grid a few times | |
for _ in 0..10 { | |
grid.update(); | |
println!("{}", grid.render()); | |
println!("-----------------------"); | |
std::thread::sleep(std::time::Duration::from_millis(500)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment