simple conway thing
-rw-r--r--.gitignore2
-rw-r--r--Cargo.toml17
-rw-r--r--LICENSE21
-rw-r--r--README.md10
-rw-r--r--src/main.rs133
-rw-r--r--src/seed.pngbin0 -> 124 bytes
6 files changed, 183 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..96ef6c0
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/target
+Cargo.lock
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..166bd4f
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,17 @@
+[package]
+name = "cgol"
+version = "0.1.0"
+edition = "2021"
+author = ["bendn <[email protected]>"]
+description = "simple finite cgol, takes seed from a image, outputs to the terminal"
+repository = "https://github.com/bend-n/cgol.git"
+license = "MIT"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+image = { version = "0.24.7", features = ["png"], default-features = false }
+
+[profile.release]
+debug = true
+lto = "thin"
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..1fafc15
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 bendn
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..2131b34
--- /dev/null
+++ b/README.md
@@ -0,0 +1,10 @@
+# conways game of life implementation
+
+- finite board
+- terminal output
+- image input
+- simple impl
+
+## demonstration
+
+https://github.com/bend-n/cgol/assets/70787919/d8848785-d4dc-4bca-ad82-c451a62e7520 \ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..ae6773e
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,133 @@
+use std::{
+ io::{self, Write},
+ time::Duration,
+};
+
+const WIDTH: usize = 50;
+const HEIGHT: usize = 20;
+pub struct Grid([[bool; HEIGHT + 2]; WIDTH + 2]);
+
+impl Default for Grid {
+ fn default() -> Self {
+ Self([[false; HEIGHT + 2]; WIDTH + 2])
+ }
+}
+
+impl Grid {
+ #[inline]
+ fn neighbors(&self, x: usize, y: usize) -> u8 {
+ let x = x + 1;
+ let y = y + 1;
+ macro_rules! n {
+ ($(($sx: tt $x: expr, $sy: tt $y: expr))+) => {{
+ let mut n = 0;
+ $(if self.0[n!(@ $sx $x + x)][n!(@ $sy $y + y)] {
+ n += 1;
+ })+
+ n
+ }};
+ (@ -$n:literal + $v: ident) => { $v - $n };
+ (@ +$n:literal + $v: ident) => { $v + $n };
+ }
+ n![(-1, -1)(+0, -1)(+1, -1)(-1, +0)(+1, +0)(-1, +1)(+0, +1)(+1, +1)]
+ }
+
+ #[inline]
+ fn kill(&mut self, x: usize, y: usize) {
+ self.set(x, y, false);
+ }
+
+ #[inline]
+ fn spawn(&mut self, x: usize, y: usize) {
+ self.set(x, y, true);
+ }
+
+ #[inline]
+ fn set(&mut self, x: usize, y: usize, to: bool) {
+ self.0[x + 1][y + 1] = to
+ }
+
+ #[inline]
+ fn cell(&self, x: usize, y: usize) -> bool {
+ self.0[x + 1][y + 1]
+ }
+
+ fn iterate(&mut self) {
+ let mut neighbors = [[0u8; HEIGHT + 2]; WIDTH + 2];
+
+ for x in 0..WIDTH {
+ for y in 0..HEIGHT {
+ neighbors[x + 1][y + 1] = self.neighbors(x, y);
+ }
+ }
+
+ for x in 0..WIDTH {
+ for y in 0..HEIGHT {
+ let cell = self.cell(x, y);
+ let n = neighbors[x + 1][y + 1];
+ match n {
+ 2 | 3 if cell => continue,
+ 3 if !cell => self.spawn(x, y),
+ _ => self.kill(x, y),
+ }
+ }
+ }
+ }
+
+ fn dead(&mut self) -> bool {
+ for row in self.0 {
+ for col in row {
+ if col {
+ return false;
+ };
+ }
+ }
+ true
+ }
+
+ fn print(&self, mut w: impl Write) -> io::Result<()> {
+ let tab = ["░░", "██"];
+ for y in 0..HEIGHT {
+ for x in 0..WIDTH {
+ w.write_all(tab[self.cell(x, y) as usize].as_bytes())?;
+ }
+ writeln!(w)?;
+ }
+ Ok(())
+ }
+}
+
+fn main() {
+ let mut grid = Grid::default();
+ let img = image::open("src/seed.png").unwrap().to_luma8();
+ assert!(img.width() == WIDTH as u32);
+ assert!(img.height() == HEIGHT as u32);
+ for x in 0..WIDTH {
+ for y in 0..HEIGHT {
+ let on = img.get_pixel(x as u32, y as u32)[0] <= 128;
+ grid.set(x, y, on);
+ }
+ }
+
+ while !grid.dead() {
+ print!("");
+ grid.print(std::io::stdout().lock()).unwrap();
+ grid.iterate();
+ std::thread::sleep(Duration::from_millis(100));
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ #[test]
+ fn neb() {
+ let mut g = Grid::default();
+ assert_eq!(g.neighbors(0, 0), 0);
+ assert_eq!(g.neighbors(5, 5), 0);
+ g.spawn(5, 5);
+ assert_eq!(g.neighbors(4, 4), 1);
+ g.spawn(4, 5);
+ assert_eq!(g.neighbors(4, 4), 2);
+ }
+}
diff --git a/src/seed.png b/src/seed.png
new file mode 100644
index 0000000..3825726
--- /dev/null
+++ b/src/seed.png
Binary files differ