Skip to content

Instantly share code, notes, and snippets.

@SaulDoesCode
Created December 10, 2023 09:15
Show Gist options
  • Save SaulDoesCode/374edfc72736faae8c99935196927c5d to your computer and use it in GitHub Desktop.
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…
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