implement regions of multiple tiles
This commit is contained in:
parent
47ff50be5f
commit
d0bed390a5
3 changed files with 213 additions and 206 deletions
120
src/main.rs
120
src/main.rs
|
@ -1,125 +1,17 @@
|
||||||
|
mod region;
|
||||||
mod tile;
|
mod tile;
|
||||||
use tile::*;
|
use region::Region;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut tile = EMPTY_TILE;
|
let mut region = Region::new();
|
||||||
let mut tile2 = EMPTY_TILE;
|
|
||||||
let mut tile3 = EMPTY_TILE;
|
|
||||||
let mut tile4 = EMPTY_TILE;
|
|
||||||
// tile[WIDTH - 8] = (0b_1111_1111_1100_0000 as Row).reverse_bits();
|
|
||||||
tile[WIDTH - 8] = 0b_00100000;
|
|
||||||
tile[WIDTH - 7] = 0b_00010000;
|
|
||||||
tile[WIDTH - 6] = 0b_01110000;
|
|
||||||
|
|
||||||
tile[WIDTH - 3] = 0b_0010;
|
|
||||||
tile[WIDTH - 2] = 0b_0001;
|
|
||||||
tile[WIDTH - 1] = 0b_0111;
|
|
||||||
loop {
|
loop {
|
||||||
let edges = Edges::full(
|
println!("---");
|
||||||
&EMPTY_TILE,
|
region.print_all();
|
||||||
&tile3,
|
region.step();
|
||||||
&tile2,
|
|
||||||
&EMPTY_TILE,
|
|
||||||
&EMPTY_TILE,
|
|
||||||
&EMPTY_TILE,
|
|
||||||
&tile4,
|
|
||||||
&EMPTY_TILE,
|
|
||||||
);
|
|
||||||
let edges2 = Edges::full(
|
|
||||||
&EMPTY_TILE,
|
|
||||||
&tile4,
|
|
||||||
&EMPTY_TILE,
|
|
||||||
&tile,
|
|
||||||
&EMPTY_TILE,
|
|
||||||
&EMPTY_TILE,
|
|
||||||
&EMPTY_TILE,
|
|
||||||
&tile3,
|
|
||||||
);
|
|
||||||
let edges3 = Edges::full(
|
|
||||||
&tile,
|
|
||||||
&EMPTY_TILE,
|
|
||||||
&tile4,
|
|
||||||
&EMPTY_TILE,
|
|
||||||
&tile2,
|
|
||||||
&EMPTY_TILE,
|
|
||||||
&EMPTY_TILE,
|
|
||||||
&EMPTY_TILE,
|
|
||||||
);
|
|
||||||
let edges4 = Edges::full(
|
|
||||||
&tile2,
|
|
||||||
&EMPTY_TILE,
|
|
||||||
&EMPTY_TILE,
|
|
||||||
&tile3,
|
|
||||||
&EMPTY_TILE,
|
|
||||||
&tile,
|
|
||||||
&EMPTY_TILE,
|
|
||||||
&EMPTY_TILE,
|
|
||||||
);
|
|
||||||
println!();
|
|
||||||
println!("\n{:#<w$}", "", w = WIDTH * 2 + 1);
|
|
||||||
print_tiles(&tile, &tile2);
|
|
||||||
// print_tile(&tile3);
|
|
||||||
println!("{:-<w$}", "", w = WIDTH * 2 + 1);
|
|
||||||
print_tiles(&tile3, &tile4);
|
|
||||||
// print_tile(&tile2);
|
|
||||||
// print_tile(&tile4);
|
|
||||||
|
|
||||||
step(&mut tile, &edges);
|
|
||||||
step(&mut tile2, &edges2);
|
|
||||||
step(&mut tile3, &edges3);
|
|
||||||
step(&mut tile4, &edges4);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut a = String::new();
|
let mut a = String::new();
|
||||||
std::io::stdin().read_line(&mut a).unwrap();
|
std::io::stdin().read_line(&mut a).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fn print_tile(tile: &Tile) {
|
|
||||||
// for y in 0..(WIDTH / 2) {
|
|
||||||
// let top = tile[y * 2];
|
|
||||||
// let bot = tile[y * 2 + 1];
|
|
||||||
// let mut row = String::with_capacity(WIDTH);
|
|
||||||
// for bit in (0..WIDTH).rev() {
|
|
||||||
// let states = ((top >> bit) & 1, (bot >> bit) & 1);
|
|
||||||
// row.push(match states {
|
|
||||||
// (0, 0) => ' ',
|
|
||||||
// (1, 0) => '▀',
|
|
||||||
// (0, 1) => '▄',
|
|
||||||
// (1, 1) => '█',
|
|
||||||
// _ => unreachable!(),
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// println!("{row}");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
fn blocks(top: Row, bottom: Row, bit: usize) -> char {
|
|
||||||
let states = ((top >> bit) & 1, (bottom >> bit) & 1);
|
|
||||||
match states {
|
|
||||||
(0, 0) => ' ',
|
|
||||||
(1, 0) => '▀',
|
|
||||||
(0, 1) => '▄',
|
|
||||||
(1, 1) => '█',
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn print_tiles(left: &TileArr, right: &TileArr) {
|
|
||||||
for y in 0..(WIDTH / 2) {
|
|
||||||
let a = left[y * 2];
|
|
||||||
let b = left[y * 2 + 1];
|
|
||||||
let mut row = String::with_capacity(WIDTH * 2 + 1);
|
|
||||||
for bit in (0..WIDTH).rev() {
|
|
||||||
row.push(blocks(a, b, bit));
|
|
||||||
}
|
|
||||||
row.push('|');
|
|
||||||
let a = right[y * 2];
|
|
||||||
let b = right[y * 2 + 1];
|
|
||||||
for bit in (0..WIDTH).rev() {
|
|
||||||
row.push(blocks(a, b, bit));
|
|
||||||
}
|
|
||||||
println!("{row}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
77
src/region.rs
Normal file
77
src/region.rs
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
use crate::tile::{Edges, Tile, WIDTH};
|
||||||
|
|
||||||
|
pub struct Region {
|
||||||
|
/// rows of tiles
|
||||||
|
tiles: Vec<Vec<Tile>>,
|
||||||
|
size: (usize, usize),
|
||||||
|
offset: (isize, isize),
|
||||||
|
auto_expand: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Region {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let tiles = vec![vec![Tile::glider(); 2]; 2];
|
||||||
|
Self {
|
||||||
|
tiles,
|
||||||
|
size: (2, 2),
|
||||||
|
offset: (-1, -1),
|
||||||
|
auto_expand: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_all(&self) {
|
||||||
|
for y in 0..self.size.1 {
|
||||||
|
for ch_row in 0..(WIDTH / 2) {
|
||||||
|
for x in 0..self.size.1 {
|
||||||
|
self.tiles[y][x].print_row(ch_row);
|
||||||
|
// print!("|");
|
||||||
|
}
|
||||||
|
println!()
|
||||||
|
}
|
||||||
|
// println!("------");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_cell(&mut self, x: isize, y: isize, state: bool) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_tile_relative(&self, x: usize, y: usize, relx: isize, rely: isize) -> Option<&Tile> {
|
||||||
|
self.tiles
|
||||||
|
.get(y.checked_add_signed(rely)?)
|
||||||
|
.and_then(|row| row.get(x.checked_add_signed(relx)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn step(&mut self) {
|
||||||
|
// store edges
|
||||||
|
let mut edges = Vec::with_capacity(self.size.1);
|
||||||
|
for y in 0..self.size.1 {
|
||||||
|
let mut row = Vec::with_capacity(self.size.0);
|
||||||
|
for x in 0..self.size.0 {
|
||||||
|
let n = self.get_tile_relative(x, y, 0, -1).unwrap_or(&Tile::EMPTY);
|
||||||
|
let s = self.get_tile_relative(x, y, 0, 1).unwrap_or(&Tile::EMPTY);
|
||||||
|
let e = self.get_tile_relative(x, y, 1, 0).unwrap_or(&Tile::EMPTY);
|
||||||
|
let w = self.get_tile_relative(x, y, -1, 0).unwrap_or(&Tile::EMPTY);
|
||||||
|
let ne = self.get_tile_relative(x, y, 1, -1).unwrap_or(&Tile::EMPTY);
|
||||||
|
let nw = self.get_tile_relative(x, y, -1, -1).unwrap_or(&Tile::EMPTY);
|
||||||
|
let se = self.get_tile_relative(x, y, 1, 1).unwrap_or(&Tile::EMPTY);
|
||||||
|
let sw = self.get_tile_relative(x, y, -1, 1).unwrap_or(&Tile::EMPTY);
|
||||||
|
|
||||||
|
let edge = Edges::full(n, s, e, w, ne, nw, se, sw);
|
||||||
|
// dbg!(&edge);
|
||||||
|
row.push(edge);
|
||||||
|
}
|
||||||
|
edges.push(row);
|
||||||
|
}
|
||||||
|
// dbg!(&edges);
|
||||||
|
for y in 0..self.size.1 {
|
||||||
|
for x in 0..self.size.0 {
|
||||||
|
// dbg!(x, y, &edges[y][x]);
|
||||||
|
self.tiles[y][x].step(&edges[y][x]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if self.auto_expand {
|
||||||
|
// todo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
104
src/tile.rs
104
src/tile.rs
|
@ -1,10 +1,9 @@
|
||||||
pub type Row = u32;
|
pub type Row = u16;
|
||||||
pub type TileArr = [Row; WIDTH];
|
|
||||||
pub const EMPTY_TILE: TileArr = [0; WIDTH];
|
|
||||||
|
|
||||||
pub const WIDTH: usize = Row::BITS as usize;
|
pub const WIDTH: usize = Row::BITS as usize;
|
||||||
const LAST: usize = WIDTH - 1;
|
const LAST: usize = WIDTH - 1;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Edges {
|
pub struct Edges {
|
||||||
n: Row,
|
n: Row,
|
||||||
s: Row,
|
s: Row,
|
||||||
|
@ -16,7 +15,54 @@ pub struct Edges {
|
||||||
se: bool,
|
se: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn step(tile: &mut TileArr, edges: &Edges) {
|
#[derive(Clone)]
|
||||||
|
pub struct Tile {
|
||||||
|
pub rows: [Row; WIDTH],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tile {
|
||||||
|
pub const EMPTY: Tile = Tile { rows: [0; WIDTH] };
|
||||||
|
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self { rows: [0; WIDTH] }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.rows.iter().fold(0, |a, r| a | r) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn glider() -> Self {
|
||||||
|
let mut tile = Self::new();
|
||||||
|
|
||||||
|
tile.rows[WIDTH - 8] = 0b_00100000;
|
||||||
|
tile.rows[WIDTH - 7] = 0b_00010000;
|
||||||
|
tile.rows[WIDTH - 6] = 0b_01110000;
|
||||||
|
|
||||||
|
tile.rows[WIDTH - 3] = 0b_0010;
|
||||||
|
tile.rows[WIDTH - 2] = 0b_0001;
|
||||||
|
tile.rows[WIDTH - 1] = 0b_0111;
|
||||||
|
tile
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_row(&self, ch_row: usize) {
|
||||||
|
let mut row = String::with_capacity(WIDTH * 2 + 1);
|
||||||
|
let top = self.rows[ch_row * 2];
|
||||||
|
let bottom = self.rows[ch_row * 2 + 1];
|
||||||
|
for bit in (0..WIDTH).rev() {
|
||||||
|
let states = ((top >> bit) & 1, (bottom >> bit) & 1);
|
||||||
|
let ch = match states {
|
||||||
|
(0, 0) => ' ',
|
||||||
|
(1, 0) => '▀',
|
||||||
|
(0, 1) => '▄',
|
||||||
|
(1, 1) => '█',
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
row.push(ch);
|
||||||
|
}
|
||||||
|
print!("{row}");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn step(&mut self, edges: &Edges) {
|
||||||
fn step_row(state: &mut Row, a0: Row, a1: Row, b0: Row, b1: Row, c0: Row, c1: Row) {
|
fn step_row(state: &mut Row, a0: Row, a1: Row, b0: Row, b1: Row, c0: Row, c1: Row) {
|
||||||
// simulates addition of [WIDTH] groups of 3 2-bit numbers using bitwise operations
|
// simulates addition of [WIDTH] groups of 3 2-bit numbers using bitwise operations
|
||||||
|
|
||||||
|
@ -34,8 +80,10 @@ pub fn step(tile: &mut TileArr, edges: &Edges) {
|
||||||
*state = (!n2 & n1 & n0) | (*state & n2 & !(n0 | n1));
|
*state = (!n2 & n1 & n0) | (*state & n2 & !(n0 | n1));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut partial_sums_1 = EMPTY_TILE;
|
let mut partial_sums_1 = [0; WIDTH];
|
||||||
let mut partial_sums_2 = EMPTY_TILE;
|
let mut partial_sums_2 = [0; WIDTH];
|
||||||
|
|
||||||
|
let tile = &mut self.rows;
|
||||||
|
|
||||||
for (y, row) in tile.iter().enumerate() {
|
for (y, row) in tile.iter().enumerate() {
|
||||||
let left = (row >> 1) | edges.west_bit(y);
|
let left = (row >> 1) | edges.west_bit(y);
|
||||||
|
@ -87,45 +135,35 @@ pub fn step(tile: &mut TileArr, edges: &Edges) {
|
||||||
partial_south_1,
|
partial_south_1,
|
||||||
partial_south_2,
|
partial_south_2,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Edges {
|
impl Edges {
|
||||||
// pub const EMPTY: Self = Edges {
|
|
||||||
// n: 0,
|
|
||||||
// s: 0,
|
|
||||||
// e: 0,
|
|
||||||
// w: 0,
|
|
||||||
// ne: false,
|
|
||||||
// nw: false,
|
|
||||||
// se: false,
|
|
||||||
// sw: false,
|
|
||||||
// };
|
|
||||||
|
|
||||||
pub fn full(
|
pub fn full(
|
||||||
n: &TileArr,
|
n: &Tile,
|
||||||
s: &TileArr,
|
s: &Tile,
|
||||||
e: &TileArr,
|
e: &Tile,
|
||||||
w: &TileArr,
|
w: &Tile,
|
||||||
ne: &TileArr,
|
ne: &Tile,
|
||||||
nw: &TileArr,
|
nw: &Tile,
|
||||||
se: &TileArr,
|
se: &Tile,
|
||||||
sw: &TileArr,
|
sw: &Tile,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut east = 0;
|
let mut east = 0;
|
||||||
let mut west = 0;
|
let mut west = 0;
|
||||||
for n in 0..WIDTH {
|
for n in 0..WIDTH {
|
||||||
east |= (e[n] >> LAST) << n;
|
east |= (e.rows[n] >> LAST) << n;
|
||||||
west |= (w[n] & 1) << n;
|
west |= (w.rows[n] & 1) << n;
|
||||||
}
|
}
|
||||||
Self {
|
Self {
|
||||||
n: n[LAST],
|
n: n.rows[LAST],
|
||||||
s: s[0],
|
s: s.rows[0],
|
||||||
e: east,
|
e: east,
|
||||||
w: west,
|
w: west,
|
||||||
nw: (nw[LAST] & 1) != 0,
|
nw: (nw.rows[LAST] & 1) != 0,
|
||||||
ne: (ne[LAST] >> LAST) != 0,
|
ne: (ne.rows[LAST] >> LAST) != 0,
|
||||||
sw: (sw[0] & 1) != 0,
|
sw: (sw.rows[0] & 1) != 0,
|
||||||
se: (se[0] >> LAST) != 0,
|
se: (se.rows[0] >> LAST) != 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue