-- 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: -- --
-- breturn b a = [a | b] --breturn :: MonadPlus m => Bool -> a -> m a -- | 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 xD :: Double -> Double 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 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 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.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.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 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 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.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.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.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 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.Container 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 (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 to files, with serialization and compression. module Game.LambdaHack.Common.HSFile -- | 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: -- --
-- 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 -- | Maximal supported vector X and Y coordinates. maxVectorDim :: Int -- | Currently unused. _moveTexts :: [Text] longMoveTexts :: [Text] -- | Given a vector of arbitrary non-zero length, produce a unit vector -- that points in the same direction (in the chessboard metric). Of -- several equally good directions it picks one of those that visually -- (in the euclidean metric) maximally align with the original vector. normalize :: Double -> Double -> Vector normalizeVector :: Vector -> 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 -- | Our own encoding of modifiers. data Modifier NoModifier :: Modifier Shift :: Modifier Control :: Modifier Alt :: Modifier -- | Key and modifier. data KM KM :: Modifier -> Key -> KM [modifier] :: KM -> Modifier [key] :: KM -> Key -- | Key, modifier and position of mouse pointer. data KMP KMP :: KM -> Point -> KMP [kmpKeyMod] :: KMP -> KM [kmpPointer] :: KMP -> Point -- | Common and terse names for keys. showKey :: Key -> String -- | 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 dirAllKey :: Bool -> Bool -> [Key] -- | Configurable event handler for the direction keys. Used for directed -- commands such as close door. handleDir :: Bool -> Bool -> KM -> Maybe Vector -- | Binding of both sets of movement keys, vi and laptop. 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.org/en-US/docs/Web/API/KeyboardEvent/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 dirKeypadKey :: [Key] dirKeypadShiftChar :: [Char] dirKeypadShiftKey :: [Key] dirLaptopKey :: [Key] dirLaptopShiftKey :: [Key] dirViChar :: [Char] dirViKey :: [Key] dirViShiftKey :: [Key] dirMoveNoModifier :: Bool -> Bool -> [Key] dirRunNoModifier :: Bool -> Bool -> [Key] dirRunControl :: [Key] dirRunShift :: [Key] 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 -- | Screen frames and animations. module Game.LambdaHack.Client.UI.Frontend.Common -- | Raw frontend definition. The minimal closed set of values that need to -- depend on the specifics of the chosen frontend. data RawFrontend RawFrontend :: (SingleFrame -> IO ()) -> IO () -> MVar () -> TQueue KMP -> RawFrontend [fdisplay] :: RawFrontend -> SingleFrame -> IO () [fshutdown] :: RawFrontend -> IO () [fshowNow] :: RawFrontend -> MVar () [fchanKey] :: RawFrontend -> TQueue KMP 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 terminal text frontend based on stdin/stdout, intended for -- logging tests, but may be used on a teletype terminal, or with -- keyboard and printer. module Game.LambdaHack.Client.UI.Frontend.Teletype -- | Set up the frontend input and output. startup :: ClientOptions -> IO RawFrontend -- | The name of the frontend. frontendName :: String -- | Text frontend based on SDL2. module Game.LambdaHack.Client.UI.Frontend.Sdl -- | Set up and start the main loop providing input and output. -- -- Apparently some SDL backends are not thread-safe -- (https://wiki.libsdl.org/FAQDevelopment; "this should only be -- run in the thread that initialized the video subsystem, and for extra -- safety, you should consider only doing those things on the main thread -- in any case") so we stick to a single bound thread (but not to the -- main thread; enough is enough and at least in the case of OpenGL all -- bound threads are supposed to be as good as the main thread). startup :: ClientOptions -> IO RawFrontend -- | The name of the frontend. frontendName :: String type FontAtlas = EnumMap AttrCharW32 Texture -- | Session data maintained by the frontend. data FrontendSession FrontendSession :: Window -> Renderer -> Font -> IORef FontAtlas -> IORef Texture -> IORef SingleFrame -> IORef Bool -> IORef Bool -> MVar SingleFrame -> MVar () -> FrontendSession [swindow] :: FrontendSession -> Window [srenderer] :: FrontendSession -> Renderer [sfont] :: FrontendSession -> Font [satlas] :: FrontendSession -> IORef FontAtlas [stexture] :: FrontendSession -> IORef Texture [spreviousFrame] :: FrontendSession -> IORef SingleFrame [sforcedShutdown] :: FrontendSession -> IORef Bool [scontinueSdlLoop] :: FrontendSession -> IORef Bool [sframeQueue] :: FrontendSession -> MVar SingleFrame [sframeDrawn] :: FrontendSession -> MVar () startupFun :: ClientOptions -> MVar RawFrontend -> IO () shutdown :: FrontendSession -> IO () forceShutdown :: FrontendSession -> IO () -- | Add a frame to be drawn. display :: FrontendSession -> SingleFrame -> IO () drawFrame :: ClientOptions -> FrontendSession -> SingleFrame -> IO () -- | Translates modifiers to our own encoding, ignoring Shift. modTranslate :: KeyModifier -> Modifier keyTranslate :: Bool -> Keycode -> Key colorToRGBA :: Color -> V4 Word8 -- | 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.org/FAQDevelopment; "this should only be -- run in the thread that initialized the video subsystem, and for extra -- safety, you should consider only doing those things on the main thread -- in any case") so we stick to a single bound thread (but not to the -- main thread; enough is enough and at least in the case of OpenGL all -- bound threads are supposed to be as good as the main thread). startup :: ClientOptions -> 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, indexed by the -- returned value. 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 -- | Initialize the frontend chosen by the player via client options. chanFrontendIO :: ClientOptions -> IO ChanFrontend -- | The name of the chosen frontend. frontendName :: String -- | Machinery allocated for an individual frontend at its startup, -- unchanged for its lifetime. data FrontSetup getKey :: ClientOptions -> FrontSetup -> RawFrontend -> [KM] -> FrameForall -> IO KMP fchanFrontend :: ClientOptions -> FrontSetup -> 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 () -- | The type of kinds of weapons, treasure, organs, blasts, etc. 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. data Effect -- | secret (learned as effect) name of the item ELabel :: Text -> Effect -- | AI and UI flag that leaks item properties EqpSlot :: EqpSlot -> Effect -- | burn with this damage Burn :: Dice -> Effect -- | explode producing this group of blasts Explode :: (GroupName ItemKind) -> Effect -- | modify HP of the actor by this amount RefillHP :: Int -> Effect -- | modify Calm of the actor by this amount RefillCalm :: Int -> Effect -- | change actor's allegiance Dominate :: Effect -- | make actor susceptible to domination Impress :: Effect -- | summon the given number of actors of this group Summon :: (GroupName ItemKind) -> Dice -> Effect -- | ascend to another level of the dungeon Ascend :: Bool -> Effect -- | escape from the dungeon Escape :: Effect -- | paralyze for this many game clips Paralyze :: Dice -> Effect -- | give free time to actor of this many game turns InsertMove :: Dice -> Effect -- | teleport actor across rougly this distance 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 -- | make the actor drop items of the given group from the given store; the -- first integer says how many item kinds to drop, the second, how many -- copie of each kind to drop DropItem :: Int -> Int -> CStore -> (GroupName ItemKind) -> Effect -- | find a suitable (i.e., numerous enough) item, starting from the floor, -- and polymorph it randomly PolyItem :: Effect -- | find a suitable (i.e., not identified) item, starting from the floor, -- and identify it Identify :: Effect -- | detect all on the map in the given radius Detect :: Int -> Effect -- | detect actors on the map in the given radius DetectActor :: Int -> Effect -- | detect items on the map in the given radius DetectItem :: Int -> Effect -- | detect exits on the map in the given radius DetectExit :: Int -> Effect -- | detect hidden tiles on the map in the radius DetectHidden :: Int -> Effect -- | send an actor flying (push or pull, depending) SendFlying :: ThrowMod -> Effect -- | push an actor PushActor :: ThrowMod -> Effect -- | pull an actor PullActor :: ThrowMod -> Effect -- | make the actor drop its best weapon DropBestWeapon :: Effect -- | activate all items with this symbol in inventory; space character -- means all symbols ActivateInv :: Char -> Effect -- | remove all smell on the level ApplyPerfume :: Effect -- | trigger one of the effects with equal probability OneOf :: [Effect] -> Effect -- | trigger the effect when item smashed (not when 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 equipment, triggered as often as Timeout permits Periodic :: Effect -- | only fire next effect if previous was triggered Composite :: [Effect] -> Effect -- | Specification of how to randomly roll a timer at item creation to -- obtain a fixed timer for the item's lifetime. 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 when pushed or pulled) AddSpeed :: Dice -> Aspect -- | FOV radius, where 1 means a single tile FOV AddSight :: Dice -> Aspect -- | smell radius AddSmell :: Dice -> Aspect -- | shine radius AddShine :: Dice -> Aspect -- | noctovision radius AddNocto :: Dice -> Aspect -- | aggression, e.g., when 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. Publicly visible. 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 -- | AI and UI hints about the role of the item. 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 boostItemKindList :: StdGen -> [ItemKind] -> [ItemKind] -- | Whether the effect has a chance of exhibiting any potentially -- noticeable behaviour. 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] boostItemKind :: ItemKind -> ItemKind validateDups :: ItemKind -> Feature -> [Text] validateDamage :: [(Int, Dice)] -> [Text] hardwiredItemGroups :: [GroupName ItemKind] instance GHC.Show.Show Game.LambdaHack.Content.ItemKind.ItemKind instance GHC.Generics.Generic 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.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. -- -- In principle, it'se possible to have many rule sets and switch between -- them during a game session or even a single game. 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 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 -- | 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 isUknownSpace :: Id TileKind -> Bool unknownId :: Id TileKind isSuspectKind :: TileKind -> Bool isOpenableKind :: TileKind -> Bool isClosableKind :: TileKind -> Bool talterForStairs :: Word8 floorSymbol :: Char validateDups :: TileKind -> Feature -> [Text] hardwiredTileGroups :: [GroupName TileKind] 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 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 -> Text -> 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 may be 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 -- | cave description [cdesc] :: CaveKind -> Text -- | 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 -- | 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 -- | 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)] -- | 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 -- | Conditional polynomial representing score calculation for this player. type HiCondPoly = [HiSummand] type HiSummand = (HiPolynomial, [Outcome]) type HiPolynomial = [(HiIndeterminant, Double)] data HiIndeterminant HiConst :: HiIndeterminant HiLoot :: HiIndeterminant HiBlitz :: HiIndeterminant HiSurvival :: HiIndeterminant HiKill :: HiIndeterminant HiLoss :: HiIndeterminant -- | 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 -- | 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 -- | Catch invalid game mode kind definitions. validateSingleModeKind :: ModeKind -> [Text] -- | Validate game mode kinds together. validateAllModeKind :: [ModeKind] -> [Text] -- | Checks, in particular, that there is at least one faction with -- fneverEmpty or the game would get stuck as soon as the dungeon is -- devoid of actors. validateSingleRoster :: Caves -> Roster -> [Text] validateSinglePlayer :: Player -> [Text] hardwiredModeGroups :: [GroupName ModeKind] instance GHC.Show.Show Game.LambdaHack.Content.ModeKind.ModeKind instance GHC.Show.Show Game.LambdaHack.Content.ModeKind.Roster instance GHC.Generics.Generic 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 -- | The standard ruleset used for level operations. stdRuleset :: Ops RuleKind -> RuleKind -- | Create content operations for type a from definition of -- content of type a. createOps :: forall a. Show a => ContentDef a -> Ops a 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 speedup :: Bool -> Ops TileKind -> TileSpeedup -- | 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 alterMinSkill :: TileSpeedup -> Id TileKind -> Int alterMinWalk :: TileSpeedup -> Id TileKind -> Int -- | 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 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 -> Maybe (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 alterMinSkillKind :: Id TileKind -> TileKind -> Word8 alterMinWalkKind :: Id TileKind -> TileKind -> Word8 -- | Weapons, treasure and all the other items in the game. 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 -- | Price an item, taking count into consideration. itemPrice :: (Item, Int) -> Int isMelee :: Item -> Bool goesIntoEqp :: Item -> Bool goesIntoInv :: Item -> Bool goesIntoSha :: Item -> Bool -- | Record of sums of aspect values of an item, container, actor, etc. 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 -- | The map of item ids to item aspects. The full map is known by the -- server. type DiscoveryAspect = EnumMap ItemId AspectRecord emptyAspectRecord :: AspectRecord sumAspectRecord :: [(AspectRecord, Int)] -> AspectRecord aspectRecordToList :: AspectRecord -> [Aspect] meanAspect :: ItemKind -> AspectRecord -- | An index of the kind identifier of an item. Clients have partial -- knowledge how these idexes map to kind ids. They gain knowledge by -- identifying items. The indexes and kind identifiers are 1-1. 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 -- | The secret part of the information about an item. If a faction knows -- the aspects of the item (the itemAspect field is not empty), -- this is a complete secret information/. data ItemDisco ItemDisco :: Id ItemKind -> ItemKind -> AspectRecord -> Bool -> Maybe AspectRecord -> ItemDisco [itemKindId] :: ItemDisco -> Id ItemKind [itemKind] :: ItemDisco -> ItemKind [itemAspectMean] :: ItemDisco -> AspectRecord [itemConst] :: ItemDisco -> Bool [itemAspect] :: ItemDisco -> Maybe AspectRecord -- | Full information about an item. data ItemFull ItemFull :: Item -> Int -> ItemTimer -> Maybe ItemDisco -> ItemFull [itemBase] :: ItemFull -> Item [itemK] :: ItemFull -> Int [itemTimer] :: ItemFull -> ItemTimer [itemDisco] :: ItemFull -> Maybe ItemDisco -- | Partial information about item kinds. These are assigned to each -- ItemKindIx. There is an item kinda, mean aspect value computed -- (and here cached) for items of that kind and a flag saying whether the -- item's aspects are constant rather than random or dependent on dungeon -- level where the item is created. data KindMean KindMean :: Id ItemKind -> AspectRecord -> Bool -> KindMean [kmKind] :: KindMean -> Id ItemKind [kmMean] :: KindMean -> AspectRecord [kmConst] :: KindMean -> Bool -- | 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 -- | The map of item kind indexes to identifiers of items that have that -- kind. type ItemIxMap = EnumMap ItemKindIx [ItemId] -- | 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 -> ~Double -> ~Double -> ~Double -> ~Double -> Benefit [benInEqp] :: Benefit -> ~Bool [benPickup] :: Benefit -> ~Double [benApply] :: Benefit -> ~Double [benMelee] :: Benefit -> ~Double [benFling] :: Benefit -> ~Double type DiscoveryBenefit = EnumMap ItemId Benefit itemNoDisco :: (Item, Int) -> ItemFull itemToFull6 :: COps -> DiscoveryKind -> DiscoveryAspect -> ItemId -> Item -> ItemQuant -> ItemFull aspectsRandom :: ItemKind -> Bool seedToAspect :: ItemSeed -> ItemKind -> AbsDepth -> AbsDepth -> AspectRecord aspectRecordFull :: ItemFull -> AspectRecord type ItemTimer = [Time] -- | Number of items in a bag, together with recharging timer, in case of -- items that need recharging, exists only temporarily or auto-activate -- at regular intervals. type ItemQuant = (Int, ItemTimer) -- | A bag of items, e.g., one of the stores of an actor or the items on a -- particular floor position or embedded in a particular map tile. type ItemBag = EnumMap ItemId ItemQuant -- | All items in the dungeon (including in actor inventories), indexed by -- item identifier. type ItemDict = EnumMap ItemId Item castAspect :: AbsDepth -> AbsDepth -> AspectRecord -> Aspect -> Rnd AspectRecord addMeanAspect :: AspectRecord -> Aspect -> AspectRecord ceilingMeanDice :: Dice -> Int instance GHC.Show.Show Game.LambdaHack.Common.Item.ItemFull instance GHC.Generics.Generic Game.LambdaHack.Common.Item.Benefit instance GHC.Show.Show Game.LambdaHack.Common.Item.Benefit 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.Show.Show Game.LambdaHack.Common.Item.ItemDisco 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.Item instance GHC.Classes.Eq Game.LambdaHack.Common.Item.Item instance GHC.Show.Show Game.LambdaHack.Common.Item.Item 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 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.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.Binary.Class.Binary Game.LambdaHack.Common.Item.Benefit instance Data.Binary.Class.Binary Game.LambdaHack.Common.Item.KindMean 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.AspectRecord instance Data.Hashable.Class.Hashable Game.LambdaHack.Common.Item.AspectRecord -- | Determining the strongest item wrt some property. module Game.LambdaHack.Common.ItemStrongest strengthEffect :: (Effect -> [b]) -> ItemFull -> [b] strengthOnSmash :: ItemFull -> [Effect] strengthCreateOrgan :: ItemFull -> [GroupName ItemKind] strengthDropOrgan :: ItemFull -> [GroupName ItemKind] strengthEqpSlot :: ItemFull -> Maybe EqpSlot strengthToThrow :: Item -> ThrowMod strongestSlot :: DiscoveryBenefit -> EqpSlot -> [(ItemId, ItemFull)] -> [(Int, (ItemId, ItemFull))] computeTrajectory :: Int -> Int -> Int -> [Point] -> ([Vector], (Speed, Int)) itemTrajectory :: Item -> [Point] -> ([Vector], (Speed, Int)) totalRange :: Item -> Int hasCharge :: Time -> ItemFull -> Bool damageUsefulness :: Item -> Double strongestMelee :: Maybe DiscoveryBenefit -> Time -> [(ItemId, ItemFull)] -> [(Double, (ItemId, ItemFull))] prEqpSlot :: EqpSlot -> AspectRecord -> Int unknownMeleeBonus :: [ItemFull] -> Bool filterRecharging :: [Effect] -> [Effect] stripRecharging :: [Effect] -> [Effect] stripOnSmash :: [Effect] -> [Effect] unknownAspect :: (Aspect -> [Dice]) -> ItemFull -> Bool -- | Possible causes of failure of request. module Game.LambdaHack.Common.ReqFailure -- | Possible causes of failure of request. 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 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 permittedPreciousAI :: Bool -> ItemFull -> Bool instance GHC.Generics.Generic Game.LambdaHack.Common.ReqFailure.ReqFailure instance GHC.Classes.Eq Game.LambdaHack.Common.ReqFailure.ReqFailure instance GHC.Show.Show Game.LambdaHack.Common.ReqFailure.ReqFailure instance Data.Binary.Class.Binary Game.LambdaHack.Common.ReqFailure.ReqFailure -- | Actors in the game: heroes, monsters, etc. module Game.LambdaHack.Common.Actor -- | A unique identifier of an actor in the dungeon. data ActorId -- | Actor properties that are changing throughout the game. If they appear -- dublets of properties of actor kinds, e.g. HP, they may be results of -- casting the dice specified in their respective actor kind and/or may -- be modified temporarily, but return to the original value from their -- respective kind over time. data Actor Actor :: ItemId -> Int64 -> ResDelta -> Int64 -> ResDelta -> Point -> Maybe Point -> LevelId -> FactionId -> Maybe ([Vector], Speed) -> ItemBag -> ItemBag -> ItemBag -> Int -> Bool -> Bool -> Actor -- | the trunk organ of the actor's body [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 -- | Whether an actor is braced for combat this clip. braced :: Actor -> Bool actorTemplate :: ItemId -> Int64 -> Int64 -> Point -> LevelId -> FactionId -> Actor waitedLastTurn :: Actor -> Bool actorDying :: Actor -> Bool actorTrunkIsBlast :: Item -> Bool hpTooLow :: Actor -> AspectRecord -> Bool calmEnough :: Actor -> AspectRecord -> Bool hpEnough :: Actor -> AspectRecord -> Bool checkAdjacent :: Actor -> Actor -> Bool eqpOverfull :: Actor -> Int -> Bool eqpFreeN :: Actor -> Int -- | All actors on the level, indexed by actor identifier. type ActorDict = EnumMap ActorId Actor -- | 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 -- | How long until an actor's smell vanishes from a tile. smellTimeout :: Delta Time 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 identifiers to levels. type Dungeon = EnumMap LevelId Level -- | Levels in the current branch, one level up (or down) from 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) -- | 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 -- | 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 -> ([Point], [Point]) -> Int -> Int -> Time -> Int -> Freqs ItemKind -> Int -> Freqs ItemKind -> [Point] -> Bool -> Text -> Text -> Level -- | absolute depth of the level [ldepth] :: Level -> AbsDepth -- | remembered items lying on the floor [lfloor] :: Level -> ItemFloor -- | remembered 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 -- | 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] -- | whether the level is covered in darkness [lnight] :: Level -> Bool -- | level name [lname] :: Level -> Text -- | level description [ldesc] :: Level -> Text updateFloor :: (ItemFloor -> ItemFloor) -> Level -> Level updateEmbed :: (ItemFloor -> ItemFloor) -> Level -> Level updateActorMap :: (ActorMap -> ActorMap) -> Level -> Level updateTile :: (TileMap -> TileMap) -> Level -> Level updateSmell :: (SmellMap -> SmellMap) -> Level -> Level -- | 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 assertSparseItems :: ItemFloor -> ItemFloor assertSparseActors :: ActorMap -> ActorMap 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. 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 slotToSentence :: EqpSlot -> Text slotToName :: EqpSlot -> Text slotToDesc :: EqpSlot -> Text slotToDecorator :: EqpSlot -> Actor -> Int -> Text statSlots :: [EqpSlot] kindAspectToSuffix :: Aspect -> Text featureToSuff :: Feature -> Text featureToSentence :: Feature -> Maybe Text affixDice :: Dice -> Text tmodToSuff :: Text -> ThrowMod -> Text affixBonus :: Int -> Text wrapInParens :: Text -> Text wrapInChevrons :: Text -> Text -- | Factions taking part in the game, e.g., a hero faction, a monster -- faction and an animal faction. 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 -- | The faction datatype. 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 -- | The goal of an actor. data TGoal -- | last seen position of the targeted actor TEnemyPos :: ActorId -> Bool -> TGoal -- | embedded item that can be triggered; in TPoint (TEmbed bag p) _ -- q usually bag is embbedded in p and q -- is an adjacent open tile TEmbed :: ItemBag -> Point -> TGoal -- | item lying on the ground TItem :: ItemBag -> TGoal -- | smell potentially left by enemies TSmell :: TGoal -- | an unknown tile to be explored TUnknown :: TGoal -- | a known tile to be patrolled TKnown :: TGoal -- | an unspecified goal 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 gleader :: Faction -> Maybe ActorId 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.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 -- | Actors perceiving other actors and the dungeon level. -- -- Visibility works according to KISS. Everything that player sees is -- real. There are no unmarked hidden tiles and only solid tiles can be -- marked, so there are no invisible walls and to pass through an -- illusory wall, you have to use a turn bumping into it first. Only -- tiles marked with Suspect can turn out to be another tile. (So, if all -- tiles are marked with Suspect, the player knows nothing for sure, but -- this should be avoided, because searching becomes too time-consuming.) -- Each actor sees adjacent tiles, even when blind, so adjacent tiles are -- known, so the actor can decide accurately whether to pass thorugh or -- alter, etc. -- -- Items are always real and visible. Actors are real, but can be -- invisible. Invisible actors in walls can't be hit, but are hinted at -- when altering the tile, so the player can flee or block. Invisible -- actors in open space can be hit. module Game.LambdaHack.Common.Perception -- | 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 -- | The list of scores, in decreasing order. data ScoreTable -- | A dictionary from game mode IDs to scores tables. type ScoreDict = EnumMap (Id ModeKind) 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 -- | Insert a new score into the table, Return new table and the ranking. -- Make sure the table doesn't grow too large. insertPos :: ScoreRecord -> ScoreTable -> (ScoreTable, Int) -- | Show a screenful of the high scores table. Parameter height is the -- number of (3-line) scores to be shown. showTable :: TimeZone -> ScoreTable -> Int -> Int -> [Text] -- | Produce a couple of renderings of the high scores table. showNearbyScores :: TimeZone -> Int -> ScoreTable -> Int -> [[Text]] 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.Classes.Ord Game.LambdaHack.Common.HighScore.ScoreRecord instance GHC.Classes.Eq Game.LambdaHack.Common.HighScore.ScoreRecord instance GHC.Show.Show Game.LambdaHack.Common.HighScore.ScoreRecord instance GHC.Show.Show Game.LambdaHack.Common.HighScore.ScoreTable instance Data.Binary.Class.Binary Game.LambdaHack.Common.HighScore.ScoreRecord -- | The common server and client basic game state type and its operations. module Game.LambdaHack.Common.State -- | View on the basic game state. The remembered fields, in -- client copies of the state, carry only a subset of the full -- information that the server keeps. Clients never directly change their -- State, but apply atomic actions sent by the server to do so -- (and/or the server applies the actions to each client state in turn). data State sdungeon :: State -> Dungeon stotalDepth :: State -> AbsDepth sactorD :: State -> ActorDict sitemD :: State -> ItemDict sitemIxMap :: State -> ItemIxMap sfactionD :: State -> FactionDict stime :: State -> Time scops :: State -> COps shigh :: State -> ScoreDict sgameModeId :: State -> Id ModeKind sdiscoKind :: State -> DiscoveryKind sdiscoAspect :: State -> DiscoveryAspect sactorAspect :: State -> ActorAspect -- | Initial complete global game state. defStateGlobal :: Dungeon -> AbsDepth -> FactionDict -> COps -> ScoreDict -> Id ModeKind -> DiscoveryKind -> 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 the item kind index map. updateItemIxMap :: (ItemIxMap -> ItemIxMap) -> 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 updateDiscoKind :: (DiscoveryKind -> DiscoveryKind) -> State -> State updateDiscoAspect :: (DiscoveryAspect -> DiscoveryAspect) -> State -> State updateActorAspect :: (ActorAspect -> ActorAspect) -> State -> State getItemBody :: ItemId -> State -> Item aspectRecordFromItem :: ItemId -> Item -> State -> AspectRecord aspectRecordFromIid :: ItemId -> State -> AspectRecord aspectRecordFromActor :: Actor -> State -> AspectRecord actorAspectInDungeon :: State -> ActorAspect unknownLevel :: COps -> AbsDepth -> X -> Y -> Text -> Text -> ([Point], [Point]) -> Int -> [Point] -> Bool -> Level unknownTileMap :: Id TileKind -> Int -> Int -> TileMap 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 itemDesc :: FactionId -> FactionDict -> Int -> CStore -> Time -> ItemFull -> AttrLine show64With2 :: Int64 -> Text -- | The part of speech describing the item parameterized by the number of -- effects/aspects to show.. partItemN :: FactionId -> FactionDict -> Bool -> Int -> Int -> CStore -> Time -> ItemFull -> (Bool, Bool, Part, Part) textAllAE :: Int -> Bool -> CStore -> ItemFull -> ([Text], [Text]) partItemWsR :: FactionId -> FactionDict -> Bool -> Int -> CStore -> Time -> ItemFull -> Part -- | 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 tryFindActor :: State -> (ActorId -> Actor -> Bool) -> Maybe (ActorId, Actor) 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 -- | Abstract syntax of requests. -- -- See -- https://github.com/LambdaHack/LambdaHack/wiki/Client-server-architecture. module Game.LambdaHack.Client.Request -- | Requests sent by AI clients to the server. If faction leader is to be -- changed, it's included as the second component. type RequestAI = (ReqAI, Maybe ActorId) -- | Possible forms of requests sent by AI clients. data ReqAI ReqAINop :: ReqAI ReqAITimed :: RequestAnyAbility -> ReqAI -- | Requests sent by UI clients to the server. If faction leader is to be -- changed, it's included as the second component. type RequestUI = (ReqUI, Maybe ActorId) -- | Possible forms of 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 -- | Basic form of requests, sent by both AI and UI clients to the server. data RequestAnyAbility RequestAnyAbility :: (RequestTimed a) -> RequestAnyAbility -- | Requests that take game time, indexed by actor ability that is needed -- for performing the corresponding actions. 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 instance GHC.Show.Show Game.LambdaHack.Client.Request.ReqAI instance GHC.Show.Show Game.LambdaHack.Client.Request.ReqUI instance GHC.Show.Show Game.LambdaHack.Client.Request.RequestAnyAbility instance GHC.Show.Show (Game.LambdaHack.Client.Request.RequestTimed a) -- | Actor preferences for targets and actions, based on actor attributes. module Game.LambdaHack.Client.Preferences -- | Compute the whole Benefit structure, containing various facets -- of AI item preference, for an item with the given effects and aspects. -- -- Note: result has non-strict fields, so arguments are forced to avoid -- leaks. When AI looks at items (including organs) more often, force the -- fields. 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 -> (Double, Double) averageTurnValue :: Double avgItemDelay :: Double avgItemLife :: Double durabilityMult :: Double organBenefit :: Double -> GroupName ItemKind -> COps -> Faction -> (Double, Int) recBenefit :: GroupName ItemKind -> COps -> Faction -> (Double, Int) fakeItem :: ItemKind -> Item aspectToBenefit :: Aspect -> Double recordToBenefit :: AspectRecord -> [Double] -- | Operations on the Actor type, and related, 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))] posToAidsLvl :: Point -> Level -> [ActorId] posToAids :: Point -> LevelId -> State -> [ActorId] posToAssocs :: Point -> LevelId -> State -> [(ActorId, Actor)] nearbyFreePoints :: (Id TileKind -> Bool) -> Point -> LevelId -> State -> [Point] -- | Calculate loot's worth for a given faction. calculateTotal :: FactionId -> State -> (ItemBag, Int) mergeItemQuant :: ItemQuant -> ItemQuant -> ItemQuant sharedInv :: FactionId -> State -> ItemBag sharedEqp :: FactionId -> State -> ItemBag sharedAllOwned :: FactionId -> State -> ItemBag sharedAllOwnedFid :: Bool -> FactionId -> State -> ItemBag findIid :: ActorId -> FactionId -> ItemId -> State -> [(ActorId, (Actor, CStore))] getActorBody :: ActorId -> State -> Actor getActorAspect :: ActorId -> State -> AspectRecord getCarriedAssocs :: Actor -> State -> [(ItemId, Item)] getCarriedIidCStore :: Actor -> [(ItemId, 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)] getActorAssocsK :: ActorId -> CStore -> State -> [(ItemId, (Item, ItemQuant))] -- | 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 -- | 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 -> State -> Skills dispEnemy :: ActorId -> ActorId -> Skills -> State -> Bool itemToFull :: State -> ItemId -> ItemQuant -> ItemFull fullAssocs :: ActorId -> [CStore] -> State -> [(ItemId, ItemFull)] storeFromC :: Container -> CStore aidFromC :: Container -> Maybe ActorId -- | 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 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 :: ActorId -> ActorId -> State -> Int inMelee :: Actor -> State -> Bool -- | Game state reading monad and basic operations. module Game.LambdaHack.Common.MonadStateRead -- | Monad for reading game state. A state monad with state modification -- disallowed (another constraint is needed to permit that). The basic -- server and client monads are like that, because server and clients -- freely modify their internal session data, but don't modify the main -- game state, except in very restricted and synchronized way. 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 -> ActorId -> m [(Double, (ItemId, ItemFull))] -- | Item slots for UI and AI item collections. module Game.LambdaHack.Client.UI.ItemSlot -- | Slot label. Usually just a character. Sometimes with a numerical -- prefix. data SlotChar SlotChar :: Int -> Char -> SlotChar [slotPrefix] :: SlotChar -> Int [slotChar] :: SlotChar -> Char -- | Mapping from slot labels to item identifiers. data ItemSlots ItemSlots :: EnumMap SlotChar ItemId -> EnumMap SlotChar ItemId -> ItemSlots [itemSlots] :: ItemSlots -> EnumMap SlotChar ItemId [organSlots] :: ItemSlots -> EnumMap SlotChar ItemId 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 -- | A key or an item slot label at a given position on the screen. type KYX = (Either [KM] SlotChar, (Y, X, X)) -- | An Overlay of text with an associated list of keys or slots that -- activated when the specified screen position is pointed at. The list -- should be sorted wrt rows and then columns. type OKX = (Overlay, [KYX]) -- | A list of active screenfulls to be shown one after another. Each -- screenful has an independent numbering of rows and columns. 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] moreMsg :: String endMsg :: String keysOKX :: Y -> X -> X -> [KM] -> 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 main game state. module Game.LambdaHack.Atomic.MonadStateWrite -- | The monad for writing to the main game state. Atomic updates -- (UpdAtomic) are given semantics in this monad. class MonadStateRead m => MonadStateWrite m modifyState :: MonadStateWrite m => (State -> State) -> m () -- | Exception signifying that atomic action failed because the information -- it carries is inconsistent with the client's state, (e.g., because the -- client knows too little to understand the command or already deduced -- the state change from earlier commands or is confused, amnesiac or -- sees illusory actors or tiles). Whenever we know the failure is -- logically impossible, we don't throw the AtomicFail -- exception, but insert a normal assertion or error call, which -- are never caught nor handled. newtype AtomicFail AtomicFail :: String -> AtomicFail atomicFail :: String -> a putState :: MonadStateWrite m => State -> m () updateLevel :: MonadStateWrite m => LevelId -> (Level -> Level) -> m () updateActor :: MonadStateWrite m => ActorId -> (Actor -> Actor) -> m () updateFaction :: MonadStateWrite m => FactionId -> (Faction -> Faction) -> m () moveActorMap :: MonadStateWrite m => ActorId -> Actor -> Actor -> m () insertBagContainer :: MonadStateWrite m => ItemBag -> Container -> m () insertItemContainer :: MonadStateWrite m => ItemId -> ItemQuant -> Container -> m () insertItemActor :: MonadStateWrite m => ItemId -> ItemQuant -> ActorId -> CStore -> m () deleteBagContainer :: MonadStateWrite m => ItemBag -> Container -> m () deleteItemContainer :: MonadStateWrite m => ItemId -> ItemQuant -> Container -> m () deleteItemActor :: MonadStateWrite m => ItemId -> ItemQuant -> ActorId -> CStore -> m () addAis :: MonadStateWrite m => [(ItemId, Item)] -> m () itemsMatch :: Item -> Item -> Bool addItemToActor :: MonadStateWrite m => ItemId -> Item -> Int -> ActorId -> m () resetActorAspect :: MonadStateWrite m => m () insertItemFloor :: MonadStateWrite m => ItemId -> ItemQuant -> LevelId -> Point -> m () insertItemEmbed :: MonadStateWrite m => ItemId -> ItemQuant -> LevelId -> Point -> m () insertItemOrgan :: MonadStateWrite m => ItemId -> ItemQuant -> ActorId -> m () insertItemEqp :: MonadStateWrite m => ItemId -> ItemQuant -> ActorId -> m () insertItemInv :: MonadStateWrite m => ItemId -> ItemQuant -> ActorId -> m () insertItemSha :: MonadStateWrite m => ItemId -> ItemQuant -> FactionId -> m () deleteItemFloor :: MonadStateWrite m => ItemId -> ItemQuant -> LevelId -> Point -> m () deleteItemEmbed :: MonadStateWrite m => ItemId -> ItemQuant -> LevelId -> Point -> m () deleteItemOrgan :: MonadStateWrite m => ItemId -> ItemQuant -> ActorId -> m () deleteItemEqp :: MonadStateWrite m => ItemId -> ItemQuant -> ActorId -> m () deleteItemInv :: MonadStateWrite m => ItemId -> ItemQuant -> ActorId -> m () deleteItemSha :: MonadStateWrite m => ItemId -> ItemQuant -> FactionId -> m () rmFromBag :: ItemQuant -> ItemId -> ItemBag -> ItemBag instance GHC.Show.Show Game.LambdaHack.Atomic.MonadStateWrite.AtomicFail instance GHC.Exception.Exception Game.LambdaHack.Atomic.MonadStateWrite.AtomicFail -- | Abstract syntax of 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 -- | Symbolic representation of areas of the screen used to define the -- meaning of mouse button presses relative to where the mouse points to. 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 -- | This triple of command categories, description and the command term -- itself defines the meaning of a human command as entered via a -- keypress, mouse click or chosen from a menu. type CmdTriple = ([CmdCategory], Text, HumanCmd) -- | Abstract syntax of human 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 -- | Description of how item manipulation is triggered and communicated to -- the player. 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 -- | UI client options. module Game.LambdaHack.Client.UI.UIOptions -- | Options that affect the UI of the client. data UIOptions UIOptions :: [(KM, CmdTriple)] -> [(Int, (Text, Text))] -> Bool -> Bool -> Text -> Text -> Int -> Int -> Int -> Bool -> Int -> Int -> Bool -> Bool -> [String] -> UIOptions [uCommands] :: UIOptions -> [(KM, CmdTriple)] [uHeroNames] :: UIOptions -> [(Int, (Text, Text))] -- | the option for Vi keys takes precendence [uVi] :: UIOptions -> Bool -- | because the laptop keys are the default [uLaptop] :: UIOptions -> Bool [uGtkFontFamily] :: UIOptions -> Text [uSdlFontFile] :: UIOptions -> Text [uSdlTtfSizeAdd] :: UIOptions -> Int [uSdlFonSizeAdd] :: UIOptions -> Int [uFontSize] :: UIOptions -> Int [uColorIsBold] :: UIOptions -> Bool [uHistoryMax] :: UIOptions -> Int [uMaxFps] :: UIOptions -> Int [uNoAnim] :: UIOptions -> Bool [uRunStopMsgs] :: UIOptions -> Bool -- | Hardwired commandline arguments to process. [uCmdline] :: UIOptions -> [String] -- | Read and parse UI config file. mkUIOptions :: COps -> Bool -> IO UIOptions -- | Modify client options with UI options. applyUIOptions :: COps -> UIOptions -> ClientOptions -> ClientOptions parseConfig :: Config -> UIOptions instance GHC.Generics.Generic Game.LambdaHack.Client.UI.UIOptions.UIOptions instance GHC.Show.Show Game.LambdaHack.Client.UI.UIOptions.UIOptions instance Control.DeepSeq.NFData Game.LambdaHack.Client.UI.UIOptions.UIOptions instance Data.Binary.Class.Binary Game.LambdaHack.Client.UI.UIOptions.UIOptions -- | The type of definitions of key-command mappings to be used for the UI -- and shorthands for specifying command triples in the content files. module Game.LambdaHack.Client.UI.Content.KeyKind -- | Key-command mappings to be specified in content and used for the UI. newtype KeyKind -- | default client UI commands KeyKind :: [(KM, CmdTriple)] -> KeyKind 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] applyIK :: [Trigger] -> CmdTriple applyI :: [Trigger] -> CmdTriple grabItems :: Text -> CmdTriple dropItems :: Text -> CmdTriple descTs :: [Trigger] -> Text defaultHeroSelect :: Int -> (String, CmdTriple) replaceCmd :: HumanCmd -> CmdTriple -> CmdTriple projectICmd :: [Trigger] -> HumanCmd grabCmd :: HumanCmd dropCmd :: HumanCmd -- | Verifying, aggregating and displaying binding of keys to commands. 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] -- | Create binding of keys to movement and other standard commands, as -- well as commands defined in the config file. stdBinding :: KeyKind -> UIOptions -> Binding -- | Produce a set of help/menu screens from the key bindings. keyHelp :: Binding -> Int -> [(Text, OKX)] -- | Turn the specified portion of bindings into a menu. 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 the frontend session. data SessionUI SessionUI :: Target -> ActorDictUI -> ItemSlots -> SlotChar -> Maybe (CStore, CStore) -> ChanFrontend -> Binding -> UIOptions -> 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 -- | UI options as set by the player [sUIOptions] :: SessionUI -> UIOptions -- | 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 -- | current level needs displaying [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 -- | 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 -- | State of last recorded and currently being recorded key sequences. data LastRecord LastRecord :: [KM] -> [KM] -> Int -> LastRecord -- | accumulated keys of the current command [currentKeys] :: LastRecord -> [KM] -- | keys of the rest of the recorded command batch [previousKeys] :: LastRecord -> [KM] -- | space left for commands to record in this batch [freeSpace] :: LastRecord -> Int data KeysHintMode KeysHintBlocked :: KeysHintMode KeysHintAbsent :: KeysHintMode KeysHintPresent :: KeysHintMode sreport :: SessionUI -> Report emptySessionUI :: UIOptions -> SessionUI 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 it 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 UpdSpotItemBag :: Container -> ItemBag -> [(ItemId, Item)] -> UpdAtomic UpdLoseItemBag :: Container -> ItemBag -> [(ItemId, Item)] -> 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 -> ItemKindIx -> (Id ItemKind) -> UpdAtomic UpdCoverKind :: Container -> ItemKindIx -> (Id ItemKind) -> UpdAtomic UpdDiscoverSeed :: Container -> ItemId -> ItemSeed -> UpdAtomic UpdCoverSeed :: Container -> ItemId -> ItemSeed -> UpdAtomic UpdDiscoverServer :: ItemId -> AspectRecord -> UpdAtomic UpdCoverServer :: ItemId -> AspectRecord -> UpdAtomic UpdPerception :: LevelId -> Perception -> Perception -> UpdAtomic UpdRestart :: FactionId -> PerLid -> State -> Challenge -> ClientOptions -> UpdAtomic UpdRestartServer :: State -> UpdAtomic UpdResume :: FactionId -> PerLid -> UpdAtomic UpdResumeServer :: State -> UpdAtomic UpdKillExit :: FactionId -> UpdAtomic UpdWriteSave :: UpdAtomic -- | Abstract syntax of atomic special effects, that is, atomic commands -- that only display special effects and don't change 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 SfxSortSlots :: SfxAtomic -- | Symbolic representation of text messages sent by server to clients and -- shown to players. 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 :: 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 -- | Representation and computation of visiblity of atomic commands by -- clients. -- -- 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, server doesn't 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 or, more -- generally, the conditions under which the update can be noticed by a -- client. -- -- The goal of this mechanics is to ensure that atomic commands involving -- some positions visible by a client convey similar information as the -- client would get by directly observing the changes of the portion of -- server state limited to the visible positions. Consequently, when the -- visible commands are later applied to the client's state, the state -- stays consistent --- in sync with the server state and correctly -- limited by visiblity. There is some wiggle room both in what "in sync" -- and "visible" means and how they propagate through time. -- -- E.g., UpdDisplaceActor in a black room between two enemy -- actors, with only 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 in similar cotext would 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 that is outside a client's visiblity. The -- decomposed actions give less information that the original command, -- but some of them may fall within the visibility range of the client. -- The original action may give more information than even the total sum -- of all actions it's broken into. E.g., UpdMoveActor informs -- about the continued existence of the actor between moves vs popping -- out of existence and then back in. -- -- This is computed in server's State from before performing the -- command. breakUpdAtomic :: MonadStateRead m => UpdAtomic -> m [UpdAtomic] -- | Given the client, its perception and an atomic command, determine if -- the client notices the command. seenAtomicCli :: Bool -> FactionId -> Perception -> PosAtomic -> Bool -- | Determine whether the server would see a command that has the given -- visibilty conditions. seenAtomicSer :: PosAtomic -> Bool posProjBody :: Actor -> PosAtomic singleAid :: MonadStateRead m => ActorId -> m PosAtomic doubleAid :: MonadStateRead m => ActorId -> ActorId -> m PosAtomic singleContainer :: MonadStateRead m => Container -> m PosAtomic instance GHC.Classes.Eq Game.LambdaHack.Atomic.PosAtomicRead.PosAtomic instance GHC.Show.Show Game.LambdaHack.Atomic.PosAtomicRead.PosAtomic -- | 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. There is no -- corresponding definition for special effects (SfxAtomic), -- because they don't modify State. -- -- For each of the commands, we are guaranteed that the client, the -- command is addressed to, perceives all the positions the command -- affects (as computed by posUpdAtomic). In the code for each -- semantic function we additonally verify the client is aware of any -- relevant items and/or actors and we throw the AtomicFail -- exception if it's not. The server keeps copies of all clients' states -- and, before sending a command to a client, applies it to the client's -- state copy. If AtomicFail is signalled, the command is -- ignored for that client. This enables simpler server code that -- addresses commands to all clients that can see it, even though not all -- are able to process it. handleUpdAtomic :: MonadStateWrite m => UpdAtomic -> m () updCreateActor :: MonadStateWrite m => ActorId -> Actor -> [(ItemId, Item)] -> m () updDestroyActor :: MonadStateWrite m => ActorId -> Actor -> [(ItemId, Item)] -> m () updCreateItem :: MonadStateWrite m => ItemId -> Item -> ItemQuant -> Container -> m () updDestroyItem :: MonadStateWrite m => ItemId -> Item -> ItemQuant -> Container -> m () updSpotItemBag :: MonadStateWrite m => Container -> ItemBag -> [(ItemId, Item)] -> m () updLoseItemBag :: MonadStateWrite m => Container -> ItemBag -> [(ItemId, Item)] -> 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 () updRecordKill :: MonadStateWrite m => ActorId -> Id ItemKind -> Int -> m () updAlterTile :: MonadStateWrite m => LevelId -> Point -> Id TileKind -> Id TileKind -> m () updAlterExplorable :: MonadStateWrite m => LevelId -> Int -> m () updSearchTile :: MonadStateWrite m => ActorId -> Point -> Id TileKind -> 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 () updAgeGame :: MonadStateWrite m => [LevelId] -> m () updUnAgeGame :: MonadStateWrite m => [LevelId] -> m () ageLevel :: MonadStateWrite m => Delta Time -> LevelId -> m () updDiscover :: MonadStateWrite m => Container -> ItemId -> Id ItemKind -> ItemSeed -> m () updCover :: Container -> ItemId -> Id ItemKind -> ItemSeed -> m () updDiscoverKind :: MonadStateWrite m => Container -> ItemKindIx -> Id ItemKind -> m () discoverKind :: MonadStateWrite m => ItemKindIx -> Id ItemKind -> m KindMean updCoverKind :: Container -> ItemKindIx -> Id ItemKind -> m () updDiscoverSeed :: MonadStateWrite m => Container -> ItemId -> ItemSeed -> m () discoverSeed :: MonadStateWrite m => ItemId -> ItemSeed -> m () updCoverSeed :: Container -> ItemId -> ItemSeed -> m () updDiscoverServer :: MonadStateWrite m => ItemId -> AspectRecord -> m () updCoverServer :: MonadStateWrite m => ItemId -> AspectRecord -> m () updRestart :: MonadStateWrite m => State -> m () updRestartServer :: MonadStateWrite m => State -> m () updResumeServer :: MonadStateWrite m => State -> m () -- | Atomic game state transformations, their representation and semantics. -- -- See -- https://github.com/LambdaHack/LambdaHack/wiki/Client-server-architecture. module Game.LambdaHack.Atomic -- | 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 it 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 UpdSpotItemBag :: Container -> ItemBag -> [(ItemId, Item)] -> UpdAtomic UpdLoseItemBag :: Container -> ItemBag -> [(ItemId, Item)] -> 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 -> ItemKindIx -> (Id ItemKind) -> UpdAtomic UpdCoverKind :: Container -> ItemKindIx -> (Id ItemKind) -> UpdAtomic UpdDiscoverSeed :: Container -> ItemId -> ItemSeed -> UpdAtomic UpdCoverSeed :: Container -> ItemId -> ItemSeed -> UpdAtomic UpdDiscoverServer :: ItemId -> AspectRecord -> UpdAtomic UpdCoverServer :: ItemId -> AspectRecord -> UpdAtomic UpdPerception :: LevelId -> Perception -> Perception -> UpdAtomic UpdRestart :: FactionId -> PerLid -> State -> Challenge -> ClientOptions -> UpdAtomic UpdRestartServer :: State -> UpdAtomic UpdResume :: FactionId -> PerLid -> UpdAtomic UpdResumeServer :: State -> UpdAtomic UpdKillExit :: FactionId -> UpdAtomic UpdWriteSave :: UpdAtomic -- | Abstract syntax of atomic special effects, that is, atomic commands -- that only display special effects and don't change 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 SfxSortSlots :: SfxAtomic -- | Symbolic representation of text messages sent by server to clients and -- shown to players. 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 :: SfxMsg SfxPurposeNothing :: CStore -> SfxMsg SfxPurposeTooFew :: Int -> Int -> SfxMsg SfxPurposeUnique :: SfxMsg SfxColdFish :: SfxMsg SfxTimerExtended :: ActorId -> ItemId -> CStore -> SfxMsg -- | The game-state semantics of atomic game commands. There is no -- corresponding definition for special effects (SfxAtomic), -- because they don't modify State. -- -- For each of the commands, we are guaranteed that the client, the -- command is addressed to, perceives all the positions the command -- affects (as computed by posUpdAtomic). In the code for each -- semantic function we additonally verify the client is aware of any -- relevant items and/or actors and we throw the AtomicFail -- exception if it's not. The server keeps copies of all clients' states -- and, before sending a command to a client, applies it to the client's -- state copy. If AtomicFail is signalled, the command is -- ignored for that client. This enables simpler server code that -- addresses commands to all clients that can see it, even though not all -- are able to process it. handleUpdAtomic :: MonadStateWrite m => UpdAtomic -> m () -- | 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, server doesn't 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 or, more -- generally, the conditions under which the update can be noticed by a -- client. -- -- The goal of this mechanics is to ensure that atomic commands involving -- some positions visible by a client convey similar information as the -- client would get by directly observing the changes of the portion of -- server state limited to the visible positions. Consequently, when the -- visible commands are later applied to the client's state, the state -- stays consistent --- in sync with the server state and correctly -- limited by visiblity. There is some wiggle room both in what "in sync" -- and "visible" means and how they propagate through time. -- -- E.g., UpdDisplaceActor in a black room between two enemy -- actors, with only 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 in similar cotext would 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 that is outside a client's visiblity. The -- decomposed actions give less information that the original command, -- but some of them may fall within the visibility range of the client. -- The original action may give more information than even the total sum -- of all actions it's broken into. E.g., UpdMoveActor informs -- about the continued existence of the actor between moves vs popping -- out of existence and then back in. -- -- This is computed in server's State from before performing the -- command. breakUpdAtomic :: MonadStateRead m => UpdAtomic -> m [UpdAtomic] -- | Given the client, its perception and an atomic command, determine if -- the client notices the command. seenAtomicCli :: Bool -> FactionId -> Perception -> PosAtomic -> Bool -- | Determine whether the server would see a command that has the given -- visibilty conditions. seenAtomicSer :: PosAtomic -> Bool -- | The monad for writing to the main game state. Atomic updates -- (UpdAtomic) are given semantics in this monad. class MonadStateRead m => MonadStateWrite m modifyState :: MonadStateWrite m => (State -> State) -> m () -- | Exception signifying that atomic action failed because the information -- it carries is inconsistent with the client's state, (e.g., because the -- client knows too little to understand the command or already deduced -- the state change from earlier commands or is confused, amnesiac or -- sees illusory actors or tiles). Whenever we know the failure is -- logically impossible, we don't throw the AtomicFail -- exception, but insert a normal assertion or error call, which -- are never caught nor handled. newtype AtomicFail AtomicFail :: String -> AtomicFail putState :: MonadStateWrite m => State -> m () -- | Client-specific game state components. module Game.LambdaHack.Client.State -- | Client state, belonging to a single faction. data StateClient StateClient :: Int -> EnumMap ActorId TgtAndPath -> EnumSet LevelId -> EnumMap ActorId BfsAndPath -> [CmdAtomic] -> DiscoveryBenefit -> PerLid -> AlterLid -> StdGen -> Maybe ActorId -> FactionId -> Bool -> Challenge -> Challenge -> Int -> Int -> EnumMap LevelId (Maybe Bool) -> EnumMap (Id ModeKind) (Map Challenge Int) -> ClientOptions -> 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 data for our actors [sbfsD] :: StateClient -> EnumMap ActorId BfsAndPath -- | atomic commands performed to date [sundo] :: StateClient -> [CmdAtomic] -- | remembered AI benefits of items [sdiscoBenefit] :: StateClient -> DiscoveryBenefit -- | faction perception indexed by level [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 -- | whether to mark suspect features [smarkSuspect] :: StateClient -> Int -- | last in-melee condition for each level [scondInMelee] :: StateClient -> EnumMap LevelId (Maybe Bool) -- | won games at particular difficulty lvls [svictories] :: StateClient -> EnumMap (Id ModeKind) (Map Challenge Int) -- | client options [soptions] :: StateClient -> ClientOptions type AlterLid = EnumMap LevelId (Array Word8) -- | Pathfinding distances to all reachable positions of an actor and a -- shortest paths to some of the positions. data BfsAndPath BfsInvalid :: BfsAndPath BfsAndPath :: Array BfsDistance -> EnumMap Point AndPath -> BfsAndPath [bfsArr] :: BfsAndPath -> Array BfsDistance [bfsPath] :: BfsAndPath -> EnumMap Point AndPath -- | Actor's target and a path to it, if any. data TgtAndPath TgtAndPath :: Target -> AndPath -> TgtAndPath [tapTgt] :: TgtAndPath -> Target [tapPath] :: TgtAndPath -> AndPath -- | Initial empty game client state. emptyStateClient :: FactionId -> StateClient -- | Cycle the smarkSuspect setting. cycleMarkSuspect :: StateClient -> StateClient -- | 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 sleader :: StateClient -> Maybe ActorId 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 -- | Monad for writing to client state. 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 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 :: MonadStateRead 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 :: MonadStateRead m => Bool -> Actor -> Point -> Int -> m (Maybe Int) maxActorSkillsClient :: MonadClient m => ActorId -> m Skills currentSkillsClient :: MonadClient m => ActorId -> m Skills pickWeaponClient :: MonadClient m => ActorId -> ActorId -> m (Maybe (RequestTimed 'AbMelee)) updateSalter :: MonadClient m => LevelId -> [(Point, Id TileKind)] -> m () createSalter :: State -> AlterLid -- | Breadth first search and related 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) -- | 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 condBFS :: MonadClient m => ActorId -> m (Bool, Word8) -- | Furthest (wrt paths) known position. furthestKnown :: MonadClient m => ActorId -> m Point -- | 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))] data FleeViaStairsOrEscape ViaStairs :: FleeViaStairsOrEscape ViaStairsUp :: FleeViaStairsOrEscape ViaStairsDown :: FleeViaStairsOrEscape ViaEscape :: FleeViaStairsOrEscape ViaNothing :: FleeViaStairsOrEscape ViaAnything :: FleeViaStairsOrEscape embedBenefit :: MonadClient m => FleeViaStairsOrEscape -> ActorId -> [(Point, ItemBag)] -> m [(Double, (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)))] -- | 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 -- | 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))] unexploredDepth :: MonadClient m => Bool -> LevelId -> 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 -- | Assorted conditions used later on in AI logic. 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 -- | 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 :: MonadStateRead m => ActorId -> m [(Int, (ActorId, Actor))] -- | 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 :: MonadStateRead m => ActorId -> m Bool -- | Check whether the actor has no weapon in equipment. condNoEqpWeaponM :: MonadStateRead 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)] -- | 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 -- | Require that the actor stands over a desirable item. condDesirableFloorItemM :: MonadClient m => ActorId -> m 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 Double -> Item -> Bool condSupport :: MonadClient m => Int -> ActorId -> m Bool -- | Require that the actor stands in the dark and so would be betrayed by -- his own equipped light, condShineWouldBetrayM :: MonadStateRead 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) -- | Picking the AI actor to move and refreshing leader and non-leader -- targets. module Game.LambdaHack.Client.AI.PickActorM -- | Pick a new leader from among the actors on the current level. Refresh -- the target of the new leader, even if unchanged. pickActorToMove :: MonadClient m => Maybe ActorId -> m ActorId -- | Inspect the tactics of the actor and set his target according to it. setTargetFromTactics :: MonadClient m => ActorId -> m () -- | AI procedure for picking the best action for an actor. module Game.LambdaHack.Client.AI.HandleAbilityM -- | Pick the most desirable AI ation for the actor. pickAction :: MonadClient m => ActorId -> Bool -> m RequestAnyAbility actionStrategy :: forall m. MonadClient m => ActorId -> Bool -> m (Strategy RequestAnyAbility) 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)) trigger :: MonadClient m => ActorId -> FleeViaStairsOrEscape -> m (Strategy (RequestTimed 'AbAlter)) projectItem :: MonadClient m => ActorId -> m (Strategy (RequestTimed 'AbProject)) data ApplyItemGroup 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) 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 (regardless if the whole -- faction is under human or computer control). queryAI :: MonadClient m => ActorId -> m RequestAI -- | Pick an actor to move and an action for him to perform, given an -- optional previous candidate actor and action and the server-proposed -- actor. pickActorAndAction :: MonadClient m => Maybe (ActorId, RequestAnyAbility) -> ActorId -> m (ActorId, RequestAnyAbility) -- | 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) -- and record this per-level. This is needed only by AI and computed as -- lazily as possible before each round of AI deliberations. udpdateCondInMelee :: MonadClient m => ActorId -> m () -- | Abstract syntax of responses. -- -- See -- https://github.com/LambdaHack/LambdaHack/wiki/Client-server-architecture. module Game.LambdaHack.Client.Response -- | Abstract syntax of responses sent by server to an AI or UI client (or -- a universal client that can handle both roles, which is why this type -- is not separated into distinct AI and UI types). A response tells a -- client how to update game state or what information to send to the -- server. data Response -- | change State by performing this atomic update RespUpdAtomicNoState :: UpdAtomic -> Response -- | put the given State, which results from performing the atomic -- update RespUpdAtomic :: State -> UpdAtomic -> Response -- | compute an AI move for the actor and send (the semantics of) it RespQueryAI :: ActorId -> Response -- | perform special effects (animations, messages, etc.) RespSfxAtomic :: SfxAtomic -> Response -- | prompt the human player for a command and send (the semantics of) it RespQueryUI :: Response instance GHC.Show.Show Game.LambdaHack.Client.Response.Response -- | Handle atomic commands received by the client. module Game.LambdaHack.Client.HandleAtomicM -- | Client monad for saving and restarting games. class MonadClient m => MonadClientSetup m saveClient :: MonadClientSetup m => m () restartClient :: MonadClientSetup m => m () -- | Effect of atomic actions on client state. It is calculated with the -- global state from after the command is executed (except where the -- supplied oldState is used). cmdAtomicSemCli :: MonadClientSetup m => State -> UpdAtomic -> m () wipeBfsIfItemAffectsSkills :: MonadClient m => [CStore] -> ActorId -> m () tileChangeAffectsBfs :: COps -> Id TileKind -> Id TileKind -> Bool createActor :: MonadClient m => ActorId -> Actor -> [(ItemId, Item)] -> m () destroyActor :: MonadClient m => ActorId -> Actor -> Bool -> m () addItemToDiscoBenefit :: MonadClient m => ItemId -> Item -> m () perception :: MonadClient m => LevelId -> Perception -> Perception -> m () discoverKind :: MonadClient m => Container -> ItemKindIx -> Id ItemKind -> m () coverKind :: Container -> ItemKindIx -> Id ItemKind -> m () discoverSeed :: MonadClient m => Container -> ItemId -> ItemSeed -> m () coverSeed :: Container -> ItemId -> ItemSeed -> m () killExit :: MonadClient m => m () -- | 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 mkFixed :: (X, Y) -> Area -> Point -> Area data SpecialArea SpecialArea :: Area -> SpecialArea SpecialFixed :: Point -> (GroupName PlaceKind) -> Area -> SpecialArea SpecialMerged :: SpecialArea -> Point -> SpecialArea -- | 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 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 -- | 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) connectGrid' :: EnumSet Point -> (X, Y) -> EnumSet Point -> EnumSet Point -> [(Point, Point)] -> Rnd [(Point, Point)] -- | Sort the sequence of two points, in the derived lexicographic order. sortPoint :: (Point, Point) -> (Point, Point) -- | Create a corridor, either horizontal or vertical, with a possible -- intermediate part that is in the opposite direction. There might not -- always exist a good intermediate point if the places are allowed to be -- close together and then we let the intermediate part degenerate. mkCorridor :: HV -> Point -> Bool -> Point -> Bool -> Area -> Rnd Corridor borderPlace :: Area -> Fence -> (Area, Area) instance GHC.Classes.Eq Game.LambdaHack.Server.DungeonGen.AreaRnd.HV -- | Generation of places from place kinds. module Game.LambdaHack.Server.DungeonGen.Place -- | The parameters of a place. All are immutable and rolled and fixed 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 -- | 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) -- | 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 -- | 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) isChancePos :: Int -> Int -> Point -> Bool -- | Construct a fence around an area, with the given tile group. buildFenceRnd :: COps -> GroupName TileKind -> Area -> Rnd TileMapEM -- | Calculate interior room area according to fence type, based on the -- total area for the room and it's fence. This is used for checking if -- the room fits in the area, for digging up the place and the fence and -- for deciding if the room is dark or lit later in the dungeon -- generation process. interiorArea :: PlaceKind -> Area -> Maybe Area -- | Roll a legend of a place plan: a map from plan symbols to tile kinds. olegend :: COps -> GroupName TileKind -> Rnd (EnumMap Char (Int, Id TileKind), EnumMap Char (Id TileKind)) ooverride :: COps -> [(Char, GroupName TileKind)] -> Rnd (EnumMap Char (Int, Id TileKind), EnumMap Char (Id TileKind)) -- | Construct a fence around an area, with the given tile kind. buildFence :: Id TileKind -> Area -> TileMapEM -- | Create a place by tiling patterns. tilePlace :: Area -> PlaceKind -> Rnd (EnumMap Point Char) 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] -- | Generate a cave using an algorithm inspired by the original Rogue, as -- follows (in gross simplification): -- --