{-# LANGUAGE DeriveGeneric #-}
-- | The type of kinds of terrain tiles.
module Game.LambdaHack.Content.TileKind
  ( TileKind(..), Feature(..)
  , makeData
  , isUknownSpace, unknownId
  , isSuspectKind, isOpenableKind, isClosableKind
  , talterForStairs, floorSymbol
#ifdef EXPOSE_INTERNAL
    -- * Internal operations
  , validateSingle, validateAll
  , validateDups, hardwiredTileGroups
#endif
  ) where

import Prelude ()

import Game.LambdaHack.Core.Prelude

import           Control.DeepSeq
import           Data.Binary
import qualified Data.Char as Char
import           Data.Hashable
import           GHC.Generics (Generic)

import Game.LambdaHack.Content.ItemKind (ItemKind)
import Game.LambdaHack.Definition.Color
import Game.LambdaHack.Definition.ContentData
import Game.LambdaHack.Definition.Defs

-- | The type of kinds of terrain tiles. See @Tile.hs@ for explanation
-- of the absence of a corresponding type @Tile@ that would hold
-- particular concrete tiles in the dungeon.
-- Note that tile names (and any other content names) should not be plural
-- (that would lead to "a stairs"), so "road with cobblestones" is fine,
-- but "granite cobblestones" is wrong.
--
-- Tile kind for unknown space has the minimal @ContentId@ index.
-- The @talter@ for unknown space is @1@ and no other tile kind has that value.
data TileKind = TileKind
  { TileKind -> Char
tsymbol  :: Char         -- ^ map symbol
  , TileKind -> Text
tname    :: Text         -- ^ short description
  , TileKind -> Freqs TileKind
tfreq    :: Freqs TileKind  -- ^ frequency within groups
  , TileKind -> Color
tcolor   :: Color        -- ^ map color
  , TileKind -> Color
tcolor2  :: Color        -- ^ map color when not in FOV
  , TileKind -> Word8
talter   :: Word8        -- ^ minimal skill needed to alter the tile
  , TileKind -> [Feature]
tfeature :: [Feature]    -- ^ properties
  }
  deriving Int -> TileKind -> ShowS
[TileKind] -> ShowS
TileKind -> String
(Int -> TileKind -> ShowS)
-> (TileKind -> String) -> ([TileKind] -> ShowS) -> Show TileKind
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TileKind] -> ShowS
$cshowList :: [TileKind] -> ShowS
show :: TileKind -> String
$cshow :: TileKind -> String
showsPrec :: Int -> TileKind -> ShowS
$cshowsPrec :: Int -> TileKind -> ShowS
Show  -- No Eq and Ord to make extending logically sound

-- | All possible terrain tile features.
data Feature =
    Embed (GroupName ItemKind)
      -- ^ initially an item of this group is embedded;
      --   we assume the item has effects and is supposed to be triggered
  | OpenTo (GroupName TileKind)
      -- ^ goes from a closed to (randomly closed or) open tile when altered
  | CloseTo (GroupName TileKind)
      -- ^ goes from an open to (randomly opened or) closed tile when altered
  | ChangeTo (GroupName TileKind)
      -- ^ alters tile, but does not change walkability
  | HideAs (GroupName TileKind)
      -- ^ when hidden, looks as the unique tile of the group
  | BuildAs (GroupName TileKind)
      -- ^ when generating, may be transformed to the unique tile of the group
  | RevealAs (GroupName TileKind)
      -- ^ when generating in opening, can be revealed to belong to the group
  | ObscureAs (GroupName TileKind)
      -- ^ when generating in solid wall, can be revealed to belong to the group
  | Walkable             -- ^ actors can walk through
  | Clear                -- ^ actors can see through
  | Dark                 -- ^ is not lit with an ambient light
  | OftenItem            -- ^ initial items often generated there
  | VeryOftenItem        -- ^ initial items very often generated there
  | OftenActor           -- ^ initial actors often generated there
  | NoItem               -- ^ no items ever generated there
  | NoActor              -- ^ no actors ever generated there
  | ConsideredByAI       -- ^ even if otherwise uninteresting, taken into
                         --   account for triggering by AI
  | Trail                -- ^ used for visible trails throughout the level
  | Spice                -- ^ in place normal legend and in override,
                         --   don't roll a tile kind only once per place,
                         --   but roll for each position; one non-spicy
                         --   (according to frequencies of non-spicy) and
                         --   at most one spicy (according to their frequencies)
                         --   is rolled per place and then, once for each
                         --   position, one of the two is semi-randomly chosen
                         --   (according to their individual frequencies only)
  deriving (Int -> Feature -> ShowS
[Feature] -> ShowS
Feature -> String
(Int -> Feature -> ShowS)
-> (Feature -> String) -> ([Feature] -> ShowS) -> Show Feature
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Feature] -> ShowS
$cshowList :: [Feature] -> ShowS
show :: Feature -> String
$cshow :: Feature -> String
showsPrec :: Int -> Feature -> ShowS
$cshowsPrec :: Int -> Feature -> ShowS
Show, Feature -> Feature -> Bool
(Feature -> Feature -> Bool)
-> (Feature -> Feature -> Bool) -> Eq Feature
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Feature -> Feature -> Bool
$c/= :: Feature -> Feature -> Bool
== :: Feature -> Feature -> Bool
$c== :: Feature -> Feature -> Bool
Eq, Eq Feature
Eq Feature =>
(Feature -> Feature -> Ordering)
-> (Feature -> Feature -> Bool)
-> (Feature -> Feature -> Bool)
-> (Feature -> Feature -> Bool)
-> (Feature -> Feature -> Bool)
-> (Feature -> Feature -> Feature)
-> (Feature -> Feature -> Feature)
-> Ord Feature
Feature -> Feature -> Bool
Feature -> Feature -> Ordering
Feature -> Feature -> Feature
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Feature -> Feature -> Feature
$cmin :: Feature -> Feature -> Feature
max :: Feature -> Feature -> Feature
$cmax :: Feature -> Feature -> Feature
>= :: Feature -> Feature -> Bool
$c>= :: Feature -> Feature -> Bool
> :: Feature -> Feature -> Bool
$c> :: Feature -> Feature -> Bool
<= :: Feature -> Feature -> Bool
$c<= :: Feature -> Feature -> Bool
< :: Feature -> Feature -> Bool
$c< :: Feature -> Feature -> Bool
compare :: Feature -> Feature -> Ordering
$ccompare :: Feature -> Feature -> Ordering
$cp1Ord :: Eq Feature
Ord, (forall x. Feature -> Rep Feature x)
-> (forall x. Rep Feature x -> Feature) -> Generic Feature
forall x. Rep Feature x -> Feature
forall x. Feature -> Rep Feature x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Feature x -> Feature
$cfrom :: forall x. Feature -> Rep Feature x
Generic)

instance Binary Feature

instance Hashable Feature

instance NFData Feature

-- | Validate a single tile kind.
validateSingle :: TileKind -> [Text]
validateSingle :: TileKind -> [Text]
validateSingle t :: TileKind
t@TileKind{..} =
  [ "suspect tile is walkable" | Feature
Walkable Feature -> [Feature] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Feature]
tfeature
                                 Bool -> Bool -> Bool
