-
Notifications
You must be signed in to change notification settings - Fork 52
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
134 additions
and
117 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
{-# LANGUAGE OverloadedStrings #-} | ||
|
||
-- | | ||
-- SPDX-License-Identifier: BSD-3-Clause | ||
module Swarm.Game.Scenario.WorldPalette where | ||
|
||
import Control.Arrow (first) | ||
import Control.Lens hiding (from, (.=), (<.>)) | ||
import Data.Aeson.KeyMap (KeyMap) | ||
import Data.Aeson.KeyMap qualified as KM | ||
import Data.Map qualified as M | ||
import Data.Set qualified as Set | ||
import Data.Text (Text) | ||
import Data.Text qualified as T | ||
import Data.Tuple (swap) | ||
import Swarm.Game.Entity | ||
import Swarm.Game.Scenario.Cell | ||
import Swarm.Game.Scenario.EntityFacade | ||
import Swarm.Game.Scenario.RobotLookup | ||
import Swarm.Game.Terrain (TerrainType) | ||
import Swarm.Util.Yaml | ||
|
||
-- | A world palette maps characters to 'Cell' values. | ||
newtype WorldPalette e = WorldPalette | ||
{unPalette :: KeyMap (PCell e)} | ||
deriving (Eq, Show) | ||
|
||
instance FromJSONE (EntityMap, RobotMap) (WorldPalette Entity) where | ||
parseJSONE = withObjectE "palette" $ fmap WorldPalette . mapM parseJSONE | ||
|
||
type TerrainWith a = (TerrainType, Maybe a) | ||
|
||
cellToTerrainPair :: CellPaintDisplay -> TerrainWith EntityFacade | ||
cellToTerrainPair (Cell terrain maybeEntity _) = (terrain, maybeEntity) | ||
|
||
toCellPaintDisplay :: Cell -> CellPaintDisplay | ||
toCellPaintDisplay (Cell terrain maybeEntity r) = | ||
Cell terrain (mkFacade <$> maybeEntity) r | ||
|
||
toKey :: TerrainWith EntityFacade -> TerrainWith EntityName | ||
toKey = fmap $ fmap (\(EntityFacade eName _display) -> eName) | ||
|
||
-- | We want to identify all of the unique (terrain, entity facade) pairs. | ||
-- However, "EntityFacade" includes a "Display" record, which contains more | ||
-- fields than desirable for use as a unique key. | ||
-- Therefore, we extract just the entity name for use in a | ||
-- (terrain, entity name) key, and couple it with the original | ||
-- (terrain, entity facade) pair in a Map. | ||
getUniqueTerrainFacadePairs :: | ||
[[CellPaintDisplay]] -> | ||
M.Map (TerrainWith EntityName) (TerrainWith EntityFacade) | ||
getUniqueTerrainFacadePairs cellGrid = | ||
M.fromList $ concatMap (map genTuple) cellGrid | ||
where | ||
genTuple c = | ||
(toKey terrainEfd, terrainEfd) | ||
where | ||
terrainEfd = cellToTerrainPair c | ||
|
||
constructPalette :: | ||
[(Char, TerrainWith EntityFacade)] -> | ||
KM.KeyMap CellPaintDisplay | ||
constructPalette mappedPairs = | ||
KM.fromMapText terrainEntityPalette | ||
where | ||
g (terrain, maybeEfd) = Cell terrain maybeEfd [] | ||
terrainEntityPalette = M.fromList $ map (bimap T.singleton g) mappedPairs | ||
|
||
constructWorldMap :: | ||
[(Char, TerrainWith EntityFacade)] -> | ||
[[CellPaintDisplay]] -> | ||
Text | ||
constructWorldMap mappedPairs = | ||
T.unlines . map (T.pack . map renderMapCell) | ||
where | ||
invertedMappedPairs = map (swap . fmap toKey) mappedPairs | ||
|
||
renderMapCell c = | ||
-- NOTE: This lookup should never fail | ||
M.findWithDefault (error "Palette lookup failed!") k $ | ||
M.fromList invertedMappedPairs | ||
where | ||
k = toKey $ cellToTerrainPair c | ||
|
||
-- | All alphanumeric characters. These are used as supplemental | ||
-- map placeholders in case a pre-existing display character is | ||
-- not available to re-use. | ||
genericCharacterPool :: Set.Set Char | ||
genericCharacterPool = Set.fromList $ ['A' .. 'Z'] <> ['a' .. 'z'] <> ['0' .. '9'] | ||
|
||
-- | Note that display characters are not unique | ||
-- across different entities! However, the palette KeyMap | ||
-- as a conveyance serves to dedupe them. | ||
prepForJson :: | ||
WorldPalette EntityFacade -> | ||
[[CellPaintDisplay]] -> | ||
(Text, KM.KeyMap CellPaintDisplay) | ||
prepForJson (WorldPalette suggestedPalette) cellGrid = | ||
(constructWorldMap mappedPairs cellGrid, constructPalette mappedPairs) | ||
where | ||
preassignments :: [(Char, TerrainWith EntityFacade)] | ||
preassignments = | ||
map (first T.head . fmap cellToTerrainPair) $ | ||
M.toList $ | ||
KM.toMapText suggestedPalette | ||
|
||
entityCells :: M.Map (TerrainWith EntityName) (TerrainWith EntityFacade) | ||
entityCells = getUniqueTerrainFacadePairs cellGrid | ||
|
||
unassignedCells :: M.Map (TerrainWith EntityName) (TerrainWith EntityFacade) | ||
unassignedCells = | ||
M.withoutKeys entityCells $ | ||
Set.fromList $ | ||
map (toKey . snd) preassignments | ||
|
||
unassignedCharacters :: Set.Set Char | ||
unassignedCharacters = | ||
-- TODO (#1149): How can we efficiently use the Unicode categories (in "Data.Char") | ||
-- to generate this pool? | ||
Set.difference genericCharacterPool $ | ||
Set.fromList $ | ||
map fst preassignments | ||
|
||
newlyAssignedPairs :: [(Char, TerrainWith EntityFacade)] | ||
newlyAssignedPairs = zip (Set.toList unassignedCharacters) $ M.elems unassignedCells | ||
|
||
mappedPairs = preassignments <> newlyAssignedPairs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters