-- | Setting up game data and restoring or starting a game. module Game.LambdaHack.Start ( start ) where import qualified Control.Monad.State as MState import qualified Data.Array.Unboxed as A import Game.LambdaHack.Action import Game.LambdaHack.State import qualified Game.LambdaHack.DungeonState as DungeonState import qualified Game.LambdaHack.Save as Save import Game.LambdaHack.Turn import qualified Game.LambdaHack.Config as Config import Game.LambdaHack.ActorState import Game.LambdaHack.Item import qualified Game.LambdaHack.Feature as F import Game.LambdaHack.Content.TileKind import Game.LambdaHack.Content.RuleKind import Game.LambdaHack.Tile import qualified Game.LambdaHack.Kind as Kind import Game.LambdaHack.Msg speedup :: Kind.Ops TileKind -> Kind.Speedup TileKind speedup Kind.Ops{ofoldrWithKey, obounds} = let createTab :: (TileKind -> Bool) -> A.UArray (Kind.Id TileKind) Bool createTab p = let f _ k acc = p k : acc clearAssocs = ofoldrWithKey f [] in A.listArray obounds clearAssocs tabulate :: (TileKind -> Bool) -> Kind.Id TileKind -> Bool tabulate p = (createTab p A.!) isClearTab = tabulate $ kindHasFeature F.Clear isLitTab = tabulate $ kindHasFeature F.Lit in Kind.TileSpeedup {isClearTab, isLitTab} -- | Compute and insert auxiliary optimized components into game content, -- to be used in time-critical sections of the code. speedupCops :: Session -> Session speedupCops sess@Session{scops = cops@Kind.COps{cotile=tile}} = let ospeedup = speedup tile cotile = tile {Kind.ospeedup} scops = cops {Kind.cotile} in sess {scops} -- | Either restore a saved game, or setup a new game. -- Then call the main game loop. start :: Config.CP -> Session -> IO () start config1 slowSess = do let sess@Session{scops = cops@Kind.COps{corule}} = speedupCops slowSess title = rtitle $ Kind.stdRuleset corule pathsDataFile = rpathsDataFile $ Kind.stdRuleset corule restored <- Save.restoreGame pathsDataFile config1 title case restored of Right (msg, diary) -> do -- Starting a new game. (g2, config2) <- Config.getSetGen config1 "dungeonRandomGenerator" let (DungeonState.FreshDungeon{..}, ag) = MState.runState (DungeonState.generate cops config2) g2 sflavour = MState.evalState (dungeonFlavourMap (Kind.coitem cops)) ag (g3, config3) <- Config.getSetGen config2 "startingRandomGenerator" let state = defaultState config3 sflavour freshDungeon entryLevel entryLoc g3 hstate = initialHeroes cops entryLoc state handlerToIO sess hstate diary{sreport = singletonReport msg} handleTurn Left (state, diary) -> -- Running a restored a game. handlerToIO sess state -- This overwrites the "Really save/quit?" messages. diary{sreport = singletonReport $ "Welcome back to " ++ title ++ "."} handleTurn