{-# LANGUAGE ApplicativeDo #-} -- | Parsing of commandline arguments. module Game.LambdaHack.Server.Commandline ( serverOptionsPI #ifdef EXPOSE_INTERNAL -- * Internal operations , serverOptionsP -- other internal operations too numerous and changing, so not listed #endif ) where import Prelude () import Game.LambdaHack.Core.Prelude -- Cabal import qualified Paths_LambdaHack as Self (version) import qualified Data.Text as T import Data.Version import Options.Applicative import qualified System.Random as R -- Dependence on ClientOptions is an anomaly. Instead, probably the raw -- remaining commandline should be passed and parsed by the client to extract -- client and ui options from and singnal an error if anything was left. import Game.LambdaHack.Client (ClientOptions (..)) import Game.LambdaHack.Definition.Defs import Game.LambdaHack.Common.Faction import Game.LambdaHack.Content.ModeKind import Game.LambdaHack.Server.ServerOptions -- | Parser for server options from commandline arguments. serverOptionsPI :: ParserInfo ServerOptions serverOptionsPI = info (serverOptionsP <**> helper <**> version) $ fullDesc <> progDesc "Configure debug options here, gameplay options in configuration file." version :: Parser (a -> a) version = infoOption (showVersion Self.version) (long "version" <> help "Print engine version information") serverOptionsP :: Parser ServerOptions serverOptionsP = do ~(snewGameSer, scurChalSer) <- serToChallenge <$> newGameP knowMap <- knowMapP knowEvents <- knowEventsP knowItems <- knowItemsP showItemSamples <- showItemSamplesP sexposePlaces <- exposePlacesP sexposeItems <- exposeItemsP sexposeActors <- exposeActorsP sniff <- sniffP sallClear <- allClearP sboostRandomItem <- boostRandItemP sgameMode <- gameModeP sautomateAll <- automateAllP skeepAutomated <- keepAutomatedP sstopAfterSeconds <- stopAfterSecsP sstopAfterFrames <- stopAfterFramesP sprintEachScreen <- printEachScreenP sbenchmark <- benchmarkP sdungeonRng <- setDungeonRngP smainRng <- setMainRngP sdumpInitRngs <- dumpInitRngsP sdbgMsgSer <- dbgMsgSerP sgtkFontFamily <- gtkFontFamilyP sdlFontFile <- sdlFontFileP sdlScalableSizeAdd <- sdlScalableSizeAddP sdlBitmapSizeAdd <- sdlBitmapSizeAddP sscalableFontSize <- scalableFontSizeP sfontDir <- fontDirP slogPriority <- logPriorityP smaxFps <- maxFpsP sdisableAutoYes <- disableAutoYesP snoAnim <- noAnimP ssavePrefixSer <- savePrefixP sfrontendTeletype <- frontendTeletypeP sfrontendNull <- frontendNullP sfrontendLazy <- frontendLazyP sdbgMsgCli <- dbgMsgCliP pure ServerOptions { sclientOptions = ClientOptions { stitle = Nothing , snewGameCli = snewGameSer , ssavePrefixCli = ssavePrefixSer , .. } , sknowMap = knowMap || knowEvents || knowItems , sknowEvents = knowEvents || knowItems , sknowItems = knowItems , sshowItemSamples = not (knowEvents || knowItems) && showItemSamples , .. } where serToChallenge :: Maybe Int -> (Bool, Challenge) serToChallenge Nothing = (False, defaultChallenge) serToChallenge (Just cdiff) = (True, defaultChallenge {cdiff}) knowMapP :: Parser Bool knowMapP = switch ( long "knowMap" <> help "Reveal map for all clients in the next game" ) knowEventsP :: Parser Bool knowEventsP = switch ( long "knowEvents" <> help "Show all events in the next game (implies --knowMap)" ) knowItemsP :: Parser Bool knowItemsP = switch ( long "knowItems" <> help "Auto-identify all items in the next game (implies --knowEvents)" ) exposePlacesP :: Parser Bool exposePlacesP = switch ( long "exposePlaces" <> help "Expose all possible places in the next game" ) exposeItemsP :: Parser Bool exposeItemsP = switch ( long "exposeItems" <> help "Expose all possible items in the next game" ) exposeActorsP :: Parser Bool exposeActorsP = switch ( long "exposeActors" <> help "Expose all killable actors in the next game" ) showItemSamplesP :: Parser Bool showItemSamplesP = switch ( long "showItemSamples" <> help "At game over show samples of all items (--sknowEvents disables this)" ) sniffP :: Parser Bool sniffP = switch ( long "sniff" <> help "Monitor all trafic between server and clients" ) allClearP :: Parser Bool allClearP = switch ( long "allClear" <> help "Let all map tiles be translucent" ) boostRandItemP :: Parser Bool boostRandItemP = switch ( long "boostRandomItem" <> help "Pick a random item and make it very common" ) gameModeP :: Parser (Maybe (GroupName ModeKind)) gameModeP = optional $ toGameMode <$> strOption ( long "gameMode" <> metavar "MODE" <> help "Start next game in the scenario indicated by MODE" ) where toGameMode :: String -> GroupName ModeKind toGameMode = toGroupName . T.pack automateAllP :: Parser Bool automateAllP = switch ( long "automateAll" <> help "Give control of all UI teams to computer" ) keepAutomatedP :: Parser Bool keepAutomatedP = switch ( long "keepAutomated" <> help "Keep factions automated after game over" ) newGameP :: Parser (Maybe Int) newGameP = optional $ option auto ( long "newGame" <> help "Start a new game, overwriting the save file, with difficulty for all UI players set to N" <> metavar "N" ) stopAfterSecsP :: Parser (Maybe Int) stopAfterSecsP = optional $ option auto ( long "stopAfterSeconds" <> help "Exit game session after around N seconds" <> metavar "N" ) stopAfterFramesP :: Parser (Maybe Int) stopAfterFramesP = optional $ option auto ( long "stopAfterFrames" <> help "Exit game session after around N frames" <> metavar "N" ) printEachScreenP :: Parser Bool printEachScreenP = switch ( long "printEachScreen" <> help "Take a screenshot of each rendered distinct frame (SDL only)" ) benchmarkP :: Parser Bool benchmarkP = switch ( long "benchmark" <> help "Restrict file IO, print timing stats" ) setDungeonRngP :: Parser (Maybe R.StdGen) setDungeonRngP = optional $ option auto ( long "setDungeonRng" <> metavar "RNG_SEED" <> help "Set dungeon generation RNG seed to string RNG_SEED" ) setMainRngP :: Parser (Maybe R.StdGen) setMainRngP = optional $ option auto ( long "setMainRng" <> metavar "RNG_SEED" <> help "Set the main game RNG seed to string RNG_SEED" ) dumpInitRngsP :: Parser Bool dumpInitRngsP = switch ( long "dumpInitRngs" <> help "Dump the RNG seeds used to initialize the game" ) dbgMsgSerP :: Parser Bool dbgMsgSerP = switch ( long "dbgMsgSer" <> help "Emit extra internal server debug messages" ) gtkFontFamilyP :: Parser (Maybe Text) gtkFontFamilyP = optional $ T.pack <$> strOption ( long "gtkFontFamily" <> metavar "FONT_FAMILY" <> help "Use FONT_FAMILY for the main game window in GTK frontend" ) sdlFontFileP :: Parser (Maybe Text) sdlFontFileP = optional $ T.pack <$> strOption ( long "sdlFontFile" <> metavar "FONT_FILE" <> help "Use FONT_FILE for the main game window in SDL2 frontend" ) sdlScalableSizeAddP :: Parser (Maybe Int) sdlScalableSizeAddP = optional $ option auto ( long "sdlScalableSizeAdd" <> metavar "N" <> help "Enlarge map cells by N over scalable font max height in SDL2 frontend (N may be negative)" ) sdlBitmapSizeAddP :: Parser (Maybe Int) sdlBitmapSizeAddP = optional $ option auto ( long "sdlBitmapSizeAdd" <> metavar "N" <> help "Enlarge map cells by N on top of bitmap font max height in SDL2 frontend (N may be negative)" ) scalableFontSizeP :: Parser (Maybe Int) scalableFontSizeP = optional $ option auto ( long "scalableFontSize" <> metavar "N" <> help "Use font size of N pixels for the main game window (interpreted differently by different graphical frontends; ignored for bitmap fonts)" ) fontDirP :: Parser (Maybe FilePath) fontDirP = optional $ option auto ( long "fontDir" <> metavar "FILEPATH" <> help "Take font files for the SDL2 frontend from FILEPATH" ) maxFpsP :: Parser (Maybe Int) maxFpsP = optional $ max 1 <$> option auto ( long "maxFps" <> metavar "N" <> help "Display at most N frames per second" ) logPriorityP :: Parser (Maybe Int) logPriorityP = optional $ max 0 <$> option auto ( long "logPriority" <> metavar "N" <> help "Log only messages of priority at least N, where 1 (all) is the lowest and 5 (errors only) is the default." ) disableAutoYesP :: Parser Bool disableAutoYesP = switch ( long "disableAutoYes" <> help "Never auto-answer prompts, not even when UI faction is automated" ) noAnimP :: Parser (Maybe Bool) noAnimP = flag Nothing (Just True) ( long "noAnim" <> help "Don't show any animations" ) savePrefixP :: Parser String savePrefixP = strOption ( long "savePrefix" <> metavar "PREFIX" <> value "" <> help "Prepend PREFIX to all savefile names" ) frontendTeletypeP :: Parser Bool frontendTeletypeP = switch ( long "frontendTeletype" <> help "Use the line terminal frontend (for tests)" ) frontendNullP :: Parser Bool frontendNullP = switch ( long "frontendNull" <> help "Use frontend with no display (for benchmarks)" ) frontendLazyP :: Parser Bool frontendLazyP = switch ( long "frontendLazy" <> help "Use frontend that not even computes frames (for benchmarks)" ) dbgMsgCliP :: Parser Bool dbgMsgCliP = switch ( long "dbgMsgCli" <> help "Emit extra internal client debug messages" )