This commit is contained in:
Eric Mertens 2022-11-30 16:44:30 -08:00
parent 48af4f917c
commit 4dec7e103d

View File

@ -39,18 +39,45 @@ renderBox world locMap box boxName =
[ [
horizCat horizCat
[ [
if boxWalls box ! (y,x) then char myAttr '▓' if boxWalls box ! (y,x) then unit myAttr '▓'
else case Map.lookup (Location boxName y x) locMap of else case Map.lookup (Location boxName y x) locMap of
Nothing -> char myAttr '░' Nothing -> unit myAttr '░'
Just n -> char (boxColor (worldBoxes world Map.! n)) n Just n -> unit (boxColor (worldBoxes world Map.! n)) n
| x <- [xlo .. xhi] | x <- [xlo .. xhi]
] ]
| let ((ylo,xlo),(yhi,xhi)) = bounds (boxWalls box) | let ((ylo,xlo),(yhi,xhi)) = bounds (boxWalls box)
, let myAttr = boxColor box , let myAttr = boxColor box
, y <- [ylo .. yhi] , y <- [ylo .. yhi]
, let unit a x = string a [x,x]
] ]
renderBox' :: World -> Map Location Char -> Box -> Char -> ((Int,Int),(Int,Int)) -> Int -> Image
renderBox' world locMap box boxName ((ylo,xlo),(yhi,xhi)) scale
| scale == 1 = renderBox world locMap box boxName
| otherwise =
vertCat
[
horizCat
[
if not (inRange (bounds (boxWalls box)) (y,x)) then unit defAttr '?' else
if boxWalls box ! (y,x) then unit myAttr '▓'
else case Map.lookup (Location boxName y x) locMap of
Nothing -> unit myAttr '░'
Just n -> renderBox' world locMap box' n (bounds (boxWalls box')) (scale `div` boxSize box)
where
box' = worldBoxes world Map.! n
| x <- [xlo .. xhi]
]
| let myAttr = boxColor box
, y <- [ylo .. yhi]
]
where
unit a x =
vertCat (replicate scale (string a (replicate (2*scale) x)))
makeWalls :: [String] -> Array Coord Bool makeWalls :: [String] -> Array Coord Bool
makeWalls rows = listArray ((ylo,xlo),(yhi,xhi)) (map (' '/=) (concat rows)) makeWalls rows = listArray ((ylo,xlo),(yhi,xhi)) (map (' '/=) (concat rows))
where where
@ -61,6 +88,29 @@ makeWalls rows = listArray ((ylo,xlo),(yhi,xhi)) (map (' '/=) (concat rows))
mkRange n = (- (n-1)`div`2, n`div`2) mkRange n = (- (n-1)`div`2, n`div`2)
boxSize :: Box -> Int
boxSize box = yhi-ylo+1
where
((ylo,_),(yhi,_)) = bounds (boxWalls box)
drawNestedWorld :: World -> Image
drawNestedWorld world = renderBox' world locMap box0 name0 bnds 49
where
locMap = Map.fromList [(boxLocation loc, n) | (n, loc) <- Map.toList (worldBoxes world)]
(bnds,name0) = go 2 0 0 (worldMe world)
box0 = worldBoxes world Map.! name0
go 0 y x name = (((y-1,x-1),(y+1,x+1)), name)
go n y x name =
case Map.lookup name (worldBoxes world) of
Nothing -> (((y-1,x-1),(y+1,x+1)), name)
Just box -> go (n-1) y x name'
where
Location name' y x = boxLocation box
drawWorld :: World -> Image drawWorld :: World -> Image
drawWorld world = drawWorld world =
horizCat $ horizCat $
@ -72,6 +122,8 @@ drawWorld world =
where where
locMap = Map.fromList [(boxLocation loc, n) | (n, loc) <- Map.toList (worldBoxes world)] locMap = Map.fromList [(boxLocation loc, n) | (n, loc) <- Map.toList (worldBoxes world)]
solid n = makeWalls (replicate n (replicate n 'x'))
world0 :: World world0 :: World
world0 = World { world0 = World {
worldMe = 'b', worldMe = 'b',
@ -80,49 +132,43 @@ world0 = World {
boxColor = withForeColor defAttr green, boxColor = withForeColor defAttr green,
boxLocation = Location '1' (-1) 0, boxLocation = Location '1' (-1) 0,
boxWalls = makeWalls [ boxWalls = makeWalls [
"▓▓▓ ▓▓▓", "▓▓ ▓▓",
"▓ ▓",
"▓ ▓", "▓ ▓",
"▓ ▓", "▓ ▓",
"▓ ▓", "▓ ▓",
"▓ ▓ ▓", "▓ ▓ ▓",
"▓ ▓", "▓ ▓",
"▓ ▓", "▓ ▓ ▓"
"▓▓▓ ▓ ▓▓▓"
] ]
}), }),
('2', Box { ('2', Box {
boxColor = withForeColor defAttr cyan, boxColor = withForeColor defAttr cyan,
boxLocation = Location '1' 1 1, boxLocation = Location '1' 1 1,
boxWalls = makeWalls [ boxWalls = makeWalls [
"▓▓▓ ▓▓▓", "▓▓▓ ▓▓▓",
"▓ ▓", "▓ ▓",
"▓ ▓", "▓ ▓",
" ", " ",
"▓ ▓", "▓ ▓",
"▓ ▓", "▓ ▓",
"▓▓▓ ▓▓▓" "▓▓▓ ▓▓▓"
] ]
}), }),
('b', Box { ('b', Box {
boxColor = withForeColor defAttr red, boxColor = withForeColor defAttr red,
boxLocation = Location '1' 0 1, boxLocation = Location '1' 0 1,
boxWalls = makeWalls [ boxWalls = solid 7
"▓ ▓",
" ",
"▓ ▓"
]
}), }),
('x', Box { ('x', Box {
boxColor = withForeColor defAttr yellow, boxColor = withForeColor defAttr yellow,
boxLocation = Location '1' 0 (-1), boxLocation = Location '1' 0 (-1),
boxWalls = makeWalls [""] boxWalls = solid 7
}), }),
('y', Box { ('y', Box {
boxColor = withForeColor defAttr magenta, boxColor = withForeColor defAttr magenta,
boxLocation = Location '1' 0 (-2), boxLocation = Location '1' 0 (-2),
boxWalls = makeWalls [""] boxWalls = solid 7
}) })
] ]
@ -162,7 +208,7 @@ main =
loop :: Vty -> NonEmpty World -> IO () loop :: Vty -> NonEmpty World -> IO ()
loop vty (world :| history) = loop vty (world :| history) =
do update vty (picForImage (drawWorld world)) do update vty (picForImage (drawNestedWorld world))
ev <- nextEvent vty ev <- nextEvent vty
case ev of case ev of
EvKey key _modifier -> EvKey key _modifier ->
@ -204,21 +250,24 @@ moveBlock world visited loc dir =
-- moving a box -- moving a box
(name,box):_ -> (name,box):_ ->
do loc' <- nextLoc world loc dir do loc' <- nextLoc world loc dir
guard (not (isWall loc' world))
moveBlock' world visited loc loc' dir name box moveBlock' world visited loc loc' dir name box
moveBlock' world visited loc loc' dir name box = moveBlock' world visited loc loc' dir name box =
msum [moveTo loc', moveInto loc', moveToEat loc'] msum [moveTo loc', moveInto loc', moveToEat loc']
where where
moveTo loc' = moveBlock world (addVisited loc loc' visited) loc' dir moveTo loc' =
do guard (not (isWall loc' world))
moveBlock world (addVisited loc loc' visited) loc' dir
moveInto loc' = moveInto loc' =
do (n,b) <- boxAt world loc' do guard (not (isWall loc' world))
(n,b) <- boxAt world loc'
let locI = enterLoc n b dir let locI = enterLoc n b dir
moveBlock world (addVisited loc locI visited) locI dir moveBlock world (addVisited loc locI visited) locI dir
moveToEat loc' = moveToEat loc' =
do let dir' = invert dir do guard (not (isWall loc' world))
let dir' = invert dir
let locE = enterLoc name box dir' let locE = enterLoc name box dir'
(name', box') <- boxAt world loc' (name', box') <- boxAt world loc'
moveBlock' world (addVisited loc loc' visited) loc' locE dir' name' box' moveBlock' world (addVisited loc loc' visited) loc' locE dir' name' box'