-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A roguelike game engine in early development -- @package LambdaHack @version 0.2.14 -- | Common definitions for the Field of View algorithms. See -- https://github.com/LambdaHack/LambdaHack/wiki/Fov-and-los for -- some more context and references. module Game.LambdaHack.Server.Fov.Common -- | Distance from the (0, 0) point where FOV originates. type Distance = Int -- | Progress along an arc with a constant distance from (0, 0). type Progress = Int -- | Rotated and translated coordinates of 2D points, so that the points -- fit in a single quadrant area (e, g., quadrant I for Permissive FOV, -- hence both coordinates positive; adjacent diagonal halves of quadrant -- I and II for Digital FOV, hence y positive). The special coordinates -- are written using the standard mathematical coordinate setup, where -- quadrant I, with x and y positive, is on the upper right. data Bump B :: !Int -> !Int -> Bump bx :: Bump -> !Int by :: Bump -> !Int -- | Straight line between points. data Line Line :: !Bump -> !Bump -> Line -- | Convex hull represented as a list of points. type ConvexHull = [Bump] -- | An edge (comprising of a line and a convex hull) of the area to be -- scanned. type Edge = (Line, ConvexHull) -- | The area left to be scanned, delimited by edges. type EdgeInterval = (Edge, Edge) -- | Maximal element of a non-empty list. Prefers elements from the rear, -- which is essential for PFOV, to avoid ill-defined lines. maximal :: (a -> a -> Bool) -> [a] -> a -- | Check if the line from the second point to the first is more steep -- than the line from the third point to the first. This is related to -- the formal notion of gradient (or angle), but hacked wrt signs to work -- fast in this particular setup. Returns True for ill-defined lines. steeper :: Bump -> Bump -> Bump -> Bool -- | Extends a convex hull of bumps with a new bump. Nothing needs to be -- done if the new bump already lies within the hull. The first argument -- is typically steeper, optionally negated, applied to the second -- argument. addHull :: (Bump -> Bump -> Bool) -> Bump -> ConvexHull -> ConvexHull instance Show Bump instance Show Line -- | A restrictive variant of Recursive Shadow Casting FOV with infinite -- range. It's not designed for dungeons with diagonal walls and so here -- they block visibility, though they don't block movement. The main -- advantage of the algorithm is that it's very simple and fast. module Game.LambdaHack.Server.Fov.Shadow -- | Rotated and translated coordinates of 2D points, so that they fit in -- the same single octant area. type SBump = (Progress, Distance) -- | The area left to be scanned, delimited by fractions of the original -- arc. Interval (0, 1) means the whole 45 degrees arc of the -- processed octant is to be scanned. type Interval = (Rational, Rational) -- | Calculates the list of tiles, in SBump coordinates, visible -- from (0, 0). scan :: (SBump -> Bool) -> Distance -> Interval -> [SBump] -- | Keeping track of forked threads. module Game.LambdaHack.Common.Thread forkChild :: MVar [Async ()] -> IO () -> IO () waitForChildren :: MVar [Async ()] -> IO () -- | Queues implemented with two stacks to ensure fast writes. module Game.LambdaHack.Common.LQueue -- | Queues implemented with two stacks. type LQueue a = ([a], [a]) -- | Create a new empty mutable queue. newLQueue :: LQueue a -- | Check if the queue is empty. nullLQueue :: LQueue a -> Bool -- | The length of the queue. lengthLQueue :: LQueue a -> Int -- | Try reading a queue. Return Nothing if empty. tryReadLQueue :: LQueue a -> Maybe (a, LQueue a) -- | Write to the queue. Faster than reading. writeLQueue :: LQueue a -> a -> LQueue a -- | Remove all but the last written non-Nothing element of the -- queue. trimLQueue :: LQueue (Maybe a) -> LQueue (Maybe a) -- | Remove frames up to and including the first segment of -- Nothing frames. | If the resulting queue is empty, apply -- trimLQueue instead. dropStartLQueue :: LQueue (Maybe a) -> LQueue (Maybe a) -- | Dump all but the last written non-Nothing element of the -- queue, if any. lastLQueue :: LQueue (Maybe a) -> Maybe a toListLQueue :: LQueue a -> [a] -- | Saving/loading with serialization and compression. module Game.LambdaHack.Common.File -- | Serialize, compress and save data with an EOF marker. The OK -- is used as an EOF marker to ensure any apparent problems with -- corrupted files are reported to the user ASAP. encodeEOF :: Binary a => FilePath -> a -> IO () -- | Read, decompress and deserialize data with an EOF marker. The -- OK EOF marker ensures any easily detectable file corruption -- is discovered and reported before the function returns. strictDecodeEOF :: Binary a => FilePath -> IO a -- | Try to create a directory, if it doesn't exist. Terminate the program -- with an exception if the directory does not exist, but can't be -- created. tryCreateDir :: FilePath -> IO () -- | Try to copy over data files, if not already there. tryCopyDataFiles :: FilePath -> (FilePath -> IO FilePath) -> [(FilePath, FilePath)] -> IO () -- | 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 -- | AI strategy abilities. module Game.LambdaHack.Common.Ability -- | Actor and faction abilities corresponding to client-server requests. data Ability AbMove :: Ability AbMelee :: Ability AbDisplace :: Ability AbAlter :: Ability AbWait :: Ability AbMoveItem :: Ability AbProject :: Ability AbApply :: Ability AbTrigger :: Ability type Skills = EnumMap Ability Int zeroSkills :: Skills unitSkills :: Skills addSkills :: Skills -> Skills -> Skills scaleSkills :: Int -> Skills -> Skills instance Read Ability instance Eq Ability instance Ord Ability instance Generic Ability instance Enum Ability instance Bounded Ability instance Datatype D1Ability instance Constructor C1_0Ability instance Constructor C1_1Ability instance Constructor C1_2Ability instance Constructor C1_3Ability instance Constructor C1_4Ability instance Constructor C1_5Ability instance Constructor C1_6Ability instance Constructor C1_7Ability instance Constructor C1_8Ability instance Hashable Ability instance Binary Ability instance Show Ability -- | Basic operations on 2D points represented as linear offsets. module Game.LambdaHack.Common.Point -- | Spacial dimension for points and vectors. type X = Int -- | Spacial dimension for points and vectors. type Y = Int -- | 2D points in cartesian representation. Coordinates grow to the right -- and down, so that the (0, 0) point is in the top-left corner of the -- screen. Coordinates are never negative. data Point Point :: !X -> !Y -> Point px :: Point -> !X py :: Point -> !Y -- | The maximum number of bits for level X and Y dimension (16). The value -- is chosen to support architectures with 32-bit Ints. maxLevelDimExponent :: Int -- | The distance between two points in the chessboard metric. chessDist :: Point -> Point -> Int -- | Squared euclidean distance between two points. euclidDistSq :: Point -> Point -> Int -- | Checks whether two points are adjacent on the map (horizontally, -- vertically or diagonally). adjacent :: Point -> Point -> Bool -- | Checks that a point belongs to an area. inside :: Point -> (X, Y, X, Y) -> Bool -- | Bresenham's line algorithm generalized to arbitrary starting -- eps (eps value of 0 gives the standard BLA). Skips -- the source point and goes through the second point to the edge of the -- level. GIves Nothing if the points are equal. The target is -- given as Point to permit aiming out of the level, e.g., to -- get uniform distributions of directions for explosions close to the -- edge of the level. bla :: X -> Y -> Int -> Point -> Point -> Maybe [Point] -- | A list of all points on a straight vertical or straight horizontal -- line between two points. Fails if no such line exists. fromTo :: Point -> Point -> [Point] instance Eq Point instance Ord Point instance Enum Point instance Binary Point instance Show Point -- | Basic operations on 2D vectors represented in an efficient, but not -- unique, way. module Game.LambdaHack.Common.Vector -- | 2D vectors in cartesian representation. Coordinates grow to the right -- and down, so that the (1, 1) vector points to the bottom-right corner -- of the screen. data Vector Vector :: !X -> !Y -> Vector vx :: Vector -> !X vy :: Vector -> !Y -- | Tells if a vector has length 1 in the chessboard metric. isUnit :: Vector -> Bool -- | Checks whether a unit vector is a diagonal direction, as opposed to -- cardinal. If the vector is not unit, it checks that the vector is not -- horizontal nor vertical. isDiagonal :: Vector -> Bool -- | Reverse an arbirary vector. neg :: Vector -> Vector -- | The lenght of a vector in the chessboard metric, where diagonal moves -- cost 1. chessDistVector :: Vector -> Int -- | Squared euclidean distance between two vectors. euclidDistSqVector :: Vector -> Vector -> Int -- | Vectors of all unit moves in the chessboard metric, clockwise, -- starting north-west. moves :: [Vector] -- | Vectors of all cardinal direction unit moves, clockwise, starting -- north. movesCardinal :: [Vector] -- | Vectors of all diagonal direction unit moves, clockwise, starting -- north. movesDiagonal :: [Vector] compassText :: Vector -> Text -- | All (8 at most) closest neighbours of a point within an area. vicinity :: X -> Y -> Point -> [Point] -- | All (4 at most) cardinal direction neighbours of a point within an -- area. vicinityCardinal :: X -> Y -> Point -> [Point] -- | Translate a point by a vector. shift :: Point -> Vector -> Point -- | Translate a point by a vector, but only if the result fits in an area. shiftBounded :: X -> Y -> Point -> Vector -> Point -- | A list of points that a list of vectors leads to. trajectoryToPath :: Point -> [Vector] -> [Point] -- | A list of points that a list of vectors leads to, bounded by level -- size. trajectoryToPathBounded :: X -> Y -> Point -> [Vector] -> [Point] -- | The vector between the second point and the first. We have -- --
--   shift pos1 (pos2 `vectorToFrom` pos1) == pos2
--   
-- -- The arguments are in the same order as in the underlying scalar -- subtraction. vectorToFrom :: Point -> Point -> Vector -- | A list of vectors between a list of points. pathToTrajectory :: [Point] -> [Vector] type RadianAngle = Double -- | Rotate a vector by the given angle (expressed in radians) -- counterclockwise and return a unit vector approximately in the -- resulting direction. rotate :: RadianAngle -> Vector -> Vector -- | Given two distinct positions, determine the direction (a unit vector) -- in which one should move from the first in order to get closer to the -- second. Ignores obstacles. Of several equally good directions (in the -- chessboard metric) it picks one of those that visually (in the -- euclidean metric) maximally align with the vector between the two -- points. towards :: Point -> Point -> Vector instance Eq Vector instance Ord Vector instance Show Vector instance Read Vector instance Enum Vector instance Binary Vector -- | Arrays, based on Data.Vector.Unboxed, indexed by Point. module Game.LambdaHack.Common.PointArray -- | Arrays indexed by Point. data Array c -- | Array lookup. (!) :: Enum c => Array c -> Point -> c -- | Construct an array updated with the association list. (//) :: Enum c => Array c -> [(Point, c)] -> Array c -- | Create an array from a replicated element. replicateA :: Enum c => X -> Y -> c -> Array c -- | Create an array from a replicated monadic action. replicateMA :: Enum c => Monad m => X -> Y -> m c -> m (Array c) -- | Create an array from a monadic function. generateMA :: Enum c => Monad m => X -> Y -> (Point -> m c) -> m (Array c) -- | Content identifiers array size. sizeA :: Array c -> (X, Y) -- | Fold left strictly over an array. foldlA :: Enum c => (a -> c -> a) -> a -> Array c -> a -- | Fold left strictly over an array (function applied to each element and -- its index). ifoldlA :: Enum c => (a -> Point -> c -> a) -> a -> Array c -> a -- | Map over an array (function applied to each element and its index). imapA :: (Enum c, Enum d) => (Point -> c -> d) -> Array c -> Array d -- | Yield the point coordinates of a minimum element of the array. The -- array may not be empty. minIndexA :: Enum c => Array c -> Point -- | Yield the point coordinates of the last minimum element of the array. -- The array may not be empty. minLastIndexA :: Enum c => Array c -> Point -- | Yield the point coordinates of the first maximum element of the array. -- The array may not be empty. maxIndexA :: Enum c => Array c -> Point -- | Yield the point coordinates of the last maximum element of the array. -- The array may not be empty. maxLastIndexA :: Enum c => Array c -> Point instance Eq (Array c) instance Binary (Array c) instance Show (Array c) -- | Breadth first search algorithms. module Game.LambdaHack.Client.Bfs -- | Weighted distance between points along shortest paths. data BfsDistance -- | State of legality of moves between adjacent points. data MoveLegal MoveBlocked :: MoveLegal MoveToOpen :: MoveLegal MoveToUnknown :: MoveLegal -- | The distance value that denote no legal path between points. apartBfs :: BfsDistance -- | Fill out the given BFS array. fillBfs :: (Point -> Point -> MoveLegal) -> (Point -> Point -> Bool) -> Point -> Array BfsDistance -> Array BfsDistance -- | Find a path, without the source position, with the smallest length. -- The eps coefficient determines which direction (or the -- closest directions available) that path should prefer, where 0 means -- north-west and 1 means north. findPathBfs :: (Point -> Point -> MoveLegal) -> (Point -> Point -> Bool) -> Point -> Point -> Int -> Array BfsDistance -> Maybe [Point] -- | Access a BFS array and interpret the looked up distance value. accessBfs :: Array BfsDistance -> Point -> Maybe Int -- | The minimal distance value assigned to paths that don't enter any -- unknown tiles. minKnownBfs :: BfsDistance instance Show BfsDistance instance Eq BfsDistance instance Ord BfsDistance instance Enum BfsDistance instance Bounded BfsDistance instance Bits BfsDistance instance Eq MoveLegal -- | 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 -- | Divide uniformly a larger area into the given number of smaller areas -- overlapping at the edges. grid :: (X, Y) -> Area -> [(Point, Area)] -- | Enlarge (or shrink) the given area on all fours sides by the amount. shrink :: Area -> Maybe Area instance Show Area instance Binary Area -- | Hacks that haven't found their home yet. module Game.LambdaHack.Common.Misc -- | A unique identifier of a faction in a game. data FactionId -- | Abstract level identifiers. data LevelId -- | Absolute depth in the dungeon. When used for the maximum depth of the -- whole dungeon, this can be different than dungeon size, e.g., when the -- dungeon is branched, and it can even be different than the length of -- the longest branch, if levels at some depths are missing. newtype AbsDepth AbsDepth :: Int -> AbsDepth -- | A unique identifier of an actor in the dungeon. data ActorId -- | Item container type. data Container CFloor :: !LevelId -> !Point -> Container CActor :: !ActorId -> !CStore -> Container -- | for bootstrapping actor bodies CTrunk :: !FactionId -> !LevelId -> !Point -> Container data CStore CGround :: CStore COrgan :: CStore CEqp :: CStore CInv :: CStore CSha :: CStore -- | Level bounds. TODO: query terminal size instead and scroll view. normalLevelBound :: (Int, Int) -- | Integer division, rounding up. divUp :: Integral a => a -> a -> a -- | For each group that the kind belongs to, denoted by a Text -- name in the first component of a pair, the second component of a pair -- shows how common the kind is within the group. type Freqs = [(Text, Int)] -- |
--   breturn b a = [a | b]
--   
breturn :: MonadPlus m => Bool -> a -> m a serverSaveName :: String -- | What distance signifies that two actors are "nearby". nearby :: Int instance Show CStore instance Read CStore instance Eq CStore instance Ord CStore instance Enum CStore instance Bounded CStore instance Generic CStore instance Show FactionId instance Eq FactionId instance Ord FactionId instance Enum FactionId instance Binary FactionId instance Show LevelId instance Eq LevelId instance Ord LevelId instance Enum LevelId instance Hashable LevelId instance Binary LevelId instance Show AbsDepth instance Eq AbsDepth instance Ord AbsDepth instance Hashable AbsDepth instance Binary AbsDepth instance Show ActorId instance Eq ActorId instance Ord ActorId instance Enum ActorId instance Binary ActorId instance Show Container instance Eq Container instance Ord Container instance Generic Container instance Datatype D1CStore instance Constructor C1_0CStore instance Constructor C1_1CStore instance Constructor C1_2CStore instance Constructor C1_3CStore instance Constructor C1_4CStore instance Datatype D1Container instance Constructor C1_0Container instance Constructor C1_1Container instance Constructor C1_2Container instance (Enum k, Hashable k, Hashable e) => Hashable (EnumMap k e) instance Enum k => Adjustable (EnumMap k) instance Enum k => Lookup (EnumMap k) instance Enum k => Indexable (EnumMap k) instance Enum k => TraversableWithKey (EnumMap k) instance Enum k => FoldableWithKey (EnumMap k) instance Enum k => Keyed (EnumMap k) instance Enum k => ZipWithKey (EnumMap k) instance Zip (EnumMap k) instance (Binary k, Binary v, Eq k, Hashable k) => Binary (HashMap k v) instance (Enum k, Binary k) => Binary (EnumSet k) instance (Enum k, Binary k, Binary e) => Binary (EnumMap k e) instance Hashable CStore instance Binary CStore instance Binary Container -- | Game time and speed. module Game.LambdaHack.Common.Time -- | Game time in ticks. The time dimension. One tick is 1 microsecond (one -- millionth of a second), one turn is 0.5 s. data Time -- | Start of the game time, or zero lenght time interval. timeZero :: Time -- | At least once per clip all moves are resolved and a frame or a frame -- delay is generated. Currently one clip is 0.1 s, but it may change, -- and the code should not depend on this fixed value. timeClip :: Time -- | One turn is 0.5 s. The code may depend on that. Actors at normal speed -- (2 m/s) take one turn to move one tile (1 m by 1 m). timeTurn :: Time -- | An infinitesimal time period. timeEpsilon :: Time -- | Absolute time addition, e.g., for summing the total game session time -- from the times of individual games. absoluteTimeAdd :: Time -> Time -> Time -- | Absolute time negation. To be used for reversing time flow, e.g., for -- comparing absolute times in the reverse order. absoluteTimeNegate :: Time -> Time -- | How many time intervals of the latter kind fits in an interval of the -- former kind. timeFit :: Time -> Time -> Int -- | How many time intervals of the latter kind cover an interval of the -- former kind (rounded up). timeFitUp :: Time -> Time -> Int -- | One-dimentional vectors. Introduced to tell apart the 2 uses of Time: -- as an absolute game time and as an increment. newtype Delta a Delta :: a -> Delta a -- | Shifting an absolute time by a time vector. timeShift :: Time -> Delta Time -> Time -- | Time time vector between the second and the first absolute times. The -- arguments are in the same order as in the underlying scalar -- subtraction. timeDeltaToFrom :: Time -> Time -> Delta Time -- | Reverse a time vector. timeDeltaReverse :: Delta Time -> Delta Time -- | Scale the time vector by an Int scalar value. timeDeltaScale :: Delta Time -> Int -> Delta Time -- | Represent the main 10 thresholds of a time range by digits, given the -- total length of the time range. timeDeltaToDigit :: Delta Time -> Delta Time -> Char -- | The number of time ticks it takes to walk 1 meter at the given speed. ticksPerMeter :: Speed -> Delta Time -- | Speed in meters per 1 million seconds (m/Ms). Actors at normal speed -- (2 m/s) take one time turn (0.5 s) to move one tile (1 m by 1 m). data Speed -- | Constructor for content definitions. toSpeed :: Int -> Speed -- | Pretty-printing of speed in the format used in content definitions. fromSpeed :: Speed -> Int -- | No movement possible at that speed. speedZero :: Speed -- | Normal speed (2 m/s) that suffices to move one tile in one turn. speedNormal :: Speed -- | Scale speed by an Int scalar value. speedScale :: Rational -> Speed -> Speed -- | Speed addition. speedAdd :: Speed -> Speed -> Speed -- | Speed negation. speedNegate :: Speed -> Speed -- | Calculate projectile speed from item weight in grams and velocity -- percent modifier. See -- https://github.com/LambdaHack/LambdaHack/wiki/Item-statistics. speedFromWeight :: Int -> Int -> Speed -- | Calculate maximum range in meters of a projectile from its speed. See -- https://github.com/LambdaHack/LambdaHack/wiki/Item-statistics. -- With this formula, each projectile flies for at most 1 second, that is -- 2 turns, and then drops to the ground. rangeFromSpeed :: Speed -> Int -- | Calculate maximum range taking into account the linger percentage. rangeFromSpeedAndLinger :: Speed -> Int -> Int instance Show Time instance Eq Time instance Ord Time instance Enum Time instance Bounded Time instance Binary Time instance Show a => Show (Delta a) instance Eq a => Eq (Delta a) instance Ord a => Ord (Delta a) instance Enum a => Enum (Delta a) instance Bounded a => Bounded (Delta a) instance Binary a => Binary (Delta a) instance Functor Delta instance Eq Speed instance Ord Speed instance Binary Speed instance Show Speed -- | The type of kinds of game modes. module Game.LambdaHack.Content.ModeKind -- | Requested cave groups for particular levels. The default is the "dng" -- group, which means a random choice from all caves that can randomly -- appear. The second component of the pair is the Escape -- feature on the level. True means it's represented by -- <, False, by >. type Caves = IntMap (Text, Maybe Bool) -- | The specification of players for the game mode. data Players Players :: ![Player] -> ![(Text, Text)] -> ![(Text, Text)] -> Players -- | players, both human and computer playersList :: Players -> ![Player] -- | the initial enmity matrix playersEnemy :: Players -> ![(Text, Text)] -- | the initial aliance matrix playersAlly :: Players -> ![(Text, Text)] -- | Properties of a particular player. data Player Player :: !Text -> !Text -> !Bool -> !Bool -> !Int -> !Int -> !Bool -> !Bool -> !Bool -> Player -- | name of the player playerName :: Player -> !Text -- | name of faction(s) the player can control playerFaction :: Player -> !Text -- | whether the player is a spawn (score, AI) playerIsSpawn :: Player -> !Bool -- | whether the player is a hero (score, AI, UI) playerIsHero :: Player -> !Bool -- | level where the initial members start playerEntry :: Player -> !Int -- | number of initial members playerInitial :: Player -> !Int -- | leaderless factions can't be controlled by a human or a user-supplied -- AI client playerLeader :: Player -> !Bool -- | is the faction under AI control? playerAI :: Player -> !Bool -- | does the faction have a UI client (for control or passive observation) playerUI :: Player -> !Bool -- | Game mode specification. data ModeKind ModeKind :: !Char -> !Text -> !Freqs -> !Players -> !Caves -> !Text -> ModeKind -- | a symbol (matches the keypress, if any) msymbol :: ModeKind -> !Char -- | short description mname :: ModeKind -> !Text -- | frequency within groups mfreq :: ModeKind -> !Freqs -- | players taking part in the game mplayers :: ModeKind -> !Players -- | arena of the game mcaves :: ModeKind -> !Caves -- | description mdesc :: ModeKind -> !Text -- | No specific possible problems for the content of this kind, so far, so -- the validation function always returns the empty list of offending -- kinds. validateModeKind :: [ModeKind] -> [ModeKind] instance Show Player instance Eq Player instance Show Players instance Eq Players instance Show ModeKind instance Binary Player -- | The type of game rule sets and assorted game data. module Game.LambdaHack.Content.RuleKind -- | The type of game rule sets and assorted game data. -- -- For now the rules are immutable througout the game, so there is no -- type Rule to hold any changing parameters, just -- RuleKind for the fixed set. However, in the future, if the -- rules can get changed during gameplay based on data mining of player -- behaviour, we may add such a type and then RuleKind will -- become just a starting template, analogously as for the other content. -- -- The raccessible field hold extra conditions that have to be -- met for a tile to be accessible, on top of being an open tile (or -- openable, in some contexts). The raccessibleDoor field -- contains yet additional conditions concerning tiles that are doors, -- whether open or closed. Precondition: the two positions are next to -- each other. We assume the predicate is symmetric. data RuleKind RuleKind :: !Char -> !Text -> !Freqs -> !(Maybe (Point -> Point -> Bool)) -> !(Maybe (Point -> Point -> Bool)) -> !Text -> (FilePath -> IO FilePath) -> !Version -> !FilePath -> !String -> !Text -> !Bool -> !FovMode -> !Int -> !Int -> !FilePath -> !String -> !Bool -> RuleKind -- | a symbol rsymbol :: RuleKind -> !Char -- | short description rname :: RuleKind -> !Text -- | frequency within groups rfreq :: RuleKind -> !Freqs raccessible :: RuleKind -> !(Maybe (Point -> Point -> Bool)) raccessibleDoor :: RuleKind -> !(Maybe (Point -> Point -> Bool)) -- | the title of the game rtitle :: RuleKind -> !Text -- | the path to data files rpathsDataFile :: RuleKind -> FilePath -> IO FilePath -- | the version of the game rpathsVersion :: RuleKind -> !Version -- | base 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 -- | FOV calculation mode rfovMode :: RuleKind -> !FovMode -- | game backup is saved that often rsaveBkpClips :: RuleKind -> !Int -- | flip AI/spawn leader level that often rleadLevelClips :: RuleKind -> !Int -- | name of the scores file rscoresFile :: RuleKind -> !FilePath -- | name of the savefile prefix rsavePrefix :: RuleKind -> !String -- | whether shared stashes are available rsharedStash :: RuleKind -> !Bool -- | Validates the ASCII art format (TODO). validateRuleKind :: [RuleKind] -> [RuleKind] -- | Field Of View scanning mode. data FovMode -- | restrictive shadow casting Shadow :: FovMode -- | permissive FOV Permissive :: FovMode -- | digital FOV Digital :: FovMode instance Show FovMode instance Read FovMode instance Binary FovMode instance Show RuleKind -- | The type of kinds of game factions (heroes, enemies, NPCs, etc.). module Game.LambdaHack.Content.FactionKind -- | Faction properties that are fixed for a given kind of factions. data FactionKind FactionKind :: !Char -> !Text -> !Freqs -> !Skills -> !Skills -> FactionKind -- | a symbol fsymbol :: FactionKind -> !Char -- | short description fname :: FactionKind -> !Text -- | frequency within groups ffreq :: FactionKind -> !Freqs -- | skills of the picked leader fSkillsLeader :: FactionKind -> !Skills -- | skills of the other actors fSkillsOther :: FactionKind -> !Skills -- | No specific possible problems for the content of this kind, so far, so -- the validation function always returns the empty list of offending -- kinds. validateFactionKind :: [FactionKind] -> [FactionKind] instance Show FactionKind -- | A game requires the engine provided by the library, perhaps -- customized, and game content, defined completely afresh for the -- particular game. The general type of the content is -- ContentDef and it has instances for all content kinds, such -- as items kinds (Game.LambdaHack.Content.ItemKind). The -- possible kinds are fixed in the library and all defined in the same -- directory. On the other hand, game content, that is all elements of -- ContentDef instances, are defined in a directory of the game -- code proper, with names corresponding to their kinds. module Game.LambdaHack.Common.ContentDef -- | The general type of a particular game content, e.g., item kinds. data ContentDef a ContentDef :: (a -> Char) -> (a -> Text) -> (a -> Freqs) -> ([a] -> [a]) -> [a] -> ContentDef a -- | symbol, e.g., to print on the map getSymbol :: ContentDef a -> a -> Char -- | name, e.g., to show to the player getName :: ContentDef a -> a -> Text -- | frequency within groups getFreq :: ContentDef a -> a -> Freqs -- | validate and catch some offenders, if any validate :: ContentDef a -> [a] -> [a] -- | all the defined content of this type content :: ContentDef a -> [a] -- | 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 -> ![(Int, Int)] -> !Cover -> !Fence -> ![Text] -> ![(Char, Text)] -> PlaceKind -- | a symbol psymbol :: PlaceKind -> !Char -- | short description pname :: PlaceKind -> !Text -- | frequency within groups pfreq :: PlaceKind -> !Freqs -- | rarity on given depths prarity :: PlaceKind -> ![(Int, Int)] -- | how to fill whole place based on the corner pcover :: PlaceKind -> !Cover -- | whether to fence the place with solid border pfence :: PlaceKind -> !Fence -- | plan of the top-left corner of the place ptopLeft :: PlaceKind -> ![Text] -- | legend override, ignoring tile symbol poverride :: PlaceKind -> ![(Char, Text)] -- | A method of filling the whole area (except for CVerbatim, which is -- 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 -- | The choice of a fence type for the place. data Fence -- | put a solid wall fence around the place FWall :: Fence -- | leave an empty floor space around the place FFloor :: Fence -- | skip the fence and fill all with the place proper FNone :: Fence -- | Filter a list of kinds, passing through only the incorrect ones, if -- any. -- -- Verify that the top-left corner map is rectangular and not empty. validatePlaceKind :: [PlaceKind] -> [PlaceKind] instance Show Cover instance Eq Cover instance Show Fence instance Eq Fence instance Show PlaceKind -- | DFOV (Digital Field of View) implemented according to specification at -- http://roguebasin.roguelikedevelopment.org/index.php?title=Digital_field_of_view_implementation. -- This fast version of the algorithm, based on PFOV, has AFAIK -- never been described nor implemented before. module Game.LambdaHack.Server.Fov.Digital -- | Calculates the list of tiles, in Bump coordinates, visible -- from (0, 0), within the given sight range. scan :: Distance -> (Bump -> Bool) -> [Bump] -- | Create a line from two points. Debug: check if well-defined. dline :: Bump -> Bump -> Line -- | Compare steepness of (p1, f) and (p2, f). Debug: -- Verify that the results of 2 independent checks are equal. dsteeper :: Bump -> Bump -> Bump -> Bool -- | The X coordinate, represented as a fraction, of the intersection of a -- given line and the line of diagonals of diamonds at distance -- d from (0, 0). intersect :: Line -> Distance -> (Int, Int) -- | Debug functions for DFOV: -- -- Debug: calculate steeper for DFOV in another way and compare results. debugSteeper :: Bump -> Bump -> Bump -> Bool -- | Debug: check if a view border line for DFOV is legal. debugLine :: Line -> (Bool, String) -- | PFOV (Permissive Field of View) clean-room reimplemented based on the -- algorithm described in -- http://roguebasin.roguelikedevelopment.org/index.php?title=Precise_Permissive_Field_of_View, -- though the general structure is more influenced by recursive shadow -- casting, as implemented in Shadow.hs. In the result, this algorithm is -- much faster than the original algorithm on dense maps, since it does -- not scan areas blocked by shadows. module Game.LambdaHack.Server.Fov.Permissive -- | Calculates the list of tiles, in Bump coordinates, visible -- from (0, 0). scan :: (Bump -> Bool) -> [Bump] -- | Create a line from two points. Debug: check if well-defined. dline :: Bump -> Bump -> Line -- | Compare steepness of (p1, f) and (p2, f). Debug: -- Verify that the results of 2 independent checks are equal. dsteeper :: Bump -> Bump -> Bump -> Bool -- | The Y coordinate, represented as a fraction, of the intersection of a -- given line and the line of diagonals of squares at distance d -- from (0, 0). intersect :: Line -> Distance -> (Int, Int) -- | Debug functions for PFOV: -- -- Debug: calculate steeper for PFOV in another way and compare results. debugSteeper :: Bump -> Bump -> Bump -> Bool -- | Debug: checks postconditions of borderLine. debugLine :: Line -> (Bool, String) -- | Colours and text attributes. module Game.LambdaHack.Common.Color -- | Colours supported by the major frontends. data Color Black :: Color Red :: Color Green :: Color Brown :: Color Blue :: Color Magenta :: Color Cyan :: Color White :: Color BrBlack :: Color BrRed :: Color BrGreen :: Color BrYellow :: Color BrBlue :: Color BrMagenta :: Color BrCyan :: Color BrWhite :: Color -- | The default colours, to optimize attribute setting. defBG :: Color -- | The default colours, to optimize attribute setting. defFG :: Color -- | A helper for the terminal frontends that display bright via bold. isBright :: Color -> Bool -- | Due to the limitation of the curses library used in the curses -- frontend, only these are legal backgrounds. legalBG :: [Color] -- | Colour sets. darkCol :: [Color] -- | Colour sets. brightCol :: [Color] -- | Colour sets. stdCol :: [Color] -- | Translationg to heavily modified Linux console color RGB values. colorToRGB :: Color -> String -- | Text attributes: foreground and backgroud colors. data Attr Attr :: !Color -> !Color -> Attr -- | foreground colour fg :: Attr -> !Color -- | backgroud color bg :: Attr -> !Color -- | The default attribute, to optimize attribute setting. defAttr :: Attr data AttrChar AttrChar :: !Attr -> !Char -> AttrChar acAttr :: AttrChar -> !Attr acChar :: AttrChar -> !Char instance Show Color instance Eq Color instance Ord Color instance Enum Color instance Bounded Color instance Generic Color instance Show Attr instance Eq Attr instance Ord Attr instance Show AttrChar instance Eq AttrChar instance Ord AttrChar instance Datatype D1Color instance Constructor C1_0Color instance Constructor C1_1Color instance Constructor C1_2Color instance Constructor C1_3Color instance Constructor C1_4Color instance Constructor C1_5Color instance Constructor C1_6Color instance Constructor C1_7Color instance Constructor C1_8Color instance Constructor C1_9Color instance Constructor C1_10Color instance Constructor C1_11Color instance Constructor C1_12Color instance Constructor C1_13Color instance Constructor C1_14Color instance Constructor C1_15Color instance Binary Color instance Enum AttrChar instance Enum Attr instance Hashable Color -- | Game messages displayed on top of the screen for the player to read. module Game.LambdaHack.Common.Msg -- | Re-exported English phrase creation functions, applied to default -- irregular word sets. makePhrase :: [Part] -> Text -- | Re-exported English phrase creation functions, applied to default -- irregular word sets. makeSentence :: [Part] -> Text -- | The type of a single message. type Msg = Text -- | An infix synonym for mappend. -- -- Since: 4.5.0.0 (<>) :: Monoid m => m -> m -> m (<+>) :: Text -> Text -> Text tshow :: Show a => a -> Text toWidth :: Int -> Text -> Text -- | The "press something to see more" mark. moreMsg :: Msg -- | The confirmation request message. yesnoMsg :: Msg -- | Add a space at the message end, for display overlayed over the level -- map. Also trims (does not wrap!) too long lines. In case of newlines, -- displays only the first line, but marks the message as partial. truncateMsg :: X -> Text -> Text -- | The type of a set of messages to show at the screen at once. data Report -- | Empty set of messages. emptyReport :: Report -- | Test if the set of messages is empty. nullReport :: Report -> Bool -- | Construct a singleton set of messages. singletonReport :: Msg -> Report -- | Add message to the end of report. addMsg :: Report -> Msg -> Report -- | Split a messages into chunks that fit in one line. We assume the width -- of the messages line is the same as of level map. splitReport :: X -> Report -> Overlay -- | Render a report as a (possibly very long) string. renderReport :: Report -> Text findInReport :: (ByteString -> Bool) -> Report -> Maybe ByteString lastMsgOfReport :: Report -> (ByteString, Report) -- | The history of reports. data History -- | Empty history of reports. emptyHistory :: History lengthHistory :: History -> Int -- | Construct a singleton history of reports. singletonHistory :: Report -> History mergeHistory :: [(Msg, History)] -> History -- | Add a report to history, handling repetitions. addReport :: Report -> History -> History -- | Render history as many lines of text, wrapping if necessary. renderHistory :: History -> Overlay -- | Take the given prefix of reports from a history. takeHistory :: Int -> History -> History lastReportOfHistory :: History -> Maybe Report -- | A series of screen lines that may or may not fit the width nor height -- of the screen. An overlay may be transformed by adding the first line -- and/or by splitting into a slideshow of smaller overlays. data Overlay emptyOverlay :: Overlay truncateToOverlay :: Text -> Overlay toOverlay :: [Text] -> Overlay -- | A few overlays, displayed one by one upon keypress. When displayed, -- they are trimmed, not wrapped and any lines below the lower screen -- edge are not visible. If the boolean flag is set, the overlay is -- displayed over a blank screen, including the bottom lines. data Slideshow -- | Split an overlay into a slideshow in which each overlay, prefixed by -- msg and postfixed by moreMsg except for the last -- one, fits on the screen wrt height (but lines may be too wide). splitOverlay :: Bool -> Y -> Overlay -> Overlay -> Slideshow -- | Declare the list of raw overlays to be fit for display on the screen. -- In particular, current Report is eiter empty or unimportant -- or contained in the overlays and if any vertical or horizontal -- trimming of the overlays happens, this is intended. toSlideshow :: Bool -> [[Text]] -> Slideshow encodeLine :: [AttrChar] -> ScreenLine encodeOverlay :: [[AttrChar]] -> Overlay type ScreenLine = Vector Int32 toScreenLine :: Text -> ScreenLine -- | Split a string into lines. Avoids ending the line with a character -- other than whitespace or punctuation. Space characters are removed -- from the start, but never from the end of lines. Newlines are -- respected. splitText :: X -> Text -> [Text] instance Show Report instance Binary Report instance Show History instance Binary History instance Show Overlay instance Eq Overlay instance Binary Overlay instance Show Slideshow instance Eq Slideshow instance Monoid Slideshow -- | A list of items with relative frequencies of appearance. module Game.LambdaHack.Common.Frequency -- | The frequency distribution type. Not normalized (operations may or may -- not group the same elements and sum their frequencies). -- -- The Eq instance compares raw representations, not relative, -- normalized frequencies, so operations don't need to preserve the -- expected equalities, unless they do some kind of normalization (see -- Dice). data Frequency a -- | Uniform discrete frequency distribution. uniformFreq :: Text -> [a] -> Frequency a -- | Takes a name and a list of frequencies and items into the frequency -- distribution. toFreq :: Text -> [(Int, a)] -> Frequency a -- | Scale frequecy distribution, multiplying it by a positive integer -- constant. scaleFreq :: Show a => Int -> Frequency a -> Frequency a -- | Change the description of the frequency. renameFreq :: Text -> Frequency a -> Frequency a -- | Set frequency of an element. setFreq :: Eq a => Frequency a -> a -> Int -> Frequency a -- | Test if the frequency distribution is empty. nullFreq :: Frequency a -> Bool -- | give acces to raw frequency values runFrequency :: Frequency a -> [(Int, a)] -- | short description for debug, etc.; keep it lazy, because it's rarely -- used nameFrequency :: Frequency a -> Text maxFreq :: (Show a, Ord a) => Frequency a -> a minFreq :: (Show a, Ord a) => Frequency a -> a meanFreq :: (Show a, Integral a) => Frequency a -> Rational instance Show a => Show (Frequency a) instance Read a => Read (Frequency a) instance Eq a => Eq (Frequency a) instance Ord a => Ord (Frequency a) instance Foldable Frequency instance Traversable Frequency instance Generic (Frequency a) instance Datatype D1Frequency instance Constructor C1_0Frequency instance Selector S1_0_0Frequency instance Selector S1_0_1Frequency instance Binary a => Binary (Frequency a) instance Hashable a => Hashable (Frequency a) instance Alternative Frequency instance MonadPlus Frequency instance Applicative Frequency instance Functor Frequency instance Monad Frequency -- | AI strategies to direct actors not controlled directly by human -- players. No operation in this module involves the State or -- Action type. module Game.LambdaHack.Client.AI.Strategy -- | A strategy is a choice of (non-empty) frequency tables of possible -- actions. data Strategy a nullStrategy :: Strategy a -> Bool -- | Strategy where only the actions from the given single frequency table -- can be picked. liftFrequency :: Frequency a -> Strategy a -- | Strategy with the actions from both argument strategies, with original -- frequencies. (.|) :: Strategy a -> Strategy a -> Strategy a -- | Strategy with no actions at all. reject :: Strategy a -- | Conditionally accepted strategy. (.=>) :: Bool -> Strategy a -> Strategy a -- | Strategy with all actions not satisfying the predicate removed. The -- remaining actions keep their original relative frequency values. only :: (a -> Bool) -> Strategy a -> Strategy a -- | When better choices are towards the start of the list, this is the -- best frequency of the strategy. bestVariant :: Strategy a -> Frequency a -- | Overwrite the description of all frequencies within the strategy. renameStrategy :: Text -> Strategy a -> Strategy a -- | Like return, but pick a name of the single frequency. returN :: Text -> a -> Strategy a mapStrategyM :: Monad m => (a -> m (Maybe b)) -> Strategy a -> m (Strategy b) instance Show a => Show (Strategy a) instance Alternative Strategy instance MonadPlus Strategy instance Applicative Strategy instance Functor Strategy instance Monad Strategy -- | Representation of dice for parameters scaled with current level depth. module Game.LambdaHack.Common.Dice -- | Dice for parameters scaled with current level depth. To the result of -- rolling the first set of dice we add the second, scaled in proportion -- to current depth divided by maximal dungeon depth. The result if then -- multiplied by the scale --- to be used to ensure that dice results are -- multiples of, e.g., 10. The scale is set with |*|. data Dice diceConst :: Dice -> SimpleDice diceLevel :: Dice -> SimpleDice diceScale :: Dice -> Int (|*|) :: Dice -> Int -> Dice d :: Int -> Dice z :: Int -> Dice dl :: Int -> Dice zl :: Int -> Dice intToDice :: Int -> Dice -- | Maximal value of dice. The scaled part taken assuming maximum level. -- Assumes the frequencies are not null. maxDice :: Dice -> Int -- | Minimal value of dice. The scaled part ignored. Assumes the -- frequencies are not null. minDice :: Dice -> Int -- | Mean value of dice. The scaled part taken assuming average level. -- Assumes the frequencies are not null. meanDice :: Dice -> Rational reduceDice :: Dice -> Maybe Int -- | Dice for rolling a pair of integer parameters pertaining to, -- respectively, the X and Y cartesian 2D coordinates. data DiceXY DiceXY :: !Dice -> !Dice -> DiceXY -- | Maximal value of DiceXY. maxDiceXY :: DiceXY -> (Int, Int) -- | Minimal value of DiceXY. minDiceXY :: DiceXY -> (Int, Int) -- | Mean value of DiceXY. meanDiceXY :: DiceXY -> (Rational, Rational) instance Read Dice instance Eq Dice instance Ord Dice instance Generic Dice instance Show DiceXY instance Eq DiceXY instance Ord DiceXY instance Generic DiceXY instance Datatype D1Dice instance Constructor C1_0Dice instance Selector S1_0_0Dice instance Selector S1_0_1Dice instance Selector S1_0_2Dice instance Datatype D1DiceXY instance Constructor C1_0DiceXY instance Binary DiceXY instance Hashable DiceXY instance Num Dice instance Binary Dice instance Hashable Dice instance Show Dice instance Num SimpleDice -- | Effects of content on the game state. No operation in this module -- involves state or monad types. module Game.LambdaHack.Common.Effect -- | 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 a NoEffect :: !Text -> Effect a Hurt :: !Dice -> Effect a Burn :: !Int -> Effect a -- | explode, producing this group of shrapnel Explode :: !Text -> Effect a RefillHP :: !Int -> Effect a RefillCalm :: !Int -> Effect a Dominate :: Effect a Impress :: Effect a CallFriend :: !a -> Effect a Summon :: !Freqs -> !a -> Effect a CreateItem :: !a -> Effect a Ascend :: !Int -> Effect a -- | the Int says if can be placed on last level, etc. Escape :: !Int -> Effect a Paralyze :: !a -> Effect a InsertMove :: !a -> Effect a Teleport :: !a -> Effect a PolyItem :: !CStore -> Effect a Identify :: !CStore -> Effect a SendFlying :: !ThrowMod -> Effect a PushActor :: !ThrowMod -> Effect a PullActor :: !ThrowMod -> Effect a DropBestWeapon :: Effect a -- | symbol ' ' means all, True means hit on drop DropEqp :: !Char -> !Bool -> Effect a -- | symbol ' ' means all ActivateInv :: !Char -> Effect a ApplyPerfume :: Effect a OneOf :: ![Effect a] -> Effect a -- | trigger if item smashed (not applied nor meleed) OnSmash :: !(Effect a) -> Effect a -- | enable the aspect for k clips TimedAspect :: !Int -> !(Aspect a) -> Effect a -- | Aspects of items. Additive (starting at 0) for all items wielded by an -- actor and affect the actor (except Periodic that only affect -- the item and so is not additive). data Aspect a -- | is activated this many times in 100 Periodic :: !a -> Aspect a -- | percentage damage bonus in melee AddHurtMelee :: !a -> Aspect a -- | percentage armor bonus against melee AddArmorMelee :: !a -> Aspect a -- | percentage damage bonus in ranged AddHurtRanged :: !a -> Aspect a -- | percentage armor bonus against ranged AddArmorRanged :: !a -> Aspect a -- | maximal hp AddMaxHP :: !a -> Aspect a -- | maximal calm AddMaxCalm :: !a -> Aspect a -- | speed in m/10s AddSpeed :: !a -> Aspect a -- | skills in particular abilities AddSkills :: !Skills -> Aspect a -- | FOV radius, where 1 means a single tile AddSight :: !a -> Aspect a -- | smell radius, where 1 means a single tile AddSmell :: !a -> Aspect a -- | light radius, where 1 means a single tile AddLight :: !a -> Aspect a -- | Parameters modifying a throw. Not additive and don't start at 0. data ThrowMod ThrowMod :: !Int -> !Int -> ThrowMod -- | fly with this percentage of base throw speed throwVelocity :: ThrowMod -> !Int -- | fly for this percentage of 2 turns throwLinger :: ThrowMod -> !Int -- | Features of item. Affect only the item in question, not the actor, and -- so not additive in any sense. data Feature -- | change to this group when altered ChangeTo :: !Text -> Feature -- | break even when not hitting an enemy Fragile :: Feature -- | don't break even 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: goes to inventory EqpSlot :: !EqpSlot -> !Text -> Feature -- | AI and UI flag: careful, can be precious; don't risk identifying by -- use Precious :: Feature data EqpSlot EqpSlotPeriodic :: EqpSlot EqpSlotAddHurtMelee :: EqpSlot EqpSlotAddArmorMelee :: EqpSlot EqpSlotAddHurtRanged :: EqpSlot EqpSlotAddArmorRanged :: EqpSlot EqpSlotAddMaxHP :: EqpSlot EqpSlotAddMaxCalm :: EqpSlot EqpSlotAddSpeed :: EqpSlot EqpSlotAddSkills :: EqpSlot EqpSlotAddSight :: EqpSlot EqpSlotAddSmell :: EqpSlot EqpSlotAddLight :: EqpSlot EqpSlotWeapon :: EqpSlot -- | Transform an effect using a stateful function. effectTrav :: Effect a -> (a -> State s b) -> State s (Effect b) -- | Transform an aspect using a stateful function. aspectTrav :: Aspect a -> (a -> State s b) -> State s (Aspect b) instance Show a => Show (Aspect a) instance Read a => Read (Aspect a) instance Eq a => Eq (Aspect a) instance Ord a => Ord (Aspect a) instance Generic (Aspect a) instance Functor Aspect instance Show ThrowMod instance Read ThrowMod instance Eq ThrowMod instance Ord ThrowMod instance Generic ThrowMod instance Show a => Show (Effect a) instance Read a => Read (Effect a) instance Eq a => Eq (Effect a) instance Ord a => Ord (Effect a) instance Generic (Effect a) instance Functor Effect instance Show EqpSlot instance Eq EqpSlot instance Ord EqpSlot instance Generic EqpSlot instance Show Feature instance Eq Feature instance Ord Feature instance Generic Feature instance Datatype D1Aspect instance Constructor C1_0Aspect instance Constructor C1_1Aspect instance Constructor C1_2Aspect instance Constructor C1_3Aspect instance Constructor C1_4Aspect instance Constructor C1_5Aspect instance Constructor C1_6Aspect instance Constructor C1_7Aspect instance Constructor C1_8Aspect instance Constructor C1_9Aspect instance Constructor C1_10Aspect instance Constructor C1_11Aspect instance Datatype D1ThrowMod instance Constructor C1_0ThrowMod instance Selector S1_0_0ThrowMod instance Selector S1_0_1ThrowMod instance Datatype D1Effect instance Constructor C1_0Effect instance Constructor C1_1Effect instance Constructor C1_2Effect instance Constructor C1_3Effect instance Constructor C1_4Effect instance Constructor C1_5Effect instance Constructor C1_6Effect instance Constructor C1_7Effect instance Constructor C1_8Effect instance Constructor C1_9Effect instance Constructor C1_10Effect instance Constructor C1_11Effect instance Constructor C1_12Effect instance Constructor C1_13Effect instance Constructor C1_14Effect instance Constructor C1_15Effect instance Constructor C1_16Effect instance Constructor C1_17Effect instance Constructor C1_18Effect instance Constructor C1_19Effect instance Constructor C1_20Effect instance Constructor C1_21Effect instance Constructor C1_22Effect instance Constructor C1_23Effect instance Constructor C1_24Effect instance Constructor C1_25Effect instance Constructor C1_26Effect instance Constructor C1_27Effect instance Datatype D1EqpSlot instance Constructor C1_0EqpSlot instance Constructor C1_1EqpSlot instance Constructor C1_2EqpSlot instance Constructor C1_3EqpSlot instance Constructor C1_4EqpSlot instance Constructor C1_5EqpSlot instance Constructor C1_6EqpSlot instance Constructor C1_7EqpSlot instance Constructor C1_8EqpSlot instance Constructor C1_9EqpSlot instance Constructor C1_10EqpSlot instance Constructor C1_11EqpSlot instance Constructor C1_12EqpSlot instance Datatype D1Feature instance Constructor C1_0Feature instance Constructor C1_1Feature instance Constructor C1_2Feature instance Constructor C1_3Feature instance Constructor C1_4Feature instance Constructor C1_5Feature instance Constructor C1_6Feature instance Constructor C1_7Feature instance Binary EqpSlot instance Binary Feature instance Binary ThrowMod instance Binary a => Binary (Aspect a) instance Binary a => Binary (Effect a) instance Hashable EqpSlot instance Hashable Feature instance Hashable ThrowMod instance Hashable a => Hashable (Aspect a) instance Hashable a => Hashable (Effect a) -- | Terrain tile features. module Game.LambdaHack.Common.Feature -- | All possible terrain tile features. data Feature -- | causes the effect when triggered Cause :: !(Effect Int) -> Feature -- | goes from a closed to an open tile when altered OpenTo :: !Text -> Feature -- | goes from an open to a closed tile when altered CloseTo :: !Text -> Feature -- | alters tile, but does not change walkability ChangeTo :: !Text -> Feature -- | when hidden, looks as a tile of the group HideAs :: !Text -> Feature -- | if secret, can be revealed to belong to the group RevealAs :: !Text -> Feature -- | actors can walk through Walkable :: Feature -- | actors can see through Clear :: Feature -- | is not lit with an ambient shine Dark :: Feature -- | may not be what it seems (clients only) Suspect :: Feature -- | sustains the effect continuously, TODO Aura :: !(Effect Int) -> Feature -- | can never be excavated nor seen through Impenetrable :: Feature -- | initial items often generated there OftenItem :: Feature -- | initial actors and stairs often generated there OftenActor :: Feature -- | no items ever generated there NoItem :: Feature -- | no actors nor stairs ever generated there NoActor :: Feature -- | used for visible trails throughout the level Trail :: Feature instance Show Feature instance Read Feature instance Eq Feature instance Ord Feature instance Generic Feature instance Datatype D1Feature instance Constructor C1_0Feature instance Constructor C1_1Feature instance Constructor C1_2Feature instance Constructor C1_3Feature instance Constructor C1_4Feature instance Constructor C1_5Feature instance Constructor C1_6Feature instance Constructor C1_7Feature instance Constructor C1_8Feature instance Constructor C1_9Feature instance Constructor C1_10Feature instance Constructor C1_11Feature instance Constructor C1_12Feature instance Constructor C1_13Feature instance Constructor C1_14Feature instance Constructor C1_15Feature instance Constructor C1_16Feature instance Hashable Feature instance Binary Feature -- | Representation of probabilities and random computations. module Game.LambdaHack.Common.Random -- | The monad of computations with random generator state. The lazy state -- monad is OK here: the state is small and regularly forced. type Rnd a = State StdGen a -- | Get a random object within a range with a uniform distribution. randomR :: Random a => (a, a) -> Rnd a -- | Get a random object of a given type with a uniform distribution. random :: Random a => Rnd a -- | Get any element of a list with equal probability. oneOf :: [a] -> Rnd a -- | Gen an element according to a frequency distribution. frequency :: Show a => Frequency a -> Rnd a -- | Fractional chance. type Chance = Rational -- | Give True, with probability determined by the fraction. chance :: Chance -> Rnd Bool -- | Cast dice scaled with current level depth. Note that at the first -- level, the scaled dice are always ignored. castDice :: AbsDepth -> AbsDepth -> Dice -> Rnd Int -- | Cast dice scaled with current level depth and return True if -- the results is greater than 50. chanceDice :: AbsDepth -> AbsDepth -> Dice -> Rnd Bool -- | Cast dice, scaled with current level depth, for coordinates. castDiceXY :: AbsDepth -> AbsDepth -> DiceXY -> Rnd (Int, Int) -- | 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 random room according to given parameters. mkRoom :: (X, Y) -> (X, Y) -> Area -> Rnd Area -- | Create a void room, i.e., a single point area within the designated -- area. mkVoidRoom :: 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 :: (X, Y) -> Rnd [(Point, Point)] -- | Pick a single random connection between adjacent areas within a grid. randomConnection :: (X, Y) -> Rnd (Point, Point) -- | The coordinates of consecutive fields of a corridor. type Corridor = [Point] -- | Try to connect two interiors of places with a corridor. Choose -- entrances at least 4 or 3 tiles distant from the edges, if the place -- is big enough. Note that with pfence == FNone, the area -- considered is the strict interior of the place, without the outermost -- tiles. connectPlaces :: (Area, Area) -> (Area, Area) -> Rnd Corridor -- | The type of cave layout kinds. module Game.LambdaHack.Content.CaveKind -- | Parameters for the generation of dungeon levels. data CaveKind CaveKind :: !Char -> !Text -> !Freqs -> !X -> !Y -> !DiceXY -> !DiceXY -> !DiceXY -> !Dice -> !Dice -> !Rational -> !Rational -> !Int -> !Chance -> !Chance -> !Int -> !Freqs -> !Dice -> !Freqs -> !Freqs -> !Bool -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> CaveKind -- | a symbol csymbol :: CaveKind -> !Char -- | short description cname :: CaveKind -> !Text -- | frequency within groups cfreq :: CaveKind -> !Freqs -- | 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 cminPlaceSize :: CaveKind -> !DiceXY -- | maximal size of places cmaxPlaceSize :: CaveKind -> !DiceXY -- | the chance a place is dark cdarkChance :: CaveKind -> !Dice -- | the chance the cave is dark cnightChance :: CaveKind -> !Dice -- | a proportion of extra connections cauxConnects :: CaveKind -> !Rational -- | at most this proportion of rooms void cmaxVoid :: CaveKind -> !Rational -- | minimal distance between stairs cminStairDist :: CaveKind -> !Int -- | 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 -- | actor groups to consider cactorFreq :: CaveKind -> !Freqs -- | the number of items in the cave citemNum :: CaveKind -> !Dice -- | item groups to consider citemFreq :: CaveKind -> !Freqs -- | place groups to consider cplaceFreq :: CaveKind -> !Freqs -- | are passable default tiles permitted cpassable :: CaveKind -> !Bool -- | the default cave tile group name cdefTile :: CaveKind -> !Text -- | the dark cave corridor tile group name cdarkCorTile :: CaveKind -> !Text -- | the lit cave corridor tile group name clitCorTile :: CaveKind -> !Text -- | the filler wall group name cfillerTile :: CaveKind -> !Text -- | the outer fence wall group name couterFenceTile :: CaveKind -> !Text -- | the dark place plan legend group name clegendDarkTile :: CaveKind -> !Text -- | the lit place plan legend group name clegendLitTile :: CaveKind -> !Text -- | Filter a list of kinds, passing through only the incorrect ones, if -- any. -- -- Catch caves with not enough space for all the places. Check the size -- of the cave descriptions to make sure they fit on screen. validateCaveKind :: [CaveKind] -> [CaveKind] instance Show CaveKind -- | Frontend-independent keyboard input operations. module Game.LambdaHack.Client.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 Home :: Key -- | a keypad key for a character (digits and operators) KP :: !Char -> Key -- | a single printable character Char :: !Char -> Key -- | an unknown key, registered to warn the user Unknown :: !Text -> Key showKey :: Key -> Text -- | Configurable event handler for the direction keys. Used for directed -- commands such as close door. handleDir :: Bool -> Bool -> KM -> (Vector -> a) -> a -> a dirAllKey :: Bool -> Bool -> [Key] -- | Binding of both sets of movement keys. moveBinding :: Bool -> Bool -> (Vector -> a) -> (Vector -> a) -> [(KM, a)] mkKM :: String -> 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. keyTranslate :: String -> Key -- | Our own encoding of modifiers. Incomplete. data Modifier NoModifier :: Modifier Control :: Modifier data KM KM :: !Modifier -> !Key -> KM modifier :: KM -> !Modifier key :: KM -> !Key -- | Show a key with a modifier, if any. showKM :: KM -> Text escKM :: KM spaceKM :: KM pgupKM :: KM pgdnKM :: KM instance Read Key instance Ord Key instance Eq Key instance Generic Key instance Read Modifier instance Ord Modifier instance Eq Modifier instance Generic Modifier instance Read KM instance Ord KM instance Eq KM instance Generic KM instance Datatype D1Key instance Constructor C1_0Key instance Constructor C1_1Key instance Constructor C1_2Key instance Constructor C1_3Key instance Constructor C1_4Key instance Constructor C1_5Key instance Constructor C1_6Key instance Constructor C1_7Key instance Constructor C1_8Key instance Constructor C1_9Key instance Constructor C1_10Key instance Constructor C1_11Key instance Constructor C1_12Key instance Constructor C1_13Key instance Constructor C1_14Key instance Constructor C1_15Key instance Constructor C1_16Key instance Constructor C1_17Key instance Datatype D1Modifier instance Constructor C1_0Modifier instance Constructor C1_1Modifier instance Datatype D1KM instance Constructor C1_0KM instance Selector S1_0_0KM instance Selector S1_0_1KM instance Binary KM instance Show KM instance Binary Modifier instance Binary Key -- | Saving and restoring server game state. module Game.LambdaHack.Common.Save type ChanSave a = MVar (Maybe a) saveToChan :: ChanSave a -> a -> IO () wrapInSaves :: Binary a => (a -> FilePath) -> (ChanSave a -> IO ()) -> IO () -- | Restore a saved game, if it exists. Initialize directory structure and -- cope over data files, if needed. restoreGame :: Binary a => String -> [(FilePath, FilePath)] -> (FilePath -> IO FilePath) -> IO (Maybe a) delayPrint :: Text -> IO () -- | Abstract syntax human player commands. module Game.LambdaHack.Client.UI.HumanCmd data CmdCategory CmdMenu :: CmdCategory CmdMove :: CmdCategory CmdItem :: CmdCategory CmdTgt :: CmdCategory CmdAuto :: CmdCategory CmdMeta :: CmdCategory CmdDebug :: CmdCategory CmdMinimal :: CmdCategory -- | Abstract syntax of player commands. data HumanCmd Move :: !Vector -> HumanCmd Run :: !Vector -> HumanCmd Wait :: HumanCmd MoveItem :: ![CStore] -> !CStore -> !Text -> !Text -> !Bool -> HumanCmd Project :: ![Trigger] -> HumanCmd Apply :: ![Trigger] -> HumanCmd AlterDir :: ![Trigger] -> HumanCmd TriggerTile :: ![Trigger] -> HumanCmd StepToTarget :: HumanCmd GameRestart :: !Text -> HumanCmd GameExit :: HumanCmd GameSave :: HumanCmd Automate :: HumanCmd GameDifficultyCycle :: HumanCmd PickLeader :: !Int -> HumanCmd MemberCycle :: HumanCmd MemberBack :: HumanCmd DescribeItem :: !CStore -> HumanCmd AllOwned :: HumanCmd SelectActor :: HumanCmd SelectNone :: HumanCmd Clear :: HumanCmd Repeat :: !Int -> HumanCmd Record :: HumanCmd History :: HumanCmd MarkVision :: HumanCmd MarkSmell :: HumanCmd MarkSuspect :: HumanCmd Help :: HumanCmd MainMenu :: HumanCmd Macro :: !Text -> ![String] -> HumanCmd MoveCursor :: !Vector -> !Int -> HumanCmd TgtFloor :: HumanCmd TgtEnemy :: HumanCmd TgtUnknown :: HumanCmd TgtItem :: HumanCmd TgtStair :: !Bool -> HumanCmd TgtAscend :: !Int -> HumanCmd EpsIncr :: !Bool -> HumanCmd TgtClear :: HumanCmd Cancel :: HumanCmd Accept :: HumanCmd 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 TriggerFeature :: !Part -> !Part -> !Feature -> Trigger verb :: Trigger -> !Part object :: Trigger -> !Part feature :: Trigger -> !Feature -- | Commands that are forbidden on a remote level, because they would -- usually take time when invoked on one. Note that some commands that -- take time are not included, because they don't take time in targeting -- mode. noRemoteHumanCmd :: HumanCmd -> Bool categoryDescription :: CmdCategory -> Text -- | Description of player commands. cmdDescription :: HumanCmd -> Text instance Show CmdCategory instance Read CmdCategory instance Eq CmdCategory instance Show Trigger instance Read Trigger instance Eq Trigger instance Ord Trigger instance Show HumanCmd instance Read HumanCmd instance Eq HumanCmd instance Ord HumanCmd -- | The type of key-command mappings to be used for the UI. module Game.LambdaHack.Client.UI.Content.KeyKind -- | Key-command mappings to be used for the UI. data KeyKind KeyKind :: ![(KM, ([CmdCategory], HumanCmd))] -> KeyKind -- | default client UI commands rhumanCommands :: KeyKind -> ![(KM, ([CmdCategory], HumanCmd))] -- | Description of effects. No operation in this module involves state or -- monad types. module Game.LambdaHack.Common.EffectDescription effectToSuffix :: Effect Int -> Text aspectToSuffix :: Aspect Int -> Text featureToSuff :: Feature -> Text kindEffectToSuffix :: Effect Dice -> Text kindAspectToSuffix :: Aspect Dice -> Text -- | 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. data TileKind TileKind :: !Char -> !Text -> !Freqs -> !Color -> !Color -> ![Feature] -> TileKind -- | map symbol tsymbol :: TileKind -> !Char -- | short description tname :: TileKind -> !Text -- | frequency within groups tfreq :: TileKind -> !Freqs -- | map color tcolor :: TileKind -> !Color -- | map color when not in FOV tcolor2 :: TileKind -> !Color -- | properties tfeature :: TileKind -> ![Feature] -- | Filter a list of kinds, passing through only the incorrect ones, if -- any. -- -- If tiles look the same on the map, the description and the 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 iiles may -- freely differ wrt dungeon generation, AI preferences, etc. validateTileKind :: [TileKind] -> [TileKind] -- | Features of tiles that differentiate them substantially from one -- another. By tile content validation condition, this means the player -- can tell such tile apart, and only looking at the map, not tile name. -- 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 instance Show TileKind -- | Screen frames and animations. module Game.LambdaHack.Client.UI.Animation -- | The data sufficent to draw a single game screen frame. data SingleFrame SingleFrame :: ![ScreenLine] -> !Overlay -> ![ScreenLine] -> !Bool -> SingleFrame -- | screen, from top to bottom, line by line sfLevel :: SingleFrame -> ![ScreenLine] -- | some extra lines to show over the top sfTop :: SingleFrame -> !Overlay -- | some extra lines to show at the bottom sfBottom :: SingleFrame -> ![ScreenLine] -- | display only sfTop, on blank screen sfBlank :: SingleFrame -> !Bool decodeLine :: ScreenLine -> [AttrChar] encodeLine :: [AttrChar] -> ScreenLine -- | Overlays the sfTop and sfBottom fields onto the -- sfLevel field. The resulting frame has empty sfTop -- and sfBottom. To be used by simple frontends that don't -- display overlays in separate windowspanesscrolled views. overlayOverlay :: SingleFrame -> SingleFrame -- | Animation is a list of frame modifications to play one by one, where -- each modification if a map from positions to level map symbols. data Animation -- | Sequences of screen frames, including delays. type Frames = [Maybe SingleFrame] -- | Render animations on top of a screen frame. renderAnim :: X -> Y -> SingleFrame -> Animation -> Frames restrictAnim :: EnumSet Point -> Animation -> Animation -- | Attack animation. A part of it also reused for self-damage and -- healing. twirlSplash :: (Point, Point) -> Color -> Color -> Animation -- | Attack that hits through a block. blockHit :: (Point, Point) -> Color -> Color -> Animation -- | Attack that is blocked. blockMiss :: (Point, Point) -> Animation -- | Death animation for an organic body. deathBody :: Point -> Animation -- | Swap-places animation, both hostile and friendly. swapPlaces :: (Point, Point) -> Animation fadeout :: Bool -> Bool -> Int -> X -> Y -> Rnd Animation instance Eq SingleFrame instance Show SingleFrame instance Generic SingleFrame instance Eq Animation instance Show Animation instance Monoid Animation instance Datatype D1SingleFrame instance Constructor C1_0SingleFrame instance Selector S1_0_0SingleFrame instance Selector S1_0_1SingleFrame instance Selector S1_0_2SingleFrame instance Selector S1_0_3SingleFrame instance Binary SingleFrame -- | The appearance of in-game items, as communicated to the player. module Game.LambdaHack.Common.Flavour -- | The type of item flavours. data Flavour -- | Turn a colour set into a flavour set. zipPlain :: [Color] -> [Flavour] -- | Turn a colour set into a flavour set. zipFancy :: [Color] -> [Flavour] -- | The standard full set of flavours. stdFlav :: [Flavour] -- | Get the underlying base colour of a flavour. flavourToColor :: Flavour -> Color -- | Construct the full name of a flavour. flavourToName :: Flavour -> Text -- | Simple names for team colors (bright colours preferred). colorToTeamName :: Color -> Text -- | Human-readable names, for item colors. The simple set. colorToPlainName :: Color -> Text -- | Human-readable names, for item colors. The fancy set. colorToFancyName :: Color -> Text instance Show Flavour instance Eq Flavour instance Ord Flavour instance Generic Flavour instance Datatype D1Flavour instance Constructor C1_0Flavour instance Selector S1_0_0Flavour instance Selector S1_0_1Flavour instance Binary Flavour instance Hashable Flavour -- | The type of kinds of weapons, treasure, organs, shrapnel and actors. module Game.LambdaHack.Content.ItemKind -- | Item properties that are fixed for a given kind of items. data ItemKind ItemKind :: !Char -> !Text -> !Freqs -> ![Flavour] -> !Dice -> ![(Int, Int)] -> !Part -> !Int -> ![Aspect Dice] -> ![Effect Dice] -> ![Feature] -> !Text -> ![(Text, CStore)] -> ItemKind -- | map symbol isymbol :: ItemKind -> !Char -- | generic name iname :: ItemKind -> !Text -- | frequency within groups ifreq :: ItemKind -> !Freqs -- | possible flavours iflavour :: ItemKind -> ![Flavour] -- | created in that quantity icount :: ItemKind -> !Dice -- | rarity on given depths irarity :: ItemKind -> ![(Int, Int)] -- | the verb for applying and melee iverbHit :: ItemKind -> !Part -- | weight in grams iweight :: ItemKind -> !Int -- | keep the aspect continuously iaspects :: ItemKind -> ![Aspect Dice] -- | cause the effect when triggered ieffects :: ItemKind -> ![Effect Dice] -- | public properties ifeature :: ItemKind -> ![Feature] -- | description idesc :: ItemKind -> !Text -- | accompanying organs and items ikit :: ItemKind -> ![(Text, CStore)] toVelocity :: Int -> Feature toLinger :: Int -> Feature -- | Filter a list of kinds, passing through only the incorrect ones, if -- any. validateItemKind :: [ItemKind] -> [ItemKind] instance Show ItemKind -- | General content types and operations. module Game.LambdaHack.Common.Kind -- | Content identifiers for the content type c. data Id c -- | Type family for auxiliary data structures for speeding up content -- operations. -- | Content operations for the content of type a. data Ops a Ops :: (Id a -> a) -> (Text -> Id a) -> (Text -> (a -> Bool) -> Rnd (Maybe (Id a))) -> (forall b. (Id a -> a -> b -> b) -> b -> b) -> (forall b. Text -> (Int -> Id a -> a -> b -> b) -> b -> b) -> !(Id a, Id a) -> !(Maybe (Speedup a)) -> Ops a -- | the 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 -> Text -> Id a -- | pick a random id belonging to a group and satisfying a predicate opick :: Ops a -> Text -> (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 over the given group only ofoldrGroup :: Ops a -> forall b. Text -> (Int -> Id a -> a -> b -> b) -> b -> b -- | bounds of identifiers of content a obounds :: Ops a -> !(Id a, Id a) -- | auxiliary speedup components ospeedup :: Ops a -> !(Maybe (Speedup a)) -- | Operations for all content types, gathered together. data COps COps :: !(Ops CaveKind) -> !(Ops FactionKind) -> !(Ops ItemKind) -> !(Ops ModeKind) -> !(Ops PlaceKind) -> !(Ops RuleKind) -> !(Ops TileKind) -> COps cocave :: COps -> !(Ops CaveKind) cofaction :: COps -> !(Ops FactionKind) coitem :: COps -> !(Ops ItemKind) comode :: COps -> !(Ops ModeKind) coplace :: COps -> !(Ops PlaceKind) corule :: COps -> !(Ops RuleKind) cotile :: COps -> !(Ops TileKind) -- | Create content operations for type a from definition of -- content of type a. createOps :: Show a => ContentDef a -> Ops a -- | The standard ruleset used for level operations. stdRuleset :: Ops RuleKind -> RuleKind data Tab createTab :: Ops TileKind -> (TileKind -> Bool) -> Tab accessTab :: Tab -> Id TileKind -> Bool instance Show (Id c) instance Eq (Id c) instance Ord (Id c) instance Ix (Id c) instance Enum (Id c) instance Bounded (Id c) instance Binary (Id c) instance Eq COps instance Show COps -- | Weapons, treasure and all the other items in the game. No operation in -- this module involves the state or any of our custom monads. module Game.LambdaHack.Common.Item -- | A unique identifier of an item in the dungeon. data ItemId -- | Game items in actor possesion or strewn around the dungeon. The fields -- jsymbol, jname and jflavour make it -- possible to refer to and draw an unidentified item. Full information -- about item is available through the jkindIx index as soon as -- the item is identified. data Item Item :: !ItemKindIx -> !LevelId -> !Char -> !Text -> !Flavour -> ![Feature] -> !Int -> Item -- | index pointing to the kind of the item jkindIx :: Item -> !ItemKindIx -- | the level on which item was created jlid :: Item -> !LevelId -- | individual map symbol jsymbol :: Item -> !Char -- | individual generic name jname :: Item -> !Text -- | individual flavour jflavour :: Item -> !Flavour -- | public properties jfeature :: Item -> ![Feature] -- | weight in grams, obvious enough jweight :: Item -> !Int seedToAspectsEffects :: ItemSeed -> ItemKind -> AbsDepth -> AbsDepth -> ItemAspectEffect -- | An index of the kind id of an item. Clients have partial knowledge how -- these idexes map to kind ids. They gain knowledge by identifying -- items. data ItemKindIx -- | The map of item kind indexes to item kind ids. The full map, as known -- by the server, is a bijection. type Discovery = EnumMap ItemKindIx (Id ItemKind) -- | A seed for rolling aspects and effects of an item Clients have partial -- knowledge of how item ids map to the seeds. They gain knowledge by -- identifying items. data ItemSeed data ItemAspectEffect ItemAspectEffect :: ![Aspect Int] -> ![Effect Int] -> ItemAspectEffect -- | the aspects of the item jaspects :: ItemAspectEffect -> ![Aspect Int] -- | the effects when activated jeffects :: ItemAspectEffect -> ![Effect Int] -- | The map of item ids to item aspects and effects. The full map is known -- by the server. type DiscoAE = EnumMap ItemId ItemAspectEffect data ItemFull ItemFull :: !Item -> !Int -> !(Maybe ItemDisco) -> ItemFull itemBase :: ItemFull -> !Item itemK :: ItemFull -> !Int itemDisco :: ItemFull -> !(Maybe ItemDisco) data ItemDisco ItemDisco :: Id ItemKind -> ItemKind -> Maybe ItemAspectEffect -> ItemDisco itemKindId :: ItemDisco -> Id ItemKind itemKind :: ItemDisco -> ItemKind itemAE :: ItemDisco -> Maybe ItemAspectEffect itemNoDisco :: (Item, Int) -> ItemFull itemNoAE :: ItemFull -> ItemFull type ItemBag = EnumMap ItemId Int -- | All items in the dungeon (including in actor inventories), indexed by -- item identifier. type ItemDict = EnumMap ItemId Item type ItemKnown = (Item, ItemAspectEffect) instance Show ItemId instance Eq ItemId instance Ord ItemId instance Enum ItemId instance Binary ItemId instance Show ItemKindIx instance Eq ItemKindIx instance Ord ItemKindIx instance Enum ItemKindIx instance Ix ItemKindIx instance Hashable ItemKindIx instance Binary ItemKindIx instance Show ItemSeed instance Eq ItemSeed instance Ord ItemSeed instance Enum ItemSeed instance Hashable ItemSeed instance Binary ItemSeed instance Show ItemAspectEffect instance Eq ItemAspectEffect instance Generic ItemAspectEffect instance Show ItemDisco instance Show Item instance Eq Item instance Generic Item instance Show ItemFull instance Datatype D1ItemAspectEffect instance Constructor C1_0ItemAspectEffect instance Selector S1_0_0ItemAspectEffect instance Selector S1_0_1ItemAspectEffect instance Datatype D1Item instance Constructor C1_0Item instance Selector S1_0_0Item instance Selector S1_0_1Item instance Selector S1_0_2Item instance Selector S1_0_3Item instance Selector S1_0_4Item instance Selector S1_0_5Item instance Selector S1_0_6Item instance Binary Item instance Hashable Item instance Hashable ItemAspectEffect instance Binary ItemAspectEffect -- | 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 -- | The last time a hero left a smell in a given tile. To be used by -- monsters that hunt by smell. type SmellTime = Time -- | Whether a tile kind has the given feature. kindHasFeature :: Feature -> TileKind -> Bool -- | Whether a tile kind (specified by its id) has the given feature. hasFeature :: Ops TileKind -> Feature -> Id TileKind -> Bool -- | Whether a tile does not block vision. Essential for efficiency of -- FOV, hence tabulated. isClear :: Ops TileKind -> Id TileKind -> Bool -- | Whether a tile is lit on its own. Essential for efficiency of -- Perception, hence tabulated. isLit :: Ops TileKind -> Id TileKind -> Bool -- | Whether actors can walk into a tile. Essential for efficiency of -- pathfinding, hence tabulated. isWalkable :: Ops TileKind -> Id TileKind -> Bool isPassableKind :: TileKind -> Bool -- | Whether actors can walk into a tile, perhaps opening a door first, -- perhaps a hidden door. Essential for efficiency of pathfinding, hence -- tabulated. isPassable :: Ops TileKind -> Id TileKind -> Bool -- | Whether a tile is a door, open or closed. Essential for efficiency of -- pathfinding, hence tabulated. isDoor :: Ops TileKind -> Id TileKind -> Bool -- | Whether a tile is suspect. Essential for efficiency of pathfinding, -- hence tabulated. isSuspect :: Ops TileKind -> Id TileKind -> Bool -- | Whether one can easily explore a tile, possibly finding a treasure or -- a clue. 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. isExplorable :: Ops TileKind -> Id TileKind -> Bool -- | The player can't tell one tile from the other. lookSimilar :: TileKind -> TileKind -> Bool speedup :: Bool -> Ops TileKind -> Speedup TileKind openTo :: Ops TileKind -> Id TileKind -> Rnd (Id TileKind) closeTo :: Ops TileKind -> Id TileKind -> Rnd (Id TileKind) causeEffects :: Ops TileKind -> Id TileKind -> [Effect Int] revealAs :: Ops TileKind -> Id TileKind -> Rnd (Id TileKind) hideAs :: Ops TileKind -> Id TileKind -> Id TileKind -- | 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 -- | Whether a tile kind (specified by its id) has a ChangeTo feature. -- Essential for efficiency of pathfinding, hence tabulated. isChangeable :: Ops TileKind -> Id TileKind -> Bool isEscape :: Ops TileKind -> Id TileKind -> Bool isStair :: Ops TileKind -> Id TileKind -> Bool -- | Determining the strongest item wrt some property. No operation in this -- module involves the state or any of our custom monads. module Game.LambdaHack.Common.ItemStrongest strengthOnSmash :: ItemFull -> [Effect Int] strengthToThrow :: Item -> ThrowMod strengthEqpSlot :: Item -> Maybe (EqpSlot, Text) strengthFromEqpSlot :: EqpSlot -> ItemFull -> Maybe Int strongestSlotNoFilter :: EqpSlot -> [(ItemId, ItemFull)] -> [(Int, (ItemId, ItemFull))] strongestSlot :: EqpSlot -> [(ItemId, ItemFull)] -> [(Int, (ItemId, ItemFull))] sumSlotNoFilter :: EqpSlot -> [ItemFull] -> Int sumSkills :: [ItemFull] -> Skills totalRange :: Item -> Int computeTrajectory :: Int -> Int -> Int -> [Point] -> ([Vector], (Speed, Int)) itemTrajectory :: Item -> [Point] -> ([Vector], (Speed, Int)) unknownPrecious :: ItemFull -> Bool permittedRanged :: ItemFull -> Maybe Int -> Bool unknownMelee :: [ItemFull] -> Bool -- | Descripitons of items. module Game.LambdaHack.Common.ItemDescription -- | The part of speech describing the item parameterized by the number of -- effects/aspects to show.. partItemN :: Bool -> Int -> CStore -> ItemFull -> (Part, Part) -- | The part of speech describing the item. partItem :: CStore -> ItemFull -> (Part, Part) partItemWs :: Int -> CStore -> ItemFull -> Part partItemAW :: CStore -> ItemFull -> Part partItemWownW :: Part -> CStore -> ItemFull -> Part itemDesc :: CStore -> ItemFull -> Overlay textAllAE :: Bool -> CStore -> ItemFull -> [Text] viewItem :: Item -> (Char, Attr) -- | Server types and operations for items that don't involve server state -- nor our custom monads. module Game.LambdaHack.Server.ItemRev -- | Reverse item map, for item creation, to keep items and item -- identifiers in bijection. type ItemRev = HashMap ItemKnown ItemId -- | Build an item with the given stats. buildItem :: FlavourMap -> DiscoRev -> Id ItemKind -> ItemKind -> LevelId -> Item -- | Generate an item based on level. newItem :: COps -> FlavourMap -> DiscoRev -> Freqs -> LevelId -> AbsDepth -> AbsDepth -> Rnd (Maybe (ItemKnown, ItemFull, ItemSeed, Int, Text)) -- | The reverse map to Discovery, needed for item creation. type DiscoRev = EnumMap (Id ItemKind) ItemKindIx serverDiscos :: Ops ItemKind -> Rnd (Discovery, DiscoRev) -- | The map of item ids to item seeds. The full map is known by the -- server. type ItemSeedDict = EnumMap ItemId ItemSeed -- | Flavours assigned by the server to item kinds, in this particular -- game. data FlavourMap emptyFlavourMap :: FlavourMap -- | Randomly chooses flavour for all item kinds for this game. dungeonFlavourMap :: Ops ItemKind -> Rnd FlavourMap instance Show FlavourMap instance Binary FlavourMap -- | Actors in the game: heroes, monsters, etc. No operation in this module -- involves the State or Action type. module Game.LambdaHack.Common.Actor -- | A unique identifier of an actor in the dungeon. data ActorId -- | Chance that a new monster is generated. Currently depends on the -- number of monsters already present, and on the level. In the future, -- the strength of the character and the strength of the monsters present -- could further influence the chance, and the chance could also affect -- which monster is generated. How many and which monsters are generated -- will also depend on the cave kind used to build the level. monsterGenChance :: AbsDepth -> AbsDepth -> Int -> Rnd Bool -- | The part of speech describing the actor. partActor :: Actor -> Part -- | The part of speech containing the actor pronoun. partPronoun :: Actor -> Part -- | Actor properties that are changing throughout the game. If they are -- dublets of properties from ActorKind, they are usually -- modified temporarily, but tend to return to the original value from -- ActorKind over time. E.g., HP. data Actor Actor :: !ItemId -> !Char -> !Text -> !Text -> !Color -> !Time -> !Int64 -> !ResDelta -> !Int64 -> !ResDelta -> !Point -> !Point -> !LevelId -> !LevelId -> !FactionId -> !FactionId -> !(Maybe ([Vector], Speed)) -> !ItemBag -> !ItemBag -> !ItemBag -> !Bool -> !Bool -> Actor btrunk :: Actor -> !ItemId -- | individual map symbol bsymbol :: Actor -> !Char -- | individual name bname :: Actor -> !Text -- | individual pronoun bpronoun :: Actor -> !Text -- | individual map color Resources bcolor :: Actor -> !Color -- | absolute time of next action btime :: Actor -> !Time -- | 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 Location bcalmDelta :: Actor -> !ResDelta -- | current position bpos :: Actor -> !Point -- | previous position boldpos :: Actor -> !Point -- | current level blid :: Actor -> !LevelId -- | previous level boldlid :: Actor -> !LevelId -- | faction the actor belongs to bfid :: Actor -> !FactionId -- | previous faction of the actor boldfid :: Actor -> !FactionId -- | trajectory the actor must travel and his travel speed Items btrajectory :: Actor -> !(Maybe ([Vector], Speed)) -- | organs borgan :: Actor -> !ItemBag -- | personal equipment beqp :: Actor -> !ItemBag -- | personal inventory Assorted binv :: Actor -> !ItemBag -- | is the actor waiting right now? bwait :: Actor -> !Bool -- | is a projectile? (shorthand only, this can be deduced from bkind) bproj :: Actor -> !Bool data ResDelta ResDelta :: !Int64 -> !Int64 -> ResDelta -- | resource change this player turn resCurrentTurn :: ResDelta -> !Int64 -- | resource change last player turn resPreviousTurn :: ResDelta -> !Int64 deltaSerious :: ResDelta -> Bool deltaMild :: ResDelta -> Bool xM :: Int -> Int64 minusM :: Int64 minusTwoM :: Int64 oneM :: Int64 bspeed :: Actor -> [ItemFull] -> Speed -- | A template for a new actor. actorTemplate :: ItemId -> Char -> Text -> Text -> Color -> Int64 -> Int64 -> Point -> LevelId -> Time -> FactionId -> Actor -- | Add time taken by a single step at the actor's current speed. timeShiftFromSpeed :: Actor -> [ItemFull] -> Time -> Time -- | Whether an actor is braced for combat this clip. braced :: Actor -> Bool -- | The actor waited last turn. waitedLastTurn :: Actor -> Bool actorDying :: Actor -> Bool actorNewBorn :: Actor -> Bool hpTooLow :: Actor -> [ItemFull] -> Bool -- | Checks for the presence of actors in a position. Does not check if the -- tile is walkable. unoccupied :: [Actor] -> Point -> Bool -- | All actors on the level, indexed by actor identifier. type ActorDict = EnumMap ActorId Actor -- | How long until an actor's smell vanishes from a tile. smellTimeout :: Delta Time checkAdjacent :: Actor -> Actor -> Bool mapActorItems_ :: Monad m => (ItemId -> Int -> m a) -> Actor -> m () ppCStore :: CStore -> Text ppContainer :: Container -> Text instance Show ResDelta instance Eq ResDelta instance Show Actor instance Eq Actor instance Binary ResDelta instance Binary Actor -- | Factions taking part in the game: e.g., two human players controlling -- the hero faction battling the monster and the animal factions. module Game.LambdaHack.Common.Faction -- | A unique identifier of a faction in a game. data FactionId -- | All factions in the game, indexed by faction identifier. type FactionDict = EnumMap FactionId Faction data Faction Faction :: !(Id FactionKind) -> !Text -> !Color -> !Player -> !Dipl -> !(Maybe Status) -> !(Maybe ActorId) -> !ItemBag -> !(EnumMap (Id ItemKind) Int) -> Faction -- | the kind of the faction gkind :: Faction -> !(Id FactionKind) -- | individual name gname :: Faction -> !Text -- | color of actors or their frames gcolor :: Faction -> !Color -- | the player spec for this faction gplayer :: Faction -> !Player -- | diplomatic mode gdipl :: Faction -> !Dipl -- | cause of game end/exit gquit :: Faction -> !(Maybe Status) -- | the leader of the faction, if any gleader :: Faction -> !(Maybe ActorId) -- | faction's shared inventory gsha :: Faction -> !ItemBag -- | members killed gvictims :: Faction -> !(EnumMap (Id ItemKind) Int) -- | Diplomacy states. Higher overwrite lower in case of assymetric -- content. data Diplomacy Unknown :: Diplomacy Neutral :: Diplomacy Alliance :: Diplomacy War :: Diplomacy -- | 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 -- | Current game status. data Status Status :: !Outcome -> !Int -> !Text -> Status -- | current game outcome stOutcome :: Status -> !Outcome -- | depth of the final encounter stDepth :: Status -> !Int -- | extra information stInfo :: Status -> !Text -- | Tell whether the faction consists of heroes. isHeroFact :: Faction -> Bool -- | Tell whether the faction consists of human civilians. isCivilianFact :: COps -> Faction -> Bool -- | Tell whether the faction consists of summoned horrors only. isHorrorFact :: COps -> Faction -> Bool -- | Tell whether the faction is considered permanent dungeon dwellers -- (normally these are just spawning factions, but there are exceptions). isSpawnFact :: Faction -> Bool -- | Tell whether actors of the faction can be summoned by items, etc. isSummonFact :: COps -> Faction -> Bool -- | Tell whether all moving actors of the factions can move at once. isAllMoveFact :: COps -> Faction -> Bool -- | Tell whether a faction that we know is still in game, keeps arena. -- Such factions win if they can escape the dungeon. Keeping arena means, -- if the faction is still in game, it always has a leader in the dungeon -- somewhere. So, leaderless factions and spawner factions do not keep an -- arena, even though the latter usually has a leader for most of the -- game. keepArenaFact :: Faction -> Bool -- | 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 instance Show Diplomacy instance Eq Diplomacy instance Ord Diplomacy instance Enum Diplomacy instance Show Outcome instance Eq Outcome instance Ord Outcome instance Enum Outcome instance Show Status instance Eq Status instance Ord Status instance Show Faction instance Eq Faction instance Binary Status instance Binary Outcome instance Binary Diplomacy instance Binary Faction -- | Screen frames and animations. module Game.LambdaHack.Common.ClientOptions data DebugModeCli DebugModeCli :: !(Maybe String) -> !(Maybe Int) -> !Bool -> !Bool -> !(Maybe Bool) -> !Bool -> !Int -> !(Maybe String) -> !Bool -> !Bool -> !Bool -> DebugModeCli -- | Font to use for the main game window. sfont :: DebugModeCli -> !(Maybe String) -- | Maximal frames per second. This is better low and fixed, to avoid -- jerkiness and delays that tell the player there are many intelligent -- enemies on the level. That's better than scaling AI sofistication down -- based on the FPS setting and machine speed. smaxFps :: DebugModeCli -> !(Maybe Int) -- | Don't maintain any requested delays between frames, e.g., for -- screensaver. snoDelay :: DebugModeCli -> !Bool -- | Auto-answer all prompts, e.g., for screensaver. snoMore :: DebugModeCli -> !Bool -- | Don't show any animations. snoAnim :: DebugModeCli -> !(Maybe Bool) -- | Start a new game, overwriting the save file. snewGameCli :: DebugModeCli -> !Bool -- | The difficulty level for all UI clients. sdifficultyCli :: DebugModeCli -> !Int -- | Prefix of the save game file. ssavePrefixCli :: DebugModeCli -> !(Maybe String) -- | Whether to use the stdout/stdin frontend for all clients. sfrontendStd :: DebugModeCli -> !Bool -- | Whether to use void (no input/output) frontend for all clients. sfrontendNull :: DebugModeCli -> !Bool -- | Show clients' internal debug messages. sdbgMsgCli :: DebugModeCli -> !Bool defDebugModeCli :: DebugModeCli instance Show DebugModeCli instance Eq DebugModeCli instance Generic DebugModeCli instance Datatype D1DebugModeCli instance Constructor C1_0DebugModeCli instance Selector S1_0_0DebugModeCli instance Selector S1_0_1DebugModeCli instance Selector S1_0_2DebugModeCli instance Selector S1_0_3DebugModeCli instance Selector S1_0_4DebugModeCli instance Selector S1_0_5DebugModeCli instance Selector S1_0_6DebugModeCli instance Selector S1_0_7DebugModeCli instance Selector S1_0_8DebugModeCli instance Selector S1_0_9DebugModeCli instance Selector S1_0_10DebugModeCli instance Binary DebugModeCli -- | Personal game configuration file type definitions. module Game.LambdaHack.Client.UI.Config -- | Fully typed contents of the UI config file. This config is a part of a -- game client. data Config Config :: ![(KM, ([CmdCategory], HumanCmd))] -> ![(Int, (Text, Text))] -> !Bool -> !Bool -> !String -> !Int -> !Int -> !Bool -> !Bool -> Config configCommands :: Config -> ![(KM, ([CmdCategory], HumanCmd))] configHeroNames :: Config -> ![(Int, (Text, Text))] -- | the option for Vi keys takes precendence configVi :: Config -> !Bool -- | because the laptop keys are the default configLaptop :: Config -> !Bool configFont :: Config -> !String configHistoryMax :: Config -> !Int configMaxFps :: Config -> !Int configNoAnim :: Config -> !Bool configRunStopMsgs :: Config -> !Bool -- | Read and parse UI config file. mkConfig :: Ops RuleKind -> IO Config applyConfigToDebug :: Config -> DebugModeCli -> Ops RuleKind -> DebugModeCli instance Show Config instance NFData Config -- | Binding of keys to commands. No operation in this module involves the -- State or Action type. module Game.LambdaHack.Client.UI.KeyBindings -- | Bindings and other information about human player commands. data Binding Binding :: !(Map KM (Text, [CmdCategory], HumanCmd)) -> ![(KM, (Text, [CmdCategory], HumanCmd))] -> !(Map HumanCmd KM) -> Binding -- | binding of keys to commands bcmdMap :: Binding -> !(Map KM (Text, [CmdCategory], HumanCmd)) -- | the properly ordered list of commands for the help menu bcmdList :: Binding -> ![(KM, (Text, [CmdCategory], HumanCmd))] -- | and from commands to their keys brevMap :: Binding -> !(Map HumanCmd KM) -- | Binding of keys to movement and other standard commands, as well as -- commands defined in the config file. stdBinding :: KeyKind -> Config -> Binding -- | Produce a set of help screens from the key bindings. keyHelp :: Binding -> Slideshow -- | Text frontend based on stdin/stdout, intended for bots. module Game.LambdaHack.Client.UI.Frontend.Std -- | No session data needs to be maintained by this frontend. data FrontendSession -- | Output to the screen via the frontend. fdisplay :: FrontendSession -> Bool -> Maybe SingleFrame -> IO () -- | Display a prompt, wait for any key. fpromptGetKey :: FrontendSession -> SingleFrame -> IO KM fsyncFrames :: FrontendSession -> IO () -- | The name of the frontend. frontendName :: String -- | Starts the main program loop using the frontend input and output. startup :: DebugModeCli -> (FrontendSession -> IO ()) -> IO () -- | Re-export the operations of the chosen raw frontend (determined at -- compile time with cabal flags). module Game.LambdaHack.Client.UI.Frontend.Chosen data RawFrontend RawFrontend :: (Bool -> Maybe SingleFrame -> IO ()) -> (SingleFrame -> IO KM) -> IO () -> !(Maybe (MVar ())) -> !DebugModeCli -> RawFrontend fdisplay :: RawFrontend -> Bool -> Maybe SingleFrame -> IO () fpromptGetKey :: RawFrontend -> SingleFrame -> IO KM fsyncFrames :: RawFrontend -> IO () fescMVar :: RawFrontend -> !(Maybe (MVar ())) fdebugCli :: RawFrontend -> !DebugModeCli chosenStartup :: DebugModeCli -> (RawFrontend -> IO ()) -> IO () stdStartup :: DebugModeCli -> (RawFrontend -> IO ()) -> IO () nullStartup :: DebugModeCli -> (RawFrontend -> IO ()) -> IO () -- | The name of the chosen 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 data FrontReq -- | show a frame FrontNormalFrame :: !SingleFrame -> FrontReq frontFrame :: FrontReq -> !SingleFrame -- | show a frame in running mode (don't insert delay between frames) FrontRunningFrame :: !SingleFrame -> FrontReq frontFrame :: FrontReq -> !SingleFrame -- | perform a single explicit delay FrontDelay :: FrontReq -- | flush frames, possibly show fadeout/fadein and ask for a keypress FrontKey :: ![KM] -> !SingleFrame -> FrontReq frontKM :: FrontReq -> ![KM] frontFr :: FrontReq -> !SingleFrame -- | show a whole slideshow without interleaving with other clients FrontSlides :: ![KM] -> ![SingleFrame] -> FrontReq frontClear :: FrontReq -> ![KM] frontSlides :: FrontReq -> ![SingleFrame] -- | exit frontend loop FrontFinish :: FrontReq -- | Connection channel between a frontend and a client. Frontend acts as a -- server, serving keys, when given frames to display. data ChanFrontend ChanFrontend :: !(TQueue KM) -> !(TQueue FrontReq) -> ChanFrontend responseF :: ChanFrontend -> !(TQueue KM) requestF :: ChanFrontend -> !(TQueue FrontReq) -- | The name of the chosen frontend. frontendName :: String startupF :: DebugModeCli -> (Maybe (MVar ()) -> (ChanFrontend -> IO ()) -> IO ()) -> IO () -- | High score table operations. module Game.LambdaHack.Common.HighScore -- | The list of scores, in decreasing order. data ScoreTable -- | Empty score table empty :: ScoreTable -- | Register a new score in a score table. register :: ScoreTable -> Int -> Time -> Status -> ClockTime -> Int -> Text -> EnumMap (Id ItemKind) Int -> EnumMap (Id ItemKind) Int -> Bool -> (Bool, (ScoreTable, Int)) -- | Show a single high score, from the given ranking in the high score -- table. showScore :: (Int, ScoreRecord) -> [Text] getRecord :: Int -> ScoreTable -> ScoreRecord -- | Generate a slideshow with the current and previous scores. highSlideshow :: ScoreTable -> Int -> Slideshow instance Eq ScoreRecord instance Ord ScoreRecord instance Show ScoreRecord instance Generic ScoreRecord instance Eq ScoreTable instance Binary ScoreTable instance Datatype D1ScoreRecord instance Constructor C1_0ScoreRecord instance Selector S1_0_0ScoreRecord instance Selector S1_0_1ScoreRecord instance Selector S1_0_2ScoreRecord instance Selector S1_0_3ScoreRecord instance Selector S1_0_4ScoreRecord instance Selector S1_0_5ScoreRecord instance Selector S1_0_6ScoreRecord instance Selector S1_0_7ScoreRecord instance Show ScoreTable instance Binary ScoreRecord instance Binary ClockTime -- | Inhabited dungeon levels and the operations to query and change them -- as the game progresses. module Game.LambdaHack.Common.Level -- | Abstract level identifiers. data LevelId -- | Absolute depth in the dungeon. When used for the maximum depth of the -- whole dungeon, this can be different than dungeon size, e.g., when the -- dungeon is branched, and it can even be different than the length of -- the longest branch, if levels at some depths are missing. data AbsDepth -- | The complete dungeon is a map from level names to levels. type Dungeon = EnumMap LevelId Level -- | Levels in the current branch, k levels shallower than the -- current. ascendInBranch :: Dungeon -> Int -> LevelId -> [LevelId] -- | 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 -> !ActorPrio -> !ItemFloor -> !TileMap -> !X -> !Y -> !SmellMap -> !Text -> !([Point], [Point]) -> !Int -> !Int -> !Time -> !Freqs -> !Int -> !Freqs -> !Int -> !Int -> !Bool -> Level -- | absolute depth of the level ldepth :: Level -> !AbsDepth -- | remembered actor times on the level lprio :: Level -> !ActorPrio -- | remembered items lying on the floor lfloor :: Level -> !ItemFloor -- | remembered level map ltile :: Level -> !TileMap -- | width of the level lxsize :: Level -> !X -- | height of the level lysize :: Level -> !Y -- | remembered smells on the level lsmell :: Level -> !SmellMap -- | level description ldesc :: Level -> !Text -- | destinations of (up, down) stairs lstair :: Level -> !([Point], [Point]) -- | currently remembered clear tiles lseen :: Level -> !Int -- | total number of initially clear tiles lclear :: Level -> !Int -- | date of the last activity on the level ltime :: Level -> !Time -- | frequency of spawned actors; [] for clients lactorFreq :: Level -> !Freqs -- | number of initial items, 0 for clients litemNum :: Level -> !Int -- | frequency of initial items; [] for clients litemFreq :: Level -> !Freqs -- | secret tile seed lsecret :: Level -> !Int -- | secret tile density lhidden :: Level -> !Int -- | has an Effect.Escape tile lescape :: Level -> !Bool -- | Actor time priority queue. type ActorPrio = EnumMap Time [ActorId] -- | Items located on map tiles. type ItemFloor = EnumMap Point ItemBag -- | Tile kinds on the map. type TileMap = Array (Id TileKind) -- | Current smell on map tiles. type SmellMap = EnumMap Point SmellTime -- | Query for tile kinds on the map. at :: Level -> Point -> Id TileKind -- | Query for items on the ground. atI :: Level -> Point -> ItemBag checkAccess :: COps -> Level -> Maybe (Point -> Point -> Bool) checkDoorAccess :: COps -> Level -> Maybe (Point -> Point -> Bool) -- | Check whether one position is accessible from another, using the -- formula from the standard ruleset. Precondition: the two positions are -- next to each other. accessible :: COps -> Level -> Point -> Point -> Bool -- | Check whether one position is accessible from another, using the -- formula from the standard ruleset, but additionally treating unknown -- tiles as walkable. Precondition: the two positions are next to each -- other. accessibleUnknown :: COps -> Level -> Point -> Point -> Bool -- | Check whether actors can move from a position along a unit vector, -- using the formula from the standard ruleset. accessibleDir :: COps -> Level -> Point -> Vector -> Bool knownLsecret :: Level -> Bool isSecretPos :: Level -> Point -> Bool hideTile :: Ops TileKind -> Level -> Point -> Id TileKind -- | 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 the conjunction of -- the list of predicates. If the permitted number of attempts is not -- enough, try again the same number of times without the first -- predicate, then without the first two, etc., until only one predicate -- remains, at which point try as many times, as needed. findPosTry :: Int -> TileMap -> (Point -> Id TileKind -> Bool) -> [Point -> Id TileKind -> Bool] -> Rnd Point mapLevelActors_ :: Monad m => (ActorId -> m a) -> Level -> m () mapDungeonActors_ :: Monad m => (ActorId -> m a) -> Dungeon -> m () instance Show Level instance Eq Level instance Binary Level -- | Actors perceiving other actors and the dungeon level. -- -- Visibility works according to KISS. Everything that player sees is -- real. There are no unmarked hidden tiles and only solid tiles can be -- marked, so there are no invisible walls and to pass through an -- illusory wall, you have use a turn bumping into it first. Only tiles -- marked with Suspect can turn out to be another tile. (So, if all tiles -- are marked with Suspect, the player knows nothing for sure, but this -- should be avoided, because searching becomes too time-consuming.) Each -- actor sees adjacent tiles, even when blind, so adjacent tiles are -- known, so the actor can decide accurately whether to pass thorugh or -- alter, etc. -- -- Items are always real and visible. Actors are real, but can be -- invisible. Invisible actors in walls can't be hit, but are hinted at -- when altering the tile, so the player can flee or block. Invisible -- actors in open space can be hit. module Game.LambdaHack.Common.Perception -- | The type representing the perception of a faction on a level. data Perception Perception :: !PerceptionVisible -> !PerceptionVisible -> Perception newtype PerceptionVisible PerceptionVisible :: EnumSet Point -> PerceptionVisible -- | The set of tiles visible by at least one hero. totalVisible :: Perception -> EnumSet Point -- | The set of tiles smelled by at least one hero. smellVisible :: Perception -> EnumSet Point nullPer :: Perception -> Bool addPer :: Perception -> Perception -> Perception diffPer :: Perception -> Perception -> Perception -- | Perception of a single faction, indexed by level identifier. type FactionPers = EnumMap LevelId Perception -- | Perception indexed by faction identifier. This can't be added to -- FactionDict, because clients can't see it. type Pers = EnumMap FactionId FactionPers instance Show PerceptionVisible instance Eq PerceptionVisible instance Binary PerceptionVisible instance Show Perception instance Eq Perception instance Generic Perception instance Datatype D1Perception instance Constructor C1_0Perception instance Selector S1_0_0Perception instance Selector S1_0_1Perception instance Binary Perception -- | Generation of places from place kinds. module Game.LambdaHack.Server.DungeonGen.Place -- | The map of tile kinds in a place (and generally anywhere in a cave). -- The map is sparse. The default tile that eventually fills the empty -- spaces is specified in the cave kind specification with -- cdefTile. type TileMapEM = EnumMap Point (Id TileKind) -- | The parameters of a place. Most are immutable and set at the time when -- a place is generated. data Place Place :: !(Id PlaceKind) -> !Area -> !Bool -> !Text -> !(Id TileKind) -> !(Id TileKind) -> Place qkind :: Place -> !(Id PlaceKind) qarea :: Place -> !Area qseen :: Place -> !Bool qlegend :: Place -> !Text qsolidFence :: Place -> !(Id TileKind) qhollowFence :: Place -> !(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 -- | Construct a fence around an area, with the given tile group. buildFenceRnd :: COps -> Text -> Area -> Rnd TileMapEM -- | Given a few parameters, roll and construct a Place -- datastructure and fill a cave section acccording to it. buildPlace :: COps -> CaveKind -> Bool -> Id TileKind -> Id TileKind -> AbsDepth -> AbsDepth -> Area -> Rnd (TileMapEM, Place) instance Show Place instance Binary 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) -> !TileMapEM -> ![Place] -> !Bool -> Cave -- | the kind of the cave dkind :: Cave -> !(Id CaveKind) -- | tile kinds in the cave dmap :: Cave -> !TileMapEM -- | places generated in the cave dplaces :: Cave -> ![Place] -- | whether the cave is dark dnight :: Cave -> !Bool -- | Cave generation by an algorithm inspired by the original Rogue, buildCave :: COps -> AbsDepth -> AbsDepth -> Id CaveKind -> Rnd Cave instance Show Cave -- | The unpopulated dungeon generation routine. module Game.LambdaHack.Server.DungeonGen -- | Freshly generated and not yet populated dungeon. data FreshDungeon FreshDungeon :: !Dungeon -> !AbsDepth -> FreshDungeon -- | maps for all levels freshDungeon :: FreshDungeon -> !Dungeon -- | absolute dungeon depth freshTotalDepth :: FreshDungeon -> !AbsDepth -- | Generate the dungeon for a new game. dungeonGen :: COps -> Caves -> Rnd FreshDungeon convertTileMaps :: Ops TileKind -> Rnd (Id TileKind) -> Maybe (Rnd (Id TileKind)) -> Int -> Int -> TileMapEM -> Rnd TileMap placeStairs :: Ops TileKind -> TileMap -> CaveKind -> [Point] -> Rnd Point -- | Create a level from a cave. buildLevel :: COps -> Cave -> AbsDepth -> LevelId -> LevelId -> LevelId -> AbsDepth -> Int -> Maybe Bool -> Rnd Level -- | Build rudimentary level from a cave kind. levelFromCaveKind :: COps -> CaveKind -> AbsDepth -> TileMap -> ([Point], [Point]) -> Freqs -> Int -> Freqs -> Int -> Bool -> Level findGenerator :: COps -> LevelId -> LevelId -> LevelId -> AbsDepth -> Int -> (Text, Maybe Bool) -> Rnd Level -- | Server and client game state types and operations. module Game.LambdaHack.Common.State -- | View on game state. Remembered fields carry a subset of the -- info in the client copies of the state. Clients never directly change -- their State, but apply atomic actions sent by the server to -- do so. data State sdungeon :: State -> Dungeon stotalDepth :: State -> AbsDepth sactorD :: State -> ActorDict sitemD :: State -> ItemDict sfactionD :: State -> FactionDict stime :: State -> Time scops :: State -> COps shigh :: State -> ScoreTable -- | Initial complete global game state. defStateGlobal :: Dungeon -> AbsDepth -> FactionDict -> COps -> ScoreTable -> State -- | Initial empty state. emptyState :: State -- | Local state created by removing secret information from global state -- components. localFromGlobal :: State -> State -- | Update dungeon data within state. updateDungeon :: (Dungeon -> Dungeon) -> State -> State -- | Update dungeon depth. updateDepth :: (AbsDepth -> AbsDepth) -> State -> State -- | Update the actor dictionary. updateActorD :: (ActorDict -> ActorDict) -> State -> State -- | Update the item dictionary. updateItemD :: (ItemDict -> ItemDict) -> State -> State -- | Update faction data within state. updateFactionD :: (FactionDict -> FactionDict) -> State -> State -- | Update global time within state. updateTime :: (Time -> Time) -> State -> State -- | Update content data within state. updateCOps :: (COps -> COps) -> State -> State instance Show State instance Eq State instance Binary State -- | Operations on the Actor type that need the State type, -- but not the Action type. TODO: Document an export list after -- it's rewritten according to #17. module Game.LambdaHack.Common.ActorState fidActorNotProjAssocs :: FactionId -> State -> [(ActorId, Actor)] fidActorNotProjList :: FactionId -> State -> [Actor] actorAssocsLvl :: (FactionId -> Bool) -> Level -> ActorDict -> [(ActorId, Actor)] actorAssocs :: (FactionId -> Bool) -> LevelId -> State -> [(ActorId, Actor)] actorList :: (FactionId -> Bool) -> LevelId -> State -> [Actor] actorRegularAssocsLvl :: (FactionId -> Bool) -> Level -> ActorDict -> [(ActorId, Actor)] actorRegularAssocs :: (FactionId -> Bool) -> LevelId -> State -> [(ActorId, Actor)] actorRegularList :: (FactionId -> Bool) -> LevelId -> State -> [Actor] bagAssocs :: State -> ItemBag -> [(ItemId, Item)] bagAssocsK :: State -> ItemBag -> [(ItemId, (Item, Int))] -- | Calculate loot's worth for a faction of a given actor. calculateTotal :: Actor -> State -> (ItemBag, Int) sharedAllOwned :: Actor -> State -> ItemBag sharedAllOwnedFid :: FactionId -> State -> ItemBag getCBag :: Container -> State -> ItemBag getActorBag :: ActorId -> CStore -> State -> ItemBag getBodyActorBag :: Actor -> CStore -> State -> ItemBag getActorAssocs :: ActorId -> CStore -> State -> [(ItemId, Item)] nearbyFreePoints :: (Id TileKind -> Bool) -> Point -> LevelId -> State -> [Point] -- | Compute the level identifier and starting position on the level, after -- a level change. whereTo :: LevelId -> Point -> Int -> Dungeon -> (LevelId, Point) getCarriedAssocs :: Actor -> State -> [(ItemId, Item)] posToActors :: Point -> LevelId -> State -> [((ActorId, Actor), [(ItemId, Item)])] -- | Finds an actor at a position on the current level. posToActor :: Point -> LevelId -> State -> Maybe ((ActorId, Actor), [(ItemId, Item)]) getItemBody :: ItemId -> State -> Item -- | Checks if the actor is present on the current level. The order of -- argument here and in other functions is set to allow -- --
--   b <- getsState (memActor a)
--   
memActor :: ActorId -> LevelId -> State -> Bool -- | Gets actor body from the current level. Error if not found. getActorBody :: ActorId -> State -> Actor tryFindHeroK :: State -> FactionId -> Int -> Maybe (ActorId, Actor) -- | Get current time from the dungeon data. getLocalTime :: LevelId -> State -> Time -- | Price an item, taking count into consideration. itemPrice :: (Item, Int) -> Int calmEnough :: Actor -> [ItemFull] -> Bool hpEnough :: Actor -> [ItemFull] -> Bool regenCalmDelta :: Actor -> [ItemFull] -> State -> Int64 actorInAmbient :: Actor -> State -> Bool actorSkills :: ActorId -> Maybe ActorId -> [ItemFull] -> State -> Skills dispEnemy :: ActorId -> ActorId -> [ItemFull] -> State -> Bool -- | Determine if the sight radius is high enough to deem the actor capable -- of projecting items and similar activities. Otherwise, the actor is -- assumed to use a combination of peripherial vision, hearing, etc., and -- not the actual focused, long-distance sight sense. radiusBlind :: Int -> Bool fullAssocs :: COps -> Discovery -> DiscoAE -> ActorId -> [CStore] -> State -> [(ItemId, ItemFull)] itemToFull :: COps -> Discovery -> DiscoAE -> ItemId -> Item -> Int -> ItemFull goesIntoInv :: Item -> Bool eqpOverfull :: Actor -> Int -> Bool storeFromC :: Container -> CStore -- | Game action monads and basic building blocks for human and computer -- player actions. Has no access to the the main action type. module Game.LambdaHack.Common.MonadStateRead class (Monad m, Functor m) => MonadStateRead m getState :: MonadStateRead m => m State getsState :: MonadStateRead m => (State -> a) -> m a getLevel :: MonadStateRead m => LevelId -> m Level nUI :: MonadStateRead m => m Int posOfAid :: MonadStateRead m => ActorId -> m (LevelId, Point) fightsAgainstSpawners :: MonadStateRead m => FactionId -> m Bool -- | The monad for writing to the game state and related operations. module Game.LambdaHack.Atomic.MonadStateWrite class MonadStateRead m => MonadStateWrite m modifyState :: MonadStateWrite m => (State -> State) -> m () putState :: MonadStateWrite m => State -> m () -- | Update a given level data within state. updateLevel :: MonadStateWrite m => LevelId -> (Level -> Level) -> m () updateActor :: MonadStateWrite m => ActorId -> (Actor -> Actor) -> m () updateFaction :: MonadStateWrite m => FactionId -> (Faction -> Faction) -> m () insertItemContainer :: MonadStateWrite m => ItemId -> Int -> Container -> m () insertItemActor :: MonadStateWrite m => ItemId -> Int -> ActorId -> CStore -> m () deleteItemContainer :: MonadStateWrite m => ItemId -> Int -> Container -> m () deleteItemActor :: MonadStateWrite m => ItemId -> Int -> ActorId -> CStore -> m () -- | Update the actor time priority queue. updatePrio :: (ActorPrio -> ActorPrio) -> Level -> Level -- | Update the items on the ground map. updateFloor :: (ItemFloor -> ItemFloor) -> Level -> Level -- | Update the tile map. updateTile :: (TileMap -> TileMap) -> Level -> Level -- | Update the smell map. updateSmell :: (SmellMap -> SmellMap) -> Level -> Level -- | Actor preferences for targets and actions based on actor attributes. module Game.LambdaHack.Client.AI.Preferences -- | Determine the total benefit from having an item in eqp or inv, -- according to item type, and also the benefit confered by equipping the -- item and from meleeing with it or applying it or throwing it. totalUsefulness :: COps -> Actor -> [ItemFull] -> Faction -> ItemFull -> Maybe (Int, (Int, Int)) -- | How much AI benefits from applying the effect. Multipllied by item p. -- Negative means harm to the enemy when thrown at him. Effects with zero -- benefit won't ever be used, neither actively nor passively. effectToBenefit :: COps -> Actor -> [ItemFull] -> Faction -> Effect Int -> Int -- | Item slots for UI and AI item collections. TODO: document module Game.LambdaHack.Client.ItemSlot type ItemSlots = (EnumMap SlotChar ItemId, IntMap ItemId) newtype SlotChar SlotChar :: Char -> SlotChar slotChar :: SlotChar -> Char allSlots :: [SlotChar] slotLabel :: Either SlotChar Int -> Part slotRange :: [SlotChar] -> Text -- | Assigns a slot to an item, for inclusion in the inventory or equipment -- of a hero. Tries to to use the requested slot, if any. assignSlot :: Item -> FactionId -> Maybe Actor -> ItemSlots -> SlotChar -> State -> Either SlotChar Int instance Show SlotChar instance Eq SlotChar instance Binary SlotChar instance Enum SlotChar instance Ord SlotChar -- | 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 data CmdAtomic UpdAtomic :: !UpdAtomic -> CmdAtomic SfxAtomic :: !SfxAtomic -> CmdAtomic -- | Abstract syntax of atomic commands. data UpdAtomic UpdCreateActor :: !ActorId -> !Actor -> ![(ItemId, Item)] -> UpdAtomic UpdDestroyActor :: !ActorId -> !Actor -> ![(ItemId, Item)] -> UpdAtomic UpdCreateItem :: !ItemId -> !Item -> !Int -> !Container -> UpdAtomic UpdDestroyItem :: !ItemId -> !Item -> !Int -> !Container -> UpdAtomic UpdSpotActor :: !ActorId -> !Actor -> ![(ItemId, Item)] -> UpdAtomic UpdLoseActor :: !ActorId -> !Actor -> ![(ItemId, Item)] -> UpdAtomic UpdSpotItem :: !ItemId -> !Item -> !Int -> !Container -> UpdAtomic UpdLoseItem :: !ItemId -> !Item -> !Int -> !Container -> UpdAtomic UpdMoveActor :: !ActorId -> !Point -> !Point -> UpdAtomic UpdWaitActor :: !ActorId -> !Bool -> UpdAtomic UpdDisplaceActor :: !ActorId -> !ActorId -> UpdAtomic UpdMoveItem :: !ItemId -> !Int -> !ActorId -> !CStore -> !CStore -> UpdAtomic UpdAgeActor :: !ActorId -> !(Delta Time) -> UpdAtomic UpdRefillHP :: !ActorId -> !Int64 -> UpdAtomic UpdRefillCalm :: !ActorId -> !Int64 -> UpdAtomic UpdOldFidActor :: !ActorId -> !FactionId -> !FactionId -> UpdAtomic UpdTrajectory :: !ActorId -> !(Maybe ([Vector], Speed)) -> !(Maybe ([Vector], Speed)) -> UpdAtomic UpdColorActor :: !ActorId -> !Color -> !Color -> UpdAtomic UpdQuitFaction :: !FactionId -> !(Maybe Actor) -> !(Maybe Status) -> !(Maybe Status) -> UpdAtomic UpdLeadFaction :: !FactionId -> !(Maybe ActorId) -> !(Maybe ActorId) -> UpdAtomic UpdDiplFaction :: !FactionId -> !FactionId -> !Diplomacy -> !Diplomacy -> UpdAtomic UpdAutoFaction :: !FactionId -> !Bool -> UpdAtomic UpdRecordKill :: !ActorId -> !(Id ItemKind) -> !Int -> UpdAtomic UpdAlterTile :: !LevelId -> !Point -> !(Id TileKind) -> !(Id TileKind) -> UpdAtomic UpdAlterClear :: !LevelId -> !Int -> UpdAtomic UpdSearchTile :: !ActorId -> !Point -> !(Id TileKind) -> !(Id TileKind) -> UpdAtomic UpdLearnSecrets :: !ActorId -> !Int -> !Int -> UpdAtomic UpdSpotTile :: !LevelId -> ![(Point, Id TileKind)] -> UpdAtomic UpdLoseTile :: !LevelId -> ![(Point, Id TileKind)] -> UpdAtomic UpdAlterSmell :: !LevelId -> !Point -> !(Maybe Time) -> !(Maybe Time) -> UpdAtomic UpdSpotSmell :: !LevelId -> ![(Point, Time)] -> UpdAtomic UpdLoseSmell :: !LevelId -> ![(Point, Time)] -> UpdAtomic UpdAgeGame :: !(Delta Time) -> ![LevelId] -> UpdAtomic UpdDiscover :: !LevelId -> !Point -> !ItemId -> !(Id ItemKind) -> !ItemSeed -> UpdAtomic UpdCover :: !LevelId -> !Point -> !ItemId -> !(Id ItemKind) -> !ItemSeed -> UpdAtomic UpdDiscoverKind :: !LevelId -> !Point -> !ItemId -> !(Id ItemKind) -> UpdAtomic UpdCoverKind :: !LevelId -> !Point -> !ItemId -> !(Id ItemKind) -> UpdAtomic UpdDiscoverSeed :: !LevelId -> !Point -> !ItemId -> !ItemSeed -> UpdAtomic UpdCoverSeed :: !LevelId -> !Point -> !ItemId -> !ItemSeed -> UpdAtomic UpdPerception :: !LevelId -> !Perception -> !Perception -> UpdAtomic UpdRestart :: !FactionId -> !Discovery -> !FactionPers -> !State -> !DebugModeCli -> !Text -> UpdAtomic UpdRestartServer :: !State -> UpdAtomic UpdResume :: !FactionId -> !FactionPers -> UpdAtomic UpdResumeServer :: !State -> UpdAtomic UpdKillExit :: !FactionId -> UpdAtomic UpdSaveBkp :: UpdAtomic UpdMsgAll :: !Msg -> UpdAtomic UpdRecordHistory :: !FactionId -> UpdAtomic -- | Abstract syntax of atomic special effects. data SfxAtomic SfxStrike :: !ActorId -> !ActorId -> !ItemId -> !HitAtomic -> SfxAtomic SfxRecoil :: !ActorId -> !ActorId -> !ItemId -> !HitAtomic -> SfxAtomic SfxProject :: !ActorId -> !ItemId -> SfxAtomic SfxCatch :: !ActorId -> !ItemId -> SfxAtomic SfxActivate :: !ActorId -> !ItemId -> !Int -> SfxAtomic SfxCheck :: !ActorId -> !ItemId -> !Int -> SfxAtomic SfxTrigger :: !ActorId -> !Point -> !Feature -> SfxAtomic SfxShun :: !ActorId -> !Point -> !Feature -> SfxAtomic SfxEffect :: !FactionId -> !ActorId -> !(Effect Int) -> SfxAtomic SfxMsgFid :: !FactionId -> !Msg -> SfxAtomic SfxMsgAll :: !Msg -> SfxAtomic SfxActorStart :: !ActorId -> SfxAtomic data HitAtomic HitClear :: HitAtomic HitBlock :: !Int -> HitAtomic undoUpdAtomic :: UpdAtomic -> Maybe UpdAtomic undoSfxAtomic :: SfxAtomic -> SfxAtomic undoCmdAtomic :: CmdAtomic -> Maybe CmdAtomic instance Show UpdAtomic instance Eq UpdAtomic instance Generic UpdAtomic instance Show HitAtomic instance Eq HitAtomic instance Generic HitAtomic instance Show SfxAtomic instance Eq SfxAtomic instance Generic SfxAtomic instance Show CmdAtomic instance Eq CmdAtomic instance Generic CmdAtomic instance Datatype D1UpdAtomic instance Constructor C1_0UpdAtomic instance Constructor C1_1UpdAtomic instance Constructor C1_2UpdAtomic instance Constructor C1_3UpdAtomic instance Constructor C1_4UpdAtomic instance Constructor C1_5UpdAtomic instance Constructor C1_6UpdAtomic instance Constructor C1_7UpdAtomic instance Constructor C1_8UpdAtomic instance Constructor C1_9UpdAtomic instance Constructor C1_10UpdAtomic instance Constructor C1_11UpdAtomic instance Constructor C1_12UpdAtomic instance Constructor C1_13UpdAtomic instance Constructor C1_14UpdAtomic instance Constructor C1_15UpdAtomic instance Constructor C1_16UpdAtomic instance Constructor C1_17UpdAtomic instance Constructor C1_18UpdAtomic instance Constructor C1_19UpdAtomic instance Constructor C1_20UpdAtomic instance Constructor C1_21UpdAtomic instance Constructor C1_22UpdAtomic instance Constructor C1_23UpdAtomic instance Constructor C1_24UpdAtomic instance Constructor C1_25UpdAtomic instance Constructor C1_26UpdAtomic instance Constructor C1_27UpdAtomic instance Constructor C1_28UpdAtomic instance Constructor C1_29UpdAtomic instance Constructor C1_30UpdAtomic instance Constructor C1_31UpdAtomic instance Constructor C1_32UpdAtomic instance Constructor C1_33UpdAtomic instance Constructor C1_34UpdAtomic instance Constructor C1_35UpdAtomic instance Constructor C1_36UpdAtomic instance Constructor C1_37UpdAtomic instance Constructor C1_38UpdAtomic instance Constructor C1_39UpdAtomic instance Constructor C1_40UpdAtomic instance Constructor C1_41UpdAtomic instance Constructor C1_42UpdAtomic instance Constructor C1_43UpdAtomic instance Constructor C1_44UpdAtomic instance Constructor C1_45UpdAtomic instance Constructor C1_46UpdAtomic instance Constructor C1_47UpdAtomic instance Datatype D1HitAtomic instance Constructor C1_0HitAtomic instance Constructor C1_1HitAtomic instance Datatype D1SfxAtomic instance Constructor C1_0SfxAtomic instance Constructor C1_1SfxAtomic instance Constructor C1_2SfxAtomic instance Constructor C1_3SfxAtomic instance Constructor C1_4SfxAtomic instance Constructor C1_5SfxAtomic instance Constructor C1_6SfxAtomic instance Constructor C1_7SfxAtomic instance Constructor C1_8SfxAtomic instance Constructor C1_9SfxAtomic instance Constructor C1_10SfxAtomic instance Constructor C1_11SfxAtomic instance Datatype D1CmdAtomic instance Constructor C1_0CmdAtomic instance Constructor C1_1CmdAtomic instance Binary HitAtomic instance Binary SfxAtomic instance Binary UpdAtomic instance Binary CmdAtomic -- | Atomic monads. module Game.LambdaHack.Atomic.MonadAtomic class MonadStateRead m => MonadAtomic m where execUpdAtomic = execAtomic . UpdAtomic execSfxAtomic = execAtomic . SfxAtomic execAtomic :: MonadAtomic m => CmdAtomic -> m () execUpdAtomic :: MonadAtomic m => UpdAtomic -> m () execSfxAtomic :: MonadAtomic m => SfxAtomic -> m () broadcastUpdAtomic :: MonadAtomic m => (FactionId -> UpdAtomic) -> m () broadcastSfxAtomic :: MonadAtomic m => (FactionId -> SfxAtomic) -> m () -- | Semantics of atomic commands shared by client and server. See -- https://github.com/LambdaHack/LambdaHack/wiki/Client-server-architecture. module Game.LambdaHack.Atomic.PosAtomicRead -- | The type representing visibility of actions to factions, based on the -- position of the action, etc. data PosAtomic -- | whomever sees all the positions, notices PosSight :: !LevelId -> ![Point] -> PosAtomic -- | observers and the faction notice PosFidAndSight :: !FactionId -> !LevelId -> ![Point] -> PosAtomic -- | whomever smells all the positions, notices PosSmell :: !LevelId -> ![Point] -> PosAtomic -- | only the faction notices PosFid :: !FactionId -> PosAtomic -- | faction and server notices PosFidAndSer :: !(Maybe LevelId) -> !FactionId -> PosAtomic -- | only the server notices PosSer :: PosAtomic -- | everybody notices PosAll :: PosAtomic -- | never broadcasted, but sent manually PosNone :: PosAtomic -- | Produce the positions where the action takes place. If a faction is -- returned, the action is visible only for that faction, if Nothing is -- returned, it's never visible. Empty list of positions implies the -- action is visible always. -- -- The goal of the mechanics: client should not get significantly more -- information by looking at the atomic commands he is able to see than -- by looking at the state changes they enact. E.g., -- UpdDisplaceActor in a black room, with one actor carrying a -- 0-radius light would not be distinguishable by looking at the state -- (or the screen) from UpdMoveActor of the illuminated actor, -- hence such UpdDisplaceActor should not be observable, but -- UpdMoveActor should be (or the former should be perceived as -- the latter). However, to simplify, we assing 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 -- | Determines if a command resets FOV. -- -- Invariant: if resetsFovCmdAtomic determines we do not need to -- reset Fov, perception (ptotal to be precise, psmell -- is irrelevant) of any faction does not change upon recomputation. -- Otherwise, save/restore would change game state. resetsFovCmdAtomic :: UpdAtomic -> Bool -- | Decompose an atomic action. The original action is visible if it's -- positions are visible both before and after the action (in between the -- FOV might have changed). The decomposed actions are only tested vs the -- FOV after the action and they give reduced information that still -- modifies client's state to match the server state wrt the current FOV -- and the subset of posUpdAtomic that is visible. The original -- actions give more information not only due to spanning potentially -- more positions than those visible. E.g., UpdMoveActor informs -- about the continued existence of the actor between moves, v.s., -- popping out of existence and then back in. breakUpdAtomic :: MonadStateRead m => UpdAtomic -> m [UpdAtomic] -- | Decompose an atomic special effect. breakSfxAtomic :: MonadStateRead m => SfxAtomic -> m [SfxAtomic] -- | Messages for some unseen game object -- creationdestructionalteration. loudUpdAtomic :: MonadStateRead m => Bool -> FactionId -> UpdAtomic -> m (Maybe Msg) seenAtomicCli :: Bool -> FactionId -> Perception -> PosAtomic -> Bool seenAtomicSer :: PosAtomic -> Bool generalMoveItem :: MonadStateRead m => ItemId -> Int -> Container -> Container -> m [UpdAtomic] instance Show PosAtomic instance Eq 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. Special effects -- (SfxAtomic) don't modify state. handleCmdAtomic :: MonadStateWrite m => CmdAtomic -> m () -- | Atomic game state transformations. TODO: haddocks. -- -- See -- https://github.com/LambdaHack/LambdaHack/wiki/Client-server-architecture. module Game.LambdaHack.Atomic class MonadStateRead m => MonadAtomic m where execUpdAtomic = execAtomic . UpdAtomic execSfxAtomic = execAtomic . SfxAtomic execAtomic :: MonadAtomic m => CmdAtomic -> m () execUpdAtomic :: MonadAtomic m => UpdAtomic -> m () execSfxAtomic :: MonadAtomic m => SfxAtomic -> m () broadcastUpdAtomic :: MonadAtomic m => (FactionId -> UpdAtomic) -> m () broadcastSfxAtomic :: MonadAtomic m => (FactionId -> SfxAtomic) -> m () data CmdAtomic UpdAtomic :: !UpdAtomic -> CmdAtomic SfxAtomic :: !SfxAtomic -> CmdAtomic -- | Abstract syntax of atomic commands. data UpdAtomic UpdCreateActor :: !ActorId -> !Actor -> ![(ItemId, Item)] -> UpdAtomic UpdDestroyActor :: !ActorId -> !Actor -> ![(ItemId, Item)] -> UpdAtomic UpdCreateItem :: !ItemId -> !Item -> !Int -> !Container -> UpdAtomic UpdDestroyItem :: !ItemId -> !Item -> !Int -> !Container -> UpdAtomic UpdSpotActor :: !ActorId -> !Actor -> ![(ItemId, Item)] -> UpdAtomic UpdLoseActor :: !ActorId -> !Actor -> ![(ItemId, Item)] -> UpdAtomic UpdSpotItem :: !ItemId -> !Item -> !Int -> !Container -> UpdAtomic UpdLoseItem :: !ItemId -> !Item -> !Int -> !Container -> UpdAtomic UpdMoveActor :: !ActorId -> !Point -> !Point -> UpdAtomic UpdWaitActor :: !ActorId -> !Bool -> UpdAtomic UpdDisplaceActor :: !ActorId -> !ActorId -> UpdAtomic UpdMoveItem :: !ItemId -> !Int -> !ActorId -> !CStore -> !CStore -> UpdAtomic UpdAgeActor :: !ActorId -> !(Delta Time) -> UpdAtomic UpdRefillHP :: !ActorId -> !Int64 -> UpdAtomic UpdRefillCalm :: !ActorId -> !Int64 -> UpdAtomic UpdOldFidActor :: !ActorId -> !FactionId -> !FactionId -> UpdAtomic UpdTrajectory :: !ActorId -> !(Maybe ([Vector], Speed)) -> !(Maybe ([Vector], Speed)) -> UpdAtomic UpdColorActor :: !ActorId -> !Color -> !Color -> UpdAtomic UpdQuitFaction :: !FactionId -> !(Maybe Actor) -> !(Maybe Status) -> !(Maybe Status) -> UpdAtomic UpdLeadFaction :: !FactionId -> !(Maybe ActorId) -> !(Maybe ActorId) -> UpdAtomic UpdDiplFaction :: !FactionId -> !FactionId -> !Diplomacy -> !Diplomacy -> UpdAtomic UpdAutoFaction :: !FactionId -> !Bool -> UpdAtomic UpdRecordKill :: !ActorId -> !(Id ItemKind) -> !Int -> UpdAtomic UpdAlterTile :: !LevelId -> !Point -> !(Id TileKind) -> !(Id TileKind) -> UpdAtomic UpdAlterClear :: !LevelId -> !Int -> UpdAtomic UpdSearchTile :: !ActorId -> !Point -> !(Id TileKind) -> !(Id TileKind) -> UpdAtomic UpdLearnSecrets :: !ActorId -> !Int -> !Int -> UpdAtomic UpdSpotTile :: !LevelId -> ![(Point, Id TileKind)] -> UpdAtomic UpdLoseTile :: !LevelId -> ![(Point, Id TileKind)] -> UpdAtomic UpdAlterSmell :: !LevelId -> !Point -> !(Maybe Time) -> !(Maybe Time) -> UpdAtomic UpdSpotSmell :: !LevelId -> ![(Point, Time)] -> UpdAtomic UpdLoseSmell :: !LevelId -> ![(Point, Time)] -> UpdAtomic UpdAgeGame :: !(Delta Time) -> ![LevelId] -> UpdAtomic UpdDiscover :: !LevelId -> !Point -> !ItemId -> !(Id ItemKind) -> !ItemSeed -> UpdAtomic UpdCover :: !LevelId -> !Point -> !ItemId -> !(Id ItemKind) -> !ItemSeed -> UpdAtomic UpdDiscoverKind :: !LevelId -> !Point -> !ItemId -> !(Id ItemKind) -> UpdAtomic UpdCoverKind :: !LevelId -> !Point -> !ItemId -> !(Id ItemKind) -> UpdAtomic UpdDiscoverSeed :: !LevelId -> !Point -> !ItemId -> !ItemSeed -> UpdAtomic UpdCoverSeed :: !LevelId -> !Point -> !ItemId -> !ItemSeed -> UpdAtomic UpdPerception :: !LevelId -> !Perception -> !Perception -> UpdAtomic UpdRestart :: !FactionId -> !Discovery -> !FactionPers -> !State -> !DebugModeCli -> !Text -> UpdAtomic UpdRestartServer :: !State -> UpdAtomic UpdResume :: !FactionId -> !FactionPers -> UpdAtomic UpdResumeServer :: !State -> UpdAtomic UpdKillExit :: !FactionId -> UpdAtomic UpdSaveBkp :: UpdAtomic UpdMsgAll :: !Msg -> UpdAtomic UpdRecordHistory :: !FactionId -> UpdAtomic -- | Abstract syntax of atomic special effects. data SfxAtomic SfxStrike :: !ActorId -> !ActorId -> !ItemId -> !HitAtomic -> SfxAtomic SfxRecoil :: !ActorId -> !ActorId -> !ItemId -> !HitAtomic -> SfxAtomic SfxProject :: !ActorId -> !ItemId -> SfxAtomic SfxCatch :: !ActorId -> !ItemId -> SfxAtomic SfxActivate :: !ActorId -> !ItemId -> !Int -> SfxAtomic SfxCheck :: !ActorId -> !ItemId -> !Int -> SfxAtomic SfxTrigger :: !ActorId -> !Point -> !Feature -> SfxAtomic SfxShun :: !ActorId -> !Point -> !Feature -> SfxAtomic SfxEffect :: !FactionId -> !ActorId -> !(Effect Int) -> SfxAtomic SfxMsgFid :: !FactionId -> !Msg -> SfxAtomic SfxMsgAll :: !Msg -> SfxAtomic SfxActorStart :: !ActorId -> SfxAtomic data HitAtomic HitClear :: HitAtomic HitBlock :: !Int -> HitAtomic -- | The type representing visibility of actions to factions, based on the -- position of the action, etc. data PosAtomic -- | whomever sees all the positions, notices PosSight :: !LevelId -> ![Point] -> PosAtomic -- | observers and the faction notice PosFidAndSight :: !FactionId -> !LevelId -> ![Point] -> PosAtomic -- | whomever smells all the positions, notices PosSmell :: !LevelId -> ![Point] -> PosAtomic -- | only the faction notices PosFid :: !FactionId -> PosAtomic -- | faction and server notices PosFidAndSer :: !(Maybe LevelId) -> !FactionId -> PosAtomic -- | only the server notices PosSer :: PosAtomic -- | everybody notices PosAll :: PosAtomic -- | never broadcasted, but sent manually PosNone :: PosAtomic -- | Produce the positions where the action takes place. If a faction is -- returned, the action is visible only for that faction, if Nothing is -- returned, it's never visible. Empty list of positions implies the -- action is visible always. -- -- The goal of the mechanics: client should not get significantly more -- information by looking at the atomic commands he is able to see than -- by looking at the state changes they enact. E.g., -- UpdDisplaceActor in a black room, with one actor carrying a -- 0-radius light would not be distinguishable by looking at the state -- (or the screen) from UpdMoveActor of the illuminated actor, -- hence such UpdDisplaceActor should not be observable, but -- UpdMoveActor should be (or the former should be perceived as -- the latter). However, to simplify, we assing 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 seenAtomicCli :: Bool -> FactionId -> Perception -> PosAtomic -> Bool generalMoveItem :: MonadStateRead m => ItemId -> Int -> Container -> Container -> m [UpdAtomic] -- | Abstract syntax of client commands. See -- https://github.com/LambdaHack/LambdaHack/wiki/Client-server-architecture. module Game.LambdaHack.Common.Response -- | Abstract syntax of client commands that don't use the UI. data ResponseAI RespUpdAtomicAI :: !UpdAtomic -> ResponseAI RespQueryAI :: !ActorId -> ResponseAI RespPingAI :: ResponseAI -- | Abstract syntax of client commands that use the UI. data ResponseUI RespUpdAtomicUI :: !UpdAtomic -> ResponseUI RespSfxAtomicUI :: !SfxAtomic -> ResponseUI RespQueryUI :: ResponseUI RespPingUI :: ResponseUI instance Show ResponseAI instance Show ResponseUI -- | Sending atomic commands to clients and executing them on the server. -- See -- https://github.com/LambdaHack/LambdaHack/wiki/Client-server-architecture. module Game.LambdaHack.Atomic.BroadcastAtomicWrite -- | Send an atomic action to all clients that can see it. handleAndBroadcast :: MonadStateWrite m => Bool -> Pers -> (a -> FactionId -> LevelId -> m Perception) -> m a -> (FactionId -> ResponseAI -> m ()) -> (FactionId -> ResponseUI -> m ()) -> CmdAtomic -> m () -- | Server and client game state types and operations. module Game.LambdaHack.Client.State -- | Client state, belonging to a single faction. Some of the data, e.g, -- the history, carries over from game to game, even across playing -- sessions. Data invariant: if _sleader is Nothing -- then so is srunning. data StateClient StateClient :: !(Maybe TgtMode) -> !Target -> !Int -> !(EnumMap ActorId (Target, Maybe PathEtc)) -> !(EnumSet LevelId) -> !(EnumMap ActorId (Array BfsDistance, Point, Int, Maybe [Point])) -> !(EnumSet ActorId) -> !(Maybe RunParams) -> !Report -> !History -> !(EnumMap LevelId Time) -> ![CmdAtomic] -> !Discovery -> !DiscoAE -> !FactionPers -> !StdGen -> !LastRecord -> ![KM] -> !Int -> !(Maybe ActorId) -> !FactionId -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Int -> !ItemSlots -> !SlotChar -> !Text -> !DebugModeCli -> StateClient -- | targeting mode stgtMode :: StateClient -> !(Maybe TgtMode) -- | the common, cursor target scursor :: StateClient -> !Target -- | a parameter of the tgt digital line seps :: StateClient -> !Int -- | targets of our actors in the dungeon stargetD :: StateClient -> !(EnumMap ActorId (Target, Maybe PathEtc)) -- | the set of fully explored levels sexplored :: StateClient -> !(EnumSet LevelId) -- | pathfinding distances for our actors and paths to their targets, if -- any sbfsD :: StateClient -> !(EnumMap ActorId (Array BfsDistance, Point, Int, Maybe [Point])) -- | the set of currently selected actors sselected :: StateClient -> !(EnumSet ActorId) -- | parameters of the current run, if any srunning :: StateClient -> !(Maybe RunParams) -- | current messages sreport :: StateClient -> !Report -- | history of messages shistory :: StateClient -> !History -- | moves are displayed up to this time sdisplayed :: StateClient -> !(EnumMap LevelId Time) -- | atomic commands performed to date sundo :: StateClient -> ![CmdAtomic] -- | remembered item discoveries sdisco :: StateClient -> !Discovery -- | remembered aspects and effects of items sdiscoAE :: StateClient -> !DiscoAE -- | faction perception indexed by levels sfper :: StateClient -> !FactionPers -- | current random generator srandom :: StateClient -> !StdGen -- | state of key sequence recording slastRecord :: StateClient -> !LastRecord -- | state of key sequence playback slastPlay :: StateClient -> ![KM] -- | player just waited this many times swaitTimes :: StateClient -> !Int -- | current picked party leader _sleader :: StateClient -> !(Maybe ActorId) -- | faction controlled by the client _sside :: StateClient -> !FactionId -- | exit the game loop squit :: StateClient -> !Bool -- | whether it's an AI client sisAI :: StateClient -> !Bool -- | mark leader and party FOV smarkVision :: StateClient -> !Bool -- | mark smell, if the leader can smell smarkSmell :: StateClient -> !Bool -- | mark suspect features smarkSuspect :: StateClient -> !Bool -- | current game difficulty level scurDifficulty :: StateClient -> !Int -- | map from slots to items sslots :: StateClient -> !ItemSlots -- | last used slot slastSlot :: StateClient -> !SlotChar -- | current game mode sgameMode :: StateClient -> !Text -- | client debugging mode sdebugCli :: StateClient -> !DebugModeCli -- | Initial game client state. defStateClient :: History -> Report -> FactionId -> Bool -> StateClient defaultHistory :: IO History -- | 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 type PathEtc = ([Point], (Point, Int)) -- | Current targeting mode of a client. newtype TgtMode TgtMode :: LevelId -> TgtMode tgtLevelId :: TgtMode -> LevelId -- | 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 -- | last seen position of the targeted actor TEnemyPos :: !ActorId -> !LevelId -> !Point -> !Bool -> Target -- | target a concrete spot TPoint :: !LevelId -> !Point -> Target -- | target position relative to actor TVector :: !Vector -> Target -- | Parameters of the current run. data RunParams RunParams :: !ActorId -> ![ActorId] -> !Int -> !(Maybe Text) -> !(Maybe Vector) -> RunParams -- | the original leader from run start runLeader :: RunParams -> !ActorId -- | the list of actors that take part runMembers :: RunParams -> ![ActorId] -- | distance of the run so far (plus one, if multiple runners) runDist :: RunParams -> !Int -- | message with the next stop reason runStopMsg :: RunParams -> !(Maybe Text) -- | the direction of the initial step runInitDir :: RunParams -> !(Maybe Vector) type LastRecord = ([KM], [KM], Int) toggleMarkVision :: StateClient -> StateClient toggleMarkSmell :: StateClient -> StateClient toggleMarkSuspect :: StateClient -> StateClient instance Show TgtMode instance Eq TgtMode instance Binary TgtMode instance Show Target instance Eq Target instance Show RunParams instance Show StateClient instance Binary Target instance Binary RunParams instance Binary StateClient -- | Basic client monad and related operations. module Game.LambdaHack.Client.MonadClient class MonadStateRead m => MonadClient m getClient :: MonadClient m => m StateClient getsClient :: MonadClient m => (StateClient -> a) -> m a modifyClient :: MonadClient m => (StateClient -> StateClient) -> m () putClient :: MonadClient m => StateClient -> m () liftIO :: MonadClient m => IO a -> m a saveChanClient :: MonadClient m => m (ChanSave (State, StateClient)) debugPrint :: MonadClient m => Text -> m () saveClient :: MonadClient m => m () saveName :: FactionId -> Bool -> String restoreGame :: MonadClient m => m (Maybe (State, StateClient)) -- | Assuming the client runs on the same machine and for the same user as -- the server, move the server savegame out of the way. removeServerSave :: MonadClient m => m () -- | Invoke pseudo-random computation with the generator kept in the state. rndToAction :: MonadClient m => Rnd a -> m a -- | The client-server communication monads. module Game.LambdaHack.Client.ProtocolClient class MonadClient m => MonadClientReadResponse resp m | m -> resp receiveResponse :: MonadClientReadResponse resp m => m resp class MonadClient m => MonadClientWriteRequest req m | m -> req sendRequest :: MonadClientWriteRequest req m => req -> m () -- | Abstract syntax of server commands. See -- https://github.com/LambdaHack/LambdaHack/wiki/Client-server-architecture. module Game.LambdaHack.Common.Request -- | Cclient-server requests sent by AI clients. data RequestAI ReqAITimed :: !(RequestTimed a) -> RequestAI ReqAILeader :: !ActorId -> !RequestAI -> RequestAI ReqAIPong :: RequestAI -- | Client-server requests sent by UI clients. data RequestUI ReqUITimed :: !(RequestTimed a) -> RequestUI ReqUILeader :: !ActorId -> !RequestUI -> RequestUI ReqUIGameRestart :: !ActorId -> !Text -> !Int -> ![(Int, (Text, Text))] -> RequestUI ReqUIGameExit :: !ActorId -> !Int -> RequestUI ReqUIGameSave :: RequestUI ReqUIAutomate :: RequestUI ReqUIPong :: [CmdAtomic] -> RequestUI -- | Client-server requests that take game time. Sent by both AI and UI -- clients. data RequestTimed :: Ability -> * ReqMove :: !Vector -> RequestTimed AbMove ReqMelee :: !ActorId -> !ItemId -> !CStore -> RequestTimed AbMelee ReqDisplace :: !ActorId -> RequestTimed AbDisplace ReqAlter :: !Point -> !(Maybe Feature) -> RequestTimed AbAlter ReqWait :: RequestTimed AbWait ReqMoveItem :: !ItemId -> !Int -> !CStore -> !CStore -> RequestTimed AbMoveItem ReqProject :: !Point -> !Int -> !ItemId -> !CStore -> RequestTimed AbProject ReqApply :: !ItemId -> !CStore -> RequestTimed AbApply ReqTrigger :: !(Maybe Feature) -> RequestTimed AbTrigger data RequestAnyAbility RequestAnyAbility :: !(RequestTimed a) -> RequestAnyAbility data ReqFailure MoveNothing :: ReqFailure MeleeSelf :: ReqFailure MeleeDistant :: ReqFailure DisplaceDistant :: ReqFailure DisplaceAccess :: ReqFailure DisplaceProjectiles :: ReqFailure DisplaceDying :: ReqFailure DisplaceBraced :: ReqFailure DisplaceSupported :: ReqFailure AlterDistant :: ReqFailure AlterBlockActor :: ReqFailure AlterBlockItem :: ReqFailure AlterNothing :: ReqFailure EqpOverfull :: ReqFailure DurablePeriodicAbuse :: ReqFailure ApplyBlind :: ReqFailure ApplyOutOfReach :: ReqFailure ItemNothing :: ReqFailure ItemNotCalm :: ReqFailure ProjectAimOnself :: ReqFailure ProjectBlockTerrain :: ReqFailure ProjectBlockActor :: ReqFailure ProjectBlind :: ReqFailure TriggerNothing :: ReqFailure showReqFailure :: ReqFailure -> Msg anyToUI :: RequestAnyAbility -> RequestUI instance Show (RequestTimed a) instance Show RequestAnyAbility instance Show RequestUI instance Show RequestAI -- | Common client monad operations. module Game.LambdaHack.Client.CommonClient -- | Get the current perception of a client. getPerFid :: MonadClient m => LevelId -> m Perception -- | Calculate the position of an actor's target. aidTgtToPos :: MonadClient m => ActorId -> LevelId -> Maybe Target -> m (Maybe Point) -- | Check whether one is permitted to aim at a target (this is only -- checked for actors; positions let player shoot at obstacles, e.g., to -- destroy them). This assumes aidTgtToPos does not return -- Nothing. Returns a different seps, if needed to -- reach the target actor. -- -- Note: Perception is not enough for the check, because the target actor -- can be obscured by a glass wall or be out of sight range, but in -- weapon range. aidTgtAims :: MonadClient m => ActorId -> LevelId -> Maybe Target -> m (Either Text Int) -- | Counts the number of steps until the projectile would hit an actor or -- obstacle. Starts searching with the given eps and returns the first -- found eps for which the number reaches the distance between actor and -- target position, or Nothing if none can be found. makeLine :: MonadClient m => Actor -> Point -> Int -> m (Maybe Int) -- | The part of speech describing the actor (designated by actor id and -- present in the dungeon) or a special name if a leader of the -- observer's faction. partAidLeader :: MonadClient m => ActorId -> m Part -- | The part of speech describing the actor or "you" if a leader of the -- client's faction. The actor may be not present in the dungeon. partActorLeader :: MonadClient m => ActorId -> Actor -> m Part -- | The part of speech with the actor's pronoun or "you" if a leader of -- the client's faction. The actor may be not present in the dungeon. partPronounLeader :: MonadClient m => ActorId -> Actor -> m Part actorSkillsClient :: MonadClient m => ActorId -> Maybe ActorId -> m Skills updateItemSlot :: MonadClient m => Maybe ActorId -> ItemId -> m () fullAssocsClient :: MonadClient m => ActorId -> [CStore] -> m [(ItemId, ItemFull)] activeItemsClient :: MonadClient m => ActorId -> m [ItemFull] itemToFullClient :: MonadClient m => m (ItemId -> Int -> ItemFull) pickWeaponClient :: MonadClient m => ActorId -> ActorId -> m [RequestTimed AbMelee] sumOrganEqpClient :: MonadClient m => EqpSlot -> ActorId -> m Int getModeClient :: MonadClient m => m ModeKind -- | Semantics of abilities in terms of actions and the AI procedure for -- picking the best action for an actor. module Game.LambdaHack.Client.AI.ConditionClient -- | Require that the target enemy is visible by the party. condTgtEnemyPresentM :: MonadClient m => ActorId -> m Bool -- | Require that the target enemy is remembered on the actor's level. condTgtEnemyRememberedM :: MonadClient m => ActorId -> m Bool -- | Require that any non-dying foe is adjacent. condAnyFoeAdjM :: MonadStateRead m => ActorId -> m Bool -- | Require the actor's HP is low enough. condHpTooLowM :: MonadClient m => ActorId -> m Bool -- | Require the actor stands over a triggerable tile. condOnTriggerableM :: MonadStateRead m => ActorId -> m Bool -- | Require the actor blocks the paths of any of his party members. condBlocksFriendsM :: MonadClient m => ActorId -> m Bool -- | Require the actor stands over a weapon. condFloorWeaponM :: MonadClient m => ActorId -> m Bool -- | Check whether the actor has no weapon in equipment. condNoEqpWeaponM :: MonadClient m => ActorId -> m Bool -- | Require that the actor can project any items. condCanProjectM :: MonadClient m => ActorId -> m Bool -- | Require the actor is not calm enough. condNotCalmEnoughM :: MonadClient m => ActorId -> m Bool -- | Require that the actor stands over a desirable item. condDesirableFloorItemM :: MonadClient m => ActorId -> m Bool -- | Require the actor is in a bad position to melee. We do not check if -- the actor has a weapon, because having no innate weapon is rare. condMeleeBadM :: MonadClient m => ActorId -> m Bool -- | Require that the actor stands in the dark, but is betrayed by his own -- equipped light, condLightBetraysM :: MonadClient m => ActorId -> m Bool -- | Produce the list of items with a given property available to the actor -- and the items' values. benAvailableItems :: MonadClient m => ActorId -> (ItemFull -> Maybe Int -> Bool) -> [CStore] -> m [((Maybe (Int, (Int, Int)), (Int, CStore)), (ItemId, ItemFull))] -- | Produce the list of items on the ground beneath the actor. benGroundItems :: MonadClient m => ActorId -> m [((Maybe (Int, (Int, Int)), (Int, CStore)), (ItemId, ItemFull))] -- | Produce the chess-distance-sorted list of non-low-HP foes on the -- level. We don't consider path-distance, because we are interested in -- how soon the foe can hit us, which can diverge greately from path -- distance for short distances. threatDistList :: MonadClient m => ActorId -> m [(Int, (ActorId, Actor))] -- | Produce a list of acceptable adjacent points to flee to. fleeList :: MonadClient m => Bool -> ActorId -> m [(Int, Point)] -- | Semantics of most ResponseAI client commands. module Game.LambdaHack.Client.AI.PickActorClient pickActorToMove :: MonadClient m => (ActorId -> (ActorId, Actor) -> m (Maybe ((ActorId, Actor), (Target, PathEtc)))) -> ActorId -> m (ActorId, Actor) -- | Breadth first search and realted algorithms using the client monad. module Game.LambdaHack.Client.BfsClient -- | Get cached BFS data and path or, if not stored, generate, store and -- return. Due to laziness, they are not calculated until needed. getCacheBfsAndPath :: MonadClient m => ActorId -> Point -> m (Array BfsDistance, Maybe [Point]) getCacheBfs :: MonadClient m => ActorId -> m (Array BfsDistance) accessCacheBfs :: MonadClient m => ActorId -> Point -> m (Maybe Int) unexploredDepth :: MonadClient m => m (Int -> LevelId -> Bool) -- | Closest reachable unknown tile position, if any. closestUnknown :: MonadClient m => ActorId -> m (Maybe Point) -- | Closest (wrt paths) suspect tile. closestSuspect :: MonadClient m => ActorId -> m [Point] -- | Finds smells closest to the actor, except under the actor. closestSmell :: MonadClient m => ActorId -> m [(Int, (Point, SmellTime))] -- | Furthest (wrt paths) known position. furthestKnown :: MonadClient m => ActorId -> m Point -- | Closest (wrt paths) triggerable open tiles. The second argument can -- ever be true only if there's no escape from the dungeon. closestTriggers :: MonadClient m => Maybe Bool -> Bool -> ActorId -> m [Point] -- | Closest (wrt paths) items and changeable tiles (e.g., item caches). closestItems :: MonadClient m => ActorId -> m ([(Int, (Point, Maybe ItemBag))]) -- | Closest (wrt paths) enemy actors. closestFoes :: MonadClient m => [(ActorId, Actor)] -> ActorId -> m [(Int, (ActorId, Actor))] -- | Semantics of abilities in terms of actions and the AI procedure for -- picking the best action for an actor. module Game.LambdaHack.Client.AI.HandleAbilityClient -- | AI strategy based on actor's sight, smell, etc. Never empty. actionStrategy :: MonadClient m => ActorId -> m (Strategy RequestAnyAbility) instance Eq ApplyItemGroup -- | Let AI pick the best target for an actor. module Game.LambdaHack.Client.AI.PickTargetClient -- | AI proposes possible targets for the actor. Never empty. targetStrategy :: MonadClient m => ActorId -> ActorId -> m (Strategy (Target, Maybe PathEtc)) -- | 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 AI player. queryAI :: MonadClient m => ActorId -> m RequestAI -- | Client signals to the server that it's still online. pongAI :: MonadClient m => m RequestAI refreshTarget :: MonadClient m => ActorId -> (ActorId, Actor) -> m (Maybe ((ActorId, Actor), (Target, PathEtc))) pickAction :: MonadClient m => (ActorId, Actor) -> m RequestAnyAbility -- | Display game data on the screen using one of the available frontends -- (determined at compile time with cabal flags). module Game.LambdaHack.Client.UI.DrawClient -- | Color mode for the display. data ColorMode -- | normal, with full colours ColorFull :: ColorMode -- | black+white only ColorBW :: ColorMode -- | Draw the whole screen: level map and status area. Pass at most a -- single page if overlay of text unchanged to the frontends to display -- separately or overlay over map, depending on the frontend. draw :: MonadClient m => Bool -> ColorMode -> LevelId -> Maybe Point -> Maybe Point -> Maybe (Array BfsDistance, Maybe [Point]) -> (Text, Maybe Text) -> (Text, Maybe Text) -> Overlay -> m SingleFrame -- | Client monad for interacting with a human through UI. module Game.LambdaHack.Client.UI.MonadClientUI class MonadClient m => MonadClientUI m getsSession :: MonadClientUI m => (SessionUI -> a) -> m a liftIO :: MonadClientUI m => IO a -> m a -- | The information that is constant across a client playing session, -- including many consecutive games in a single session, but is -- completely disregarded and reset when a new playing session starts. -- Auxiliary AI and computer player clients have no sfs nor -- sbinding. data SessionUI SessionUI :: !ChanFrontend -> !Binding -> !(Maybe (MVar ())) -> !Config -> SessionUI -- | connection with the frontend schanF :: SessionUI -> !ChanFrontend -- | binding of keys to commands sbinding :: SessionUI -> !Binding sescMVar :: SessionUI -> !(Maybe (MVar ())) sconfig :: SessionUI -> !Config -- | Color mode for the display. data ColorMode -- | normal, with full colours ColorFull :: ColorMode -- | black+white only ColorBW :: ColorMode promptGetKey :: MonadClientUI m => [KM] -> SingleFrame -> m KM -- | Display an overlay and wait for a human player command. getKeyOverlayCommand :: MonadClientUI m => Bool -> Overlay -> m KM -- | Display a slideshow, awaiting confirmation for each slide except the -- last. getInitConfirms :: MonadClientUI m => ColorMode -> [KM] -> Slideshow -> m Bool displayFrame :: MonadClientUI m => Bool -> Maybe SingleFrame -> m () displayDelay :: MonadClientUI m => m () -- | Push frames or delays to the frame queue. displayFrames :: MonadClientUI m => Frames -> m () -- | Push frames or delays to the frame queue. Additionally set -- sdisplayed. because animations not always happen after -- SfxActorStart on the leader's level (e.g., death can lead to -- leader change to another level mid-turn, and there could be melee and -- animations on that level at the same moment). displayActorStart :: MonadClientUI m => Actor -> Frames -> m () -- | Draw the current level with the overlay on top. drawOverlay :: MonadClientUI m => Bool -> ColorMode -> Overlay -> m SingleFrame stopPlayBack :: MonadClientUI m => m () stopRunning :: MonadClientUI m => m () askConfig :: MonadClientUI m => m Config -- | Get the key binding. askBinding :: MonadClientUI m => m Binding -- | Sync frames display with the frontend. syncFrames :: MonadClientUI m => m () tryTakeMVarSescMVar :: MonadClientUI m => m Bool scoreToSlideshow :: MonadClientUI m => Int -> Status -> m Slideshow getLeaderUI :: MonadClientUI m => m ActorId getArenaUI :: MonadClientUI m => m LevelId viewedLevel :: MonadClientUI m => m LevelId targetDescLeader :: MonadClientUI m => ActorId -> m (Text, Maybe Text) targetDescCursor :: MonadClientUI m => m (Text, Maybe Text) leaderTgtToPos :: MonadClientUI m => m (Maybe Point) leaderTgtAims :: MonadClientUI m => m (Either Text Int) cursorToPos :: MonadClientUI m => m (Maybe Point) -- | Startup up the frontend together with the server, which starts up -- clients. module Game.LambdaHack.Client.UI.StartupFrontendClient -- | Wire together game content, the main loop of game clients, the main -- game loop assigned to this frontend (possibly containing the server -- loop, if the whole game runs in one process), UI config and the -- definitions of game commands. srtFrontend :: (DebugModeCli -> SessionUI -> State -> StateClient -> chanServerUI -> IO ()) -> (DebugModeCli -> SessionUI -> State -> StateClient -> chanServerAI -> IO ()) -> KeyKind -> COps -> DebugModeCli -> ((FactionId -> chanServerUI -> IO ()) -> (FactionId -> chanServerAI -> IO ()) -> IO ()) -> IO () -- | A set of widgets for UI clients. module Game.LambdaHack.Client.UI.WidgetClient -- | Display a message with a -more- prompt. Return value -- indicates if the player tried to cancel/escape. displayMore :: MonadClientUI m => ColorMode -> Msg -> m Bool -- | Print a yes/no question and return the player's answer. Use black and -- white colours to turn player's attention to the choice. displayYesNo :: MonadClientUI m => ColorMode -> Msg -> m Bool -- | Print a prompt and an overlay and wait for a player keypress. If many -- overlays, scroll screenfuls with SPACE. Do not wrap screenfuls (in -- some menus ? cycles views, so the user can restart from the -- top). displayChoiceUI :: MonadClientUI m => Msg -> Overlay -> [KM] -> m (Either Slideshow KM) -- | Push the frame depicting the current level to the frame queue. Only -- one screenful of the report is shown, the rest is ignored. displayPush :: MonadClientUI m => m () displayPushIfLid :: MonadClientUI m => LevelId -> m () -- | The prompt is shown after the current message, but not added to -- history. This is useful, e.g., in targeting mode, not to spam history. promptToSlideshow :: MonadClientUI m => Msg -> m Slideshow -- | The prompt is shown after the current message at the top of each -- slide. Together they may take more than one line. The prompt is not -- added to history. The portions of overlay that fit on the the rest of -- the screen are displayed below. As many slides as needed are shown. overlayToSlideshow :: MonadClientUI m => Msg -> Overlay -> m Slideshow overlayToBlankSlideshow :: MonadClientUI m => Msg -> Overlay -> m Slideshow -- | Render animations on top of the current screen frame. animate :: MonadClientUI m => LevelId -> Animation -> m Frames fadeOutOrIn :: MonadClientUI m => Bool -> m () -- | Client monad for interacting with a human through UI. module Game.LambdaHack.Client.UI.MsgClient -- | Add a message to the current report. msgAdd :: MonadClientUI m => Msg -> m () -- | Wipe out and set a new value for the current report. msgReset :: MonadClientUI m => Msg -> m () -- | Store current report in the history and reset report. recordHistory :: MonadClientUI m => m () type SlideOrCmd a = Either Slideshow a failWith :: MonadClientUI m => Msg -> m (SlideOrCmd a) failSlides :: MonadClientUI m => Slideshow -> m (SlideOrCmd a) failSer :: MonadClientUI m => ReqFailure -> m (SlideOrCmd a) -- | Produces a textual description of the terrain and items at an already -- explored position. Mute for unknown positions. The detailed variant is -- for use in the targeting mode. lookAt :: MonadClientUI m => Bool -> Text -> Bool -> Point -> ActorId -> Text -> m Text -- | Create a list of item names. itemOverlay :: MonadClient m => CStore -> ItemBag -> m Overlay -- | Running and disturbance. -- -- The general rule is: whatever is behind you (and so ignored -- previously), determines what you ignore moving forward. This is -- calcaulated separately for the tiles to the left, to the right and in -- the middle along the running direction. So, if you want to ignore -- something start running when you stand on it (or to the right or left, -- respectively) or by entering it (or passing to the right or left, -- respectively). -- -- Some things are never ignored, such as: enemies seen, imporant -- messages heard, solid tiles and actors in the way. module Game.LambdaHack.Client.UI.RunClient -- | Continue running in the given direction. continueRun :: MonadClient m => RunParams -> m (Either Msg (RunParams, RequestAnyAbility)) -- | Actor moves or searches or alters. No visible actor at the position. moveRunAid :: MonadClient m => ActorId -> Vector -> m (Either Msg RequestAnyAbility) -- | Inventory management and party cycling. TODO: document module Game.LambdaHack.Client.UI.InventoryClient failMsg :: MonadClientUI m => Msg -> m Slideshow msgCannotChangeLeader :: Msg -- | Let a human player choose any item from a given group. Note that this -- does not guarantee the chosen item belongs to the group, as the player -- can override the choice. getGroupItem :: MonadClientUI m => (Item -> Bool) -> Part -> Part -> [CStore] -> [CStore] -> m (SlideOrCmd ((ItemId, ItemFull), Container)) -- | Let the human player choose any item from a list of items and let him -- specify the number of items. getAnyItem :: MonadClientUI m => Part -> [CStore] -> [CStore] -> Bool -> Bool -> m (SlideOrCmd ((ItemId, ItemFull), Container)) -- | Display all items from a store and let the human player choose any or -- switch to any other store. getStoreItem :: MonadClientUI m => (Actor -> [ItemFull] -> Text) -> (Actor -> Text) -> Part -> Container -> m (SlideOrCmd ((ItemId, ItemFull), Container)) -- | Switches current member to the next on the level, if any, wrapping. memberCycle :: MonadClientUI m => Bool -> m Slideshow -- | Switches current member to the previous in the whole dungeon, -- wrapping. memberBack :: MonadClientUI m => Bool -> m Slideshow -- | Select a faction leader. False, if nothing to do. pickLeader :: MonadClientUI m => Bool -> ActorId -> m Bool instance Show ItemDialogState instance Eq ItemDialogState -- | Semantics of HumanCmd client commands that do not return -- server commands. None of such commands takes game time. TODO: document module Game.LambdaHack.Client.UI.HandleHumanLocalClient gameDifficultyCycle :: MonadClientUI m => m () pickLeaderHuman :: MonadClientUI m => Int -> m Slideshow -- | Switches current member to the next on the level, if any, wrapping. memberCycleHuman :: MonadClientUI m => m Slideshow -- | Switches current member to the previous in the whole dungeon, -- wrapping. memberBackHuman :: MonadClientUI m => m Slideshow -- | Display items from a given container store and describe the chosen -- one. describeItemHuman :: MonadClientUI m => CStore -> m Slideshow -- | Display the sum of equipments and inventory of the whole party. allOwnedHuman :: MonadClientUI m => m Slideshow selectActorHuman :: MonadClientUI m => m Slideshow selectNoneHuman :: (MonadClientUI m, MonadClient m) => m () -- | Clear current messages, show the next screen if any. clearHuman :: Monad m => m () repeatHuman :: MonadClient m => Int -> m () recordHuman :: MonadClientUI m => m Slideshow historyHuman :: MonadClientUI m => m Slideshow markVisionHuman :: MonadClientUI m => m () markSmellHuman :: MonadClientUI m => m () markSuspectHuman :: MonadClientUI m => m () -- | Display command help. helpHuman :: MonadClientUI m => m Slideshow -- | Display the main menu. mainMenuHuman :: MonadClientUI m => m Slideshow macroHuman :: MonadClient m => [String] -> m () -- | Move the cursor. Assumes targeting mode. moveCursorHuman :: MonadClientUI m => Vector -> Int -> m Slideshow -- | Cycle targeting mode. Do not change position of the cursor, switch -- among things at that position. tgtFloorHuman :: MonadClientUI m => m Slideshow tgtEnemyHuman :: MonadClientUI m => m Slideshow tgtUnknownHuman :: MonadClientUI m => m Slideshow tgtItemHuman :: MonadClientUI m => m Slideshow tgtStairHuman :: MonadClientUI m => Bool -> m Slideshow -- | Change the displayed level in targeting mode to (at most) k levels -- shallower. Enters targeting mode, if not already in one. tgtAscendHuman :: MonadClientUI m => Int -> m Slideshow -- | Tweak the eps parameter of the targeting digital line. epsIncrHuman :: MonadClientUI m => Bool -> m Slideshow tgtClearHuman :: MonadClientUI m => m Slideshow -- | Cancel something, e.g., targeting mode, resetting the cursor to the -- position of the leader. Chosen target is not invalidated. cancelHuman :: MonadClientUI m => m Slideshow -> m Slideshow -- | Accept something, e.g., targeting mode, keeping cursor where it was. -- Or perform the default action, if nothing needs accepting. acceptHuman :: MonadClientUI m => m Slideshow -> m Slideshow -- | Semantics of Cmd client commands that return server commands. A -- couple of them do not take time, the rest does. TODO: document module Game.LambdaHack.Client.UI.HandleHumanGlobalClient moveRunHuman :: MonadClientUI m => Bool -> Vector -> m (SlideOrCmd RequestAnyAbility) -- | Leader waits a turn (and blocks, etc.). waitHuman :: MonadClientUI m => m (RequestTimed AbWait) moveItemHuman :: MonadClientUI m => [CStore] -> CStore -> Text -> Bool -> m (SlideOrCmd (RequestTimed AbMoveItem)) projectHuman :: MonadClientUI m => [Trigger] -> m (SlideOrCmd (RequestTimed AbProject)) applyHuman :: MonadClientUI m => [Trigger] -> m (SlideOrCmd (RequestTimed AbApply)) -- | Ask for a direction and alter a tile, if possible. alterDirHuman :: MonadClientUI m => [Trigger] -> m (SlideOrCmd (RequestTimed AbAlter)) -- | Leader tries to trigger the tile he's standing on. triggerTileHuman :: MonadClientUI m => [Trigger] -> m (SlideOrCmd (RequestTimed AbTrigger)) stepToTargetHuman :: MonadClientUI m => m (SlideOrCmd RequestAnyAbility) gameRestartHuman :: MonadClientUI m => Text -> m (SlideOrCmd RequestUI) gameExitHuman :: MonadClientUI m => m (SlideOrCmd RequestUI) gameSaveHuman :: MonadClientUI m => m RequestUI automateHuman :: MonadClientUI m => m (SlideOrCmd RequestUI) -- | Semantics of human player commands. module Game.LambdaHack.Client.UI.HandleHumanClient -- | The semantics of human player commands in terms of the Action -- monad. Decides if the action takes time and what action to perform. -- Some time cosuming commands are enabled in targeting mode, but cannot -- be invoked in targeting mode on a remote level (level different than -- the level of the leader). cmdHumanSem :: MonadClientUI m => HumanCmd -> m (SlideOrCmd RequestUI) -- | Handle atomic commands received by the client. module Game.LambdaHack.Client.HandleAtomicClient -- | Effect of atomic actions on client state is calculated in the global -- state before the command is executed. cmdAtomicSemCli :: MonadClient m => UpdAtomic -> m () -- | Clients keep a subset of atomic commands sent by the server and add -- some of their own. The result of this function is the list of commands -- kept for each command received. cmdAtomicFilterCli :: MonadClient m => UpdAtomic -> m [UpdAtomic] -- | Display atomic commands received by the client. module Game.LambdaHack.Client.UI.DisplayAtomicClient -- | Visualize atomic actions sent to the client. This is done in the -- global state after the command is executed and after the client state -- is modified by the command. displayRespUpdAtomicUI :: MonadClientUI m => Bool -> State -> StateClient -> UpdAtomic -> m () -- | Display special effects (text, animation) sent to the client. displayRespSfxAtomicUI :: MonadClientUI m => Bool -> SfxAtomic -> m () -- | Ways for the client to use player input via UI to produce server -- requests, based on the client's view (visualized for the player) of -- the game state. module Game.LambdaHack.Client.UI class MonadClient m => MonadClientUI m -- | Handle the move of a UI player. queryUI :: MonadClientUI m => m RequestUI -- | Client signals to the server that it's still online, flushes frames -- (if needed) and sends some extra info. pongUI :: MonadClientUI m => m RequestUI -- | Visualize atomic actions sent to the client. This is done in the -- global state after the command is executed and after the client state -- is modified by the command. displayRespUpdAtomicUI :: MonadClientUI m => Bool -> State -> StateClient -> UpdAtomic -> m () -- | Display special effects (text, animation) sent to the client. displayRespSfxAtomicUI :: MonadClientUI m => Bool -> SfxAtomic -> m () -- | Wire together game content, the main loop of game clients, the main -- game loop assigned to this frontend (possibly containing the server -- loop, if the whole game runs in one process), UI config and the -- definitions of game commands. srtFrontend :: (DebugModeCli -> SessionUI -> State -> StateClient -> chanServerUI -> IO ()) -> (DebugModeCli -> SessionUI -> State -> StateClient -> chanServerAI -> IO ()) -> KeyKind -> COps -> DebugModeCli -> ((FactionId -> chanServerUI -> IO ()) -> (FactionId -> chanServerAI -> IO ()) -> IO ()) -> IO () -- | Key-command mappings to be used for the UI. data KeyKind -- | The information that is constant across a client playing session, -- including many consecutive games in a single session, but is -- completely disregarded and reset when a new playing session starts. -- Auxiliary AI and computer player clients have no sfs nor -- sbinding. data SessionUI -- | Color mode for the display. data ColorMode -- | normal, with full colours ColorFull :: ColorMode -- | black+white only ColorBW :: ColorMode -- | Display a message with a -more- prompt. Return value -- indicates if the player tried to cancel/escape. displayMore :: MonadClientUI m => ColorMode -> Msg -> m Bool -- | Add a message to the current report. msgAdd :: MonadClientUI m => Msg -> m () -- | Determine and process the next human player command. The argument is -- the last stop message due to running, if any. humanCommand :: MonadClientUI m => Maybe Msg -> m RequestUI -- | Semantics of client commands. module Game.LambdaHack.Client.HandleResponseClient handleResponseAI :: (MonadAtomic m, MonadClientWriteRequest RequestAI m) => ResponseAI -> m () handleResponseUI :: (MonadClientUI m, MonadAtomic m, MonadClientWriteRequest RequestUI m) => ResponseUI -> m () -- | The main loop of the client, processing human and computer player -- moves turn by turn. module Game.LambdaHack.Client.LoopClient loopAI :: (MonadAtomic m, MonadClientReadResponse ResponseAI m, MonadClientWriteRequest RequestAI m) => DebugModeCli -> m () loopUI :: (MonadClientUI m, MonadAtomic m, MonadClientReadResponse ResponseUI m, MonadClientWriteRequest RequestUI m) => DebugModeCli -> m () -- | Semantics of responses that are sent to clients. -- -- See -- https://github.com/LambdaHack/LambdaHack/wiki/Client-server-architecture. module Game.LambdaHack.Client -- | Wire together game content, the main loop of game clients, the main -- game loop assigned to this frontend (possibly containing the server -- loop, if the whole game runs in one process), UI config and the -- definitions of game commands. exeFrontend :: (MonadAtomic m, MonadClientUI m, MonadClientReadResponse ResponseUI m, MonadClientWriteRequest RequestUI m, MonadAtomic n, MonadClientReadResponse ResponseAI n, MonadClientWriteRequest RequestAI n) => (m () -> SessionUI -> State -> StateClient -> chanServerUI -> IO ()) -> (n () -> SessionUI -> State -> StateClient -> chanServerAI -> IO ()) -> KeyKind -> COps -> DebugModeCli -> ((FactionId -> chanServerUI -> IO ()) -> (FactionId -> chanServerAI -> IO ()) -> IO ()) -> IO () -- | Server and client game state types and operations. module Game.LambdaHack.Server.State -- | Global, server state. data StateServer StateServer :: !Discovery -> !DiscoRev -> !DiscoAE -> !ItemSeedDict -> !ItemRev -> !FlavourMap -> !ActorId -> !ItemId -> !(EnumMap LevelId Time) -> ![CmdAtomic] -> !Pers -> !StdGen -> !RNGs -> !Bool -> !Bool -> !ClockTime -> !ClockTime -> !Time -> !(EnumMap FactionId [(Int, (Text, Text))]) -> !DebugModeSer -> !DebugModeSer -> StateServer -- | full item discoveries data sdisco :: StateServer -> !Discovery -- | reverse disco map, used for item creation sdiscoRev :: StateServer -> !DiscoRev -- | full item aspect and effect data sdiscoAE :: StateServer -> !DiscoAE -- | map from item ids to item seeds sitemSeedD :: StateServer -> !ItemSeedDict -- | reverse id map, used for item creation sitemRev :: StateServer -> !ItemRev -- | association of flavour to items sflavour :: StateServer -> !FlavourMap -- | stores next actor index sacounter :: StateServer -> !ActorId -- | stores next item index sicounter :: StateServer -> !ItemId -- | actors are processed up to this time sprocessed :: StateServer -> !(EnumMap LevelId Time) -- | atomic commands performed to date sundo :: StateServer -> ![CmdAtomic] -- | perception of all factions sper :: StateServer -> !Pers -- | current random generator srandom :: StateServer -> !StdGen -- | initial random generators srngs :: StateServer -> !RNGs -- | exit the game loop squit :: StateServer -> !Bool -- | make backup savefile now sbkpSave :: StateServer -> !Bool -- | this session start time sstart :: StateServer -> !ClockTime -- | this game start time sgstart :: StateServer -> !ClockTime -- | clips since the start of the session sallTime :: StateServer -> !Time -- | hero names sent by clients sheroNames :: StateServer -> !(EnumMap FactionId [(Int, (Text, Text))]) -- | current debugging mode sdebugSer :: StateServer -> !DebugModeSer -- | debugging mode for the next game sdebugNxt :: StateServer -> !DebugModeSer -- | Initial, empty game server state. emptyStateServer :: StateServer -- | Debug commands. See debugArgs for the descriptions. data DebugModeSer DebugModeSer :: !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Text -> !Bool -> !(Maybe Int) -> !Bool -> !(Maybe StdGen) -> !(Maybe StdGen) -> !(Maybe FovMode) -> !Bool -> !Int -> !Bool -> !(Maybe String) -> !Bool -> !DebugModeCli -> DebugModeSer sknowMap :: DebugModeSer -> !Bool sknowEvents :: DebugModeSer -> !Bool sniffIn :: DebugModeSer -> !Bool sniffOut :: DebugModeSer -> !Bool sallClear :: DebugModeSer -> !Bool sgameMode :: DebugModeSer -> !Text sautomateAll :: DebugModeSer -> !Bool sstopAfter :: DebugModeSer -> !(Maybe Int) sbenchmark :: DebugModeSer -> !Bool sdungeonRng :: DebugModeSer -> !(Maybe StdGen) smainRng :: DebugModeSer -> !(Maybe StdGen) sfovMode :: DebugModeSer -> !(Maybe FovMode) snewGameSer :: DebugModeSer -> !Bool sdifficultySer :: DebugModeSer -> !Int sdumpInitRngs :: DebugModeSer -> !Bool ssavePrefixSer :: DebugModeSer -> !(Maybe String) sdbgMsgSer :: DebugModeSer -> !Bool sdebugCli :: DebugModeSer -> !DebugModeCli defDebugModeSer :: DebugModeSer data RNGs RNGs :: !(Maybe StdGen) -> !(Maybe StdGen) -> RNGs dungeonRandomGenerator :: RNGs -> !(Maybe StdGen) startingRandomGenerator :: RNGs -> !(Maybe StdGen) instance Show DebugModeSer instance Show StateServer instance Binary RNGs instance Binary DebugModeSer instance Binary StateServer instance Show RNGs -- | Game action monads and basic building blocks for human and computer -- player actions. Has no access to the the main action type. Does not -- export the liftIO operation nor a few other implementation -- details. module Game.LambdaHack.Server.MonadServer class MonadStateRead m => MonadServer m getServer :: MonadServer m => m StateServer getsServer :: MonadServer m => (StateServer -> a) -> m a modifyServer :: MonadServer m => (StateServer -> StateServer) -> m () putServer :: MonadServer m => StateServer -> m () liftIO :: MonadServer m => IO a -> m a saveChanServer :: MonadServer m => m (ChanSave (State, StateServer)) debugPrint :: MonadServer m => Text -> m () saveServer :: MonadServer m => m () saveName :: String -- | Dumps RNG states from the start of the game to stderr. dumpRngs :: MonadServer m => m () -- | Read the high scores table. Return the empty table if no file. restoreScore :: MonadServer m => COps -> m ScoreTable -- | Generate a new score, register it and save. registerScore :: MonadServer m => Status -> Maybe Actor -> FactionId -> m () resetSessionStart :: MonadServer m => m () resetGameStart :: MonadServer m => m () elapsedSessionTimeGT :: MonadServer m => Int -> m Bool tellAllClipPS :: MonadServer m => m () tellGameClipPS :: MonadServer m => m () tryRestore :: MonadServer m => COps -> DebugModeSer -> m (Maybe (State, StateServer)) -- | Compute and insert auxiliary optimized components into game content, -- to be used in time-critical sections of the code. speedupCOps :: Bool -> COps -> COps -- | Invoke pseudo-random computation with the generator kept in the state. rndToAction :: MonadServer m => Rnd a -> m a -- | Gets a random generator from the arguments or, if not present, -- generates one. getSetGen :: MonadServer m => Maybe StdGen -> m StdGen -- | Parsing of commandline arguments. module Game.LambdaHack.Server.Commandline debugArgs :: [String] -> IO DebugModeSer -- | Field Of View scanning with a variety of algorithms. See -- https://github.com/LambdaHack/LambdaHack/wiki/Fov-and-los for -- discussion. module Game.LambdaHack.Server.Fov -- | Calculate the perception of the whole dungeon. dungeonPerception :: FovMode -> State -> StateServer -> Pers -- | Calculate faction's perception of a level based on the lit tiles -- cache.. fidLidPerception :: COps -> FovMode -> PersLit -> FactionId -> LevelId -> Level -> Perception type PersLit = EnumMap LevelId (PerceptionLit, EnumMap FactionId ActorEqpBody) -- | Compute all lit positions in the dungeon litInDungeon :: FovMode -> State -> StateServer -> PersLit instance Show PerceptionReachable instance Show PerceptionLit -- | Server operations for items. module Game.LambdaHack.Server.ItemServer rollAndRegisterItem :: (MonadAtomic m, MonadServer m) => LevelId -> Freqs -> Container -> Bool -> m (Maybe (ItemId, (ItemFull, Text))) registerItem :: (MonadAtomic m, MonadServer m) => ItemKnown -> ItemSeed -> Int -> Container -> Bool -> m ItemId createItems :: (MonadAtomic m, MonadServer m) => Int -> Point -> LevelId -> m () placeItemsInDungeon :: (MonadAtomic m, MonadServer m) => m () fullAssocsServer :: MonadServer m => ActorId -> [CStore] -> m [(ItemId, ItemFull)] activeItemsServer :: MonadServer m => ActorId -> m [ItemFull] itemToFullServer :: MonadServer m => m (ItemId -> Int -> ItemFull) -- | Mapping over actor's items from a give store. mapActorCStore_ :: MonadServer m => CStore -> (ItemId -> Int -> m a) -> Actor -> m () -- | Server operations common to many modules. module Game.LambdaHack.Server.CommonServer execFailure :: (MonadAtomic m, MonadServer m) => ActorId -> RequestTimed a -> ReqFailure -> m () -- | Update the cached perception for the selected level, for a faction. -- The assumption is the level, and only the level, has changed since the -- previous perception calculation. resetFidPerception :: MonadServer m => PersLit -> FactionId -> LevelId -> m Perception resetLitInDungeon :: MonadServer m => m PersLit getPerFid :: MonadServer m => FactionId -> LevelId -> m Perception revealItems :: (MonadAtomic m, MonadServer m) => Maybe FactionId -> Maybe Actor -> m () moveStores :: (MonadAtomic m, MonadServer m) => ActorId -> CStore -> CStore -> m () deduceQuits :: (MonadAtomic m, MonadServer m) => Actor -> Status -> m () deduceKilled :: (MonadAtomic m, MonadServer m) => Actor -> m () electLeader :: MonadAtomic m => FactionId -> LevelId -> ActorId -> m () addActor :: (MonadAtomic m, MonadServer m) => Text -> FactionId -> Point -> LevelId -> (Actor -> Actor) -> Text -> Time -> m (Maybe ActorId) addActorIid :: (MonadAtomic m, MonadServer m) => ItemId -> ItemFull -> FactionId -> Point -> LevelId -> (Actor -> Actor) -> Text -> Time -> m (Maybe ActorId) projectFail :: (MonadAtomic m, MonadServer m) => ActorId -> Point -> Int -> ItemId -> CStore -> Bool -> m (Maybe ReqFailure) pickWeaponServer :: MonadServer m => ActorId -> m (Maybe (ItemId, CStore)) sumOrganEqpServer :: MonadServer m => EqpSlot -> ActorId -> m Int actorSkillsServer :: MonadServer m => ActorId -> Maybe ActorId -> m Skills -- | Debug output for requests and responseQs. module Game.LambdaHack.Server.DebugServer debugResponseAI :: MonadServer m => ResponseAI -> m () debugResponseUI :: MonadServer m => ResponseUI -> m () debugRequestAI :: MonadServer m => ActorId -> RequestAI -> m () debugRequestUI :: MonadServer m => ActorId -> RequestUI -> m () instance Show a => Show (DebugAid a) -- | The server definitions for the server-client communication protocol. module Game.LambdaHack.Server.ProtocolServer -- | Connection channel between the server and a single client. data ChanServer resp req ChanServer :: !(TQueue resp) -> !(TQueue req) -> ChanServer resp req responseS :: ChanServer resp req -> !(TQueue resp) requestS :: ChanServer resp req -> !(TQueue req) -- | Connection information for all factions, indexed by faction -- identifier. type ConnServerDict = EnumMap FactionId ConnServerFaction -- | The server monad with the ability to communicate with clients. class MonadServer m => MonadServerReadRequest m getDict :: MonadServerReadRequest m => m ConnServerDict getsDict :: MonadServerReadRequest m => (ConnServerDict -> a) -> m a modifyDict :: MonadServerReadRequest m => (ConnServerDict -> ConnServerDict) -> m () putDict :: MonadServerReadRequest m => ConnServerDict -> m () liftIO :: MonadServerReadRequest m => IO a -> m a sendUpdateAI :: MonadServerReadRequest m => FactionId -> ResponseAI -> m () sendQueryAI :: MonadServerReadRequest m => FactionId -> ActorId -> m RequestAI sendPingAI :: (MonadAtomic m, MonadServerReadRequest m) => FactionId -> m () sendUpdateUI :: MonadServerReadRequest m => FactionId -> ResponseUI -> m () sendQueryUI :: (MonadAtomic m, MonadServerReadRequest m) => FactionId -> ActorId -> m RequestUI sendPingUI :: (MonadAtomic m, MonadServerReadRequest m) => FactionId -> m () killAllClients :: (MonadAtomic m, MonadServerReadRequest m) => m () childrenServer :: MVar [Async ()] -- | Update connections to the new definition of factions. Connect to -- clients in old or newly spawned threads that read and write directly -- to the channels. updateConn :: (MonadAtomic m, MonadServerReadRequest m) => (FactionId -> ChanServer ResponseUI RequestUI -> IO ()) -> (FactionId -> ChanServer ResponseAI RequestAI -> IO ()) -> m () -- | The main game action monad type implementation. Just as any other -- component of the library, this implementation can be substituted. This -- module should not be imported anywhere except in Action to -- expose the executor to any code using the library. module Game.LambdaHack.SampleImplementation.SampleMonadClient -- | Init the client, then run an action, with a given session, state and -- history, in the IO monad. executorCli :: CliImplementation resp req () -> SessionUI -> State -> StateClient -> ChanServer resp req -> IO () instance Monad (CliImplementation resp req) instance Functor (CliImplementation resp req) instance Applicative (CliImplementation resp req) instance MonadAtomic (CliImplementation resp req) instance MonadClientWriteRequest req (CliImplementation resp req) instance MonadClientReadResponse resp (CliImplementation resp req) instance MonadClientUI (CliImplementation resp req) instance MonadClient (CliImplementation resp req) instance MonadStateWrite (CliImplementation resp req) instance MonadStateRead (CliImplementation resp req) -- | The main game action monad type implementation. Just as any other -- component of the library, this implementation can be substituted. This -- module should not be imported anywhere except in Action to -- expose the executor to any code using the library. module Game.LambdaHack.SampleImplementation.SampleMonadServer -- | Run an action in the IO monad, with undefined state. executorSer :: SerImplementation () -> IO () instance Monad SerImplementation instance Functor SerImplementation instance Applicative SerImplementation instance MonadAtomic SerImplementation instance MonadServerReadRequest SerImplementation instance MonadServer SerImplementation instance MonadStateWrite SerImplementation instance MonadStateRead SerImplementation -- | Server operations performed periodically in the game loop and related -- operations. module Game.LambdaHack.Server.PeriodicServer -- | Sapwn, possibly, a monster according to the level's actor groups. We -- assume heroes are never spawned. spawnMonster :: (MonadAtomic m, MonadServer m) => LevelId -> m () addAnyActor :: (MonadAtomic m, MonadServer m) => Freqs -> LevelId -> Time -> Maybe Point -> m (Maybe ActorId) dominateFidSfx :: (MonadAtomic m, MonadServer m) => FactionId -> ActorId -> m Bool -- | Advance the move time for the given actor, check if he's dominated and -- update his calm. We don't update calm once per game turn (even though -- it would make fast actors less overpowered), beucase the effects of -- close enemies would sometimes manifest only after a couple of player -- turns (or perhaps never at all, if the player and enemy move away -- before that moment). A side effect is that under peaceful -- circumstances, non-max calm cases a consistent regeneration UI -- indicator to be displayed each turn (not every few turns). advanceTime :: (MonadAtomic m, MonadServer m) => ActorId -> m () leadLevelFlip :: (MonadAtomic m, MonadServer m) => m () -- | Operations for starting and restarting the game. module Game.LambdaHack.Server.StartServer gameReset :: MonadServer m => COps -> DebugModeSer -> Maybe StdGen -> m State reinitGame :: (MonadAtomic m, MonadServer m) => m () initPer :: MonadServer m => m () -- | Spawn actors of any specified faction, friendly or not. To be used for -- initial dungeon population and for the summon effect. recruitActors :: (MonadAtomic m, MonadServer m) => [Point] -> LevelId -> Time -> FactionId -> m Bool -- | Apply debug options that don't need a new game. applyDebug :: MonadServer m => m () initDebug :: MonadStateRead m => COps -> DebugModeSer -> m DebugModeSer -- | Handle effects (most often caused by requests sent by clients). module Game.LambdaHack.Server.HandleEffectServer applyItem :: (MonadAtomic m, MonadServer m) => ActorId -> ItemId -> CStore -> m () -- | The source actor affects the target actor, with a given item. If any -- of the effect effect fires up, the item gets identified. This function -- is mutually recursive with effect and so it's a part of -- Effect semantics. itemEffect :: (MonadAtomic m, MonadServer m) => ActorId -> ActorId -> ItemId -> ItemFull -> Bool -> Bool -> m Bool itemEffectAndDestroy :: (MonadAtomic m, MonadServer m) => ActorId -> ActorId -> ItemId -> ItemFull -> CStore -> m () effectsSem :: (MonadAtomic m, MonadServer m) => [Effect Int] -> ActorId -> ActorId -> Bool -> m Bool -- | Drop a single actor's item. Note that if there multiple copies, at -- most one explodes to avoid excessive carnage and UI clutter (let's -- say, the multiple explosions interfere with each other or perhaps -- larger quantities of explosives tend to be packaged more safely). dropEqpItem :: (MonadAtomic m, MonadServer m) => ActorId -> Actor -> Bool -> ItemId -> Int -> m () armorHurtBonus :: (MonadAtomic m, MonadServer m) => ActorId -> ActorId -> m Int -- | The main loop of the server, processing human and computer player -- moves turn by turn. module Game.LambdaHack.Server.EndServer -- | Continue or exit or restart the game. endOrLoop :: (MonadAtomic m, MonadServer m) => m () -> m () -> m () -> m () -> m () dieSer :: (MonadAtomic m, MonadServer m) => ActorId -> Actor -> Bool -> m () -- | Drop all actor's items. If the actor hits another actor and this -- collision results in all item being dropped, all items are destroyed. -- If the actor does not hit, but dies, only fragile items are destroyed -- and only if the actor was a projectile (and so died by dropping to the -- ground due to exceeded range or bumping off an obstacle). dropEqpItems :: (MonadAtomic m, MonadServer m) => ActorId -> Actor -> Bool -> m () -- | Semantics of request. A couple of them do not take time, the rest -- does. Note that since the results are atomic commands, which are -- executed only later (on the server and some of the clients), all -- condition are checkd by the semantic functions in the context of the -- state before the server command. Even if one or more atomic actions -- are already issued by the point an expression is evaluated, they do -- not influence the outcome of the evaluation. TODO: document module Game.LambdaHack.Server.HandleRequestServer -- | The semantics of server commands. The resulting actor id is of the -- actor that carried out the request. handleRequestAI :: (MonadAtomic m, MonadServer m) => FactionId -> ActorId -> RequestAI -> m ActorId -- | The semantics of server commands. The resulting actor id is of the -- actor that carried out the request. Nothing means the command -- took no time. handleRequestUI :: (MonadAtomic m, MonadServer m) => FactionId -> RequestUI -> m (Maybe ActorId) -- | Actor moves or attacks. Note that client may not be able to see an -- invisible monster so it's the server that determines if melee took -- place, etc. Also, only the server is authorized to check if a move is -- legal and it needs full context for that, e.g., the initial actor -- position to check if melee attack does not try to reach to a distant -- tile. reqMove :: (MonadAtomic m, MonadServer m) => ActorId -> Vector -> m () -- | The main loop of the server, processing human and computer player -- moves turn by turn. module Game.LambdaHack.Server.LoopServer -- | Start a game session. Loop, communicating with clients. loopSer :: (MonadAtomic m, MonadServerReadRequest m) => DebugModeSer -> (FactionId -> ChanServer ResponseUI RequestUI -> IO ()) -> (FactionId -> ChanServer ResponseAI RequestAI -> IO ()) -> COps -> m () -- | Semantics of requests that are sent to the server. -- -- See -- https://github.com/LambdaHack/LambdaHack/wiki/Client-server-architecture. module Game.LambdaHack.Server -- | Fire up the frontend with the engine fueled by content. The action -- monad types to be used are determined by the exeSer and -- executorCli calls. If other functions are used in their place -- the types are different and so the whole pattern of computation is -- different. Which of the frontends is run depends on the flags supplied -- when compiling the engine library. mainSer :: (MonadAtomic m, MonadServerReadRequest m) => [String] -> COps -> (m () -> IO ()) -> (COps -> DebugModeCli -> ((FactionId -> ChanServer ResponseUI RequestUI -> IO ()) -> (FactionId -> ChanServer ResponseAI RequestAI -> IO ()) -> IO ()) -> IO ()) -> IO ()