-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A game engine library for roguelike dungeon crawlers -- -- LambdaHack is a Haskell game engine library for roguelike games of -- arbitrary theme, size and complexity, packaged together with a little -- example dungeon crawler. Try out the browser version of the LambdaHack -- sample game at https://lambdahack.github.io (It runs fastest on -- Chrome. Keyboard commands and savefiles are supported only on recent -- enough versions of browsers. Mouse should work everywhere.) -- -- -- When completed, the engine will let you specify content to be -- procedurally generated, define the AI behaviour on top of the generic -- content-independent rules and compile a ready-to-play game binary, -- using either the supplied or a custom-made main loop. Several -- frontends are available (SDL2 is the default for desktop and there is -- a Javascript browser frontend) and many other generic engine -- components are easily overridden, but the fundamental source of -- flexibility lies in the strict and type-safe separation of code from -- the content and of clients (human and AI-controlled) from the server. -- -- Please see the changelog file for recent improvements and the issue -- tracker for short-term plans. Long term vision revolves around -- procedural content generation and includes in-game content creation, -- auto-balancing and persistent content modification based on player -- behaviour. Contributions are welcome. -- -- Games known to use the LambdaHack library: -- -- -- -- Note: All modules in this library are kept visible, to let games -- override and reuse them. OTOH, to reflect that some modules are -- implementation details relative to others, the source code adheres to -- the following convention. If a module has the same name as a -- directory, the module is the exclusive interface to the directory. No -- references to the modules in the directory are allowed except from the -- interface module. This policy is only binding when developing the -- library --- library users are free to access any modules, since the -- library authors are in no position to guess their particular needs. @package LambdaHack @version 0.6.2.0 -- | Client monad for interacting with a human through UI. module Game.LambdaHack.Common.Prelude -- | A space efficient, packed, unboxed Unicode text type. data Text :: * -- | Separated by space unless one of them is empty (in which case just the -- non-empty one). (<+>) :: Text -> Text -> Text infixr 6 <+> -- | Show and pack the result. tshow :: Show a => a -> Text -- | Integer division, rounding up. divUp :: Integral a => a -> a -> a infixl 7 `divUp` (<$$>) :: (Functor f, Functor g) => (a -> b) -> f (g a) -> f (g b) infixl 4 <$$> partitionM :: Applicative m => (a -> m Bool) -> [a] -> m ([a], [a]) -- | Split the input between the two argument arrows and combine their -- output. Note that this is in general not a functor. -- -- The default definition may be overridden with a more efficient version -- if desired. (***) :: Arrow a => forall b c b' c'. () => a b c -> a b' c' -> a (b, b') (c, c') infixr 3 *** -- | Fanout: send the input to both argument arrows and combine their -- output. -- -- The default definition may be overridden with a more efficient version -- if desired. (&&&) :: Arrow a => forall b c c'. () => a b c -> a b c' -> a b (c, c') infixr 3 &&& -- | Send the first component of the input through the argument arrow, and -- copy the rest unchanged to the output. first :: Arrow a => forall b c d. () => a b c -> a (b, d) (c, d) -- | A mirror image of first. -- -- The default definition may be overridden with a more efficient version -- if desired. second :: Arrow a => forall b c d. () => a b c -> a (d, b) (d, c) -- | Basic operations on 2D points represented as linear offsets. module Game.LambdaHack.Common.Point -- | Spacial dimension for points and vectors. type X = Int -- | Spacial dimension for points and vectors. type Y = Int -- | 2D points in cartesian representation. Coordinates grow to the right -- and down, so that the (0, 0) point is in the top-left corner of the -- screen. Coordinates are never negative. data Point Point :: X -> Y -> Point [px] :: Point -> X [py] :: Point -> Y -- | The maximum number of bits for level X and Y dimension (16). The value -- is chosen to support architectures with 32-bit Ints. maxLevelDimExponent :: Int -- | The distance between two points in the chessboard metric. chessDist :: Point -> Point -> Int -- | Squared euclidean distance between two points. euclidDistSq :: Point -> Point -> Int -- | Checks whether two points are adjacent on the map (horizontally, -- vertically or diagonally). adjacent :: Point -> Point -> Bool -- | Checks that a point belongs to an area. inside :: Point -> (X, Y, X, Y) -> Bool -- | Bresenham's line algorithm generalized to arbitrary starting -- eps (eps value of 0 gives the standard BLA). Skips -- the source point and goes through the second point to the edge of the -- level. GIves Nothing if the points are equal. The target is -- given as Point to permit aiming out of the level, e.g., to -- get uniform distributions of directions for explosions close to the -- edge of the level. bla :: X -> Y -> Int -> Point -> Point -> Maybe [Point] -- | A list of all points on a straight vertical or straight horizontal -- line between two points. Fails if no such line exists. fromTo :: Point -> Point -> [Point] originPoint :: Point instance GHC.Generics.Generic Game.LambdaHack.Common.Point.Point instance GHC.Classes.Ord Game.LambdaHack.Common.Point.Point instance GHC.Classes.Eq Game.LambdaHack.Common.Point.Point instance GHC.Show.Show Game.LambdaHack.Common.Point.Point instance Data.Binary.Class.Binary Game.LambdaHack.Common.Point.Point instance Control.DeepSeq.NFData Game.LambdaHack.Common.Point.Point instance GHC.Enum.Enum Game.LambdaHack.Common.Point.Point -- | Arrays, based on Data.Vector.Unboxed, indexed by Point. module Game.LambdaHack.Common.PointArray -- | Arrays indexed by Point. data GArray w c Array :: X -> Y -> Vector w -> GArray w c [axsize] :: GArray w c -> X [aysize] :: GArray w c -> Y [avector] :: GArray w c -> Vector w -- | Arrays of, effectively, Word8, indexed by Point. type Array c = GArray Word8 c pindex :: X -> Point -> Int punindex :: X -> Int -> Point -- | Array lookup. (!) :: (Unbox w, Enum w, Enum c) => GArray w c -> Point -> c accessI :: Unbox w => GArray w c -> Int -> w -- | Construct an array updated with the association list. (//) :: (Unbox w, Enum w, Enum c) => GArray w c -> [(Point, c)] -> GArray w c -- | Create an array from a replicated element. replicateA :: (Unbox w, Enum w, Enum c) => X -> Y -> c -> GArray w c -- | Create an array from a replicated monadic action. replicateMA :: (Unbox w, Enum w, Enum c, Monad m) => X -> Y -> m c -> m (GArray w c) -- | Create an array from a function. generateA :: (Unbox w, Enum w, Enum c) => X -> Y -> (Point -> c) -> GArray w c -- | Create an array from a monadic function. generateMA :: (Unbox w, Enum w, Enum c, Monad m) => X -> Y -> (Point -> m c) -> m (GArray w c) unfoldrNA :: (Unbox w, Enum w, Enum c) => X -> Y -> (b -> (c, b)) -> b -> GArray w c -- | Content identifiers array size. sizeA :: GArray w c -> (X, Y) -- | Fold right over an array. foldrA :: (Unbox w, Enum w, Enum c) => (c -> a -> a) -> a -> GArray w c -> a -- | Fold right strictly over an array. foldrA' :: (Unbox w, Enum w, Enum c) => (c -> a -> a) -> a -> GArray w c -> a -- | Fold left strictly over an array. foldlA' :: (Unbox w, Enum w, Enum c) => (a -> c -> a) -> a -> GArray w c -> a -- | Fold right over an array (function applied to each element and its -- index). ifoldrA :: (Unbox w, Enum w, Enum c) => (Point -> c -> a -> a) -> a -> GArray w c -> a -- | Fold right strictly over an array (function applied to each element -- and its index). ifoldrA' :: (Unbox w, Enum w, Enum c) => (Point -> c -> a -> a) -> a -> GArray w c -> a -- | Fold left strictly over an array (function applied to each element and -- its index). ifoldlA' :: (Unbox w, Enum w, Enum c) => (a -> Point -> c -> a) -> a -> GArray w c -> a -- | Fold monadically strictly over an array. foldMA' :: (Monad m, Unbox w, Enum w, Enum c) => (a -> c -> m a) -> a -> GArray w c -> m a -- | Fold monadically strictly over an array (function applied to each -- element and its index). ifoldMA' :: (Monad m, Unbox w, Enum w, Enum c) => (a -> Point -> c -> m a) -> a -> GArray w c -> m a -- | Map over an array. mapA :: (Unbox w1, Enum w1, Unbox w2, Enum w2, Enum c, Enum d) => (c -> d) -> GArray w1 c -> GArray w2 d -- | Map over an array (function applied to each element and its index). imapA :: (Unbox w1, Enum w1, Unbox w2, Enum w2, Enum c, Enum d) => (Point -> c -> d) -> GArray w1 c -> GArray w2 d -- | Map monadically over an array (function applied to each element and -- its index) and ignore the results. imapMA_ :: (Unbox w, Enum w, Enum c, Monad m) => (Point -> c -> m ()) -> GArray w c -> m () -- | Set all elements to the given value, in place, if possible. safeSetA :: (Unbox w, Enum w, Enum c) => c -> GArray w c -> GArray w c -- | Set all elements to the given value, in place. unsafeSetA :: (Unbox w, Enum w, Enum c) => c -> GArray w c -> GArray w c unsafeUpdateA :: (Unbox w, Enum w, Enum c) => GArray w c -> [(Point, c)] -> () unsafeWriteA :: (Unbox w, Enum w, Enum c) => GArray w c -> Point -> c -> () unsafeWriteManyA :: (Unbox w, Enum w, Enum c) => GArray w c -> [Point] -> c -> () -- | Yield the point coordinates of a minimum element of the array. The -- array may not be empty. minIndexA :: (Unbox w, Ord w) => GArray w c -> Point -- | Yield the point coordinates of the last minimum element of the array. -- The array may not be empty. minLastIndexA :: (Unbox w, Ord w) => GArray w c -> Point -- | Yield the point coordinates of all the minimum elements of the array. -- The array may not be empty. minIndexesA :: (Unbox w, Enum w, Ord w) => GArray w c -> [Point] -- | Yield the point coordinates of the first maximum element of the array. -- The array may not be empty. maxIndexA :: (Unbox w, Ord w) => GArray w c -> Point -- | Yield the point coordinates of the last maximum element of the array. -- The array may not be empty. maxLastIndexA :: (Unbox w, Ord w) => GArray w c -> Point -- | Force the array not to retain any extra memory. forceA :: Unbox w => GArray w c -> GArray w c fromListA :: (Unbox w, Enum w, Enum c) => X -> Y -> [c] -> GArray w c toListA :: (Unbox w, Enum w, Enum c) => GArray w c -> [c] instance (GHC.Classes.Eq w, Data.Vector.Unboxed.Base.Unbox w) => GHC.Classes.Eq (Game.LambdaHack.Common.PointArray.GArray w c) instance GHC.Show.Show (Game.LambdaHack.Common.PointArray.GArray w c) instance (Data.Vector.Unboxed.Base.Unbox w, Data.Binary.Class.Binary w) => Data.Binary.Class.Binary (Game.LambdaHack.Common.PointArray.GArray w c) -- | Hacks that haven't found their home yet. module Game.LambdaHack.Common.Misc -- | A unique identifier of a faction in a game. data FactionId -- | Abstract level identifiers. data LevelId -- | Absolute depth in the dungeon. When used for the maximum depth of the -- whole dungeon, this can be different than dungeon size, e.g., when the -- dungeon is branched, and it can even be different than the length of -- the longest branch, if levels at some depths are missing. newtype AbsDepth AbsDepth :: Int -> AbsDepth -- | A unique identifier of an actor in the dungeon. data ActorId -- | Item container type. data Container CFloor :: LevelId -> Point -> Container CEmbed :: LevelId -> Point -> Container CActor :: ActorId -> CStore -> Container -- | for bootstrapping actor bodies CTrunk :: FactionId -> LevelId -> Point -> Container data CStore CGround :: CStore COrgan :: CStore CEqp :: CStore CInv :: CStore CSha :: CStore data ItemDialogMode MStore :: CStore -> ItemDialogMode MOwned :: ItemDialogMode MStats :: ItemDialogMode MLoreItem :: ItemDialogMode MLoreOrgan :: ItemDialogMode -- | Re-exported English phrase creation functions, applied to default -- irregular word sets. makePhrase :: [Part] -> Text -- | Re-exported English phrase creation functions, applied to default -- irregular word sets. makeSentence :: [Part] -> Text -- | Level bounds. normalLevelBound :: (Int, Int) data GroupName a toGroupName :: Text -> GroupName a -- | For each group that the kind belongs to, denoted by a -- GroupName in the first component of a pair, the second -- component of a pair shows how common the kind is within the group. type Freqs a = [(GroupName a, Int)] -- |
--   breturn b a = [a | b]
--   
breturn :: MonadPlus m => Bool -> a -> m a -- | Rarity on given depths. type Rarity = [(Double, Int)] validateRarity :: Rarity -> [Text] -- | Tactic of non-leader actors. Apart of determining AI operation, each -- tactic implies a skill modifier, that is added to the non-leader -- skills defined in fskillsOther field of Player. data Tactic -- | if enemy nearby, attack, if no items, etc., explore unknown TExplore :: Tactic -- | always follow leader's target or his position if no target TFollow :: Tactic -- | follow but don't do any item management nor use TFollowNoItems :: Tactic -- | only melee and do ranged combat TMeleeAndRanged :: Tactic -- | only melee (or wait) TMeleeAdjacent :: Tactic -- | always only wait, even if enemy in melee range TBlock :: Tactic -- | if enemy nearby, attack, if no items, etc., roam randomly TRoam :: Tactic -- | find an open and uncrowded area, patrol it according to sight radius -- and fallback temporarily to TRoam when enemy is seen by the -- faction and is within the actor's sight radius TPatrol :: Tactic describeTactic :: Tactic -> Text -- | Personal data directory for the game. Depends on the OS and the game, -- e.g., for LambdaHack under Linux it's ~/.LambdaHack/. appDataDir :: IO FilePath xM :: Int -> Int64 minusM :: Int64 minusM1 :: Int64 oneM :: Int64 instance GHC.Generics.Generic Game.LambdaHack.Common.Misc.Tactic instance GHC.Enum.Bounded Game.LambdaHack.Common.Misc.Tactic instance GHC.Enum.Enum Game.LambdaHack.Common.Misc.Tactic instance GHC.Classes.Ord Game.LambdaHack.Common.Misc.Tactic instance GHC.Classes.Eq Game.LambdaHack.Common.Misc.Tactic instance GHC.Generics.Generic Game.LambdaHack.Common.Misc.Container instance GHC.Classes.Ord Game.LambdaHack.Common.Misc.Container instance GHC.Classes.Eq Game.LambdaHack.Common.Misc.Container instance GHC.Show.Show Game.LambdaHack.Common.Misc.Container instance Data.Binary.Class.Binary Game.LambdaHack.Common.Misc.ActorId instance GHC.Enum.Enum Game.LambdaHack.Common.Misc.ActorId instance GHC.Classes.Ord Game.LambdaHack.Common.Misc.ActorId instance GHC.Classes.Eq Game.LambdaHack.Common.Misc.ActorId instance GHC.Show.Show Game.LambdaHack.Common.Misc.ActorId instance Data.Binary.Class.Binary Game.LambdaHack.Common.Misc.AbsDepth instance Data.Hashable.Class.Hashable Game.LambdaHack.Common.Misc.AbsDepth instance GHC.Classes.Ord Game.LambdaHack.Common.Misc.AbsDepth instance GHC.Classes.Eq Game.LambdaHack.Common.Misc.AbsDepth instance GHC.Show.Show Game.LambdaHack.Common.Misc.AbsDepth instance Data.Binary.Class.Binary Game.LambdaHack.Common.Misc.LevelId instance Data.Hashable.Class.Hashable Game.LambdaHack.Common.Misc.LevelId instance GHC.Enum.Enum Game.LambdaHack.Common.Misc.LevelId instance GHC.Classes.Ord Game.LambdaHack.Common.Misc.LevelId instance GHC.Classes.Eq Game.LambdaHack.Common.Misc.LevelId instance GHC.Show.Show Game.LambdaHack.Common.Misc.LevelId instance Data.Binary.Class.Binary Game.LambdaHack.Common.Misc.FactionId instance Data.Hashable.Class.Hashable Game.LambdaHack.Common.Misc.FactionId instance GHC.Enum.Enum Game.LambdaHack.Common.Misc.FactionId instance GHC.Classes.Ord Game.LambdaHack.Common.Misc.FactionId instance GHC.Classes.Eq Game.LambdaHack.Common.Misc.FactionId instance GHC.Show.Show Game.LambdaHack.Common.Misc.FactionId instance GHC.Generics.Generic Game.LambdaHack.Common.Misc.ItemDialogMode instance GHC.Classes.Ord Game.LambdaHack.Common.Misc.ItemDialogMode instance GHC.Classes.Eq Game.LambdaHack.Common.Misc.ItemDialogMode instance GHC.Read.Read Game.LambdaHack.Common.Misc.ItemDialogMode instance GHC.Show.Show Game.LambdaHack.Common.Misc.ItemDialogMode instance GHC.Generics.Generic Game.LambdaHack.Common.Misc.CStore instance GHC.Enum.Bounded Game.LambdaHack.Common.Misc.CStore instance GHC.Enum.Enum Game.LambdaHack.Common.Misc.CStore instance GHC.Classes.Ord Game.LambdaHack.Common.Misc.CStore instance GHC.Classes.Eq Game.LambdaHack.Common.Misc.CStore instance GHC.Read.Read Game.LambdaHack.Common.Misc.CStore instance GHC.Show.Show Game.LambdaHack.Common.Misc.CStore instance GHC.Generics.Generic (Game.LambdaHack.Common.Misc.GroupName a) instance Data.Binary.Class.Binary (Game.LambdaHack.Common.Misc.GroupName a) instance Data.Hashable.Class.Hashable (Game.LambdaHack.Common.Misc.GroupName a) instance GHC.Classes.Ord (Game.LambdaHack.Common.Misc.GroupName a) instance GHC.Classes.Eq (Game.LambdaHack.Common.Misc.GroupName a) instance GHC.Read.Read (Game.LambdaHack.Common.Misc.GroupName a) instance GHC.Show.Show Game.LambdaHack.Common.Misc.Tactic instance Data.Binary.Class.Binary Game.LambdaHack.Common.Misc.Tactic instance Data.Hashable.Class.Hashable Game.LambdaHack.Common.Misc.Tactic instance Data.Binary.Class.Binary Game.LambdaHack.Common.Misc.Container instance Control.DeepSeq.NFData Game.LambdaHack.Common.Misc.ItemDialogMode instance Data.Binary.Class.Binary Game.LambdaHack.Common.Misc.ItemDialogMode instance Data.Binary.Class.Binary Game.LambdaHack.Common.Misc.CStore instance Data.Hashable.Class.Hashable Game.LambdaHack.Common.Misc.CStore instance Control.DeepSeq.NFData Game.LambdaHack.Common.Misc.CStore instance Data.String.IsString (Game.LambdaHack.Common.Misc.GroupName a) instance GHC.Show.Show (Game.LambdaHack.Common.Misc.GroupName a) instance Control.DeepSeq.NFData (Game.LambdaHack.Common.Misc.GroupName a) instance (GHC.Enum.Enum k, Data.Binary.Class.Binary k, Data.Binary.Class.Binary e) => Data.Binary.Class.Binary (Data.EnumMap.Strict.EnumMap k e) instance (GHC.Enum.Enum k, Data.Binary.Class.Binary k) => Data.Binary.Class.Binary (Data.EnumSet.EnumSet k) instance Data.Binary.Class.Binary Data.Time.Clock.Internal.NominalDiffTime.NominalDiffTime instance (Data.Hashable.Class.Hashable k, GHC.Classes.Eq k, Data.Binary.Class.Binary k, Data.Binary.Class.Binary v) => Data.Binary.Class.Binary (Data.HashMap.Base.HashMap k v) instance Data.Key.Zip (Data.EnumMap.Strict.EnumMap k) instance GHC.Enum.Enum k => Data.Key.ZipWithKey (Data.EnumMap.Strict.EnumMap k) instance GHC.Enum.Enum k => Data.Key.Keyed (Data.EnumMap.Strict.EnumMap k) instance GHC.Enum.Enum k => Data.Key.FoldableWithKey (Data.EnumMap.Strict.EnumMap k) instance GHC.Enum.Enum k => Data.Key.TraversableWithKey (Data.EnumMap.Strict.EnumMap k) instance GHC.Enum.Enum k => Data.Key.Indexable (Data.EnumMap.Strict.EnumMap k) instance GHC.Enum.Enum k => Data.Key.Lookup (Data.EnumMap.Strict.EnumMap k) instance GHC.Enum.Enum k => Data.Key.Adjustable (Data.EnumMap.Strict.EnumMap k) instance (GHC.Enum.Enum k, Data.Hashable.Class.Hashable k, Data.Hashable.Class.Hashable e) => Data.Hashable.Class.Hashable (Data.EnumMap.Strict.EnumMap k e) instance Control.DeepSeq.NFData NLP.Miniutter.English.Part instance Control.DeepSeq.NFData NLP.Miniutter.English.Person instance Control.DeepSeq.NFData NLP.Miniutter.English.Polarity -- | Saving/loading with serialization and compression. module Game.LambdaHack.Common.File -- | Serialize, compress and save data with an EOF marker. The OK -- is used as an EOF marker to ensure any apparent problems with -- corrupted files are reported to the user ASAP. encodeEOF :: Binary a => FilePath -> a -> IO () -- | Read, decompress and deserialize data with an EOF marker. The -- OK EOF marker ensures any easily detectable file corruption -- is discovered and reported before the function returns. strictDecodeEOF :: Binary a => FilePath -> IO a -- | Try to create a directory, if it doesn't exist. We catch exceptions in -- case many clients try to do the same thing at the same time. tryCreateDir :: FilePath -> IO () -- | The operation doesFileExist returns True if the argument -- file exists and is not a directory, and False otherwise. doesFileExist :: FilePath -> IO Bool -- | Try to write a file, given content, if the file not already there. We -- catch exceptions in case many clients try to do the same thing at the -- same time. tryWriteFile :: FilePath -> String -> IO () -- | The readFile function reads a file and returns the contents of -- the file as a string. The file is read lazily, on demand, as with -- getContents. readFile :: FilePath -> IO String -- | renameFile old new changes the name of an existing -- file system object from old to new. If the new -- object already exists, it is atomically replaced by the old -- object. Neither path may refer to an existing directory. A conformant -- implementation need not support renaming files in all situations (e.g. -- renaming across different physical devices), but the constraints must -- be documented. -- -- The operation may fail with: -- -- renameFile :: FilePath -> FilePath -> IO () -- | A list of items with relative frequencies of appearance. module Game.LambdaHack.Common.Frequency -- | The frequency distribution type. Not normalized (operations may or may -- not group the same elements and sum their frequencies). However, -- elements with zero frequency are removed upon construction. -- -- The Eq instance compares raw representations, not relative, -- normalized frequencies, so operations don't need to preserve the -- expected equalities, unless they do some kind of normalization (see -- Dice). data Frequency a -- | Uniform discrete frequency distribution. uniformFreq :: Text -> [a] -> Frequency a -- | Takes a name and a list of frequencies and items into the frequency -- distribution. toFreq :: Text -> [(Int, a)] -> Frequency a -- | Scale frequency distribution, multiplying it by a positive integer -- constant. scaleFreq :: Show a => Int -> Frequency a -> Frequency a -- | Change the description of the frequency. renameFreq :: Text -> Frequency a -> Frequency a -- | Set frequency of an element. setFreq :: Eq a => Frequency a -> a -> Int -> Frequency a -- | Test if the frequency distribution is empty. nullFreq :: Frequency a -> Bool -- | give acces to raw frequency values runFrequency :: Frequency a -> [(Int, a)] -- | short description for debug, etc.; keep it lazy, because it's rarely -- used nameFrequency :: Frequency a -> Text minFreq :: Ord a => Frequency a -> Maybe a maxFreq :: Ord a => Frequency a -> Maybe a mostFreq :: Frequency a -> Maybe a -- | Average value of an Int distribution, rounded up to avoid -- truncating it in the other code higher up, which would equate 1d0 with -- 1d1. meanFreq :: Frequency Int -> Int instance GHC.Generics.Generic (Game.LambdaHack.Common.Frequency.Frequency a) instance Data.Traversable.Traversable Game.LambdaHack.Common.Frequency.Frequency instance Data.Foldable.Foldable Game.LambdaHack.Common.Frequency.Frequency instance GHC.Classes.Ord a => GHC.Classes.Ord (Game.LambdaHack.Common.Frequency.Frequency a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Game.LambdaHack.Common.Frequency.Frequency a) instance GHC.Show.Show a => GHC.Show.Show (Game.LambdaHack.Common.Frequency.Frequency a) instance GHC.Base.Monad Game.LambdaHack.Common.Frequency.Frequency instance GHC.Base.Functor Game.LambdaHack.Common.Frequency.Frequency instance GHC.Base.Applicative Game.LambdaHack.Common.Frequency.Frequency instance GHC.Base.MonadPlus Game.LambdaHack.Common.Frequency.Frequency instance GHC.Base.Alternative Game.LambdaHack.Common.Frequency.Frequency instance Data.Hashable.Class.Hashable a => Data.Hashable.Class.Hashable (Game.LambdaHack.Common.Frequency.Frequency a) instance Data.Binary.Class.Binary a => Data.Binary.Class.Binary (Game.LambdaHack.Common.Frequency.Frequency a) instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (Game.LambdaHack.Common.Frequency.Frequency a) -- | Representation of dice for parameters scaled with current level depth. module Game.LambdaHack.Common.Dice -- | Dice for parameters scaled with current level depth. To the result of -- rolling the first set of dice we add the second, scaled in proportion -- to current depth divided by maximal dungeon depth. The result if then -- multiplied by the scale --- to be used to ensure that dice results are -- multiples of, e.g., 10. The scale is set with |*|. -- -- Dice like 100d100 lead to enormous lists, so we help a bit by keeping -- simple dice nonstrict below. data Dice diceConst :: Dice -> SimpleDice diceLevel :: Dice -> SimpleDice diceMult :: Dice -> Int -- | Multiplying the dice, after all randomness is resolved, by a constant. -- Infix declaration ensures that 1 + 2 |*| 3 parses as (1 + -- 2) |*| 3. (|*|) :: Dice -> Int -> Dice infixl 5 |*| -- | A single simple dice. d :: Int -> Dice -- | Dice scaled with level. dl :: Int -> Dice intToDice :: Int -> Dice -- | Maximal value of dice. The scaled part taken assuming median level. maxDice :: Dice -> Int -- | Minimal value of dice. The scaled part taken assuming median level. minDice :: Dice -> Int -- | Mean value of dice. The scaled part taken assuming median level. -- Assumes the frequencies are not null. meanDice :: Dice -> Int reduceDice :: Dice -> Maybe Int -- | Dice for rolling a pair of integer parameters pertaining to, -- respectively, the X and Y cartesian 2D coordinates. data DiceXY DiceXY :: Dice -> Dice -> DiceXY -- | Maximal value of DiceXY. maxDiceXY :: DiceXY -> (Int, Int) -- | Minimal value of DiceXY. minDiceXY :: DiceXY -> (Int, Int) -- | Mean value of DiceXY. meanDiceXY :: DiceXY -> (Int, Int) type SimpleDice = Frequency Int instance GHC.Generics.Generic Game.LambdaHack.Common.Dice.DiceXY instance GHC.Classes.Ord Game.LambdaHack.Common.Dice.DiceXY instance GHC.Classes.Eq Game.LambdaHack.Common.Dice.DiceXY instance GHC.Show.Show Game.LambdaHack.Common.Dice.DiceXY instance GHC.Generics.Generic Game.LambdaHack.Common.Dice.Dice instance GHC.Classes.Ord Game.LambdaHack.Common.Dice.Dice instance GHC.Classes.Eq Game.LambdaHack.Common.Dice.Dice instance Data.Hashable.Class.Hashable Game.LambdaHack.Common.Dice.DiceXY instance Data.Binary.Class.Binary Game.LambdaHack.Common.Dice.DiceXY instance GHC.Show.Show Game.LambdaHack.Common.Dice.Dice instance Data.Hashable.Class.Hashable Game.LambdaHack.Common.Dice.Dice instance Data.Binary.Class.Binary Game.LambdaHack.Common.Dice.Dice instance Control.DeepSeq.NFData Game.LambdaHack.Common.Dice.Dice instance GHC.Num.Num Game.LambdaHack.Common.Dice.Dice instance GHC.Num.Num Game.LambdaHack.Common.Dice.SimpleDice -- | A game requires the engine provided by the library, perhaps -- customized, and game content, defined completely afresh for the -- particular game. The general type of the content is -- ContentDef and it has instances for all content kinds, such -- as items kinds (Game.LambdaHack.Content.ItemKind). The -- possible kinds are fixed in the library and all defined in the same -- directory. On the other hand, game content, that is all elements of -- ContentDef instances, are defined in a directory of the game -- code proper, with names corresponding to their kinds. module Game.LambdaHack.Common.ContentDef -- | The general type of a particular game content, e.g., item kinds. data ContentDef a ContentDef :: (a -> Char) -> (a -> Text) -> (a -> Freqs a) -> (a -> [Text]) -> ([a] -> [Text]) -> Vector a -> ContentDef a -- | symbol, e.g., to print on the map [getSymbol] :: ContentDef a -> a -> Char -- | name, e.g., to show to the player [getName] :: ContentDef a -> a -> Text -- | frequency within groups [getFreq] :: ContentDef a -> a -> Freqs a -- | validate a content item and list all offences [validateSingle] :: ContentDef a -> a -> [Text] -- | validate the whole defined content of this type and list all offences [validateAll] :: ContentDef a -> [a] -> [Text] -- | all content of this type [content] :: ContentDef a -> Vector a contentFromList :: [a] -> Vector a -- | Colours and text attributes. module Game.LambdaHack.Common.Color -- | Colours supported by the major frontends. data Color Black :: Color Red :: Color Green :: Color Brown :: Color Blue :: Color Magenta :: Color Cyan :: Color White :: Color BrBlack :: Color BrRed :: Color BrGreen :: Color BrYellow :: Color BrBlue :: Color BrMagenta :: Color BrCyan :: Color BrWhite :: Color -- | The default colours, to optimize attribute setting. defFG :: Color -- | A helper for the terminal frontends that display bright via bold. isBright :: Color -> Bool -- | Colour sets. darkCol :: [Color] -- | Colour sets. brightCol :: [Color] -- | Colour sets. stdCol :: [Color] -- | Translationg to heavily modified Linux console color RGB values. -- -- Warning: SDL frontend sadly duplicates this code. colorToRGB :: Color -> Text data Highlight HighlightNone :: Highlight HighlightRed :: Highlight HighlightBlue :: Highlight HighlightYellow :: Highlight HighlightGrey :: Highlight HighlightWhite :: Highlight HighlightMagenta :: Highlight -- | Text attributes: foreground and backgroud colors. data Attr Attr :: Color -> Highlight -> Attr -- | foreground colour [fg] :: Attr -> Color -- | backgroud highlight [bg] :: Attr -> Highlight -- | The default attribute, to optimize attribute setting. defAttr :: Attr data AttrChar AttrChar :: Attr -> Char -> AttrChar [acAttr] :: AttrChar -> Attr [acChar] :: AttrChar -> Char newtype AttrCharW32 AttrCharW32 :: Word32 -> AttrCharW32 [attrCharW32] :: AttrCharW32 -> Word32 attrCharToW32 :: AttrChar -> AttrCharW32 attrCharFromW32 :: AttrCharW32 -> AttrChar fgFromW32 :: AttrCharW32 -> Color bgFromW32 :: AttrCharW32 -> Highlight charFromW32 :: AttrCharW32 -> Char attrFromW32 :: AttrCharW32 -> Attr attrEnumFromW32 :: AttrCharW32 -> Int spaceAttrW32 :: AttrCharW32 retAttrW32 :: AttrCharW32 attrChar2ToW32 :: Color -> Char -> AttrCharW32 attrChar1ToW32 :: Char -> AttrCharW32 instance Data.Binary.Class.Binary Game.LambdaHack.Common.Color.AttrCharW32 instance GHC.Enum.Enum Game.LambdaHack.Common.Color.AttrCharW32 instance GHC.Classes.Eq Game.LambdaHack.Common.Color.AttrCharW32 instance GHC.Show.Show Game.LambdaHack.Common.Color.AttrCharW32 instance GHC.Classes.Ord Game.LambdaHack.Common.Color.AttrChar instance GHC.Classes.Eq Game.LambdaHack.Common.Color.AttrChar instance GHC.Show.Show Game.LambdaHack.Common.Color.AttrChar instance GHC.Classes.Ord Game.LambdaHack.Common.Color.Attr instance GHC.Classes.Eq Game.LambdaHack.Common.Color.Attr instance GHC.Show.Show Game.LambdaHack.Common.Color.Attr instance GHC.Generics.Generic Game.LambdaHack.Common.Color.Highlight instance GHC.Enum.Bounded Game.LambdaHack.Common.Color.Highlight instance GHC.Enum.Enum Game.LambdaHack.Common.Color.Highlight instance GHC.Classes.Ord Game.LambdaHack.Common.Color.Highlight instance GHC.Classes.Eq Game.LambdaHack.Common.Color.Highlight instance GHC.Show.Show Game.LambdaHack.Common.Color.Highlight instance GHC.Generics.Generic Game.LambdaHack.Common.Color.Color instance GHC.Enum.Bounded Game.LambdaHack.Common.Color.Color instance GHC.Enum.Enum Game.LambdaHack.Common.Color.Color instance GHC.Classes.Ord Game.LambdaHack.Common.Color.Color instance GHC.Classes.Eq Game.LambdaHack.Common.Color.Color instance GHC.Show.Show Game.LambdaHack.Common.Color.Color instance GHC.Enum.Enum Game.LambdaHack.Common.Color.Attr instance Data.Binary.Class.Binary Game.LambdaHack.Common.Color.Highlight instance Data.Hashable.Class.Hashable Game.LambdaHack.Common.Color.Highlight instance Data.Binary.Class.Binary Game.LambdaHack.Common.Color.Color instance Data.Hashable.Class.Hashable Game.LambdaHack.Common.Color.Color -- | The appearance of in-game items, as communicated to the player. module Game.LambdaHack.Common.Flavour -- | The type of item flavours. data Flavour -- | Turn a colour set into a flavour set. zipPlain :: [Color] -> [Flavour] -- | Turn a colour set into a flavour set. zipFancy :: [Color] -> [Flavour] -- | The standard full set of flavours. stdFlav :: [Flavour] -- | Turn a colour set into a flavour set. zipLiquid :: [Color] -> [Flavour] -- | Get the underlying base colour of a flavour. flavourToColor :: Flavour -> Color -- | Construct the full name of a flavour. flavourToName :: Flavour -> Text -- | Simple names for team colors (bright colours preferred). colorToTeamName :: Color -> Text -- | Human-readable names for item colors. The plain set. colorToPlainName :: Color -> Text -- | Human-readable names for item colors. The fancy set. colorToFancyName :: Color -> Text instance GHC.Generics.Generic Game.LambdaHack.Common.Flavour.Flavour instance GHC.Classes.Ord Game.LambdaHack.Common.Flavour.Flavour instance GHC.Classes.Eq Game.LambdaHack.Common.Flavour.Flavour instance GHC.Show.Show Game.LambdaHack.Common.Flavour.Flavour instance GHC.Generics.Generic Game.LambdaHack.Common.Flavour.FancyName instance GHC.Classes.Ord Game.LambdaHack.Common.Flavour.FancyName instance GHC.Classes.Eq Game.LambdaHack.Common.Flavour.FancyName instance GHC.Show.Show Game.LambdaHack.Common.Flavour.FancyName instance Data.Hashable.Class.Hashable Game.LambdaHack.Common.Flavour.Flavour instance Data.Binary.Class.Binary Game.LambdaHack.Common.Flavour.Flavour instance Data.Hashable.Class.Hashable Game.LambdaHack.Common.Flavour.FancyName instance Data.Binary.Class.Binary Game.LambdaHack.Common.Flavour.FancyName -- | Screen frames and animations. module Game.LambdaHack.Common.ClientOptions data DebugModeCli DebugModeCli :: Maybe Text -> Maybe Text -> Maybe Int -> Maybe Int -> Maybe Int -> Maybe Bool -> Maybe Int -> Bool -> Maybe Bool -> Bool -> Bool -> Maybe Text -> Maybe FilePath -> String -> Bool -> Bool -> Bool -> Bool -> Maybe Int -> Maybe Int -> DebugModeCli -- | Font family to use for the GTK main game window. [sgtkFontFamily] :: DebugModeCli -> Maybe Text -- | Font file to use for the SDL2 main game window. [sdlFontFile] :: DebugModeCli -> Maybe Text -- | Pixels to add to map cells on top of scalable font max glyph height. [sdlTtfSizeAdd] :: DebugModeCli -> Maybe Int -- | Pixels to add to map cells on top of .fon font max glyph height. [sdlFonSizeAdd] :: DebugModeCli -> Maybe Int -- | Font size to use for the main game window. [sfontSize] :: DebugModeCli -> Maybe Int -- | Whether to use bold attribute for colorful characters. [scolorIsBold] :: DebugModeCli -> Maybe Bool -- | Maximal frames per second. This is better low and fixed, to avoid -- jerkiness and delays that tell the player there are many intelligent -- enemies on the level. That's better than scaling AI sofistication down -- based on the FPS setting and machine speed. [smaxFps] :: DebugModeCli -> Maybe Int -- | Never auto-answer all prompts, even if under AI control. [sdisableAutoYes] :: DebugModeCli -> Bool -- | Don't show any animations. [snoAnim] :: DebugModeCli -> Maybe Bool -- | Start a new game, overwriting the save file. [snewGameCli] :: DebugModeCli -> Bool -- | Don't create directories and files and show time stats. [sbenchmark] :: DebugModeCli -> Bool [stitle] :: DebugModeCli -> Maybe Text [sfontDir] :: DebugModeCli -> Maybe FilePath -- | Prefix of the save game file name. [ssavePrefixCli] :: DebugModeCli -> String -- | Whether to use the stdout/stdin frontend. [sfrontendTeletype] :: DebugModeCli -> Bool -- | Whether to use null (no input/output) frontend. [sfrontendNull] :: DebugModeCli -> Bool -- | Whether to use lazy (output not even calculated) frontend. [sfrontendLazy] :: DebugModeCli -> Bool -- | Show clients' internal debug messages. [sdbgMsgCli] :: DebugModeCli -> Bool [sstopAfterSeconds] :: DebugModeCli -> Maybe Int [sstopAfterFrames] :: DebugModeCli -> Maybe Int defDebugModeCli :: DebugModeCli instance GHC.Generics.Generic Game.LambdaHack.Common.ClientOptions.DebugModeCli instance GHC.Classes.Eq Game.LambdaHack.Common.ClientOptions.DebugModeCli instance GHC.Show.Show Game.LambdaHack.Common.ClientOptions.DebugModeCli instance Data.Binary.Class.Binary Game.LambdaHack.Common.ClientOptions.DebugModeCli -- | AI strategy abilities. module Game.LambdaHack.Common.Ability -- | Actor and faction abilities corresponding to client-server requests. data Ability AbMove :: Ability AbMelee :: Ability AbDisplace :: Ability AbAlter :: Ability AbWait :: Ability AbMoveItem :: Ability AbProject :: Ability AbApply :: Ability -- | Skill level in particular abilities. -- -- This representation is sparse, so better than a record when there are -- more item kinds (with few abilities) than actors (with many -- abilities), especially if the number of abilities grows as the engine -- is developed. It's also easier to code and maintain. type Skills = EnumMap Ability Int zeroSkills :: Skills unitSkills :: Skills addSkills :: Skills -> Skills -> Skills scaleSkills :: Int -> Skills -> Skills tacticSkills :: Tactic -> Skills blockOnly :: Skills meleeAdjacent :: Skills meleeAndRanged :: Skills ignoreItems :: Skills instance GHC.Enum.Bounded Game.LambdaHack.Common.Ability.Ability instance GHC.Enum.Enum Game.LambdaHack.Common.Ability.Ability instance GHC.Generics.Generic Game.LambdaHack.Common.Ability.Ability instance GHC.Classes.Ord Game.LambdaHack.Common.Ability.Ability instance GHC.Classes.Eq Game.LambdaHack.Common.Ability.Ability instance GHC.Show.Show Game.LambdaHack.Common.Ability.Ability instance Control.DeepSeq.NFData Game.LambdaHack.Common.Ability.Ability instance Data.Binary.Class.Binary Game.LambdaHack.Common.Ability.Ability instance Data.Hashable.Class.Hashable Game.LambdaHack.Common.Ability.Ability -- | Breadth first search algorithms. module Game.LambdaHack.Client.Bfs -- | Weighted distance between points along shortest paths. data BfsDistance -- | State of legality of moves between adjacent points. data MoveLegal MoveBlocked :: MoveLegal MoveToOpen :: MoveLegal MoveToClosed :: MoveLegal MoveToUnknown :: MoveLegal -- | The minimal distance value assigned to paths that don't enter any -- unknown tiles. minKnownBfs :: BfsDistance -- | The distance value that denotes no legal path between points, either -- due to blocked tiles or pathfinding aborted at earlier tiles, e.g., -- due to unknown tiles. apartBfs :: BfsDistance -- | Fill out the given BFS array. Unsafe PointArray operations -- are OK here, because the intermediate values of the vector don't leak -- anywhere outside nor are kept unevaluated and so they can't be -- overwritten by the unsafe side-effect. -- -- When computing move cost, we assume doors openable at no cost, because -- other actors use them, too, so the cost is shared and the extra -- visiblity is valuable, too. We treat unknown tiles specially. Whether -- suspect tiles are considered openable depends on -- smarkSuspect. fillBfs :: Array Word8 -> Word8 -> Point -> Array BfsDistance -> () data AndPath AndPath :: [Point] -> Point -> Int -> AndPath [pathList] :: AndPath -> [Point] [pathGoal] :: AndPath -> Point [pathLen] :: AndPath -> Int NoPath :: AndPath -- | Find a path, without the source position, with the smallest length. -- The eps coefficient determines which direction (of the -- closest directions available) that path should prefer, where 0 means -- north-west and 1 means north. findPathBfs :: Array Word8 -> (Point -> Bool) -> Point -> Point -> Int -> Array BfsDistance -> AndPath -- | Access a BFS array and interpret the looked up distance value. accessBfs :: Array BfsDistance -> Point -> Maybe Int instance GHC.Generics.Generic Game.LambdaHack.Client.Bfs.AndPath instance GHC.Show.Show Game.LambdaHack.Client.Bfs.AndPath instance GHC.Classes.Eq Game.LambdaHack.Client.Bfs.MoveLegal instance Data.Bits.Bits Game.LambdaHack.Client.Bfs.BfsDistance instance GHC.Enum.Bounded Game.LambdaHack.Client.Bfs.BfsDistance instance GHC.Enum.Enum Game.LambdaHack.Client.Bfs.BfsDistance instance GHC.Classes.Ord Game.LambdaHack.Client.Bfs.BfsDistance instance GHC.Classes.Eq Game.LambdaHack.Client.Bfs.BfsDistance instance GHC.Show.Show Game.LambdaHack.Client.Bfs.BfsDistance instance Data.Binary.Class.Binary Game.LambdaHack.Client.Bfs.AndPath -- | AI strategies to direct actors not controlled directly by human -- players. No operation in this module involves the State or -- Action type. module Game.LambdaHack.Client.AI.Strategy -- | A strategy is a choice of (non-empty) frequency tables of possible -- actions. data Strategy a nullStrategy :: Strategy a -> Bool -- | Strategy where only the actions from the given single frequency table -- can be picked. liftFrequency :: Frequency a -> Strategy a -- | Strategy with the actions from both argument strategies, with original -- frequencies. (.|) :: Strategy a -> Strategy a -> Strategy a infixr 2 .| -- | Strategy with no actions at all. reject :: Strategy a -- | Conditionally accepted strategy. (.=>) :: Bool -> Strategy a -> Strategy a infix 3 .=> -- | Strategy with all actions not satisfying the predicate removed. The -- remaining actions keep their original relative frequency values. only :: (a -> Bool) -> Strategy a -> Strategy a -- | When better choices are towards the start of the list, this is the -- best frequency of the strategy. bestVariant :: Strategy a -> Frequency a -- | Overwrite the description of all frequencies within the strategy. renameStrategy :: Text -> Strategy a -> Strategy a -- | Like return, but pick a name of the single frequency. returN :: Text -> a -> Strategy a mapStrategyM :: Monad m => (a -> m (Maybe b)) -> Strategy a -> m (Strategy b) instance Data.Traversable.Traversable Game.LambdaHack.Client.AI.Strategy.Strategy instance Data.Foldable.Foldable Game.LambdaHack.Client.AI.Strategy.Strategy instance GHC.Show.Show a => GHC.Show.Show (Game.LambdaHack.Client.AI.Strategy.Strategy a) instance GHC.Base.Monad Game.LambdaHack.Client.AI.Strategy.Strategy instance GHC.Base.Functor Game.LambdaHack.Client.AI.Strategy.Strategy instance GHC.Base.Applicative Game.LambdaHack.Client.AI.Strategy.Strategy instance GHC.Base.MonadPlus Game.LambdaHack.Client.AI.Strategy.Strategy instance GHC.Base.Alternative Game.LambdaHack.Client.AI.Strategy.Strategy -- | Representation of probabilities and random computations. module Game.LambdaHack.Common.Random -- | The monad of computations with random generator state. The lazy state -- monad is OK here: the state is small and regularly forced. type Rnd a = State StdGen a -- | Get a random object within a range with a uniform distribution. randomR :: (Random a) => (a, a) -> Rnd a -- | Get a random object of a given type with a uniform distribution. random :: (Random a) => Rnd a -- | Get any element of a list with equal probability. oneOf :: [a] -> Rnd a -- | Gen an element according to a frequency distribution. frequency :: Show a => Frequency a -> Rnd a -- | Fractional chance. type Chance = Rational -- | Give True, with probability determined by the fraction. chance :: Chance -> Rnd Bool -- | Cast dice scaled with current level depth. Note that at the first -- level, the scaled dice are always ignored. castDice :: AbsDepth -> AbsDepth -> Dice -> Rnd Int -- | Cast dice scaled with current level depth and return True if -- the results is greater than 50. chanceDice :: AbsDepth -> AbsDepth -> Dice -> Rnd Bool -- | Cast dice, scaled with current level depth, for coordinates. castDiceXY :: AbsDepth -> AbsDepth -> DiceXY -> Rnd (Int, Int) foldrM :: Foldable t => (a -> b -> Rnd b) -> b -> t a -> Rnd b foldlM' :: Foldable t => (b -> a -> Rnd b) -> b -> t a -> Rnd b -- | General content types and operations. module Game.LambdaHack.Common.KindOps -- | Content identifiers for the content type c. newtype Id c Id :: Word16 -> Id c -- | Content operations for the content of type a. data Ops a Ops :: (Id a -> a) -> (GroupName a -> Id a) -> (GroupName a -> (a -> Bool) -> Rnd (Maybe (Id a))) -> (forall b. (Id a -> a -> b -> b) -> b -> b) -> (forall b. (b -> Id a -> a -> b) -> b -> b) -> (forall b. GroupName a -> (b -> Int -> Id a -> a -> b) -> b -> b) -> Int -> Ops a -- | content element at given id [okind] :: Ops a -> Id a -> a -- | the id of the unique member of a singleton content group [ouniqGroup] :: Ops a -> GroupName a -> Id a -- | pick a random id belonging to a group and satisfying a predicate [opick] :: Ops a -> GroupName a -> (a -> Bool) -> Rnd (Maybe (Id a)) -- | fold over all content elements of a [ofoldrWithKey] :: Ops a -> forall b. (Id a -> a -> b -> b) -> b -> b -- | fold strictly over all content a [ofoldlWithKey'] :: Ops a -> forall b. (b -> Id a -> a -> b) -> b -> b -- | fold over the given group only [ofoldlGroup'] :: Ops a -> forall b. GroupName a -> (b -> Int -> Id a -> a -> b) -> b -> b -- | size of content a [olength] :: Ops a -> Int instance Data.Binary.Class.Binary (Game.LambdaHack.Common.KindOps.Id c) instance GHC.Enum.Bounded (Game.LambdaHack.Common.KindOps.Id c) instance GHC.Enum.Enum (Game.LambdaHack.Common.KindOps.Id c) instance GHC.Classes.Ord (Game.LambdaHack.Common.KindOps.Id c) instance GHC.Classes.Eq (Game.LambdaHack.Common.KindOps.Id c) instance GHC.Show.Show (Game.LambdaHack.Common.KindOps.Id c) -- | Ring buffers. module Game.LambdaHack.Common.RingBuffer data RingBuffer a empty :: Int -> a -> RingBuffer a -- | Add element to the front of the buffer. cons :: a -> RingBuffer a -> RingBuffer a uncons :: RingBuffer a -> Maybe (a, RingBuffer a) toList :: RingBuffer a -> [a] length :: RingBuffer a -> Int instance GHC.Generics.Generic (Game.LambdaHack.Common.RingBuffer.RingBuffer a) instance GHC.Show.Show a => GHC.Show.Show (Game.LambdaHack.Common.RingBuffer.RingBuffer a) instance Data.Binary.Class.Binary a => Data.Binary.Class.Binary (Game.LambdaHack.Common.RingBuffer.RingBuffer a) -- | Keeping track of forked threads. module Game.LambdaHack.Common.Thread forkChild :: MVar [Async ()] -> IO () -> IO () waitForChildren :: MVar [Async ()] -> IO () -- | Game time and speed. module Game.LambdaHack.Common.Time -- | Game time in ticks. The time dimension. One tick is 1 microsecond (one -- millionth of a second), one turn is 0.5 s. data Time -- | Start of the game time, or zero lenght time interval. timeZero :: Time -- | At least once per clip all moves are resolved and a frame or a frame -- delay is generated. Currently one clip is 0.05 s, but it may change, -- and the code should not depend on this fixed value. timeClip :: Time -- | One turn is 0.5 s. The code may depend on that. Actors at normal speed -- (2 m/s) take one turn to move one tile (1 m by 1 m). timeTurn :: Time -- | This many ticks fits in a single second. Do not export, timeSecond :: Time -- | An infinitesimal time period. timeEpsilon :: Time -- | Absolute time addition, e.g., for summing the total game session time -- from the times of individual games. absoluteTimeAdd :: Time -> Time -> Time absoluteTimeSubtract :: Time -> Time -> Time -- | Absolute time negation. To be used for reversing time flow, e.g., for -- comparing absolute times in the reverse order. absoluteTimeNegate :: Time -> Time -- | How many time intervals of the latter kind fits in an interval of the -- former kind. timeFit :: Time -> Time -> Int -- | How many time intervals of the latter kind cover an interval of the -- former kind (rounded up). timeFitUp :: Time -> Time -> Int -- | One-dimentional vectors. Introduced to tell apart the 2 uses of Time: -- as an absolute game time and as an increment. newtype Delta a Delta :: a -> Delta a -- | Shifting an absolute time by a time vector. timeShift :: Time -> Delta Time -> Time -- | Time time vector between the second and the first absolute times. The -- arguments are in the same order as in the underlying scalar -- subtraction. timeDeltaToFrom :: Time -> Time -> Delta Time -- | Time time vector between the second and the first absolute times. The -- arguments are in the same order as in the underlying scalar -- subtraction. timeDeltaSubtract :: Delta Time -> Delta Time -> Delta Time -- | Reverse a time vector. timeDeltaReverse :: Delta Time -> Delta Time -- | Scale the time vector by an Int scalar value. timeDeltaScale :: Delta Time -> Int -> Delta Time -- | Take the given percent of the time vector. timeDeltaPercent :: Delta Time -> Int -> Delta Time -- | Represent the main 10 thresholds of a time range by digits, given the -- total length of the time range. timeDeltaToDigit :: Delta Time -> Delta Time -> Char -- | The number of time ticks it takes to walk 1 meter at the given speed. ticksPerMeter :: Speed -> Delta Time -- | Speed in meters per 1 million seconds (m/Ms). Actors at normal speed -- (2 m/s) take one time turn (0.5 s) to make one step (move one tile, -- which is 1 m by 1 m). data Speed -- | Constructor for content definitions. toSpeed :: Int -> Speed -- | Pretty-printing of speed in the format used in content definitions. fromSpeed :: Speed -> Int -- | No movement possible at that speed. speedZero :: Speed -- | Fast walk speed (2 m/s) that suffices to move one tile in one turn. speedWalk :: Speed -- | Limp speed (1 m/s) that suffices to move one tile in two turns. This -- is the minimal speed for projectiles to fly just one space and drop. speedLimp :: Speed -- | Sword thrust speed (10 m/s). Base weapon damages, both melee and -- ranged, are given assuming this speed and ranged damage is modified -- accordingly when projectile speeds differ. Differences in melee weapon -- swing speeds are captured in damage bonuses instead, since many other -- factors influence total damage. -- -- Billiard ball is 25 ms, sword swing at the tip is 35 ms, -- medieval bow is 70 ms, AK47 is 700 ms. speedThrust :: Speed -- | Modify damage when projectiles is at a non-standard speed. Energy and -- so damage is proportional to the square of speed, hence the formula. modifyDamageBySpeed :: Int64 -> Speed -> Int64 -- | Scale speed by an Int scalar value. speedScale :: Rational -> Speed -> Speed -- | Divide a time vector. timeDeltaDiv :: Delta Time -> Int -> Delta Time -- | Speed addition. speedAdd :: Speed -> Speed -> Speed -- | Speed negation. speedNegate :: Speed -> Speed -- | Calculate projectile speed from item weight in grams and velocity -- percent modifier. See -- https://github.com/LambdaHack/LambdaHack/wiki/Item-statistics. speedFromWeight :: Int -> Int -> Speed -- | Calculate maximum range taking into account the linger percentage. rangeFromSpeedAndLinger :: Speed -> Int -> Int instance Data.Binary.Class.Binary Game.LambdaHack.Common.Time.Speed instance GHC.Classes.Ord Game.LambdaHack.Common.Time.Speed instance GHC.Classes.Eq Game.LambdaHack.Common.Time.Speed instance GHC.Base.Functor Game.LambdaHack.Common.Time.Delta instance Data.Binary.Class.Binary a => Data.Binary.Class.Binary (Game.LambdaHack.Common.Time.Delta a) instance GHC.Enum.Bounded a => GHC.Enum.Bounded (Game.LambdaHack.Common.Time.Delta a) instance GHC.Enum.Enum a => GHC.Enum.Enum (Game.LambdaHack.Common.Time.Delta a) instance GHC.Classes.Ord a => GHC.Classes.Ord (Game.LambdaHack.Common.Time.Delta a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Game.LambdaHack.Common.Time.Delta a) instance GHC.Show.Show a => GHC.Show.Show (Game.LambdaHack.Common.Time.Delta a) instance Data.Binary.Class.Binary Game.LambdaHack.Common.Time.Time instance GHC.Enum.Bounded Game.LambdaHack.Common.Time.Time instance GHC.Enum.Enum Game.LambdaHack.Common.Time.Time instance GHC.Classes.Ord Game.LambdaHack.Common.Time.Time instance GHC.Classes.Eq Game.LambdaHack.Common.Time.Time instance GHC.Show.Show Game.LambdaHack.Common.Time.Time instance GHC.Show.Show Game.LambdaHack.Common.Time.Speed -- | Basic operations on 2D vectors represented in an efficient, but not -- unique, way. module Game.LambdaHack.Common.Vector -- | 2D vectors in cartesian representation. Coordinates grow to the right -- and down, so that the (1, 1) vector points to the bottom-right corner -- of the screen. data Vector Vector :: X -> Y -> Vector [vx] :: Vector -> X [vy] :: Vector -> Y -- | Tells if a vector has length 1 in the chessboard metric. isUnit :: Vector -> Bool -- | Checks whether a unit vector is a diagonal direction, as opposed to -- cardinal. If the vector is not unit, it checks that the vector is not -- horizontal nor vertical. isDiagonal :: Vector -> Bool -- | Reverse an arbirary vector. neg :: Vector -> Vector -- | The lenght of a vector in the chessboard metric, where diagonal moves -- cost 1. chessDistVector :: Vector -> Int -- | Squared euclidean distance between two vectors. euclidDistSqVector :: Vector -> Vector -> Int -- | Vectors of all unit moves in the chessboard metric, clockwise, -- starting north-west. moves :: [Vector] -- | Vectors of all cardinal direction unit moves, clockwise, starting -- north. movesCardinal :: [Vector] -- | Vectors of all diagonal direction unit moves, clockwise, starting -- north. movesDiagonal :: [Vector] compassText :: Vector -> Text -- | All (8 at most) closest neighbours of a point within an area. vicinity :: X -> Y -> Point -> [Point] vicinityUnsafe :: Point -> [Point] -- | All (4 at most) cardinal direction neighbours of a point within an -- area. vicinityCardinal :: X -> Y -> Point -> [Point] vicinityCardinalUnsafe :: Point -> [Point] squareUnsafeSet :: Point -> EnumSet Point -- | Translate a point by a vector. shift :: Point -> Vector -> Point -- | Translate a point by a vector, but only if the result fits in an area. shiftBounded :: X -> Y -> Point -> Vector -> Point -- | A list of points that a list of vectors leads to. trajectoryToPath :: Point -> [Vector] -> [Point] -- | A list of points that a list of vectors leads to, bounded by level -- size. trajectoryToPathBounded :: X -> Y -> Point -> [Vector] -> [Point] -- | The vector between the second point and the first. We have -- --
--   shift pos1 (pos2 `vectorToFrom` pos1) == pos2
--   
-- -- The arguments are in the same order as in the underlying scalar -- subtraction. vectorToFrom :: Point -> Point -> Vector -- | A list of vectors between a list of points. pathToTrajectory :: [Point] -> [Vector] type RadianAngle = Double -- | Rotate a vector by the given angle (expressed in radians) -- counterclockwise and return a unit vector approximately in the -- resulting direction. rotate :: RadianAngle -> Vector -> Vector -- | Given two distinct positions, determine the direction (a unit vector) -- in which one should move from the first in order to get closer to the -- second. Ignores obstacles. Of several equally good directions (in the -- chessboard metric) it picks one of those that visually (in the -- euclidean metric) maximally align with the vector between the two -- points. towards :: Point -> Point -> Vector instance GHC.Generics.Generic Game.LambdaHack.Common.Vector.Vector instance GHC.Classes.Ord Game.LambdaHack.Common.Vector.Vector instance GHC.Classes.Eq Game.LambdaHack.Common.Vector.Vector instance GHC.Read.Read Game.LambdaHack.Common.Vector.Vector instance GHC.Show.Show Game.LambdaHack.Common.Vector.Vector instance Data.Binary.Class.Binary Game.LambdaHack.Common.Vector.Vector instance GHC.Enum.Enum Game.LambdaHack.Common.Vector.Vector instance Control.DeepSeq.NFData Game.LambdaHack.Common.Vector.Vector -- | Frontend-independent keyboard input operations. module Game.LambdaHack.Client.UI.Key -- | Frontend-independent datatype to represent keys. data Key Esc :: Key Return :: Key Space :: Key Tab :: Key BackTab :: Key BackSpace :: Key PgUp :: Key PgDn :: Key Left :: Key Right :: Key Up :: Key Down :: Key End :: Key Begin :: Key Insert :: Key Delete :: Key Home :: Key -- | a keypad key for a character (digits and operators) KP :: Char -> Key -- | a single printable character Char :: Char -> Key -- | function key Fun :: Int -> Key -- | left mouse button pressed LeftButtonPress :: Key -- | middle mouse button pressed MiddleButtonPress :: Key -- | right mouse button pressed RightButtonPress :: Key -- | left mouse button released LeftButtonRelease :: Key -- | middle mouse button released MiddleButtonRelease :: Key -- | right mouse button released RightButtonRelease :: Key -- | mouse wheel rotated north WheelNorth :: Key -- | mouse wheel rotated south WheelSouth :: Key -- | an unknown key, registered to warn the user Unknown :: String -> Key DeadKey :: Key showKey :: Key -> String -- | Configurable event handler for the direction keys. Used for directed -- commands such as close door. handleDir :: Bool -> Bool -> KM -> Maybe Vector dirAllKey :: Bool -> Bool -> [Key] -- | Binding of both sets of movement keys. moveBinding :: Bool -> Bool -> (Vector -> a) -> (Vector -> a) -> [(KM, a)] mkKM :: String -> KM mkChar :: Char -> KM mkKP :: Char -> KM -- | Translate key from a GTK string description to our internal key type. -- To be used, in particular, for the command bindings and macros in the -- config file. -- -- See -- https://github.com/twobob/gtk-/blob/master/gdk/keyname-table.h keyTranslate :: String -> Key -- | Translate key from a Web API string description -- (https:/developer.mozilla.orgen-USdocsWebAPIKeyboardEvent/key#Key_values) -- to our internal key type. To be used in web frontends. The argument -- says whether Shift is pressed. keyTranslateWeb :: String -> Bool -> Key -- | Our own encoding of modifiers. data Modifier NoModifier :: Modifier Shift :: Modifier Control :: Modifier Alt :: Modifier data KM KM :: Modifier -> Key -> KM [modifier] :: KM -> Modifier [key] :: KM -> Key -- | Show a key with a modifier, if any. showKM :: KM -> String escKM :: KM spaceKM :: KM safeSpaceKM :: KM returnKM :: KM pgupKM :: KM pgdnKM :: KM wheelNorthKM :: KM wheelSouthKM :: KM upKM :: KM downKM :: KM leftKM :: KM rightKM :: KM homeKM :: KM endKM :: KM backspaceKM :: KM leftButtonReleaseKM :: KM rightButtonReleaseKM :: KM instance GHC.Generics.Generic Game.LambdaHack.Client.UI.Key.KM instance GHC.Classes.Eq Game.LambdaHack.Client.UI.Key.KM instance GHC.Classes.Ord Game.LambdaHack.Client.UI.Key.KM instance GHC.Generics.Generic Game.LambdaHack.Client.UI.Key.Modifier instance GHC.Classes.Eq Game.LambdaHack.Client.UI.Key.Modifier instance GHC.Classes.Ord Game.LambdaHack.Client.UI.Key.Modifier instance GHC.Show.Show Game.LambdaHack.Client.UI.Key.Modifier instance GHC.Generics.Generic Game.LambdaHack.Client.UI.Key.Key instance GHC.Classes.Eq Game.LambdaHack.Client.UI.Key.Key instance GHC.Classes.Ord Game.LambdaHack.Client.UI.Key.Key instance Data.Binary.Class.Binary Game.LambdaHack.Client.UI.Key.KM instance Control.DeepSeq.NFData Game.LambdaHack.Client.UI.Key.KM instance GHC.Show.Show Game.LambdaHack.Client.UI.Key.KM instance Data.Binary.Class.Binary Game.LambdaHack.Client.UI.Key.Modifier instance Control.DeepSeq.NFData Game.LambdaHack.Client.UI.Key.Modifier instance Data.Binary.Class.Binary Game.LambdaHack.Client.UI.Key.Key instance Control.DeepSeq.NFData Game.LambdaHack.Client.UI.Key.Key -- | The type of kinds of weapons, treasure, organs, blasts and actors. module Game.LambdaHack.Content.ItemKind -- | Item properties that are fixed for a given kind of items. data ItemKind ItemKind :: Char -> Text -> Freqs ItemKind -> [Flavour] -> Dice -> Rarity -> Part -> Int -> [(Int, Dice)] -> [Aspect] -> [Effect] -> [Feature] -> Text -> [(GroupName ItemKind, CStore)] -> ItemKind -- | map symbol [isymbol] :: ItemKind -> Char -- | generic name [iname] :: ItemKind -> Text -- | frequency within groups [ifreq] :: ItemKind -> Freqs ItemKind -- | possible flavours [iflavour] :: ItemKind -> [Flavour] -- | created in that quantity [icount] :: ItemKind -> Dice -- | rarity on given depths [irarity] :: ItemKind -> Rarity -- | the verb&noun for applying and hit [iverbHit] :: ItemKind -> Part -- | weight in grams [iweight] :: ItemKind -> Int -- | frequency of basic impact damage [idamage] :: ItemKind -> [(Int, Dice)] -- | keep the aspect continuously [iaspects] :: ItemKind -> [Aspect] -- | cause the effect when triggered [ieffects] :: ItemKind -> [Effect] -- | public properties [ifeature] :: ItemKind -> [Feature] -- | description [idesc] :: ItemKind -> Text -- | accompanying organs and items [ikit] :: ItemKind -> [(GroupName ItemKind, CStore)] -- | Effects of items. Can be invoked by the item wielder to affect another -- actor or the wielder himself. Many occurences in the same item are -- possible. Constructors are sorted vs increasing impact/danger. data Effect -- | secret (learned as effect) label of the item ELabel :: Text -> Effect -- | AI and UI flag that leaks item properties EqpSlot :: EqpSlot -> Effect Burn :: Dice -> Effect -- | explode, producing this group of blasts Explode :: (GroupName ItemKind) -> Effect RefillHP :: Int -> Effect RefillCalm :: Int -> Effect Dominate :: Effect Impress :: Effect Summon :: (GroupName ItemKind) -> Dice -> Effect Ascend :: Bool -> Effect Escape :: Effect -- | expressed in game clips Paralyze :: Dice -> Effect -- | expressed in game turns InsertMove :: Dice -> Effect Teleport :: Dice -> Effect -- | create an item of the group and insert into the store with the given -- random timer CreateItem :: CStore -> (GroupName ItemKind) -> TimerDice -> Effect DropItem :: Int -> Int -> CStore -> (GroupName ItemKind) -> Effect PolyItem :: Effect Identify :: Effect Detect :: Int -> Effect DetectActor :: Int -> Effect DetectItem :: Int -> Effect DetectExit :: Int -> Effect DetectHidden :: Int -> Effect SendFlying :: ThrowMod -> Effect PushActor :: ThrowMod -> Effect PullActor :: ThrowMod -> Effect DropBestWeapon :: Effect -- | symbol ' ' means all ActivateInv :: Char -> Effect ApplyPerfume :: Effect OneOf :: [Effect] -> Effect -- | trigger if item smashed (not applied nor meleed) OnSmash :: Effect -> Effect -- | this effect inactive until timeout passes Recharging :: Effect -> Effect -- | the item is temporary, vanishes at even void Periodic activation, -- unless Durable and not Fragile, and shows message with this verb at -- last copy activation or at each activation unless Durable and Fragile Temporary :: Text -> Effect -- | at most one copy can ever be generated Unique :: Effect -- | in eqp, triggered as often as Timeout permits Periodic :: Effect data TimerDice TimerNone :: TimerDice TimerGameTurn :: Dice -> TimerDice TimerActorTurn :: Dice -> TimerDice -- | Aspects of items. Those that are named Add* are additive -- (starting at 0) for all items wielded by an actor and they affect the -- actor. data Aspect -- | some effects disabled until item recharges; expressed in game turns Timeout :: Dice -> Aspect -- | percentage damage bonus in melee AddHurtMelee :: Dice -> Aspect -- | percentage armor bonus against melee AddArmorMelee :: Dice -> Aspect -- | percentage armor bonus against ranged AddArmorRanged :: Dice -> Aspect -- | maximal hp AddMaxHP :: Dice -> Aspect -- | maximal calm AddMaxCalm :: Dice -> Aspect -- | speed in m/10s (not of a projectile) AddSpeed :: Dice -> Aspect -- | FOV radius, where 1 means a single tile AddSight :: Dice -> Aspect -- | smell radius, where 1 means a single tile AddSmell :: Dice -> Aspect -- | shine radius, where 1 means a single tile AddShine :: Dice -> Aspect -- | noctovision radius, where 1 is single tile AddNocto :: Dice -> Aspect -- | aggression, especially closing in for melee AddAggression :: Dice -> Aspect -- | bonus to an ability AddAbility :: Ability -> Dice -> Aspect -- | Parameters modifying a throw of a projectile or flight of pushed -- actor. Not additive and don't start at 0. data ThrowMod ThrowMod :: Int -> Int -> ThrowMod -- | fly with this percentage of base throw speed [throwVelocity] :: ThrowMod -> Int -- | fly for this percentage of 2 turns [throwLinger] :: ThrowMod -> Int -- | Features of item. Affect only the item in question, not the actor, and -- so not additive in any sense. data Feature -- | drop and break at target tile, even if no hit Fragile :: Feature -- | drop at target tile, even if no hit Lobable :: Feature -- | don't break even when hitting or applying Durable :: Feature -- | parameters modifying a throw ToThrow :: ThrowMod -> Feature -- | the item starts identified Identified :: Feature -- | AI and UI flag: consider applying Applicable :: Feature -- | AI and UI flag: consider equipping (independent of ^ EqpSlot, -- e.g., in case of mixed blessings) Equipable :: Feature -- | AI and UI flag: consider meleeing with Meleeable :: Feature -- | AI and UI flag: don't risk identifying by use also, can't throw or -- apply if not calm enough; Precious :: Feature -- | overrides actor's tactic Tactic :: Tactic -> Feature data EqpSlot EqpSlotMiscBonus :: EqpSlot EqpSlotAddHurtMelee :: EqpSlot EqpSlotAddArmorMelee :: EqpSlot EqpSlotAddArmorRanged :: EqpSlot EqpSlotAddMaxHP :: EqpSlot EqpSlotAddSpeed :: EqpSlot EqpSlotAddSight :: EqpSlot EqpSlotLightSource :: EqpSlot EqpSlotWeapon :: EqpSlot EqpSlotMiscAbility :: EqpSlot EqpSlotAbMove :: EqpSlot EqpSlotAbMelee :: EqpSlot EqpSlotAbDisplace :: EqpSlot EqpSlotAbAlter :: EqpSlot EqpSlotAbProject :: EqpSlot EqpSlotAbApply :: EqpSlot EqpSlotAddMaxCalm :: EqpSlot EqpSlotAddSmell :: EqpSlot EqpSlotAddNocto :: EqpSlot EqpSlotAddAggression :: EqpSlot EqpSlotAbWait :: EqpSlot EqpSlotAbMoveItem :: EqpSlot forApplyEffect :: Effect -> Bool forIdEffect :: Effect -> Bool toDmg :: Dice -> [(Int, Dice)] toVelocity :: Int -> Feature toLinger :: Int -> Feature toOrganGameTurn :: GroupName ItemKind -> Dice -> Effect toOrganActorTurn :: GroupName ItemKind -> Dice -> Effect toOrganNone :: GroupName ItemKind -> Effect -- | Catch invalid item kind definitions. validateSingleItemKind :: ItemKind -> [Text] -- | Validate all item kinds. validateAllItemKind :: [ItemKind] -> [Text] instance GHC.Show.Show Game.LambdaHack.Content.ItemKind.ItemKind instance GHC.Generics.Generic Game.LambdaHack.Content.ItemKind.Effect instance GHC.Classes.Ord Game.LambdaHack.Content.ItemKind.Effect instance GHC.Classes.Eq Game.LambdaHack.Content.ItemKind.Effect instance GHC.Show.Show Game.LambdaHack.Content.ItemKind.Effect instance GHC.Generics.Generic Game.LambdaHack.Content.ItemKind.EqpSlot instance GHC.Enum.Bounded Game.LambdaHack.Content.ItemKind.EqpSlot instance GHC.Enum.Enum Game.LambdaHack.Content.ItemKind.EqpSlot instance GHC.Classes.Ord Game.LambdaHack.Content.ItemKind.EqpSlot instance GHC.Classes.Eq Game.LambdaHack.Content.ItemKind.EqpSlot instance GHC.Show.Show Game.LambdaHack.Content.ItemKind.EqpSlot instance GHC.Generics.Generic Game.LambdaHack.Content.ItemKind.Feature instance GHC.Classes.Ord Game.LambdaHack.Content.ItemKind.Feature instance GHC.Classes.Eq Game.LambdaHack.Content.ItemKind.Feature instance GHC.Show.Show Game.LambdaHack.Content.ItemKind.Feature instance GHC.Generics.Generic Game.LambdaHack.Content.ItemKind.ThrowMod instance GHC.Classes.Ord Game.LambdaHack.Content.ItemKind.ThrowMod instance GHC.Classes.Eq Game.LambdaHack.Content.ItemKind.ThrowMod instance GHC.Show.Show Game.LambdaHack.Content.ItemKind.ThrowMod instance GHC.Generics.Generic Game.LambdaHack.Content.ItemKind.Aspect instance GHC.Classes.Ord Game.LambdaHack.Content.ItemKind.Aspect instance GHC.Classes.Eq Game.LambdaHack.Content.ItemKind.Aspect instance GHC.Show.Show Game.LambdaHack.Content.ItemKind.Aspect instance GHC.Generics.Generic Game.LambdaHack.Content.ItemKind.TimerDice instance GHC.Classes.Ord Game.LambdaHack.Content.ItemKind.TimerDice instance GHC.Classes.Eq Game.LambdaHack.Content.ItemKind.TimerDice instance Control.DeepSeq.NFData Game.LambdaHack.Content.ItemKind.Effect instance Data.Hashable.Class.Hashable Game.LambdaHack.Content.ItemKind.Effect instance Data.Binary.Class.Binary Game.LambdaHack.Content.ItemKind.Effect instance Control.DeepSeq.NFData Game.LambdaHack.Content.ItemKind.EqpSlot instance Data.Hashable.Class.Hashable Game.LambdaHack.Content.ItemKind.EqpSlot instance Data.Binary.Class.Binary Game.LambdaHack.Content.ItemKind.EqpSlot instance Data.Hashable.Class.Hashable Game.LambdaHack.Content.ItemKind.Feature instance Data.Binary.Class.Binary Game.LambdaHack.Content.ItemKind.Feature instance Control.DeepSeq.NFData Game.LambdaHack.Content.ItemKind.ThrowMod instance Data.Hashable.Class.Hashable Game.LambdaHack.Content.ItemKind.ThrowMod instance Data.Binary.Class.Binary Game.LambdaHack.Content.ItemKind.ThrowMod instance Data.Hashable.Class.Hashable Game.LambdaHack.Content.ItemKind.Aspect instance Data.Binary.Class.Binary Game.LambdaHack.Content.ItemKind.Aspect instance GHC.Show.Show Game.LambdaHack.Content.ItemKind.TimerDice instance Control.DeepSeq.NFData Game.LambdaHack.Content.ItemKind.TimerDice instance Data.Hashable.Class.Hashable Game.LambdaHack.Content.ItemKind.TimerDice instance Data.Binary.Class.Binary Game.LambdaHack.Content.ItemKind.TimerDice -- | The type of game rule sets and assorted game data. module Game.LambdaHack.Content.RuleKind -- | The type of game rule sets and assorted game data. -- -- For now the rules are immutable througout the game, so there is no -- type Rule to hold any changing parameters, just -- RuleKind for the fixed set. However, in the future, if the -- rules can get changed during gameplay based on data mining of player -- behaviour, we may add such a type and then RuleKind will -- become just a starting template, analogously as for the other content. data RuleKind RuleKind :: Char -> Text -> Freqs RuleKind -> Text -> FilePath -> Version -> FilePath -> String -> Text -> Bool -> Int -> Int -> FilePath -> Int -> RuleKind -- | a symbol [rsymbol] :: RuleKind -> Char -- | short description [rname] :: RuleKind -> Text -- | frequency within groups [rfreq] :: RuleKind -> Freqs RuleKind -- | title of the game (not lib) [rtitle] :: RuleKind -> Text -- | font directory for the game (not lib) [rfontDir] :: RuleKind -> FilePath -- | version of the game [rexeVersion] :: RuleKind -> Version -- | name of the UI config file [rcfgUIName] :: RuleKind -> FilePath -- | the default UI settings config file [rcfgUIDefault] :: RuleKind -> String -- | the ASCII art for the Main Menu [rmainMenuArt] :: RuleKind -> Text -- | whether first non-spawner actor death ends the game [rfirstDeathEnds] :: RuleKind -> Bool -- | game is saved that often [rwriteSaveClips] :: RuleKind -> Int -- | server switches leader level that often [rleadLevelClips] :: RuleKind -> Int -- | name of the scores file [rscoresFile] :: RuleKind -> FilePath -- | what distance between actors is nearby [rnearby] :: RuleKind -> Int -- | Catch invalid rule kind definitions. validateSingleRuleKind :: RuleKind -> [Text] -- | Since we have only one rule kind, the set of rule kinds is always -- valid. validateAllRuleKind :: [RuleKind] -> [Text] instance GHC.Show.Show Game.LambdaHack.Content.RuleKind.RuleKind -- | The type of kinds of terrain tiles. module Game.LambdaHack.Content.TileKind -- | 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 KindOps.Id index. -- The talter for unknown space is 1 and no other tile -- kind has that value. data TileKind TileKind :: Char -> Text -> Freqs TileKind -> Color -> Color -> Word8 -> [Feature] -> TileKind -- | map symbol [tsymbol] :: TileKind -> Char -- | short description [tname] :: TileKind -> Text -- | frequency within groups [tfreq] :: TileKind -> Freqs TileKind -- | map color [tcolor] :: TileKind -> Color -- | map color when not in FOV [tcolor2] :: TileKind -> Color -- | minimal skill needed to alter the tile [talter] :: TileKind -> Word8 -- | properties [tfeature] :: TileKind -> [Feature] -- | All possible terrain tile features. data Feature -- | initially an item of this group is embedded; we assume the item has -- effects and is supposed to be triggered Embed :: (GroupName ItemKind) -> Feature -- | goes from a closed to (randomly closed or) open tile when altered OpenTo :: (GroupName TileKind) -> Feature -- | goes from an open to (randomly opened or) closed tile when altered CloseTo :: (GroupName TileKind) -> Feature -- | alters tile, but does not change walkability ChangeTo :: (GroupName TileKind) -> Feature -- | when hidden, looks as the unique tile of the group HideAs :: (GroupName TileKind) -> Feature -- | when generating, may be transformed to the unique tile of the group BuildAs :: (GroupName TileKind) -> Feature -- | when generating in opening, can be revealed to belong to the group RevealAs :: (GroupName TileKind) -> Feature -- | when generating in solid wall, can be revealed to belong to the group ObscureAs :: (GroupName TileKind) -> Feature -- | actors can walk through Walkable :: Feature -- | actors can see through Clear :: Feature -- | is not lit with an ambient light Dark :: Feature -- | initial items often generated there OftenItem :: Feature -- | initial actors often generated there OftenActor :: Feature -- | no items ever generated there NoItem :: Feature -- | no actors ever generated there NoActor :: Feature -- | is allowed to have the same look as another tile Indistinct :: Feature -- | even if otherwise uninteresting, taken into account for triggering by -- AI ConsideredByAI :: Feature -- | used for visible trails throughout the level Trail :: Feature -- | 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 and at most -- one spicy is rolled per place and then one of the two is rolled for -- each position Spice :: Feature -- | Validate a single tile kind. validateSingleTileKind :: TileKind -> [Text] -- | Validate all tile kinds. -- -- If tiles look the same on the map (symbol and color), their -- substantial features should be the same, too. Otherwise, the player -- has to inspect manually all the tiles of that kind, or even experiment -- with them, to see if any is special. This would be tedious. Note that -- tiles may freely differ wrt text blurb, dungeon generation, AI -- preferences, etc. validateAllTileKind :: [TileKind] -> [Text] -- | Features of tiles that differentiate them substantially from one -- another. The intention is the player can easily tell such tiles apart -- by their behaviour and only looking at the map, not tile name nor -- description. So if running uses this function, it won't stop at places -- that the player can't himself tell from other places, and so running -- does not confer any advantages, except UI convenience. Hashes are -- accurate enough for our purpose, given that we use arbitrary -- heuristics anyway. actionFeatures :: Bool -> TileKind -> IntSet data TileSpeedup TileSpeedup :: Tab Bool -> Tab Bool -> Tab Bool -> Tab Bool -> Tab Bool -> Tab Bool -> Tab Bool -> Tab Bool -> Tab Bool -> Tab Bool -> Tab Bool -> Tab Bool -> Tab Bool -> Tab Word8 -> Tab Word8 -> TileSpeedup [isClearTab] :: TileSpeedup -> Tab Bool [isLitTab] :: TileSpeedup -> Tab Bool [isWalkableTab] :: TileSpeedup -> Tab Bool [isDoorTab] :: TileSpeedup -> Tab Bool [isChangableTab] :: TileSpeedup -> Tab Bool [isSuspectTab] :: TileSpeedup -> Tab Bool [isHideAsTab] :: TileSpeedup -> Tab Bool [consideredByAITab] :: TileSpeedup -> Tab Bool [isOftenItemTab] :: TileSpeedup -> Tab Bool [isOftenActorTab] :: TileSpeedup -> Tab Bool [isNoItemTab] :: TileSpeedup -> Tab Bool [isNoActorTab] :: TileSpeedup -> Tab Bool [isEasyOpenTab] :: TileSpeedup -> Tab Bool [alterMinSkillTab] :: TileSpeedup -> Tab Word8 [alterMinWalkTab] :: TileSpeedup -> Tab Word8 newtype Tab a Tab :: (Vector a) -> Tab a isUknownSpace :: Id TileKind -> Bool unknownId :: Id TileKind isSuspectKind :: TileKind -> Bool isOpenableKind :: TileKind -> Bool isClosableKind :: TileKind -> Bool talterForStairs :: Word8 floorSymbol :: Char instance GHC.Show.Show Game.LambdaHack.Content.TileKind.TileKind instance GHC.Generics.Generic Game.LambdaHack.Content.TileKind.Feature instance GHC.Classes.Ord Game.LambdaHack.Content.TileKind.Feature instance GHC.Classes.Eq Game.LambdaHack.Content.TileKind.Feature instance GHC.Show.Show Game.LambdaHack.Content.TileKind.Feature instance Data.Binary.Class.Binary Game.LambdaHack.Content.TileKind.Feature instance Data.Hashable.Class.Hashable Game.LambdaHack.Content.TileKind.Feature instance Control.DeepSeq.NFData Game.LambdaHack.Content.TileKind.Feature -- | The type of kinds of rooms, halls and passages. module Game.LambdaHack.Content.PlaceKind -- | Parameters for the generation of small areas within a dungeon level. data PlaceKind PlaceKind :: Char -> Text -> Freqs PlaceKind -> Rarity -> Cover -> Fence -> [Text] -> [(Char, GroupName TileKind)] -> PlaceKind -- | a symbol [psymbol] :: PlaceKind -> Char -- | short description [pname] :: PlaceKind -> Text -- | frequency within groups [pfreq] :: PlaceKind -> Freqs PlaceKind -- | rarity on given depths [prarity] :: PlaceKind -> Rarity -- | how to fill whole place based on the corner [pcover] :: PlaceKind -> Cover -- | whether to fence place with solid border [pfence] :: PlaceKind -> Fence -- | plan of the top-left corner of the place [ptopLeft] :: PlaceKind -> [Text] -- | legend override [poverride] :: PlaceKind -> [(Char, GroupName TileKind)] -- | A method of filling the whole area (except for CVerbatim and CMirror, -- which are just placed in the middle of the area) by transforming a -- given corner. data Cover -- | reflect every other corner, overlapping 1 row and column CAlternate :: Cover -- | fill symmetrically 4 corners and stretch their borders CStretch :: Cover -- | tile separately and symmetrically quarters of the place CReflect :: Cover -- | just build the given interior, without filling the area CVerbatim :: Cover -- | build the given interior in one of 4 mirrored variants CMirror :: Cover -- | The choice of a fence type for the place. data Fence -- | put a solid wall fence around the place FWall :: Fence -- | leave an empty space, like the rooms floor FFloor :: Fence -- | leave an empty space, like the caves ground FGround :: Fence -- | skip the fence and fill all with the place proper FNone :: Fence -- | Catch invalid place kind definitions. In particular, verify that the -- top-left corner map is rectangular and not empty. validateSinglePlaceKind :: PlaceKind -> [Text] -- | Validate all place kinds. Currently always valid. validateAllPlaceKind :: [PlaceKind] -> [Text] instance GHC.Show.Show Game.LambdaHack.Content.PlaceKind.PlaceKind instance GHC.Classes.Eq Game.LambdaHack.Content.PlaceKind.Fence instance GHC.Show.Show Game.LambdaHack.Content.PlaceKind.Fence instance GHC.Classes.Eq Game.LambdaHack.Content.PlaceKind.Cover instance GHC.Show.Show Game.LambdaHack.Content.PlaceKind.Cover -- | The type of cave layout kinds. module Game.LambdaHack.Content.CaveKind -- | Parameters for the generation of dungeon levels. Warning: for -- efficiency, avoid embedded items in any of the common tiles. data CaveKind CaveKind :: Char -> Text -> Freqs CaveKind -> X -> Y -> DiceXY -> DiceXY -> DiceXY -> Dice -> Dice -> Rational -> Rational -> Int -> Dice -> Chance -> Chance -> Int -> Int -> Freqs ItemKind -> Dice -> Freqs ItemKind -> Freqs PlaceKind -> Bool -> GroupName TileKind -> GroupName TileKind -> GroupName TileKind -> GroupName TileKind -> GroupName TileKind -> GroupName TileKind -> GroupName TileKind -> Maybe (GroupName PlaceKind) -> Freqs PlaceKind -> CaveKind -- | a symbol [csymbol] :: CaveKind -> Char -- | short description [cname] :: CaveKind -> Text -- | frequency within groups [cfreq] :: CaveKind -> Freqs CaveKind -- | X size of the whole cave [cxsize] :: CaveKind -> X -- | Y size of the whole cave [cysize] :: CaveKind -> Y -- | the dimensions of the grid of places [cgrid] :: CaveKind -> DiceXY -- | minimal size of places; for merging [cminPlaceSize] :: CaveKind -> DiceXY -- | maximal size of places [cmaxPlaceSize] :: CaveKind -> DiceXY -- | the chance a place is dark [cdarkChance] :: CaveKind -> Dice -- | the chance the cave is dark [cnightChance] :: CaveKind -> Dice -- | a proportion of extra connections [cauxConnects] :: CaveKind -> Rational -- | at most this proportion of rooms void [cmaxVoid] :: CaveKind -> Rational -- | minimal distance between stairs [cminStairDist] :: CaveKind -> Int -- | extra stairs on top of from above [cextraStairs] :: CaveKind -> Dice -- | the chance of a door in an opening [cdoorChance] :: CaveKind -> Chance -- | if there's a door, is it open? [copenChance] :: CaveKind -> Chance -- | if not open, hidden one in n times [chidden] :: CaveKind -> Int -- | the lower, the more monsters spawn [cactorCoeff] :: CaveKind -> Int -- | actor groups to consider [cactorFreq] :: CaveKind -> Freqs ItemKind -- | the number of items in the cave [citemNum] :: CaveKind -> Dice -- | item groups to consider [citemFreq] :: CaveKind -> Freqs ItemKind -- | place groups to consider [cplaceFreq] :: CaveKind -> Freqs PlaceKind -- | are passable default tiles permitted [cpassable] :: CaveKind -> Bool -- | the default cave tile [cdefTile] :: CaveKind -> GroupName TileKind -- | the dark cave corridor tile [cdarkCorTile] :: CaveKind -> GroupName TileKind -- | the lit cave corridor tile [clitCorTile] :: CaveKind -> GroupName TileKind -- | the filler wall [cfillerTile] :: CaveKind -> GroupName TileKind -- | the outer fence wall [couterFenceTile] :: CaveKind -> GroupName TileKind -- | the dark place plan legend [clegendDarkTile] :: CaveKind -> GroupName TileKind -- | the lit place plan legend [clegendLitTile] :: CaveKind -> GroupName TileKind -- | escape, if any [cescapeGroup] :: CaveKind -> Maybe (GroupName PlaceKind) -- | place groups to consider for stairs; in this case the rarity of items -- in the group does not affect group choice [cstairFreq] :: CaveKind -> Freqs PlaceKind -- | Catch caves with not enough space for all the places. Check the size -- of the cave descriptions to make sure they fit on screen. Etc. validateSingleCaveKind :: CaveKind -> [Text] -- | Validate all cave kinds. Note that names don't have to be unique: we -- can have several variants of a cave with a given name. validateAllCaveKind :: [CaveKind] -> [Text] instance GHC.Show.Show Game.LambdaHack.Content.CaveKind.CaveKind -- | The type of kinds of game modes. module Game.LambdaHack.Content.ModeKind -- | Requested cave groups for particular levels. The second component is -- the Escape feature on the level. True means it's -- represented by <, False, by >. type Caves = IntMap (GroupName CaveKind) -- | The specification of players for the game mode. data Roster Roster :: [(Player, [(Int, Dice, GroupName ItemKind)])] -> [(Text, Text)] -> [(Text, Text)] -> Roster -- | players in the particular team and levels, numbers and groups of their -- initial members [rosterList] :: Roster -> [(Player, [(Int, Dice, GroupName ItemKind)])] -- | the initial enmity matrix [rosterEnemy] :: Roster -> [(Text, Text)] -- | the initial aliance matrix [rosterAlly] :: Roster -> [(Text, Text)] -- | Properties of a particular player. data Player Player :: Text -> [GroupName ItemKind] -> Skills -> Bool -> Bool -> HiCondPoly -> Bool -> Tactic -> LeaderMode -> Bool -> Player -- | name of the player [fname] :: Player -> Text -- | names of actor groups that may naturally fall under player's control, -- e.g., upon spawning or summoning [fgroups] :: Player -> [GroupName ItemKind] -- | fixed skill modifiers to the non-leader actors; also summed with -- skills implied by ftactic (which is not fixed) [fskillsOther] :: Player -> Skills -- | the player can escape the dungeon [fcanEscape] :: Player -> Bool -- | the faction declared killed if no actors [fneverEmpty] :: Player -> Bool -- | score polynomial for the player [fhiCondPoly] :: Player -> HiCondPoly -- | whether actors have gender [fhasGender] :: Player -> Bool -- | non-leaders behave according to this tactic; can be changed during the -- game [ftactic] :: Player -> Tactic -- | the mode of switching the leader [fleaderMode] :: Player -> LeaderMode -- | does the faction have a UI client (for control or passive observation) [fhasUI] :: Player -> Bool -- | Game mode specification. data ModeKind ModeKind :: Char -> Text -> Freqs ModeKind -> Roster -> Caves -> Text -> ModeKind -- | a symbol [msymbol] :: ModeKind -> Char -- | short description [mname] :: ModeKind -> Text -- | frequency within groups [mfreq] :: ModeKind -> Freqs ModeKind -- | players taking part in the game [mroster] :: ModeKind -> Roster -- | arena of the game [mcaves] :: ModeKind -> Caves -- | description [mdesc] :: ModeKind -> Text -- | If a faction with LeaderUI and LeaderAI has any -- actor, it has a leader. data LeaderMode -- | faction can have no leader, is whole under AI control LeaderNull :: LeaderMode -- | leader under AI control LeaderAI :: AutoLeader -> LeaderMode -- | leader under UI control, assumes fhasUI LeaderUI :: AutoLeader -> LeaderMode data AutoLeader AutoLeader :: Bool -> Bool -> AutoLeader -- | leader switching between levels is automatically done by the server -- and client is not permitted to change to leaders from other levels -- (the frequency of leader level switching done by the server is -- controlled by RuleKind.rleadLevelClips); if the flag is -- False, server still does a subset of the automatic switching, -- e.g., when the old leader dies and no other actor of the faction -- resides on his level, but the client (particularly UI) is expected to -- do changes as well [autoDungeon] :: AutoLeader -> Bool -- | client is discouraged from leader switching (e.g., because non-leader -- actors have the same skills as leader); server is guaranteed to switch -- leader within a level very rarely, e.g., when the old leader dies; if -- the flag is False, server still does a subset of the -- automatic switching, but the client is expected to do more, because -- it's advantageous for that kind of a faction [autoLevel] :: AutoLeader -> Bool -- | Outcome of a game. data Outcome -- | the faction was eliminated Killed :: Outcome -- | the faction lost the game in another way Defeated :: Outcome -- | game is supended Camping :: Outcome -- | the player won by eliminating all rivals Conquer :: Outcome -- | the player escaped the dungeon alive Escape :: Outcome -- | game is restarted Restart :: Outcome data HiIndeterminant HiConst :: HiIndeterminant HiLoot :: HiIndeterminant HiBlitz :: HiIndeterminant HiSurvival :: HiIndeterminant HiKill :: HiIndeterminant HiLoss :: HiIndeterminant -- | Conditional polynomial representing score calculation for this player. type HiCondPoly = [HiSummand] type HiSummand = (HiPolynomial, [Outcome]) type HiPolynomial = [(HiIndeterminant, Double)] -- | Catch invalid game mode kind definitions. validateSingleModeKind :: ModeKind -> [Text] -- | Validate game mode kinds together. validateAllModeKind :: [ModeKind] -> [Text] instance GHC.Show.Show Game.LambdaHack.Content.ModeKind.ModeKind instance GHC.Classes.Eq Game.LambdaHack.Content.ModeKind.Roster instance GHC.Show.Show Game.LambdaHack.Content.ModeKind.Roster instance GHC.Generics.Generic Game.LambdaHack.Content.ModeKind.Player instance GHC.Classes.Ord Game.LambdaHack.Content.ModeKind.Player instance GHC.Classes.Eq Game.LambdaHack.Content.ModeKind.Player instance GHC.Show.Show Game.LambdaHack.Content.ModeKind.Player instance GHC.Generics.Generic Game.LambdaHack.Content.ModeKind.LeaderMode instance GHC.Classes.Ord Game.LambdaHack.Content.ModeKind.LeaderMode instance GHC.Classes.Eq Game.LambdaHack.Content.ModeKind.LeaderMode instance GHC.Show.Show Game.LambdaHack.Content.ModeKind.LeaderMode instance GHC.Generics.Generic Game.LambdaHack.Content.ModeKind.AutoLeader instance GHC.Classes.Ord Game.LambdaHack.Content.ModeKind.AutoLeader instance GHC.Classes.Eq Game.LambdaHack.Content.ModeKind.AutoLeader instance GHC.Show.Show Game.LambdaHack.Content.ModeKind.AutoLeader instance GHC.Generics.Generic Game.LambdaHack.Content.ModeKind.HiIndeterminant instance GHC.Classes.Ord Game.LambdaHack.Content.ModeKind.HiIndeterminant instance GHC.Classes.Eq Game.LambdaHack.Content.ModeKind.HiIndeterminant instance GHC.Show.Show Game.LambdaHack.Content.ModeKind.HiIndeterminant instance GHC.Generics.Generic Game.LambdaHack.Content.ModeKind.Outcome instance GHC.Enum.Bounded Game.LambdaHack.Content.ModeKind.Outcome instance GHC.Enum.Enum Game.LambdaHack.Content.ModeKind.Outcome instance GHC.Classes.Ord Game.LambdaHack.Content.ModeKind.Outcome instance GHC.Classes.Eq Game.LambdaHack.Content.ModeKind.Outcome instance GHC.Show.Show Game.LambdaHack.Content.ModeKind.Outcome instance Data.Binary.Class.Binary Game.LambdaHack.Content.ModeKind.Player instance Data.Binary.Class.Binary Game.LambdaHack.Content.ModeKind.LeaderMode instance Data.Binary.Class.Binary Game.LambdaHack.Content.ModeKind.AutoLeader instance Data.Binary.Class.Binary Game.LambdaHack.Content.ModeKind.HiIndeterminant instance Data.Binary.Class.Binary Game.LambdaHack.Content.ModeKind.Outcome -- | General content types and operations. module Game.LambdaHack.Common.Kind -- | Content identifiers for the content type c. data Id c -- | Content operations for the content of type a. data Ops a Ops :: (Id a -> a) -> (GroupName a -> Id a) -> (GroupName a -> (a -> Bool) -> Rnd (Maybe (Id a))) -> (forall b. (Id a -> a -> b -> b) -> b -> b) -> (forall b. (b -> Id a -> a -> b) -> b -> b) -> (forall b. GroupName a -> (b -> Int -> Id a -> a -> b) -> b -> b) -> Int -> Ops a -- | content element at given id [okind] :: Ops a -> Id a -> a -- | the id of the unique member of a singleton content group [ouniqGroup] :: Ops a -> GroupName a -> Id a -- | pick a random id belonging to a group and satisfying a predicate [opick] :: Ops a -> GroupName a -> (a -> Bool) -> Rnd (Maybe (Id a)) -- | fold over all content elements of a [ofoldrWithKey] :: Ops a -> forall b. (Id a -> a -> b -> b) -> b -> b -- | fold strictly over all content a [ofoldlWithKey'] :: Ops a -> forall b. (b -> Id a -> a -> b) -> b -> b -- | fold over the given group only [ofoldlGroup'] :: Ops a -> forall b. GroupName a -> (b -> Int -> Id a -> a -> b) -> b -> b -- | size of content a [olength] :: Ops a -> Int -- | Operations for all content types, gathered together. data COps COps :: Ops CaveKind -> Ops ItemKind -> Ops ModeKind -> Ops PlaceKind -> Ops RuleKind -> Ops TileKind -> TileSpeedup -> COps [cocave] :: COps -> Ops CaveKind [coitem] :: COps -> Ops ItemKind [comode] :: COps -> Ops ModeKind [coplace] :: COps -> Ops PlaceKind [corule] :: COps -> Ops RuleKind [cotile] :: COps -> Ops TileKind [coTileSpeedup] :: COps -> TileSpeedup -- | Create content operations for type a from definition of -- content of type a. createOps :: forall a. Show a => ContentDef a -> Ops a -- | The standard ruleset used for level operations. stdRuleset :: Ops RuleKind -> RuleKind instance GHC.Show.Show Game.LambdaHack.Common.Kind.COps instance GHC.Classes.Eq Game.LambdaHack.Common.Kind.COps -- | Operations concerning dungeon level tiles. -- -- Unlike for many other content types, there is no type Tile, -- of particular concrete tiles in the dungeon, corresponding to -- TileKind (the type of kinds of terrain tiles). This is because -- the tiles are too numerous and there's not enough storage space for a -- well-rounded Tile type, on one hand, and on the other hand, -- tiles are accessed too often in performance critical code to try to -- compress their representation and/or recompute them. Instead, of -- defining a Tile type, we express various properties of -- concrete tiles by arrays or sparse EnumMaps, as appropriate. -- -- Actors at normal speed (2 m/s) take one turn to move one tile (1 m by -- 1 m). module Game.LambdaHack.Common.Tile -- | Whether a tile kind has the given feature. kindHasFeature :: Feature -> TileKind -> Bool -- | Whether a tile kind (specified by its id) has the given feature. hasFeature :: Ops TileKind -> Feature -> Id TileKind -> Bool -- | Whether a tile does not block vision. Essential for efficiency of -- FOV, hence tabulated. isClear :: TileSpeedup -> Id TileKind -> Bool -- | Whether a tile has ambient light --- is lit on its own. Essential for -- efficiency of Perception, hence tabulated. isLit :: TileSpeedup -> Id TileKind -> Bool -- | Whether actors can walk into a tile. Essential for efficiency of -- pathfinding, hence tabulated. isWalkable :: TileSpeedup -> Id TileKind -> Bool -- | Whether a tile is a door, open or closed. Essential for efficiency of -- pathfinding, hence tabulated. isDoor :: TileSpeedup -> Id TileKind -> Bool -- | Whether a tile is changable. isChangable :: TileSpeedup -> Id TileKind -> Bool -- | Whether a tile is suspect. Essential for efficiency of pathfinding, -- hence tabulated. isSuspect :: TileSpeedup -> Id TileKind -> Bool isHideAs :: TileSpeedup -> Id TileKind -> Bool consideredByAI :: TileSpeedup -> Id TileKind -> Bool -- | Whether one can easily explore a tile, possibly finding a treasure, -- either spawned there or dropped there by a (dying from poison) foe. -- Doors can't be explorable since revealing a secret tile should not -- change it's (walkable and) explorable status. Door status should not -- depend on whether they are open or not so that a foe opening a door -- doesn't force us to backtrack to explore it. Still, a foe that digs -- through a wall will affect our exploration counter and if content lets -- walls contain threasure, such backtraking makes sense. isExplorable :: TileSpeedup -> Id TileKind -> Bool isOftenItem :: TileSpeedup -> Id TileKind -> Bool isOftenActor :: TileSpeedup -> Id TileKind -> Bool isNoItem :: TileSpeedup -> Id TileKind -> Bool isNoActor :: TileSpeedup -> Id TileKind -> Bool -- | Whether a tile kind (specified by its id) has an OpenTo feature and -- reasonable alter min skill. isEasyOpen :: TileSpeedup -> Id TileKind -> Bool speedup :: Bool -> Ops TileKind -> TileSpeedup alterMinSkill :: TileSpeedup -> Id TileKind -> Int alterMinWalk :: TileSpeedup -> Id TileKind -> Int openTo :: Ops TileKind -> Id TileKind -> Rnd (Id TileKind) closeTo :: Ops TileKind -> Id TileKind -> Rnd (Id TileKind) embeddedItems :: Ops TileKind -> Id TileKind -> [GroupName ItemKind] revealAs :: Ops TileKind -> Id TileKind -> Rnd (Id TileKind) obscureAs :: Ops TileKind -> Id TileKind -> Rnd (Id TileKind) hideAs :: Ops TileKind -> Id TileKind -> Id TileKind buildAs :: Ops TileKind -> Id TileKind -> Id TileKind isEasyOpenKind :: TileKind -> Bool -- | Whether a tile kind (specified by its id) has an OpenTo feature. isOpenable :: Ops TileKind -> Id TileKind -> Bool -- | Whether a tile kind (specified by its id) has a CloseTo feature. isClosable :: Ops TileKind -> Id TileKind -> Bool createTab :: Unbox a => Ops TileKind -> (TileKind -> a) -> Tab a createTabWithKey :: Unbox a => Ops TileKind -> (Id TileKind -> TileKind -> a) -> Tab a accessTab :: Unbox a => Tab a -> Id TileKind -> a -- | Weapons, treasure and all the other items in the game. No operation in -- this module involves the state or any of our custom monads. module Game.LambdaHack.Common.Item -- | A unique identifier of an item in the dungeon. data ItemId -- | Game items in actor possesion or strewn around the dungeon. The fields -- jsymbol, jname and jflavour make it -- possible to refer to and draw an unidentified item. Full information -- about item is available through the jkindIx index as soon as -- the item is identified. data Item Item :: ItemKindIx -> LevelId -> Maybe FactionId -> Char -> Text -> Flavour -> [Feature] -> Int -> Dice -> Item -- | index pointing to the kind of the item [jkindIx] :: Item -> ItemKindIx -- | lowest level the item was created at [jlid] :: Item -> LevelId -- | the faction that created the item, if any [jfid] :: Item -> Maybe FactionId -- | map symbol [jsymbol] :: Item -> Char -- | generic name [jname] :: Item -> Text -- | flavour [jflavour] :: Item -> Flavour -- | public properties [jfeature] :: Item -> [Feature] -- | weight in grams, obvious enough [jweight] :: Item -> Int -- | impact damage of this particular weapon [jdamage] :: Item -> Dice data ItemSource ItemSourceLevel :: LevelId -> ItemSource ItemSourceFaction :: FactionId -> ItemSource -- | Price an item, taking count into consideration. itemPrice :: (Item, Int) -> Int goesIntoEqp :: Item -> Bool isMelee :: Item -> Bool goesIntoInv :: Item -> Bool goesIntoSha :: Item -> Bool seedToAspect :: ItemSeed -> ItemKind -> AbsDepth -> AbsDepth -> AspectRecord meanAspect :: ItemKind -> AspectRecord aspectRecordToList :: AspectRecord -> [Aspect] aspectRecordFull :: ItemFull -> AspectRecord aspectsRandom :: ItemKind -> Bool -- | An index of the kind id of an item. Clients have partial knowledge how -- these idexes map to kind ids. They gain knowledge by identifying -- items. data ItemKindIx -- | A seed for rolling aspects of an item Clients have partial knowledge -- of how item ids map to the seeds. They gain knowledge by identifying -- items. data ItemSeed data KindMean KindMean :: Id ItemKind -> AspectRecord -> KindMean [kmKind] :: KindMean -> Id ItemKind [kmMean] :: KindMean -> AspectRecord -- | The map of item kind indexes to item kind ids. The full map, as known -- by the server, is 1-1. type DiscoveryKind = EnumMap ItemKindIx KindMean -- | Fields are intentionally kept non-strict, because they are recomputed -- often, but not used every time. The fields are, in order: 1. whether -- the item should be kept in equipment (not in pack nor stash) 2. the -- total benefit from picking the item up (to use or to put in equipment) -- 3. the benefit of applying the item to self 4. the (usually negative) -- benefit of hitting a foe in meleeing with the item 5. the (usually -- negative) benefit of flinging an item at an opponent data Benefit Benefit :: ~Bool -> ~Int -> ~Int -> ~Int -> ~Int -> Benefit [benInEqp] :: Benefit -> ~Bool [benPickup] :: Benefit -> ~Int [benApply] :: Benefit -> ~Int [benMelee] :: Benefit -> ~Int [benFling] :: Benefit -> ~Int type DiscoveryBenefit = EnumMap ItemId Benefit data AspectRecord AspectRecord :: Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Skills -> AspectRecord [aTimeout] :: AspectRecord -> Int [aHurtMelee] :: AspectRecord -> Int [aArmorMelee] :: AspectRecord -> Int [aArmorRanged] :: AspectRecord -> Int [aMaxHP] :: AspectRecord -> Int [aMaxCalm] :: AspectRecord -> Int [aSpeed] :: AspectRecord -> Int [aSight] :: AspectRecord -> Int [aSmell] :: AspectRecord -> Int [aShine] :: AspectRecord -> Int [aNocto] :: AspectRecord -> Int [aAggression] :: AspectRecord -> Int [aSkills] :: AspectRecord -> Skills emptyAspectRecord :: AspectRecord sumAspectRecord :: [(AspectRecord, Int)] -> AspectRecord -- | The map of item ids to item aspects. The full map is known by the -- server. type DiscoveryAspect = EnumMap ItemId AspectRecord data ItemFull ItemFull :: Item -> Int -> ItemTimer -> Maybe ItemDisco -> ItemFull [itemBase] :: ItemFull -> Item [itemK] :: ItemFull -> Int [itemTimer] :: ItemFull -> ItemTimer [itemDisco] :: ItemFull -> Maybe ItemDisco data ItemDisco ItemDisco :: Id ItemKind -> ItemKind -> AspectRecord -> Maybe AspectRecord -> ItemDisco [itemKindId] :: ItemDisco -> Id ItemKind [itemKind] :: ItemDisco -> ItemKind [itemAspectMean] :: ItemDisco -> AspectRecord [itemAspect] :: ItemDisco -> Maybe AspectRecord itemNoDisco :: (Item, Int) -> ItemFull itemToFull :: COps -> DiscoveryKind -> DiscoveryAspect -> ItemId -> Item -> ItemQuant -> ItemFull type ItemTimer = [Time] type ItemQuant = (Int, ItemTimer) type ItemBag = EnumMap ItemId ItemQuant -- | All items in the dungeon (including in actor inventories), indexed by -- item identifier. type ItemDict = EnumMap ItemId Item instance GHC.Show.Show Game.LambdaHack.Common.Item.ItemFull instance GHC.Generics.Generic Game.LambdaHack.Common.Item.ItemSource instance GHC.Classes.Eq Game.LambdaHack.Common.Item.ItemSource instance GHC.Show.Show Game.LambdaHack.Common.Item.ItemSource instance GHC.Generics.Generic Game.LambdaHack.Common.Item.Item instance GHC.Classes.Eq Game.LambdaHack.Common.Item.Item instance GHC.Show.Show Game.LambdaHack.Common.Item.Item instance GHC.Show.Show Game.LambdaHack.Common.Item.ItemDisco instance GHC.Generics.Generic Game.LambdaHack.Common.Item.KindMean instance GHC.Classes.Eq Game.LambdaHack.Common.Item.KindMean instance GHC.Show.Show Game.LambdaHack.Common.Item.KindMean instance GHC.Generics.Generic Game.LambdaHack.Common.Item.AspectRecord instance GHC.Classes.Ord Game.LambdaHack.Common.Item.AspectRecord instance GHC.Classes.Eq Game.LambdaHack.Common.Item.AspectRecord instance GHC.Show.Show Game.LambdaHack.Common.Item.AspectRecord instance Data.Binary.Class.Binary Game.LambdaHack.Common.Item.ItemSeed instance Data.Hashable.Class.Hashable Game.LambdaHack.Common.Item.ItemSeed instance GHC.Enum.Enum Game.LambdaHack.Common.Item.ItemSeed instance GHC.Classes.Ord Game.LambdaHack.Common.Item.ItemSeed instance GHC.Classes.Eq Game.LambdaHack.Common.Item.ItemSeed instance GHC.Show.Show Game.LambdaHack.Common.Item.ItemSeed instance GHC.Generics.Generic Game.LambdaHack.Common.Item.Benefit instance GHC.Show.Show Game.LambdaHack.Common.Item.Benefit instance Data.Binary.Class.Binary Game.LambdaHack.Common.Item.ItemKindIx instance Data.Hashable.Class.Hashable Game.LambdaHack.Common.Item.ItemKindIx instance GHC.Arr.Ix Game.LambdaHack.Common.Item.ItemKindIx instance GHC.Enum.Enum Game.LambdaHack.Common.Item.ItemKindIx instance GHC.Classes.Ord Game.LambdaHack.Common.Item.ItemKindIx instance GHC.Classes.Eq Game.LambdaHack.Common.Item.ItemKindIx instance GHC.Show.Show Game.LambdaHack.Common.Item.ItemKindIx instance Data.Binary.Class.Binary Game.LambdaHack.Common.Item.ItemId instance GHC.Enum.Enum Game.LambdaHack.Common.Item.ItemId instance GHC.Classes.Ord Game.LambdaHack.Common.Item.ItemId instance GHC.Classes.Eq Game.LambdaHack.Common.Item.ItemId instance GHC.Show.Show Game.LambdaHack.Common.Item.ItemId instance Data.Hashable.Class.Hashable Game.LambdaHack.Common.Item.ItemSource instance Data.Binary.Class.Binary Game.LambdaHack.Common.Item.ItemSource instance Data.Hashable.Class.Hashable Game.LambdaHack.Common.Item.Item instance Data.Binary.Class.Binary Game.LambdaHack.Common.Item.Item instance Data.Binary.Class.Binary Game.LambdaHack.Common.Item.KindMean instance Data.Binary.Class.Binary Game.LambdaHack.Common.Item.AspectRecord instance Data.Hashable.Class.Hashable Game.LambdaHack.Common.Item.AspectRecord instance Data.Binary.Class.Binary Game.LambdaHack.Common.Item.Benefit -- | Determining the strongest item wrt some property. No operation in this -- module involves the state or any of our custom monads. module Game.LambdaHack.Common.ItemStrongest strengthOnSmash :: ItemFull -> [Effect] strengthCreateOrgan :: ItemFull -> [GroupName ItemKind] strengthDropOrgan :: ItemFull -> [GroupName ItemKind] strengthEqpSlot :: ItemFull -> Maybe EqpSlot strengthToThrow :: Item -> ThrowMod strengthEffect :: (Effect -> [b]) -> ItemFull -> [b] strongestSlot :: DiscoveryBenefit -> EqpSlot -> [(ItemId, ItemFull)] -> [(Int, (ItemId, ItemFull))] totalRange :: Item -> Int computeTrajectory :: Int -> Int -> Int -> [Point] -> ([Vector], (Speed, Int)) itemTrajectory :: Item -> [Point] -> ([Vector], (Speed, Int)) unknownMelee :: [ItemFull] -> Bool filterRecharging :: [Effect] -> [Effect] stripRecharging :: [Effect] -> [Effect] stripOnSmash :: [Effect] -> [Effect] hasCharge :: Time -> ItemFull -> Bool damageUsefulness :: Item -> Int strongestMelee :: Maybe DiscoveryBenefit -> Time -> [(ItemId, ItemFull)] -> [(Int, (ItemId, ItemFull))] prEqpSlot :: EqpSlot -> AspectRecord -> Int -- | Actors in the game: heroes, monsters, etc. No operation in this module -- involves the State or Action type. module Game.LambdaHack.Common.Actor -- | A unique identifier of an actor in the dungeon. data ActorId -- | Chance that a new monster is generated. Currently depends on the -- number of monsters already present, and on the level. In the future, -- the strength of the character and the strength of the monsters present -- could further influence the chance, and the chance could also affect -- which monster is generated. How many and which monsters are generated -- will also depend on the cave kind used to build the level. monsterGenChance :: AbsDepth -> AbsDepth -> Int -> Int -> Rnd Bool -- | Actor properties that are changing throughout the game. If they are -- dublets of properties from ActorKind, they are usually -- modified temporarily, but tend to return to the original value from -- ActorKind over time. E.g., HP. data Actor Actor :: ItemId -> Int64 -> ResDelta -> Int64 -> ResDelta -> Point -> (Maybe Point) -> LevelId -> FactionId -> (Maybe ([Vector], Speed)) -> ItemBag -> ItemBag -> ItemBag -> Int -> Bool -> Bool -> Actor [btrunk] :: Actor -> ItemId -- | current hit points * 1M [bhp] :: Actor -> Int64 -- | HP delta this turn * 1M [bhpDelta] :: Actor -> ResDelta -- | current calm * 1M [bcalm] :: Actor -> Int64 -- | calm delta this turn * 1M [bcalmDelta] :: Actor -> ResDelta -- | current position [bpos] :: Actor -> Point -- | previous position, if any [boldpos] :: Actor -> (Maybe Point) -- | current level [blid] :: Actor -> LevelId -- | faction the actor currently belongs to [bfid] :: Actor -> FactionId -- | trajectory the actor must travel and his travel speed [btrajectory] :: Actor -> (Maybe ([Vector], Speed)) -- | organs [borgan] :: Actor -> ItemBag -- | personal equipment [beqp] :: Actor -> ItemBag -- | personal inventory pack [binv] :: Actor -> ItemBag -- | number of weapons among eqp and organs [bweapon] :: Actor -> Int -- | is the actor waiting right now? [bwait] :: Actor -> Bool -- | is a projectile? (shorthand only, this can be deduced from btrunk) [bproj] :: Actor -> Bool data ResDelta ResDelta :: (Int64, Int64) -> (Int64, Int64) -> ResDelta -- | resource change this player turn [resCurrentTurn] :: ResDelta -> (Int64, Int64) -- | resource change last player turn [resPreviousTurn] :: ResDelta -> (Int64, Int64) type ActorAspect = EnumMap ActorId AspectRecord deltaSerious :: ResDelta -> Bool deltaMild :: ResDelta -> Bool actorCanMelee :: ActorAspect -> ActorId -> Actor -> Bool bspeed :: Actor -> AspectRecord -> Speed -- | A template for a new actor. actorTemplate :: ItemId -> Int64 -> Int64 -> Point -> LevelId -> FactionId -> Actor -- | Whether an actor is braced for combat this clip. braced :: Actor -> Bool -- | The actor waited last turn. waitedLastTurn :: Actor -> Bool actorDying :: Actor -> Bool actorTrunkIsBlast :: Item -> Bool hpTooLow :: Actor -> AspectRecord -> Bool calmEnough :: Actor -> AspectRecord -> Bool hpEnough :: Actor -> AspectRecord -> Bool -- | All actors on the level, indexed by actor identifier. type ActorDict = EnumMap ActorId Actor -- | How long until an actor's smell vanishes from a tile. smellTimeout :: Delta Time checkAdjacent :: Actor -> Actor -> Bool eqpOverfull :: Actor -> Int -> Bool eqpFreeN :: Actor -> Int instance GHC.Generics.Generic Game.LambdaHack.Common.Actor.Actor instance GHC.Classes.Eq Game.LambdaHack.Common.Actor.Actor instance GHC.Show.Show Game.LambdaHack.Common.Actor.Actor instance GHC.Generics.Generic Game.LambdaHack.Common.Actor.ResDelta instance GHC.Classes.Eq Game.LambdaHack.Common.Actor.ResDelta instance GHC.Show.Show Game.LambdaHack.Common.Actor.ResDelta instance Data.Binary.Class.Binary Game.LambdaHack.Common.Actor.Actor instance Data.Binary.Class.Binary Game.LambdaHack.Common.Actor.ResDelta -- | Inhabited dungeon levels and the operations to query and change them -- as the game progresses. module Game.LambdaHack.Common.Level -- | Abstract level identifiers. data LevelId -- | Absolute depth in the dungeon. When used for the maximum depth of the -- whole dungeon, this can be different than dungeon size, e.g., when the -- dungeon is branched, and it can even be different than the length of -- the longest branch, if levels at some depths are missing. data AbsDepth -- | The complete dungeon is a map from level names to levels. type Dungeon = EnumMap LevelId Level -- | Levels in the current branch, k levels shallower than the -- current. ascendInBranch :: Dungeon -> Bool -> LevelId -> [LevelId] -- | Compute the level identifier and stair position on the new level, -- after a level change. -- -- We assume there is never a staircase up and down at the same position. whereTo :: LevelId -> Point -> Maybe Bool -> Dungeon -> (LevelId, Point) -- | A view on single, inhabited dungeon level. Remembered fields -- carry a subset of the info in the client copies of levels. data Level Level :: AbsDepth -> ItemFloor -> ItemFloor -> ActorMap -> TileMap -> X -> Y -> SmellMap -> Text -> ([Point], [Point]) -> Int -> Int -> Time -> Int -> Freqs ItemKind -> Int -> Freqs ItemKind -> [Point] -> Bool -> Level -- | absolute depth of the level [ldepth] :: Level -> AbsDepth -- | remembered items lying on the floor [lfloor] :: Level -> ItemFloor -- | items embedded in the tile [lembed] :: Level -> ItemFloor -- | seen actors at positions on the level [lactor] :: Level -> ActorMap -- | remembered level map [ltile] :: Level -> TileMap -- | width of the level [lxsize] :: Level -> X -- | height of the level [lysize] :: Level -> Y -- | remembered smells on the level [lsmell] :: Level -> SmellMap -- | level description [ldesc] :: Level -> Text -- | positions of (up, down) stairs [lstair] :: Level -> ([Point], [Point]) -- | currently remembered clear tiles [lseen] :: Level -> Int -- | total number of explorable tiles [lexplorable] :: Level -> Int -- | local time on the level (possibly frozen) [ltime] :: Level -> Time -- | the lower, the more monsters spawn [lactorCoeff] :: Level -> Int -- | frequency of spawned actors; [] for clients [lactorFreq] :: Level -> Freqs ItemKind -- | number of initial items, 0 for clients [litemNum] :: Level -> Int -- | frequency of initial items; [] for clients [litemFreq] :: Level -> Freqs ItemKind -- | positions of IK.Escape tiles [lescape] :: Level -> [Point] [lnight] :: Level -> Bool -- | Items located on map tiles. type ItemFloor = EnumMap Point ItemBag -- | Items located on map tiles. type ActorMap = EnumMap Point [ActorId] -- | Tile kinds on the map. type TileMap = GArray Word16 (Id TileKind) -- | Current smell on map tiles. type SmellMap = EnumMap Point Time -- | Query for tile kinds on the map. at :: Level -> Point -> Id TileKind -- | Find a random position on the map satisfying a predicate. findPoint :: X -> Y -> (Point -> Maybe Point) -> Rnd Point -- | Find a random position on the map satisfying a predicate. findPos :: TileMap -> (Point -> Id TileKind -> Bool) -> Rnd Point -- | Try to find a random position on the map satisfying conjunction of the -- mandatory and an optional predicate. If the permitted number of -- attempts is not enough, try again the same number of times without the -- next optional predicate, and fall back to trying as many times, as -- needed, with only the mandatory predicate. findPosTry :: Int -> TileMap -> (Point -> Id TileKind -> Bool) -> [Point -> Id TileKind -> Bool] -> Rnd Point findPosTry2 :: Int -> TileMap -> (Point -> Id TileKind -> Bool) -> [Point -> Id TileKind -> Bool] -> (Point -> Id TileKind -> Bool) -> [Point -> Id TileKind -> Bool] -> Rnd Point instance GHC.Classes.Eq Game.LambdaHack.Common.Level.Level instance GHC.Show.Show Game.LambdaHack.Common.Level.Level instance Data.Binary.Class.Binary Game.LambdaHack.Common.Level.Level -- | Description of effects. No operation in this module involves state or -- monad types. module Game.LambdaHack.Client.UI.EffectDescription -- | Suffix to append to a basic content name if the content causes the -- effect. -- -- We show absolute time in seconds, not moves, because actors -- can have different speeds (and actions can potentially take different -- time intervals). We call the time taken by one player move, when -- walking, a move. Turn and clip are used -- mostly internally, the former as an absolute time unit. We show -- distances in steps, because one step, from a tile to another -- tile, is always 1 meter. We don't call steps tiles, reserving -- that term for the context of terrain kinds or units of area. effectToSuffix :: Effect -> Text featureToSuff :: Feature -> Text kindAspectToSuffix :: Aspect -> Text affixDice :: Dice -> Text featureToSentence :: Feature -> Maybe Text slotToSentence :: EqpSlot -> Text slotToName :: EqpSlot -> Text slotToDesc :: EqpSlot -> Text slotToDecorator :: EqpSlot -> Actor -> Int -> Text statSlots :: [EqpSlot] -- | Factions taking part in the game: e.g., two human players controlling -- the hero faction battling the monster and the animal factions. module Game.LambdaHack.Common.Faction -- | A unique identifier of a faction in a game. data FactionId -- | All factions in the game, indexed by faction identifier. type FactionDict = EnumMap FactionId Faction data Faction Faction :: Text -> Color -> Player -> [(Int, Int, GroupName ItemKind)] -> Dipl -> Maybe Status -> Maybe ActorId -> ItemBag -> EnumMap (Id ItemKind) Int -> EnumMap (Id ModeKind) (IntMap (EnumMap (Id ItemKind) Int)) -> Faction -- | individual name [gname] :: Faction -> Text -- | color of actors or their frames [gcolor] :: Faction -> Color -- | the player spec for this faction [gplayer] :: Faction -> Player -- | initial actors [ginitial] :: Faction -> [(Int, Int, GroupName ItemKind)] -- | diplomatic mode [gdipl] :: Faction -> Dipl -- | cause of game end/exit [gquit] :: Faction -> Maybe Status -- | the leader of the faction; don't use in place of _sleader on clients [_gleader] :: Faction -> Maybe ActorId -- | faction's shared inventory [gsha] :: Faction -> ItemBag -- | members killed [gvictims] :: Faction -> EnumMap (Id ItemKind) Int -- | members killed in the past, by game mode and difficulty level [gvictimsD] :: Faction -> EnumMap (Id ModeKind) (IntMap (EnumMap (Id ItemKind) Int)) -- | Diplomacy states. Higher overwrite lower in case of asymmetric -- content. data Diplomacy Unknown :: Diplomacy Neutral :: Diplomacy Alliance :: Diplomacy War :: Diplomacy -- | Current game status. data Status Status :: Outcome -> Int -> Maybe (GroupName ModeKind) -> Status -- | current game outcome [stOutcome] :: Status -> Outcome -- | depth of the final encounter [stDepth] :: Status -> Int -- | new game group to start, if any [stNewGame] :: Status -> Maybe (GroupName ModeKind) -- | The type of na actor target. data Target -- | target an actor; cycle only trough seen foes, unless the flag is set TEnemy :: ActorId -> Bool -> Target -- | target a concrete spot TPoint :: TGoal -> LevelId -> Point -> Target -- | target position relative to actor TVector :: Vector -> Target data TGoal -- | last seen position of the targeted actor TEnemyPos :: ActorId -> Bool -> TGoal -- | in TPoint (TEmbed bag p) _ q usually bag is -- embbedded in p and q is an adjacent open tile TEmbed :: ItemBag -> Point -> TGoal TItem :: ItemBag -> TGoal TSmell :: TGoal TUnknown :: TGoal TKnown :: TGoal TAny :: TGoal data Challenge Challenge :: Int -> Bool -> Bool -> Challenge -- | game difficulty level (HP bonus or malus) [cdiff] :: Challenge -> Int -- | lone wolf challenge (only one starting character) [cwolf] :: Challenge -> Bool -- | cold fish challenge (no healing from enemies) [cfish] :: Challenge -> Bool tgtKindDescription :: Target -> Text -- | Tell whether the faction consists of summoned horrors only. -- -- Horror player is special, for summoned actors that don't belong to any -- of the main players of a given game. E.g., animals summoned during a -- skirmish game between two hero factions land in the horror faction. In -- every game, either all factions for which summoning items exist should -- be present or a horror player should be added to host them. isHorrorFact :: Faction -> Bool nameOfHorrorFact :: GroupName ItemKind noRunWithMulti :: Faction -> Bool isAIFact :: Faction -> Bool autoDungeonLevel :: Faction -> (Bool, Bool) automatePlayer :: Bool -> Player -> Player -- | Check if factions are at war. Assumes symmetry. isAtWar :: Faction -> FactionId -> Bool -- | Check if factions are allied. Assumes symmetry. isAllied :: Faction -> FactionId -> Bool difficultyBound :: Int difficultyDefault :: Int difficultyCoeff :: Int -> Int difficultyInverse :: Int -> Int defaultChallenge :: Challenge type Dipl = EnumMap FactionId Diplomacy instance GHC.Generics.Generic Game.LambdaHack.Common.Faction.Challenge instance GHC.Classes.Ord Game.LambdaHack.Common.Faction.Challenge instance GHC.Classes.Eq Game.LambdaHack.Common.Faction.Challenge instance GHC.Show.Show Game.LambdaHack.Common.Faction.Challenge instance GHC.Generics.Generic Game.LambdaHack.Common.Faction.Target instance GHC.Classes.Ord Game.LambdaHack.Common.Faction.Target instance GHC.Classes.Eq Game.LambdaHack.Common.Faction.Target instance GHC.Show.Show Game.LambdaHack.Common.Faction.Target instance GHC.Generics.Generic Game.LambdaHack.Common.Faction.TGoal instance GHC.Classes.Ord Game.LambdaHack.Common.Faction.TGoal instance GHC.Classes.Eq Game.LambdaHack.Common.Faction.TGoal instance GHC.Show.Show Game.LambdaHack.Common.Faction.TGoal instance GHC.Generics.Generic Game.LambdaHack.Common.Faction.Faction instance GHC.Classes.Ord Game.LambdaHack.Common.Faction.Faction instance GHC.Classes.Eq Game.LambdaHack.Common.Faction.Faction instance GHC.Show.Show Game.LambdaHack.Common.Faction.Faction instance GHC.Generics.Generic Game.LambdaHack.Common.Faction.Status instance GHC.Classes.Ord Game.LambdaHack.Common.Faction.Status instance GHC.Classes.Eq Game.LambdaHack.Common.Faction.Status instance GHC.Show.Show Game.LambdaHack.Common.Faction.Status instance GHC.Generics.Generic Game.LambdaHack.Common.Faction.Diplomacy instance GHC.Enum.Enum Game.LambdaHack.Common.Faction.Diplomacy instance GHC.Classes.Ord Game.LambdaHack.Common.Faction.Diplomacy instance GHC.Classes.Eq Game.LambdaHack.Common.Faction.Diplomacy instance GHC.Show.Show Game.LambdaHack.Common.Faction.Diplomacy instance Data.Binary.Class.Binary Game.LambdaHack.Common.Faction.Challenge instance Data.Binary.Class.Binary Game.LambdaHack.Common.Faction.Target instance Data.Binary.Class.Binary Game.LambdaHack.Common.Faction.TGoal instance Data.Binary.Class.Binary Game.LambdaHack.Common.Faction.Faction instance Data.Binary.Class.Binary Game.LambdaHack.Common.Faction.Status instance Data.Binary.Class.Binary Game.LambdaHack.Common.Faction.Diplomacy -- | Abstract syntax of server commands. See -- https://github.com/LambdaHack/LambdaHack/wiki/Client-server-architecture. module Game.LambdaHack.Common.Request type RequestAI = (ReqAI, Maybe ActorId) -- | Client-server requests sent by AI clients. data ReqAI ReqAITimed :: RequestAnyAbility -> ReqAI ReqAINop :: ReqAI type RequestUI = (ReqUI, Maybe ActorId) -- | Client-server requests sent by UI clients. data ReqUI ReqUINop :: ReqUI ReqUITimed :: RequestAnyAbility -> ReqUI ReqUIGameRestart :: (GroupName ModeKind) -> Challenge -> ReqUI ReqUIGameExit :: ReqUI ReqUIGameSave :: ReqUI ReqUITactic :: Tactic -> ReqUI ReqUIAutomate :: ReqUI -- | Client-server requests that take game time. Sent by both AI and UI -- clients. data RequestTimed :: Ability -> * [ReqMove] :: Vector -> RequestTimed 'AbMove [ReqMelee] :: ActorId -> ItemId -> CStore -> RequestTimed 'AbMelee [ReqDisplace] :: ActorId -> RequestTimed 'AbDisplace [ReqAlter] :: Point -> RequestTimed 'AbAlter [ReqWait] :: RequestTimed 'AbWait [ReqWait10] :: RequestTimed 'AbWait [ReqMoveItems] :: [(ItemId, Int, CStore, CStore)] -> RequestTimed 'AbMoveItem [ReqProject] :: Point -> Int -> ItemId -> CStore -> RequestTimed 'AbProject [ReqApply] :: ItemId -> CStore -> RequestTimed 'AbApply data RequestAnyAbility RequestAnyAbility :: (RequestTimed a) -> RequestAnyAbility data ReqFailure MoveNothing :: ReqFailure MeleeSelf :: ReqFailure MeleeDistant :: ReqFailure DisplaceDistant :: ReqFailure DisplaceAccess :: ReqFailure DisplaceProjectiles :: ReqFailure DisplaceDying :: ReqFailure DisplaceBraced :: ReqFailure DisplaceImmobile :: ReqFailure DisplaceSupported :: ReqFailure AlterUnskilled :: ReqFailure AlterUnwalked :: ReqFailure AlterDistant :: ReqFailure AlterBlockActor :: ReqFailure AlterBlockItem :: ReqFailure AlterNothing :: ReqFailure EqpOverfull :: ReqFailure EqpStackFull :: ReqFailure ApplyUnskilled :: ReqFailure ApplyRead :: ReqFailure ApplyOutOfReach :: ReqFailure ApplyCharging :: ReqFailure ApplyNoEffects :: ReqFailure ItemNothing :: ReqFailure ItemNotCalm :: ReqFailure NotCalmPrecious :: ReqFailure ProjectUnskilled :: ReqFailure ProjectAimOnself :: ReqFailure ProjectBlockTerrain :: ReqFailure ProjectBlockActor :: ReqFailure ProjectLobable :: ReqFailure ProjectOutOfReach :: ReqFailure TriggerNothing :: ReqFailure NoChangeDunLeader :: ReqFailure impossibleReqFailure :: ReqFailure -> Bool showReqFailure :: ReqFailure -> Text timedToUI :: RequestTimed a -> ReqUI permittedPrecious :: Bool -> Bool -> ItemFull -> Either ReqFailure Bool permittedProject :: Bool -> Int -> Bool -> [Char] -> ItemFull -> Either ReqFailure Bool permittedProjectAI :: Int -> Bool -> ItemFull -> Bool permittedApply :: Time -> Int -> Bool -> [Char] -> ItemFull -> Either ReqFailure Bool instance GHC.Generics.Generic Game.LambdaHack.Common.Request.ReqFailure instance GHC.Classes.Eq Game.LambdaHack.Common.Request.ReqFailure instance GHC.Show.Show Game.LambdaHack.Common.Request.ReqFailure instance GHC.Show.Show Game.LambdaHack.Common.Request.ReqAI instance GHC.Show.Show Game.LambdaHack.Common.Request.ReqUI instance GHC.Show.Show Game.LambdaHack.Common.Request.RequestAnyAbility instance GHC.Show.Show (Game.LambdaHack.Common.Request.RequestTimed a) instance Data.Binary.Class.Binary Game.LambdaHack.Common.Request.ReqFailure -- | 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 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 -- | Visible positions. newtype PerVisible PerVisible :: EnumSet Point -> PerVisible [pvisible] :: PerVisible -> EnumSet Point -- | Smelled positions. newtype PerSmelled PerSmelled :: EnumSet Point -> PerSmelled [psmelled] :: PerSmelled -> EnumSet Point -- | The type representing the perception of a faction on a level. data Perception Perception :: PerVisible -> PerSmelled -> Perception [psight] :: Perception -> PerVisible [psmell] :: Perception -> PerSmelled -- | Perception of a single faction, indexed by level identifier. type PerLid = 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 = EnumMap FactionId PerLid -- | The set of tiles visible by at least one hero. totalVisible :: Perception -> EnumSet Point -- | The set of tiles smelt by at least one hero. totalSmelled :: Perception -> EnumSet Point emptyPer :: Perception nullPer :: Perception -> Bool addPer :: Perception -> Perception -> Perception diffPer :: Perception -> Perception -> Perception instance GHC.Generics.Generic Game.LambdaHack.Common.Perception.Perception instance GHC.Classes.Eq Game.LambdaHack.Common.Perception.Perception instance GHC.Show.Show Game.LambdaHack.Common.Perception.Perception instance Data.Binary.Class.Binary Game.LambdaHack.Common.Perception.PerSmelled instance GHC.Classes.Eq Game.LambdaHack.Common.Perception.PerSmelled instance GHC.Show.Show Game.LambdaHack.Common.Perception.PerSmelled instance Data.Binary.Class.Binary Game.LambdaHack.Common.Perception.PerVisible instance GHC.Classes.Eq Game.LambdaHack.Common.Perception.PerVisible instance GHC.Show.Show Game.LambdaHack.Common.Perception.PerVisible instance Data.Binary.Class.Binary Game.LambdaHack.Common.Perception.Perception -- | High score table operations. module Game.LambdaHack.Common.HighScore -- | A dictionary from game mode IDs to scores tables. type ScoreDict = EnumMap (Id ModeKind) ScoreTable -- | The list of scores, in decreasing order. data ScoreTable -- | Empty score table empty :: ScoreDict -- | Register a new score in a score table. register :: ScoreTable -> Int -> Time -> Status -> POSIXTime -> Challenge -> Text -> EnumMap (Id ItemKind) Int -> EnumMap (Id ItemKind) Int -> HiCondPoly -> (Bool, (ScoreTable, Int)) -- | Show a single high score, from the given ranking in the high score -- table. showScore :: TimeZone -> (Int, ScoreRecord) -> [Text] getTable :: Id ModeKind -> ScoreDict -> ScoreTable getRecord :: Int -> ScoreTable -> ScoreRecord -- | Generate a slideshow with the current and previous scores. highSlideshow :: ScoreTable -> Int -> Text -> TimeZone -> (Text, [[Text]]) -- | A single score record. Records are ordered in the highscore table, -- from the best to the worst, in lexicographic ordering wrt the fields -- below. data ScoreRecord instance Data.Binary.Class.Binary Game.LambdaHack.Common.HighScore.ScoreTable instance GHC.Classes.Eq Game.LambdaHack.Common.HighScore.ScoreTable instance GHC.Generics.Generic Game.LambdaHack.Common.HighScore.ScoreRecord instance GHC.Show.Show Game.LambdaHack.Common.HighScore.ScoreRecord instance GHC.Classes.Ord Game.LambdaHack.Common.HighScore.ScoreRecord instance GHC.Classes.Eq Game.LambdaHack.Common.HighScore.ScoreRecord instance GHC.Show.Show Game.LambdaHack.Common.HighScore.ScoreTable instance Data.Binary.Class.Binary Game.LambdaHack.Common.HighScore.ScoreRecord -- | Server and client game state types and operations. module Game.LambdaHack.Common.State -- | View on game state. Remembered fields carry a subset of the -- info in the client copies of the state. Clients never directly change -- their State, but apply atomic actions sent by the server to -- do so. data State sdungeon :: State -> Dungeon stotalDepth :: State -> AbsDepth sactorD :: State -> ActorDict sitemD :: State -> ItemDict sfactionD :: State -> FactionDict stime :: State -> Time scops :: State -> COps shigh :: State -> ScoreDict sgameModeId :: State -> Id ModeKind -- | Initial complete global game state. defStateGlobal :: Dungeon -> AbsDepth -> FactionDict -> COps -> ScoreDict -> Id ModeKind -> State -- | Initial empty state. emptyState :: COps -> State -- | Local state created by removing secret information from global state -- components. localFromGlobal :: State -> State -- | Update dungeon data within state. updateDungeon :: (Dungeon -> Dungeon) -> State -> State -- | Update dungeon depth. updateDepth :: (AbsDepth -> AbsDepth) -> State -> State -- | Update the actor dictionary. updateActorD :: (ActorDict -> ActorDict) -> State -> State -- | Update the item dictionary. updateItemD :: (ItemDict -> ItemDict) -> State -> State -- | Update faction data within state. updateFactionD :: (FactionDict -> FactionDict) -> State -> State -- | Update global time within state. updateTime :: (Time -> Time) -> State -> State -- | Update content data within state. updateCOps :: (COps -> COps) -> State -> State instance GHC.Classes.Eq Game.LambdaHack.Common.State.State instance GHC.Show.Show Game.LambdaHack.Common.State.State instance Data.Binary.Class.Binary Game.LambdaHack.Common.State.State -- | Descripitons of items. module Game.LambdaHack.Client.UI.ItemDescription -- | The part of speech describing the item. partItem :: FactionId -> FactionDict -> CStore -> Time -> ItemFull -> (Bool, Bool, Part, Part) partItemShort :: FactionId -> FactionDict -> CStore -> Time -> ItemFull -> (Bool, Bool, Part, Part) partItemHigh :: FactionId -> FactionDict -> CStore -> Time -> ItemFull -> (Bool, Bool, Part, Part) partItemWs :: FactionId -> FactionDict -> Int -> CStore -> Time -> ItemFull -> Part partItemWsRanged :: FactionId -> FactionDict -> Int -> CStore -> Time -> ItemFull -> Part partItemShortAW :: FactionId -> FactionDict -> CStore -> Time -> ItemFull -> Part partItemMediumAW :: FactionId -> FactionDict -> CStore -> Time -> ItemFull -> Part partItemShortWownW :: FactionId -> FactionDict -> Part -> CStore -> Time -> ItemFull -> Part viewItem :: Item -> AttrCharW32 show64With2 :: Int64 -> Text -- | Screen overlays. module Game.LambdaHack.Client.UI.Overlay type AttrLine = [AttrCharW32] emptyAttrLine :: Int -> AttrLine textToAL :: Text -> AttrLine fgToAL :: Color -> Text -> AttrLine stringToAL :: String -> AttrLine (<+:>) :: AttrLine -> AttrLine -> AttrLine infixr 6 <+:> -- | Split a string into lines. Avoids ending the line with a character -- other than whitespace or punctuation. Space characters are removed -- from the start, but never from the end of lines. Newlines are -- respected. splitAttrLine :: X -> AttrLine -> [AttrLine] itemDesc :: FactionId -> FactionDict -> Int -> CStore -> Time -> ItemFull -> AttrLine glueLines :: [AttrLine] -> [AttrLine] -> [AttrLine] updateLines :: Int -> (AttrLine -> AttrLine) -> [AttrLine] -> [AttrLine] type Overlay = [(Int, AttrLine)] -- | Color mode for the display. data ColorMode -- | normal, with full colours ColorFull :: ColorMode -- | black+white only ColorBW :: ColorMode type FrameST s = Mutable Vector s Word32 -> ST s () newtype FrameForall FrameForall :: (forall s. FrameST s) -> FrameForall [unFrameForall] :: FrameForall -> forall s. FrameST s writeLine :: Int -> AttrLine -> FrameForall instance GHC.Classes.Eq Game.LambdaHack.Client.UI.Overlay.ColorMode -- | Game messages displayed on top of the screen for the player to read. module Game.LambdaHack.Client.UI.Msg -- | The type of a single game message. data Msg toMsg :: AttrLine -> Msg toPrompt :: AttrLine -> Msg data RepMsgN -- | The set of messages, with repetitions, to show at the screen at once. data Report -- | Empty set of messages. emptyReport :: Report -- | Test if the set of messages is empty. nullReport :: Report -> Bool -- | Construct a singleton set of messages. singletonReport :: Msg -> Report -- | Add a message to the end of report. Deletes old prompt messages. snocReport :: Report -> Msg -> Report -- | Add a message to the end of report. Does not delete old prompt -- messages nor handle repetitions. consReportNoScrub :: Msg -> Report -> Report -- | Render a report as a (possibly very long) AttrLine. renderReport :: Report -> AttrLine findInReport :: (AttrLine -> Bool) -> Report -> Maybe Msg incrementInReport :: (AttrLine -> Bool) -> Report -> Maybe Report lastMsgOfReport :: Report -> (AttrLine, Report) -- | The history of reports. This is a ring buffer of the given length data History -- | Empty history of reports of the given maximal length. emptyHistory :: Int -> History -- | Add a report to history, handling repetitions. addReport :: History -> Time -> Report -> History lengthHistory :: History -> Int lastReportOfHistory :: History -> Report replaceLastReportOfHistory :: Report -> History -> History splitReportForHistory :: X -> AttrLine -> [AttrLine] -- | Render history as many lines of text, wrapping if necessary. renderHistory :: History -> [AttrLine] instance GHC.Generics.Generic Game.LambdaHack.Client.UI.Msg.History instance GHC.Show.Show Game.LambdaHack.Client.UI.Msg.History instance Data.Binary.Class.Binary Game.LambdaHack.Client.UI.Msg.Report instance GHC.Show.Show Game.LambdaHack.Client.UI.Msg.Report instance GHC.Generics.Generic Game.LambdaHack.Client.UI.Msg.RepMsgN instance GHC.Show.Show Game.LambdaHack.Client.UI.Msg.RepMsgN instance GHC.Generics.Generic Game.LambdaHack.Client.UI.Msg.Msg instance GHC.Classes.Eq Game.LambdaHack.Client.UI.Msg.Msg instance GHC.Show.Show Game.LambdaHack.Client.UI.Msg.Msg instance Data.Binary.Class.Binary Game.LambdaHack.Client.UI.Msg.History instance Data.Binary.Class.Binary Game.LambdaHack.Client.UI.Msg.RepMsgN instance Data.Binary.Class.Binary Game.LambdaHack.Client.UI.Msg.Msg -- | Screen frames. module Game.LambdaHack.Client.UI.Frame -- | An overlay that fits on the screen (or is meant to be truncated on -- display) and is padded to fill the whole screen and is displayed as a -- single game screen frame. -- -- Note that we don't provide a list of color-highlighed positions -- separately, because overlays need to obscure not only map, but the -- highlights as well. newtype SingleFrame SingleFrame :: GArray Word32 AttrCharW32 -> SingleFrame [singleFrame] :: SingleFrame -> GArray Word32 AttrCharW32 -- | Sequences of screen frames, including delays. type Frames = [Maybe FrameForall] blankSingleFrame :: SingleFrame -- | Overlays either the game map only or the whole empty screen frame. We -- assume the lines of the overlay are not too long nor too many. overlayFrame :: Overlay -> FrameForall -> FrameForall overlayFrameWithLines :: Bool -> [AttrLine] -> FrameForall -> FrameForall instance GHC.Show.Show Game.LambdaHack.Client.UI.Frame.SingleFrame instance GHC.Classes.Eq Game.LambdaHack.Client.UI.Frame.SingleFrame -- | Screen frames and animations. module Game.LambdaHack.Client.UI.Frontend.Common data RawFrontend RawFrontend :: (SingleFrame -> IO ()) -> IO () -> MVar () -> TQueue KMP -> RawFrontend [fdisplay] :: RawFrontend -> SingleFrame -> IO () [fshutdown] :: RawFrontend -> IO () [fshowNow] :: RawFrontend -> MVar () [fchanKey] :: RawFrontend -> TQueue KMP data KMP KMP :: KM -> Point -> KMP [kmpKeyMod] :: KMP -> KM [kmpPointer] :: KMP -> Point startupBound :: (MVar RawFrontend -> IO ()) -> IO RawFrontend createRawFrontend :: (SingleFrame -> IO ()) -> IO () -> IO RawFrontend -- | Empty the keyboard channel. resetChanKey :: TQueue KMP -> IO () saveKMP :: RawFrontend -> Modifier -> Key -> Point -> IO () -- | Translates modifiers to our own encoding. modifierTranslate :: Bool -> Bool -> Bool -> Bool -> Modifier -- | Line terimanl text frontend based on stdin/stdout, intended for -- logging tests, but may be used for a teletype terminal, or keyboard -- and printer. module Game.LambdaHack.Client.UI.Frontend.Teletype -- | Set up the frontend input and output. startup :: DebugModeCli -> IO RawFrontend -- | The name of the frontend. frontendName :: String shutdown :: IO () -- | Output to the screen via the frontend. display :: SingleFrame -> IO () -- | Re-export the operations of the chosen raw frontend (determined at -- compile time with cabal flags). module Game.LambdaHack.Client.UI.Frontend.Chosen -- | Set up and start the main loop providing input and output. -- -- Apparently some SDL backends are not thread-safe -- (https:/wiki.libsdl.orgFAQDevelopment), so we stick to main -- thread. startup :: DebugModeCli -> IO RawFrontend -- | The name of the frontend. frontendName :: String -- | Display game data on the screen and receive user input using one of -- the available raw frontends and derived operations. module Game.LambdaHack.Client.UI.Frontend -- | The instructions sent by clients to the raw frontend. data FrontReq :: * -> * -- | Show a frame. [FrontFrame] :: {frontFrame :: FrameForall} -> FrontReq () -- | Perform an explicit delay of the given length. [FrontDelay] :: Int -> FrontReq () -- | Flush frames, display a frame and ask for a keypress. [FrontKey] :: {frontKeyKeys :: [KM], frontKeyFrame :: FrameForall} -> FrontReq KMP -- | Inspect the fkeyPressed MVar. [FrontPressed] :: FrontReq Bool -- | discard a key in the queue, if any. [FrontDiscard] :: FrontReq () -- | Add a key to the queue. [FrontAdd] :: KMP -> FrontReq () -- | set in the frontend that it should auto-answer prompts. [FrontAutoYes] :: Bool -> FrontReq () -- | shut the frontend down. [FrontShutdown] :: FrontReq () -- | Connection channel between a frontend and a client. Frontend acts as a -- server, serving keys, etc., when given frames to display. newtype ChanFrontend ChanFrontend :: (forall a. FrontReq a -> IO a) -> ChanFrontend data KMP KMP :: KM -> Point -> KMP [kmpKeyMod] :: KMP -> KM [kmpPointer] :: KMP -> Point -- | The name of the chosen frontend. frontendName :: String chanFrontendIO :: DebugModeCli -> IO ChanFrontend data FSession -- | Display a prompt, wait for any of the specified keys (for any key, if -- the list is empty). Repeat if an unexpected key received. getKey :: DebugModeCli -> FSession -> RawFrontend -> [KM] -> FrameForall -> IO KMP -- | Read UI requests from the client and send them to the frontend, fchanFrontend :: DebugModeCli -> FSession -> RawFrontend -> ChanFrontend display :: RawFrontend -> FrameForall -> IO () defaultMaxFps :: Int microInSec :: Int frameTimeoutThread :: Int -> MVar Int -> RawFrontend -> IO () lazyStartup :: IO RawFrontend nullStartup :: IO RawFrontend seqFrame :: SingleFrame -> IO () -- | Screen frames and animations. module Game.LambdaHack.Client.UI.Animation -- | Animation is a list of frame modifications to play one by one, where -- each modification if a map from positions to level map symbols. data Animation -- | Render animations on top of a screen frame. renderAnim :: FrameForall -> Animation -> Frames pushAndDelay :: Animation blinkColorActor :: Point -> Char -> Color -> Color -> Animation -- | Attack animation. A part of it also reused for self-damage and -- healing. twirlSplash :: (Point, Point) -> Color -> Color -> Animation -- | Attack that hits through a block. blockHit :: (Point, Point) -> Color -> Color -> Animation -- | Attack that is blocked. blockMiss :: (Point, Point) -> Animation -- | Death animation for an organic body. deathBody :: Point -> Animation -- | Death animation for an organic body, short version (e.g., for -- enemies). shortDeathBody :: Point -> Animation -- | Mark actor location animation. actorX :: Point -> Animation -- | Swap-places animation, both hostile and friendly. swapPlaces :: (Point, Point) -> Animation -- | Actor teleport animation. teleport :: (Point, Point) -> Animation fadeout :: Bool -> Int -> X -> Y -> Rnd Animation instance GHC.Show.Show Game.LambdaHack.Client.UI.Animation.Animation instance GHC.Classes.Eq Game.LambdaHack.Client.UI.Animation.Animation -- | UI aspects of actors. module Game.LambdaHack.Client.UI.ActorUI data ActorUI ActorUI :: Char -> Text -> Text -> Color -> ActorUI -- | individual map symbol [bsymbol] :: ActorUI -> Char -- | individual name [bname] :: ActorUI -> Text -- | individual pronoun [bpronoun] :: ActorUI -> Text -- | individual map color [bcolor] :: ActorUI -> Color type ActorDictUI = EnumMap ActorId ActorUI keySelected :: (ActorId, Actor, ActorUI) -> (Bool, Bool, Char, Color, ActorId) -- | The part of speech describing the actor. partActor :: ActorUI -> Part -- | The part of speech containing the actor pronoun. partPronoun :: ActorUI -> Part ppContainer :: Container -> Text ppCStore :: CStore -> (Text, Text) ppCStoreIn :: CStore -> Text ppCStoreWownW :: Bool -> CStore -> Part -> [Part] ppContainerWownW :: (ActorId -> Part) -> Bool -> Container -> [Part] verbCStore :: CStore -> Text tryFindHeroK :: ActorDictUI -> FactionId -> Int -> State -> Maybe (ActorId, Actor) instance GHC.Generics.Generic Game.LambdaHack.Client.UI.ActorUI.ActorUI instance GHC.Classes.Eq Game.LambdaHack.Client.UI.ActorUI.ActorUI instance GHC.Show.Show Game.LambdaHack.Client.UI.ActorUI.ActorUI instance Data.Binary.Class.Binary Game.LambdaHack.Client.UI.ActorUI.ActorUI -- | Actor preferences for targets and actions based on actor attributes. module Game.LambdaHack.Client.Preferences totalUsefulness :: COps -> Faction -> [Effect] -> AspectRecord -> Item -> Benefit -- | How much AI benefits from applying the effect. The first component is -- benefit when applied to self, the second is benefit (preferably -- negative) when applied to enemy. This represents benefit from using -- the effect every avgItemDelay turns, so if the item is not -- durable, the value is adjusted down elsewhere. The benefit includes -- the drawback of having to use the actor's turn, except when there is -- battle and item is a weapon and so there is usually nothing better to -- do than to melee, or when the actor is stuck or idle or laying in wait -- or luring an enemy from a safe distance. So there is less than -- averageTurnValue included in each benefit, so in case when -- turn is not spent, e.g, periodic or temporary effects, the difference -- in value is only slight. effectToBenefit :: COps -> Faction -> Effect -> (Int, Int) organBenefit :: Int -> GroupName ItemKind -> COps -> Faction -> (Int, Int) aspectToBenefit :: Aspect -> Int recordToBenefit :: AspectRecord -> [Int] -- | Operations on the Actor type that need the State type, -- but not our custom monad types. module Game.LambdaHack.Common.ActorState fidActorNotProjAssocs :: FactionId -> State -> [(ActorId, Actor)] actorAssocs :: (FactionId -> Bool) -> LevelId -> State -> [(ActorId, Actor)] actorRegularAssocs :: (FactionId -> Bool) -> LevelId -> State -> [(ActorId, Actor)] warActorRegularList :: FactionId -> LevelId -> State -> [Actor] friendlyActorRegularList :: FactionId -> LevelId -> State -> [Actor] fidActorRegularIds :: FactionId -> LevelId -> State -> [ActorId] bagAssocs :: State -> ItemBag -> [(ItemId, Item)] bagAssocsK :: State -> ItemBag -> [(ItemId, (Item, ItemQuant))] -- | Calculate loot's worth for a given faction. calculateTotal :: FactionId -> State -> (ItemBag, Int) mergeItemQuant :: ItemQuant -> ItemQuant -> ItemQuant sharedEqp :: FactionId -> State -> ItemBag sharedAllOwnedFid :: Bool -> FactionId -> State -> ItemBag findIid :: ActorId -> FactionId -> ItemId -> State -> [(ActorId, (Actor, CStore))] getContainerBag :: Container -> State -> ItemBag getFloorBag :: LevelId -> Point -> State -> ItemBag getEmbedBag :: LevelId -> Point -> State -> ItemBag getBodyStoreBag :: Actor -> CStore -> State -> ItemBag mapActorItems_ :: Monad m => (CStore -> ItemId -> ItemQuant -> m a) -> Actor -> State -> m () getActorAssocs :: ActorId -> CStore -> State -> [(ItemId, Item)] nearbyFreePoints :: (Id TileKind -> Bool) -> Point -> LevelId -> State -> [Point] getCarriedAssocs :: Actor -> State -> [(ItemId, Item)] getCarriedIidCStore :: Actor -> [(ItemId, CStore)] posToAidsLvl :: Point -> Level -> [ActorId] posToAids :: Point -> LevelId -> State -> [ActorId] posToAssocs :: Point -> LevelId -> State -> [(ActorId, Actor)] getItemBody :: ItemId -> State -> Item -- | Checks if the actor is present on the current level. The order of -- argument here and in other functions is set to allow -- --
--   b <- getsState (memActor a)
--   
memActor :: ActorId -> LevelId -> State -> Bool getActorBody :: ActorId -> State -> Actor -- | Get current time from the dungeon data. getLocalTime :: LevelId -> State -> Time regenCalmDelta :: Actor -> AspectRecord -> State -> Int64 actorInAmbient :: Actor -> State -> Bool canDeAmbientList :: Actor -> State -> [Point] actorSkills :: Maybe ActorId -> ActorId -> AspectRecord -> State -> Skills dispEnemy :: ActorId -> ActorId -> Skills -> State -> Bool fullAssocs :: COps -> DiscoveryKind -> DiscoveryAspect -> ActorId -> [CStore] -> State -> [(ItemId, ItemFull)] storeFromC :: Container -> CStore -- | Determine the dungeon level of the container. If the item is in a -- shared stash, the level depends on which actor asks. lidFromC :: Container -> State -> LevelId posFromC :: Container -> State -> Point aidFromC :: Container -> Maybe ActorId isEscape :: LevelId -> Point -> State -> Bool isStair :: LevelId -> Point -> State -> Bool -- | Require that any non-dying foe is adjacent. We include even -- projectiles that explode when stricken down, because they can be -- caught and then they don't explode, so it makes sense to focus on -- handling them. If there are many projectiles in a single adjacent -- position, we only test the first one, the one that would be hit in -- melee (this is not optimal if the actor would need to flee instead of -- meleeing, but fleeing with *many* projectiles adjacent is a possible -- waste of a move anyway). anyFoeAdj :: ActorId -> State -> Bool actorAdjacentAssocs :: Actor -> State -> [(ActorId, Actor)] armorHurtBonus :: ActorAspect -> ActorId -> ActorId -> State -> Int -- | Game action monads and basic building blocks for human and computer -- player actions. Has no access to the main action type. module Game.LambdaHack.Common.MonadStateRead class (Monad m, Functor m, Applicative m) => MonadStateRead m getsState :: MonadStateRead m => (State -> a) -> m a getState :: MonadStateRead m => m State getLevel :: MonadStateRead m => LevelId -> m Level nUI :: MonadStateRead m => m Int getGameMode :: MonadStateRead m => m ModeKind isNoConfirmsGame :: MonadStateRead m => m Bool getEntryArena :: MonadStateRead m => Faction -> m LevelId pickWeaponM :: MonadStateRead m => Maybe DiscoveryBenefit -> [(ItemId, ItemFull)] -> Skills -> ActorAspect -> ActorId -> m [(Int, (ItemId, ItemFull))] -- | Item slots for UI and AI item collections. module Game.LambdaHack.Client.UI.ItemSlot data ItemSlots ItemSlots :: (EnumMap SlotChar ItemId) -> (EnumMap SlotChar ItemId) -> ItemSlots data SlotChar SlotChar :: Int -> Char -> SlotChar [slotPrefix] :: SlotChar -> Int [slotChar] :: SlotChar -> Char allSlots :: Int -> [SlotChar] allZeroSlots :: [SlotChar] intSlots :: [SlotChar] slotLabel :: SlotChar -> Text -- | Assigns a slot to an item, for inclusion in the inventory of a hero. -- Tries to to use the requested slot, if any. assignSlot :: CStore -> Item -> FactionId -> Maybe Actor -> ItemSlots -> SlotChar -> State -> SlotChar instance GHC.Show.Show Game.LambdaHack.Client.UI.ItemSlot.ItemSlots instance GHC.Classes.Eq Game.LambdaHack.Client.UI.ItemSlot.SlotChar instance GHC.Show.Show Game.LambdaHack.Client.UI.ItemSlot.SlotChar instance Data.Binary.Class.Binary Game.LambdaHack.Client.UI.ItemSlot.ItemSlots instance GHC.Classes.Ord Game.LambdaHack.Client.UI.ItemSlot.SlotChar instance Data.Binary.Class.Binary Game.LambdaHack.Client.UI.ItemSlot.SlotChar instance GHC.Enum.Enum Game.LambdaHack.Client.UI.ItemSlot.SlotChar -- | Slideshows. module Game.LambdaHack.Client.UI.Slideshow type KYX = (Either [KM] SlotChar, (Y, X, X)) type OKX = ([AttrLine], [KYX]) data Slideshow emptySlideshow :: Slideshow unsnoc :: Slideshow -> Maybe (Slideshow, OKX) toSlideshow :: [OKX] -> Slideshow menuToSlideshow :: OKX -> Slideshow wrapOKX :: Y -> X -> X -> [(KM, String)] -> OKX splitOverlay :: X -> Y -> Report -> [KM] -> OKX -> Slideshow splitOKX :: X -> Y -> AttrLine -> [KM] -> OKX -> [OKX] instance GHC.Classes.Eq Game.LambdaHack.Client.UI.Slideshow.Slideshow instance GHC.Show.Show Game.LambdaHack.Client.UI.Slideshow.Slideshow -- | The monad for writing to the game state and related operations. module Game.LambdaHack.Atomic.MonadStateWrite class MonadStateRead m => MonadStateWrite m modifyState :: MonadStateWrite m => (State -> State) -> m () putState :: MonadStateWrite m => State -> m () -- | Update a given level data within state. updateLevel :: MonadStateWrite m => LevelId -> (Level -> Level) -> m () updateActor :: MonadStateWrite m => ActorId -> (Actor -> Actor) -> m () updateFaction :: MonadStateWrite m => FactionId -> (Faction -> Faction) -> m () insertItemContainer :: MonadStateWrite m => ItemId -> ItemQuant -> Container -> m () insertItemActor :: MonadStateWrite m => ItemId -> ItemQuant -> ActorId -> CStore -> m () deleteItemContainer :: MonadStateWrite m => ItemId -> ItemQuant -> Container -> m () deleteItemActor :: MonadStateWrite m => ItemId -> ItemQuant -> ActorId -> CStore -> m () -- | Update the items on the ground map. updateFloor :: (ItemFloor -> ItemFloor) -> Level -> Level -- | Update the actors on the ground map. updateActorMap :: (ActorMap -> ActorMap) -> Level -> Level moveActorMap :: MonadStateWrite m => ActorId -> Actor -> Actor -> m () -- | Update the tile map. updateTile :: (TileMap -> TileMap) -> Level -> Level -- | Update the smell map. updateSmell :: (SmellMap -> SmellMap) -> Level -> Level -- | Abstract syntax human player commands. module Game.LambdaHack.Client.UI.HumanCmd data CmdCategory CmdMainMenu :: CmdCategory CmdItemMenu :: CmdCategory CmdMove :: CmdCategory CmdItem :: CmdCategory CmdAim :: CmdCategory CmdMeta :: CmdCategory CmdMouse :: CmdCategory CmdInternal :: CmdCategory CmdNoHelp :: CmdCategory CmdDebug :: CmdCategory CmdMinimal :: CmdCategory categoryDescription :: CmdCategory -> Text data CmdArea CaMessage :: CmdArea CaMapLeader :: CmdArea CaMapParty :: CmdArea CaMap :: CmdArea CaLevelNumber :: CmdArea CaArenaName :: CmdArea CaPercentSeen :: CmdArea CaXhairDesc :: CmdArea CaSelected :: CmdArea CaCalmGauge :: CmdArea CaHPGauge :: CmdArea CaTargetDesc :: CmdArea areaDescription :: CmdArea -> Text type CmdTriple = ([CmdCategory], Text, HumanCmd) -- | Abstract syntax of player commands. data HumanCmd Macro :: [String] -> HumanCmd ByArea :: [(CmdArea, HumanCmd)] -> HumanCmd ByAimMode :: HumanCmd -> HumanCmd -> HumanCmd [exploration] :: HumanCmd -> HumanCmd [aiming] :: HumanCmd -> HumanCmd ByItemMode :: [Trigger] -> HumanCmd -> HumanCmd -> HumanCmd [ts] :: HumanCmd -> [Trigger] [notChosen] :: HumanCmd -> HumanCmd [chosen] :: HumanCmd -> HumanCmd ComposeIfLocal :: HumanCmd -> HumanCmd -> HumanCmd ComposeUnlessError :: HumanCmd -> HumanCmd -> HumanCmd Compose2ndLocal :: HumanCmd -> HumanCmd -> HumanCmd LoopOnNothing :: HumanCmd -> HumanCmd Wait :: HumanCmd Wait10 :: HumanCmd MoveDir :: Vector -> HumanCmd RunDir :: Vector -> HumanCmd RunOnceAhead :: HumanCmd MoveOnceToXhair :: HumanCmd RunOnceToXhair :: HumanCmd ContinueToXhair :: HumanCmd MoveItem :: [CStore] -> CStore -> (Maybe Part) -> Bool -> HumanCmd Project :: [Trigger] -> HumanCmd Apply :: [Trigger] -> HumanCmd AlterDir :: [Trigger] -> HumanCmd AlterWithPointer :: [Trigger] -> HumanCmd Help :: HumanCmd ItemMenu :: HumanCmd MainMenu :: HumanCmd GameDifficultyIncr :: HumanCmd GameWolfToggle :: HumanCmd GameFishToggle :: HumanCmd GameScenarioIncr :: HumanCmd GameRestart :: HumanCmd GameExit :: HumanCmd GameSave :: HumanCmd Tactic :: HumanCmd Automate :: HumanCmd Clear :: HumanCmd SortSlots :: HumanCmd ChooseItem :: ItemDialogMode -> HumanCmd ChooseItemMenu :: ItemDialogMode -> HumanCmd ChooseItemProject :: [Trigger] -> HumanCmd ChooseItemApply :: [Trigger] -> HumanCmd PickLeader :: Int -> HumanCmd PickLeaderWithPointer :: HumanCmd MemberCycle :: HumanCmd MemberBack :: HumanCmd SelectActor :: HumanCmd SelectNone :: HumanCmd SelectWithPointer :: HumanCmd Repeat :: Int -> HumanCmd Record :: HumanCmd History :: HumanCmd MarkVision :: HumanCmd MarkSmell :: HumanCmd MarkSuspect :: HumanCmd SettingsMenu :: HumanCmd ChallengesMenu :: HumanCmd Cancel :: HumanCmd Accept :: HumanCmd TgtClear :: HumanCmd ItemClear :: HumanCmd MoveXhair :: Vector -> Int -> HumanCmd AimTgt :: HumanCmd AimFloor :: HumanCmd AimEnemy :: HumanCmd AimItem :: HumanCmd AimAscend :: Int -> HumanCmd EpsIncr :: Bool -> HumanCmd XhairUnknown :: HumanCmd XhairItem :: HumanCmd XhairStair :: Bool -> HumanCmd XhairPointerFloor :: HumanCmd XhairPointerEnemy :: HumanCmd AimPointerFloor :: HumanCmd AimPointerEnemy :: HumanCmd -- | Commands that are forbidden on a remote level, because they would -- usually take time when invoked on one, but not necessarily do what the -- player expects. Note that some commands that normally take time are -- not included, because they don't take time in aiming mode or their -- individual sanity conditions include a remote level check. noRemoteHumanCmd :: HumanCmd -> Bool data Trigger ApplyItem :: Part -> Part -> Char -> Trigger [verb] :: Trigger -> Part [object] :: Trigger -> Part [symbol] :: Trigger -> Char AlterFeature :: Part -> Part -> Feature -> Trigger [verb] :: Trigger -> Part [object] :: Trigger -> Part [feature] :: Trigger -> Feature instance GHC.Generics.Generic Game.LambdaHack.Client.UI.HumanCmd.HumanCmd instance GHC.Classes.Ord Game.LambdaHack.Client.UI.HumanCmd.HumanCmd instance GHC.Classes.Eq Game.LambdaHack.Client.UI.HumanCmd.HumanCmd instance GHC.Read.Read Game.LambdaHack.Client.UI.HumanCmd.HumanCmd instance GHC.Show.Show Game.LambdaHack.Client.UI.HumanCmd.HumanCmd instance GHC.Generics.Generic Game.LambdaHack.Client.UI.HumanCmd.Trigger instance GHC.Classes.Ord Game.LambdaHack.Client.UI.HumanCmd.Trigger instance GHC.Classes.Eq Game.LambdaHack.Client.UI.HumanCmd.Trigger instance GHC.Show.Show Game.LambdaHack.Client.UI.HumanCmd.Trigger instance GHC.Generics.Generic Game.LambdaHack.Client.UI.HumanCmd.CmdArea instance GHC.Classes.Ord Game.LambdaHack.Client.UI.HumanCmd.CmdArea instance GHC.Classes.Eq Game.LambdaHack.Client.UI.HumanCmd.CmdArea instance GHC.Read.Read Game.LambdaHack.Client.UI.HumanCmd.CmdArea instance GHC.Show.Show Game.LambdaHack.Client.UI.HumanCmd.CmdArea instance GHC.Generics.Generic Game.LambdaHack.Client.UI.HumanCmd.CmdCategory instance GHC.Classes.Eq Game.LambdaHack.Client.UI.HumanCmd.CmdCategory instance GHC.Read.Read Game.LambdaHack.Client.UI.HumanCmd.CmdCategory instance GHC.Show.Show Game.LambdaHack.Client.UI.HumanCmd.CmdCategory instance Control.DeepSeq.NFData Game.LambdaHack.Client.UI.HumanCmd.HumanCmd instance Data.Binary.Class.Binary Game.LambdaHack.Client.UI.HumanCmd.HumanCmd instance GHC.Read.Read Game.LambdaHack.Client.UI.HumanCmd.Trigger instance Control.DeepSeq.NFData Game.LambdaHack.Client.UI.HumanCmd.Trigger instance Data.Binary.Class.Binary Game.LambdaHack.Client.UI.HumanCmd.Trigger instance Control.DeepSeq.NFData Game.LambdaHack.Client.UI.HumanCmd.CmdArea instance Data.Binary.Class.Binary Game.LambdaHack.Client.UI.HumanCmd.CmdArea instance Control.DeepSeq.NFData Game.LambdaHack.Client.UI.HumanCmd.CmdCategory instance Data.Binary.Class.Binary Game.LambdaHack.Client.UI.HumanCmd.CmdCategory -- | The type of key-command mappings to be used for the UI. module Game.LambdaHack.Client.UI.Content.KeyKind -- | Key-command mappings to be used for the UI. newtype KeyKind KeyKind :: [(KM, CmdTriple)] -> KeyKind -- | default client UI commands [rhumanCommands] :: KeyKind -> [(KM, CmdTriple)] evalKeyDef :: (String, CmdTriple) -> (KM, CmdTriple) addCmdCategory :: CmdCategory -> CmdTriple -> CmdTriple replaceDesc :: Text -> CmdTriple -> CmdTriple moveItemTriple :: [CStore] -> CStore -> Part -> Bool -> CmdTriple repeatTriple :: Int -> CmdTriple mouseLMB :: CmdTriple mouseMMB :: CmdTriple mouseRMB :: CmdTriple goToCmd :: HumanCmd runToAllCmd :: HumanCmd autoexploreCmd :: HumanCmd autoexplore25Cmd :: HumanCmd aimFlingCmd :: HumanCmd projectI :: [Trigger] -> CmdTriple projectA :: [Trigger] -> CmdTriple flingTs :: [Trigger] applyI :: [Trigger] -> CmdTriple applyIK :: [Trigger] -> CmdTriple grabItems :: Text -> CmdTriple dropItems :: Text -> CmdTriple descTs :: [Trigger] -> Text defaultHeroSelect :: Int -> (String, CmdTriple) -- | Personal game configuration file type definitions. module Game.LambdaHack.Client.UI.Config -- | Fully typed contents of the UI config file. This config is a part of a -- game client. data Config Config :: [(KM, CmdTriple)] -> [(Int, (Text, Text))] -> Bool -> Bool -> Text -> Text -> Int -> Int -> Int -> Bool -> Int -> Int -> Bool -> Bool -> [String] -> Config [configCommands] :: Config -> [(KM, CmdTriple)] [configHeroNames] :: Config -> [(Int, (Text, Text))] -- | the option for Vi keys takes precendence [configVi] :: Config -> Bool -- | because the laptop keys are the default [configLaptop] :: Config -> Bool [configGtkFontFamily] :: Config -> Text [configSdlFontFile] :: Config -> Text [configSdlTtfSizeAdd] :: Config -> Int [configSdlFonSizeAdd] :: Config -> Int [configFontSize] :: Config -> Int [configColorIsBold] :: Config -> Bool [configHistoryMax] :: Config -> Int [configMaxFps] :: Config -> Int [configNoAnim] :: Config -> Bool [configRunStopMsgs] :: Config -> Bool [configCmdline] :: Config -> [String] -- | Read and parse UI config file. mkConfig :: COps -> Bool -> IO Config applyConfigToDebug :: COps -> Config -> DebugModeCli -> DebugModeCli instance GHC.Generics.Generic Game.LambdaHack.Client.UI.Config.Config instance GHC.Show.Show Game.LambdaHack.Client.UI.Config.Config instance Control.DeepSeq.NFData Game.LambdaHack.Client.UI.Config.Config instance Data.Binary.Class.Binary Game.LambdaHack.Client.UI.Config.Config -- | Binding of keys to commands. No operation in this module involves the -- State or Action type. module Game.LambdaHack.Client.UI.KeyBindings -- | Bindings and other information about human player commands. data Binding Binding :: Map KM CmdTriple -> [(KM, CmdTriple)] -> Map HumanCmd [KM] -> Binding -- | binding of keys to commands [bcmdMap] :: Binding -> Map KM CmdTriple -- | the properly ordered list of commands for the help menu [bcmdList] :: Binding -> [(KM, CmdTriple)] -- | and from commands to their keys [brevMap] :: Binding -> Map HumanCmd [KM] -- | Binding of keys to movement and other standard commands, as well as -- commands defined in the config file. stdBinding :: KeyKind -> Config -> Binding -- | Produce a set of help screens from the key bindings. keyHelp :: Binding -> Int -> [(Text, OKX)] okxsN :: Binding -> Int -> Int -> (HumanCmd -> Bool) -> CmdCategory -> [Text] -> [Text] -> OKX -- | The client UI session state. module Game.LambdaHack.Client.UI.SessionUI -- | The information that is used across a client playing session, -- including many consecutive games in a single session. Some of it is -- saved, some is reset when a new playing session starts. An important -- component is a frontend session. data SessionUI SessionUI :: Target -> ActorDictUI -> ItemSlots -> SlotChar -> Maybe (CStore, CStore) -> ChanFrontend -> Binding -> Config -> Maybe AimMode -> Bool -> Maybe (CStore, ItemId) -> EnumSet ActorId -> Maybe RunParams -> Report -> History -> Point -> LastRecord -> [KM] -> EnumSet ActorId -> Int -> Bool -> Bool -> Map String Int -> Bool -> KeysHintMode -> POSIXTime -> POSIXTime -> Time -> Int -> Int -> SessionUI -- | the common xhair [sxhair] :: SessionUI -> Target -- | assigned actor UI presentations [sactorUI] :: SessionUI -> ActorDictUI -- | map from slots to items [sslots] :: SessionUI -> ItemSlots -- | last used slot [slastSlot] :: SessionUI -> SlotChar -- | last item move stores [slastItemMove] :: SessionUI -> Maybe (CStore, CStore) -- | connection with the frontend [schanF] :: SessionUI -> ChanFrontend -- | binding of keys to commands [sbinding] :: SessionUI -> Binding [sconfig] :: SessionUI -> Config -- | aiming mode [saimMode] :: SessionUI -> Maybe AimMode -- | last mouse aiming not vacuus [sxhairMoused] :: SessionUI -> Bool -- | selected item, if any [sitemSel] :: SessionUI -> Maybe (CStore, ItemId) -- | the set of currently selected actors [sselected] :: SessionUI -> EnumSet ActorId -- | parameters of the current run, if any [srunning] :: SessionUI -> Maybe RunParams -- | current messages [_sreport] :: SessionUI -> Report -- | history of messages [shistory] :: SessionUI -> History -- | mouse pointer position [spointer] :: SessionUI -> Point -- | state of key sequence recording [slastRecord] :: SessionUI -> LastRecord -- | state of key sequence playback [slastPlay] :: SessionUI -> [KM] -- | actors that just got out of sight [slastLost] :: SessionUI -> EnumSet ActorId -- | player just waited this many times [swaitTimes] :: SessionUI -> Int -- | mark leader and party FOV [smarkVision] :: SessionUI -> Bool -- | mark smell, if the leader can smell [smarkSmell] :: SessionUI -> Bool -- | indices of last used menu items [smenuIxMap] :: SessionUI -> Map String Int -- | something to display on current level [sdisplayNeeded] :: SessionUI -> Bool -- | how to show keys hints when no messages [skeysHintMode] :: SessionUI -> KeysHintMode -- | this session start time [sstart] :: SessionUI -> POSIXTime -- | this game start time [sgstart] :: SessionUI -> POSIXTime -- | clips from start of session to current game start [sallTime] :: SessionUI -> Time -- | this game current frame count [snframes] :: SessionUI -> Int -- | frame count from start of session to current game start [sallNframes] :: SessionUI -> Int -- | Initial empty game client state. emptySessionUI :: Config -> SessionUI -- | Current aiming mode of a client. newtype AimMode AimMode :: LevelId -> AimMode [aimLevelId] :: AimMode -> LevelId -- | Parameters of the current run. data RunParams RunParams :: ActorId -> [ActorId] -> Bool -> Maybe Text -> Int -> RunParams -- | the original leader from run start [runLeader] :: RunParams -> ActorId -- | the list of actors that take part [runMembers] :: RunParams -> [ActorId] -- | initial run continuation by any run participant, including run leader [runInitial] :: RunParams -> Bool -- | message with the next stop reason [runStopMsg] :: RunParams -> Maybe Text -- | waiting for others to move out of the way [runWaiting] :: RunParams -> Int type LastRecord = ([KM], [KM], Int) data KeysHintMode KeysHintBlocked :: KeysHintMode KeysHintAbsent :: KeysHintMode KeysHintPresent :: KeysHintMode toggleMarkVision :: SessionUI -> SessionUI toggleMarkSmell :: SessionUI -> SessionUI getActorUI :: ActorId -> SessionUI -> ActorUI instance GHC.Enum.Bounded Game.LambdaHack.Client.UI.SessionUI.KeysHintMode instance GHC.Enum.Enum Game.LambdaHack.Client.UI.SessionUI.KeysHintMode instance GHC.Classes.Eq Game.LambdaHack.Client.UI.SessionUI.KeysHintMode instance GHC.Show.Show Game.LambdaHack.Client.UI.SessionUI.RunParams instance Data.Binary.Class.Binary Game.LambdaHack.Client.UI.SessionUI.AimMode instance GHC.Classes.Eq Game.LambdaHack.Client.UI.SessionUI.AimMode instance GHC.Show.Show Game.LambdaHack.Client.UI.SessionUI.AimMode instance Data.Binary.Class.Binary Game.LambdaHack.Client.UI.SessionUI.SessionUI instance Data.Binary.Class.Binary Game.LambdaHack.Client.UI.SessionUI.RunParams -- | A set of atomic commands shared by client and server. These are the -- largest building blocks that have no components that can be observed -- in isolation. -- -- We try to make atomic commands respect the laws of energy and mass -- conservation, unless they really can't, e.g., monster spawning. For -- example item removal from inventory is not an atomic command, but item -- dropped from the inventory to the ground is. This makes it easier to -- undo the commands. In principle, the commands are the only way to -- affect the basic game state (State). -- -- See -- https://github.com/LambdaHack/LambdaHack/wiki/Client-server-architecture. module Game.LambdaHack.Atomic.CmdAtomic -- | Abstract syntax of atomic commands, that is, atomic game state -- transformations. data CmdAtomic -- | atomic updates UpdAtomic :: UpdAtomic -> CmdAtomic -- | atomic special effects SfxAtomic :: SfxAtomic -> CmdAtomic -- | Abstract syntax of atomic updates, that is, atomic commands that -- really change the state. Most of them are an encoding of a game state -- diff, though they also carry some intentional hints that help clients -- determine whether and how to communicate them to players. data UpdAtomic UpdCreateActor :: ActorId -> Actor -> [(ItemId, Item)] -> UpdAtomic UpdDestroyActor :: ActorId -> Actor -> [(ItemId, Item)] -> UpdAtomic UpdCreateItem :: ItemId -> Item -> ItemQuant -> Container -> UpdAtomic UpdDestroyItem :: ItemId -> Item -> ItemQuant -> Container -> UpdAtomic UpdSpotActor :: ActorId -> Actor -> [(ItemId, Item)] -> UpdAtomic UpdLoseActor :: ActorId -> Actor -> [(ItemId, Item)] -> UpdAtomic UpdSpotItem :: Bool -> ItemId -> Item -> ItemQuant -> Container -> UpdAtomic UpdLoseItem :: Bool -> ItemId -> Item -> ItemQuant -> Container -> UpdAtomic UpdMoveActor :: ActorId -> Point -> Point -> UpdAtomic UpdWaitActor :: ActorId -> Bool -> UpdAtomic UpdDisplaceActor :: ActorId -> ActorId -> UpdAtomic UpdMoveItem :: ItemId -> Int -> ActorId -> CStore -> CStore -> UpdAtomic UpdRefillHP :: ActorId -> Int64 -> UpdAtomic UpdRefillCalm :: ActorId -> Int64 -> UpdAtomic UpdTrajectory :: ActorId -> (Maybe ([Vector], Speed)) -> (Maybe ([Vector], Speed)) -> UpdAtomic UpdQuitFaction :: FactionId -> (Maybe Status) -> (Maybe Status) -> UpdAtomic UpdLeadFaction :: FactionId -> (Maybe ActorId) -> (Maybe ActorId) -> UpdAtomic UpdDiplFaction :: FactionId -> FactionId -> Diplomacy -> Diplomacy -> UpdAtomic UpdTacticFaction :: FactionId -> Tactic -> Tactic -> UpdAtomic UpdAutoFaction :: FactionId -> Bool -> UpdAtomic UpdRecordKill :: ActorId -> (Id ItemKind) -> Int -> UpdAtomic UpdAlterTile :: LevelId -> Point -> (Id TileKind) -> (Id TileKind) -> UpdAtomic UpdAlterExplorable :: LevelId -> Int -> UpdAtomic UpdSearchTile :: ActorId -> Point -> (Id TileKind) -> UpdAtomic UpdHideTile :: ActorId -> Point -> (Id TileKind) -> UpdAtomic UpdSpotTile :: LevelId -> [(Point, Id TileKind)] -> UpdAtomic UpdLoseTile :: LevelId -> [(Point, Id TileKind)] -> UpdAtomic UpdAlterSmell :: LevelId -> Point -> Time -> Time -> UpdAtomic UpdSpotSmell :: LevelId -> [(Point, Time)] -> UpdAtomic UpdLoseSmell :: LevelId -> [(Point, Time)] -> UpdAtomic UpdTimeItem :: ItemId -> Container -> ItemTimer -> ItemTimer -> UpdAtomic UpdAgeGame :: [LevelId] -> UpdAtomic UpdUnAgeGame :: [LevelId] -> UpdAtomic UpdDiscover :: Container -> ItemId -> (Id ItemKind) -> ItemSeed -> UpdAtomic UpdCover :: Container -> ItemId -> (Id ItemKind) -> ItemSeed -> UpdAtomic UpdDiscoverKind :: Container -> ItemId -> (Id ItemKind) -> UpdAtomic UpdCoverKind :: Container -> ItemId -> (Id ItemKind) -> UpdAtomic UpdDiscoverSeed :: Container -> ItemId -> ItemSeed -> UpdAtomic UpdCoverSeed :: Container -> ItemId -> ItemSeed -> UpdAtomic UpdPerception :: LevelId -> Perception -> Perception -> UpdAtomic UpdRestart :: FactionId -> DiscoveryKind -> PerLid -> State -> Challenge -> DebugModeCli -> UpdAtomic UpdRestartServer :: State -> UpdAtomic UpdResume :: FactionId -> PerLid -> UpdAtomic UpdResumeServer :: State -> UpdAtomic UpdKillExit :: FactionId -> UpdAtomic UpdWriteSave :: UpdAtomic UpdMsgAll :: Text -> UpdAtomic -- | Abstract syntax of atomic special effects, that is, atomic commands -- that only display special effects and don't change the state. data SfxAtomic SfxStrike :: ActorId -> ActorId -> ItemId -> CStore -> SfxAtomic SfxRecoil :: ActorId -> ActorId -> ItemId -> CStore -> SfxAtomic SfxSteal :: ActorId -> ActorId -> ItemId -> CStore -> SfxAtomic SfxRelease :: ActorId -> ActorId -> ItemId -> CStore -> SfxAtomic SfxProject :: ActorId -> ItemId -> CStore -> SfxAtomic SfxReceive :: ActorId -> ItemId -> CStore -> SfxAtomic SfxApply :: ActorId -> ItemId -> CStore -> SfxAtomic SfxCheck :: ActorId -> ItemId -> CStore -> SfxAtomic SfxTrigger :: ActorId -> Point -> SfxAtomic SfxShun :: ActorId -> Point -> SfxAtomic SfxEffect :: FactionId -> ActorId -> Effect -> Int64 -> SfxAtomic SfxMsgFid :: FactionId -> SfxMsg -> SfxAtomic data SfxMsg SfxUnexpected :: ReqFailure -> SfxMsg SfxLoudUpd :: Bool -> UpdAtomic -> SfxMsg SfxLoudStrike :: Bool -> (Id ItemKind) -> Int -> SfxMsg SfxLoudSummon :: Bool -> (GroupName ItemKind) -> Dice -> SfxMsg SfxFizzles :: SfxMsg SfxNothingHappens :: SfxMsg SfxVoidDetection :: SfxMsg SfxSummonLackCalm :: ActorId -> SfxMsg SfxLevelNoMore :: SfxMsg SfxLevelPushed :: SfxMsg SfxBracedImmune :: ActorId -> SfxMsg SfxEscapeImpossible :: SfxMsg SfxTransImpossible :: SfxMsg SfxIdentifyNothing :: CStore -> SfxMsg SfxPurposeNothing :: CStore -> SfxMsg SfxPurposeTooFew :: Int -> Int -> SfxMsg SfxPurposeUnique :: SfxMsg SfxColdFish :: SfxMsg SfxTimerExtended :: ActorId -> ItemId -> CStore -> SfxMsg undoUpdAtomic :: UpdAtomic -> Maybe UpdAtomic undoSfxAtomic :: SfxAtomic -> SfxAtomic undoCmdAtomic :: CmdAtomic -> Maybe CmdAtomic instance GHC.Generics.Generic Game.LambdaHack.Atomic.CmdAtomic.CmdAtomic instance GHC.Classes.Eq Game.LambdaHack.Atomic.CmdAtomic.CmdAtomic instance GHC.Show.Show Game.LambdaHack.Atomic.CmdAtomic.CmdAtomic instance GHC.Generics.Generic Game.LambdaHack.Atomic.CmdAtomic.SfxAtomic instance GHC.Classes.Eq Game.LambdaHack.Atomic.CmdAtomic.SfxAtomic instance GHC.Show.Show Game.LambdaHack.Atomic.CmdAtomic.SfxAtomic instance GHC.Generics.Generic Game.LambdaHack.Atomic.CmdAtomic.SfxMsg instance GHC.Classes.Eq Game.LambdaHack.Atomic.CmdAtomic.SfxMsg instance GHC.Show.Show Game.LambdaHack.Atomic.CmdAtomic.SfxMsg instance GHC.Generics.Generic Game.LambdaHack.Atomic.CmdAtomic.UpdAtomic instance GHC.Classes.Eq Game.LambdaHack.Atomic.CmdAtomic.UpdAtomic instance GHC.Show.Show Game.LambdaHack.Atomic.CmdAtomic.UpdAtomic instance Data.Binary.Class.Binary Game.LambdaHack.Atomic.CmdAtomic.CmdAtomic instance Data.Binary.Class.Binary Game.LambdaHack.Atomic.CmdAtomic.SfxAtomic instance Data.Binary.Class.Binary Game.LambdaHack.Atomic.CmdAtomic.SfxMsg instance Data.Binary.Class.Binary Game.LambdaHack.Atomic.CmdAtomic.UpdAtomic -- | Semantics of atomic commands shared by client and server. See -- https://github.com/LambdaHack/LambdaHack/wiki/Client-server-architecture. module Game.LambdaHack.Atomic.PosAtomicRead -- | The type representing visibility of atomic commands to factions, based -- on the position of the command, etc. Note that the server sees and -- smells all positions. data PosAtomic -- | whomever sees all the positions, notices PosSight :: LevelId -> [Point] -> PosAtomic -- | observers and the faction notice PosFidAndSight :: [FactionId] -> LevelId -> [Point] -> PosAtomic -- | whomever smells all the positions, notices PosSmell :: LevelId -> [Point] -> PosAtomic -- | only the faction notices PosFid :: FactionId -> PosAtomic -- | faction and server notices PosFidAndSer :: (Maybe LevelId) -> FactionId -> PosAtomic -- | only the server notices PosSer :: PosAtomic -- | everybody notices PosAll :: PosAtomic -- | never broadcasted, but sent manually PosNone :: PosAtomic -- | Produce the positions where the atomic update takes place. -- -- The goal of the mechanics is to ensure the commands don't carry -- significantly more information than their corresponding state diffs -- would. In other words, the atomic commands involving the positions -- seen by a client should convey similar information as the client would -- get by directly observing the changes the commands enact on the -- visible portion of server game state. The client is then free to -- change its copy of game state accordingly or not --- it only partially -- reflects reality anyway. -- -- E.g., UpdDisplaceActor in a black room, with one actor -- carrying a 0-radius light would not be distinguishable by looking at -- the state (or the screen) from UpdMoveActor of the -- illuminated actor, hence such UpdDisplaceActor should not be -- observable, but UpdMoveActor should be (or the former should -- be perceived as the latter). However, to simplify, we assign as strict -- visibility requirements to UpdMoveActor as to -- UpdDisplaceActor and fall back to UpdSpotActor -- (which provides minimal information that does not contradict state) if -- the visibility is lower. posUpdAtomic :: MonadStateRead m => UpdAtomic -> m PosAtomic -- | Produce the positions where the atomic special effect takes place. posSfxAtomic :: MonadStateRead m => SfxAtomic -> m PosAtomic -- | Decompose an atomic action. The decomposed actions give reduced -- information that still modifies client's state to match the server -- state wrt the current FOV and the subset of posUpdAtomic that -- is visible. The original actions give more information not only due to -- spanning potentially more positions than those visible. E.g., -- UpdMoveActor informs about the continued existence of the -- actor between moves, v.s., popping out of existence and then back in. breakUpdAtomic :: MonadStateRead m => UpdAtomic -> m [UpdAtomic] -- | Given the client, it's perception and an atomic command, determine if -- the client notices the command. seenAtomicCli :: Bool -> FactionId -> Perception -> PosAtomic -> Bool seenAtomicSer :: PosAtomic -> Bool -- | Generate the atomic updates that jointly perform a given item move. generalMoveItem :: MonadStateRead m => Bool -> ItemId -> Int -> Container -> Container -> m [UpdAtomic] posProjBody :: Actor -> PosAtomic instance GHC.Classes.Eq Game.LambdaHack.Atomic.PosAtomicRead.PosAtomic instance GHC.Show.Show Game.LambdaHack.Atomic.PosAtomicRead.PosAtomic -- | Atomic monads for handling atomic game state transformations. module Game.LambdaHack.Atomic.MonadAtomic -- | The monad for executing atomic game state transformations. class MonadStateRead m => MonadAtomic m -- | Execute an atomic command that really changes the state. execUpdAtomic :: MonadAtomic m => UpdAtomic -> m () -- | Execute an atomic command that only displays special effects. execSfxAtomic :: MonadAtomic m => SfxAtomic -> m () execSendPer :: MonadAtomic m => FactionId -> LevelId -> Perception -> Perception -> Perception -> m () -- | Semantics of atomic commands shared by client and server. See -- https://github.com/LambdaHack/LambdaHack/wiki/Client-server-architecture. module Game.LambdaHack.Atomic.HandleAtomicWrite -- | The game-state semantics of atomic game commands. Special effects -- (SfxAtomic) don't modify state. handleUpdAtomic :: MonadStateWrite m => UpdAtomic -> m () -- | Creates an actor. Note: after this command, usually a new leader for -- the party should be elected (in case this actor is the only one -- alive). updCreateActor :: MonadStateWrite m => ActorId -> Actor -> [(ItemId, Item)] -> m () -- | Kills an actor. updDestroyActor :: MonadStateWrite m => ActorId -> Actor -> [(ItemId, Item)] -> m () -- | Create a few copies of an item that is already registered for the -- dungeon (in sitemRev field of StateServer). updCreateItem :: MonadStateWrite m => ItemId -> Item -> ItemQuant -> Container -> m () -- | Destroy some copies (possibly not all) of an item. updDestroyItem :: MonadStateWrite m => ItemId -> Item -> ItemQuant -> Container -> m () updMoveActor :: MonadStateWrite m => ActorId -> Point -> Point -> m () updWaitActor :: MonadStateWrite m => ActorId -> Bool -> m () updDisplaceActor :: MonadStateWrite m => ActorId -> ActorId -> m () updMoveItem :: MonadStateWrite m => ItemId -> Int -> ActorId -> CStore -> CStore -> m () updRefillHP :: MonadStateWrite m => ActorId -> Int64 -> m () updRefillCalm :: MonadStateWrite m => ActorId -> Int64 -> m () updTrajectory :: MonadStateWrite m => ActorId -> Maybe ([Vector], Speed) -> Maybe ([Vector], Speed) -> m () updQuitFaction :: MonadStateWrite m => FactionId -> Maybe Status -> Maybe Status -> m () updLeadFaction :: MonadStateWrite m => FactionId -> Maybe ActorId -> Maybe ActorId -> m () updDiplFaction :: MonadStateWrite m => FactionId -> FactionId -> Diplomacy -> Diplomacy -> m () updTacticFaction :: MonadStateWrite m => FactionId -> Tactic -> Tactic -> m () updAutoFaction :: MonadStateWrite m => FactionId -> Bool -> m () -- | Record a given number (usually just 1, or -1 for undo) of actor kills -- for score calculation. updRecordKill :: MonadStateWrite m => ActorId -> Id ItemKind -> Int -> m () -- | Alter an attribute (actually, the only, the defining attribute) of a -- visible tile. This is similar to e.g., UpdTrajectory. -- -- For now, we don't remove embedded items when altering a tile and -- neither do we create fresh ones. It works fine, e.g., for tiles on -- fire that change into burnt out tile and then the fire item can no -- longer be triggered due to alterMinSkillKind excluding items -- without Embed, even if the burnt tile has low enough -- talter. updAlterTile :: MonadStateWrite m => LevelId -> Point -> Id TileKind -> Id TileKind -> m () updAlterExplorable :: MonadStateWrite m => LevelId -> Int -> m () updSpotTile :: MonadStateWrite m => LevelId -> [(Point, Id TileKind)] -> m () updLoseTile :: MonadStateWrite m => LevelId -> [(Point, Id TileKind)] -> m () updAlterSmell :: MonadStateWrite m => LevelId -> Point -> Time -> Time -> m () updSpotSmell :: MonadStateWrite m => LevelId -> [(Point, Time)] -> m () updLoseSmell :: MonadStateWrite m => LevelId -> [(Point, Time)] -> m () updTimeItem :: MonadStateWrite m => ItemId -> Container -> ItemTimer -> ItemTimer -> m () -- | Age the game. updAgeGame :: MonadStateWrite m => [LevelId] -> m () updUnAgeGame :: MonadStateWrite m => [LevelId] -> m () updRestart :: MonadStateWrite m => State -> m () updRestartServer :: MonadStateWrite m => State -> m () updResumeServer :: MonadStateWrite m => State -> m () -- | Atomic game state transformations. -- -- See -- https://github.com/LambdaHack/LambdaHack/wiki/Client-server-architecture. module Game.LambdaHack.Atomic -- | The monad for executing atomic game state transformations. class MonadStateRead m => MonadAtomic m -- | Execute an atomic command that really changes the state. execUpdAtomic :: MonadAtomic m => UpdAtomic -> m () -- | Execute an atomic command that only displays special effects. execSfxAtomic :: MonadAtomic m => SfxAtomic -> m () execSendPer :: MonadAtomic m => FactionId -> LevelId -> Perception -> Perception -> Perception -> m () -- | Abstract syntax of atomic commands, that is, atomic game state -- transformations. data CmdAtomic -- | atomic updates UpdAtomic :: UpdAtomic -> CmdAtomic -- | atomic special effects SfxAtomic :: SfxAtomic -> CmdAtomic -- | Abstract syntax of atomic updates, that is, atomic commands that -- really change the state. Most of them are an encoding of a game state -- diff, though they also carry some intentional hints that help clients -- determine whether and how to communicate them to players. data UpdAtomic UpdCreateActor :: ActorId -> Actor -> [(ItemId, Item)] -> UpdAtomic UpdDestroyActor :: ActorId -> Actor -> [(ItemId, Item)] -> UpdAtomic UpdCreateItem :: ItemId -> Item -> ItemQuant -> Container -> UpdAtomic UpdDestroyItem :: ItemId -> Item -> ItemQuant -> Container -> UpdAtomic UpdSpotActor :: ActorId -> Actor -> [(ItemId, Item)] -> UpdAtomic UpdLoseActor :: ActorId -> Actor -> [(ItemId, Item)] -> UpdAtomic UpdSpotItem :: Bool -> ItemId -> Item -> ItemQuant -> Container -> UpdAtomic UpdLoseItem :: Bool -> ItemId -> Item -> ItemQuant -> Container -> UpdAtomic UpdMoveActor :: ActorId -> Point -> Point -> UpdAtomic UpdWaitActor :: ActorId -> Bool -> UpdAtomic UpdDisplaceActor :: ActorId -> ActorId -> UpdAtomic UpdMoveItem :: ItemId -> Int -> ActorId -> CStore -> CStore -> UpdAtomic UpdRefillHP :: ActorId -> Int64 -> UpdAtomic UpdRefillCalm :: ActorId -> Int64 -> UpdAtomic UpdTrajectory :: ActorId -> (Maybe ([Vector], Speed)) -> (Maybe ([Vector], Speed)) -> UpdAtomic UpdQuitFaction :: FactionId -> (Maybe Status) -> (Maybe Status) -> UpdAtomic UpdLeadFaction :: FactionId -> (Maybe ActorId) -> (Maybe ActorId) -> UpdAtomic UpdDiplFaction :: FactionId -> FactionId -> Diplomacy -> Diplomacy -> UpdAtomic UpdTacticFaction :: FactionId -> Tactic -> Tactic -> UpdAtomic UpdAutoFaction :: FactionId -> Bool -> UpdAtomic UpdRecordKill :: ActorId -> (Id ItemKind) -> Int -> UpdAtomic UpdAlterTile :: LevelId -> Point -> (Id TileKind) -> (Id TileKind) -> UpdAtomic UpdAlterExplorable :: LevelId -> Int -> UpdAtomic UpdSearchTile :: ActorId -> Point -> (Id TileKind) -> UpdAtomic UpdHideTile :: ActorId -> Point -> (Id TileKind) -> UpdAtomic UpdSpotTile :: LevelId -> [(Point, Id TileKind)] -> UpdAtomic UpdLoseTile :: LevelId -> [(Point, Id TileKind)] -> UpdAtomic UpdAlterSmell :: LevelId -> Point -> Time -> Time -> UpdAtomic UpdSpotSmell :: LevelId -> [(Point, Time)] -> UpdAtomic UpdLoseSmell :: LevelId -> [(Point, Time)] -> UpdAtomic UpdTimeItem :: ItemId -> Container -> ItemTimer -> ItemTimer -> UpdAtomic UpdAgeGame :: [LevelId] -> UpdAtomic UpdUnAgeGame :: [LevelId] -> UpdAtomic UpdDiscover :: Container -> ItemId -> (Id ItemKind) -> ItemSeed -> UpdAtomic UpdCover :: Container -> ItemId -> (Id ItemKind) -> ItemSeed -> UpdAtomic UpdDiscoverKind :: Container -> ItemId -> (Id ItemKind) -> UpdAtomic UpdCoverKind :: Container -> ItemId -> (Id ItemKind) -> UpdAtomic UpdDiscoverSeed :: Container -> ItemId -> ItemSeed -> UpdAtomic UpdCoverSeed :: Container -> ItemId -> ItemSeed -> UpdAtomic UpdPerception :: LevelId -> Perception -> Perception -> UpdAtomic UpdRestart :: FactionId -> DiscoveryKind -> PerLid -> State -> Challenge -> DebugModeCli -> UpdAtomic UpdRestartServer :: State -> UpdAtomic UpdResume :: FactionId -> PerLid -> UpdAtomic UpdResumeServer :: State -> UpdAtomic UpdKillExit :: FactionId -> UpdAtomic UpdWriteSave :: UpdAtomic UpdMsgAll :: Text -> UpdAtomic -- | Abstract syntax of atomic special effects, that is, atomic commands -- that only display special effects and don't change the state. data SfxAtomic SfxStrike :: ActorId -> ActorId -> ItemId -> CStore -> SfxAtomic SfxRecoil :: ActorId -> ActorId -> ItemId -> CStore -> SfxAtomic SfxSteal :: ActorId -> ActorId -> ItemId -> CStore -> SfxAtomic SfxRelease :: ActorId -> ActorId -> ItemId -> CStore -> SfxAtomic SfxProject :: ActorId -> ItemId -> CStore -> SfxAtomic SfxReceive :: ActorId -> ItemId -> CStore -> SfxAtomic SfxApply :: ActorId -> ItemId -> CStore -> SfxAtomic SfxCheck :: ActorId -> ItemId -> CStore -> SfxAtomic SfxTrigger :: ActorId -> Point -> SfxAtomic SfxShun :: ActorId -> Point -> SfxAtomic SfxEffect :: FactionId -> ActorId -> Effect -> Int64 -> SfxAtomic SfxMsgFid :: FactionId -> SfxMsg -> SfxAtomic data SfxMsg SfxUnexpected :: ReqFailure -> SfxMsg SfxLoudUpd :: Bool -> UpdAtomic -> SfxMsg SfxLoudStrike :: Bool -> (Id ItemKind) -> Int -> SfxMsg SfxLoudSummon :: Bool -> (GroupName ItemKind) -> Dice -> SfxMsg SfxFizzles :: SfxMsg SfxNothingHappens :: SfxMsg SfxVoidDetection :: SfxMsg SfxSummonLackCalm :: ActorId -> SfxMsg SfxLevelNoMore :: SfxMsg SfxLevelPushed :: SfxMsg SfxBracedImmune :: ActorId -> SfxMsg SfxEscapeImpossible :: SfxMsg SfxTransImpossible :: SfxMsg SfxIdentifyNothing :: CStore -> SfxMsg SfxPurposeNothing :: CStore -> SfxMsg SfxPurposeTooFew :: Int -> Int -> SfxMsg SfxPurposeUnique :: SfxMsg SfxColdFish :: SfxMsg SfxTimerExtended :: ActorId -> ItemId -> CStore -> SfxMsg -- | The type representing visibility of atomic commands to factions, based -- on the position of the command, etc. Note that the server sees and -- smells all positions. data PosAtomic -- | whomever sees all the positions, notices PosSight :: LevelId -> [Point] -> PosAtomic -- | observers and the faction notice PosFidAndSight :: [FactionId] -> LevelId -> [Point] -> PosAtomic -- | whomever smells all the positions, notices PosSmell :: LevelId -> [Point] -> PosAtomic -- | only the faction notices PosFid :: FactionId -> PosAtomic -- | faction and server notices PosFidAndSer :: (Maybe LevelId) -> FactionId -> PosAtomic -- | only the server notices PosSer :: PosAtomic -- | everybody notices PosAll :: PosAtomic -- | never broadcasted, but sent manually PosNone :: PosAtomic -- | Produce the positions where the atomic update takes place. -- -- The goal of the mechanics is to ensure the commands don't carry -- significantly more information than their corresponding state diffs -- would. In other words, the atomic commands involving the positions -- seen by a client should convey similar information as the client would -- get by directly observing the changes the commands enact on the -- visible portion of server game state. The client is then free to -- change its copy of game state accordingly or not --- it only partially -- reflects reality anyway. -- -- E.g., UpdDisplaceActor in a black room, with one actor -- carrying a 0-radius light would not be distinguishable by looking at -- the state (or the screen) from UpdMoveActor of the -- illuminated actor, hence such UpdDisplaceActor should not be -- observable, but UpdMoveActor should be (or the former should -- be perceived as the latter). However, to simplify, we assign as strict -- visibility requirements to UpdMoveActor as to -- UpdDisplaceActor and fall back to UpdSpotActor -- (which provides minimal information that does not contradict state) if -- the visibility is lower. posUpdAtomic :: MonadStateRead m => UpdAtomic -> m PosAtomic -- | Produce the positions where the atomic special effect takes place. posSfxAtomic :: MonadStateRead m => SfxAtomic -> m PosAtomic -- | Decompose an atomic action. The decomposed actions give reduced -- information that still modifies client's state to match the server -- state wrt the current FOV and the subset of posUpdAtomic that -- is visible. The original actions give more information not only due to -- spanning potentially more positions than those visible. E.g., -- UpdMoveActor informs about the continued existence of the -- actor between moves, v.s., popping out of existence and then back in. breakUpdAtomic :: MonadStateRead m => UpdAtomic -> m [UpdAtomic] -- | Given the client, it's perception and an atomic command, determine if -- the client notices the command. seenAtomicCli :: Bool -> FactionId -> Perception -> PosAtomic -> Bool seenAtomicSer :: PosAtomic -> Bool -- | Generate the atomic updates that jointly perform a given item move. generalMoveItem :: MonadStateRead m => Bool -> ItemId -> Int -> Container -> Container -> m [UpdAtomic] posProjBody :: Actor -> PosAtomic class MonadStateRead m => MonadStateWrite m modifyState :: MonadStateWrite m => (State -> State) -> m () -- | The game-state semantics of atomic game commands. Special effects -- (SfxAtomic) don't modify state. handleUpdAtomic :: MonadStateWrite m => UpdAtomic -> m () -- | Abstract syntax of client commands. See -- https://github.com/LambdaHack/LambdaHack/wiki/Client-server-architecture. module Game.LambdaHack.Common.Response -- | Abstract syntax of client commands for both AI and UI clients. data Response RespUpdAtomic :: UpdAtomic -> Response RespQueryAI :: ActorId -> Response RespSfxAtomic :: SfxAtomic -> Response RespQueryUI :: Response type CliSerQueue = MVar -- | Connection channel between the server and a single client. data ChanServer ChanServer :: CliSerQueue Response -> CliSerQueue RequestAI -> Maybe (CliSerQueue RequestUI) -> ChanServer [responseS] :: ChanServer -> CliSerQueue Response [requestAIS] :: ChanServer -> CliSerQueue RequestAI [requestUIS] :: ChanServer -> Maybe (CliSerQueue RequestUI) instance GHC.Show.Show Game.LambdaHack.Common.Response.Response -- | Server and client game state types and operations. module Game.LambdaHack.Client.State -- | Client state, belonging to a single faction. Some of the data, e.g, -- the history, carries over from game to game, even across playing -- sessions. -- -- When many actors want to fling at the same target, they set their -- personal targets to follow the common xhair. When each wants to kill a -- fleeing enemy they recently meleed, they keep the enemies as their -- personal targets. -- -- Data invariant: if _sleader is Nothing then so is -- srunning. data StateClient StateClient :: Int -> EnumMap ActorId TgtAndPath -> EnumSet LevelId -> EnumMap ActorId BfsAndPath -> [CmdAtomic] -> DiscoveryKind -> DiscoveryAspect -> DiscoveryBenefit -> ActorAspect -> PerLid -> AlterLid -> StdGen -> Maybe ActorId -> FactionId -> Bool -> Challenge -> Challenge -> Int -> Int -> EnumMap LevelId (Maybe Bool) -> EnumMap (Id ModeKind) (Map Challenge Int) -> DebugModeCli -> StateClient -- | a parameter of the aiming digital line [seps] :: StateClient -> Int -- | targets of our actors in the dungeon [stargetD] :: StateClient -> EnumMap ActorId TgtAndPath -- | the set of fully explored levels [sexplored] :: StateClient -> EnumSet LevelId -- | pathfinding distances for our actors and paths to their targets, if -- any [sbfsD] :: StateClient -> EnumMap ActorId BfsAndPath -- | atomic commands performed to date [sundo] :: StateClient -> [CmdAtomic] -- | remembered item discoveries [sdiscoKind] :: StateClient -> DiscoveryKind -- | remembered aspects of items [sdiscoAspect] :: StateClient -> DiscoveryAspect -- | remembered AI benefits of items [sdiscoBenefit] :: StateClient -> DiscoveryBenefit -- | best known actor aspect data [sactorAspect] :: StateClient -> ActorAspect -- | faction perception indexed by levels [sfper] :: StateClient -> PerLid -- | cached alter ability data for positions [salter] :: StateClient -> AlterLid -- | current random generator [srandom] :: StateClient -> StdGen -- | candidate new leader of the faction; Faction._gleader is the old -- leader [_sleader] :: StateClient -> Maybe ActorId -- | faction controlled by the client [_sside] :: StateClient -> FactionId -- | exit the game loop [squit] :: StateClient -> Bool -- | current game challenge setup [scurChal] :: StateClient -> Challenge -- | next game challenge setup [snxtChal] :: StateClient -> Challenge -- | next game scenario number [snxtScenario] :: StateClient -> Int -- | mark suspect features [smarkSuspect] :: StateClient -> Int -- | condInMelee value, unless invalidated [scondInMelee] :: StateClient -> EnumMap LevelId (Maybe Bool) -- | won games at particular difficulty levels [svictories] :: StateClient -> EnumMap (Id ModeKind) (Map Challenge Int) -- | client debugging mode [sdebugCli] :: StateClient -> DebugModeCli -- | Initial empty game client state. emptyStateClient :: FactionId -> StateClient type AlterLid = EnumMap LevelId (Array Word8) -- | Update target parameters within client state. updateTarget :: ActorId -> (Maybe Target -> Maybe Target) -> StateClient -> StateClient -- | Get target parameters from client state. getTarget :: ActorId -> StateClient -> Maybe Target -- | Update picked leader within state. Verify actor's faction. updateLeader :: ActorId -> State -> StateClient -> StateClient sside :: StateClient -> FactionId data BfsAndPath BfsInvalid :: BfsAndPath BfsAndPath :: Array BfsDistance -> EnumMap Point AndPath -> BfsAndPath [bfsArr] :: BfsAndPath -> Array BfsDistance [bfsPath] :: BfsAndPath -> EnumMap Point AndPath data TgtAndPath TgtAndPath :: Target -> AndPath -> TgtAndPath [tapTgt] :: TgtAndPath -> Target [tapPath] :: TgtAndPath -> AndPath cycleMarkSuspect :: StateClient -> StateClient instance GHC.Show.Show Game.LambdaHack.Client.State.StateClient instance GHC.Generics.Generic Game.LambdaHack.Client.State.TgtAndPath instance GHC.Show.Show Game.LambdaHack.Client.State.TgtAndPath instance GHC.Show.Show Game.LambdaHack.Client.State.BfsAndPath instance Data.Binary.Class.Binary Game.LambdaHack.Client.State.StateClient instance Data.Binary.Class.Binary Game.LambdaHack.Client.State.TgtAndPath -- | Basic client monad and related operations. module Game.LambdaHack.Client.MonadClient class MonadStateRead m => MonadClient m getsClient :: MonadClient m => (StateClient -> a) -> m a modifyClient :: MonadClient m => (StateClient -> StateClient) -> m () liftIO :: MonadClient m => IO a -> m a class MonadClient m => MonadClientSetup m saveClient :: MonadClientSetup m => m () restartClient :: MonadClientSetup m => m () getClient :: MonadClient m => m StateClient putClient :: MonadClient m => StateClient -> m () debugPossiblyPrint :: MonadClient m => Text -> m () -- | Invoke pseudo-random computation with the generator kept in the state. rndToAction :: MonadClient m => Rnd a -> m a -- | Invoke pseudo-random computation, don't change generator kept in -- state. rndToActionForget :: MonadClient m => Rnd a -> m a -- | Common client monad operations. module Game.LambdaHack.Client.CommonM -- | Get the current perception of a client. getPerFid :: MonadClient m => LevelId -> m Perception -- | Calculate the position of an actor's target. aidTgtToPos :: MonadClient m => ActorId -> LevelId -> Target -> m (Maybe Point) -- | Counts the number of steps until the projectile would hit an actor or -- obstacle. Starts searching with the given eps and returns the first -- found eps for which the number reaches the distance between actor and -- target position, or Nothing if none can be found. makeLine :: MonadClient m => Bool -> Actor -> Point -> Int -> m (Maybe Int) maxActorSkillsClient :: MonadClient m => ActorId -> m Skills currentSkillsClient :: MonadClient m => ActorId -> m Skills fullAssocsClient :: MonadClient m => ActorId -> [CStore] -> m [(ItemId, ItemFull)] itemToFullClient :: MonadClient m => m (ItemId -> ItemQuant -> ItemFull) pickWeaponClient :: MonadClient m => ActorId -> ActorId -> m (Maybe (RequestTimed 'AbMelee)) updateSalter :: MonadClient m => LevelId -> [(Point, Id TileKind)] -> m () createSalter :: State -> AlterLid aspectRecordFromItemClient :: MonadClient m => ItemId -> Item -> m AspectRecord aspectRecordFromActorClient :: MonadClient m => Actor -> [(ItemId, Item)] -> m AspectRecord createSactorAspect :: MonadClient m => State -> m ActorAspect -- | Breadth first search and realted algorithms using the client monad. module Game.LambdaHack.Client.BfsM invalidateBfsAid :: MonadClient m => ActorId -> m () invalidateBfsLid :: MonadClient m => LevelId -> m () invalidateBfsAll :: MonadClient m => m () createBfs :: MonadClient m => Bool -> Word8 -> ActorId -> m (Array BfsDistance) condBFS :: MonadClient m => ActorId -> m (Bool, Word8) -- | Get cached BFS array and path or, if not stored, generate and store -- first. getCacheBfsAndPath :: forall m. MonadClient m => ActorId -> Point -> m (Array BfsDistance, AndPath) -- | Get cached BFS array or, if not stored, generate and store first. getCacheBfs :: MonadClient m => ActorId -> m (Array BfsDistance) -- | Get cached BFS path or, if not stored, generate and store first. getCachePath :: MonadClient m => ActorId -> Point -> m AndPath createPath :: MonadClient m => ActorId -> Target -> m TgtAndPath unexploredDepth :: MonadClient m => Bool -> LevelId -> m Bool -- | Closest reachable unknown tile position, if any. -- -- Note: some of these tiles are behind suspect tiles and they are chosen -- in preference to more distant directly accessible unknown tiles. This -- is in principle OK, but in dungeons with few hidden doors AI is at a -- disadvantage (and with many hidden doors, it fares as well as a human -- that deduced the dungeon properties). Changing Bfs to accomodate all -- dungeon styles would be complex and would slow down the engine. -- -- If the level has inaccessible open areas (at least from the stairs AI -- used) the level will be nevertheless here finally marked explored, to -- enable transition to other levels. We should generally avoid such -- levels, because digging and/or trying to find other stairs leading to -- disconnected areas is not KISS so we don't do this in AI, so AI is at -- a disadvantage. closestUnknown :: MonadClient m => ActorId -> m (Maybe Point) -- | Finds smells closest to the actor, except under the actor, because -- actors consume smell only moving over them, not standing. Of the -- closest, prefers the newest smell. closestSmell :: MonadClient m => ActorId -> m [(Int, (Point, Time))] -- | Furthest (wrt paths) known position. furthestKnown :: MonadClient m => ActorId -> m Point data FleeViaStairsOrEscape ViaStairs :: FleeViaStairsOrEscape ViaStairsUp :: FleeViaStairsOrEscape ViaStairsDown :: FleeViaStairsOrEscape ViaEscape :: FleeViaStairsOrEscape ViaNothing :: FleeViaStairsOrEscape ViaAnything :: FleeViaStairsOrEscape embedBenefit :: MonadClient m => FleeViaStairsOrEscape -> ActorId -> [(Point, ItemBag)] -> m [(Int, (Point, ItemBag))] -- | Closest (wrt paths) AI-triggerable tiles with embedded items. In AI, -- the level the actor is on is either explored or the actor already has -- a weapon equipped, so no need to explore further, he tries to find -- enemies on other levels, but before that, he triggers other tiles in -- hope of some loot or beneficial effect to enter next level with. closestTriggers :: MonadClient m => FleeViaStairsOrEscape -> ActorId -> m [(Int, (Point, (Point, ItemBag)))] -- | Closest (wrt paths) items. closestItems :: MonadClient m => ActorId -> m [(Int, (Point, ItemBag))] -- | Closest (wrt paths) enemy actors. closestFoes :: MonadClient m => [(ActorId, Actor)] -> ActorId -> m [(Int, (ActorId, Actor))] -- | Check whether the actor has enough gear to go look for enemies. We -- assume weapons in equipment are better than any among organs or at -- least provide some essential diversity. Disabled if, due to tactic, -- actors follow leader and so would repeatedly move towards and away -- form stairs at leader change, depending on current leader's gear. -- Number of items of a single kind is ignored, because variety is -- needed. condEnoughGearM :: MonadClient m => ActorId -> m Bool updatePathFromBfs :: MonadClient m => Bool -> BfsAndPath -> ActorId -> Point -> m (Array BfsDistance, AndPath) instance GHC.Classes.Eq Game.LambdaHack.Client.BfsM.FleeViaStairsOrEscape instance GHC.Show.Show Game.LambdaHack.Client.BfsM.FleeViaStairsOrEscape -- | Semantics of abilities in terms of actions and the AI procedure for -- picking the best action for an actor. module Game.LambdaHack.Client.AI.ConditionM -- | Require that the target enemy is visible by the party. condAimEnemyPresentM :: MonadClient m => ActorId -> m Bool -- | Require that the target enemy is remembered on the actor's level. condAimEnemyRememberedM :: MonadClient m => ActorId -> m Bool -- | Check if the target is nonmoving. condTgtNonmovingM :: MonadClient m => ActorId -> m Bool -- | Require that any non-dying foe is adjacent, except projectiles that -- (possibly) explode upon contact. condAnyFoeAdjM :: MonadStateRead m => ActorId -> m Bool -- | Require the actor stands adjacent to a triggerable tile (e.g., -- stairs). condAdjTriggerableM :: MonadStateRead m => ActorId -> m Bool -- | Require the actor blocks the paths of any of his party members. condBlocksFriendsM :: MonadClient m => ActorId -> m Bool -- | Require the actor stands over a weapon that would be auto-equipped. condFloorWeaponM :: MonadClient m => ActorId -> m Bool -- | Check whether the actor has no weapon in equipment. condNoEqpWeaponM :: MonadClient m => ActorId -> m Bool -- | Require that the actor can project any items. condCanProjectM :: MonadClient m => Int -> ActorId -> m Bool condProjectListM :: MonadClient m => Int -> ActorId -> m [(Maybe Benefit, CStore, ItemId, ItemFull)] -- | Require that the actor stands over a desirable item. condDesirableFloorItemM :: MonadClient m => ActorId -> m Bool condSupport :: MonadClient m => Int -> ActorId -> m Bool -- | Produce the list of items with a given property available to the actor -- and the items' values. benAvailableItems :: MonadClient m => ActorId -> [CStore] -> m [(Maybe Benefit, CStore, ItemId, ItemFull)] hinders :: Bool -> Bool -> Bool -> Bool -> Actor -> AspectRecord -> ItemFull -> Bool -- | Produce the list of items on the ground beneath the actor that are -- worth picking up. benGroundItems :: MonadClient m => ActorId -> m [(Maybe Benefit, CStore, ItemId, ItemFull)] desirableItem :: Bool -> Maybe Int -> Item -> Bool -- | Produce the chess-distance-sorted list of non-low-HP, melee-cabable -- foes on the level. We don't consider path-distance, because we are -- interested in how soon the foe can close in to hit us, which can -- diverge greately from path distance for short distances, e.g., when -- terrain gets revealed. We don't consider non-moving actors, because -- they can't chase us and also because they can't be aggresive so to -- resolve the stalemate, the opposing AI has to be aggresive by ignoring -- them and then when melee is started, it's usually too late to retreat. meleeThreatDistList :: MonadClient m => ActorId -> m [(Int, (ActorId, Actor))] -- | Require that the actor stands in the dark and so would be betrayed by -- his own equipped light, condShineWouldBetrayM :: MonadClient m => ActorId -> m Bool -- | Produce a list of acceptable adjacent points to flee to. fleeList :: MonadClient m => ActorId -> m ([(Int, Point)], [(Int, Point)]) -- | Let AI pick the best target for an actor. module Game.LambdaHack.Client.AI.PickTargetM -- | Verify and possibly change the target of an actor. This function both -- updates the target in the client state and returns the new target -- explicitly. refreshTarget :: MonadClient m => (ActorId, Actor) -> m (Maybe TgtAndPath) -- | AI proposes possible targets for the actor. Never empty. targetStrategy :: forall m. MonadClient m => ActorId -> m (Strategy TgtAndPath) -- | Semantics of most ResponseAI client commands. module Game.LambdaHack.Client.AI.PickActorM pickActorToMove :: MonadClient m => Maybe ActorId -> m ActorId useTactics :: MonadClient m => ActorId -> m () -- | Semantics of abilities in terms of actions and the AI procedure for -- picking the best action for an actor. module Game.LambdaHack.Client.AI.HandleAbilityM -- | AI strategy based on actor's sight, smell, etc. Never empty. actionStrategy :: forall m. MonadClient m => ActorId -> Bool -> m (Strategy RequestAnyAbility) data ApplyItemGroup -- | A strategy to always just wait. waitBlockNow :: MonadClient m => m (Strategy (RequestTimed 'AbWait)) pickup :: MonadClient m => ActorId -> Bool -> m (Strategy (RequestTimed 'AbMoveItem)) equipItems :: MonadClient m => ActorId -> m (Strategy (RequestTimed 'AbMoveItem)) toShare :: EqpSlot -> Bool yieldUnneeded :: MonadClient m => ActorId -> m (Strategy (RequestTimed 'AbMoveItem)) unEquipItems :: MonadClient m => ActorId -> m (Strategy (RequestTimed 'AbMoveItem)) groupByEqpSlot :: [(ItemId, ItemFull)] -> EnumMap EqpSlot [(ItemId, ItemFull)] bestByEqpSlot :: DiscoveryBenefit -> [(ItemId, ItemFull)] -> [(ItemId, ItemFull)] -> [(ItemId, ItemFull)] -> [(EqpSlot, ([(Int, (ItemId, ItemFull))], [(Int, (ItemId, ItemFull))], [(Int, (ItemId, ItemFull))]))] harmful :: DiscoveryBenefit -> ItemId -> Bool meleeBlocker :: MonadClient m => ActorId -> m (Strategy (RequestTimed 'AbMelee)) meleeAny :: MonadClient m => ActorId -> m (Strategy (RequestTimed 'AbMelee)) -- | The level the actor is on is either explored or the actor already has -- a weapon equipped, so no need to explore further, he tries to find -- enemies on other levels. We don't verify any embedded item is targeted -- by the actor, but at least the actor doesn't target a visible enemy at -- this point. trigger :: MonadClient m => ActorId -> FleeViaStairsOrEscape -> m (Strategy (RequestTimed 'AbAlter)) projectItem :: MonadClient m => ActorId -> m (Strategy (RequestTimed 'AbProject)) applyItem :: MonadClient m => ActorId -> ApplyItemGroup -> m (Strategy (RequestTimed 'AbApply)) flee :: MonadClient m => ActorId -> [(Int, Point)] -> m (Strategy RequestAnyAbility) displaceFoe :: MonadClient m => ActorId -> m (Strategy RequestAnyAbility) displaceBlocker :: MonadClient m => ActorId -> Bool -> m (Strategy RequestAnyAbility) displaceTowards :: MonadClient m => ActorId -> Point -> Bool -> m (Strategy Vector) chase :: MonadClient m => ActorId -> Bool -> Bool -> m (Strategy RequestAnyAbility) moveTowards :: MonadClient m => ActorId -> Point -> Point -> Bool -> m (Strategy Vector) -- | Actor moves or searches or alters or attacks. This function is very -- general, even though it's often used in contexts when only one or two -- of the many cases can possibly occur. moveOrRunAid :: MonadClient m => ActorId -> Vector -> m (Maybe RequestAnyAbility) instance GHC.Classes.Eq Game.LambdaHack.Client.AI.HandleAbilityM.ApplyItemGroup -- | Ways for the client to use AI to produce server requests, based on the -- client's view of the game state. module Game.LambdaHack.Client.AI -- | Handle the move of an actor under AI control (of UI or AI player). queryAI :: MonadClient m => ActorId -> m RequestAI pickAI :: MonadClient m => Maybe (ActorId, RequestAnyAbility) -> ActorId -> m (ActorId, RequestAnyAbility) -- | Pick an action the actor will perform this turn. pickAction :: MonadClient m => ActorId -> Bool -> m RequestAnyAbility udpdateCondInMelee :: MonadClient m => ActorId -> m () -- | Check if any non-dying foe (projectile or not) is adjacent to any of -- our normal actors (whether they can melee or just need to flee, in -- which case alert is needed so that they are not slowed down by -- others). condInMeleeM :: MonadClient m => Actor -> m Bool -- | Handle atomic commands received by the client. module Game.LambdaHack.Client.HandleAtomicM -- | Effect of atomic actions on client state is calculated with the global -- state from before the command is executed. cmdAtomicSemCli :: MonadClientSetup m => UpdAtomic -> m () -- | Clients keep a subset of atomic commands sent by the server and add -- some of their own. The result of this function is the list of commands -- kept for each command received. cmdAtomicFilterCli :: MonadClient m => UpdAtomic -> m [UpdAtomic] -- | Rectangular areas of levels and their basic operations. module Game.LambdaHack.Server.DungeonGen.Area -- | The type of areas. The bottom left and the top right points. data Area -- | Checks if it's an area with at least one field. toArea :: (X, Y, X, Y) -> Maybe Area fromArea :: Area -> (X, Y, X, Y) trivialArea :: Point -> Area isTrivialArea :: Area -> Bool -- | Divide uniformly a larger area into the given number of smaller areas -- overlapping at the edges. -- -- When a list of fixed centers (some important points inside) of -- (non-overlapping) areas is given, incorporate those, with as little -- disruption, as possible. grid :: EnumMap Point (GroupName PlaceKind) -> [Point] -> (X, Y) -> Area -> ((X, Y), EnumMap Point SpecialArea) -- | Shrink the given area on all fours sides by the amount. shrink :: Area -> Maybe Area expand :: Area -> Area sumAreas :: Area -> Area -> Area data SpecialArea SpecialArea :: Area -> SpecialArea SpecialFixed :: Point -> (GroupName PlaceKind) -> Area -> SpecialArea SpecialMerged :: SpecialArea -> Point -> SpecialArea instance GHC.Show.Show Game.LambdaHack.Server.DungeonGen.Area.SpecialArea instance GHC.Classes.Eq Game.LambdaHack.Server.DungeonGen.Area.Area instance GHC.Show.Show Game.LambdaHack.Server.DungeonGen.Area.Area instance Data.Binary.Class.Binary Game.LambdaHack.Server.DungeonGen.Area.Area -- | Operations on the Area type that involve random numbers. module Game.LambdaHack.Server.DungeonGen.AreaRnd -- | Pick a random point within an area. xyInArea :: Area -> Rnd Point -- | Create a void room, i.e., a single point area within the designated -- area. mkVoidRoom :: Area -> Rnd Area -- | Create a random room according to given parameters. mkRoom :: (X, Y) -> (X, Y) -> Area -> Rnd Area mkFixed :: (X, Y) -> Area -> Point -> Area -- | Pick a subset of connections between adjacent areas within a grid -- until there is only one connected component in the graph of all areas. connectGrid :: EnumSet Point -> (X, Y) -> Rnd [(Point, Point)] -- | Pick a single random connection between adjacent areas within a grid. randomConnection :: (X, Y) -> Rnd (Point, Point) -- | The choice of horizontal and vertical orientation. data HV Horiz :: HV Vert :: HV -- | The coordinates of consecutive fields of a corridor. type Corridor = [Point] -- | Try to connect two interiors of places with a corridor. Choose -- entrances some steps away from the edges, if the place is big enough. -- Note that with pfence == FNone, the inner area considered is -- the strict interior of the place, without the outermost tiles. -- -- The corridor connects (touches) the inner areas and the turning point -- of the corridor (if any) is outside of the outer areas and inside the -- grid areas. connectPlaces :: (Area, Fence, Area) -> (Area, Fence, Area) -> Rnd (Maybe Corridor) instance GHC.Classes.Eq Game.LambdaHack.Server.DungeonGen.AreaRnd.HV -- | Generation of places from place kinds. module Game.LambdaHack.Server.DungeonGen.Place -- | The map of tile kinds in a place (and generally anywhere in a cave). -- The map is sparse. The default tile that eventually fills the empty -- spaces is specified in the cave kind specification with -- cdefTile. type TileMapEM = EnumMap Point (Id TileKind) -- | The parameters of a place. All are immutable and set at the time when -- a place is generated. data Place Place :: Id PlaceKind -> Area -> Bool -> GroupName TileKind -> Id TileKind -> Id TileKind -> Id TileKind -> Place [qkind] :: Place -> Id PlaceKind [qarea] :: Place -> Area [qseen] :: Place -> Bool [qlegend] :: Place -> GroupName TileKind [qFWall] :: Place -> Id TileKind [qFFloor] :: Place -> Id TileKind [qFGround] :: Place -> Id TileKind isChancePos :: Int -> Int -> Point -> Bool -- | For CAlternate tiling, require the place be comprised of an -- even number of whole corners, with exactly one square overlap between -- consecutive coners and no trimming. For other tiling methods, check -- that the area is large enough for tiling the corner twice in each -- direction, with a possible one row/column overlap. placeCheck :: Area -> PlaceKind -> Bool -- | Construct a fence around an area, with the given tile group. buildFenceRnd :: COps -> GroupName TileKind -> Area -> Rnd TileMapEM -- | Given a few parameters, roll and construct a Place -- datastructure and fill a cave section acccording to it. buildPlace :: COps -> CaveKind -> Bool -> Id TileKind -> Id TileKind -> AbsDepth -> AbsDepth -> Int -> Area -> Maybe (GroupName PlaceKind) -> Rnd (TileMapEM, Place) instance GHC.Show.Show Game.LambdaHack.Server.DungeonGen.Place.Place instance Data.Binary.Class.Binary Game.LambdaHack.Server.DungeonGen.Place.Place -- | Generation of caves (not yet inhabited dungeon levels) from cave -- kinds. module Game.LambdaHack.Server.DungeonGen.Cave -- | The type of caves (not yet inhabited dungeon levels). data Cave Cave :: Id CaveKind -> Int -> TileMapEM -> [Place] -> Bool -> Cave -- | the kind of the cave [dkind] :: Cave -> Id CaveKind -- | secret tile seed [dsecret] :: Cave -> Int -- | tile kinds in the cave [dmap] :: Cave -> TileMapEM -- | places generated in the cave [dplaces] :: Cave -> [Place] -- | whether the cave is dark [dnight] :: Cave -> Bool bootFixedCenters :: CaveKind -> [Point] -- | Cave generation by an algorithm inspired by the original Rogue, buildCave :: COps -> AbsDepth -> AbsDepth -> Int -> Id CaveKind -> EnumMap Point (GroupName PlaceKind) -> Rnd Cave instance GHC.Show.Show Game.LambdaHack.Server.DungeonGen.Cave.Cave -- | The unpopulated dungeon generation routine. module Game.LambdaHack.Server.DungeonGen -- | Freshly generated and not yet populated dungeon. data FreshDungeon FreshDungeon :: Dungeon -> AbsDepth -> FreshDungeon -- | maps for all levels [freshDungeon] :: FreshDungeon -> Dungeon -- | absolute dungeon depth [freshTotalDepth] :: FreshDungeon -> AbsDepth -- | Generate the dungeon for a new game. dungeonGen :: COps -> Caves -> Rnd FreshDungeon convertTileMaps :: COps -> Bool -> Rnd (Id TileKind) -> Maybe (Rnd (Id TileKind)) -> Int -> Int -> TileMapEM -> Rnd TileMap -- | Places yet another staircase (or escape), taking into account only the -- already existing stairs. placeDownStairs :: CaveKind -> [Point] -> Rnd Point -- | Create a level from a cave. buildLevel :: COps -> Int -> GroupName CaveKind -> Int -> AbsDepth -> [Point] -> Rnd (Level, [Point]) -- | Build rudimentary level from a cave kind. levelFromCaveKind :: COps -> CaveKind -> AbsDepth -> TileMap -> ([Point], [Point]) -> Int -> [Point] -> Bool -> Level -- | DFOV (Digital Field of View) implemented according to specification at -- http://roguebasin.roguelikedevelopment.org/index.php?title=Digital_field_of_view_implementation. -- This fast version of the algorithm, based on PFOV, has AFAIK -- never been described nor implemented before. module Game.LambdaHack.Server.FovDigital -- | Calculates the list of tiles, in Bump coordinates, visible -- from (0, 0), within the given sight range. scan :: EnumSet Point -> Distance -> Array Bool -> (Bump -> Point) -> EnumSet Point -- | Rotated and translated coordinates of 2D points, so that the points -- fit in a single quadrant area (e, g., quadrant I for Permissive FOV, -- hence both coordinates positive; adjacent diagonal halves of quadrant -- I and II for Digital FOV, hence y positive). The special coordinates -- are written using the standard mathematical coordinate setup, where -- quadrant I, with x and y positive, is on the upper right. data Bump B :: Int -> Int -> Bump [bx] :: Bump -> Int [by] :: Bump -> Int -- | Distance from the (0, 0) point where FOV originates. type Distance = Int -- | Progress along an arc with a constant distance from (0, 0). type Progress = Int -- | Straight line between points. data Line Line :: Bump -> Bump -> Line -- | Convex hull represented as a list of points. type ConvexHull = [Bump] -- | An edge (comprising of a line and a convex hull) of the area to be -- scanned. type Edge = (Line, ConvexHull) -- | The area left to be scanned, delimited by edges. type EdgeInterval = (Edge, Edge) -- | Check if the line from the second point to the first is more steep -- than the line from the third point to the first. This is related to -- the formal notion of gradient (or angle), but hacked wrt signs to work -- fast in this particular setup. Returns True for ill-defined lines. steeper :: Bump -> Bump -> Bump -> Ordering -- | Extends a convex hull of bumps with a new bump. Nothing needs to be -- done if the new bump already lies within the hull. The first argument -- is typically steeper, optionally negated, applied to the second -- argument. addHull :: (Bump -> Bump -> Ordering) -> Bump -> ConvexHull -> ConvexHull -- | Create a line from two points. Debug: check if well-defined. dline :: Bump -> Bump -> Line -- | Compare steepness of (p1, f) and (p2, f). Debug: -- Verify that the results of 2 independent checks are equal. dsteeper :: Bump -> Bump -> Bump -> Ordering -- | The X coordinate, represented as a fraction, of the intersection of a -- given line and the line of diagonals of diamonds at distance -- d from (0, 0). intersect :: Line -> Distance -> (Int, Int) -- | Debug functions for DFOV: -- -- Debug: calculate steeper for DFOV in another way and compare results. _debugSteeper :: Bump -> Bump -> Bump -> Ordering -- | Debug: check if a view border line for DFOV is legal. _debugLine :: Line -> (Bool, String) instance GHC.Show.Show Game.LambdaHack.Server.FovDigital.Line instance GHC.Show.Show Game.LambdaHack.Server.FovDigital.Bump -- | Field Of View scanning with a variety of algorithms. See -- https://github.com/LambdaHack/LambdaHack/wiki/Fov-and-los for -- discussion. module Game.LambdaHack.Server.Fov data FovValid a FovValid :: a -> FovValid a FovInvalid :: FovValid a -- | Main perception validity map, for all factions. type PerValidFid = EnumMap FactionId (EnumMap LevelId Bool) -- | Visually reachable positions (light passes through them to the actor). -- They need to be intersected with lucid positions to obtain visible -- positions. newtype PerReachable PerReachable :: EnumSet Point -> PerReachable [preachable] :: PerReachable -> EnumSet Point data CacheBeforeLucid CacheBeforeLucid :: PerReachable -> PerVisible -> PerSmelled -> CacheBeforeLucid [creachable] :: CacheBeforeLucid -> PerReachable [cnocto] :: CacheBeforeLucid -> PerVisible [csmell] :: CacheBeforeLucid -> PerSmelled type PerActor = EnumMap ActorId (FovValid CacheBeforeLucid) data PerceptionCache PerceptionCache :: FovValid CacheBeforeLucid -> PerActor -> PerceptionCache [ptotal] :: PerceptionCache -> FovValid CacheBeforeLucid [perActor] :: PerceptionCache -> PerActor -- | Server cache of perceptions of a single faction, indexed by level -- identifier. type PerCacheLid = EnumMap LevelId PerceptionCache -- | Server cache of perceptions, indexed by faction identifier. type PerCacheFid = EnumMap FactionId PerCacheLid -- | Map from level positions that currently hold item or actor(s) with -- shine to the maximum of radiuses of the shining lights. -- -- Note: ActorAspect and FovShine shoudn't be in -- State, because on client they need to be updated every time -- an item discovery is made, unlike on the server, where it's much -- simpler and cheaper. BTW, floor and (many projectile) actors light on -- a single tile should be additive for FovShine to be -- incrementally updated. -- -- FovShine should not even be kept in StateServer, -- because it's cheap to compute, compared to FovLucid and -- invalidated almost as often (not invalidated only by -- UpdAlterTile). newtype FovShine FovShine :: EnumMap Point Int -> FovShine [fovShine] :: FovShine -> EnumMap Point Int -- | Level positions with either ambient light or shining items or actors. newtype FovLucid FovLucid :: EnumSet Point -> FovLucid [fovLucid] :: FovLucid -> EnumSet Point type FovLucidLid = EnumMap LevelId (FovValid FovLucid) -- | Level positions that pass through light and vision. newtype FovClear FovClear :: Array Bool -> FovClear [fovClear] :: FovClear -> Array Bool type FovClearLid = EnumMap LevelId FovClear -- | Level positions with tiles that have ambient light. newtype FovLit FovLit :: EnumSet Point -> FovLit [fovLit] :: FovLit -> EnumSet Point type FovLitLid = EnumMap LevelId FovLit -- | Compute positions visible (reachable and seen) by the party. A -- position is lucid, if it's lit by an ambient light or by a weak, -- portable light source, e.g,, carried by an actor. A reachable and -- lucid position is visible. Additionally, positions directly adjacent -- to an actor are assumed to be visible to him (through sound, touch, -- noctovision, whatever). perceptionFromPTotal :: FovLucid -> CacheBeforeLucid -> Perception perActorFromLevel :: PerActor -> (ActorId -> Actor) -> ActorAspect -> FovClear -> PerActor totalFromPerActor :: PerActor -> CacheBeforeLucid -- | Update lights on the level. This is needed every (even enemy) actor -- move to show thrown torches. We need to update lights even if cmd -- doesn't change any perception, so that for next cmd that does, but -- doesn't change lights, and operates on the same level, the lights are -- up to date. We could make lights lazy to ensure no computation is -- wasted, but it's rare that cmd changed them, but not the perception -- (e.g., earthquake in an uninhabited corner of the active arena, but -- the we'd probably want some feedback, at least sound). lucidFromLevel :: DiscoveryAspect -> ActorAspect -> FovClearLid -> FovLitLid -> State -> LevelId -> Level -> FovLucid -- | Calculate the perception and its caches for the whole dungeon. perFidInDungeon :: DiscoveryAspect -> State -> (ActorAspect, FovLitLid, FovClearLid, FovLucidLid, PerValidFid, PerCacheFid, PerFid) aspectRecordFromActorServer :: DiscoveryAspect -> Actor -> AspectRecord boundSightByCalm :: Int -> Int64 -> Int -- | Compute positions reachable by the actor. Reachable are all fields on -- a visually unblocked path from the actor position. Also compute -- positions seen by noctovision and perceived by smell. cacheBeforeLucidFromActor :: FovClear -> Actor -> AspectRecord -> CacheBeforeLucid perceptionCacheFromLevel :: ActorAspect -> FovClearLid -> FactionId -> LevelId -> State -> PerceptionCache -- | Calculate perception of a faction. perLidFromFaction :: ActorAspect -> FovLucidLid -> FovClearLid -> FactionId -> State -> (PerLid, PerCacheLid) clearFromLevel :: COps -> Level -> FovClear clearInDungeon :: State -> FovClearLid litFromLevel :: COps -> Level -> FovLit litInDungeon :: State -> FovLitLid shineFromLevel :: DiscoveryAspect -> ActorAspect -> State -> LevelId -> Level -> FovShine floorLightSources :: DiscoveryAspect -> Level -> [(Point, Int)] -- | Compute all dynamically lit positions on a level, whether lit by -- actors or shining floor items. Note that an actor can be blind, in -- which case he doesn't see his own light (but others, from his or other -- factions, possibly do). lucidFromItems :: FovClear -> [(Point, Int)] -> [FovLucid] lucidInDungeon :: DiscoveryAspect -> ActorAspect -> FovClearLid -> FovLitLid -> State -> FovLucidLid -- | Perform a full scan for a given position. Returns the positions that -- are currently in the field of view. The Field of View algorithm to use -- is passed in the second argument. The actor's own position is -- considred reachable by him. fullscan :: FovClear -> Int -> Point -> EnumSet Point instance GHC.Classes.Eq Game.LambdaHack.Server.Fov.FovLit instance GHC.Show.Show Game.LambdaHack.Server.Fov.FovLit instance GHC.Classes.Eq Game.LambdaHack.Server.Fov.FovClear instance GHC.Show.Show Game.LambdaHack.Server.Fov.FovClear instance GHC.Classes.Eq Game.LambdaHack.Server.Fov.FovLucid instance GHC.Show.Show Game.LambdaHack.Server.Fov.FovLucid instance GHC.Classes.Eq Game.LambdaHack.Server.Fov.FovShine instance GHC.Show.Show Game.LambdaHack.Server.Fov.FovShine instance GHC.Classes.Eq Game.LambdaHack.Server.Fov.PerceptionCache instance GHC.Show.Show Game.LambdaHack.Server.Fov.PerceptionCache instance GHC.Classes.Eq Game.LambdaHack.Server.Fov.CacheBeforeLucid instance GHC.Show.Show Game.LambdaHack.Server.Fov.CacheBeforeLucid instance GHC.Classes.Eq Game.LambdaHack.Server.Fov.PerReachable instance GHC.Show.Show Game.LambdaHack.Server.Fov.PerReachable instance GHC.Classes.Eq a => GHC.Classes.Eq (Game.LambdaHack.Server.Fov.FovValid a) instance GHC.Show.Show a => GHC.Show.Show (Game.LambdaHack.Server.Fov.FovValid a) -- | Server types and operations for items that don't involve server state -- nor our custom monads. module Game.LambdaHack.Server.ItemRev -- | The essential item properties, used for the ItemRev hash -- table from items to their ids, needed to assign ids to newly generated -- items. All the other meaningul properties can be derived from them. -- Note 1: jlid is not meaningful; it gets forgotten if items -- from different levels roll the same random properties and so are -- merged. However, the first item generated by the server wins, which is -- most of the time the lower jlid item, which makes sense for -- the client. Note 2: ItemSeed instead of AspectRecord -- is not enough, becaused different seeds may result in the same -- AspectRecord and we don't want such items to be distinct in -- UI and elsewhere. type ItemKnown = (ItemKindIx, AspectRecord, Dice, Maybe FactionId) -- | Reverse item map, for item creation, to keep items and item -- identifiers in bijection. type ItemRev = HashMap ItemKnown ItemId -- | Build an item with the given stats. buildItem :: FlavourMap -> DiscoveryKindRev -> Id ItemKind -> ItemKind -> LevelId -> Dice -> Item -- | Generate an item based on level. newItem :: COps -> FlavourMap -> DiscoveryKind -> DiscoveryKindRev -> UniqueSet -> Freqs ItemKind -> Int -> LevelId -> AbsDepth -> AbsDepth -> Rnd (Maybe (ItemKnown, ItemFull, ItemDisco, ItemSeed, GroupName ItemKind)) type UniqueSet = EnumSet (Id ItemKind) -- | The reverse map to DiscoveryKind, needed for item creation. type DiscoveryKindRev = EnumMap (Id ItemKind) ItemKindIx serverDiscos :: COps -> Rnd (DiscoveryKind, DiscoveryKindRev) -- | The map of item ids to item seeds, needed for item creation. type ItemSeedDict = EnumMap ItemId ItemSeed -- | Flavours assigned by the server to item kinds, in this particular -- game. data FlavourMap emptyFlavourMap :: FlavourMap -- | Randomly chooses flavour for all item kinds for this game. dungeonFlavourMap :: COps -> Rnd FlavourMap instance Data.Binary.Class.Binary Game.LambdaHack.Server.ItemRev.FlavourMap instance GHC.Show.Show Game.LambdaHack.Server.ItemRev.FlavourMap -- | Server and client game state types and operations. module Game.LambdaHack.Server.State -- | Global, server state. data StateServer StateServer :: ActorTime -> DiscoveryKind -> DiscoveryKindRev -> UniqueSet -> DiscoveryAspect -> ItemSeedDict -> ItemRev -> FlavourMap -> ActorId -> ItemId -> EnumMap LevelId Int -> [CmdAtomic] -> PerFid -> PerValidFid -> PerCacheFid -> ActorAspect -> FovLucidLid -> FovClearLid -> FovLitLid -> [LevelId] -> Bool -> StdGen -> RNGs -> Bool -> Bool -> DebugModeSer -> DebugModeSer -> StateServer -- | absolute times of next actions [sactorTime] :: StateServer -> ActorTime -- | full item kind discoveries data [sdiscoKind] :: StateServer -> DiscoveryKind -- | reverse map, used for item creation [sdiscoKindRev] :: StateServer -> DiscoveryKindRev -- | already generated unique items [suniqueSet] :: StateServer -> UniqueSet -- | full item aspect data [sdiscoAspect] :: StateServer -> DiscoveryAspect -- | map from item ids to item seeds [sitemSeedD] :: StateServer -> ItemSeedDict -- | reverse id map, used for item creation [sitemRev] :: StateServer -> ItemRev -- | association of flavour to items [sflavour] :: StateServer -> FlavourMap -- | stores next actor index [sacounter] :: StateServer -> ActorId -- | stores next item index [sicounter] :: StateServer -> ItemId [snumSpawned] :: StateServer -> EnumMap LevelId Int -- | atomic commands performed to date [sundo] :: StateServer -> [CmdAtomic] -- | perception of all factions [sperFid] :: StateServer -> PerFid -- | perception validity for all factions [sperValidFid] :: StateServer -> PerValidFid -- | perception cache of all factions [sperCacheFid] :: StateServer -> PerCacheFid -- | full actor aspect data [sactorAspect] :: StateServer -> ActorAspect -- | ambient or shining light positions [sfovLucidLid] :: StateServer -> FovLucidLid -- | clear tiles positions [sfovClearLid] :: StateServer -> FovClearLid -- | ambient light positions [sfovLitLid] :: StateServer -> FovLitLid -- | active arenas [sarenas] :: StateServer -> [LevelId] -- | whether active arenas valid [svalidArenas] :: StateServer -> Bool -- | current random generator [srandom] :: StateServer -> StdGen -- | initial random generators [srngs] :: StateServer -> RNGs -- | exit the game loop [squit] :: StateServer -> Bool -- | write savegame to a file now [swriteSave] :: StateServer -> Bool -- | current debugging mode [sdebugSer] :: StateServer -> DebugModeSer -- | debugging mode for the next game [sdebugNxt] :: StateServer -> DebugModeSer -- | Initial, empty game server state. emptyStateServer :: StateServer -- | Debug commands. See debugArgs for the descriptions. data DebugModeSer DebugModeSer :: Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Maybe (GroupName ModeKind) -> Bool -> Bool -> Maybe StdGen -> Maybe StdGen -> Bool -> Challenge -> Bool -> String -> Bool -> DebugModeCli -> DebugModeSer [sknowMap] :: DebugModeSer -> Bool [sknowEvents] :: DebugModeSer -> Bool [sknowItems] :: DebugModeSer -> Bool [sniffIn] :: DebugModeSer -> Bool [sniffOut] :: DebugModeSer -> Bool [sallClear] :: DebugModeSer -> Bool [sboostRandomItem] :: DebugModeSer -> Bool [sgameMode] :: DebugModeSer -> Maybe (GroupName ModeKind) [sautomateAll] :: DebugModeSer -> Bool [skeepAutomated] :: DebugModeSer -> Bool [sdungeonRng] :: DebugModeSer -> Maybe StdGen [smainRng] :: DebugModeSer -> Maybe StdGen [snewGameSer] :: DebugModeSer -> Bool [scurChalSer] :: DebugModeSer -> Challenge [sdumpInitRngs] :: DebugModeSer -> Bool [ssavePrefixSer] :: DebugModeSer -> String [sdbgMsgSer] :: DebugModeSer -> Bool [sdebugCli] :: DebugModeSer -> DebugModeCli defDebugModeSer :: DebugModeSer data RNGs RNGs :: Maybe StdGen -> Maybe StdGen -> RNGs [dungeonRandomGenerator] :: RNGs -> Maybe StdGen [startingRandomGenerator] :: RNGs -> Maybe StdGen type ActorTime = EnumMap FactionId (EnumMap LevelId (EnumMap ActorId Time)) updateActorTime :: FactionId -> LevelId -> ActorId -> Time -> ActorTime -> ActorTime ageActor :: FactionId -> LevelId -> ActorId -> Delta Time -> ActorTime -> ActorTime instance GHC.Show.Show Game.LambdaHack.Server.State.StateServer instance GHC.Show.Show Game.LambdaHack.Server.State.DebugModeSer instance Data.Binary.Class.Binary Game.LambdaHack.Server.State.StateServer instance GHC.Show.Show Game.LambdaHack.Server.State.RNGs instance Data.Binary.Class.Binary Game.LambdaHack.Server.State.RNGs instance Data.Binary.Class.Binary Game.LambdaHack.Server.State.DebugModeSer -- | Parsing of commandline arguments. module Game.LambdaHack.Server.Commandline -- | Parse server debug parameters from commandline arguments. debugArgs :: [String] -> DebugModeSer -- | Saving and restoring server game state. module Game.LambdaHack.Common.Save type ChanSave a = MVar (Maybe a) saveToChan :: ChanSave a -> a -> IO () wrapInSaves :: Binary a => COps -> (a -> FilePath) -> (ChanSave a -> IO ()) -> IO () -- | Restore a saved game, if it exists. Initialize directory structure and -- copy over data files, if needed. restoreGame :: Binary a => COps -> FilePath -> IO (Maybe a) saveNameCli :: COps -> FactionId -> String saveNameSer :: COps -> String -- | Repeatedly save a simple serialized version of the current state. loopSave :: Binary a => COps -> (a -> FilePath) -> ChanSave a -> IO () -- | Game action monads and basic building blocks for human and computer -- player actions. Has no access to the main action type. Does not export -- the liftIO operation nor a few other implementation details. module Game.LambdaHack.Server.MonadServer class MonadStateRead m => MonadServer m getsServer :: MonadServer m => (StateServer -> a) -> m a modifyServer :: MonadServer m => (StateServer -> StateServer) -> m () saveChanServer :: MonadServer m => m (ChanSave (State, StateServer)) liftIO :: MonadServer m => IO a -> m a getServer :: MonadServer m => m StateServer putServer :: MonadServer m => StateServer -> m () debugPossiblyPrint :: MonadServer m => Text -> m () debugPossiblyPrintAndExit :: MonadServer m => Text -> m () serverPrint :: MonadServer m => Text -> m () saveServer :: MonadServer m => m () -- | Dumps RNG states from the start of the game to stdout. dumpRngs :: MonadServer m => RNGs -> m () -- | Read the high scores dictionary. Return the empty table if no file. restoreScore :: forall m. MonadServer m => COps -> m ScoreDict -- | Generate a new score, register it and save. registerScore :: MonadServer m => Status -> FactionId -> m () -- | Invoke pseudo-random computation with the generator kept in the state. rndToAction :: MonadServer m => Rnd a -> m a -- | Gets a random generator from the arguments or, if not present, -- generates one. getSetGen :: MonadServer m => Maybe StdGen -> m StdGen -- | Server operations for items. module Game.LambdaHack.Server.ItemM rollItem :: (MonadAtomic m, MonadServer m) => Int -> LevelId -> Freqs ItemKind -> m (Maybe (ItemKnown, ItemFull, ItemDisco, ItemSeed, GroupName ItemKind)) rollAndRegisterItem :: (MonadAtomic m, MonadServer m) => LevelId -> Freqs ItemKind -> Container -> Bool -> Maybe Int -> m (Maybe (ItemId, (ItemFull, GroupName ItemKind))) registerItem :: (MonadAtomic m, MonadServer m) => ItemFull -> ItemKnown -> ItemSeed -> Container -> Bool -> m ItemId placeItemsInDungeon :: forall m. (MonadAtomic m, MonadServer m) => m () embedItemsInDungeon :: (MonadAtomic m, MonadServer m) => m () fullAssocsServer :: MonadServer m => ActorId -> [CStore] -> m [(ItemId, ItemFull)] itemToFullServer :: MonadServer m => m (ItemId -> ItemQuant -> ItemFull) -- | Mapping over actor's items from a give store. mapActorCStore_ :: MonadServer m => CStore -> (ItemId -> ItemQuant -> m a) -> Actor -> m () -- | Handle atomic commands before they are executed to change State and -- sent to clients. module Game.LambdaHack.Server.HandleAtomicM -- | Effect of atomic actions on server state is calculated with the global -- state from before the command is executed. cmdAtomicSemSer :: MonadServer m => UpdAtomic -> m () addItemToActor :: MonadServer m => ItemId -> Int -> ActorId -> m () updateSclear :: MonadServer m => LevelId -> Point -> Id TileKind -> Id TileKind -> m Bool updateSlit :: MonadServer m => LevelId -> Point -> Id TileKind -> Id TileKind -> m Bool invalidateLucidLid :: MonadServer m => LevelId -> m () invalidateLucidAid :: MonadServer m => ActorId -> m () actorHasShine :: ActorAspect -> ActorId -> Bool itemAffectsShineRadius :: DiscoveryAspect -> ItemId -> [CStore] -> Bool itemAffectsPerRadius :: DiscoveryAspect -> ItemId -> Bool addPerActor :: MonadServer m => ActorId -> Actor -> m () addPerActorAny :: MonadServer m => ActorId -> Actor -> m () deletePerActor :: MonadServer m => ActorId -> Actor -> m () deletePerActorAny :: MonadServer m => ActorId -> Actor -> m () invalidatePerActor :: MonadServer m => ActorId -> m () reconsiderPerActor :: MonadServer m => ActorId -> m () invalidatePerLid :: MonadServer m => LevelId -> m () -- | Debug output for requests and responseQs. module Game.LambdaHack.Server.DebugM debugResponse :: MonadServer m => FactionId -> Response -> m () debugRequestAI :: MonadServer m => ActorId -> RequestAI -> m () debugRequestUI :: MonadServer m => ActorId -> RequestUI -> m () instance GHC.Show.Show a => GHC.Show.Show (Game.LambdaHack.Server.DebugM.DebugAid a) -- | Server operations common to many modules. module Game.LambdaHack.Server.CommonM execFailure :: (MonadAtomic m, MonadServer m) => ActorId -> RequestTimed a -> ReqFailure -> m () getPerFid :: MonadServer m => FactionId -> LevelId -> m Perception revealItems :: (MonadAtomic m, MonadServer m) => Maybe FactionId -> m () moveStores :: (MonadAtomic m, MonadServer m) => Bool -> ActorId -> CStore -> CStore -> m () deduceQuits :: (MonadAtomic m, MonadServer m) => FactionId -> Status -> m () deduceKilled :: (MonadAtomic m, MonadServer m) => ActorId -> m () electLeader :: MonadAtomic m => FactionId -> LevelId -> ActorId -> m () supplantLeader :: MonadAtomic m => FactionId -> ActorId -> m () addActor :: (MonadAtomic m, MonadServer m) => GroupName ItemKind -> FactionId -> Point -> LevelId -> (Actor -> Actor) -> Time -> m (Maybe ActorId) registerActor :: (MonadAtomic m, MonadServer m) => ItemKnown -> ItemFull -> ItemDisco -> ItemSeed -> FactionId -> Point -> LevelId -> (Actor -> Actor) -> Time -> m (Maybe ActorId) addActorIid :: (MonadAtomic m, MonadServer m) => ItemId -> ItemFull -> Bool -> FactionId -> Point -> LevelId -> (Actor -> Actor) -> Time -> m (Maybe ActorId) projectFail :: (MonadAtomic m, MonadServer m) => ActorId -> Point -> Int -> ItemId -> CStore -> Bool -> m (Maybe ReqFailure) discoverIfNoEffects :: (MonadAtomic m, MonadServer m) => Container -> ItemId -> ItemFull -> m () pickWeaponServer :: MonadServer m => ActorId -> m (Maybe (ItemId, CStore)) currentSkillsServer :: MonadServer m => ActorId -> m Skills recomputeCachePer :: MonadServer m => FactionId -> LevelId -> m Perception -- | Operations for starting and restarting the game. module Game.LambdaHack.Server.StartM gameReset :: MonadServer m => COps -> DebugModeSer -> Maybe (GroupName ModeKind) -> Maybe StdGen -> m State reinitGame :: (MonadAtomic m, MonadServer m) => m () updatePer :: (MonadAtomic m, MonadServer m) => FactionId -> LevelId -> m () initPer :: MonadServer m => m () -- | Apply debug options that don't need a new game. applyDebug :: MonadServer m => m () -- | Server operations performed periodically in the game loop and related -- operations. module Game.LambdaHack.Server.PeriodicM -- | Spawn, possibly, a monster according to the level's actor groups. We -- assume heroes are never spawned. spawnMonster :: (MonadAtomic m, MonadServer m) => m () addAnyActor :: (MonadAtomic m, MonadServer m) => Freqs ItemKind -> LevelId -> Time -> Maybe Point -> m (Maybe ActorId) -- | Advance the move time for the given actor advanceTime :: (MonadAtomic m, MonadServer m) => ActorId -> Int -> m () overheadActorTime :: (MonadAtomic m, MonadServer m) => FactionId -> m () -- | Swap the relative move times of two actors (e.g., when switching a UI -- leader). swapTime :: (MonadAtomic m, MonadServer m) => ActorId -> ActorId -> m () leadLevelSwitch :: (MonadAtomic m, MonadServer m) => m () udpateCalm :: (MonadAtomic m, MonadServer m) => ActorId -> Int64 -> m () -- | Handle effects (most often caused by requests sent by clients). module Game.LambdaHack.Server.HandleEffectM applyItem :: (MonadAtomic m, MonadServer m) => ActorId -> ItemId -> CStore -> m () meleeEffectAndDestroy :: (MonadAtomic m, MonadServer m) => ActorId -> ActorId -> ItemId -> Container -> m () effectAndDestroy :: (MonadAtomic m, MonadServer m) => Bool -> ActorId -> ActorId -> ItemId -> Container -> Bool -> [Effect] -> ItemFull -> m () itemEffectEmbedded :: (MonadAtomic m, MonadServer m) => ActorId -> Point -> ItemBag -> m () -- | Drop a single actor's item. Note that if there are multiple copies, at -- most one explodes to avoid excessive carnage and UI clutter (let's -- say, the multiple explosions interfere with each other or perhaps -- larger quantities of explosives tend to be packaged more safely). dropCStoreItem :: (MonadAtomic m, MonadServer m) => Bool -> CStore -> ActorId -> Actor -> Int -> ItemId -> ItemQuant -> m () dominateFidSfx :: (MonadAtomic m, MonadServer m) => FactionId -> ActorId -> m Bool pickDroppable :: MonadStateRead m => ActorId -> Actor -> m Container cutCalm :: (MonadAtomic m, MonadServer m) => ActorId -> m () -- | Semantics of request. A couple of them do not take time, the rest -- does. Note that since the results are atomic commands, which are -- executed only later (on the server and some of the clients), all -- condition are checkd by the semantic functions in the context of the -- state before the server command. Even if one or more atomic actions -- are already issued by the point an expression is evaluated, they do -- not influence the outcome of the evaluation. module Game.LambdaHack.Server.HandleRequestM -- | The semantics of server commands. AI always takes time and so doesn't -- loop. handleRequestAI :: (MonadAtomic m) => ReqAI -> m (Maybe RequestAnyAbility) -- | The semantics of server commands. Only the first two cases take time. handleRequestUI :: (MonadAtomic m, MonadServer m) => FactionId -> ActorId -> ReqUI -> m (Maybe RequestAnyAbility) switchLeader :: (MonadAtomic m, MonadServer m) => FactionId -> ActorId -> m () handleRequestTimed :: (MonadAtomic m, MonadServer m) => FactionId -> ActorId -> RequestTimed a -> m Bool -- | Actor moves or attacks. Note that client may not be able to see an -- invisible monster so it's the server that determines if melee took -- place, etc. Also, only the server is authorized to check if a move is -- legal and it needs full context for that, e.g., the initial actor -- position to check if melee attack does not try to reach to a distant -- tile. reqMove :: (MonadAtomic m, MonadServer m) => ActorId -> Vector -> m () -- | Actor tries to swap positions with another. reqDisplace :: (MonadAtomic m, MonadServer m) => ActorId -> ActorId -> m () reqGameExit :: (MonadAtomic m, MonadServer m) => ActorId -> m () -- | This is a shorthand. Instead of setting bwait in -- ReqWait and unsetting in all other requests, we call this -- once before executing a request. setBWait :: (MonadAtomic m) => RequestTimed a -> ActorId -> m (Maybe Bool) handleRequestTimedCases :: (MonadAtomic m, MonadServer m) => ActorId -> RequestTimed a -> m () -- | Add a smell trace for the actor to the level. For now, only actors -- with gender leave strong and unique enough smell. If smell already -- there and the actor can smell, remove smell. Projectiles are ignored. -- As long as an actor can smell, he doesn't leave any smell ever. affectSmell :: (MonadAtomic m, MonadServer m) => ActorId -> m () -- | Resolves the result of an actor moving into another. Actors on blocked -- positions can be attacked without any restrictions. For instance, an -- actor embedded in a wall can be attacked from an adjacent position. -- This function is analogous to projectGroupItem, but for melee and not -- using up the weapon. No problem if there are many projectiles at the -- spot. We just attack the one specified. reqMelee :: (MonadAtomic m, MonadServer m) => ActorId -> ActorId -> ItemId -> CStore -> m () -- | Search and/or alter the tile. -- -- Note that if serverTile /= freshClientTile, -- freshClientTile should not be alterable (but -- serverTile may be). reqAlter :: (MonadAtomic m, MonadServer m) => ActorId -> Point -> m () -- | Do nothing. -- -- Something is sometimes done in setBWait. reqWait :: MonadAtomic m => ActorId -> m () reqMoveItems :: (MonadAtomic m, MonadServer m) => ActorId -> [(ItemId, Int, CStore, CStore)] -> m () reqMoveItem :: (MonadAtomic m, MonadServer m) => ActorId -> Bool -> (ItemId, Int, CStore, CStore) -> m () computeRndTimeout :: Time -> ItemId -> ItemFull -> Rnd (Maybe Time) reqProject :: (MonadAtomic m, MonadServer m) => ActorId -> Point -> Int -> ItemId -> CStore -> m () reqApply :: (MonadAtomic m, MonadServer m) => ActorId -> ItemId -> CStore -> m () reqGameRestart :: (MonadAtomic m, MonadServer m) => ActorId -> GroupName ModeKind -> Challenge -> m () reqGameSave :: MonadServer m => m () reqTactic :: MonadAtomic m => FactionId -> Tactic -> m () reqAutomate :: MonadAtomic m => FactionId -> m () -- | The main loop of the server, processing human and computer player -- moves turn by turn. module Game.LambdaHack.Server.EndM -- | Continue or exit or restart the game. endOrLoop :: (MonadAtomic m, MonadServer m) => m () -> (Maybe (GroupName ModeKind) -> m ()) -> m () -> m () -> m () dieSer :: (MonadAtomic m, MonadServer m) => ActorId -> Actor -> m () -- | Client monad for interacting with a human through UI. module Game.LambdaHack.Client.UI.MonadClientUI -- | The monad that gives the client access to UI operations. class MonadClient m => MonadClientUI m getsSession :: MonadClientUI m => (SessionUI -> a) -> m a modifySession :: MonadClientUI m => (SessionUI -> SessionUI) -> m () liftIO :: MonadClientUI m => IO a -> m a getSession :: MonadClientUI m => m SessionUI putSession :: MonadClientUI m => SessionUI -> m () clientPrintUI :: MonadClientUI m => Text -> m () -- | The row where the dungeon map starts. mapStartY :: Y -- | Push frames or delays to the frame queue. The frames depict the -- lid level. displayFrames :: MonadClientUI m => LevelId -> Frames -> m () setFrontAutoYes :: MonadClientUI m => Bool -> m () anyKeyPressed :: MonadClientUI m => m Bool discardPressedKey :: MonadClientUI m => m () addPressedEsc :: MonadClientUI m => m () -- | Write FrontKey UI request to the frontend, read the reply, set -- pointer, return key. connFrontendFrontKey :: MonadClientUI m => [KM] -> FrameForall -> m KM frontendShutdown :: MonadClientUI m => m () chanFrontend :: MonadClientUI m => DebugModeCli -> m ChanFrontend getReportUI :: MonadClientUI m => m Report getLeaderUI :: MonadClientUI m => m ActorId getArenaUI :: MonadClientUI m => m LevelId viewedLevelUI :: MonadClientUI m => m LevelId leaderTgtToPos :: MonadClientUI m => m (Maybe Point) xhairToPos :: MonadClientUI m => m (Maybe Point) clearXhair :: MonadClientUI m => m () clearAimMode :: MonadClientUI m => m () scoreToSlideshow :: MonadClientUI m => Int -> Status -> m Slideshow defaultHistory :: MonadClientUI m => Int -> m History tellAllClipPS :: MonadClientUI m => m () tellGameClipPS :: MonadClientUI m => m () elapsedSessionTimeGT :: MonadClientUI m => Int -> m Bool resetSessionStart :: MonadClientUI m => m () resetGameStart :: MonadClientUI m => m () -- | The part of speech describing the actor (designated by actor id and -- present in the dungeon) or a special name if a leader of the -- observer's faction. partAidLeader :: MonadClientUI m => ActorId -> m Part -- | The part of speech describing the actor or "you" if a leader of the -- client's faction. The actor may be not present in the dungeon. partActorLeader :: MonadClientUI m => ActorId -> ActorUI -> m Part partActorLeaderFun :: MonadClientUI m => m (ActorId -> Part) -- | The part of speech with the actor's pronoun or "you" if a leader of -- the client's faction. The actor may be not present in the dungeon. partPronounLeader :: MonadClient m => ActorId -> ActorUI -> m Part tryRestore :: MonadClientUI m => m (Maybe (State, StateClient, Maybe SessionUI)) leaderSkillsClientUI :: MonadClientUI m => m Skills -- | Running and disturbance. -- -- The general rule is: whatever is behind you (and so ignored -- previously), determines what you ignore moving forward. This is -- calcaulated separately for the tiles to the left, to the right and in -- the middle along the running direction. So, if you want to ignore -- something start running when you stand on it (or to the right or left, -- respectively) or by entering it (or passing to the right or left, -- respectively). -- -- Some things are never ignored, such as: enemies seen, imporant -- messages heard, solid tiles and actors in the way. module Game.LambdaHack.Client.UI.RunM -- | Continue running in the given direction. continueRun :: MonadClientUI m => LevelId -> RunParams -> m (Either Text RequestAnyAbility) -- | A set of Overlay monad operations. module Game.LambdaHack.Client.UI.OverlayM describeMainKeys :: MonadClientUI m => m Text -- | Produces a textual description of the terrain and items at an already -- explored position. Mute for unknown positions. The detailed variant is -- for use in the aiming mode. lookAt :: MonadClientUI m => Bool -> Text -> Bool -> Point -> ActorId -> Text -> m Text -- | Client monad for interacting with a human through UI. module Game.LambdaHack.Client.UI.MsgM -- | Add a message to the current report. msgAdd :: MonadClientUI m => Text -> m () -- | Add a prompt to the current report. promptAdd :: MonadClientUI m => Text -> m () -- | Add a prompt to the current report. promptAddAttr :: MonadClientUI m => AttrLine -> m () -- | Store current report in the history and reset report. recordHistory :: MonadClientUI m => m () -- | Display game data on the screen using one of the available frontends -- (determined at compile time with cabal flags). module Game.LambdaHack.Client.UI.DrawM targetDescLeader :: MonadClientUI m => ActorId -> m (Maybe Text, Maybe Text) -- | Draw the whole screen: level map and status area. Pass at most a -- single page if overlay of text unchanged to the frontends to display -- separately or overlay over map, depending on the frontend. drawBaseFrame :: MonadClientUI m => ColorMode -> LevelId -> m FrameForall targetDesc :: MonadClientUI m => Maybe Target -> m (Maybe Text, Maybe Text) targetDescXhair :: MonadClientUI m => m (Text, Maybe Text) drawFrameTerrain :: forall m. MonadClientUI m => LevelId -> m FrameForall drawFrameContent :: forall m. MonadClientUI m => LevelId -> m FrameForall drawFramePath :: forall m. MonadClientUI m => LevelId -> m FrameForall drawFrameActor :: forall m. MonadClientUI m => LevelId -> m FrameForall drawFrameExtra :: forall m. MonadClientUI m => ColorMode -> LevelId -> m FrameForall drawFrameStatus :: MonadClientUI m => LevelId -> m AttrLine drawArenaStatus :: Bool -> Level -> Int -> AttrLine drawLeaderStatus :: MonadClient m => Int -> m AttrLine drawLeaderDamage :: MonadClientUI m => Int -> m AttrLine drawSelected :: MonadClientUI m => LevelId -> Int -> EnumSet ActorId -> m (Int, AttrLine) -- | A set of Frame monad operations. module Game.LambdaHack.Client.UI.FrameM -- | Draw the current level with the overlay on top. If the overlay is too -- long, it's truncated. Similarly, for each line of the overlay, if it's -- too wide, it's truncated. drawOverlay :: MonadClientUI m => ColorMode -> Bool -> [AttrLine] -> LevelId -> m FrameForall promptGetKey :: MonadClientUI m => ColorMode -> [AttrLine] -> Bool -> [KM] -> m KM stopPlayBack :: MonadClientUI m => m () -- | Render and display animations on top of the current screen frame. animate :: MonadClientUI m => LevelId -> Animation -> m () fadeOutOrIn :: MonadClientUI m => Bool -> m () -- | A set of Slideshow monad operations. module Game.LambdaHack.Client.UI.SlideshowM -- | Add current report to the overlay, split the result and produce, -- possibly, many slides. overlayToSlideshow :: MonadClientUI m => Y -> [KM] -> OKX -> m Slideshow -- | Split current report into a slideshow. reportToSlideshow :: MonadClientUI m => [KM] -> m Slideshow -- | Split current report into a slideshow. Keep report unchanged. reportToSlideshowKeep :: MonadClientUI m => [KM] -> m Slideshow -- | Display a message. Return value indicates if the player wants to -- continue. Feature: if many pages, only the last SPACE exits (but first -- ESC). displaySpaceEsc :: MonadClientUI m => ColorMode -> Text -> m Bool -- | Display a message. Ignore keypresses. Feature: if many pages, only the -- last SPACE exits (but first ESC). displayMore :: MonadClientUI m => ColorMode -> Text -> m () displayMoreKeep :: MonadClientUI m => ColorMode -> Text -> m () -- | Print a yes/no question and return the player's answer. Use black and -- white colours to turn player's attention to the choice. displayYesNo :: MonadClientUI m => ColorMode -> Text -> m Bool getConfirms :: MonadClientUI m => ColorMode -> [KM] -> Slideshow -> m KM displayChoiceScreen :: forall m. MonadClientUI m => ColorMode -> Bool -> Int -> Slideshow -> [KM] -> m (Either KM SlotChar, Int) -- | Helper functions for both inventory management and human commands. module Game.LambdaHack.Client.UI.HandleHelperM type MError = Maybe FailError type FailOrCmd a = Either FailError a data FailError showFailError :: FailError -> Text mergeMError :: MError -> MError -> MError failWith :: MonadClientUI m => Text -> m (FailOrCmd a) failSer :: MonadClientUI m => ReqFailure -> m (FailOrCmd a) failMsg :: MonadClientUI m => Text -> m MError weaveJust :: FailOrCmd a -> Either MError a sortSlots :: MonadClientUI m => FactionId -> Maybe Actor -> m () -- | Switches current member to the next on the level, if any, wrapping. memberCycle :: MonadClientUI m => Bool -> m MError -- | Switches current member to the previous in the whole dungeon, -- wrapping. memberBack :: MonadClientUI m => Bool -> m MError partyAfterLeader :: MonadClientUI m => ActorId -> m [(ActorId, Actor, ActorUI)] -- | Select a faction leader. False, if nothing to do. pickLeader :: MonadClientUI m => Bool -> ActorId -> m Bool pickLeaderWithPointer :: MonadClientUI m => m MError -- | Create a list of item names. itemOverlay :: MonadClientUI m => CStore -> LevelId -> ItemBag -> m OKX statsOverlay :: MonadClient m => ActorId -> m OKX pickNumber :: MonadClientUI m => Bool -> Int -> m (Either MError Int) instance GHC.Show.Show Game.LambdaHack.Client.UI.HandleHelperM.FailError -- | Inventory management and party cycling. module Game.LambdaHack.Client.UI.InventoryM data Suitability SuitsEverything :: Suitability SuitsSomething :: (ItemFull -> Bool) -> Suitability -- | Let the human player choose a single, preferably suitable, item from a -- list of items. Don't display stores empty for all actors. Start with a -- non-empty store. getFull :: MonadClientUI m => m Suitability -> (Actor -> ActorUI -> AspectRecord -> ItemDialogMode -> Text) -> (Actor -> ActorUI -> AspectRecord -> ItemDialogMode -> Text) -> [CStore] -> [CStore] -> Bool -> Bool -> m (Either Text ([(ItemId, ItemFull)], (ItemDialogMode, Either KM SlotChar))) -- | Let a human player choose any item from a given group. Note that this -- does not guarantee the chosen item belongs to the group, as the player -- can override the choice. Used e.g., for applying and projecting. getGroupItem :: MonadClientUI m => m Suitability -> Text -> Text -> [CStore] -> [CStore] -> m (Either Text ((ItemId, ItemFull), (ItemDialogMode, Either KM SlotChar))) -- | Display all items from a store and let the human player choose any or -- switch to any other store. Used, e.g., for viewing inventory and item -- descriptions. getStoreItem :: MonadClientUI m => (Actor -> ActorUI -> AspectRecord -> ItemDialogMode -> Text) -> ItemDialogMode -> m (Either Text (ItemId, ItemFull), (ItemDialogMode, Either KM SlotChar)) ppItemDialogMode :: ItemDialogMode -> (Text, Text) ppItemDialogModeFrom :: ItemDialogMode -> Text storeFromMode :: ItemDialogMode -> CStore instance GHC.Classes.Eq Game.LambdaHack.Client.UI.InventoryM.ItemDialogState instance GHC.Show.Show Game.LambdaHack.Client.UI.InventoryM.ItemDialogState -- | Semantics of HumanCmd client commands that do not return -- server commands. None of such commands takes game time. module Game.LambdaHack.Client.UI.HandleHumanLocalM macroHuman :: MonadClientUI m => [String] -> m () -- | Clear current messages, cycle key hints mode. clearHuman :: MonadClientUI m => m () sortSlotsHuman :: MonadClientUI m => m () -- | Display items from a given container store and possibly let the user -- chose one. chooseItemHuman :: MonadClientUI m => ItemDialogMode -> m MError chooseItemDialogMode :: MonadClientUI m => ItemDialogMode -> m (FailOrCmd ItemDialogMode) chooseItemProjectHuman :: forall m. MonadClientUI m => [Trigger] -> m MError chooseItemApplyHuman :: forall m. MonadClientUI m => [Trigger] -> m MError psuitReq :: MonadClientUI m => [Trigger] -> m (Either Text (ItemFull -> Either ReqFailure (Point, Bool))) triggerSymbols :: [Trigger] -> [Char] permittedApplyClient :: MonadClientUI m => [Char] -> m (ItemFull -> Either ReqFailure Bool) pickLeaderHuman :: MonadClientUI m => Int -> m MError pickLeaderWithPointerHuman :: MonadClientUI m => m MError -- | Switches current member to the next on the viewed level, if any, -- wrapping. memberCycleHuman :: MonadClientUI m => m MError -- | Switches current member to the previous in the whole dungeon, -- wrapping. memberBackHuman :: MonadClientUI m => m MError selectActorHuman :: MonadClientUI m => m () selectNoneHuman :: MonadClientUI m => m () selectWithPointerHuman :: MonadClientUI m => m MError repeatHuman :: MonadClientUI m => Int -> m () recordHuman :: MonadClientUI m => m () historyHuman :: forall m. MonadClientUI m => m () markVisionHuman :: MonadClientUI m => m () markSmellHuman :: MonadClientUI m => m () markSuspectHuman :: MonadClientUI m => m () -- | End aiming mode, rejecting the current position. cancelHuman :: MonadClientUI m => m () -- | Accept the current x-hair position as target, ending aiming mode, if -- active. acceptHuman :: MonadClientUI m => m () tgtClearHuman :: MonadClientUI m => m () itemClearHuman :: MonadClientUI m => m () -- | Move the xhair. Assumes aiming mode. moveXhairHuman :: MonadClientUI m => Vector -> Int -> m MError -- | Start aiming. aimTgtHuman :: MonadClientUI m => m MError -- | Cycle aiming mode. Do not change position of the xhair, switch among -- things at that position. aimFloorHuman :: MonadClientUI m => m () aimEnemyHuman :: MonadClientUI m => m () aimItemHuman :: MonadClientUI m => m () -- | Change the displayed level in aiming mode to (at most) k levels -- shallower. Enters aiming mode, if not already in one. aimAscendHuman :: MonadClientUI m => Int -> m MError -- | Tweak the eps parameter of the aiming digital line. epsIncrHuman :: MonadClientUI m => Bool -> m () xhairUnknownHuman :: MonadClientUI m => m MError xhairItemHuman :: MonadClientUI m => m MError xhairStairHuman :: MonadClientUI m => Bool -> m MError xhairPointerFloorHuman :: MonadClientUI m => m () xhairPointerEnemyHuman :: MonadClientUI m => m () aimPointerFloorHuman :: MonadClientUI m => m () aimPointerEnemyHuman :: MonadClientUI m => m () -- | Display atomic commands received by the client. module Game.LambdaHack.Client.UI.DisplayAtomicM -- | Visualize atomic actions sent to the client. This is done in the -- global state after the command is executed and after the client state -- is modified by the command. displayRespUpdAtomicUI :: MonadClientUI m => Bool -> StateClient -> UpdAtomic -> m () -- | Display special effects (text, animation) sent to the client. displayRespSfxAtomicUI :: MonadClientUI m => Bool -> SfxAtomic -> m () -- | Semantics of Cmd client commands that return server commands. A -- couple of them do not take time, the rest does. Here prompts and menus -- and displayed, but any feedback resulting from the commands (e.g., -- from inventory manipulation) is generated later on, for all clients -- that witness the results of the commands. module Game.LambdaHack.Client.UI.HandleHumanGlobalM -- | Pick command depending on area the mouse pointer is in. The first -- matching area is chosen. If none match, only interrupt. byAreaHuman :: MonadClientUI m => (HumanCmd -> m (Either MError ReqUI)) -> [(CmdArea, HumanCmd)] -> m (Either MError ReqUI) byAimModeHuman :: MonadClientUI m => m (Either MError ReqUI) -> m (Either MError ReqUI) -> m (Either MError ReqUI) byItemModeHuman :: MonadClientUI m => [Trigger] -> m (Either MError ReqUI) -> m (Either MError ReqUI) -> m (Either MError ReqUI) composeIfLocalHuman :: MonadClientUI m => m (Either MError ReqUI) -> m (Either MError ReqUI) -> m (Either MError ReqUI) composeUnlessErrorHuman :: MonadClientUI m => m (Either MError ReqUI) -> m (Either MError ReqUI) -> m (Either MError ReqUI) compose2ndLocalHuman :: MonadClientUI m => m (Either MError ReqUI) -> m (Either MError ReqUI) -> m (Either MError ReqUI) loopOnNothingHuman :: MonadClientUI m => m (Either MError ReqUI) -> m (Either MError ReqUI) -- | Leader waits a turn (and blocks, etc.). waitHuman :: MonadClientUI m => m (RequestTimed 'AbWait) -- | Leader waits a 1/10th of a turn (and doesn't block, etc.). waitHuman10 :: MonadClientUI m => m (RequestTimed 'AbWait) moveRunHuman :: MonadClientUI m => Bool -> Bool -> Bool -> Bool -> Vector -> m (FailOrCmd RequestAnyAbility) runOnceAheadHuman :: MonadClientUI m => m (Either MError ReqUI) moveOnceToXhairHuman :: MonadClientUI m => m (FailOrCmd RequestAnyAbility) runOnceToXhairHuman :: MonadClientUI m => m (FailOrCmd RequestAnyAbility) continueToXhairHuman :: MonadClientUI m => m (FailOrCmd RequestAnyAbility) moveItemHuman :: forall m. MonadClientUI m => [CStore] -> CStore -> Maybe Part -> Bool -> m (FailOrCmd (RequestTimed 'AbMoveItem)) projectHuman :: MonadClientUI m => [Trigger] -> m (FailOrCmd (RequestTimed 'AbProject)) applyHuman :: MonadClientUI m => [Trigger] -> m (FailOrCmd (RequestTimed 'AbApply)) -- | Ask for a direction and alter a tile in the specified way, if -- possible. alterDirHuman :: MonadClientUI m => [Trigger] -> m (FailOrCmd (RequestTimed 'AbAlter)) -- | Try to alter a tile using a feature under the pointer. alterWithPointerHuman :: MonadClientUI m => [Trigger] -> m (FailOrCmd (RequestTimed 'AbAlter)) -- | Display command help. helpHuman :: MonadClientUI m => (HumanCmd -> m (Either MError ReqUI)) -> m (Either MError ReqUI) itemMenuHuman :: MonadClientUI m => (HumanCmd -> m (Either MError ReqUI)) -> m (Either MError ReqUI) chooseItemMenuHuman :: MonadClientUI m => (HumanCmd -> m (Either MError ReqUI)) -> ItemDialogMode -> m (Either MError ReqUI) -- | Display the main menu. mainMenuHuman :: MonadClientUI m => (HumanCmd -> m (Either MError ReqUI)) -> m (Either MError ReqUI) -- | Display the settings menu. settingsMenuHuman :: MonadClientUI m => (HumanCmd -> m (Either MError ReqUI)) -> m (Either MError ReqUI) -- | Display the challenges menu. challengesMenuHuman :: MonadClientUI m => (HumanCmd -> m (Either MError ReqUI)) -> m (Either MError ReqUI) gameDifficultyIncr :: MonadClientUI m => m () gameWolfToggle :: MonadClientUI m => m () gameFishToggle :: MonadClientUI m => m () gameScenarioIncr :: MonadClientUI m => m () gameRestartHuman :: MonadClientUI m => m (FailOrCmd ReqUI) gameExitHuman :: MonadClientUI m => m ReqUI gameSaveHuman :: MonadClientUI m => m ReqUI tacticHuman :: MonadClientUI m => m (FailOrCmd ReqUI) automateHuman :: MonadClientUI m => m (FailOrCmd ReqUI) -- | Semantics of human player commands. module Game.LambdaHack.Client.UI.HandleHumanM -- | The semantics of human player commands in terms of the Action -- monad. Decides if the action takes time and what action to perform. -- Some time cosuming commands are enabled in aiming mode, but cannot be -- invoked in aiming mode on a remote level (level different than the -- level of the leader). cmdHumanSem :: MonadClientUI m => HumanCmd -> m (Either MError ReqUI) -- | Ways for the client to use player input via UI to produce server -- requests, based on the client's view (visualized for the player) of -- the game state. module Game.LambdaHack.Client.UI -- | The monad that gives the client access to UI operations. class MonadClient m => MonadClientUI m getsSession :: MonadClientUI m => (SessionUI -> a) -> m a modifySession :: MonadClientUI m => (SessionUI -> SessionUI) -> m () liftIO :: MonadClientUI m => IO a -> m a putSession :: MonadClientUI m => SessionUI -> m () -- | Handle the move of a UI player. queryUI :: MonadClientUI m => m RequestUI -- | Visualize atomic actions sent to the client. This is done in the -- global state after the command is executed and after the client state -- is modified by the command. displayRespUpdAtomicUI :: MonadClientUI m => Bool -> StateClient -> UpdAtomic -> m () -- | Display special effects (text, animation) sent to the client. displayRespSfxAtomicUI :: MonadClientUI m => Bool -> SfxAtomic -> m () -- | Key-command mappings to be used for the UI. data KeyKind -- | The information that is used across a client playing session, -- including many consecutive games in a single session. Some of it is -- saved, some is reset when a new playing session starts. An important -- component is a frontend session. data SessionUI SessionUI :: Target -> ActorDictUI -> ItemSlots -> SlotChar -> Maybe (CStore, CStore) -> ChanFrontend -> Binding -> Config -> Maybe AimMode -> Bool -> Maybe (CStore, ItemId) -> EnumSet ActorId -> Maybe RunParams -> Report -> History -> Point -> LastRecord -> [KM] -> EnumSet ActorId -> Int -> Bool -> Bool -> Map String Int -> Bool -> KeysHintMode -> POSIXTime -> POSIXTime -> Time -> Int -> Int -> SessionUI -- | the common xhair [sxhair] :: SessionUI -> Target -- | assigned actor UI presentations [sactorUI] :: SessionUI -> ActorDictUI -- | map from slots to items [sslots] :: SessionUI -> ItemSlots -- | last used slot [slastSlot] :: SessionUI -> SlotChar -- | last item move stores [slastItemMove] :: SessionUI -> Maybe (CStore, CStore) -- | connection with the frontend [schanF] :: SessionUI -> ChanFrontend -- | binding of keys to commands [sbinding] :: SessionUI -> Binding [sconfig] :: SessionUI -> Config -- | aiming mode [saimMode] :: SessionUI -> Maybe AimMode -- | last mouse aiming not vacuus [sxhairMoused] :: SessionUI -> Bool -- | selected item, if any [sitemSel] :: SessionUI -> Maybe (CStore, ItemId) -- | the set of currently selected actors [sselected] :: SessionUI -> EnumSet ActorId -- | parameters of the current run, if any [srunning] :: SessionUI -> Maybe RunParams -- | current messages [_sreport] :: SessionUI -> Report -- | history of messages [shistory] :: SessionUI -> History -- | mouse pointer position [spointer] :: SessionUI -> Point -- | state of key sequence recording [slastRecord] :: SessionUI -> LastRecord -- | state of key sequence playback [slastPlay] :: SessionUI -> [KM] -- | actors that just got out of sight [slastLost] :: SessionUI -> EnumSet ActorId -- | player just waited this many times [swaitTimes] :: SessionUI -> Int -- | mark leader and party FOV [smarkVision] :: SessionUI -> Bool -- | mark smell, if the leader can smell [smarkSmell] :: SessionUI -> Bool -- | indices of last used menu items [smenuIxMap] :: SessionUI -> Map String Int -- | something to display on current level [sdisplayNeeded] :: SessionUI -> Bool -- | how to show keys hints when no messages [skeysHintMode] :: SessionUI -> KeysHintMode -- | this session start time [sstart] :: SessionUI -> POSIXTime -- | this game start time [sgstart] :: SessionUI -> POSIXTime -- | clips from start of session to current game start [sallTime] :: SessionUI -> Time -- | this game current frame count [snframes] :: SessionUI -> Int -- | frame count from start of session to current game start [sallNframes] :: SessionUI -> Int -- | Initial empty game client state. emptySessionUI :: Config -> SessionUI -- | Fully typed contents of the UI config file. This config is a part of a -- game client. data Config applyConfigToDebug :: COps -> Config -> DebugModeCli -> DebugModeCli configCmdline :: Config -> [String] -- | Read and parse UI config file. mkConfig :: COps -> Bool -> IO Config -- | Connection channel between a frontend and a client. Frontend acts as a -- server, serving keys, etc., when given frames to display. data ChanFrontend chanFrontend :: MonadClientUI m => DebugModeCli -> m ChanFrontend frontendShutdown :: MonadClientUI m => m () -- | Color mode for the display. data ColorMode -- | normal, with full colours ColorFull :: ColorMode -- | black+white only ColorBW :: ColorMode -- | Split current report into a slideshow. reportToSlideshow :: MonadClientUI m => [KM] -> m Slideshow getConfirms :: MonadClientUI m => ColorMode -> [KM] -> Slideshow -> m KM -- | Add a message to the current report. msgAdd :: MonadClientUI m => Text -> m () -- | Add a prompt to the current report. promptAdd :: MonadClientUI m => Text -> m () addPressedEsc :: MonadClientUI m => m () tryRestore :: MonadClientUI m => m (Maybe (State, StateClient, Maybe SessionUI)) -- | Binding of keys to movement and other standard commands, as well as -- commands defined in the config file. stdBinding :: KeyKind -> Config -> Binding -- | Let the human player issue commands until any command takes time. humanCommand :: forall m. MonadClientUI m => m ReqUI -- | Semantics of client commands. module Game.LambdaHack.Client.HandleResponseM class MonadClient m => MonadClientReadResponse m receiveResponse :: MonadClientReadResponse m => m Response class MonadClient m => MonadClientWriteRequest m sendRequestAI :: MonadClientWriteRequest m => RequestAI -> m () sendRequestUI :: MonadClientWriteRequest m => RequestUI -> m () clientHasUI :: MonadClientWriteRequest m => m Bool handleResponse :: (MonadClientSetup m, MonadClientUI m, MonadAtomic m, MonadClientWriteRequest m) => Response -> m () -- | The main loop of the client, processing human and computer player -- moves turn by turn. module Game.LambdaHack.Client.LoopM -- | The main game loop for an AI or UI client. loopCli :: (MonadClientSetup m, MonadClientUI m, MonadAtomic m, MonadClientReadResponse m, MonadClientWriteRequest m) => KeyKind -> Config -> DebugModeCli -> m () -- | Semantics of responses that are sent to clients. -- -- See -- https://github.com/LambdaHack/LambdaHack/wiki/Client-server-architecture. module Game.LambdaHack.Client -- | The main game loop for an AI or UI client. loopCli :: (MonadClientSetup m, MonadClientUI m, MonadAtomic m, MonadClientReadResponse m, MonadClientWriteRequest m) => KeyKind -> Config -> DebugModeCli -> m () -- | Key-command mappings to be used for the UI. data KeyKind -- | The information that is used across a client playing session, -- including many consecutive games in a single session. Some of it is -- saved, some is reset when a new playing session starts. An important -- component is a frontend session. data SessionUI -- | Initial empty game client state. emptySessionUI :: Config -> SessionUI -- | Fully typed contents of the UI config file. This config is a part of a -- game client. data Config applyConfigToDebug :: COps -> Config -> DebugModeCli -> DebugModeCli configCmdline :: Config -> [String] -- | Read and parse UI config file. mkConfig :: COps -> Bool -> IO Config -- | The server definitions for the server-client communication protocol. module Game.LambdaHack.Server.ProtocolM -- | Connection information for all factions, indexed by faction -- identifier. type ConnServerDict = EnumMap FactionId ChanServer -- | The server monad with the ability to communicate with clients. class MonadServer m => MonadServerReadRequest m getsDict :: MonadServerReadRequest m => (ConnServerDict -> a) -> m a modifyDict :: MonadServerReadRequest m => (ConnServerDict -> ConnServerDict) -> m () liftIO :: MonadServerReadRequest m => IO a -> m a putDict :: MonadServerReadRequest m => ConnServerDict -> m () sendUpdate :: MonadServerReadRequest m => FactionId -> UpdAtomic -> m () sendSfx :: MonadServerReadRequest m => FactionId -> SfxAtomic -> m () sendQueryAI :: MonadServerReadRequest m => FactionId -> ActorId -> m RequestAI sendQueryUI :: (MonadAtomic m, MonadServerReadRequest m) => FactionId -> ActorId -> m RequestUI killAllClients :: (MonadAtomic m, MonadServerReadRequest m) => m () childrenServer :: MVar [Async ()] -- | Update connections to the new definition of factions. Connect to -- clients in old or newly spawned threads that read and write directly -- to the channels. updateConn :: (MonadAtomic m, MonadServerReadRequest m) => Config -> (Maybe SessionUI -> FactionId -> ChanServer -> IO ()) -> m () tryRestore :: MonadServerReadRequest m => COps -> DebugModeSer -> m (Maybe (State, StateServer)) -- | Sending atomic commands to clients and executing them on the server. -- See -- https://github.com/LambdaHack/LambdaHack/wiki/Client-server-architecture. module Game.LambdaHack.Server.BroadcastAtomic -- | Send an atomic action to all clients that can see it. handleAndBroadcast :: (MonadStateWrite m, MonadServerReadRequest m) => CmdAtomic -> m () sendPer :: MonadServerReadRequest m => FactionId -> LevelId -> Perception -> Perception -> Perception -> m () handleCmdAtomicServer :: MonadStateWrite m => PosAtomic -> UpdAtomic -> m () atomicRemember :: LevelId -> Perception -> State -> [UpdAtomic] -- | The main loop of the server, processing human and computer player -- moves turn by turn. module Game.LambdaHack.Server.LoopM -- | Start a game session, including the clients, and then loop, -- communicating with the clients. loopSer :: (MonadAtomic m, MonadServerReadRequest m) => DebugModeSer -> Config -> (Maybe SessionUI -> FactionId -> ChanServer -> IO ()) -> m () factionArena :: MonadStateRead m => Faction -> m (Maybe LevelId) arenasForLoop :: MonadStateRead m => m [LevelId] handleFidUpd :: (MonadAtomic m, MonadServerReadRequest m) => Bool -> (FactionId -> m ()) -> FactionId -> Faction -> m Bool -- | Handle a clip (a part of a turn for which one or more frames will be -- generated). Run the leader and other actors moves. Eventually advance -- the time and repeat. loopUpd :: forall m. (MonadAtomic m, MonadServerReadRequest m) => m () -> m () -- | Handle the end of every clip. Do whatever has to be done every fixed -- number of time units, e.g., monster generation. Advance time. Perform -- periodic saves, if applicable. endClip :: forall m. (MonadAtomic m, MonadServer m) => (FactionId -> m ()) -> m () -- | Trigger periodic items for all actors on the given level. applyPeriodicLevel :: (MonadAtomic m, MonadServer m) => m () handleTrajectories :: (MonadAtomic m, MonadServer m) => LevelId -> FactionId -> m () hTrajectories :: (MonadAtomic m, MonadServer m) => (ActorId, Actor) -> m () handleActors :: (MonadAtomic m, MonadServerReadRequest m) => LevelId -> FactionId -> m Bool hActors :: forall m. (MonadAtomic m, MonadServerReadRequest m) => FactionId -> [(ActorId, Actor)] -> m Bool gameExit :: (MonadAtomic m, MonadServerReadRequest m) => m () restartGame :: (MonadAtomic m, MonadServer m) => m () -> m () -> Maybe (GroupName ModeKind) -> m () -- | Save game on server and all clients. writeSaveAll :: (MonadAtomic m, MonadServer m) => Bool -> m () -- | Manage trajectory of a projectile. -- -- Colliding with a wall or actor doesn't take time, because the -- projectile does not move (the move is blocked). Not advancing time -- forces dead projectiles to be destroyed ASAP. Otherwise, with some -- timings, it can stay on the game map dead, blocking path of -- human-controlled actors and alarming the hapless human. setTrajectory :: (MonadAtomic m, MonadServer m) => ActorId -> m () -- | Semantics of requests that are sent to the server. -- -- See -- https://github.com/LambdaHack/LambdaHack/wiki/Client-server-architecture. module Game.LambdaHack.Server -- | Start a game session, including the clients, and then loop, -- communicating with the clients. loopSer :: (MonadAtomic m, MonadServerReadRequest m) => DebugModeSer -> Config -> (Maybe SessionUI -> FactionId -> ChanServer -> IO ()) -> m () -- | Parse server debug parameters from commandline arguments. debugArgs :: [String] -> DebugModeSer -- | Debug commands. See debugArgs for the descriptions. data DebugModeSer DebugModeSer :: Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Maybe (GroupName ModeKind) -> Bool -> Bool -> Maybe StdGen -> Maybe StdGen -> Bool -> Challenge -> Bool -> String -> Bool -> DebugModeCli -> DebugModeSer [sknowMap] :: DebugModeSer -> Bool [sknowEvents] :: DebugModeSer -> Bool [sknowItems] :: DebugModeSer -> Bool [sniffIn] :: DebugModeSer -> Bool [sniffOut] :: DebugModeSer -> Bool [sallClear] :: DebugModeSer -> Bool [sboostRandomItem] :: DebugModeSer -> Bool [sgameMode] :: DebugModeSer -> Maybe (GroupName ModeKind) [sautomateAll] :: DebugModeSer -> Bool [skeepAutomated] :: DebugModeSer -> Bool [sdungeonRng] :: DebugModeSer -> Maybe StdGen [smainRng] :: DebugModeSer -> Maybe StdGen [snewGameSer] :: DebugModeSer -> Bool [scurChalSer] :: DebugModeSer -> Challenge [sdumpInitRngs] :: DebugModeSer -> Bool [ssavePrefixSer] :: DebugModeSer -> String [sdbgMsgSer] :: DebugModeSer -> Bool [sdebugCli] :: DebugModeSer -> DebugModeCli -- | The main game action monad type implementation. Just as any other -- component of the library, this implementation can be substituted. This -- module should not be imported anywhere except in Action to -- expose the executor to any code using the library. module Game.LambdaHack.SampleImplementation.SampleMonadClient -- | Init the client, then run an action, with a given session, state and -- history, in the IO monad. executorCli :: KeyKind -> Config -> DebugModeCli -> COps -> Maybe SessionUI -> FactionId -> ChanServer -> IO () data CliState CliState :: State -> StateClient -> Maybe SessionUI -> ChanServer -> ChanSave (State, StateClient, Maybe SessionUI) -> CliState -- | current global state [cliState] :: CliState -> State -- | current client state [cliClient] :: CliState -> StateClient -- | UI state, empty for AI clients [cliSession] :: CliState -> Maybe SessionUI -- | this client connection information [cliDict] :: CliState -> ChanServer -- | connection to the save thread [cliToSave] :: CliState -> ChanSave (State, StateClient, Maybe SessionUI) -- | Client state transformation monad. newtype CliImplementation a CliImplementation :: StateT CliState IO a -> CliImplementation a [runCliImplementation] :: CliImplementation a -> StateT CliState IO a instance GHC.Base.Applicative Game.LambdaHack.SampleImplementation.SampleMonadClient.CliImplementation instance GHC.Base.Functor Game.LambdaHack.SampleImplementation.SampleMonadClient.CliImplementation instance GHC.Base.Monad Game.LambdaHack.SampleImplementation.SampleMonadClient.CliImplementation instance GHC.Generics.Generic Game.LambdaHack.SampleImplementation.SampleMonadClient.CliState instance Game.LambdaHack.Common.MonadStateRead.MonadStateRead Game.LambdaHack.SampleImplementation.SampleMonadClient.CliImplementation instance Game.LambdaHack.Atomic.MonadStateWrite.MonadStateWrite Game.LambdaHack.SampleImplementation.SampleMonadClient.CliImplementation instance Game.LambdaHack.Client.MonadClient.MonadClient Game.LambdaHack.SampleImplementation.SampleMonadClient.CliImplementation instance Game.LambdaHack.Client.MonadClient.MonadClientSetup Game.LambdaHack.SampleImplementation.SampleMonadClient.CliImplementation instance Game.LambdaHack.Client.UI.MonadClientUI.MonadClientUI Game.LambdaHack.SampleImplementation.SampleMonadClient.CliImplementation instance Game.LambdaHack.Client.HandleResponseM.MonadClientReadResponse Game.LambdaHack.SampleImplementation.SampleMonadClient.CliImplementation instance Game.LambdaHack.Client.HandleResponseM.MonadClientWriteRequest Game.LambdaHack.SampleImplementation.SampleMonadClient.CliImplementation instance Game.LambdaHack.Atomic.MonadAtomic.MonadAtomic Game.LambdaHack.SampleImplementation.SampleMonadClient.CliImplementation -- | The main game action monad type implementation. Just as any other -- component of the library, this implementation can be substituted. This -- module should not be imported anywhere except in Action to -- expose the executor to any code using the library. module Game.LambdaHack.SampleImplementation.SampleMonadServer -- | Run an action in the IO monad, with undefined state. executorSer :: COps -> KeyKind -> DebugModeSer -> IO () data SerState SerState :: State -> StateServer -> ConnServerDict -> ChanSave (State, StateServer) -> SerState -- | current global state [serState] :: SerState -> State -- | current server state [serServer] :: SerState -> StateServer -- | client-server connection information [serDict] :: SerState -> ConnServerDict -- | connection to the save thread [serToSave] :: SerState -> ChanSave (State, StateServer) -- | Server state transformation monad. newtype SerImplementation a SerImplementation :: StateT SerState IO a -> SerImplementation a [runSerImplementation] :: SerImplementation a -> StateT SerState IO a instance GHC.Base.Applicative Game.LambdaHack.SampleImplementation.SampleMonadServer.SerImplementation instance GHC.Base.Functor Game.LambdaHack.SampleImplementation.SampleMonadServer.SerImplementation instance GHC.Base.Monad Game.LambdaHack.SampleImplementation.SampleMonadServer.SerImplementation instance Game.LambdaHack.Common.MonadStateRead.MonadStateRead Game.LambdaHack.SampleImplementation.SampleMonadServer.SerImplementation instance Game.LambdaHack.Atomic.MonadStateWrite.MonadStateWrite Game.LambdaHack.SampleImplementation.SampleMonadServer.SerImplementation instance Game.LambdaHack.Server.MonadServer.MonadServer Game.LambdaHack.SampleImplementation.SampleMonadServer.SerImplementation instance Game.LambdaHack.Server.ProtocolM.MonadServerReadRequest Game.LambdaHack.SampleImplementation.SampleMonadServer.SerImplementation instance Game.LambdaHack.Atomic.MonadAtomic.MonadAtomic Game.LambdaHack.SampleImplementation.SampleMonadServer.SerImplementation