{-# 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.Common.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.Common.Faction import Game.LambdaHack.Common.Misc 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 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 sdlTtfSizeAdd <- sdlTtfSizeAddP sdlFonSizeAdd <- sdlFonSizeAddP sfontSize <- fontSizeP sfontDir <- fontDirP scolorIsBold <- noColorIsBoldP 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 , .. } 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)" ) 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" ) sdlTtfSizeAddP :: Parser (Maybe Int) sdlTtfSizeAddP = optional $ option auto ( long "sdlTtfSizeAdd" <> metavar "N" <> help "Enlarge map cells by N over scalable font max height in SDL2 frontend" ) sdlFonSizeAddP :: Parser (Maybe Int) sdlFonSizeAddP = optional $ option auto ( long "sdlFonSizeAdd" <> metavar "N" <> help "Enlarge map cells by N on top of .fon font max height in SDL2 frontend" ) fontSizeP :: Parser (Maybe Int) fontSizeP = optional $ option auto ( long "fontSize" <> metavar "N" <> help "Use font size N for the main game window (interpreted differently by different graphical frontends)" ) fontDirP :: Parser (Maybe FilePath) fontDirP = optional $ option auto ( long "fontDir" <> metavar "FILEPATH" <> help "Take font files for the SDL2 frontend from FILEPATH" ) noColorIsBoldP :: Parser (Maybe Bool) noColorIsBoldP = flag Nothing (Just False) ( long "noColorIsBold" <> help "Refrain from making some bright color characters bolder" ) 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 1 <$> 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" )