auto_worlds 0.1.0

Worlds implementing different rules for cellular automata
Documentation
use auto_cellular::{
    cell::BasicCell,
    common::{linearize, Dimensions, DoubleVec, Index},
    world::BasicWorld,
};

use crate::PROPORTION;

#[derive(Clone, Default, Copy)]
pub enum Cell {
    On,
    Dying,
    #[default]
    Off,
}

impl BasicCell for Cell {
    fn next_state(&self) -> Self {
        match *self {
            Cell::On => Cell::Dying,
            Cell::Dying => Cell::Off,
            Cell::Off => Cell::On,
        }
    }
    fn random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
        let x: f64 = rng.gen();
        if x < PROPORTION {
            Cell::Off
        } else {
            Cell::On
        }
    }
}

pub struct World {
    cells: DoubleVec<Cell>,
    dimensions: Dimensions,
    delta: Vec<(Index, Cell)>,
}

impl BasicWorld<Cell> for World {
    fn changes(&self) -> Vec<(Index, Cell)> {
        let mut delta = vec![];

        for j in 0..self.dimensions().1 {
            for i in 0..self.dimensions().0 {
                let p = (i, j);
                let cell = &self.cells()[j][i];
                let alive = self
                    .moore_neighbors(p)
                    .iter()
                    .filter(|c| matches!(self.cells()[c.1][c.0], Cell::On))
                    .count();

                match cell {
                    Cell::Off if 2 == alive => delta.push((p, cell.next_state())),
                    Cell::Dying => delta.push((p, cell.next_state())),
                    Cell::On => delta.push((p, cell.next_state())),
                    _ => {}
                }
            }
        }

        delta
    }

    fn new(cells: DoubleVec<Cell>, dimensions: Dimensions) -> Self {
        let clone = cells.clone();
        Self {
            cells,
            dimensions,
            delta: linearize(clone),
        }
    }

    fn cells(&self) -> &DoubleVec<Cell> {
        &self.cells
    }

    fn cells_mut(&mut self) -> &mut DoubleVec<Cell> {
        &mut self.cells
    }

    fn delta(&self) -> &Vec<(Index, Cell)> {
        &self.delta
    }

    fn delta_mut(&mut self) -> &mut Vec<(Index, Cell)> {
        &mut self.delta
    }

    fn dimensions(&self) -> Dimensions {
        self.dimensions
    }
}