about summary refs log tree commit diff
path: root/src/display
diff options
context:
space:
mode:
authorGriffin Smith <root@gws.fyi>2019-07-28T21·45-0400
committerGriffin Smith <root@gws.fyi>2019-07-28T21·45-0400
commit6c1eba67629504f10fa08ee68fb31f507c99b0d1 (patch)
treed5af8f3eb6dc32a1308a20863e5c8814a4634098 /src/display
parentf22bcad817ee354b355d29b6b289894e2d15cfaa (diff)
Allow converting generated levels to entities
Add a new Wall entity, and allow converting generated levels to entity
maps containing them, then finally displaying them using some of
the (now expanded) box drawing machinery.
Diffstat (limited to 'src/display')
-rw-r--r--src/display/draw_box.rs50
-rw-r--r--src/display/mod.rs20
-rw-r--r--src/display/viewport.rs12
3 files changed, 75 insertions, 7 deletions
diff --git a/src/display/draw_box.rs b/src/display/draw_box.rs
index 5dc1627a298d..3b2b4aaf4f1d 100644
--- a/src/display/draw_box.rs
+++ b/src/display/draw_box.rs
@@ -2,6 +2,7 @@ use crate::display::utils::clone_times;
 use crate::display::utils::times;
 use crate::types::BoundingBox;
 use crate::types::Dimensions;
+use crate::types::Neighbors;
 use itertools::Itertools;
 use proptest::prelude::Arbitrary;
 use proptest::strategy;
