support sizes other than 9

This commit is contained in:
Eric Mertens
2022-12-06 13:39:30 -08:00
parent b396d85eae
commit 2912fb9488
19 changed files with 346 additions and 771 deletions

View File

@@ -34,7 +34,7 @@ parseBlocks (x:xs) =
case words x of
["block", [name], color, boring] ->
do color_ <- parseColor color
let (xs1,xs2) = splitAt 9 xs
let (xs1,xs2) = splitWalls xs
let locs = findLocs name xs1
let b = Box undefined (Original (walls xs1)) color_ (boring == "boring")
bs <- parseBlocks xs2
@@ -49,13 +49,17 @@ parseBlocks (x:xs) =
pure ((name, Box undefined (Infinity target) color_ True,[]):bs)
["epsilon", [name], [target], color] ->
do color_ <- parseColor color
let (xs1,xs2) = splitAt 9 xs
let (xs1,xs2) = splitWalls xs
let locs = findLocs name xs1
let b = Box undefined (Epsilon target (walls xs1)) color_ False
bs <- parseBlocks xs2
pure ((name, b, locs):bs)
_ -> Left "bad block"
splitWalls (x:xs) =
case splitAt (length x - 1) xs of
(a,b) -> (x:a, b)
parseColor :: String -> Either String Attr
parseColor "white" = Right (withForeColor defAttr white)
parseColor "cyan" = Right (withForeColor defAttr cyan)
@@ -68,11 +72,23 @@ parseColor "green" = Right (withForeColor defAttr green)
parseColor x = Left ("bad color " ++ x)
walls :: [String] -> Array Coord Bool
walls rows = listArray ((-4,-4),(4,4)) (map ('▓'==) (concat rows))
walls rows = listArray ((ylo,xlo),(yhi,xhi)) (map ('▓'==) (concat rows))
where
width = length (head rows)
height = length rows
ylo = - ((height - 1) `div` 2)
yhi = height `div` 2
xlo = - ((width - 1) `div` 2)
xhi = width `div` 2
mkRange :: Int -> (Int, Int)
mkRange n = (-(n-1)`div`2, n`div`2)
findLocs :: Char -> [[Char]] -> [(Char, Location)]
findLocs name xs =
[ (c, Location name y x)
| (y, row) <- zip [-4..] xs
, (x, c ) <- zip [-4..] row
]
| let (ylo, yhi) = mkRange (length xs)
, (y, row) <- zip [ylo .. yhi] xs
, let (xlo,xhi) = mkRange (length row)
, (x, c ) <- zip [xlo..xhi] row
]

View File

