Allure-0.4.2: src/Tile.hs
module Tile where
import qualified Data.List as L
import qualified Data.Array.Unboxed as A
import Data.Binary
import Content.TileKind
import qualified Feature as F
import qualified Kind
import Geometry
newtype SecretStrength = SecretStrength{secretStrength :: Time}
deriving (Show, Eq, Ord)
instance Binary SecretStrength where
put = put . secretStrength
get = fmap SecretStrength get
-- TODO: remove this file
wallId, openingId, floorLightId, floorDarkId, unknownId, doorOpenId, doorClosedId, doorSecretId, stairsUpId, stairsDownId :: Kind.Id TileKind
wallId = Kind.getId (\ t -> tsymbol t == '#' && (L.null $ tfeature t))
openingId = Kind.getId (\ t -> tsymbol t == '.' && kindHasFeature F.Exit t)
floorLightId =
Kind.getId (\ t -> tsymbol t == '.' && kindHas [F.Lit] [F.Exit] t)
floorDarkId =
Kind.getId (\ t -> tsymbol t == '.' && kindHas [] [F.Exit, F.Lit] t)
unknownId = Kind.getId ((== ' ') . tsymbol)
doorOpenId = Kind.getId (kindHasFeature F.Closable)
doorClosedId = Kind.getId (kindHasFeature F.Openable)
doorSecretId = Kind.getId (kindHasFeature F.Hidden)
stairsUpId = Kind.getId (kindHas [F.Lit, F.Climbable] [])
stairsDownId = Kind.getId (kindHas [F.Lit, F.Descendable] [])
-- | The player can't tell if the tile is a secret door or not.
canBeSecretDoor :: Kind.Id TileKind -> Bool
canBeSecretDoor t =
let u = Kind.getKind t
s = Kind.getKind doorSecretId
in tsymbol u == tsymbol s &&
tname u == tname s &&
tcolor u == tcolor s &&
tcolor2 u == tcolor2 s
isUnknown :: Kind.Id TileKind -> Bool
isUnknown t = t == unknownId
isOpening :: Kind.Id TileKind -> Bool
isOpening t = t == openingId
kindHasFeature :: F.Feature -> TileKind -> Bool
kindHasFeature f t = f `elem` tfeature t
kindHas :: [F.Feature] -> [F.Feature] -> TileKind -> Bool
kindHas yes no t = L.all (flip kindHasFeature t) yes &&
not (L.any (flip kindHasFeature t) no)
hasFeature :: F.Feature -> Kind.Id TileKind -> Bool
hasFeature f t = kindHasFeature f (Kind.getKind t)
-- | Does not block vision. Essential for efficiency of FOV, hence tabulated.
clearTab :: A.UArray (Kind.Id TileKind) Bool
clearTab = let f _ k acc = kindHasFeature F.Clear k : acc
clearAssocs = Kind.foldrWithKey f []
in A.listArray Kind.boundsId clearAssocs
isClear :: Kind.Id TileKind -> Bool
isClear i = clearTab A.! i
-- | Is lit on its own. Essential for efficiency of Perception, hence tabulated.
litTab :: A.UArray (Kind.Id TileKind) Bool
litTab = let f _ k acc = kindHasFeature F.Lit k : acc
litAssocs = Kind.foldrWithKey f []
in A.listArray Kind.boundsId litAssocs
isLit :: Kind.Id TileKind -> Bool
isLit i = litTab A.! i
-- | Does not block land movement.
isWalkable :: Kind.Id TileKind -> Bool
isWalkable = hasFeature F.Walkable
-- | Provides an exit from a room.
isExit :: Kind.Id TileKind -> Bool
isExit = hasFeature F.Exit
-- | Is a good candidate to deposit items, replace by other tiles, etc.
isBoring :: Kind.Id TileKind -> Bool
isBoring t =
let fs = tfeature (Kind.getKind t)
optional = [F.Exit, F.Lit]
mandatory = [F.Walkable, F.Clear]
in fs L.\\ optional `L.elem` L.permutations mandatory