    -- | The type of tile kinds. Every terrain tile in the game is
    -- an instantiated tile kind.
    module Game.LambdaHack.Content.TileKind
      ( pattern S_UNKNOWN_SPACE, pattern S_UNKNOWN_OUTER_FENCE, pattern S_BASIC_OUTER_FENCE, pattern AQUATIC
      , TileKind(..), ProjectileTriggers(..), Feature(..)
      , makeData
      , isUknownSpace, unknownId
      , isSuspectKind, isOpenableKind, isClosableKind
      , talterForStairs, floorSymbol
      , mandatoryGroups, mandatoryGroupsSingleton
    #ifdef EXPOSE_INTERNAL
        -- * Internal operations
      , validateSingle, validateAll, validateDups
    #endif
      ) where

    import Prelude ()

    import Game.LambdaHack.Core.Prelude

    import Data.Word (Word8)

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

    -- | 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 activate embeds
                                 --   and, in case of big actors not standing on
                                 --   the tile, to alter the tile in any way
      , TileKind -> [Feature]
    tfeature :: [Feature]    -- ^ properties; order matters
      }
      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
    $cshowsPrec :: Int -> TileKind -> ShowS
    showsPrec :: Int -> TileKind -> ShowS
    $cshow :: TileKind -> String
    show :: TileKind -> String
    $cshowList :: [TileKind] -> ShowS
    showList :: [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 closed or open tile when altered
      | CloseTo (GroupName TileKind)
          -- ^ goes from an open to open or closed tile when altered
      | ChangeTo (GroupName TileKind)
          -- ^ alters tile, but does not change walkability
      | OpenWith ProjectileTriggers
                 [(Int, GroupName ItemKind)] (GroupName TileKind)
          -- ^ alters tile, as before, using up all listed items from the ground
          --   and equipment; the list never empty; for simplicity, such tiles
          --   are never taken into account when pathfinding
      | CloseWith ProjectileTriggers
                  [(Int, GroupName ItemKind)] (GroupName TileKind)
      | ChangeWith ProjectileTriggers
                   [(Int, GroupName ItemKind)] (GroupName TileKind)
      | 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;
                             --   counterpart of @VeryOftenItem@ for dark places
      | 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
    $cshowsPrec :: Int -> Feature -> ShowS
    showsPrec :: Int -> Feature -> ShowS
    $cshow :: Feature -> String
    show :: Feature -> String
    $cshowList :: [Feature] -> ShowS
    showList :: [Feature] -> ShowS
    Show, Feature -> Feature -> Bool
    (Feature -> Feature -> Bool)
    -> (Feature -> Feature -> Bool) -> Eq Feature
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Feature -> Feature -> Bool
    == :: Feature -> Feature -> Bool
    $c/= :: Feature -> Feature -> Bool
    /= :: Feature -> Feature -> Bool
    Eq)

    -- | Marks whether projectiles are permitted to trigger the tile transformation
    -- action.
    data ProjectileTriggers = ProjYes | ProjNo
      deriving (Int -> ProjectileTriggers -> ShowS
    [ProjectileTriggers] -> ShowS
    ProjectileTriggers -> String
    (Int -> ProjectileTriggers -> ShowS)
    -> (ProjectileTriggers -> String)
    -> ([ProjectileTriggers] -> ShowS)
    -> Show ProjectileTriggers
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> ProjectileTriggers -> ShowS
    showsPrec :: Int -> ProjectileTriggers -> ShowS
    $cshow :: ProjectileTriggers -> String
    show :: ProjectileTriggers -> String
    $cshowList :: [ProjectileTriggers] -> ShowS
    showList :: [ProjectileTriggers] -> ShowS
    Show, ProjectileTriggers -> ProjectileTriggers -> Bool
    (ProjectileTriggers -> ProjectileTriggers -> Bool)
    -> (ProjectileTriggers -> ProjectileTriggers -> Bool)
    -> Eq ProjectileTriggers
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: ProjectileTriggers -> ProjectileTriggers -> Bool
    == :: ProjectileTriggers -> ProjectileTriggers -> Bool
    $c/= :: ProjectileTriggers -> ProjectileTriggers -> Bool
    /= :: ProjectileTriggers -> ProjectileTriggers -> Bool
    Eq)

    -- | Validate a single tile kind.
    validateSingle :: TileKind -> [Text]
    validateSingle :: TileKind -> [Text]
    validateSingle t :: TileKind
    t@TileKind{Char
    Freqs TileKind
    [Feature]
    Word8
    Text
    Color
    tsymbol :: TileKind -> Char
    tname :: TileKind -> Text
    tfreq :: TileKind -> Freqs TileKind
    tcolor :: TileKind -> Color
    tcolor2 :: TileKind -> Color
    talter :: TileKind -> Word8
    tfeature :: TileKind -> [Feature]
    tsymbol :: Char
    tname :: Text
    tfreq :: Freqs TileKind
    tcolor :: Color
    tcolor2 :: Color
    talter :: Word8
    tfeature :: [Feature]
    ..} =
      [ Text
    "suspect tile is walkable" | Feature
    Walkable Feature -> [Feature] -> Bool
    forall a. Eq a => a -> [a] -> 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]
    ++ [ Text
    "openable tile is open" | Feature
    Walkable Feature -> [Feature] -> Bool
    forall a. Eq a => a -> [a] -> 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]
    ++ [ Text
    "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]
    ++ [ Text
    "walkable tile is considered for activating by AI"
         | Feature
    Walkable Feature -> [Feature] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [Feature]
    tfeature
           Bool -> Bool -> Bool
    && Feature
    ConsideredByAI Feature -> [Feature] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [Feature]
    tfeature ]
      [Text] -> [Text] -> [Text]
    forall a. [a] -> [a] -> [a]
    ++ [ Text
    "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 a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [Feature]
    tfeature ]
      [Text] -> [Text] -> [Text]
    forall a. [a] -> [a] -> [a]
    ++ [ Text
    "OftenItem and NoItem on a tile" | Feature
    OftenItem Feature -> [Feature] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [Feature]
    tfeature
                                              Bool -> Bool -> Bool
    && Feature
    NoItem Feature -> [Feature] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [Feature]
    tfeature ]
      [Text] -> [Text] -> [Text]
    forall a. [a] -> [a] -> [a]
    ++ [ Text
    "OftenActor and NoActor on a tile" | Feature
    OftenItem Feature -> [Feature] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [Feature]
    tfeature
                                                Bool -> Bool -> Bool
    && Feature
    NoItem Feature -> [Feature] -> Bool
    forall a. Eq a => a -> [a] -> 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 Feature
    _ = Bool
    False
              ts :: [Feature]
    ts = (Feature -> Bool) -> [Feature] -> [Feature]
    forall a. (a -> Bool) -> [a] -> [a]
    filter Feature -> Bool
    f [Feature]
    tfeature
          in [ Text
    "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
    > Int
    1 ])
      [Text] -> [Text] -> [Text]
    forall a. [a] -> [a] -> [a]
    ++ (let f :: Feature -> Bool
              f :: Feature -> Bool
    f HideAs{} = Bool
    True
              f Feature
    _ = Bool
    False
              ts :: [Feature]
    ts = (Feature -> Bool) -> [Feature] -> [Feature]
    forall a. (a -> Bool) -> [a] -> [a]
    filter Feature -> Bool
    f [Feature]
    tfeature
          in [Text
    "more than one HideAs specification" | [Feature] -> Int
    forall a. [a] -> Int
    length [Feature]
    ts Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > Int
    1])
      [Text] -> [Text] -> [Text]
    forall a. [a] -> [a] -> [a]
    ++ (let f :: Feature -> Bool
              f :: Feature -> Bool
    f BuildAs{} = Bool
    True
              f Feature
    _ = Bool
    False
              ts :: [Feature]
    ts = (Feature -> Bool) -> [Feature] -> [Feature]
    forall a. (a -> Bool) -> [a] -> [a]
    filter Feature -> Bool
    f [Feature]
    tfeature
          in [Text
    "more than one BuildAs specification" | [Feature] -> Int
    forall a. [a] -> Int
    length [Feature]
    ts Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > Int
    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
    VeryOftenItem, Feature
    OftenActor
           , Feature
    NoItem, Feature
    NoActor, Feature
    ConsideredByAI, Feature
    Trail, Feature
    Spice ]

    validateDups :: TileKind -> Feature -> [Text]
    validateDups :: TileKind -> Feature -> [Text]
    validateDups TileKind{Char
    Freqs TileKind
    [Feature]
    Word8
    Text
    Color
    tsymbol :: TileKind -> Char
    tname :: TileKind -> Text
    tfreq :: TileKind -> Freqs TileKind
    tcolor :: TileKind -> Color
    tcolor2 :: TileKind -> Color
    talter :: TileKind -> Word8
    tfeature :: TileKind -> [Feature]
    tsymbol :: Char
    tname :: Text
    tfreq :: Freqs TileKind
    tcolor :: Color
    tcolor2 :: Color
    talter :: Word8
    tfeature :: [Feature]
    ..} 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 [Text
    "more than one" Text -> Text -> Text
    <+> Feature -> Text
    forall a. Show a => a -> Text
    tshow Feature
    feat Text -> Text -> Text
    <+> Text
    "specification" | [Feature] -> Int
    forall a. [a] -> Int
    length [Feature]
    ts Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    > Int
    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 :: [TileKind] -> ContentData TileKind -> [Text]
    validateAll :: [TileKind] -> ContentData TileKind -> [Text]
    validateAll [TileKind]
    content ContentData TileKind
    cotile =
      let f :: Feature -> Bool
          f :: Feature -> Bool
    f HideAs{} = Bool
    True
          f BuildAs{} = Bool
    True
          f Feature
    _ = Bool
    False
          wrongGrooup :: TileKind -> GroupName TileKind -> Bool
    wrongGrooup TileKind
    k GroupName TileKind
    grp = Bool -> Bool
    not (ContentData TileKind -> GroupName TileKind -> Bool
    forall a. ContentData a -> GroupName a -> Bool
    oisSingletonGroup ContentData TileKind
    cotile GroupName TileKind
    grp)
                              Bool -> Bool -> Bool
    || Maybe Int -> Bool
    forall a. Maybe a -> Bool
    isJust (GroupName TileKind
    grp GroupName TileKind -> Freqs TileKind -> Maybe Int
    forall a b. Eq a => a -> [(a, b)] -> Maybe b
    `lookup` TileKind -> Freqs TileKind
    tfreq TileKind
    k)
          wrongFooAsGroups :: [GroupName TileKind]
    wrongFooAsGroups =
            [ GroupName TileKind
    cgroup
            | TileKind
    k <- [TileKind]
    content
            , let (GroupName TileKind
    cgroup, Bool
    notSingleton) = case (Feature -> Bool) -> [Feature] -> Maybe Feature
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
    find Feature -> Bool
    f (TileKind -> [Feature]
    tfeature TileKind
    k) of
                    Just (HideAs GroupName TileKind
    grp) | TileKind -> GroupName TileKind -> Bool
    wrongGrooup TileKind
    k GroupName TileKind
    grp -> (GroupName TileKind
    grp, Bool
    True)
                    Just (BuildAs GroupName TileKind
    grp) | TileKind -> GroupName TileKind -> Bool
    wrongGrooup TileKind
    k GroupName TileKind
    grp -> (GroupName TileKind
    grp, Bool
    True)
                    Maybe Feature
    _ -> (GroupName TileKind
    forall a. HasCallStack => a
    undefined, Bool
    False)
            , Bool
    notSingleton
            ]
      in [ Text
    "HideAs or BuildAs groups not singletons or point to themselves:"
           Text -> Text -> Text
    <+> [GroupName TileKind] -> Text
    forall a. Show a => a -> Text
    tshow [GroupName TileKind]
    wrongFooAsGroups
         | Bool -> Bool
    not (Bool -> Bool) -> Bool -> Bool
    forall a b. (a -> b) -> a -> b
    $ [GroupName TileKind] -> Bool
    forall a. [a] -> Bool
    null [GroupName TileKind]
    wrongFooAsGroups ]
         [Text] -> [Text] -> [Text]
    forall a. [a] -> [a] -> [a]
    ++ [ Text
    "unknown tile (the first) should be the unknown one"
            | TileKind -> Word8
    talter ([TileKind] -> TileKind
    forall a. HasCallStack => [a] -> a
    head [TileKind]
    content) Word8 -> Word8 -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Word8
    1
              Bool -> Bool -> Bool
    || TileKind -> Text
    tname ([TileKind] -> TileKind
    forall a. HasCallStack => [a] -> a
    head [TileKind]
    content) Text -> Text -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Text
    "unknown space" ]
         [Text] -> [Text] -> [Text]
    forall a. [a] -> [a] -> [a]
    ++ [ Text
    "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
    any (\TileKind
    tk -> TileKind -> Word8
    talter TileKind
    tk Word8 -> Word8 -> Bool
    forall a. Eq a => a -> a -> Bool
    == Word8
    1) ([TileKind] -> [TileKind]
    forall a. HasCallStack => [a] -> [a]
    tail [TileKind]
    content) ]

    -- * Mandatory item groups

    mandatoryGroupsSingleton :: [GroupName TileKind]
    mandatoryGroupsSingleton :: [GroupName TileKind]
    mandatoryGroupsSingleton =
           [GroupName TileKind
    S_UNKNOWN_SPACE, GroupName TileKind
    S_UNKNOWN_OUTER_FENCE, GroupName TileKind
    S_BASIC_OUTER_FENCE]

    pattern S_UNKNOWN_SPACE, S_UNKNOWN_OUTER_FENCE, S_BASIC_OUTER_FENCE :: GroupName TileKind

    mandatoryGroups :: [GroupName TileKind]
    mandatoryGroups :: [GroupName TileKind]
    mandatoryGroups = []

    pattern $mS_UNKNOWN_SPACE :: forall {r}. GroupName TileKind -> ((# #) -> r) -> ((# #) -> r) -> r
    $bS_UNKNOWN_SPACE :: GroupName TileKind
    S_UNKNOWN_SPACE = GroupName "unknown space"
    pattern $mS_UNKNOWN_OUTER_FENCE :: forall {r}. GroupName TileKind -> ((# #) -> r) -> ((# #) -> r) -> r
    $bS_UNKNOWN_OUTER_FENCE :: GroupName TileKind
    S_UNKNOWN_OUTER_FENCE = GroupName "unknown outer fence"
    pattern $mS_BASIC_OUTER_FENCE :: forall {r}. GroupName TileKind -> ((# #) -> r) -> ((# #) -> r) -> r
    $bS_BASIC_OUTER_FENCE :: GroupName TileKind
    S_BASIC_OUTER_FENCE = GroupName "basic outer fence"

    -- * Optional item groups

    pattern AQUATIC :: GroupName TileKind

    pattern $mAQUATIC :: forall {r}. GroupName TileKind -> ((# #) -> r) -> ((# #) -> r) -> r
    $bAQUATIC :: GroupName TileKind
    AQUATIC = GroupName "aquatic"

    isUknownSpace :: ContentId TileKind -> Bool
    {-# INLINE isUknownSpace #-}
    isUknownSpace :: ContentId TileKind -> Bool
    isUknownSpace ContentId TileKind
    tt = Word16 -> ContentId TileKind
    forall c. Word16 -> ContentId c
    toContentId Word16
    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 Word16
    0

    isSuspectKind :: TileKind -> Bool
    isSuspectKind :: TileKind -> Bool
    isSuspectKind TileKind
    t =
      let getTo :: Feature -> Bool
    getTo RevealAs{} = Bool
    True
          getTo ObscureAs{} = Bool
    True
          getTo Feature
    _ = 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 TileKind
    t =
      let getTo :: Feature -> Bool
    getTo OpenTo{} = Bool
    True
          getTo Feature
    _ = 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 TileKind
    t =
      let getTo :: Feature -> Bool
    getTo CloseTo{} = Bool
    True
          getTo Feature
    _ = 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 = Word8
    3

    floorSymbol :: Char
    floorSymbol :: Char
    floorSymbol = Char
    '·'  -- '\x00B7'

    -- 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 :: [TileKind] -> [GroupName TileKind] -> [GroupName TileKind]
             -> ContentData TileKind
    makeData :: [TileKind]
    -> [GroupName TileKind]
    -> [GroupName TileKind]
    -> ContentData TileKind
    makeData [TileKind]
    content [GroupName TileKind]
    groupNamesAtMostOne [GroupName TileKind]
    groupNames =
      String
    -> (TileKind -> Text)
    -> (TileKind -> Freqs TileKind)
    -> (TileKind -> [Text])
    -> ([TileKind] -> ContentData TileKind -> [Text])
    -> [TileKind]
    -> [GroupName TileKind]
    -> [GroupName TileKind]
    -> ContentData TileKind
    forall c.
    Show c =>
    String
    -> (c -> Text)
    -> (c -> Freqs c)
    -> (c -> [Text])
    -> ([c] -> ContentData c -> [Text])
    -> [c]
    -> [GroupName c]
    -> [GroupName c]
    -> ContentData c
    makeContentData String
    "TileKind" TileKind -> Text
    tname TileKind -> Freqs TileKind
    tfreq TileKind -> [Text]
    validateSingle [TileKind] -> ContentData TileKind -> [Text]
    validateAll [TileKind]
    content
                      ([GroupName TileKind]
    mandatoryGroupsSingleton [GroupName TileKind]
    -> [GroupName TileKind] -> [GroupName TileKind]
    forall a. [a] -> [a] -> [a]
    ++ [GroupName TileKind]
    groupNamesAtMostOne)
                      ([GroupName TileKind]
    mandatoryGroups [GroupName TileKind]
    -> [GroupName TileKind] -> [GroupName TileKind]
    forall a. [a] -> [a] -> [a]
    ++ [GroupName TileKind]
    groupNames)