&& TileKind -> Bool
isSuspectKind TileKind
t ]
  [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [ "openable tile is open" | Feature
Walkable Feature -> [Feature] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Feature]
tfeature
                                 Bool -> Bool -> Bool
&& TileKind -> Bool
isOpenableKind TileKind
t ]
  [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [ "closable tile is closed" | Feature
Walkable Feature -> [Feature] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [Feature]
tfeature
                                   Bool -> Bool -> Bool
&& TileKind -> Bool
isClosableKind TileKind
t ]
  [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [ "walkable tile is considered for triggering by AI"
     | Feature
Walkable Feature -> [Feature] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Feature]
tfeature
       Bool -> Bool -> Bool
&& Feature
ConsideredByAI Feature -> [Feature] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Feature]
tfeature ]
  [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [ "trail tile not walkable" | Feature
Walkable Feature -> [Feature] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [Feature]
tfeature
                                   Bool -> Bool -> Bool
&& Feature
Trail Feature -> [Feature] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Feature]
tfeature ]
  [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [ "OftenItem and NoItem on a tile" | Feature
OftenItem Feature -> [Feature] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Feature]
tfeature
                                          Bool -> Bool -> Bool
&& Feature
NoItem Feature -> [Feature] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Feature]
tfeature ]
  [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [ "OftenActor and NoActor on a tile" | Feature
OftenItem Feature -> [Feature] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Feature]
tfeature
                                            Bool -> Bool -> Bool
&& Feature
NoItem Feature -> [Feature] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Feature]
tfeature ]
  [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ (let f :: Feature -> Bool
          f :: Feature -> Bool
f OpenTo{} = Bool
True
          f CloseTo{} = Bool
True
          f ChangeTo{} = Bool
True
          f _ = Bool
False
          ts :: [Feature]
ts = (Feature -> Bool) -> [Feature] -> [Feature]
forall a. (a -> Bool) -> [a] -> [a]
filter Feature -> Bool
f [Feature]
tfeature
      in [ "more than one OpenTo, CloseTo and ChangeTo specification"
         | [Feature] -> Int
forall a. [a] -> Int
length [Feature]
ts Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> 1 ])
  [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ (let f :: Feature -> Bool
          f :: Feature -> Bool
f HideAs{} = Bool
True
          f _ = Bool
False
          ts :: [Feature]
ts = (Feature -> Bool) -> [Feature] -> [Feature]
forall a. (a -> Bool) -> [a] -> [a]
filter Feature -> Bool
f [Feature]
tfeature
      in ["more than one HideAs specification" | [Feature] -> Int
forall a. [a] -> Int
length [Feature]
ts Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> 1])
  [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ (let f :: Feature -> Bool
          f :: Feature -> Bool
f BuildAs{} = Bool
True
          f _ = Bool
False
          ts :: [Feature]
ts = (Feature -> Bool) -> [Feature] -> [Feature]
forall a. (a -> Bool) -> [a] -> [a]
filter Feature -> Bool
f [Feature]
tfeature
      in ["more than one BuildAs specification" | [Feature] -> Int
forall a. [a] -> Int
length [Feature]
ts Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> 1])
  [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ (Feature -> [Text]) -> [Feature] -> [Text]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (TileKind -> Feature -> [Text]
validateDups TileKind
t)
       [ Feature
Walkable, Feature
Clear, Feature
Dark, Feature
OftenItem, Feature
OftenActor, Feature
NoItem, Feature
NoActor
       , Feature
ConsideredByAI, Feature
Trail, Feature
Spice ]

validateDups :: TileKind -> Feature -> [Text]
validateDups :: TileKind -> Feature -> [Text]
validateDups TileKind{..} feat :: Feature
feat =
  let ts :: [Feature]
ts = (Feature -> Bool) -> [Feature] -> [Feature]
forall a. (a -> Bool) -> [a] -> [a]
filter (Feature -> Feature -> Bool
forall a. Eq a => a -> a -> Bool
== Feature
feat) [Feature]
tfeature
  in ["more than one" Text -> Text -> Text
<+> Feature -> Text
forall a. Show a => a -> Text
tshow Feature
feat Text -> Text -> Text
<+> "specification" | [Feature] -> Int
forall a. [a] -> Int
length [Feature]
ts Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> 1]

-- | Validate all tile kinds.
--
-- We don't check it any more, but if tiles look the same on the map
-- (symbol and color), their substantial features should be the same, too,
-- unless there is a good reason they shouldn't. Otherwise the player has
-- to inspect manually all the tiles with this look to see if any is special.
-- This tends to be tedious. Note that tiles may freely differ wrt text blurb,
-- dungeon generation rules, AI preferences, etc., whithout causing the tedium.
validateAll :: ContentData ItemKind -> [TileKind] -> ContentData TileKind
            -> [Text]
validateAll :: ContentData ItemKind
-> [TileKind] -> ContentData TileKind -> [Text]
validateAll coitem :: ContentData ItemKind
coitem content :: [TileKind]
content cotile :: ContentData TileKind
cotile =
  let g :: Feature -> Maybe (GroupName TileKind)
      g :: Feature -> Maybe (GroupName TileKind)
g (OpenTo grp :: GroupName TileKind
grp) = GroupName TileKind -> Maybe (GroupName TileKind)
forall a. a -> Maybe a
Just GroupName TileKind
grp
      g (CloseTo grp :: GroupName TileKind
grp) = GroupName TileKind -> Maybe (GroupName TileKind)
forall a. a -> Maybe a
Just GroupName TileKind
grp
      g (ChangeTo grp :: GroupName TileKind
grp) = GroupName TileKind -> Maybe (GroupName TileKind)
forall a. a -> Maybe a
Just GroupName TileKind
grp
      g (HideAs grp :: GroupName TileKind
grp) = GroupName TileKind -> Maybe (GroupName TileKind)
forall a. a -> Maybe a
Just GroupName TileKind
grp
      g (BuildAs grp :: GroupName TileKind
grp) = GroupName TileKind -> Maybe (GroupName TileKind)
forall a. a -> Maybe a
Just GroupName TileKind
grp
      g (RevealAs grp :: GroupName TileKind
grp) = GroupName TileKind -> Maybe (GroupName TileKind)
forall a. a -> Maybe a
Just GroupName TileKind
grp
      g (ObscureAs grp :: GroupName TileKind
grp) = GroupName TileKind -> Maybe (GroupName TileKind)
forall a. a -> Maybe a
Just GroupName TileKind
grp
      g _ = Maybe (GroupName TileKind)
forall a. Maybe a
Nothing
      missingTileGroups :: [(Text, [GroupName TileKind])]
missingTileGroups =
        [ (TileKind -> Text
tname TileKind
k, [GroupName TileKind]
absGroups)
        | TileKind
k <- [TileKind]
content
        , let grps :: [GroupName TileKind]
grps = (Feature -> Maybe (GroupName TileKind))
-> [Feature] -> [GroupName TileKind]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe Feature -> Maybe (GroupName TileKind)
g ([Feature] -> [GroupName TileKind])
-> [Feature] -> [GroupName TileKind]
forall a b. (a -> b) -> a -> b
$ TileKind -> [Feature]
tfeature TileKind
k
              absGroups :: [GroupName TileKind]
absGroups = (GroupName TileKind -> Bool)
-> [GroupName TileKind] -> [GroupName TileKind]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool)
-> (GroupName TileKind -> Bool) -> GroupName TileKind -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ContentData TileKind -> GroupName TileKind -> Bool
forall a. ContentData a -> GroupName a -> Bool
omemberGroup ContentData TileKind
cotile) [GroupName TileKind]
grps
        , Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [GroupName TileKind] -> Bool
forall a. [a] -> Bool
null [GroupName TileKind]
absGroups
        ]
      h :: Feature -> Maybe (GroupName ItemKind)
      h :: Feature -> Maybe (GroupName ItemKind)
h (Embed grp :: GroupName ItemKind
grp) = GroupName ItemKind -> Maybe (GroupName ItemKind)
forall a. a -> Maybe a
Just GroupName ItemKind
grp
      h _ = Maybe (GroupName ItemKind)
forall a. Maybe a
Nothing
      missingItemGroups :: [(Text, [GroupName ItemKind])]
missingItemGroups =
        [ (TileKind -> Text
tname TileKind
k, [GroupName ItemKind]
absGroups)
        | TileKind
k <- [TileKind]
content
        , let grps :: [GroupName ItemKind]
grps = (Feature -> Maybe (GroupName ItemKind))
-> [Feature] -> [GroupName ItemKind]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe Feature -> Maybe (GroupName ItemKind)
h ([Feature] -> [GroupName ItemKind])
-> [Feature] -> [GroupName ItemKind]
forall a b. (a -> b) -> a -> b
$ TileKind -> [Feature]
tfeature TileKind
k
              absGroups :: [GroupName ItemKind]
absGroups = (GroupName ItemKind -> Bool)
-> [GroupName ItemKind] -> [GroupName ItemKind]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool)
-> (GroupName ItemKind -> Bool) -> GroupName ItemKind -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ContentData ItemKind -> GroupName ItemKind -> Bool
forall a. ContentData a -> GroupName a -> Bool
omemberGroup ContentData ItemKind
coitem) [GroupName ItemKind]
grps
        , Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [GroupName ItemKind] -> Bool
forall a. [a] -> Bool
null [GroupName ItemKind]
absGroups
        ]
      missingHardwiredGroups :: [GroupName TileKind]
