-- | The type of game rule sets and assorted game data. module Game.LambdaHack.Content.RuleKind ( RuleKind(..), validateRuleKind, FovMode(..) ) where import Data.Binary import Data.Text (Text) import Data.Version import Game.LambdaHack.Common.HumanCmd import qualified Game.LambdaHack.Common.Key as K import Game.LambdaHack.Common.Misc import Game.LambdaHack.Common.Point -- TODO: very few rules are configurable yet, extend as needed. -- TODO: in the future, in @raccessible@ check flying for chasms, -- swimming for water, etc. -- TODO: tweak other code to allow games with only cardinal direction moves -- | 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 { rsymbol :: !Char -- ^ a symbol , rname :: !Text -- ^ short description , rfreq :: !Freqs -- ^ frequency within groups , raccessible :: !(Maybe (Point -> Point -> Bool)) , raccessibleDoor :: !(Maybe (Point -> Point -> Bool)) , rtitle :: !Text -- ^ the title of the game , rpathsDataFile :: FilePath -> IO FilePath -- ^ the path to data files , rpathsVersion :: !Version -- ^ the version of the game , ritemMelee :: ![Char] -- ^ symbols of melee weapons , ritemRanged :: ![Char] -- ^ ranged weapons and missiles , ritemProject :: ![Char] -- ^ symbols of items AI can project , rcfgUIName :: !FilePath -- ^ base name of the UI config file , rcfgUIDefault :: !String -- ^ the default UI settings config file , rmainMenuArt :: !Text -- ^ the ASCII art for the Main Menu , rhumanCommands :: ![(K.KM, (CmdCategory, HumanCmd))] -- ^ default client commands , rfirstDeathEnds :: !Bool -- ^ whether first non-spawner actor death -- ends the game , rfovMode :: !FovMode -- ^ FOV calculation mode , rsaveBkpClips :: !Int -- ^ game backup is saved that often , rleadLevelClips :: !Int -- ^ AI/spawn leader level flipped that often , rscoresFile :: !FilePath -- ^ name of the scores file , rsavePrefix :: !String -- ^ name of the savefile prefix } -- TODO: should Blind really be a FovMode, or a modifier? Let's decide -- when other similar modifiers are added. -- | Field Of View scanning mode. data FovMode = Shadow -- ^ restrictive shadow casting | Permissive -- ^ permissive FOV | Digital !Int -- ^ digital FOV with the given radius | Blind -- ^ only feeling out adjacent tiles by touch deriving (Show, Read) instance Binary FovMode where put Shadow = putWord8 0 put Permissive = putWord8 1 put (Digital r) = putWord8 2 >> put r put Blind = putWord8 3 get = do tag <- getWord8 case tag of 0 -> return Shadow 1 -> return Permissive 2 -> fmap Digital get 3 -> return Blind _ -> fail "no parse (FovMode)" -- | A dummy instance of the 'Show' class, to satisfy general requirments -- about content. We won't have many rule sets and they contain functions, -- so defining a proper instance is not practical. instance Show RuleKind where show _ = "The game ruleset specification." -- | Validates the ASCII art format (TODO). validateRuleKind :: [RuleKind] -> [RuleKind] validateRuleKind _ = []