@@ -4,52 +4,55 @@ import Data.Array
import Data.Map (Map)
import Data.Map qualified as Map
import Data.Set qualified as Set
import Data.List (intersperse)
import Data.List (intersperse, group)
import Graphics.Vty
import Model
border :: Int
border = 20
unit :: Attr -> Int -> Char -> Image
unit a scale x =
vertCat (replicate scale (string a (replicate (2*scale) x)))
unit :: Attr -> Int -> Int -> Char -> Image
unit a h w c =
vertCat (replicate h (string a (replicate w c)))
drawBox :: Attr -> Int {- ^ width -} -> Int {- ^ height -} -> Image
drawBox a _ 1 = string a "[]"
drawBox a 2 1 = string a "[]"
drawBox a w 1 = string a ("[" ++ replicate (w-2) '-' ++ "]")
drawBox a w h = vertCat $
string a ('┌' : replicate (w-2) '─' ++ "") :
replicate (h-2) (string a ('│' : replicate (w-2) ' ' ++ "")) ++
[string a ('└' : replicate (w-2) '─' ++ "")]
button :: Attr -> Int -> Image
button a 1 = string a "[]"
button a n = vertCat $
string a ('┌' : replicate (2*n-2) '─' ++ "") :
replicate (n-2) (string a ('' : replicate (2*n-2) '' ++ "")) ++
[string a ('' : replicate (2*n-2) '' ++ "")]
button :: Attr -> Int -> Int -> Image
button a 1 2 = string a "[]"
button a 1 n = string a ("[" ++ replicate (n-2) '-' ++ "]")
button a h w = vertCat $
string a ('' : replicate (w-2) '' ++ "") :
replicate (h-2) (string a ('' : replicate (w-2) '' ++ "")) ++
[string a ('└' : replicate (w-2) '─' ++ "")]
home :: Attr -> Int -> Image
home a 1 = string a "<>"
home a n = vertCat $
string a ('╔' : replicate (2*n-2) '═' ++ "") :
replicate (n-2) (string a ('' : replicate (2*n-2) '' ++ "")) ++
[string a ('' : replicate (2*n-2) '' ++ "")]
home :: Attr -> Int -> Int -> Image
home a 1 2 = string a "<>"
home a 1 w = string a ("<" ++ replicate (w-2) '=' ++ ">")
home a h w = vertCat $
string a ('' : replicate (w-2) '' ++ "") :
replicate (h-2) (string a ('' : replicate (w-2) '' ++ "")) ++
[string a ('╚' : replicate (w-2) '═' ++ "")]
renderCell :: World -> Map Location Char -> Char -> Box -> Int -> Int -> Int -> Image
renderCell world locMap name box y x scale =
if boxWalls world box ! (y,x) then unit (boxColor box) scale wallChar
renderCell :: World -> Map Location Char -> Char -> Box -> Int -> Int -> Int -> Int -> Image
renderCell world locMap name box y x h w =
if boxWalls world box ! (y,x) then unit (boxColor box) h w wallChar
else case Map.lookup (Location name' y x) locMap of
Just n ->
if scale < 9
then unit (boxColor (worldBoxes world Map.! n)) scale n
else renderBox world locMap (worldBoxes world Map.! n) n
(scale `div` boxSize world box)
let box' = worldBoxes world Map.! n
in if h < boxSize world box'
then unit (boxColor box') h w n
else renderBox world locMap box' n
h w
Nothing
| Set.member loc (worldButtons world) -> button (boxColor box) scale
| loc == worldHome world -> home (boxColor box) scale
| otherwise -> unit (boxColor box) scale floorChar
| Set.member loc (worldButtons world) -> button (boxColor box) h w
| loc == worldHome world -> home (boxColor box) h w
| otherwise -> unit (boxColor box) h w floorChar
where
loc = Location name' y x
name' = contentName world name box
@@ -74,16 +77,19 @@ contentName world name box =
Infinity c -> contentName world c (worldBoxes world Map.! c)
Epsilon{} -> name
renderBox :: World -> Map Location Char -> Box -> Char -> Int -> Image
renderBox world locMap box name scale =
renderBox :: World -> Map Location Char -> Box -> Char -> Int -> Int -> Image
renderBox world locMap box name h w =
vertCat [
horizCat [
renderCell world locMap name box y x scale
| x <- [xlo .. xhi]
renderCell world locMap name box y x h w
| (x,w) <- zip [xlo .. xhi] (divisions boxWidth w)
]
| let ((ylo,xlo),(yhi,xhi)) = bounds (boxWalls world box)
, y <- [ylo .. yhi]
| (y,h) <- zip [ylo .. yhi] (divisions boxHeight h)
]
where
((ylo,xlo),(yhi,xhi)) = bounds (boxWalls world box)
boxWidth = xhi - xlo + 1
boxHeight = yhi - ylo + 1
render ::
Bool {- ^ show flat overlay -} ->
@@ -115,7 +121,7 @@ renderFlat locMap world =
pad 2 1 2 1 $
horizCat $
intersperse (char borderAttr ' ')
[renderBox world locMap b n 2
[renderBox world locMap b n 18 36
| (n,b) <- Map.assocs (worldBoxes world)
, not (boxBoring b)]
@@ -133,10 +139,10 @@ drawNestedWorld locMap world =
intersperse (char defAttr ' ')
[
case stackedLoc world locMap (Location name1 y_ x_) of
Nothing -> unit (withForeColor defAttr black) 81 '?'
Nothing -> unit (withForeColor defAttr black) 81 162 '?'
Just (Location n y x) ->
let box = worldBoxes world Map.! n in
renderCell world locMap n box y x 81
renderCell world locMap n box y x 81 (81*2)
| x_ <- [x1-1 .. x1+1]
]
| y_ <- [y1-1 .. y1+1]
@@ -192,4 +198,16 @@ fixup1 :: Int -> Int -> Int -> Int -> Int
fixup1 _ _ 0 i = i
fixup1 _ hi (-1) _ = hi
fixup1 lo _ 1 _ = lo
fixup1 _ _ _ _ = error "fixup1: bad delta"
fixup1 _ _ _ _ = error "fixup1: bad delta"
divisions :: Int -> Int -> [Int]
divisions divs size =
map length $ group
[ round (
(fromIntegral i + 1 / 2)
/ fromIntegral size
* fromIntegral divs
- 1/2
)
| i <- [0 ..size-1]
]