Skip to content

Commit

Permalink
Parameterize scenario datatypes (#903)
Browse files Browse the repository at this point in the history
Towards #873

## Motivation

The `Entity` datatype has a fair amount of state and extra fields that are not relevant to serializing a scenario (in particular, a world map) to a file.

In this PR, the `Cell` record is renamed to `PCell` (representing "Parameterized Cell"), replacing `Entity` with a type parameter.  This permits the introduction of a trimmed-down `Entity` type for the purpose of serialization.  This lightweight type can also be a reliable `Map` key.

A type alias `Cell` is created with the original `Entity` type as a parameter.

The `WorldDescription` and `WorldPalette` are likewise parameterized on the `Cell` type.
  • Loading branch information
kostmo authored Dec 20, 2022
1 parent 52a63c9 commit aa6b9f2
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 13 deletions.
6 changes: 4 additions & 2 deletions src/Swarm/Game/Scenario.hs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ module Swarm.Game.Scenario (
objectiveCondition,

-- * WorldDescription
Cell (..),
WorldDescription (..),
PCell (..),
Cell,
PWorldDescription (..),
WorldDescription,
IndexedTRobot,

-- * Scenario
Expand Down
13 changes: 10 additions & 3 deletions src/Swarm/Game/Scenario/Cell.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
{-# LANGUAGE OverloadedStrings #-}

module Swarm.Game.Scenario.Cell (
Cell (..),
PCell (..),
Cell,
) where

import Control.Lens hiding (from, (<.>))
Expand All @@ -22,13 +23,19 @@ import Swarm.Util.Yaml

-- | A single cell in a world map, which contains a terrain value,
-- and optionally an entity and robot.
data Cell = Cell
-- It is parameterized on the Entity type to facilitate less
-- stateful versions of the Entity type in rendering scenario data.
data PCell e = Cell
{ cellTerrain :: TerrainType
, cellEntity :: Maybe Entity
, cellEntity :: Maybe e
, cellRobots :: [IndexedTRobot]
}
deriving (Eq, Show)

-- | A single cell in a world map, which contains a terrain value,
-- and optionally an entity and robot.
type Cell = PCell Entity

-- | Parse a tuple such as @[grass, rock, base]@ into a 'Cell'. The
-- entity and robot, if present, are immediately looked up and
-- converted into 'Entity' and 'TRobot' values. If they are not
Expand Down
20 changes: 12 additions & 8 deletions src/Swarm/Game/Scenario/WorldDescription.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,27 @@ import Witch (into)
------------------------------------------------------------

-- | A world palette maps characters to 'Cell' values.
newtype WorldPalette = WorldPalette
{unPalette :: KeyMap Cell}
newtype WorldPalette e = WorldPalette
{unPalette :: KeyMap (PCell e)}
deriving (Eq, Show)

instance FromJSONE (EntityMap, RobotMap) WorldPalette where
instance FromJSONE (EntityMap, RobotMap) (WorldPalette Entity) where
parseJSONE = withObjectE "palette" $ fmap WorldPalette . mapM parseJSONE

-- | A description of a world parsed from a YAML file.
data WorldDescription = WorldDescription
{ defaultTerrain :: Maybe Cell
-- This type is parameterized to accommodate Cells that
-- utilize a less stateful Entity type.
data PWorldDescription e = WorldDescription
{ defaultTerrain :: Maybe (PCell e)
, offsetOrigin :: Bool
, palette :: WorldPalette
, palette :: WorldPalette e
, ul :: Location
, area :: [[Cell]]
, area :: [[PCell e]]
}
deriving (Eq, Show)

type WorldDescription = PWorldDescription Entity

instance FromJSONE (EntityMap, RobotMap) WorldDescription where
parseJSONE = withObjectE "world description" $ \v -> do
pal <- v ..:? "palette" ..!= WorldPalette mempty
Expand All @@ -52,7 +56,7 @@ instance FromJSONE (EntityMap, RobotMap) WorldDescription where
-- string into a nested list of 'Cell' values by looking up each
-- character in the palette, failing if any character in the raw map
-- is not contained in the palette.
paintMap :: MonadFail m => WorldPalette -> Text -> m [[Cell]]
paintMap :: MonadFail m => WorldPalette e -> Text -> m [[PCell e]]
paintMap pal = traverse (traverse toCell . into @String) . T.lines
where
toCell c = case KeyMap.lookup (Key.fromString [c]) (unPalette pal) of
Expand Down

0 comments on commit aa6b9f2

Please sign in to comment.