LambdaHack 0.7.0.0 → 0.7.1.0
raw patch · 28 files changed
+567/−396 lines, 28 filesdep ~randomPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: random
API changes (from Hackage documentation)
- Game.LambdaHack.Client.UI.Frontend.Sdl: [sdisplayPermitted] :: FrontendSession -> MVar Bool
- Game.LambdaHack.Client.UI.Frontend.Sdl: displayNoLock :: ClientOptions -> FrontendSession -> SingleFrame -> IO ()
+ Game.LambdaHack.Client.ClientOptions: [slogPriority] :: ClientOptions -> Maybe Int
+ Game.LambdaHack.Client.UI.Frontend.Sdl: [scontinueSdlLoop] :: FrontendSession -> IORef Bool
+ Game.LambdaHack.Client.UI.Frontend.Sdl: [sframeDrawn] :: FrontendSession -> MVar ()
+ Game.LambdaHack.Client.UI.Frontend.Sdl: [sframeQueue] :: FrontendSession -> MVar SingleFrame
+ Game.LambdaHack.Client.UI.Frontend.Sdl: drawFrame :: ClientOptions -> FrontendSession -> SingleFrame -> IO ()
- Game.LambdaHack.Client.ClientOptions: ClientOptions :: Maybe Text -> Maybe Text -> Maybe Int -> Maybe Int -> Maybe Int -> Maybe Bool -> Maybe Int -> Bool -> Maybe Bool -> Bool -> Bool -> Maybe Text -> Maybe FilePath -> String -> Bool -> Bool -> Bool -> Bool -> Maybe Int -> Maybe Int -> ClientOptions
+ Game.LambdaHack.Client.ClientOptions: ClientOptions :: Maybe Text -> Maybe Text -> Maybe Int -> Maybe Int -> Maybe Int -> Maybe Bool -> Maybe Int -> Maybe Int -> Bool -> Maybe Bool -> Bool -> Bool -> Maybe Text -> Maybe FilePath -> String -> Bool -> Bool -> Bool -> Bool -> Maybe Int -> Maybe Int -> ClientOptions
- Game.LambdaHack.Client.UI.Frontend.Sdl: FrontendSession :: Window -> Renderer -> Font -> IORef FontAtlas -> IORef Texture -> IORef SingleFrame -> IORef Bool -> MVar Bool -> FrontendSession
+ Game.LambdaHack.Client.UI.Frontend.Sdl: FrontendSession :: Window -> Renderer -> Font -> IORef FontAtlas -> IORef Texture -> IORef SingleFrame -> IORef Bool -> IORef Bool -> MVar SingleFrame -> MVar () -> FrontendSession
- Game.LambdaHack.Client.UI.Frontend.Sdl: display :: ClientOptions -> FrontendSession -> SingleFrame -> IO ()
+ Game.LambdaHack.Client.UI.Frontend.Sdl: display :: FrontendSession -> SingleFrame -> IO ()
Files
- CHANGELOG.md +7/−0
- CREDITS +1/−0
- Game/LambdaHack/Client/AI/PickActorM.hs +1/−1
- Game/LambdaHack/Client/ClientOptions.hs +3/−0
- Game/LambdaHack/Client/UI/DisplayAtomicM.hs +9/−5
- Game/LambdaHack/Client/UI/Frontend/Dom.hs +2/−2
- Game/LambdaHack/Client/UI/Frontend/Sdl.hs +218/−194
- Game/LambdaHack/Client/UI/HandleHumanLocalM.hs +1/−0
- Game/LambdaHack/Client/UI/Key.hs +2/−2
- Game/LambdaHack/Common/Save.hs +1/−0
- Game/LambdaHack/Common/Thread.hs +2/−1
- Game/LambdaHack/Server/Commandline.hs +16/−1
- Game/LambdaHack/Server/DebugM.hs +1/−0
- Game/LambdaHack/Server/HandleRequestM.hs +1/−1
- Game/LambdaHack/Server/PeriodicM.hs +10/−11
- GameDefinition/Content/CaveKind.hs +10/−10
- GameDefinition/Content/ItemKind.hs +80/−3
- GameDefinition/Content/ItemKindActor.hs +48/−26
- GameDefinition/Content/ItemKindBlast.hs +33/−33
- GameDefinition/Content/ItemKindEmbed.hs +17/−13
- GameDefinition/Content/ItemKindOrgan.hs +20/−18
- GameDefinition/Content/ItemKindTemporary.hs +1/−1
- GameDefinition/Main.hs +7/−2
- GameDefinition/MainMenu.ascii +3/−3
- LICENSE +1/−1
- LambdaHack.cabal +1/−1
- Makefile +63/−60
- README.md +8/−7
CHANGELOG.md view
@@ -1,3 +1,10 @@+## [v0.7.1.0, aka 'Ancient troubles'](https://github.com/LambdaHack/LambdaHack/compare/v0.7.0.0...v0.7.1.0)++- add amazing cave and item (actor, blast, organ) descriptions+- package for Windows as an installer and also as zip archives+- fix a crash from SDL frontend under some OpenGL drivers (no thread-safety)+- add WWW address to the Main Menu, for other sites that may run our JS blob+ ## [v0.7.0.0, aka 'The dice are cast'](https://github.com/LambdaHack/LambdaHack/compare/v0.6.2.0...v0.7.0.0) - decouple tile searching from tile alteration
CREDITS view
@@ -5,6 +5,7 @@ Mikolaj Konarski Tuukka Turto Veronika Romashkina+@Peritract Fonts 16x16x.fon, 8x8x.fon and 8x8xb.fon are are taken from
Game/LambdaHack/Client/AI/PickActorM.hs view
@@ -85,7 +85,7 @@ -- because he is likely to be still stuck. Just ((aid, b), tgt) Just aidToAvoid | aid /= aidToAvoid ->- -- Not an attempted leader stuck this turn/+ -- Not an attempted leader stuck this turn. Just ((aid, b), tgt) _ -> Nothing oursTgtRaw <- mapM refresh ours
Game/LambdaHack/Client/ClientOptions.hs view
@@ -25,6 +25,8 @@ -- ^ Font size to use for the main game window. , scolorIsBold :: Maybe Bool -- ^ Whether to use bold attribute for colorful characters.+ , slogPriority :: Maybe Int+ -- ^ How much to log (e.g., from SDL). 1 is all, 5 is errors, the default. , smaxFps :: Maybe Int -- ^ Maximal frames per second. -- This is better low and fixed, to avoid jerkiness and delays@@ -67,6 +69,7 @@ , sdlFonSizeAdd = Nothing , sfontSize = Nothing , scolorIsBold = Nothing+ , slogPriority = Nothing , smaxFps = Nothing , sdisableAutoYes = False , snoAnim = Nothing
Game/LambdaHack/Client/UI/DisplayAtomicM.hs view
@@ -758,7 +758,9 @@ case (toSt, partingPart) of (Just status, Just pp) -> do isNoConfirms <- isNoConfirmsGame- go <- if isNoConfirms then return False else displaySpaceEsc ColorFull ""+ go <- if isNoConfirms && fmap stOutcome toSt /= Just Camping+ then return False+ else displaySpaceEsc ColorFull "" when (side == fid) recordHistory -- we are going to exit or restart, so record and clear, but only once when go $ do@@ -820,10 +822,12 @@ if go2 then viewItems pointer2 else return True go3 <- viewItems 2 when go3 $ do- -- Show score for any UI client after any kind of game exit,- -- even though it is saved only for human UI clients at game over.- scoreSlides <- scoreToSlideshow total status- void $ getConfirms ColorFull [K.spaceKM, K.escKM] scoreSlides+ unless isNoConfirms $ do+ -- Show score for any UI client after any kind of game exit,+ -- even though it is saved only for human UI clients at game over+ -- (that is not a noConfirms or benchmark game).+ scoreSlides <- scoreToSlideshow total status+ void $ getConfirms ColorFull [K.spaceKM, K.escKM] scoreSlides -- The last prompt stays onscreen during shutdown, etc. promptAdd pp partingSlide <- reportToSlideshow [K.spaceKM, K.escKM]
Game/LambdaHack/Client/UI/Frontend/Dom.hs view
@@ -94,7 +94,7 @@ tableElem <- unsafeCastTo HTMLTableElement tableElemRaw appendChild_ divBlock tableElem scharStyle <- getStyle tableElem- -- Speed: http://www.w3.org/TR/CSS21/tables.html#fixed-table-layout+ -- Speed: <http://www.w3.org/TR/CSS21/tables.html#fixed-table-layout> setProp scharStyle "table-layout" "fixed" setProp scharStyle "font-family" "lambdaHackFont" setProp scharStyle "font-size" $ tshow (fromJust sfontSize) <> "px"@@ -187,7 +187,7 @@ maybe (return ()) (\key -> IO.liftIO $ saveKMP rf modifier key pointer) mkey saveMouse = do- -- https://hackage.haskell.org/package/ghcjs-dom-0.2.1.0/docs/GHCJS-DOM-EventM.html+ -- <https://hackage.haskell.org/package/ghcjs-dom-0.2.1.0/docs/GHCJS-DOM-EventM.html> but <- mouseButton modifier <- readMod let key = case but of
Game/LambdaHack/Client/UI/Frontend/Sdl.hs view
@@ -4,7 +4,7 @@ #ifdef EXPOSE_INTERNAL -- * Internal operations , FontAtlas, FrontendSession(..), startupFun, shutdown, forceShutdown- , display, displayNoLock, modTranslate, keyTranslate, colorToRGBA+ , display, drawFrame, modTranslate, keyTranslate, colorToRGBA #endif ) where @@ -13,7 +13,6 @@ import Game.LambdaHack.Common.Prelude hiding (Alt) import Control.Concurrent-import Control.Concurrent.Async import qualified Data.Char as Char import qualified Data.EnumMap.Strict as EM import Data.IORef@@ -28,6 +27,7 @@ import qualified SDL import qualified SDL.Font as TTF import SDL.Input.Keyboard.Codes+import qualified SDL.Raw.Basic as SDL (logSetAllPriority) import qualified SDL.Vect as Vect import Game.LambdaHack.Client.ClientOptions@@ -50,7 +50,9 @@ , stexture :: IORef SDL.Texture , spreviousFrame :: IORef SingleFrame , sforcedShutdown :: IORef Bool- , sdisplayPermitted :: MVar Bool+ , scontinueSdlLoop :: IORef Bool+ , sframeQueue :: MVar SingleFrame+ , sframeDrawn :: MVar () } -- | The name of the frontend.@@ -60,14 +62,22 @@ -- | Set up and start the main loop providing input and output. -- -- Apparently some SDL backends are not thread-safe--- (https://wiki.libsdl.org/FAQDevelopment),--- so we stick to main thread.+-- (<https://wiki.libsdl.org/FAQDevelopment>;+-- "this should only be run in the thread that initialized the video subsystem,+-- and for extra safety, you should consider only doing those things+-- on the main thread in any case")+-- so we stick to a single bound thread (but not to the main thread;+-- enough is enough and at least in the case of OpenGL all bound threads+-- are supposed to be as good as the main thread). startup :: ClientOptions -> IO RawFrontend startup soptions = startupBound $ startupFun soptions startupFun :: ClientOptions -> MVar RawFrontend -> IO () startupFun soptions@ClientOptions{..} rfMVar = do SDL.initialize [SDL.InitVideo, SDL.InitEvents]+ -- lowest: pattern SDL_LOG_PRIORITY_VERBOSE = (1) :: LogPriority+ -- our default: pattern SDL_LOG_PRIORITY_ERROR = (5) :: LogPriority+ SDL.logSetAllPriority $ toEnum $ fromMaybe 5 slogPriority let title = fromJust stitle fontFileName = T.unpack (fromJust sdlFontFile) fontFile | isRelative fontFileName = fromJust sfontDir </> fontFileName@@ -86,7 +96,10 @@ screenV2 = SDL.V2 (toEnum $ xsize * boxSize) (toEnum $ ysize * boxSize) windowConfig = SDL.defaultWindow {SDL.windowInitialSize = screenV2}- rendererConfig = SDL.defaultRenderer {SDL.rendererTargetTexture = True}+ rendererConfig = SDL.RendererConfig+ { rendererType = SDL.AcceleratedVSyncRenderer+ , rendererTargetTexture = True+ } swindow <- SDL.createWindow title windowConfig srenderer <- SDL.createRenderer swindow (-1) rendererConfig let initTexture = do@@ -104,78 +117,46 @@ stexture <- newIORef texture spreviousFrame <- newIORef blankSingleFrame sforcedShutdown <- newIORef False- sdisplayPermitted <- newMVar True+ scontinueSdlLoop <- newIORef True+ sframeQueue <- newEmptyMVar+ sframeDrawn <- newEmptyMVar let sess = FrontendSession{..}- rf <- createRawFrontend (display soptions sess) (shutdown sess)+ rf <- createRawFrontend (display sess) (shutdown sess) putMVar rfMVar rf let pointTranslate :: forall i. (Enum i) => Vect.Point Vect.V2 i -> Point pointTranslate (SDL.P (SDL.V2 x y)) = Point (fromEnum x `div` boxSize) (fromEnum y `div` boxSize) redraw = do- displayPermitted <- takeMVar sdisplayPermitted- when displayPermitted $ do- -- Textures may be trashed and even invalid, especially on Windows.- atlas <- readIORef satlas- writeIORef satlas EM.empty- oldTexture <- readIORef stexture- newTexture <- initTexture- mapM_ SDL.destroyTexture $ EM.elems atlas- SDL.destroyTexture oldTexture- writeIORef stexture newTexture- prevFrame <- readIORef spreviousFrame- writeIORef spreviousFrame blankSingleFrame- displayNoLock soptions sess prevFrame- putMVar sdisplayPermitted displayPermitted- storeKeys :: IO ()- storeKeys = do- e <- SDL.waitEvent -- blocks here, so no polling- case SDL.eventPayload e of- SDL.KeyboardEvent keyboardEvent- | SDL.keyboardEventKeyMotion keyboardEvent == SDL.Pressed -> do- let sym = SDL.keyboardEventKeysym keyboardEvent- ksm = SDL.keysymModifier sym- shiftPressed = SDL.keyModifierLeftShift ksm- || SDL.keyModifierRightShift ksm- key = keyTranslate shiftPressed $ SDL.keysymKeycode sym- modifier = modTranslate ksm- p <- SDL.getAbsoluteMouseLocation- when (key == K.Esc) $ resetChanKey (fchanKey rf)- saveKMP rf modifier key (pointTranslate p)- SDL.MouseButtonEvent mouseButtonEvent- | SDL.mouseButtonEventMotion mouseButtonEvent == SDL.Released -> do- md <- modTranslate <$> SDL.getModState- let key = case SDL.mouseButtonEventButton mouseButtonEvent of- SDL.ButtonLeft -> K.LeftButtonRelease- SDL.ButtonMiddle -> K.MiddleButtonRelease- SDL.ButtonRight -> K.RightButtonRelease- _ -> K.LeftButtonRelease -- any other is spare left- modifier = if md == K.Shift then K.NoModifier else md- p = SDL.mouseButtonEventPos mouseButtonEvent- saveKMP rf modifier key (pointTranslate p)- SDL.MouseWheelEvent mouseWheelEvent -> do- md <- modTranslate <$> SDL.getModState- let SDL.V2 _ y = SDL.mouseWheelEventPos mouseWheelEvent- mkey = case (compare y 0, SDL.mouseWheelEventDirection- mouseWheelEvent) of- (EQ, _) -> Nothing- (LT, SDL.ScrollNormal) -> Just K.WheelSouth- (GT, SDL.ScrollNormal) -> Just K.WheelNorth- (LT, SDL.ScrollFlipped) -> Just K.WheelSouth- (GT, SDL.ScrollFlipped) -> Just K.WheelNorth- modifier = if md == K.Shift then K.NoModifier else md- p <- SDL.getAbsoluteMouseLocation- maybe (return ())- (\key -> saveKMP rf modifier key (pointTranslate p)) mkey- SDL.WindowClosedEvent{} -> forceShutdown sess- SDL.QuitEvent -> forceShutdown sess- SDL.WindowRestoredEvent{} -> redraw- SDL.WindowExposedEvent{} -> redraw -- needed on Windows- -- Probably not needed, because textures nor their content not lost:- -- SDL.WindowShownEvent{} -> redraw- _ -> return ()- displayPermitted <- readMVar sdisplayPermitted- if displayPermitted- then storeKeys+ -- Textures may be trashed and even invalid, especially on Windows.+ atlas <- readIORef satlas+ writeIORef satlas EM.empty+ oldTexture <- readIORef stexture+ newTexture <- initTexture+ mapM_ SDL.destroyTexture $ EM.elems atlas+ SDL.destroyTexture oldTexture+ writeIORef stexture newTexture+ prevFrame <- readIORef spreviousFrame+ writeIORef spreviousFrame blankSingleFrame+ drawFrame soptions sess prevFrame+ loopSDL :: IO ()+ loopSDL = do+ me <- SDL.pollEvent -- events take precedence over frames+ case me of+ Nothing -> do+ mfr <- tryTakeMVar sframeQueue+ case mfr of+ Just fr -> do+ -- Some SDL2 (OpenGL) backends are very thread-unsafe,+ -- so we need to ensure we draw on the same (bound) OS thread+ -- that initialized SDL, hence we have to poll frames.+ drawFrame soptions sess fr+ putMVar sframeDrawn () -- signal that drawing ended+ Nothing -> threadDelay 15000+ -- 60 polls per second, so keyboard snappy enough+ Just e -> handleEvent e+ continueSdlLoop <- readIORef scontinueSdlLoop+ if continueSdlLoop+ then loopSDL else do TTF.free sfont TTF.quit@@ -185,10 +166,54 @@ forcedShutdown <- readIORef sforcedShutdown when forcedShutdown exitSuccess -- not in the main thread, so no exit yet, see "Main"- storeKeys+ handleEvent e = case SDL.eventPayload e of+ SDL.KeyboardEvent keyboardEvent+ | SDL.keyboardEventKeyMotion keyboardEvent == SDL.Pressed -> do+ let sym = SDL.keyboardEventKeysym keyboardEvent+ ksm = SDL.keysymModifier sym+ shiftPressed = SDL.keyModifierLeftShift ksm+ || SDL.keyModifierRightShift ksm+ key = keyTranslate shiftPressed $ SDL.keysymKeycode sym+ modifier = modTranslate ksm+ p <- SDL.getAbsoluteMouseLocation+ when (key == K.Esc) $ resetChanKey (fchanKey rf)+ saveKMP rf modifier key (pointTranslate p)+ SDL.MouseButtonEvent mouseButtonEvent+ | SDL.mouseButtonEventMotion mouseButtonEvent == SDL.Released -> do+ md <- modTranslate <$> SDL.getModState+ let key = case SDL.mouseButtonEventButton mouseButtonEvent of+ SDL.ButtonLeft -> K.LeftButtonRelease+ SDL.ButtonMiddle -> K.MiddleButtonRelease+ SDL.ButtonRight -> K.RightButtonRelease+ _ -> K.LeftButtonRelease -- any other is spare left+ modifier = if md == K.Shift then K.NoModifier else md+ p = SDL.mouseButtonEventPos mouseButtonEvent+ saveKMP rf modifier key (pointTranslate p)+ SDL.MouseWheelEvent mouseWheelEvent -> do+ md <- modTranslate <$> SDL.getModState+ let SDL.V2 _ y = SDL.mouseWheelEventPos mouseWheelEvent+ mkey = case (compare y 0, SDL.mouseWheelEventDirection+ mouseWheelEvent) of+ (EQ, _) -> Nothing+ (LT, SDL.ScrollNormal) -> Just K.WheelSouth+ (GT, SDL.ScrollNormal) -> Just K.WheelNorth+ (LT, SDL.ScrollFlipped) -> Just K.WheelSouth+ (GT, SDL.ScrollFlipped) -> Just K.WheelNorth+ modifier = if md == K.Shift then K.NoModifier else md+ p <- SDL.getAbsoluteMouseLocation+ maybe (return ())+ (\key -> saveKMP rf modifier key (pointTranslate p)) mkey+ SDL.WindowClosedEvent{} -> forceShutdown sess+ SDL.QuitEvent -> forceShutdown sess+ SDL.WindowRestoredEvent{} -> redraw+ SDL.WindowExposedEvent{} -> redraw -- needed on Windows+ -- Probably not needed, because textures nor their content not lost:+ -- SDL.WindowShownEvent{} -> redraw+ _ -> return ()+ loopSDL shutdown :: FrontendSession -> IO ()-shutdown FrontendSession{..} = void $ swapMVar sdisplayPermitted False+shutdown FrontendSession{..} = writeIORef scontinueSdlLoop False forceShutdown :: FrontendSession -> IO () forceShutdown sess@FrontendSession{..} = do@@ -196,33 +221,31 @@ shutdown sess -- | Add a frame to be drawn.-display :: ClientOptions- -> FrontendSession -- ^ frontend session data+display :: FrontendSession -- ^ frontend session data -> SingleFrame -- ^ the screen frame to draw -> IO ()-display soptions sess@FrontendSession{..} curFrame = do- displayPermitted <- takeMVar sdisplayPermitted- if displayPermitted then do- -- Apparently some SDL backends are not thread-safe, so keep to main thread:- a <- asyncBound $ displayNoLock soptions sess curFrame- wait a- putMVar sdisplayPermitted displayPermitted+display FrontendSession{..} curFrame = do+ continueSdlLoop <- readIORef scontinueSdlLoop+ if continueSdlLoop then do+ putMVar sframeQueue curFrame+ -- Wait until the frame is drawn.+ takeMVar sframeDrawn else do- putMVar sdisplayPermitted displayPermitted forcedShutdown <- readIORef sforcedShutdown when forcedShutdown $ -- When there's a forced shutdown, ignore displaying one frame -- and don't occupy the CPU creating new ones and moving on with the game -- (possibly also saving the new game state, surprising the player),- -- but give time for SDL to clean up and exit via @exitSuccess@+ -- but delay the server and client thread(s) for a long time+ -- and let the SDL-init thread clean up and exit via @exitSuccess@ -- to avoid exiting via "thread blocked". threadDelay 50000 -displayNoLock :: ClientOptions- -> FrontendSession -- ^ frontend session data- -> SingleFrame -- ^ the screen frame to draw- -> IO ()-displayNoLock ClientOptions{..} FrontendSession{..} curFrame = do+drawFrame :: ClientOptions+ -> FrontendSession -- ^ frontend session data+ -> SingleFrame -- ^ the screen frame to draw+ -> IO ()+drawFrame ClientOptions{..} FrontendSession{..} curFrame = do let isFonFile = "fon" `isSuffixOf` T.unpack (fromJust sdlFontFile) sdlSizeAdd = fromJust $ if isFonFile then sdlFonSizeAdd else sdlTtfSizeAdd boxSize <- (+ sdlSizeAdd) <$> TTF.height sfont@@ -234,7 +257,8 @@ let rect = SDL.Rectangle (vp (x * boxSize) (y * boxSize)) (Vect.V2 (toEnum boxSize) (toEnum boxSize)) SDL.drawRect srenderer $ Just rect- SDL.rendererDrawColor srenderer SDL.$= colorToRGBA Color.Black -- reset back to black+ SDL.rendererDrawColor srenderer SDL.$= colorToRGBA Color.Black+ -- reset back to black setChar :: Int -> Word32 -> Word32 -> IO () setChar i w wPrev = unless (w == wPrev) $ do atlas <- readIORef satlas@@ -251,7 +275,7 @@ Color.HighlightGrey -> normalizeAc Color.BrBlack Color.HighlightWhite -> normalizeAc Color.White Color.HighlightMagenta -> normalizeAc Color.BrMagenta- -- https://www.libsdl.org/projects/SDL_ttf/docs/SDL_ttf_42.html#SEC42+ -- <https://www.libsdl.org/projects/SDL_ttf/docs/SDL_ttf_42.html#SEC42> textTexture <- case EM.lookup ac atlas of Nothing -> do -- Make all visible floors bold (no bold fold variant for 16x16x,@@ -264,7 +288,8 @@ else 8901 -- 0x22c5 else acCharRaw textSurface <-- TTF.shadedGlyph sfont (colorToRGBA fg) (colorToRGBA Color.Black) acChar+ TTF.shadedGlyph sfont (colorToRGBA fg)+ (colorToRGBA Color.Black) acChar textTexture <- SDL.createTextureFromSurface srenderer textSurface SDL.freeSurface textSurface writeIORef satlas $ EM.insert ac textTexture atlas -- not @acRaw@@@ -309,107 +334,106 @@ False keyTranslate :: Bool -> SDL.Keycode -> K.Key-keyTranslate shiftPressed n =- case n of- KeycodeEscape -> K.Esc- KeycodeReturn -> K.Return- KeycodeBackspace -> K.BackSpace- KeycodeTab -> if shiftPressed then K.BackTab else K.Tab- KeycodeSpace -> K.Space- KeycodeExclaim -> K.Char '!'- KeycodeQuoteDbl -> K.Char '"'- KeycodeHash -> K.Char '#'- KeycodePercent -> K.Char '%'- KeycodeDollar -> K.Char '$'- KeycodeAmpersand -> K.Char '&'- KeycodeQuote -> if shiftPressed then K.Char '"' else K.Char '\''- KeycodeLeftParen -> K.Char '('- KeycodeRightParen -> K.Char ')'- KeycodeAsterisk -> K.Char '*'- KeycodePlus -> K.Char '+'- KeycodeComma -> if shiftPressed then K.Char '<' else K.Char ','- KeycodeMinus -> if shiftPressed then K.Char '_' else K.Char '-'- KeycodePeriod -> if shiftPressed then K.Char '>' else K.Char '.'- KeycodeSlash -> if shiftPressed then K.Char '?' else K.Char '/'- Keycode1 -> if shiftPressed then K.Char '!' else K.Char '1'- Keycode2 -> if shiftPressed then K.Char '@' else K.Char '2'- Keycode3 -> if shiftPressed then K.Char '#' else K.Char '3'- Keycode4 -> if shiftPressed then K.Char '$' else K.Char '4'- Keycode5 -> if shiftPressed then K.Char '%' else K.Char '5'- Keycode6 -> if shiftPressed then K.Char '^' else K.Char '6'- Keycode7 -> if shiftPressed then K.Char '&' else K.Char '7'- Keycode8 -> if shiftPressed then K.Char '*' else K.Char '8'- Keycode9 -> if shiftPressed then K.Char '(' else K.Char '9'- Keycode0 -> if shiftPressed then K.Char ')' else K.Char '0'- KeycodeColon -> K.Char ':'- KeycodeSemicolon -> if shiftPressed then K.Char ':' else K.Char ';'- KeycodeLess -> K.Char '<'- KeycodeEquals -> if shiftPressed then K.Char '+' else K.Char '='- KeycodeGreater -> K.Char '>'- KeycodeQuestion -> K.Char '?'- KeycodeAt -> K.Char '@'- KeycodeLeftBracket -> if shiftPressed then K.Char '{' else K.Char '['- KeycodeBackslash -> if shiftPressed then K.Char '|' else K.Char '\\'- KeycodeRightBracket -> if shiftPressed then K.Char '}' else K.Char ']'- KeycodeCaret -> K.Char '^'- KeycodeUnderscore -> K.Char '_'- KeycodeBackquote -> if shiftPressed then K.Char '~' else K.Char '`'- KeycodeUp -> K.Up- KeycodeDown -> K.Down- KeycodeLeft -> K.Left- KeycodeRight -> K.Right- KeycodeHome -> K.Home- KeycodeEnd -> K.End- KeycodePageUp -> K.PgUp- KeycodePageDown -> K.PgDn- KeycodeInsert -> K.Insert- KeycodeDelete -> K.Delete- KeycodeKPDivide -> K.KP '/'- KeycodeKPMultiply -> K.KP '*'- KeycodeKPMinus -> K.Char '-' -- KP and normal are merged here- KeycodeKPPlus -> K.Char '+' -- KP and normal are merged here- KeycodeKPEnter -> K.Return- KeycodeKPEquals -> K.Return -- in case of some funny layouts- KeycodeKP1 -> if shiftPressed then K.KP '1' else K.End- KeycodeKP2 -> if shiftPressed then K.KP '2' else K.Down- KeycodeKP3 -> if shiftPressed then K.KP '3' else K.PgDn- KeycodeKP4 -> if shiftPressed then K.KP '4' else K.Left- KeycodeKP5 -> if shiftPressed then K.KP '5' else K.Begin- KeycodeKP6 -> if shiftPressed then K.KP '6' else K.Right- KeycodeKP7 -> if shiftPressed then K.KP '7' else K.Home- KeycodeKP8 -> if shiftPressed then K.KP '8' else K.Up- KeycodeKP9 -> if shiftPressed then K.KP '9' else K.PgUp- KeycodeKP0 -> if shiftPressed then K.KP '0' else K.Insert- KeycodeKPPeriod -> K.Char '.' -- dot and comma are merged here- KeycodeKPComma -> K.Char '.' -- to sidestep national standards- KeycodeF1 -> K.Fun 1- KeycodeF2 -> K.Fun 2- KeycodeF3 -> K.Fun 3- KeycodeF4 -> K.Fun 4- KeycodeF5 -> K.Fun 5- KeycodeF6 -> K.Fun 6- KeycodeF7 -> K.Fun 7- KeycodeF8 -> K.Fun 8- KeycodeF9 -> K.Fun 9- KeycodeF10 -> K.Fun 10- KeycodeF11 -> K.Fun 11- KeycodeF12 -> K.Fun 12- KeycodeLCtrl -> K.DeadKey- KeycodeLShift -> K.DeadKey- KeycodeLAlt -> K.DeadKey- KeycodeLGUI -> K.DeadKey- KeycodeRCtrl -> K.DeadKey- KeycodeRShift -> K.DeadKey- KeycodeRAlt -> K.DeadKey- KeycodeRGUI -> K.DeadKey- KeycodeMode -> K.DeadKey- KeycodeNumLockClear -> K.DeadKey- KeycodeUnknown -> K.Unknown "KeycodeUnknown"- _ -> let i = fromEnum $ unwrapKeycode n- in if | 97 <= i && i <= 122- && shiftPressed -> K.Char $ Char.chr $ i - 32- | 32 <= i && i <= 126 -> K.Char $ Char.chr i- | otherwise -> K.Unknown $ show n+keyTranslate shiftPressed n = case n of+ KeycodeEscape -> K.Esc+ KeycodeReturn -> K.Return+ KeycodeBackspace -> K.BackSpace+ KeycodeTab -> if shiftPressed then K.BackTab else K.Tab+ KeycodeSpace -> K.Space+ KeycodeExclaim -> K.Char '!'+ KeycodeQuoteDbl -> K.Char '"'+ KeycodeHash -> K.Char '#'+ KeycodePercent -> K.Char '%'+ KeycodeDollar -> K.Char '$'+ KeycodeAmpersand -> K.Char '&'+ KeycodeQuote -> if shiftPressed then K.Char '"' else K.Char '\''+ KeycodeLeftParen -> K.Char '('+ KeycodeRightParen -> K.Char ')'+ KeycodeAsterisk -> K.Char '*'+ KeycodePlus -> K.Char '+'+ KeycodeComma -> if shiftPressed then K.Char '<' else K.Char ','+ KeycodeMinus -> if shiftPressed then K.Char '_' else K.Char '-'+ KeycodePeriod -> if shiftPressed then K.Char '>' else K.Char '.'+ KeycodeSlash -> if shiftPressed then K.Char '?' else K.Char '/'+ Keycode1 -> if shiftPressed then K.Char '!' else K.Char '1'+ Keycode2 -> if shiftPressed then K.Char '@' else K.Char '2'+ Keycode3 -> if shiftPressed then K.Char '#' else K.Char '3'+ Keycode4 -> if shiftPressed then K.Char '$' else K.Char '4'+ Keycode5 -> if shiftPressed then K.Char '%' else K.Char '5'+ Keycode6 -> if shiftPressed then K.Char '^' else K.Char '6'+ Keycode7 -> if shiftPressed then K.Char '&' else K.Char '7'+ Keycode8 -> if shiftPressed then K.Char '*' else K.Char '8'+ Keycode9 -> if shiftPressed then K.Char '(' else K.Char '9'+ Keycode0 -> if shiftPressed then K.Char ')' else K.Char '0'+ KeycodeColon -> K.Char ':'+ KeycodeSemicolon -> if shiftPressed then K.Char ':' else K.Char ';'+ KeycodeLess -> K.Char '<'+ KeycodeEquals -> if shiftPressed then K.Char '+' else K.Char '='+ KeycodeGreater -> K.Char '>'+ KeycodeQuestion -> K.Char '?'+ KeycodeAt -> K.Char '@'+ KeycodeLeftBracket -> if shiftPressed then K.Char '{' else K.Char '['+ KeycodeBackslash -> if shiftPressed then K.Char '|' else K.Char '\\'+ KeycodeRightBracket -> if shiftPressed then K.Char '}' else K.Char ']'+ KeycodeCaret -> K.Char '^'+ KeycodeUnderscore -> K.Char '_'+ KeycodeBackquote -> if shiftPressed then K.Char '~' else K.Char '`'+ KeycodeUp -> K.Up+ KeycodeDown -> K.Down+ KeycodeLeft -> K.Left+ KeycodeRight -> K.Right+ KeycodeHome -> K.Home+ KeycodeEnd -> K.End+ KeycodePageUp -> K.PgUp+ KeycodePageDown -> K.PgDn+ KeycodeInsert -> K.Insert+ KeycodeDelete -> K.Delete+ KeycodeKPDivide -> K.KP '/'+ KeycodeKPMultiply -> K.KP '*'+ KeycodeKPMinus -> K.Char '-' -- KP and normal are merged here+ KeycodeKPPlus -> K.Char '+' -- KP and normal are merged here+ KeycodeKPEnter -> K.Return+ KeycodeKPEquals -> K.Return -- in case of some funny layouts+ KeycodeKP1 -> if shiftPressed then K.KP '1' else K.End+ KeycodeKP2 -> if shiftPressed then K.KP '2' else K.Down+ KeycodeKP3 -> if shiftPressed then K.KP '3' else K.PgDn+ KeycodeKP4 -> if shiftPressed then K.KP '4' else K.Left+ KeycodeKP5 -> if shiftPressed then K.KP '5' else K.Begin+ KeycodeKP6 -> if shiftPressed then K.KP '6' else K.Right+ KeycodeKP7 -> if shiftPressed then K.KP '7' else K.Home+ KeycodeKP8 -> if shiftPressed then K.KP '8' else K.Up+ KeycodeKP9 -> if shiftPressed then K.KP '9' else K.PgUp+ KeycodeKP0 -> if shiftPressed then K.KP '0' else K.Insert+ KeycodeKPPeriod -> K.Char '.' -- dot and comma are merged here+ KeycodeKPComma -> K.Char '.' -- to sidestep national standards+ KeycodeF1 -> K.Fun 1+ KeycodeF2 -> K.Fun 2+ KeycodeF3 -> K.Fun 3+ KeycodeF4 -> K.Fun 4+ KeycodeF5 -> K.Fun 5+ KeycodeF6 -> K.Fun 6+ KeycodeF7 -> K.Fun 7+ KeycodeF8 -> K.Fun 8+ KeycodeF9 -> K.Fun 9+ KeycodeF10 -> K.Fun 10+ KeycodeF11 -> K.Fun 11+ KeycodeF12 -> K.Fun 12+ KeycodeLCtrl -> K.DeadKey+ KeycodeLShift -> K.DeadKey+ KeycodeLAlt -> K.DeadKey+ KeycodeLGUI -> K.DeadKey+ KeycodeRCtrl -> K.DeadKey+ KeycodeRShift -> K.DeadKey+ KeycodeRAlt -> K.DeadKey+ KeycodeRGUI -> K.DeadKey+ KeycodeMode -> K.DeadKey+ KeycodeNumLockClear -> K.DeadKey+ KeycodeUnknown -> K.Unknown "KeycodeUnknown"+ _ -> let i = fromEnum $ unwrapKeycode n+ in if | 97 <= i && i <= 122+ && shiftPressed -> K.Char $ Char.chr $ i - 32+ | 32 <= i && i <= 126 -> K.Char $ Char.chr i+ | otherwise -> K.Unknown $ show n sDL_ALPHA_OPAQUE :: Word8
Game/LambdaHack/Client/UI/HandleHumanLocalM.hs view
@@ -755,6 +755,7 @@ in "Originally of" <+> gname tfact <> ", now fighting for" <+> dominatedBy <> "." _ | bfid body == side -> "" -- just one of us+ _ | bproj body -> "Launched by" <+> gname bfact <> "." _ -> "One of" <+> gname bfact <> "." idesc = case itemDisco $ itemToF (btrunk body) (1, []) of Nothing -> "" -- no details, only show the name
Game/LambdaHack/Client/UI/Key.hs view
@@ -281,7 +281,7 @@ -- To be used, in particular, for the command bindings and macros -- in the config file. ----- See https://github.com/twobob/gtk-/blob/master/gdk/keyname-table.h+-- See <https://github.com/twobob/gtk-/blob/master/gdk/keyname-table.h> keyTranslate :: String -> Key keyTranslate "less" = Char '<' keyTranslate "greater" = Char '>'@@ -426,7 +426,7 @@ keyTranslate s = Unknown s -- | Translate key from a Web API string description--- (https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key#Key_values)+-- (<https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key#Key_values>) -- to our internal key type. To be used in web frontends. -- The argument says whether Shift is pressed. keyTranslateWeb :: String -> Bool -> Key
Game/LambdaHack/Common/Save.hs view
@@ -52,6 +52,7 @@ dataDir <- appDataDir tryCreateDir (dataDir </> "saves") let fileName = stateToFileName s+ yield -- minimize UI lag due to saving encodeEOF (dataDir </> "saves" </> fileName) (vExevLib cops, s) -- Wait until the save finished. During that time, the mvar -- is continually updated to newest state values.
Game/LambdaHack/Common/Thread.hs view
@@ -10,7 +10,8 @@ import Control.Concurrent.Async import Control.Concurrent.MVar --- Swiped from http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Concurrent.html. Ported to Async to link exceptions, to let travis tests fail.+-- Swiped from <http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Concurrent.html>+-- Ported to Async to link exceptions, to let travis tests fail. forkChild :: MVar [Async ()] -> IO () -> IO () forkChild children io = do
Game/LambdaHack/Server/Commandline.hs view
@@ -12,8 +12,11 @@ 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 @@ -29,10 +32,15 @@ -- | Parser for server options from commandline arguments. serverOptionsPI :: ParserInfo ServerOptions-serverOptionsPI = info ( helper <*> serverOptionsP )+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)@@ -60,6 +68,7 @@ sfontSize <- fontSizeP sfontDir <- fontDirP scolorIsBold <- noColorIsBoldP+ slogPriority <- logPriorityP smaxFps <- maxFpsP sdisableAutoYes <- disableAutoYesP snoAnim <- noAnimP@@ -228,6 +237,12 @@ 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 =
Game/LambdaHack/Server/DebugM.hs view
@@ -40,6 +40,7 @@ debugResponse fid resp = case resp of RespUpdAtomic _ cmd@UpdPerception{} -> debugPlain fid "RespUpdAtomic" cmd RespUpdAtomic _ cmd@UpdResume{} -> debugPlain fid "RespUpdAtomic" cmd+ RespUpdAtomic _ cmd@UpdRestart{} -> debugPlain fid "RespUpdAtomic" cmd RespUpdAtomic _ cmd@UpdSpotTile{} -> debugPlain fid "RespUpdAtomic" cmd RespUpdAtomic _ cmd -> debugPretty fid "RespUpdAtomic" cmd RespUpdAtomicNoState cmd@UpdPerception{} ->
Game/LambdaHack/Server/HandleRequestM.hs view
@@ -85,7 +85,7 @@ {-# INLINE setBWait #-} setBWait cmd aid b = do let mwait = case cmd of- ReqWait -> Just True -- true wait, with bracind, no overhead, etc.+ ReqWait -> Just True -- true wait, with bracing, no overhead, etc. ReqWait10 -> Just False -- false wait, only one clip at a time _ -> Nothing when ((mwait == Just True) /= bwait b) $
Game/LambdaHack/Server/PeriodicM.hs view
@@ -160,13 +160,13 @@ modifyServer $ \ser -> ser {sactorTime = ageActor (bfid b) (blid b) aid t $ sactorTime ser} --- Add communication overhead time delta to all non-projectile, non-dying--- faction's actors (except the leader). Effectively, this limits moves+-- | Add communication overhead time delta to all non-projectile, non-dying+-- faction's actors, except the leader. Effectively, this limits moves -- of a faction on a level to 10, regardless of the number of actors -- and their speeds. To avoid animals suddenly acting extremely sluggish -- whenever monster's leader visits a distant arena that has a crowd -- of animals, overhead applies only to actors on the same level.--- Since the number of active arenas is limited, this bounds the total moves+-- Since the number of active levels is limited, this bounds the total moves -- per turn of each faction as well. -- -- Leader is immune from overhead and so he is faster than other faction@@ -176,22 +176,21 @@ -- having very long UI turns, introducing UI lag. overheadActorTime :: MonadServerAtomic m => FactionId -> LevelId -> m () overheadActorTime fid lid = do- actorTime <- getsServer $ (EM.! fid) . sactorTime+ actorTimeFid <- getsServer $ (EM.! fid) . sactorTime+ let actorTimeLid = actorTimeFid EM.! lid s <- getState mleader <- getsState $ gleader . (EM.! fid) . sfactionD- arenas <- getsServer sarenas- let f !lid2 !_aid !time | lid2 /= lid = time- f _ aid time =+ let f !aid !time = let body = getActorBody aid s in if isNothing (btrajectory body)- && bhp body > 0+ && bhp body > 0 -- speed up all-move-at-once carcass removal && Just aid /= mleader -- leader fast, for UI to be fast then timeShift time (Delta timeClip) else time- g !acc !lid2 = EM.adjust (EM.mapWithKey $ f lid2) lid acc- actorTimeNew = foldl' g actorTime arenas+ actorTimeLid2 = EM.mapWithKey f actorTimeLid+ actorTimeFid2 = EM.insert lid actorTimeLid2 actorTimeFid modifyServer $ \ser ->- ser {sactorTime = EM.insert fid actorTimeNew $ sactorTime ser}+ ser {sactorTime = EM.insert fid actorTimeFid2 $ sactorTime ser} -- | Swap the relative move times of two actors (e.g., when switching -- a UI leader).
GameDefinition/Content/CaveKind.hs view
@@ -60,7 +60,7 @@ , clegendLitTile = "legendLit" , cescapeGroup = Nothing , cstairFreq = [("staircase", 100)]- , cdesc = ""+ , cdesc = "Winding tunnels stretch into the dark." } -- no lit corridor alternative, because both lit # and . look bad here arena = rogue { csymbol = 'A'@@ -87,7 +87,7 @@ , cdefTile = "arenaSetLit" , cdarkCorTile = "trailLit" -- let trails give off light , clitCorTile = "trailLit"- , cdesc = ""+ , cdesc = "The shelves groan with dusty books and tattered scrolls." } arena2 = arena { cname = "Smoking rooms"@@ -98,7 +98,7 @@ , citemNum = 7 `d` 5 -- rare, so make it exciting , citemFreq = [("useful", 20), ("treasure", 40), ("any vial", 40)] , cdefTile = "arenaSetDark"- , cdesc = ""+ , cdesc = "Velvet couches exude the strong smell of tobacco." } laboratory = arena2 { csymbol = 'L'@@ -121,7 +121,7 @@ , cdefTile = "fillerWall" , cdarkCorTile = "labTrailLit" -- let lab smoke give off light always , clitCorTile = "labTrailLit"- , cdesc = "An experiment (or was it manufacturing?) had gone wrong here."+ , cdesc = "Shattered glassware and the sharp scent of spilt chemicals show that something terrible happened here." } empty = rogue { csymbol = 'E'@@ -153,7 +153,7 @@ , cdefTile = "emptySet" , cdarkCorTile = "floorArenaDark" , clitCorTile = "floorArenaLit"- , cdesc = ""+ , cdesc = "Swirls of warm fog fill the air, the hiss of geysers sounding all around." } noise = rogue { csymbol = 'N'@@ -180,7 +180,7 @@ , couterFenceTile = "noise fence" -- ensures no cut-off parts from collapsed , cdarkCorTile = "floorArenaDark" , clitCorTile = "floorArenaLit"- , cdesc = ""+ , cdesc = "Soon, these passages will be swallowed up by the mud." } noise2 = noise { cname = "Frozen derelict mine"@@ -189,12 +189,12 @@ , citemNum = 13 `d` 5 -- an incentive to explore the final labyrinth , cplaceFreq = [("noise", 1), ("mine", 99)] , cstairFreq = [("gated staircase", 100)]- , cdesc = ""+ , cdesc = "Pillars of shining ice create a frozen labyrinth." } shallow2rogue = rogue { cfreq = [("shallow random 2", 100)] , cextraStairs = 1 -- ensure heroes meet initial monsters and their loot- , cdesc = ""+ , cdesc = "The snorts and grunts of savage beasts can be clearly heard." } shallow1rogue = shallow2rogue { csymbol = 'B'@@ -206,7 +206,7 @@ , citemNum = 8 `d` 5 -- lure them in with loot , citemFreq = filter ((/= "treasure") . fst) $ citemFreq rogue , cescapeGroup = Just "escape up"- , cdesc = ""+ , cdesc = "This close to the surface, the sunlight still illuminates the dungeon." } raid = rogue { csymbol = 'T'@@ -244,7 +244,7 @@ , cdefTile = "brawlSetLit" , cdarkCorTile = "floorArenaLit" , clitCorTile = "floorArenaLit"- , cdesc = ""+ , cdesc = "Sunlight falls through the trees and dapples on the ground." } shootout = rogue -- a scenario with strong missiles; -- few solid tiles, but only translucent tiles or walkable
GameDefinition/Content/ItemKind.hs view
@@ -35,9 +35,9 @@ items :: [ItemKind] items =- [sandstoneRock, dart, spike, slingStone, slingBullet, paralizingProj, harpoon, net, light1, light2, light3, blanket, flask1, flask2, flask3, flask4, flask5, flask6, flask7, flask8, flask9, flask10, flask11, flask12, flask13, flask14, flask15, flask16, flask17, flask18, flask19, flask20, potion1, potion2, potion3, potion4, potion5, potion6, potion7, potion8, potion9, potion10, scroll1, scroll2, scroll3, scroll4, scroll5, scroll6, scroll7, scroll8, scroll9, scroll10, scroll11, scroll12, scroll13, jumpingPole, sharpeningTool, seeingItem, motionScanner, gorget, necklace1, necklace2, necklace3, necklace4, necklace5, necklace6, necklace7, necklace8, necklace9, imageItensifier, sightSharpening, ring1, ring2, ring3, ring4, ring5, ring6, ring7, ring8, armorLeather, armorMail, gloveFencing, gloveGauntlet, gloveJousting, buckler, shield, dagger, daggerDropBestWeapon, hammer, hammerParalyze, hammerSpark, sword, swordImpress, swordNullify, halberd, halberdPushActor, wand1, wand2, gem1, gem2, gem3, gem4, gem5, currency]+ [sandstoneRock, dart, spike, slingStone, slingBullet, paralizingProj, harpoon, net, light1, light2, light3, blanket, flask1, flask2, flask3, flask4, flask5, flask6, flask7, flask8, flask9, flask10, flask11, flask12, flask13, flask14, flask15, flask16, flask17, flask18, flask19, flask20, potion1, potion2, potion3, potion4, potion5, potion6, potion7, potion8, potion9, potion10, scroll1, scroll2, scroll3, scroll4, scroll5, scroll6, scroll7, scroll8, scroll9, scroll10, scroll11, scroll12, scroll13, jumpingPole, sharpeningTool, seeingItem, motionScanner, gorget, necklace1, necklace2, necklace3, necklace4, necklace5, necklace6, necklace7, necklace8, necklace9, imageItensifier, sightSharpening, ring1, ring2, ring3, ring4, ring5, ring6, ring7, ring8, armorLeather, armorMail, gloveFencing, gloveGauntlet, gloveJousting, buckler, shield, dagger, daggerDropBestWeapon, hammer, hammerParalyze, hammerSpark, sword, swordImpress, swordNullify, halberd, halberdPushActor, wand1, wand2, gem1, gem2, gem3, gem4, gem5, currency, explosive, firecracker] -sandstoneRock, dart, spike, slingStone, slingBullet, paralizingProj, harpoon, net, light1, light2, light3, blanket, flask1, flask2, flask3, flask4, flask5, flask6, flask7, flask8, flask9, flask10, flask11, flask12, flask13, flask14, flask15, flask16, flask17, flask18, flask19, flask20, potion1, potion2, potion3, potion4, potion5, potion6, potion7, potion8, potion9, potion10, scroll1, scroll2, scroll3, scroll4, scroll5, scroll6, scroll7, scroll8, scroll9, scroll10, scroll11, scroll12, scroll13, jumpingPole, sharpeningTool, seeingItem, motionScanner, gorget, necklace1, necklace2, necklace3, necklace4, necklace5, necklace6, necklace7, necklace8, necklace9, imageItensifier, sightSharpening, ring1, ring2, ring3, ring4, ring5, ring6, ring7, ring8, armorLeather, armorMail, gloveFencing, gloveGauntlet, gloveJousting, buckler, shield, dagger, daggerDropBestWeapon, hammer, hammerParalyze, hammerSpark, sword, swordImpress, swordNullify, halberd, halberdPushActor, wand1, wand2, gem1, gem2, gem3, gem4, gem5, currency :: ItemKind+sandstoneRock, dart, spike, slingStone, slingBullet, paralizingProj, harpoon, net, light1, light2, light3, blanket, flask1, flask2, flask3, flask4, flask5, flask6, flask7, flask8, flask9, flask10, flask11, flask12, flask13, flask14, flask15, flask16, flask17, flask18, flask19, flask20, potion1, potion2, potion3, potion4, potion5, potion6, potion7, potion8, potion9, potion10, scroll1, scroll2, scroll3, scroll4, scroll5, scroll6, scroll7, scroll8, scroll9, scroll10, scroll11, scroll12, scroll13, jumpingPole, sharpeningTool, seeingItem, motionScanner, gorget, necklace1, necklace2, necklace3, necklace4, necklace5, necklace6, necklace7, necklace8, necklace9, imageItensifier, sightSharpening, ring1, ring2, ring3, ring4, ring5, ring6, ring7, ring8, armorLeather, armorMail, gloveFencing, gloveGauntlet, gloveJousting, buckler, shield, dagger, daggerDropBestWeapon, hammer, hammerParalyze, hammerSpark, sword, swordImpress, swordNullify, halberd, halberdPushActor, wand1, wand2, gem1, gem2, gem3, gem4, gem5, currency, explosive, firecracker :: ItemKind necklace, ring, potion, flask, scroll, wand, gem :: ItemKind -- generic templates @@ -276,7 +276,7 @@ , AddArmorMelee 1, AddMaxCalm 2 ] , ieffects = [] , ifeature = [Lobable, Identified, Equipable] -- not Fragile; reusable douse- , idesc = ""+ , idesc = "Warm, comforting, and concealing, woven from soft wool." , ikit = [] } @@ -293,6 +293,77 @@ -- all aspects. -- -- No flask nor temporary organ of Calm depletion, since Calm reduced often.++-- All the explosive items are currently disabled (empty rarity),+-- so that we can brainstorm them without breaking game balance.+explosive = ItemKind+ { isymbol = symbolFlask+ -- if it's, in fact, a flask of laboratory-produced highly explosive+ -- liquid, symbolFlask makes sense; it also suggests it can be lobbed,+ -- which is very handy for an explosive thrown weapon;+ -- but symbolProjectile makes sense, too, if it's essentially a small+ -- grenade, specifically designed to be thrown, or symbolTool+ -- if it's a heavy mining explosive+ , iname = "explosive" -- we will need something more specific, even it it's+ -- only a generic template item+ , ifreq = [("useful", 100)]+ , iflavour = zipLiquid [BrRed]+ -- this ensures the object will be bright red on the screen+ -- and will be described as "red-speckled"; we are also free+ -- to manually set both the colour and the description+ , icount = 1+ , irarity = [] -- [(1, 7), (10, 4)] means it's quite common (7) first level+ -- and less common (4) on the deepest level of the dungeon,+ -- linearly interpolating in-between+ , iverbHit = "blast"+ , iweight = 500 -- flavour and affects the speed when thrown;+ -- 250g and below is full speed+ , idamage = toDmg 0+ , iaspects = []+ , ieffects = [Explode "blast 20", OnSmash (Explode "blast 20")]+ -- this is tricky: @OnSmash@ causes the explosion when the item+ -- hits a tile (including floor), so a well aimed item can successfully+ -- ungulf many enemies (or a single hidden or fast-moving enemy)+ -- in an explosion; however the lone @Explode "blast 20"@+ -- activates only when an actor is hit (or applies the item)+ -- and makes the actor the centre of the explosion and so keeps him+ -- unharmed (from the initial explosion; fireckrackers cause chain+ -- explosion so the secondary blasts can harm him);+ -- this is why "oil lamp", which is the closest to a grenade+ -- we currently have, doesn't have a lone Exlode effect,+ -- but instead causes a couple of unplesant effects directly:+ -- slight burning, before the fire is doused, and paralysis+ -- from slipping on the oil and slippery grip of items,+ -- until the oil can be wiped out; it also causes a tiny impact damage;+ -- all this suggests that we should define "blastI" item+ -- that not only blasts outward, but also inward, by first creating+ -- particles that move 1 (or 2?) tle away outward and then starting+ -- a standard "blast" explosion in each (firecracker does that,+ -- but with many, not just 2 levels of explosions)+ , ifeature = [Lobable, Fragile, Identified, toVelocity 50]+ -- not Applicable, because won't be applied, only thrown;+ -- Fragile, because we want it to explode at target tile, even if+ -- it hits no actor nor wall when it gets there;+ -- Identified, because the player recognizes it from the description+ -- already (unless we design granades that all look alike, but some+ -- explode with blast, others with fireckracker, etc. and the player+ -- needs to experiment to learn to recognize them);+ -- @toVelocity 50@ means will have 50% of the speed of an ideally shaped+ -- item of the same weight+ , idesc = "The practical application of science."+ , ikit = []+ }++firecracker = explosive+ { iname = "firecracker bag/stick?"+ -- remove the revealing name if we go the "10 kinds of grenades" route,+ -- but make sure it's not too similar to the current "20 kinds of flasks+ -- and potions that also explode" fun+ , iverbHit = "crack" -- a pun, matches the verb from ItemKindBlast.hs+ , ieffects = [Explode "firecracker 5", OnSmash (Explode "firecracker 5")]+ , idesc = "String and paper, concealing a deadly surprise."+ }+ flask = ItemKind { isymbol = symbolFlask , iname = "flask"@@ -473,6 +544,7 @@ , irarity = [(6, 9), (10, 9)] , ieffects = [ Unique, ELabel "of Attraction", Impress, RefillCalm (-20) , OnSmash (Explode "pheromone") ]+ -- , idesc = "" } potion3 = potion { ieffects = [ RefillHP 5, DropItem 1 maxBound COrgan "poisoned"@@ -532,6 +604,7 @@ , Impress, RefillCalm (-60) , OnSmash (Explode "healing mist 2") , OnSmash (Explode "pheromone") ]+ -- , idesc = "" } -- * Non-exploding consumables, not specifically designed for throwing@@ -782,6 +855,7 @@ , Recharging (RefillCalm (-1)) ] -- fake "hears something" :) ++ ieffects necklace , ifeature = Durable : ifeature necklace+ -- , idesc = "" } necklace8 = necklace { iaspects = [Timeout $ (1 `d` 3 + 3 - 1 `dl` 3) * 5]@@ -896,6 +970,7 @@ , ieffects = [ Unique, ELabel "of Rush" -- no explosion, because Durable , EqpSlot EqpSlotAddSpeed ] , ifeature = Durable : ifeature ring+ -- , idesc = "" } ring7 = ring { ifreq = [("useful", 10), ("ring of opportunity sniper", 1) ]@@ -1098,6 +1173,7 @@ , idamage = toDmg $ 8 `d` 1 , iaspects = iaspects hammer ++ [Timeout $ (1 `d` 2 + 3 - 1 `dl` 2) * 2] , ieffects = ieffects hammer ++ [Unique, Recharging $ Paralyze 10]+ -- , idesc = "" } hammerSpark = hammer { iname = "Grand Smithhammer"@@ -1106,6 +1182,7 @@ , idamage = toDmg $ 12 `d` 1 , iaspects = iaspects hammer ++ [AddShine 3, Timeout $ (1 `d` 4 + 4 - 1 `dl` 4) * 2] , ieffects = ieffects hammer ++ [Unique, Recharging $ Explode "spark"]+ -- , idesc = "" } sword = ItemKind { isymbol = symbolEdged
GameDefinition/Content/ItemKindActor.hs view
@@ -22,7 +22,6 @@ geyserBoiling, geyserArsenic, geyserSulfur :: ItemKind -- * Hunams- warrior = ItemKind { isymbol = '@' , iname = "warrior" -- modified if initial actors in hero faction@@ -39,18 +38,26 @@ , AddAbility AbAlter 2 ] , ieffects = [] , ifeature = [Durable, Identified]- , idesc = ""+ , idesc = "A hardened veteran of combat." , ikit = [ ("fist", COrgan), ("foot", COrgan), ("eye 6", COrgan) , ("sapient brain", COrgan) ] } warrior2 = warrior- { iname = "adventurer" }+ { iname = "adventurer"+ -- , idesc = ""+ } warrior3 = warrior- { iname = "blacksmith" }+ { iname = "blacksmith"+ -- , idesc = ""+ } warrior4 = warrior- { iname = "forester" }+ { iname = "forester"+ -- , idesc = ""+ } warrior5 = warrior- { iname = "scientist" }+ { iname = "scientist"+ -- , idesc = ""+ } scout = warrior { iname = "scout"@@ -59,11 +66,13 @@ ++ [ ("add sight", CEqp) , ("armor ranged", CEqp) , ("add nocto 1", CInv) ]+ -- , idesc = "" } ranger = warrior { iname = "ranger" , ifreq = [("ranger hero", 100), ("mobile", 1)] , ikit = ikit warrior ++ [("weak arrow", CInv), ("armor ranged", CEqp)]+ -- , idesc = "" } escapist = warrior { iname = "escapist"@@ -75,6 +84,7 @@ , ("flask", CInv) , ("light source", CInv) , ("blanket", CInv) ]+ -- , idesc = "" } ambusher = warrior { iname = "ambusher"@@ -83,25 +93,37 @@ ++ [ ("ring of opportunity sniper", CEqp) , ("light source", CEqp), ("wooden torch", CInv) , ("weak arrow", CInv), ("any arrow", CSha), ("flask", CSha) ]+ -- , idesc = "" } soldier = warrior { iname = "soldier" , ifreq = [("soldier hero", 100), ("mobile", 1)] , ikit = ikit warrior ++ [("starting weapon", CEqp)]+ -- , idesc = "" } civilian = warrior { iname = "clerk" , ifreq = [("civilian", 100), ("mobile", 1)]- , iflavour = zipPlain [BrBlack] }+ , iflavour = zipPlain [BrBlack]+ -- , idesc = ""+ } civilian2 = civilian- { iname = "hairdresser" }+ { iname = "hairdresser"+ -- , idesc = ""+ } civilian3 = civilian- { iname = "lawyer" }+ { iname = "lawyer"+ -- , idesc = ""+ } civilian4 = civilian- { iname = "peddler" }+ { iname = "peddler"+ -- , idesc = ""+ } civilian5 = civilian- { iname = "tax collector" }+ { iname = "tax collector"+ -- , idesc = ""+ } -- * Monsters @@ -238,7 +260,7 @@ , iaspects = [ AddMaxHP 12, AddMaxCalm 70, AddSpeed 24, AddNocto 2 ] , ieffects = [] , ifeature = [Durable, Identified]- , idesc = ""+ , idesc = "An opportunistic predator, feeding on carrion and the weak." , ikit = [ ("small jaw", COrgan), ("eye 6", COrgan), ("nostril", COrgan) , ("animal brain", COrgan) ] }@@ -261,7 +283,7 @@ -- on either side, are just too frustrating. , ieffects = [] , ifeature = [Durable, Identified]- , idesc = ""+ , idesc = "It soars high above, searching for vulnerable prey." , ikit = [ ("screeching beak", COrgan) -- in reality it grunts and hisses , ("small claw", COrgan), ("eye 7", COrgan) , ("animal brain", COrgan) ]@@ -280,7 +302,7 @@ , AddAbility AbAlter (-2) ] -- can't use stairs nor doors , ieffects = [] , ifeature = [Durable, Identified]- , idesc = ""+ , idesc = "Its only defence is the terrible stench." , ikit = [ ("scent gland", COrgan) , ("small claw", COrgan), ("snout", COrgan) , ("nostril", COrgan), ("eye 3", COrgan)@@ -300,7 +322,7 @@ , AddAbility AbAlter (-2) ] -- can't use stairs nor doors , ieffects = [] , ifeature = [Durable, Identified]- , idesc = ""+ , idesc = "When threatened, it rolls into a ball." , ikit = [ ("hooked claw", COrgan), ("snout", COrgan) , ("armored skin", COrgan), ("armored skin", COrgan) , ("nostril", COrgan), ("eye 3", COrgan)@@ -320,7 +342,7 @@ , AddAbility AbAlter (-2) ] -- can't use stairs nor doors , ieffects = [] , ifeature = [Durable, Identified]- , idesc = ""+ , idesc = "Numbing venom ensures that even the fastest prey has no escape." , ikit = [ ("venom tooth", COrgan), ("small claw", COrgan) , ("eye 3", COrgan), ("nostril", COrgan) , ("animal brain", COrgan) ]@@ -339,7 +361,7 @@ , AddAbility AbAlter (-2) ] -- can't use stairs nor doors , ieffects = [] , ifeature = [Durable, Identified]- , idesc = ""+ , idesc = "Beware its rattle - it serves as a warning of an agonising death." , ikit = [ ("venom fang", COrgan) , ("eye 4", COrgan), ("nostril", COrgan) , ("animal brain", COrgan) ]@@ -357,7 +379,7 @@ , iaspects = [ AddMaxHP 41, AddMaxCalm 60, AddSpeed 18, AddNocto 2 ] , ieffects = [] , ifeature = [Durable, Identified]- , idesc = ""+ , idesc = "Larger and more aggressive than any other lizard." , ikit = [ ("large tail", COrgan), ("jaw", COrgan) , ("hooked claw", COrgan), ("speed gland 4", COrgan) , ("armored skin", COrgan), ("eye 3", COrgan)@@ -377,7 +399,7 @@ , iaspects = [ AddMaxHP 20, AddMaxCalm 70, AddSpeed 32, AddNocto 2 ] , ieffects = [] , ifeature = [Durable, Identified]- , idesc = ""+ , idesc = "Skulking in the shadows, waiting for easy prey." , ikit = [ ("jaw", COrgan), ("eye 6", COrgan), ("nostril", COrgan) , ("animal brain", COrgan) ] }@@ -394,7 +416,7 @@ , iaspects = [ AddMaxHP 41, AddMaxCalm 70, AddSpeed 18, AddNocto 2 ] , ieffects = [] , ifeature = [Durable, Identified]- , idesc = ""+ , idesc = "An armored predator from the dawn of time." , ikit = [ ("large jaw", COrgan), ("large tail", COrgan) , ("small claw", COrgan) , ("armored skin", COrgan), ("eye 6", COrgan)@@ -438,7 +460,7 @@ , AddAbility AbAlter (-2) ] -- can't use stairs nor doors , ieffects = [] , ifeature = [Durable, Identified]- , idesc = ""+ , idesc = "Every bee would die for the queen." , ikit = [ ("bee sting", COrgan), ("vision 6", COrgan) , ("insect mortality", COrgan), ("animal brain", COrgan) ] }@@ -457,7 +479,7 @@ , AddArmorMelee 80, AddArmorRanged 40 ] , ieffects = [] , ifeature = [Durable, Identified]- , idesc = ""+ , idesc = "A vicious cloud of stings and hate." , ikit = [ ("sting", COrgan), ("vision 8", COrgan) , ("insect mortality", COrgan), ("animal brain", COrgan) ] }@@ -475,7 +497,7 @@ , AddAbility AbWait 1, AddAbility AbMelee 1 ] , ieffects = [] , ifeature = [Durable, Identified]- , idesc = ""+ , idesc = "Each branch bears long, curved thorns." , ikit = [("thorn", COrgan), ("armored skin", COrgan)] } geyserBoiling = ItemKind@@ -493,7 +515,7 @@ , AddArmorMelee 40, AddArmorRanged 20 ] -- hard material , ieffects = [] , ifeature = [Durable, Identified]- , idesc = ""+ , idesc = "A jet of acidic water, hot enough to melt flesh." , ikit = [("boiling vent", COrgan), ("boiling fissure", COrgan)] } geyserArsenic = ItemKind@@ -511,7 +533,7 @@ , AddAbility AbWait 1, AddAbility AbMelee 1 ] , ieffects = [] , ifeature = [Durable, Identified]- , idesc = ""+ , idesc = "The sharp scent betrays the poison within the spray." , ikit = [("arsenic vent", COrgan), ("arsenic fissure", COrgan)] } geyserSulfur = ItemKind@@ -529,6 +551,6 @@ , AddAbility AbWait 1, AddAbility AbMelee 1 ] , ieffects = [] , ifeature = [Durable, Identified]- , idesc = ""+ , idesc = "The pool boils and bubbles, stinking of rotten eggs. Despite the smell, these waters purify and strengthen." , ikit = [("sulfur vent", COrgan), ("sulfur fissure", COrgan)] }
GameDefinition/Content/ItemKindBlast.hs view
@@ -87,7 +87,7 @@ $ toGroupName $ "firecracker" <+> tshow (n - 1) | n > 2 ] , ifeature = [toVelocity 5, Fragile, Identified]- , idesc = ""+ , idesc = "Scraps of burnt paper, covering little pockets of black powder, buffeted by colorful explosions." , ikit = [] } firecracker7 = firecracker 7@@ -114,7 +114,7 @@ -- Linger 10, because sometimes it takes 2 turns due to starting just -- before actor turn's end (e.g., via a necklace). , ifeature = [toLinger 10, Fragile, Identified] -- 2 steps, 1 turn- , idesc = ""+ , idesc = "A pleasant scent." , ikit = [] } pheromone = ItemKind@@ -130,7 +130,7 @@ , iaspects = [] , ieffects = [Impress, RefillCalm (-10)] , ifeature = [toVelocity 10, Fragile, Identified] -- 2 steps, 2 turns- , idesc = ""+ , idesc = "A sharp, strong scent." , ikit = [] } mistCalming = ItemKind -- unused@@ -146,7 +146,7 @@ , iaspects = [] , ieffects = [RefillCalm 2] , ifeature = [toVelocity 5, Fragile, Identified] -- 1 step, 1 turn- , idesc = ""+ , idesc = "A soothing, gentle cloud." , ikit = [] } odorDistressing = ItemKind@@ -162,7 +162,7 @@ , iaspects = [] , ieffects = [RefillCalm (-20)] , ifeature = [toLinger 10, Fragile, Identified] -- 2 steps, 1 turn- , idesc = ""+ , idesc = "It turns the stomach." , ikit = [] } mistHealing = ItemKind@@ -178,7 +178,7 @@ , iaspects = [AddShine 1] , ieffects = [RefillHP 2] , ifeature = [toVelocity 5, Fragile, Identified] -- 1 step, 1 turn- , idesc = ""+ , idesc = "It fills the air with light and life." , ikit = [] } mistHealing2 = ItemKind@@ -194,7 +194,7 @@ , iaspects = [AddShine 2] , ieffects = [RefillHP 4] , ifeature = [toVelocity 5, Fragile, Identified] -- 1 step, 1 turn- , idesc = ""+ , idesc = "At its touch, wounds close and bruises fade." , ikit = [] } mistWounding = ItemKind@@ -210,7 +210,7 @@ , iaspects = [] , ieffects = [RefillHP (-2)] , ifeature = [toVelocity 5, Fragile, Identified] -- 1 step, 1 turn- , idesc = ""+ , idesc = "The air itself stings and itches." , ikit = [] } distortion = ItemKind@@ -226,7 +226,7 @@ , iaspects = [] , ieffects = [Teleport $ 15 + 1 `d` 10] , ifeature = [toLinger 10, Fragile, Identified] -- 2 steps, 1 turn- , idesc = ""+ , idesc = "The air shifts oddly, as though light is being warped." , ikit = [] } glassPiece = ItemKind -- when blowing up windows@@ -242,7 +242,7 @@ , iaspects = [] , ieffects = [RefillHP (-1)] -- high velocity, so can't do idamage , ifeature = [toLinger 20, Fragile, Identified] -- 4 steps, 1 turn- , idesc = ""+ , idesc = "Swift, sharp edges." , ikit = [] } smoke = ItemKind -- when stuff burns out -- unused@@ -258,7 +258,7 @@ , iaspects = [] , ieffects = [] , ifeature = [toVelocity 20, Fragile, Identified] -- 4 steps, 2 turns- , idesc = ""+ , idesc = "Twirling clouds of grey smoke." , ikit = [] } boilingWater = ItemKind@@ -274,7 +274,7 @@ , iaspects = [] , ieffects = [Burn 1] , ifeature = [toVelocity 30, Fragile, Identified] -- 6 steps, 2 turns- , idesc = ""+ , idesc = "It bubbles and hisses." , ikit = [] } glue = ItemKind@@ -290,7 +290,7 @@ , iaspects = [] , ieffects = [Paralyze 10] , ifeature = [toVelocity 20, Fragile, Identified] -- 4 steps, 2 turns- , idesc = ""+ , idesc = "Thick and clinging." , ikit = [] } singleSpark = ItemKind@@ -306,7 +306,7 @@ , iaspects = [AddShine 4] , ieffects = [] , ifeature = [toLinger 5, Fragile, Identified] -- 1 step, 1 turn- , idesc = ""+ , idesc = "A glowing ember." , ikit = [] } spark = ItemKind@@ -322,7 +322,7 @@ , iaspects = [AddShine 4] , ieffects = [Burn 1] , ifeature = [toLinger 10, Fragile, Identified] -- 2 steps, 1 turn- , idesc = ""+ , idesc = "A flash of fire." , ikit = [] } @@ -345,7 +345,7 @@ , iaspects = [] , ieffects = [toOrganActorTurn "strengthened" (3 + 1 `d` 3)] , ifeature = [toLinger 10, Fragile, Identified]- , idesc = ""+ , idesc = "A thick rain of droplets." , ikit = [] } sparseShower = ItemKind@@ -361,7 +361,7 @@ , iaspects = [] , ieffects = [toOrganGameTurn "weakened" (3 + 1 `d` 3)] , ifeature = [toLinger 10, Fragile, Identified]- , idesc = ""+ , idesc = "Light droplets that cling to clothing." , ikit = [] } protectingBalmMelee = ItemKind@@ -377,7 +377,7 @@ , iaspects = [] , ieffects = [toOrganActorTurn "protected from melee" (3 + 1 `d` 3)] , ifeature = [toLinger 10, Fragile, Identified]- , idesc = ""+ , idesc = "A thick ointment that hardens the skin." , ikit = [] } protectingBalmRanged = ItemKind@@ -393,7 +393,7 @@ , iaspects = [] , ieffects = [toOrganActorTurn "protected from ranged" (3 + 1 `d` 3)] , ifeature = [toLinger 10, Fragile, Identified]- , idesc = ""+ , idesc = "Grease that protects from flying death." , ikit = [] } vulnerabilityBalm = ItemKind@@ -409,7 +409,7 @@ , iaspects = [] , ieffects = [toOrganGameTurn "defenseless" (3 + 1 `d` 3)] , ifeature = [toLinger 10, Fragile, Identified]- , idesc = ""+ , idesc = "Only the most learned make use of this." , ikit = [] } resolutionDust = ItemKind@@ -426,7 +426,7 @@ , ieffects = [toOrganActorTurn "resolute" (3 + 1 `d` 3)] -- short enough duration that @calmEnough@ not a big problem , ifeature = [toLinger 10, Fragile, Identified]- , idesc = ""+ , idesc = "A handful of honest earth, to strengthen the soul." , ikit = [] } hasteSpray = ItemKind@@ -442,7 +442,7 @@ , iaspects = [] , ieffects = [toOrganActorTurn "hasted" (3 + 1 `d` 3)] , ifeature = [toLinger 10, Fragile, Identified]- , idesc = ""+ , idesc = "A quick spurt." , ikit = [] } slownessMist = ItemKind@@ -458,7 +458,7 @@ , iaspects = [] , ieffects = [toOrganGameTurn "slowed" (3 + 1 `d` 3)] , ifeature = [toVelocity 5, Fragile, Identified] -- 1 step, 1 turn, mist- , idesc = ""+ , idesc = "Clammy fog, making each movement an effort." , ikit = [] } eyeDrop = ItemKind@@ -474,7 +474,7 @@ , iaspects = [] , ieffects = [toOrganActorTurn "far-sighted" (3 + 1 `d` 3)] , ifeature = [toLinger 10, Fragile, Identified]- , idesc = ""+ , idesc = "Not to be taken orally." , ikit = [] } ironFiling = ItemKind@@ -490,7 +490,7 @@ , iaspects = [] , ieffects = [toOrganActorTurn "blind" (10 + 1 `d` 10)] , ifeature = [toLinger 10, Fragile, Identified]- , idesc = ""+ , idesc = "A shaving of bright metal." , ikit = [] } smellyDroplet = ItemKind@@ -506,7 +506,7 @@ , iaspects = [] , ieffects = [toOrganActorTurn "keen-smelling" (3 + 1 `d` 3)] , ifeature = [toLinger 10, Fragile, Identified]- , idesc = ""+ , idesc = "A viscous lump that stains the skin." , ikit = [] } eyeShine = ItemKind@@ -522,7 +522,7 @@ , iaspects = [] , ieffects = [toOrganActorTurn "shiny-eyed" (3 + 1 `d` 3)] , ifeature = [toLinger 10, Fragile, Identified]- , idesc = ""+ , idesc = "They almost glow in the dark." , ikit = [] } @@ -541,7 +541,7 @@ , iaspects = [] , ieffects = [toOrganActorTurn "drunk" (3 + 1 `d` 3)] , ifeature = [toLinger 10, Fragile, Identified]- , idesc = ""+ , idesc = "It burns in the best way." , ikit = [] } waste = ItemKind@@ -557,7 +557,7 @@ , iaspects = [] , ieffects = [Burn 1] , ifeature = [toLinger 10, Fragile, Identified]- , idesc = ""+ , idesc = "Sodden and foul-smelling." , ikit = [] } youthSprinkle = ItemKind@@ -573,7 +573,7 @@ , iaspects = [] , ieffects = [toOrganNone "regenerating"] , ifeature = [toLinger 10, Fragile, Identified]- , idesc = ""+ , idesc = "Bright and smelling of the Spring." , ikit = [] } poisonCloud = ItemKind@@ -589,7 +589,7 @@ , iaspects = [] , ieffects = [toOrganNone "poisoned"] , ifeature = [toVelocity 10, Fragile, Identified] -- 2 steps, 2 turns- , idesc = ""+ , idesc = "Choking gas that stings the eyes." , ikit = [] } mistAntiSlow = ItemKind@@ -605,7 +605,7 @@ , iaspects = [] , ieffects = [DropItem 1 1 COrgan "slowed"] , ifeature = [toVelocity 5, Fragile, Identified] -- 1 step, 1 turn- , idesc = ""+ , idesc = "A cleansing rain." , ikit = [] } mistAntidote = ItemKind@@ -621,6 +621,6 @@ , iaspects = [] , ieffects = [DropItem 1 maxBound COrgan "poisoned"] , ifeature = [toVelocity 5, Fragile, Identified] -- 1 step, 1 turn- , idesc = ""+ , idesc = "Washes away death's dew." , ikit = [] }
GameDefinition/Content/ItemKindEmbed.hs view
@@ -32,7 +32,7 @@ , iaspects = [] , ieffects = [Ascend True] , ifeature = [Identified, Durable]- , idesc = ""+ , idesc = "Stairs that rise towards escape." , ikit = [] } stairsDown = stairsUp@@ -40,12 +40,14 @@ , iname = "staircase down" , ifreq = [("staircase down", 1)] , ieffects = [Ascend False]+ , idesc = "" } escape = stairsUp { iname = "escape" , ifreq = [("escape", 1)] , iflavour = zipPlain [BrYellow] , ieffects = [Escape]+ , idesc = "" } terrainCache = stairsUp { isymbol = 'O'@@ -53,6 +55,7 @@ , ifreq = [("terrain cache", 1)] , iflavour = zipPlain [BrYellow] , ieffects = [CreateItem CGround "useful" TimerNone]+ , idesc = "Glittering gold, just waiting to be taken." } terrainCacheTrap = ItemKind { isymbol = '^'@@ -70,7 +73,7 @@ , ELabel "", ELabel "", ELabel "" , ELabel "", ELabel "" ]] , ifeature = [Identified] -- not Durable, springs at most once- , idesc = ""+ , idesc = "It's a trap!" , ikit = [] } signboardExit = ItemKind@@ -86,7 +89,7 @@ , iaspects = [] , ieffects = [DetectExit 100] , ifeature = [Identified, Durable]- , idesc = ""+ , idesc = "A battered sign, carved by unknown hands." , ikit = [] } signboardMap = signboardExit@@ -107,7 +110,7 @@ , iaspects = [] , ieffects = [Burn 1, Explode "single spark"] , ifeature = [Identified, Durable]- , idesc = ""+ , idesc = "A few small logs, burning brightly." , ikit = [] } fireBig = fireSmall@@ -117,7 +120,7 @@ , ieffects = [ Burn 2, Explode "spark" , CreateItem CInv "wooden torch" TimerNone ] , ifeature = [Identified, Durable]- , idesc = ""+ , idesc = "Glowing with light and warmth." , ikit = [] } frost = ItemKind@@ -135,7 +138,7 @@ , RefillCalm 20 -- cold reason , PushActor (ThrowMod 200 50) ] -- slippery ice , ifeature = [Identified, Durable]- , idesc = ""+ , idesc = "Intricate patterns of shining ice." , ikit = [] } rubble = ItemKind@@ -155,7 +158,7 @@ , ELabel "", ELabel "", ELabel "" , ELabel "", ELabel "", ELabel "" ]] , ifeature = [Identified, Durable]- , idesc = ""+ , idesc = "Broken chunks of rock and glass." , ikit = [] } staircaseTrapUp = ItemKind@@ -171,7 +174,7 @@ , iaspects = [] , ieffects = [Temporary "be caught in an updraft", Teleport 5] , ifeature = [Identified] -- not Durable, springs at most once- , idesc = ""+ , idesc = "A hidden spring, to help the unwary soar." , ikit = [] } -- Needs to be separate from staircaseTrapUp, to make sure the item is@@ -181,6 +184,7 @@ { ifreq = [("staircase trap down", 1)] , ieffects = [ Temporary "tumble down the stairwell" , toOrganActorTurn "drunk" (20 + 1 `d` 5) ]+ , idesc = "A treacherous slab, to teach those who are too proud." } doorwayTrap = ItemKind { isymbol = '^'@@ -197,7 +201,7 @@ , toOrganActorTurn "slowed" (20 + 1 `d` 5) , toOrganActorTurn "weakened" (20 + 1 `d` 5) ]] , ifeature = [Identified] -- not Durable, springs at most once- , idesc = ""+ , idesc = "Just turn the handle..." , ikit = [] } obscenePictograms = ItemKind@@ -217,7 +221,7 @@ [ toOrganActorTurn "strengthened" (3 + 1 `d` 3) , CreateItem CInv "sandstone rock" TimerNone ] ] , ifeature = [Identified, Durable]- , idesc = ""+ , idesc = "They aren't even anatomically possible." , ikit = [] } subtleFresco = ItemKind@@ -236,7 +240,7 @@ , Recharging $ toOrganActorTurn "far-sighted" (3 + 1 `d` 3) , Recharging $ toOrganActorTurn "keen-smelling" (3 + 1 `d` 3) ] , ifeature = [Identified, Durable]- , idesc = ""+ , idesc = "Expensive yet tasteful." , ikit = [] } scratchOnWall = ItemKind@@ -252,7 +256,7 @@ , iaspects = [] , ieffects = [Temporary "start making sense of the scratches", DetectHidden 3] , ifeature = [Identified, Durable]- , idesc = ""+ , idesc = "A seemingly random series of scratches, carved deep into the wall." , ikit = [] } pulpit = ItemKind@@ -270,6 +274,6 @@ , toOrganGameTurn "defenseless" (20 + 1 `d` 5) , Explode "PhD defense question" ] , ifeature = [Identified] -- not Durable, springs at most once- , idesc = ""+ , idesc = "A dark wood stand, where strange priests once preached." , ikit = [] }
GameDefinition/Content/ItemKindOrgan.hs view
@@ -41,7 +41,7 @@ , iaspects = [] , ieffects = [] , ifeature = [Durable, Identified, Meleeable]- , idesc = ""+ , idesc = "Simple but effective." , ikit = [] } foot = fist@@ -49,7 +49,7 @@ , ifreq = [("foot", 50)] , iverbHit = "kick" , idamage = toDmg $ 4 `d` 1- , idesc = ""+ , idesc = "A weapon you can still use if disarmed." } -- * Universal weapon organs@@ -62,14 +62,14 @@ , idamage = toDmg $ 2 `d` 1 , iaspects = [Timeout $ 4 + 1 `d` 4] , ieffects = [Recharging (toOrganGameTurn "slowed" 2)]- , idesc = ""+ , idesc = "A curved talon." } smallClaw = fist { iname = "small claw" , ifreq = [("small claw", 50)] , iverbHit = "slash" , idamage = toDmg $ 2 `d` 1- , idesc = ""+ , idesc = "A pearly spike." } snout = fist { iname = "snout"@@ -77,7 +77,7 @@ , icount = 1 , iverbHit = "bite" , idamage = toDmg $ 2 `d` 1- , idesc = ""+ , idesc = "Sensitive and wide-nostrilled." } smallJaw = fist { iname = "small jaw"@@ -85,7 +85,7 @@ , icount = 1 , iverbHit = "rip" , idamage = toDmg $ 3 `d` 1- , idesc = ""+ , idesc = "Filled with small, even teeth." } jaw = fist { iname = "jaw"@@ -93,7 +93,7 @@ , icount = 1 , iverbHit = "rip" , idamage = toDmg $ 5 `d` 1- , idesc = ""+ , idesc = "Delivers a powerful bite." } largeJaw = fist { iname = "large jaw"@@ -101,7 +101,7 @@ , icount = 1 , iverbHit = "crush" , idamage = toDmg $ 10 `d` 1- , idesc = ""+ , idesc = "Enough to swallow anything in a single gulp." } horn = fist { iname = "horn"@@ -110,7 +110,7 @@ , iverbHit = "impale" , idamage = toDmg $ 6 `d` 1 , iaspects = [AddHurtMelee 20]- , idesc = ""+ , idesc = "Sharp and solid, for defence or attack." } -- * Special weapon organs@@ -121,7 +121,7 @@ , icount = 4 , iverbHit = "slap" , idamage = toDmg $ 4 `d` 1- , idesc = ""+ , idesc = "Damp and dextrous." } thorn = fist { iname = "thorn"@@ -130,7 +130,7 @@ , iverbHit = "impale" , idamage = toDmg $ 1 `d` 3 , ifeature = [Identified, Meleeable] -- not Durable- , idesc = ""+ , idesc = "Sharp yet brittle." } boilingFissure = fist { iname = "fissure"@@ -141,7 +141,7 @@ , iaspects = [AddHurtMelee 20] -- decreasing as count decreases , ieffects = [InsertMove $ 1 `d` 3] , ifeature = [Identified, Meleeable] -- not Durable- , idesc = ""+ , idesc = "A deep crack to the underworld." } arsenicFissure = boilingFissure { iname = "fissure"@@ -149,6 +149,7 @@ , icount = 3 + 1 `d` 3 , idamage = toDmg $ 2 `d` 1 , ieffects = [toOrganGameTurn "weakened" (2 + 1 `d` 2)]+ , idesc = "" } sulfurFissure = boilingFissure { iname = "fissure"@@ -156,6 +157,7 @@ , icount = 2 + 1 `d` 2 , idamage = toDmg 0 , ieffects = [RefillHP 5]+ , idesc = "" } beeSting = fist { iname = "bee sting"@@ -186,7 +188,7 @@ , idamage = toDmg $ 2 `d` 1 , iaspects = [Timeout $ 5 + 1 `d` 3] , ieffects = [Recharging (toOrganGameTurn "slowed" (3 + 1 `d` 3))]- , idesc = ""+ , idesc = "A chilling numbness spreads from its bite." } venomFang = fist { iname = "venom fang"@@ -196,7 +198,7 @@ , idamage = toDmg $ 2 `d` 1 , iaspects = [Timeout $ 7 + 1 `d` 5] , ieffects = [Recharging (toOrganNone "poisoned")]- , idesc = ""+ , idesc = "Dripping with deadly venom." } screechingBeak = fist { iname = "screeching beak"@@ -206,7 +208,7 @@ , idamage = toDmg $ 2 `d` 1 , iaspects = [Timeout $ 5 + 1 `d` 5] , ieffects = [Recharging $ Summon "scavenger" $ 1 + 1 `dl` 2]- , idesc = ""+ , idesc = "Both a weapon and a beacon, calling more scavengers to the meal." } largeTail = fist { iname = "large tail"@@ -216,7 +218,7 @@ , idamage = toDmg $ 6 `d` 1 , iaspects = [Timeout $ 1 + 1 `d` 3, AddHurtMelee 20] , ieffects = [Recharging (PushActor (ThrowMod 400 25))]- , idesc = ""+ , idesc = "Slow but heavy." } -- Non-weapons@@ -236,7 +238,7 @@ , iaspects = [AddArmorMelee 30, AddArmorRanged 15] , ieffects = [] , ifeature = [Durable, Identified]- , idesc = ""+ , idesc = "Homemade armour is just as good." , ikit = [] } @@ -249,7 +251,7 @@ , icount = 2 , iverbHit = "glare at" , iaspects = [AddSight (intToDice n)]- , idesc = ""+ , idesc = "A piercing stare." } eye2 = eye 2 eye3 = eye 3
GameDefinition/Content/ItemKindTemporary.hs view
@@ -42,7 +42,7 @@ , Recharging $ tmpNoLonger name , OnSmash $ tmpNoLonger name ] , ifeature = [Identified, Fragile, Durable] -- hack: destroy on drop- , idesc = ""+ , idesc = "" -- no description needed; stats are enough , ikit = [] }
GameDefinition/Main.hs view
@@ -13,8 +13,11 @@ import qualified GHC.IO.Handle as GHC.IO.Handle import qualified Options.Applicative as OA import System.Exit+import System.FilePath import qualified System.IO as SIO +import Game.LambdaHack.Common.File (tryCreateDir)+import Game.LambdaHack.Common.Misc import Game.LambdaHack.Server (serverOptionsPI) import TieKnot @@ -25,8 +28,10 @@ -- For the case when the game is started not on a console. isTerminal <- SIO.hIsTerminalDevice SIO.stdout unless isTerminal $ do- fstdout <- SIO.openFile "stdout.txt" SIO.WriteMode- fstderr <- SIO.openFile "stderr.txt" SIO.WriteMode+ dataDir <- appDataDir+ tryCreateDir dataDir+ fstdout <- SIO.openFile (dataDir </> "stdout.txt") SIO.WriteMode+ fstderr <- SIO.openFile (dataDir </> "stderr.txt") SIO.WriteMode GHC.IO.Handle.hDuplicateTo fstdout SIO.stdout GHC.IO.Handle.hDuplicateTo fstderr SIO.stderr serverOptions <- OA.execParser serverOptionsPI
GameDefinition/MainMenu.ascii view
@@ -1,9 +1,9 @@ fffffjjjjtti,:Lft: tDEGLLGEKEK; . . . . .iEDEGL.;iiij ... fLLLLfffjjjti;.fL . GDDLfGDEDEf . . . . ;LDWEGi,;iit .. LD#WWELfffjjtt;.if.: .DEGLLGEDLti, . . . . . ,tLKDG ,;itt.-fK#WWW#DLffjjtt;:;j... tDEGfLDEDGtK. .LambdaHack itLEG::;itt.-;K#WWWWW Lfffjjti:.t... tDEGfLDEDL, .. . . tDGj.;itt.- EWWWWKW GLffjjti: t, tDEGLGEEDj; . tLDLi,ittj+fK#WWW#DLffjjtt;:;j... tDEGfLDEDGtK. . LambdaHack itLEG::;itt.+;K#WWWWW Lfffjjti:.t... tDEGfLDEDL, . tDGj.;itt.+ EWWWWKW GLffjjti: t, tDEGLGEEDj; <lambdahack.github.io> tLDLi,ittj EKWWWEWG GLffjjti: tt .tDEGGDEDGi, ;fEG :iitj LEWWWKKK GLfffjti: tt tDDLGDEDGf. {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ ;jGG :iitj DWWWKDWL DLffjjti: jt.DDLGDEDLD {{{{{{{{{{{{{{{{{{{{{{{{{{{{{{ ,jDG .ittj
LICENSE view
@@ -14,7 +14,7 @@ The whole LambdaHack is licensed under the BSD3 licence, as follows. Copyright (c) 2008--2017 Andres Loeh-Copyright (c) 2010--2017 Mikolaj Konarski+Copyright (c) 2010--2017 Mikolaj Konarski and others (see git history) All rights reserved.
LambdaHack.cabal view
@@ -5,7 +5,7 @@ -- PVP summary:+-+------- breaking API changes -- | | +----- minor or non-breaking API additions -- | | | +--- code changes with no API change-version: 0.7.0.0+version: 0.7.1.0 synopsis: A game engine library for roguelike dungeon crawlers description: LambdaHack is a Haskell game engine library for roguelike games of arbitrary theme, size and complexity,
Makefile view
@@ -1,5 +1,5 @@ play:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --dumpInitRngs+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --dumpInitRngs configure-debug: cabal configure --enable-profiling --profiling-detail=all-functions -fwith_expensive_assertions --disable-optimization@@ -17,83 +17,81 @@ ccjs dist/build/LambdaHack/LambdaHack.jsexe/all.js --compilation_level=ADVANCED_OPTIMIZATIONS --isolation_mode=IIFE --assume_function_wrapper --jscomp_off="*" --externs=node > ../lambdahack.github.io/lambdahack.all.js frontendRaid:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --savePrefix test --newGame 5 --dumpInitRngs --automateAll --gameMode raid+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --savePrefix test --newGame 5 --dumpInitRngs --automateAll --gameMode raid frontendBrawl:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --savePrefix test --newGame 5 --dumpInitRngs --automateAll --gameMode brawl+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --savePrefix test --newGame 5 --dumpInitRngs --automateAll --gameMode brawl frontendShootout:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --savePrefix test --newGame 5 --dumpInitRngs --automateAll --gameMode shootout+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --savePrefix test --newGame 5 --dumpInitRngs --automateAll --gameMode shootout frontendEscape:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --savePrefix test --newGame 3 --dumpInitRngs --automateAll --gameMode escape+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --savePrefix test --newGame 3 --dumpInitRngs --automateAll --gameMode escape frontendZoo:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --savePrefix test --newGame 2 --dumpInitRngs --automateAll --gameMode zoo+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --savePrefix test --newGame 2 --dumpInitRngs --automateAll --gameMode zoo frontendAmbush:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --savePrefix test --newGame 5 --dumpInitRngs --automateAll --gameMode ambush+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --savePrefix test --newGame 5 --dumpInitRngs --automateAll --gameMode ambush frontendCrawl:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --savePrefix test --newGame 1 --dumpInitRngs --automateAll --gameMode crawl+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --savePrefix test --newGame 1 --dumpInitRngs --automateAll --gameMode crawl frontendSafari:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --savePrefix test --newGame 2 --dumpInitRngs --automateAll --gameMode safari+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --savePrefix test --newGame 2 --dumpInitRngs --automateAll --gameMode safari frontendSafariSurvival:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --savePrefix test --newGame 5 --dumpInitRngs --automateAll --gameMode "safari survival"+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --savePrefix test --newGame 5 --dumpInitRngs --automateAll --gameMode "safari survival" frontendBattle:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --savePrefix test --newGame 5 --dumpInitRngs --automateAll --gameMode battle+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --savePrefix test --newGame 5 --dumpInitRngs --automateAll --gameMode battle frontendBattleSurvival:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --savePrefix test --newGame 5 --dumpInitRngs --automateAll --gameMode "battle survival"+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --savePrefix test --newGame 5 --dumpInitRngs --automateAll --gameMode "battle survival" frontendDefense:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --savePrefix test --newGame 9 --dumpInitRngs --automateAll --gameMode defense+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --savePrefix test --newGame 9 --dumpInitRngs --automateAll --gameMode defense benchMemoryAnim:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --newGame 1 --maxFps 100000 --benchmark --stopAfterFrames 33000 --automateAll --keepAutomated --gameMode crawl --setDungeonRng 120 --setMainRng 47 --frontendNull --noAnim +RTS -s -A1M -RTS+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --newGame 1 --maxFps 100000 --benchmark --stopAfterFrames 33000 --automateAll --keepAutomated --gameMode crawl --setDungeonRng 120 --setMainRng 47 --frontendNull --noAnim +RTS -s -A1M -RTS benchBattle:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --newGame 3 --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfterFrames 1500 --automateAll --keepAutomated --gameMode battle --setDungeonRng 7 --setMainRng 7+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --newGame 3 --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfterFrames 1500 --automateAll --keepAutomated --gameMode battle --setDungeonRng 7 --setMainRng 7 benchAnimBattle:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --newGame 3 --maxFps 100000 --frontendNull --benchmark --stopAfterFrames 7000 --automateAll --keepAutomated --gameMode battle --setDungeonRng 7 --setMainRng 7+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --newGame 3 --maxFps 100000 --frontendNull --benchmark --stopAfterFrames 7000 --automateAll --keepAutomated --gameMode battle --setDungeonRng 7 --setMainRng 7 benchFrontendBattle:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --newGame 3 --noAnim --maxFps 100000 --benchmark --stopAfterFrames 1500 --automateAll --keepAutomated --gameMode battle --setDungeonRng 7 --setMainRng 7+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --newGame 3 --noAnim --maxFps 100000 --benchmark --stopAfterFrames 1500 --automateAll --keepAutomated --gameMode battle --setDungeonRng 7 --setMainRng 7 benchCrawl:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --newGame 1 --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfterFrames 7000 --automateAll --keepAutomated --gameMode crawl --setDungeonRng 0 --setMainRng 0+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --newGame 1 --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfterFrames 7000 --automateAll --keepAutomated --gameMode crawl --setDungeonRng 0 --setMainRng 0 benchFrontendCrawl:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --newGame 1 --noAnim --maxFps 100000 --benchmark --stopAfterFrames 7000 --automateAll --keepAutomated --gameMode crawl --setDungeonRng 0 --setMainRng 0+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --newGame 1 --noAnim --maxFps 100000 --benchmark --stopAfterFrames 7000 --automateAll --keepAutomated --gameMode crawl --setDungeonRng 0 --setMainRng 0 benchNull: benchBattle benchAnimBattle benchCrawl bench: benchBattle benchAnimBattle benchFrontendBattle benchCrawl benchFrontendCrawl nativeBenchCrawl:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --newGame 2 --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfterFrames 2000 --automateAll --keepAutomated --gameMode crawl --setDungeonRng 0 --setMainRng 0+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --newGame 2 --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfterFrames 2000 --automateAll --keepAutomated --gameMode crawl --setDungeonRng 0 --setMainRng 0 nativeBenchBattle:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --newGame 3 --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfterFrames 1000 --automateAll --keepAutomated --gameMode battle --setDungeonRng 0 --setMainRng 0+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --newGame 3 --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfterFrames 1000 --automateAll --keepAutomated --gameMode battle --setDungeonRng 0 --setMainRng 0 nativeBench: nativeBenchBattle nativeBenchCrawl nodeBenchCrawl:- node dist/build/LambdaHack/LambdaHack.jsexe/all.js --dbgMsgSer --newGame 2 --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfterFrames 2000 --automateAll --keepAutomated --gameMode crawl --setDungeonRng 0 --setMainRng 0+ node dist/build/LambdaHack/LambdaHack.jsexe/all.js --dbgMsgSer --logPriority 4 --newGame 2 --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfterFrames 2000 --automateAll --keepAutomated --gameMode crawl --setDungeonRng 0 --setMainRng 0 nodeBenchBattle:- node dist/build/LambdaHack/LambdaHack.jsexe/all.js --dbgMsgSer --newGame 3 --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfterFrames 1000 --automateAll --keepAutomated --gameMode battle --setDungeonRng 0 --setMainRng 0+ node dist/build/LambdaHack/LambdaHack.jsexe/all.js --dbgMsgSer --logPriority 4 --newGame 3 --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfterFrames 1000 --automateAll --keepAutomated --gameMode battle --setDungeonRng 0 --setMainRng 0 nodeBench: nodeBenchBattle nodeBenchCrawl -test-travis-short: test-short- test-travis: test-short test-medium benchNull test: test-short test-medium benchNull@@ -103,70 +101,73 @@ test-medium: testRaid-medium testBrawl-medium testShootout-medium testEscape-medium testZoo-medium testAmbush-medium testCrawl-medium testSafari-medium testSafariSurvival-medium testBattle-medium testBattleSurvival-medium testRaid-medium:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --newGame 5 --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 20 --dumpInitRngs --automateAll --keepAutomated --gameMode raid 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --newGame 5 --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 20 --dumpInitRngs --automateAll --keepAutomated --gameMode raid 2> /tmp/teletypetest.log testBrawl-medium:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --newGame 5 --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 20 --dumpInitRngs --automateAll --keepAutomated --gameMode brawl 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --newGame 5 --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 20 --dumpInitRngs --automateAll --keepAutomated --gameMode brawl 2> /tmp/teletypetest.log testShootout-medium:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --newGame 5 --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 20 --dumpInitRngs --automateAll --keepAutomated --gameMode shootout 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --newGame 5 --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 20 --dumpInitRngs --automateAll --keepAutomated --gameMode shootout 2> /tmp/teletypetest.log testEscape-medium:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --newGame 3 --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 40 --dumpInitRngs --automateAll --keepAutomated --gameMode escape 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --newGame 3 --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 40 --dumpInitRngs --automateAll --keepAutomated --gameMode escape 2> /tmp/teletypetest.log testZoo-medium:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --newGame 2 --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 100 --dumpInitRngs --automateAll --keepAutomated --gameMode zoo 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --newGame 2 --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 100 --dumpInitRngs --automateAll --keepAutomated --gameMode zoo 2> /tmp/teletypetest.log testAmbush-medium:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --newGame 5 --noAnim --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 20 --dumpInitRngs --automateAll --keepAutomated --gameMode ambush 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --newGame 5 --noAnim --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 20 --dumpInitRngs --automateAll --keepAutomated --gameMode ambush 2> /tmp/teletypetest.log testCrawl-medium:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --newGame 1 --noAnim --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 200 --dumpInitRngs --automateAll --keepAutomated --gameMode crawl 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --newGame 1 --noAnim --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 200 --dumpInitRngs --automateAll --keepAutomated --gameMode crawl 2> /tmp/teletypetest.log testSafari-medium:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --newGame 2 --noAnim --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 100 --dumpInitRngs --automateAll --keepAutomated --gameMode safari 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --newGame 2 --noAnim --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 100 --dumpInitRngs --automateAll --keepAutomated --gameMode safari 2> /tmp/teletypetest.log testSafariSurvival-medium:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --newGame 8 --noAnim --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 60 --dumpInitRngs --automateAll --keepAutomated --gameMode "safari survival" 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --newGame 8 --noAnim --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 60 --dumpInitRngs --automateAll --keepAutomated --gameMode "safari survival" 2> /tmp/teletypetest.log testBattle-medium:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --newGame 3 --noAnim --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 20 --dumpInitRngs --automateAll --keepAutomated --gameMode battle 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --newGame 3 --noAnim --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 20 --dumpInitRngs --automateAll --keepAutomated --gameMode battle 2> /tmp/teletypetest.log testBattleSurvival-medium:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --newGame 7 --noAnim --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 60 --dumpInitRngs --automateAll --keepAutomated --gameMode "battle survival" 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --newGame 7 --noAnim --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 60 --dumpInitRngs --automateAll --keepAutomated --gameMode "battle survival" 2> /tmp/teletypetest.log testDefense-medium:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --newGame 9 --noAnim --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 300 --dumpInitRngs --automateAll --keepAutomated --gameMode defense 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --newGame 9 --noAnim --maxFps 100000 --frontendTeletype --benchmark --stopAfterSeconds 300 --dumpInitRngs --automateAll --keepAutomated --gameMode defense 2> /tmp/teletypetest.log test-short-new:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --newGame 5 --savePrefix raid --dumpInitRngs --automateAll --keepAutomated --gameMode raid --frontendTeletype --stopAfterSeconds 2 2> /tmp/teletypetest.log- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --newGame 5 --savePrefix brawl --dumpInitRngs --automateAll --keepAutomated --gameMode brawl --frontendTeletype --stopAfterSeconds 2 2> /tmp/teletypetest.log- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --newGame 5 --savePrefix shootout --dumpInitRngs --automateAll --keepAutomated --gameMode shootout --frontendTeletype --stopAfterSeconds 2 2> /tmp/teletypetest.log- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --newGame 5 --savePrefix escape --dumpInitRngs --automateAll --keepAutomated --gameMode escape --frontendTeletype --stopAfterSeconds 2 2> /tmp/teletypetest.log- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --newGame 5 --savePrefix zoo --dumpInitRngs --automateAll --keepAutomated --gameMode zoo --frontendTeletype --stopAfterSeconds 2 2> /tmp/teletypetest.log- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --newGame 5 --savePrefix ambush --dumpInitRngs --automateAll --keepAutomated --gameMode ambush --frontendTeletype --stopAfterSeconds 2 2> /tmp/teletypetest.log- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --newGame 5 --savePrefix crawl --dumpInitRngs --automateAll --keepAutomated --gameMode crawl --frontendTeletype --stopAfterSeconds 2 2> /tmp/teletypetest.log- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --newGame 5 --savePrefix safari --dumpInitRngs --automateAll --keepAutomated --gameMode safari --frontendTeletype --stopAfterSeconds 2 2> /tmp/teletypetest.log- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --newGame 5 --savePrefix safariSurvival --dumpInitRngs --automateAll --keepAutomated --gameMode "safari survival" --frontendTeletype --stopAfterSeconds 2 2> /tmp/teletypetest.log- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --newGame 5 --savePrefix battle --dumpInitRngs --automateAll --keepAutomated --gameMode battle --frontendTeletype --stopAfterSeconds 2 2> /tmp/teletypetest.log- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --newGame 5 --savePrefix battleSurvival --dumpInitRngs --automateAll --keepAutomated --gameMode "battle survival" --frontendTeletype --stopAfterSeconds 2 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --newGame 5 --savePrefix raid --dumpInitRngs --automateAll --keepAutomated --gameMode raid --frontendTeletype --stopAfterSeconds 2 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --newGame 5 --savePrefix brawl --dumpInitRngs --automateAll --keepAutomated --gameMode brawl --frontendTeletype --stopAfterSeconds 2 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --newGame 5 --savePrefix shootout --dumpInitRngs --automateAll --keepAutomated --gameMode shootout --frontendTeletype --stopAfterSeconds 2 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --newGame 5 --savePrefix escape --dumpInitRngs --automateAll --keepAutomated --gameMode escape --frontendTeletype --stopAfterSeconds 2 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --newGame 5 --savePrefix zoo --dumpInitRngs --automateAll --keepAutomated --gameMode zoo --frontendTeletype --stopAfterSeconds 2 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --newGame 5 --savePrefix ambush --dumpInitRngs --automateAll --keepAutomated --gameMode ambush --frontendTeletype --stopAfterSeconds 2 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --newGame 5 --savePrefix crawl --dumpInitRngs --automateAll --keepAutomated --gameMode crawl --frontendTeletype --stopAfterSeconds 2 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --newGame 5 --savePrefix safari --dumpInitRngs --automateAll --keepAutomated --gameMode safari --frontendTeletype --stopAfterSeconds 2 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --newGame 5 --savePrefix safariSurvival --dumpInitRngs --automateAll --keepAutomated --gameMode "safari survival" --frontendTeletype --stopAfterSeconds 2 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --newGame 5 --savePrefix battle --dumpInitRngs --automateAll --keepAutomated --gameMode battle --frontendTeletype --stopAfterSeconds 2 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --newGame 5 --savePrefix battleSurvival --dumpInitRngs --automateAll --keepAutomated --gameMode "battle survival" --frontendTeletype --stopAfterSeconds 2 2> /tmp/teletypetest.log # "--setDungeonRng 0 --setMainRng 0" is needed for determinism relative to seed # generated before game save test-short-load:- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --savePrefix raid --dumpInitRngs --automateAll --keepAutomated --gameMode raid --frontendTeletype --stopAfterSeconds 2 --setDungeonRng 0 --setMainRng 0 2> /tmp/teletypetest.log- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --savePrefix brawl --dumpInitRngs --automateAll --keepAutomated --gameMode brawl --frontendTeletype --stopAfterSeconds 2 --setDungeonRng 0 --setMainRng 0 2> /tmp/teletypetest.log- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --savePrefix shootout --dumpInitRngs --automateAll --keepAutomated --gameMode shootouti --frontendTeletype --stopAfterSeconds 2 --setDungeonRng 0 --setMainRng 0 2> /tmp/teletypetest.log- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --savePrefix escape --dumpInitRngs --automateAll --keepAutomated --gameMode escape --frontendTeletype --stopAfterSeconds 2 --setDungeonRng 0 --setMainRng 0 2> /tmp/teletypetest.log- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --savePrefix zoo --dumpInitRngs --automateAll --keepAutomated --gameMode zoo --frontendTeletype --stopAfterSeconds 2 --setDungeonRng 0 --setMainRng 0 2> /tmp/teletypetest.log- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --savePrefix ambush --dumpInitRngs --automateAll --keepAutomated --gameMode ambush --frontendTeletype --stopAfterSeconds 2 --setDungeonRng 0 --setMainRng 0 2> /tmp/teletypetest.log- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --savePrefix crawl --dumpInitRngs --automateAll --keepAutomated --gameMode crawl --frontendTeletype --stopAfterSeconds 2 --setDungeonRng 0 --setMainRng 0 2> /tmp/teletypetest.log- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --savePrefix safari --dumpInitRngs --automateAll --keepAutomated --gameMode safari --frontendTeletype --stopAfterSeconds 2 --setDungeonRng 0 --setMainRng 0 2> /tmp/teletypetest.log- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --savePrefix safariSurvival --dumpInitRngs --automateAll --keepAutomated --gameMode "safari survival" --frontendTeletype --stopAfterSeconds 2 --setDungeonRng 0 --setMainRng 0 2> /tmp/teletypetest.log- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --savePrefix battle --dumpInitRngs --automateAll --keepAutomated --gameMode battle --frontendTeletype --stopAfterSeconds 2 --setDungeonRng 0 --setMainRng 0 2> /tmp/teletypetest.log- dist/build/LambdaHack/LambdaHack --dbgMsgSer --boostRandomItem --savePrefix battleSurvival --dumpInitRngs --automateAll --keepAutomated --gameMode "battle survival" --frontendTeletype --stopAfterSeconds 2 --setDungeonRng 0 --setMainRng 0 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --savePrefix raid --dumpInitRngs --automateAll --keepAutomated --gameMode raid --frontendTeletype --stopAfterSeconds 2 --setDungeonRng 0 --setMainRng 0 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --savePrefix brawl --dumpInitRngs --automateAll --keepAutomated --gameMode brawl --frontendTeletype --stopAfterSeconds 2 --setDungeonRng 0 --setMainRng 0 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --savePrefix shootout --dumpInitRngs --automateAll --keepAutomated --gameMode shootouti --frontendTeletype --stopAfterSeconds 2 --setDungeonRng 0 --setMainRng 0 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --savePrefix escape --dumpInitRngs --automateAll --keepAutomated --gameMode escape --frontendTeletype --stopAfterSeconds 2 --setDungeonRng 0 --setMainRng 0 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --savePrefix zoo --dumpInitRngs --automateAll --keepAutomated --gameMode zoo --frontendTeletype --stopAfterSeconds 2 --setDungeonRng 0 --setMainRng 0 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --savePrefix ambush --dumpInitRngs --automateAll --keepAutomated --gameMode ambush --frontendTeletype --stopAfterSeconds 2 --setDungeonRng 0 --setMainRng 0 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --savePrefix crawl --dumpInitRngs --automateAll --keepAutomated --gameMode crawl --frontendTeletype --stopAfterSeconds 2 --setDungeonRng 0 --setMainRng 0 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --savePrefix safari --dumpInitRngs --automateAll --keepAutomated --gameMode safari --frontendTeletype --stopAfterSeconds 2 --setDungeonRng 0 --setMainRng 0 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --savePrefix safariSurvival --dumpInitRngs --automateAll --keepAutomated --gameMode "safari survival" --frontendTeletype --stopAfterSeconds 2 --setDungeonRng 0 --setMainRng 0 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --savePrefix battle --dumpInitRngs --automateAll --keepAutomated --gameMode battle --frontendTeletype --stopAfterSeconds 2 --setDungeonRng 0 --setMainRng 0 2> /tmp/teletypetest.log+ dist/build/LambdaHack/LambdaHack --dbgMsgSer --logPriority 4 --boostRandomItem --savePrefix battleSurvival --dumpInitRngs --automateAll --keepAutomated --gameMode "battle survival" --frontendTeletype --stopAfterSeconds 2 --setDungeonRng 0 --setMainRng 0 2> /tmp/teletypetest.log +version:+ dist/build/LambdaHack/LambdaHack --version+ build-binary-common: cabal install --disable-library-profiling --disable-profiling --disable-documentation -f-release --only-dependencies cabal configure --disable-library-profiling --disable-profiling -f-release --prefix=/ --datadir=. --datasubdir=.@@ -189,7 +190,9 @@ build-binary: build-binary-common cp LambdaHackTheGameInstall/bin/LambdaHack LambdaHackTheGame- tar -czf LambdaHack_x_ubuntu-16.04-amd64.tar.gz LambdaHackTheGame+ dist/build/LambdaHack/LambdaHack --version > /dev/null; \+ LH_VERSION=$$(cat ~/.LambdaHack/stdout.txt); \+ tar -czf LambdaHack_$${LH_VERSION}_ubuntu-16.04-amd64.tar.gz LambdaHackTheGame new-build-dev: cabal new-build --datadir=. --disable-optimization -j1
README.md view
@@ -75,14 +75,16 @@ you may prefer to use a native binary for your architecture, if it exists. Pre-compiled game binaries for some platforms are available through-the release page[11] and from AppVeyor (Windows 32bit[17] and Windows 64bit[18];-note that these no longer work on Windows XP, since Cygwin and MSYS2-dropped support for XP). To use a pre-compiled binary archive,+the release page[11] (and continuously from AppVeyor[18]).+Note that Windows binaries no longer work on Windows XP, since Cygwin+and MSYS2 dropped support for XP). To use a pre-compiled binary archive, unpack it and run the executable in the unpacked directory.+Or use program shortcuts from the installer, if available. -On Linux, make sure you have the SDL2 libraries suite installed on your system-(e.g., libsdl2, libsdl2-ttf). For Windows, the SDL2 and all other needed-libraries are already contained in the game's binary archive.+On Linux, make sure you have the SDL2 libraries installed on your system+(e.g., libsdl2-2.0-0, libsdl2-ttf-2.0-0 on Ubuntu; also libdw1).+For Windows, the SDL2 and all other needed libraries are already contained+in the game's binary archive. Screen and keyboard configuration@@ -246,5 +248,4 @@ [11]: https://github.com/LambdaHack/LambdaHack/releases/latest [15]: https://github.com/ghcjs/ghcjs [16]: https://www.npmjs.com/package/google-closure-compiler-[17]: https://ci.appveyor.com/project/Mikolaj/lambdahack-4hh0j/build/artifacts [18]: https://ci.appveyor.com/project/Mikolaj/lambdahack/build/artifacts