Browse Source

Got grid and head working

master
Thomas Johnson 2 years ago
commit
9263d5f185
  1. 2
      .gitignore
  2. 9
      Cargo.toml
  3. 160
      src/grid.rs
  4. 51
      src/head.rs
  5. 35
      src/main.rs

2
.gitignore

@ -0,0 +1,2 @@
/target
Cargo.lock

9
Cargo.toml

@ -0,0 +1,9 @@
[package]
name = "etch-a-term"
version = "0.1.0"
authors = ["thajohns <thajohns@clarkson.edu>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

160
src/grid.rs

@ -0,0 +1,160 @@
use core::ops::{Index, IndexMut};
pub fn add_v2(a: (isize, isize), b: (isize, isize)) -> (isize, isize) {
(a.0 + b.0, a.1 + b.1)
}
#[derive(Clone, Debug)]
pub struct Grid {
dims: (usize, usize),
origin: (isize, isize),
cells: Vec<Cell>,
}
impl Grid {
pub fn new(dims: (usize, usize), origin: (isize, isize)) -> Grid {
Grid {
dims,
origin,
cells: vec![Cell::new(); dims.0 * dims.1],
}
}
pub fn dims(&self) -> (usize, usize) {
self.dims
}
pub fn origin(&self) -> (isize, isize) {
self.origin
}
// TODO: use for resizing
pub fn linear_idx_to_coords(linear_idx: usize, dims: (usize, usize), origin: (isize, isize)) -> Option<(isize, isize)> {
let unadjusted = ((linear_idx / dims.0), (linear_idx % dims.0));
if unadjusted.0 >= dims.0 || unadjusted.1 >= dims.1 {
None
} else {
Some((unadjusted.0 as isize - origin.0, unadjusted.1 as isize - origin.1))
}
}
// TODO: use for resizing
pub fn coords_to_linear_idx(coords: (isize, isize), dims: (usize, usize), origin: (isize, isize)) -> Option<usize> {
let adjusted = add_v2(coords, origin);
if !(0..dims.0 as isize).contains(&adjusted.0) || !(0..dims.1 as isize).contains(&adjusted.1) {
None
} else {
Some(adjusted.0 as usize * dims.0 + adjusted.1 as usize)
}
}
pub fn in_bounds(&self, coords: (isize, isize)) -> bool {
let adjusted = add_v2(coords, self.origin);
(0..self.dims.0 as isize).contains(&adjusted.0) && (0..self.dims.1 as isize).contains(&adjusted.1)
}
pub fn to_2d_string(&self) -> String {
let mut s = String::new();
for y in 0..self.dims.1 {
for x in 0..self.dims.0 {
s.push(self[(x as isize, y as isize)].to_char());
}
s.push('\n');
}
s
}
}
impl Index<(isize, isize)> for Grid {
type Output = Cell;
fn index(&self, coords: (isize, isize)) -> &Self::Output {
let linidx = Self::coords_to_linear_idx(coords, self.dims, self.origin).expect("coordinates out of bounds in grid!");
&self.cells[linidx]
}
}
impl IndexMut<(isize, isize)> for Grid {
fn index_mut(&mut self, coords: (isize, isize)) -> &mut Self::Output {
let linidx = Self::coords_to_linear_idx(coords, self.dims, self.origin).expect("coordinates out of bounds in grid!");
&mut self.cells[linidx]
}
}
#[derive(Clone, Debug)]
pub struct Cell {
dirs: [bool; 4],
}
impl Cell {
pub fn new() -> Self {
Self {
dirs: [false; 4]
}
}
pub fn reset(&mut self) {
self.dirs = [false; 4];
}
pub fn draw_to_center(&mut self, from: Direction) {
self.dirs[from as usize] = true;
}
pub fn draw_from_center(&mut self, to: Direction) {
self.dirs[to as usize] = true;
}
pub fn to_char(&self) -> char {
match self.dirs {
[false, false, false, false] => ' ',
[false, false, false, true] => '╴',
[false, false, true, false] => '╷',
[false, false, true, true] => '┐',
[false, true, false, false] => '╶',
[false, true, false, true] => '─',
[false, true, true, false] => '┌',
[false, true, true, true] => '┬',
[true, false, false, false] => '╵',
[true, false, false, true] => '┘',
[true, false, true, false] => '│',
[true, false, true, true] => '┤',
[true, true, false, false] => '└',
[true, true, false, true] => '┴',
[true, true, true, false] => '├',
[true, true, true, true] => '┼',
}
}
}
#[derive(Clone, Copy, Debug)]
pub enum Direction {
North = 0,
East = 1,
South = 2,
West = 3,
}
impl Direction {
pub fn offset(&self) -> (isize, isize) {
use Direction::*;
match self {
North => (0, -1),
East => (1, 0),
South => (0, 1),
West => (-1, 0),
}
}
pub fn opposite(&self) -> Direction {
use Direction::*;
match self {
North => South,
East => West,
South => North,
West => East,
}
}
}

51
src/head.rs

@ -0,0 +1,51 @@
use core::fmt::Debug;
use core::ops::Deref;
use core::cell::RefCell;
use crate::grid::{add_v2, Grid, Direction};
#[derive(Clone, Debug)]
pub struct Head<G: Clone + Debug> {
grid: G,
down: bool,
coords: (isize, isize),
}
impl<G> Head<G> where
G: Clone + Debug + Deref<Target=RefCell<Grid>> {
pub fn new_at(grid: G, coords: (isize, isize)) -> Self {
Self {
grid,
down: true,
coords,
}
}
pub fn go(&mut self, dir: Direction) {
if self.down && self.grid.borrow().in_bounds(self.coords) {
self.grid.borrow_mut()[self.coords].draw_from_center(dir);
}
self.coords = add_v2(self.coords, dir.offset());
if self.down && self.grid.borrow().in_bounds(self.coords) {
self.grid.borrow_mut()[self.coords].draw_to_center(dir.opposite());
}
}
pub fn up(&mut self) {
self.down = false;
}
pub fn down(&mut self) {
self.down = true;
}
pub fn coords(&self) -> (isize, isize) {
self.coords
}
pub fn move_to(&mut self, coords: (isize, isize)) {
self.coords = coords;
}
}

35
src/main.rs

@ -0,0 +1,35 @@
#![feature(associated_type_bounds)]
pub mod grid;
pub mod head;
use std::rc::Rc;
use core::cell::RefCell;
use crate::grid::{Grid, Direction::*};
use crate::head::Head;
fn main() {
let grid = Rc::new(RefCell::new(Grid::new((8, 8), (0, 0))));
let mut head = Head::new_at(grid.clone(), (0, 0));
for dir in [
South,
East,
North,
East,
East,
South,
West,
South,
East,
South,
West,
West,
North,
West,
South,
].iter() {
head.go(*dir);
}
print!("{}", grid.borrow().to_2d_string());
}
Loading…
Cancel
Save