@@ -22,42 +23,50 @@ use std::io::{self, Write};
 static BOX: char = '☐';
 
 static BOX_CHARS: [[char; 16]; 8] = [
+    // 0
     [
         // 0    1    2    3    4    5    6    7    8    9
         '─', '━', '│', '┃', '┄', '┅', '┆', '┇', '┈', '┉',
         // 10
         '┊', '┋', '┌', '┍', '┎', '┏',
     ],
+    // 1
     [
         // 0    1    2    3    4    5    6    7    8    9
         '┐', '┑', '┒', '┓', '└', '┕', '┖', '┗', '┘', '┙',
         '┚', '┛', '├', '┝', '┞', '┟',
     ],
+    // 2
     [
         // 0    1    2    3    4    5    6    7    8    9
         '┠', '┡', '┢', '┣', '┤', '┥', '┦', '┧', '┨', '┩',
         '┪', '┫', '┬', '┭', '┮', '┯',
     ],
+    // 3
     [
         // 0    1    2    3    4    5    6    7    8    9
         '┰', '┱', '┲', '┳', '┴', '┵', '┶', '┷', '┸', '┹',
         '┺', '┻', '┼', '┽', '┾', '┿',
     ],
+    // 4
     [
         // 0    1    2    3    4    5    6    7    8    9
         '╀', '╁', '╂', '╃', '╄', '╅', '╆', '╇', '╈', '╉',
         '╊', '╋', '╌', '╍', '╎', '╏',
     ],
+    // 5
     [
         // 0    1    2    3    4    5    6    7    8    9
         '═', '║', '╒', '╓', '╔', '╕', '╖', '╗', '╘', '╙',
         '╚', '╛', '╜', '╝', '╞', '╟',
     ],
+    // 6
     [
         // 0    1    2    3    4    5    6    7    8    9
         '╠', '╡', '╢', '╣', '╤', '╥', '╦', '╧', '╨', '╩',
         '╪', '╫', '╬', '╭', '╮', '╯',
     ],
+    // 7
     [
         // 0    1    2    3    4    5    6    7    8    9
         '╰', '╱', '╲', '╳', '╴', '╵', '╶', '╷', '╸', '╹',
@@ -85,8 +94,8 @@ impl Arbitrary for BoxStyle {
     }
 }
 
-trait Stylable {
-    fn style(self, style: BoxStyle) -> char;
+pub trait Stylable {
+    fn style(&self, style: BoxStyle) -> char;
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Arbitrary)]
@@ -98,7 +107,7 @@ enum Corner {
 }
 
 impl Stylable for Corner {
-    fn style(self, style: BoxStyle) -> char {
+    fn style(&self, style: BoxStyle) -> char {
         use BoxStyle::*;
         use Corner::*;
 
@@ -119,7 +128,7 @@ enum Line {
 }
 
 impl Stylable for Line {
-    fn style(self, style: BoxStyle) -> char {
+    fn style(&self, style: BoxStyle) -> char {
         use BoxStyle::*;
         use Line::*;
         match (self, style) {
@@ -130,6 +139,39 @@ impl Stylable for Line {
     }
 }
 
+impl Stylable for Neighbors<Option<BoxStyle>> {
+    fn style(&self, style: BoxStyle) -> char {
+        use BoxStyle::*;
+        match (self.left, self.right, self.top, self.bottom) {
+            (None, None, None, None) => BOX,
+            (Some(Thin), None, None, None) => BOX_CHARS[7][4],
+            (None, Some(Thin), None, None) => BOX_CHARS[7][6],
+            (None, None, Some(Thin), None) => BOX_CHARS[7][5],
+            (None, None, None, Some(Thin)) => BOX_CHARS[7][7],
+            (Some(Thin), Some(Thin), None, None) => Line::H.style(Thin),
+            (Some(Thin), None, Some(Thin), None) => {
+                Corner::BottomRight.style(Thin)
+            }
+            (Some(Thin), None, None, Some(Thin)) => {
+                Corner::TopRight.style(Thin)
+            }
+            (None, Some(Thin), Some(Thin), None) => {
+                Corner::BottomLeft.style(Thin)
+            }
+            (None, Some(Thin), None, Some(Thin)) => Corner::TopLeft.style(Thin),
+            (None, None, Some(Thin), Some(Thin)) => Line::V.style(Thin),
+            (None, Some(Thin), Some(Thin), Some(Thin)) => BOX_CHARS[1][12],
+            (Some(Thin), None, Some(Thin), Some(Thin)) => BOX_CHARS[2][4],
+            (Some(Thin), Some(Thin), None, Some(Thin)) => BOX_CHARS[2][12],
+            (Some(Thin), Some(Thin), Some(Thin), None) => BOX_CHARS[3][4],
+            (Some(Thin), Some(Thin), Some(Thin), Some(Thin)) => {
+                BOX_CHARS[3][12]
+            }
+            neighs => panic!("unimplemented: {:?}", neighs),
+        }
+    }
+}
+
 #[must_use]
 pub fn make_box(style: BoxStyle, dims: Dimensions) -> String {
     if dims.h == 0 || dims.w == 0 {
diff --git a/src/display/mod.rs b/src/display/mod.rs
index 3e30200ac723..10690284f126 100644
--- a/src/display/mod.rs
+++ b/src/display/mod.rs
@@ -2,6 +2,8 @@ pub mod color;
 pub mod draw_box;
 pub mod utils;
 pub mod viewport;
+use crate::entities::entity::Entity;
+use crate::types::Neighbors;
 use crate::types::Positioned;
 pub use draw_box::{make_box, BoxStyle};
 use std::io::{self, Write};
@@ -29,3 +31,21 @@ impl<T: Draw> Draw for Box<T> {
         (**self).do_draw(out)
     }
 }
+
+pub trait DrawWithNeighbors: Positioned {
+    fn do_draw_with_neighbors<'a, 'b>(
+        &'a self,
+        out: &'b mut Write,
+        neighbors: &'a Neighbors<Vec<&'a Box<dyn Entity>>>,
+    ) -> io::Result<()>;
+}
+
+impl<T: Draw> DrawWithNeighbors for T {
+    fn do_draw_with_neighbors<'a, 'b>(
+        &'a self,
+        out: &'b mut Write,
+        _neighbors: &'a Neighbors<Vec<&'a Box<dyn Entity>>>,
+    ) -> io::Result<()> {
+        self.do_draw(out)
+    }
+}
diff --git a/src/display/viewport.rs b/src/display/viewport.rs
index 372c0a2969d5..9ff7db07be20 100644
--- a/src/display/viewport.rs
+++ b/src/display/viewport.rs
@@ -1,7 +1,9 @@
 use super::BoxStyle;
-use super::Draw;
+use super::DrawWithNeighbors;
 use crate::display::draw_box::draw_box;
 use crate::display::utils::clone_times;
+use crate::entities::entity::Entity;
+use crate::types::Neighbors;
 use crate::types::{pos, BoundingBox, Direction, Position, Positioned};
 use std::fmt::{self, Debug};
 use std::io::{self, Write};
@@ -77,12 +79,16 @@ impl<W> Debug for Viewport<W> {
 
 impl<W: Write> Viewport<W> {
     /// Draw the given entity to the viewport at its position, if visible
-    pub fn draw<T: Draw>(&mut self, entity: &T) -> io::Result<()> {
+    pub fn draw<'a, T: DrawWithNeighbors>(
+        &mut self,
+        entity: &T,
+        neighbors: &Neighbors<Vec<&Box<dyn Entity>>>,
+    ) -> io::Result<()> {
         if !self.visible(entity) {
             return Ok(());
         }
         self.cursor_goto(entity.position())?;
-        entity.do_draw(self)?;
+        entity.do_draw_with_neighbors(self, neighbors)?;
         self.reset_cursor()
     }