swarm-0.5.0.0: src/Swarm/Game/World/Render.hs
-- |
-- SPDX-License-Identifier: BSD-3-Clause
--
-- TUI-independent world rendering.
module Swarm.Game.World.Render where
import Control.Effect.Lift (sendIO)
import Control.Lens (view)
import Data.List.NonEmpty qualified as NE
import Swarm.Doc.Gen (loadStandaloneScenario)
import Swarm.Game.Display (defaultChar)
import Swarm.Game.ResourceLoading (initNameGenerator, readAppData)
import Swarm.Game.Scenario (Scenario, area, scenarioWorlds, ul, worldName)
import Swarm.Game.Scenario.Status (emptyLaunchParams)
import Swarm.Game.Scenario.Topography.Area (AreaDimensions (..), getAreaDimensions, isEmpty, upperLeftToBottomRight)
import Swarm.Game.Scenario.Topography.Cell
import Swarm.Game.Scenario.Topography.EntityFacade (EntityFacade (..), mkFacade)
import Swarm.Game.State
import Swarm.Game.Universe
import Swarm.Game.World qualified as W
import Swarm.TUI.Editor.Util (getContentAt, getMapRectangle)
import Swarm.Util.Effect (simpleErrorHandle)
import Swarm.Util.Erasable (erasableToMaybe)
getDisplayChar :: PCell EntityFacade -> Char
getDisplayChar = maybe ' ' facadeChar . erasableToMaybe . cellEntity
where
facadeChar (EntityFacade _ d) = view defaultChar d
getDisplayGrid :: Scenario -> GameState -> [[PCell EntityFacade]]
getDisplayGrid myScenario gs =
getMapRectangle
mkFacade
(getContentAt worlds . mkCosmic)
boundingBox
where
worlds = view (landscape . multiWorld) gs
firstScenarioWorld = NE.head $ view scenarioWorlds myScenario
worldArea = area firstScenarioWorld
upperLeftLocation = ul firstScenarioWorld
rawAreaDims = getAreaDimensions worldArea
areaDims =
if isEmpty rawAreaDims
then AreaDimensions 20 10
else rawAreaDims
lowerRightLocation = upperLeftToBottomRight areaDims upperLeftLocation
mkCosmic = Cosmic $ worldName firstScenarioWorld
boundingBox = (W.locToCoords upperLeftLocation, W.locToCoords lowerRightLocation)
renderScenarioMap :: FilePath -> IO [String]
renderScenarioMap fp = simpleErrorHandle $ do
(myScenario, (worldDefs, entities, recipes)) <- loadStandaloneScenario fp
appDataMap <- readAppData
nameGen <- initNameGenerator appDataMap
let gsc = GameStateConfig nameGen entities recipes worldDefs
gs <- sendIO $ scenarioToGameState myScenario emptyLaunchParams gsc
let grid = getDisplayGrid myScenario gs
return $ map (map getDisplayChar) grid
printScenarioMap :: [String] -> IO ()
printScenarioMap =
sendIO . mapM_ putStrLn