Skip to content

Commit

Permalink
Merge branch 'feature/cellular_automata_cave' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
neoneye committed Dec 12, 2023
2 parents 01e2a7e + 32d2d9c commit fc271ec
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 3 deletions.
2 changes: 1 addition & 1 deletion rust_project/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion rust_project/loda-rust-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "loda-rust-cli"
version = "2023.11.29"
version = "2023.12.12"
authors = ["Simon Strandgaard <neoneye@gmail.com>"]
description = "Command line interface for LODA Rust"
repository = "https://github.com/loda-lang/loda-rust"
Expand Down
113 changes: 112 additions & 1 deletion rust_project/loda-rust-cli/src/arc/cellular_automaton.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,41 @@ pub mod rule {
}
}

} // mod rule
/// Create a cave system
/// https://www.roguebasin.com/index.php/Cellular_Automata_Method_for_Generating_Random_Cave-Like_Levels
/// http://pixelenvy.ca/wa/ca_cave.html
pub struct Cave;

impl super::CARule for Cave {
fn apply(center: u8, neighbors: &[u8; 8]) -> u8 {
let alive_count: usize = neighbors.iter().filter(|&&value| value > 0).count();
if alive_count < 4 {
return 0;
}
if alive_count > 5 {
return 1;
}
center
}
}

/// Create a maze
/// https://conwaylife.com/wiki/OCA:Maze
pub struct Maze;

impl super::CARule for Maze {
fn apply(center: u8, neighbors: &[u8; 8]) -> u8 {
let alive_count: usize = neighbors.iter().filter(|&&value| value > 0).count();
if alive_count == 3 {
return 1;
}
if alive_count < 1 || alive_count > 5 {
return 0;
}
center
}
}
} // mod rule

#[cfg(test)]
mod tests {
Expand Down Expand Up @@ -529,4 +562,82 @@ mod tests {
let expected: Image = Image::try_create(6, 6, expected_pixels).expect("image");
assert_eq!(actual, expected);
}

#[test]
fn test_60000_cave() {
// Act
let pixels: Vec<u8> = vec![
1, 1, 0, 1, 0, 1, 0, 1, 1, 1,
1, 0, 0, 1, 0, 0, 0, 1, 0, 1,
0, 1, 0, 1, 1, 0, 1, 1, 0, 1,
0, 1, 1, 1, 0, 0, 1, 1, 1, 1,
0, 0, 1, 1, 1, 0, 0, 0, 1, 1,
0, 0, 1, 1, 1, 1, 0, 1, 0, 0,
0, 1, 1, 0, 0, 0, 0, 1, 1, 0,
0, 0, 0, 0, 1, 0, 1, 0, 1, 1,
1, 1, 1, 1, 0, 1, 1, 0, 0, 0,
1, 1, 0, 1, 0, 0, 0, 0, 0, 0
];
let input: Image = Image::try_create(10, 10, pixels).expect("image");
let mut ca: CellularAutomaton<_> = CellularAutomaton::<rule::Cave>::with_image(&input, Some(0));

// Act
ca.step_once();
let actual: Image = ca.current;

// Assert
let expected_pixels: Vec<u8> = vec![
0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
0, 0, 1, 1, 0, 0, 1, 1, 1, 0,
0, 0, 1, 1, 0, 0, 0, 1, 1, 1,
0, 0, 1, 1, 1, 0, 0, 0, 1, 0,
0, 0, 1, 1, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 1, 0, 0, 0, 0, 0, 0, 0, 0
];
let expected: Image = Image::try_create(10, 10, expected_pixels).expect("image");
assert_eq!(actual, expected);
}

#[test]
fn test_70000_maze() {
// Act
let pixels: Vec<u8> = vec![
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 1, 0, 1, 1, 0, 0,
0, 0, 1, 1, 0, 0, 1, 1, 0, 0,
0, 0, 1, 1, 1, 0, 0, 0, 0, 0,
0, 0, 1, 1, 1, 1, 0, 1, 0, 0,
0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 1, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
];
let input: Image = Image::try_create(10, 10, pixels).expect("image");
let mut ca: CellularAutomaton<_> = CellularAutomaton::<rule::Maze>::with_image(&input, Some(0));

// Act
ca.step_once();
let actual: Image = ca.current;

// Assert
let expected_pixels: Vec<u8> = vec![
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 0, 0,
0, 0, 1, 0, 0, 0, 1, 1, 0, 0,
0, 1, 1, 0, 1, 0, 0, 1, 0, 0,
0, 1, 1, 0, 1, 1, 1, 1, 0, 0,
0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
];
let expected: Image = Image::try_create(10, 10, expected_pixels).expect("image");
assert_eq!(actual, expected);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
//! https://huggingface.co/datasets/neoneye/gameoflife-v1
//!
//! Future experiments:
//! Use different symbols than only . and *.
//! Use different separator characters. Currently no separator is used.
//! Detect of what symbols are being used, so it writes that: dead=., alive=*, separator=none.
//! Do more prediction steps. Currently only 1 or 2 steps are being used.
//!
//! Game of life: check for oscillators
//! Game of life: recognize shapes.
use super::{CellularAutomaton, cellular_automaton::rule};
Expand Down

0 comments on commit fc271ec

Please sign in to comment.