missingHardwiredGroups =
        (GroupName TileKind -> Bool)
-> [GroupName TileKind] -> [GroupName TileKind]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool)
-> (GroupName TileKind -> Bool) -> GroupName TileKind -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ContentData TileKind -> GroupName TileKind -> Bool
forall a. ContentData a -> GroupName a -> Bool
omemberGroup ContentData TileKind
cotile) [GroupName TileKind]
hardwiredTileGroups
  in [ "unknown tile (the first) should be the unknown one"
     | TileKind -> Word8
talter ([TileKind] -> TileKind
forall a. [a] -> a
head [TileKind]
content) Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
/= 1 Bool -> Bool -> Bool
|| TileKind -> Text
tname ([TileKind] -> TileKind
forall a. [a] -> a
head [TileKind]
content) Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
/= "unknown space" ]
     [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [ "no tile other than the unknown (the first) should require skill 1"
        | (TileKind -> Bool) -> [TileKind] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (\tk :: TileKind
tk -> TileKind -> Word8
talter TileKind
tk Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== 1) ([TileKind] -> [TileKind]
forall a. [a] -> [a]
tail [TileKind]
content) ]
     [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [ "only unknown tile may have talter 1"
        | (TileKind -> Bool) -> [TileKind] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any ((Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== 1) (Word8 -> Bool) -> (TileKind -> Word8) -> TileKind -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TileKind -> Word8
talter) ([TileKind] -> Bool) -> [TileKind] -> Bool
forall a b. (a -> b) -> a -> b
$ [TileKind] -> [TileKind]
forall a. [a] -> [a]
tail [TileKind]
content ]
     [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [ "mentioned tile groups not in content:" Text -> Text -> Text
<+> [(Text, [GroupName TileKind])] -> Text
forall a. Show a => a -> Text
tshow [(Text, [GroupName TileKind])]
missingTileGroups
        | Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [(Text, [GroupName TileKind])] -> Bool
forall a. [a] -> Bool
null [(Text, [GroupName TileKind])]
missingTileGroups ]
     [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [ "embedded item groups not in content:" Text -> Text -> Text
<+> [(Text, [GroupName ItemKind])] -> Text
forall a. Show a => a -> Text
tshow [(Text, [GroupName ItemKind])]
missingItemGroups
        | Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [(Text, [GroupName ItemKind])] -> Bool
forall a. [a] -> Bool
null [(Text, [GroupName ItemKind])]
missingItemGroups ]
     [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [ "hardwired groups not in content:" Text -> Text -> Text
<+> [GroupName TileKind] -> Text
forall a. Show a => a -> Text
tshow [GroupName TileKind]
missingHardwiredGroups
        | Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [GroupName TileKind] -> Bool
forall a. [a] -> Bool
null [GroupName TileKind]
missingHardwiredGroups ]

hardwiredTileGroups :: [GroupName TileKind]
hardwiredTileGroups :: [GroupName TileKind]
hardwiredTileGroups =
  [ "unknown space", "legendLit", "legendDark", "unknown outer fence"
  , "basic outer fence" ]

isUknownSpace :: ContentId TileKind -> Bool
{-# INLINE isUknownSpace #-}
isUknownSpace :: ContentId TileKind -> Bool
isUknownSpace tt :: ContentId TileKind
tt = Word16 -> ContentId TileKind
forall c. Word16 -> ContentId c
toContentId 0 ContentId TileKind -> ContentId TileKind -> Bool
forall a. Eq a => a -> a -> Bool
== ContentId TileKind
tt

unknownId :: ContentId TileKind
{-# INLINE unknownId #-}
unknownId :: ContentId TileKind
unknownId = Word16 -> ContentId TileKind
forall c. Word16 -> ContentId c
toContentId 0

isSuspectKind :: TileKind -> Bool
isSuspectKind :: TileKind -> Bool
isSuspectKind t :: TileKind
t =
  let getTo :: Feature -> Bool
getTo RevealAs{} = Bool
True
      getTo ObscureAs{} = Bool
True
      getTo _ = Bool
False
  in (Feature -> Bool) -> [Feature] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Feature -> Bool
getTo ([Feature] -> Bool) -> [Feature] -> Bool
forall a b. (a -> b) -> a -> b
$ TileKind -> [Feature]
tfeature TileKind
t

isOpenableKind :: TileKind -> Bool
isOpenableKind :: TileKind -> Bool
isOpenableKind t :: TileKind
t =
  let getTo :: Feature -> Bool
getTo OpenTo{} = Bool
True
      getTo _ = Bool
False
  in (Feature -> Bool) -> [Feature] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Feature -> Bool
getTo ([Feature] -> Bool) -> [Feature] -> Bool
forall a b. (a -> b) -> a -> b
$ TileKind -> [Feature]
tfeature TileKind
t

isClosableKind :: TileKind -> Bool
isClosableKind :: TileKind -> Bool
isClosableKind t :: TileKind
t =
  let getTo :: Feature -> Bool
getTo CloseTo{} = Bool
True
      getTo _ = Bool
False
  in (Feature -> Bool) -> [Feature] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Feature -> Bool
getTo ([Feature] -> Bool) -> [Feature] -> Bool
forall a b. (a -> b) -> a -> b
$ TileKind -> [Feature]
tfeature TileKind
t

talterForStairs :: Word8
talterForStairs :: Word8
talterForStairs = 3

floorSymbol :: Char.Char
floorSymbol :: Char
floorSymbol = Int -> Char
Char.chr 183

-- Alter skill schema:
-- 0  can be altered by everybody (escape)
-- 1  unknown only
-- 2  openable and suspect
-- 3  stairs
-- 4  closable
-- 5  changeable (e.g., caches)
-- 10  weak obstructions
-- 50  considerable obstructions
-- 100  walls
-- maxBound  impenetrable walls, etc., can never be altered

makeData :: ContentData ItemKind -> [TileKind] -> ContentData TileKind
makeData :: ContentData ItemKind -> [TileKind] -> ContentData TileKind
makeData coitem :: ContentData ItemKind
coitem =
  String
-> (TileKind -> Text)
-> (TileKind -> Freqs TileKind)
-> (TileKind -> [Text])
-> ([TileKind] -> ContentData TileKind -> [Text])
-> [TileKind]
-> ContentData TileKind
forall c.
Show c =>
String
-> (c -> Text)
-> (c -> Freqs c)
-> (c -> [Text])
-> ([c] -> ContentData c -> [Text])
-> [c]
-> ContentData c
makeContentData "TileKind" TileKind -> Text
tname TileKind -> Freqs TileKind
tfreq TileKind -> [Text]
validateSingle (ContentData ItemKind
-> [TileKind] -> ContentData TileKind -> [Text]
validateAll ContentData ItemKind
coitem)