1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
|
{-# LANGUAGE DeriveGeneric, GeneralizedNewtypeDeriving #-}
-- | Actors perceiving other actors and the dungeon level.
--
-- Visibility works according to KISS. Everything that player sees is real.
-- There are no unmarked hidden tiles and only solid tiles can be marked,
-- so there are no invisible walls and to pass through an illusory wall,
-- you have to use a turn bumping into it first. Only tiles marked with Suspect
-- can turn out to be another tile. (So, if all tiles are marked with
-- Suspect, the player knows nothing for sure, but this should be avoided,
-- because searching becomes too time-consuming.)
-- Each actor sees adjacent tiles, even when blind, so adjacent tiles are
-- known, so the actor can decide accurately whether to pass thorugh
-- or alter, etc.
--
-- Items are always real and visible. Actors are real, but can be invisible.
-- Invisible actors in walls can't be hit, but are hinted at when altering
-- the tile, so the player can flee or block. Invisible actors in open
-- space can be hit.
module Game.LambdaHack.Common.Perception
( PerVisible(..)
, PerSmelled(..)
, Perception(..)
, PerLid
, PerFid
, totalVisible, totalSmelled
, emptyPer, nullPer, addPer, diffPer
) where
import Prelude ()
import Game.LambdaHack.Core.Prelude
import Data.Binary
import qualified Data.EnumMap.Strict as EM
import qualified Data.EnumSet as ES
import GHC.Generics (Generic)
import Game.LambdaHack.Common.Types
import Game.LambdaHack.Common.Point
-- | Visible positions.
newtype PerVisible = PerVisible {pvisible :: ES.EnumSet Point}
deriving (Show, Eq, Binary)
-- | Smelled positions.
newtype PerSmelled = PerSmelled {psmelled :: ES.EnumSet Point}
deriving (Show, Eq, Binary)
-- | The type representing the perception of a faction on a level.
data Perception = Perception
{ psight :: PerVisible
, psmell :: PerSmelled
}
deriving (Show, Eq, Generic)
instance Binary Perception
-- | Perception of a single faction, indexed by level identifier.
type PerLid = EM.EnumMap LevelId Perception
-- | Perception indexed by faction identifier.
-- This can't be added to @FactionDict@, because clients can't see it
-- for other factions.
type PerFid = EM.EnumMap FactionId PerLid
-- | The set of tiles visible by at least one hero.
totalVisible :: Perception -> ES.EnumSet Point
totalVisible = pvisible . psight
-- | The set of tiles smelt by at least one hero.
totalSmelled :: Perception -> ES.EnumSet Point
totalSmelled = psmelled . psmell
emptyPer :: Perception
emptyPer = Perception { psight = PerVisible ES.empty
, psmell = PerSmelled ES.empty }
nullPer :: Perception -> Bool
nullPer per = per == emptyPer
addPer :: Perception -> Perception -> Perception
addPer per1 per2 =
Perception
{ psight = PerVisible
$ totalVisible per1 `ES.union` totalVisible per2
, psmell = PerSmelled
$ totalSmelled per1 `ES.union` totalSmelled per2
}
diffPer :: Perception -> Perception -> Perception
diffPer per1 per2 =
Perception
{ psight = PerVisible
$ totalVisible per1 ES.\\ totalVisible per2
, psmell = PerSmelled
$ totalSmelled per1 ES.\\ totalSmelled per2
}
|