-- | The type of kinds of rooms, halls and passages.
module Game.LambdaHack.Content.PlaceKind
( PlaceKind(..), Cover(..), Fence(..)
, validateSinglePlaceKind, validateAllPlaceKind
) where
import Data.Text (Text)
import qualified Data.Text as T
import Game.LambdaHack.Common.Misc
import Game.LambdaHack.Content.TileKind (TileKind)
-- | Parameters for the generation of small areas within a dungeon level.
data PlaceKind = PlaceKind
{ psymbol :: !Char -- ^ a symbol
, pname :: !Text -- ^ short description
, pfreq :: !(Freqs PlaceKind) -- ^ frequency within groups
, prarity :: !Rarity -- ^ rarity on given depths
, pcover :: !Cover -- ^ how to fill whole place based on the corner
, pfence :: !Fence -- ^ whether to fence place with solid border
, ptopLeft :: ![Text] -- ^ plan of the top-left corner of the place
, poverride :: ![(Char, GroupName TileKind)] -- ^ legend override
}
deriving Show -- No Eq and Ord to make extending it logically sound
-- | A method of filling the whole area (except for CVerbatim, which is just
-- placed in the middle of the area) by transforming a given corner.
data Cover =
CAlternate -- ^ reflect every other corner, overlapping 1 row and column
| CStretch -- ^ fill symmetrically 4 corners and stretch their borders
| CReflect -- ^ tile separately and symmetrically quarters of the place
| CVerbatim -- ^ just build the given interior, without filling the area
deriving (Show, Eq)
-- | The choice of a fence type for the place.
data Fence =
FWall -- ^ put a solid wall fence around the place
| FFloor -- ^ leave an empty space, like the rooms floor
| FGround -- ^ leave an empty space, like the caves ground
| FNone -- ^ skip the fence and fill all with the place proper
deriving (Show, Eq)
-- TODO: Verify that places are fully accessible from any entrace on the fence
-- that is at least 4 tiles distant from the edges, if the place is big enough,
-- (unless the place has FNone fence, in which case the entrance is
-- at the outer tiles of the place).
-- TODO: (spans multiple contents) Check that all symbols in place plans
-- are present in the legend.
-- | Catch invalid place kind definitions. In particular, verify that
-- the top-left corner map is rectangular and not empty.
validateSinglePlaceKind :: PlaceKind -> [Text]
validateSinglePlaceKind PlaceKind{..} =
let dxcorner = case ptopLeft of
[] -> 0
l : _ -> T.length l
in [ "top-left corner empty" | dxcorner == 0 ]
++ [ "top-left corner not rectangular"
| any (/= dxcorner) (map T.length ptopLeft) ]
++ validateRarity prarity
-- | Validate all place kinds. Currently always valid.
validateAllPlaceKind :: [PlaceKind] -> [Text]
validateAllPlaceKind _ = []