From b37fb0bfd9272484c5fa93e2826ee3433eeedda6 Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Sat, 22 Jul 2023 17:04:10 +0200 Subject: [PATCH] rle parsing --- .gitignore | 1 + src/lib.rs | 1 + src/main.rs | 18 ++++++++++----- src/region.rs | 31 +++++++++++++++++++++++++- src/rle.rs | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/tile.rs | 4 ++-- 6 files changed, 109 insertions(+), 8 deletions(-) create mode 100644 src/rle.rs diff --git a/.gitignore b/.gitignore index ea8c4bf..6631e2e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +*.rle diff --git a/src/lib.rs b/src/lib.rs index dae266f..106cec6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,3 @@ pub mod region; +pub mod rle; pub mod tile; diff --git a/src/main.rs b/src/main.rs index 664dad8..a71f106 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,21 @@ -use gol_bitwise::region::Region; +use std::env; + +use gol_bitwise::{region::Region, rle}; fn main() { - let mut region = Region::new(1, 1); - region.randomise(); - print!("\x1B[2J"); // clear screen + let mut region = if let Some(file) = env::args().nth(1) { + Region::from_bools(rle::parse(&file).unwrap()) + } else { + let mut r = Region::new(1, 1); + r.randomise(); + r + }; + region.auto_grow(); loop { + print!("\x1B[2J"); // clear screen print!("\x1B[u"); // reset cursor - region.print_all(true); + region.print_all(false); region.step(); region.auto_grow(); { diff --git a/src/region.rs b/src/region.rs index 619da53..48f3d5e 100644 --- a/src/region.rs +++ b/src/region.rs @@ -1,4 +1,4 @@ -use crate::tile::{Edges, Tile, WIDTH}; +use crate::tile::{Edges, Row, Tile, WIDTH}; pub struct Region { /// rows of tiles @@ -11,6 +11,35 @@ impl Region { Self { tiles } } + pub fn from_bools(board: Vec>) -> Self { + let height = board.len() / WIDTH + 1; + let width = board[0].len() / WIDTH + 1; + let mut tiles = vec![vec![Tile::new(); width]; height]; + + for tile_y in 0..height { + for tile_x in 0..width { + let tile = &mut tiles[tile_y][tile_x]; + for y in 0..WIDTH { + let by = tile_y * WIDTH + y; + if by >= board.len() { + break; + } + let mut row = 0; + for x in 0..WIDTH { + let bx = tile_x * WIDTH + x; + if bx >= board[by].len() { + break; + } + row |= (board[by][bx] as Row) << (WIDTH - x - 1) as Row; + } + tile.rows[y] = row; + } + } + } + + Self { tiles } + } + pub fn randomise(&mut self) { for row in self.tiles.iter_mut() { for tile in row { diff --git a/src/rle.rs b/src/rle.rs new file mode 100644 index 0000000..0f079ef --- /dev/null +++ b/src/rle.rs @@ -0,0 +1,62 @@ +use std::fs; + +// one of the shittest RLE parsers in existence :) + +pub fn parse(filename: &str) -> Option>> { + let file = fs::read_to_string(filename).ok()?; + let mut meta = None; + let mut rle = String::new(); + for line in file.lines() { + if line.starts_with('#') { + continue; + } + if meta.is_none() { + meta = Some(line.to_owned()); + continue; + } + rle.push_str(line); + } + let meta = meta?; + + let properties = meta.split(", ").collect::>(); + let width: usize = properties.get(0)?.split('=').nth(1)?.trim().parse().ok()?; + let height: usize = properties.get(1)?.split('=').nth(1)?.trim().parse().ok()?; + + let mut board = vec![vec![false; width]; height]; + + let mut x = 0; + let mut y = 0; + let mut run_count = 0; + + for char in rle.chars() { + match char { + 'b' => { + run_count = run_count.max(1); + x += run_count; + run_count = 0; + } + 'o' => { + run_count = run_count.max(1); + for rx in x..(x + run_count) { + board[y][rx] = true; + } + x += run_count; + run_count = 0; + } + '$' => { + run_count = run_count.max(1); + y += run_count; + run_count = 0; + x = 0; + } + '0'..='9' => { + run_count *= 10; + run_count += ((char as u8) - b'0') as usize; + } + '!' => break, + '\n' => (), + other => println!("Unknown token {other} in RLE"), + } + } + Some(board) +} diff --git a/src/tile.rs b/src/tile.rs index 3f5ad5b..778029f 100644 --- a/src/tile.rs +++ b/src/tile.rs @@ -1,4 +1,4 @@ -type Row = u16; +pub type Row = u16; pub const WIDTH: usize = Row::BITS as usize; const LAST: usize = WIDTH - 1; @@ -15,7 +15,7 @@ pub struct Edges { se: bool, } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct Tile { pub rows: [Row; WIDTH], }