packages feed

Allure 0.4.99.0 → 0.4.100.0

raw patch · 18 files changed

+1478/−810 lines, 18 filesdep ~LambdaHack

Dependency ranges changed: LambdaHack

Files

Allure.cabal view
@@ -4,8 +4,8 @@ -- http://www.haskell.org/haskellwiki/Package_versioning_policy -- PVP summary: +-+------- breaking API changes --              | | +----- non-breaking API additions---              | | |  +--- code changes with no API change-version:        0.4.99.0+--              | | |   +--- code changes with no API change+version:        0.4.100.0 synopsis:       Near-future Sci-Fi roguelike and tactical squad game description:   Allure of the Stars                is a near-future Sci-Fi roguelike and tactical squad game.@@ -23,7 +23,7 @@                available at <http://hackage.haskell.org/package/LambdaHack>. homepage:      http://allureofthestars.com bug-reports:   http://github.com/AllureOfTheStars/Allure/issues-license:       OtherLicense+license:       AGPL license-file:  LICENSE tested-with:   GHC == 7.6.3, GHC == 7.8 data-files:    GameDefinition/config.ui.default, GameDefinition/scores,@@ -41,6 +41,11 @@   type:               git   location:           git://github.com/AllureOfTheStars/Allure.git +flag release+  description:        prepare for a release (expose, optimize, etc.)+  default:            True+  manual:             True+ executable Allure   hs-source-dirs:     GameDefinition   main-is:            Main.hs@@ -49,7 +54,8 @@                       Content.ItemKind,                       Content.ItemKindActor,                       Content.ItemKindOrgan,-                      Content.ItemKindShrapnel,+                      Content.ItemKindBlast,+                      Content.ItemKindTemporary,                       Content.ModeKind,                       Content.ModeKindPlayer,                       Content.PlaceKind,@@ -57,7 +63,7 @@                       Content.TileKind,                       TieKnot,                       Paths_Allure-  build-depends:      LambdaHack >= 0.4.99.0 && < 0.5.1.0,+  build-depends:      LambdaHack >= 0.4.100.0 && < 0.5.1.0,                       template-haskell >= 2.6 && < 3,                        base       >= 4       && < 5,@@ -73,9 +79,12 @@   ghc-options:        -Wall -fwarn-orphans -fwarn-tabs -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates -fwarn-monomorphism-restriction -fwarn-unrecognised-pragmas   ghc-options:        -fno-warn-auto-orphans -fno-warn-implicit-prelude   ghc-options:        -fno-ignore-asserts -funbox-strict-fields-  ghc-options:        -threaded -with-rtsopts=-C0.005 -rtsopts--- ghc-options:       -with-rtsopts=-N  -- eats all cores+  ghc-options:        -threaded "-with-rtsopts=-C0.005" -rtsopts +  if flag(release)+    ghc-options:      -O2 "-with-rtsopts=-N1"+-- TODO: -N+ test-suite test   type:               exitcode-stdio-1.0   hs-source-dirs:     GameDefinition, test@@ -96,4 +105,8 @@   ghc-options:        -Wall -fwarn-orphans -fwarn-tabs -fwarn-incomplete-uni-patterns -fwarn-incomplete-record-updates -fwarn-monomorphism-restriction -fwarn-unrecognised-pragmas   ghc-options:        -fno-warn-auto-orphans -fno-warn-implicit-prelude   ghc-options:        -fno-ignore-asserts -funbox-strict-fields-  ghc-options:        -threaded -with-rtsopts=-C0.005 -rtsopts+  ghc-options:        -threaded "-with-rtsopts=-C0.005" -rtsopts++  if flag(release)+    ghc-options:      -O2 "-with-rtsopts=-N1"+-- TODO: -N
CHANGELOG.md view
@@ -1,4 +1,17 @@-## [v0.4.99.0, aka 'Player escapes through airlock'](https://github.com/LambdaHack/LambdaHack/compare/v0.4.14...v0.4.99.0)+## [v0.4.100.0, aka 'The last interstellar thaw'](https://github.com/AllureOfTheStars/Allure/compare/v0.4.99.0..v0.4.100.0)++- update vs the unexpectedly thawed v0.5.0.0 of LambdaHack content API+- unexpectedly add items with timeouts and temporary effects+- start campaign on level 3 and don't spawn aliens until level 4+- rebalance campaign (probably still too hard)+- tweak skills of some factions and actors+- rename tablets to chips to make their vanishing easier to understand+- make colorful characters bold (if it resizes your fonts, turn off via colorIsBold = False in config file or --noColorIsBold on commandline)+- start the game with a screensaver safari mode+- improve keyboard handling on Windows+- add i386 Linux and Windows compilation targets to Makefile++## [v0.4.99.0, aka 'Player escapes through airlock'](https://github.com/AllureOfTheStars/Allure/compare/v0.4.14...v0.4.99.0)  - balance game content a bit (campaign still unbalanced) - fix a bug where doors can't be closed
GameDefinition/Client/UI/Content/KeyKind.hs view
@@ -12,9 +12,9 @@ import qualified Game.LambdaHack.Client.Key as K import Game.LambdaHack.Client.UI.Content.KeyKind import Game.LambdaHack.Client.UI.HumanCmd-import qualified Game.LambdaHack.Common.Effect as Effect-import qualified Game.LambdaHack.Common.Feature as F import Game.LambdaHack.Common.Misc+import qualified Game.LambdaHack.Content.ItemKind as IK+import qualified Game.LambdaHack.Content.TileKind as TK  standardKeys :: KeyKind standardKeys = KeyKind@@ -39,25 +39,25 @@       , ("less", ([CmdMove, CmdMinimal], TriggerTile            [ TriggerFeature { verb = "ascend"                             , object = "a level"-                            , feature = F.Cause (Effect.Ascend 1) }+                            , feature = TK.Cause (IK.Ascend 1) }            , TriggerFeature { verb = "escape"                             , object = "spaceship"-                            , feature = F.Cause (Effect.Escape 1) } ]))+                            , feature = TK.Cause (IK.Escape 1) } ]))       , ("CTRL-less", ([CmdMove], TriggerTile            [ TriggerFeature { verb = "ascend"                             , object = "10 levels"-                            , feature = F.Cause (Effect.Ascend 10) } ]))+                            , feature = TK.Cause (IK.Ascend 10) } ]))       , ("greater", ([CmdMove, CmdMinimal], TriggerTile            [ TriggerFeature { verb = "descend"                             , object = "a level"-                            , feature = F.Cause (Effect.Ascend (-1)) }+                            , feature = TK.Cause (IK.Ascend (-1)) }            , TriggerFeature { verb = "escape"                             , object = "spaceship"-                            , feature = F.Cause (Effect.Escape (-1)) } ]))+                            , feature = TK.Cause (IK.Escape (-1)) } ]))       , ("CTRL-greater", ([CmdMove], TriggerTile            [ TriggerFeature { verb = "descend"                             , object = "10 levels"-                            , feature = F.Cause (Effect.Ascend (-10)) } ]))+                            , feature = TK.Cause (IK.Ascend (-10)) } ]))       , ("semicolon", ([CmdMove], StepToTarget))       , ("colon", ([CmdMove], Macro "go to target for 100 steps"                                     ["semicolon", "V"]))@@ -81,9 +81,12 @@       , ("c", ([CmdMove], AlterDir            [ AlterFeature { verb = "close"                           , object = "door"-                          , feature = F.CloseTo "closed door" }+                          , feature = TK.CloseTo "closed door" }            ]))+      , ("CTRL-KP_Begin", ([CmdMove], Macro "" ["KP_Begin"]))       , ("period", ([CmdMove], Macro "" ["KP_Begin"]))+      , ("KP_5", ([CmdMove], Macro "" ["KP_Begin"]))+      , ("CTRL-KP_5", ([CmdMove], Macro "" ["KP_Begin"]))       , ("i", ([CmdMove], Macro "" ["KP_Begin"]))        -- Item use@@ -99,16 +102,16 @@       , ("G", ([CmdItem], DescribeItem CGround))       , ("A", ([CmdItem], AllOwned))       , ("g", ([CmdItem, CmdMinimal],-               MoveItem [CGround] CEqp "get" "an item" True))+               MoveItem [CGround] CEqp (Just "get") "an item" True))       , ("d", ([CmdItem], MoveItem [CEqp, CInv, CSha] CGround-                                   "drop" "an item" False))+                                   Nothing "an item" False))       , ("e", ([CmdItem], MoveItem [CInv, CSha] CEqp-                                   "equip" "an item" False))+                                   Nothing "an item" False))       , ("p", ([CmdItem], MoveItem [CEqp, CSha] CInv-                                   "pack" "an item into inventory backpack"+                                   Nothing "an item into inventory backpack"                                    False))       , ("s", ([CmdItem], MoveItem [CInv, CEqp] CSha-                                   "stash" "and share an item" False))+                                   Nothing "and share an item" False))       , ("a", ([CmdItem, CmdMinimal], Apply            [ ApplyItem { verb = "activate"                        , object = "applicable item"@@ -117,14 +120,14 @@                        , object = "drink"                        , symbol = '!' }            , ApplyItem { verb = "read"-                       , object = "tablet"+                       , object = "chip"                        , symbol = '?' }            ]))       , ("q", ([CmdItem], Apply [ApplyItem { verb = "quaff"                                            , object = "drink"                                            , symbol = '!' }]))       , ("r", ([CmdItem], Apply [ApplyItem { verb = "read"-                                           , object = "tablet"+                                           , object = "chip"                                            , symbol = '?' }]))       , ("f", ([CmdItem, CmdMinimal], Project            [ApplyItem { verb = "fling"@@ -179,5 +182,6 @@       , ("CTRL-s", ([CmdDebug], GameSave))       , ("CTRL-f", ([CmdDebug], GameRestart "safari"))       , ("CTRL-e", ([CmdDebug], GameRestart "defense"))+      , ("CTRL-O", ([CmdDebug], DescribeItem COrgan))       ]   }
GameDefinition/Content/CaveKind.hs view
@@ -21,9 +21,9 @@   , validateSingle = validateSingleCaveKind   , validateAll = validateAllCaveKind   , content =-      [rogue, arena, empty, noise, battle, skirmish, ambush, safari1, safari2, safari3]+      [rogue, arena, empty, noise, battle, skirmish, ambush, safari1, safari2, safari3, bridge, shallow2rogue, shallow2arena, shallow2empty, shallow1arena, shallow1empty]   }-rogue,        arena, empty, noise, battle, skirmish, ambush, safari1, safari2, safari3 :: CaveKind+rogue,        arena, empty, noise, battle, skirmish, ambush, safari1, safari2, safari3, bridge, shallow2rogue, shallow2arena, shallow2empty, shallow1arena, shallow1empty :: CaveKind  rogue = CaveKind   { csymbol       = 'R'@@ -73,7 +73,6 @@   , cdefTile      = "arenaSet"   , cdarkCorTile  = "trailLit"  -- let trails give off light   , clitCorTile   = "trailLit"--- TODO: re-add when less rooms , couterFenceTile = "oriels fence"   } empty = rogue   { csymbol       = 'E'@@ -95,12 +94,11 @@   , cdefTile      = "emptySet"   , cdarkCorTile  = "floorArenaDark"   , clitCorTile   = "floorArenaLit"-  , couterFenceTile = "oriels fence"   } noise = rogue   { csymbol       = 'N'   , cname         = "Machine rooms"-  , cfreq         = [("campaign random", 50), ("caveNoise", 1)]+  , cfreq         = [("caveNoise", 1)]   , cgrid         = DiceXY (2 + d 2) 3   , cminPlaceSize = DiceXY 12 5   , cmaxPlaceSize = DiceXY 24 15@@ -185,3 +183,43 @@ safari1 = ambush {cfreq = [("caveSafari1", 1)]} safari2 = battle {cfreq = [("caveSafari2", 1)]} safari3 = skirmish {cfreq = [("caveSafari3", 1)]}+bridge = rogue+  { csymbol       = 'B'+  , cname         = "Captain's bridge"+  , cfreq         = [("caveBridge", 1)]+  , cgrid         = DiceXY (d 2 + 1) 2+  , cminPlaceSize = DiceXY 10 7+  , cmaxPlaceSize = DiceXY 40 14+  , cdarkChance   = 0+  , cmaxVoid      = 1%10+  , cactorFreq    = []  -- safe, nothing spawns+  , citemFreq     = filter ((/= "treasure") . fst) $ citemFreq arena+  , cdarkCorTile  = "emergency walkway"+  , clitCorTile   = "emergency walkway"+  }+shallow2rogue = rogue+  { cfreq         = [("shallow random 2", 100)]+  , cactorFreq    = filter ((/= "alien") . fst) $ cactorFreq rogue+  , citemFreq     = filter ((/= "treasure") . fst) $ citemFreq rogue+  }+shallow2arena = arena+  { cfreq         = [("shallow random 2", 100)]+  , cactorFreq    = filter ((/= "alien") . fst) $ cactorFreq empty+  , citemFreq     = filter ((/= "treasure") . fst) $ citemFreq empty+  }+shallow2empty = empty+  { cfreq         = [("shallow random 2", 100)]+  , cactorFreq    = filter ((/= "alien") . fst) $ cactorFreq empty+  , citemFreq     = filter ((/= "treasure") . fst) $ citemFreq empty+  }+shallow1arena = shallow2arena  -- TODO: replace some rooms with oriels?+  { cname         = "Outermost deck"+  , cfreq         = [("shallow random 1", 100)]+  , cminPlaceSize = DiceXY (2 * d 2 + 3) 3+  , couterFenceTile = "oriels fence"+  }+shallow1empty = shallow2empty  -- TODO: add oriel areas or glass on floor+  { cname         = "Outermost deck"+  , cfreq         = [("shallow random 1", 100)]+  , couterFenceTile = "oriels fence"+  }
GameDefinition/Content/ItemKind.hs view
@@ -9,12 +9,12 @@ import Data.List  import Content.ItemKindActor+import Content.ItemKindBlast import Content.ItemKindOrgan-import Content.ItemKindShrapnel+import Content.ItemKindTemporary import Game.LambdaHack.Common.Color import Game.LambdaHack.Common.ContentDef import Game.LambdaHack.Common.Dice-import Game.LambdaHack.Common.Effect import Game.LambdaHack.Common.Flavour import Game.LambdaHack.Common.Misc import Game.LambdaHack.Content.ItemKind@@ -26,44 +26,47 @@   , getFreq = ifreq   , validateSingle = validateSingleItemKind   , validateAll = validateAllItemKind-  , content = items ++ organs ++ shrapnels ++ actors+  , content = items ++ organs ++ blasts ++ actors ++ temporaries   }  items :: [ItemKind] items =-  [canOfGlue, crankSpotlight, buckler, dart, dart200, gem1, gem2, gem3, gloveFencing, gloveGauntlet, gloveJousting, currency, gorget, harpoon, jumpingPole, contactLens, necklace1, necklace2, necklace3, necklace4, necklace5, necklace6, necklace7, net, needle, oilLamp, potion1, potion2, potion3, potion4, potion5, potion6, potion7, potion8, potion9, potion10, potion11, ring1, ring2, ring3, ring4, ring5, scroll1, scroll2, scroll3, scroll4, scroll5, scroll6, scroll7, scroll8, scroll9, shield, dagger, hammer, sword, halberd, wand1, wand2, candle, armorLeather, armorMail, honingSteel, constructionHooter]+  [dart, dart200, canOfGlue, harpoon, net, needle, jumpingPole, honingSteel, candle, oilLamp, crankSpotlight, gorget, necklace1, necklace2, necklace3, necklace4, necklace5, necklace6, necklace7, contactLens, ring1, ring2, ring3, ring4, ring5, potion1, potion2, potion3, potion4, potion5, potion6, potion7, potion8, flask1, flask2, flask3, flask4, flask5, flask6, flask7, flask8, flask9, flask10, flask11, flask12, flask13, flask14, constructionHooter, scroll1, scroll2, scroll3, scroll4, scroll5, scroll6, scroll7, scroll8, scroll9, scroll10, armorLeather, armorMail, gloveFencing, gloveGauntlet, gloveJousting, buckler, shield, dagger, daggerDropBestWeapon, hammer, hammerParalyze, hammerSpark, sword, swordImpress, swordNullify, halberd, halberdPushActor, wand1, wand2, gem1, gem2, gem3, currency] -canOfGlue,    crankSpotlight, buckler, dart, dart200, gem1, gem2, gem3, gloveFencing, gloveGauntlet, gloveJousting, currency, gorget, harpoon, jumpingPole, contactLens, necklace1, necklace2, necklace3, necklace4, necklace5, necklace6, necklace7, net, needle, oilLamp, potion1, potion2, potion3, potion4, potion5, potion6, potion7, ring1, potion8, potion9, potion10, potion11, ring2, ring3, ring4, ring5, scroll1, scroll2, scroll3, scroll4, scroll5, scroll6, scroll7, scroll8, scroll9, shield, dagger, hammer, sword, halberd, wand1, wand2, candle, armorLeather, armorMail, honingSteel, constructionHooter :: ItemKind+dart,    dart200, canOfGlue, harpoon, net, needle, jumpingPole, honingSteel, candle, oilLamp, crankSpotlight, gorget, necklace1, necklace2, necklace3, necklace4, necklace5, necklace6, necklace7, contactLens, ring1, ring2, ring3, ring4, ring5, potion1, potion2, potion3, potion4, potion5, potion6, potion7, potion8, flask1, flask2, flask3, flask4, flask5, flask6, flask7, flask8, flask9, flask10, flask11, flask12, flask13, flask14, constructionHooter, scroll1, scroll2, scroll3, scroll4, scroll5, scroll6, scroll7, scroll8, scroll9, scroll10, armorLeather, armorMail, gloveFencing, gloveGauntlet, gloveJousting, buckler, shield, dagger, daggerDropBestWeapon, hammer, hammerParalyze, hammerSpark, sword, swordImpress, swordNullify, halberd, halberdPushActor, wand1, wand2, gem1, gem2, gem3, currency :: ItemKind -gem, necklace, potion, ring, scroll, wand :: ItemKind  -- generic templates+necklace, ring, potion, flask, scroll, wand, gem :: ItemKind  -- generic templates -{- Item group symbols (from Angband, only as an informal convention for now):+-- * Item group symbols, from Angband and variants -! potion, flask, concoction, bottle, jar, vial, canister-? scroll, book, note, tablet, remote-, food-- magical wand, magical rod, transmitter, pistol, rifle-_ magical staff, scanner-= ring-" necklace-$ currency, gem-~ light, tool-/ polearm-| edged weapon-\ hafted weapon-} launcher-{ projectile-( clothes-[ torso armour-] misc. armour-) shield+symbolProjectile, _symbolLauncher, symbolLight, symbolTool, symbolGem, symbolGold, symbolNecklace, symbolRing, symbolPotion, symbolFlask, symbolScroll, symbolTorsoArmor, symbolMiscArmor, _symbolClothes, symbolShield, symbolPolearm, symbolEdged, symbolHafted, symbolWand, _symbolStaff, _symbolFood :: Char --}+symbolProjectile = '{'+_symbolLauncher  = '}'+symbolLight      = '~'+symbolTool       = '~'+symbolGem        = '*'+symbolGold       = '$'+symbolNecklace   = '"'+symbolRing       = '='+symbolPotion     = '!'  -- concoction, bottle, jar, vial, canister+symbolFlask      = '!'+symbolScroll     = '?'  -- book, note, tablet, remote, chip, card+symbolTorsoArmor = '['+symbolMiscArmor  = ']'+_symbolClothes   = '('+symbolShield     = ')'+symbolPolearm    = '/'+symbolEdged      = '|'+symbolHafted     = '\\'+symbolWand       = '-'  -- magical rod, transmitter, pistol, rifle+_symbolStaff     = '_'  -- scanner+_symbolFood      = ','  -- * Thrown weapons  dart = ItemKind-  { isymbol  = '{'+  { isymbol  = symbolProjectile   , iname    = "steak knife"   , ifreq    = [("useful", 100), ("any arrow", 100)]   , iflavour = zipPlain [BrCyan]@@ -73,12 +76,12 @@   , iweight  = 100   , iaspects = [AddHurtRanged ((d 6 + dl 6) |*| 10)]   , ieffects = [Hurt (3 * d 1)]-  , ifeature = [toVelocity 75]  -- no fins no special balance+  , ifeature = [toVelocity 75, Identified]  -- no fins, no special balance   , idesc    = "Not particularly well balanced, but with a laser-sharpened titanium tip and blade."   , ikit     = []   } dart200 = ItemKind-  { isymbol  = '{'+  { isymbol  = symbolProjectile   , iname    = "billiard ball"   , ifreq    = [("useful", 100), ("any arrow", 50)]  -- TODO: until arrows added   , iflavour = zipPlain [BrWhite]@@ -88,7 +91,7 @@   , iweight  = 300   , iaspects = [AddHurtRanged ((d 6 + dl 6) |*| 10)]   , ieffects = [Hurt (2 * d 1)]-  , ifeature = [toVelocity 150]+  , ifeature = [toVelocity 150, Identified]   , idesc    = "Ideal shape, size and weight for throwing."   , ikit     = []   }@@ -96,22 +99,23 @@ -- * Exotic thrown weapons  canOfGlue = ItemKind-  { isymbol  = '{'-  , iname    = "can of glue"-  , ifreq    = [("useful", 100)]+  { isymbol  = symbolProjectile+  , iname    = "can"+  , ifreq    = [("useful", 100), ("can of sticky foam", 1)]   , iflavour = zipPlain [Magenta]   , icount   = dl 4   , irarity  = [(5, 5), (10, 20)]   , iverbHit = "glue"   , iweight  = 1500   , iaspects = []-  , ieffects = [Paralyze (5 + d 10)]-  , ifeature = [toVelocity 50]  -- unwieldy-  , idesc    = "A can of liquid, fast-setting, construction glue."+  , ieffects = [ NoEffect "of sticky foam", Paralyze (5 + d 7)+               , OnSmash (Explode "glue")]+  , ifeature = [toVelocity 50, Identified]  -- unwieldy+  , idesc    = "A can of liquid, fast-setting, construction foam."   , ikit     = []   } harpoon = ItemKind-  { isymbol  = '{'+  { isymbol  = symbolProjectile   , iname    = "harpoon"   , ifreq    = [("useful", 100)]   , iflavour = zipPlain [Brown]@@ -126,7 +130,7 @@   , ikit     = []   } net = ItemKind-  { isymbol  = '{'+  { isymbol  = symbolProjectile   , iname    = "net"   , ifreq    = [("useful", 100)]   , iflavour = zipPlain [White]@@ -135,14 +139,14 @@   , iverbHit = "entangle"   , iweight  = 1000   , iaspects = []-  , ieffects = [ Paralyze (5 + d 5)-               , DropBestWeapon, DropEqp ')' False ]-  , ifeature = []-  , idesc    = "A large synthetic fibre net with weights affixed along the edges. Entangles weapon and appendages alike."+  , ieffects = [ toOrganGameTurn "slow 10" (3 + d 3)+               , DropItem CEqp "torso armor" False ]+  , ifeature = [Identified]+  , idesc    = "A large synthetic fibre net with weights affixed along the edges. Entangles armor and restricts movement."   , ikit     = []   } needle = ItemKind-  { isymbol  = '{'+  { isymbol  = symbolProjectile   , iname    = "needle"   , ifreq    = []   , iflavour = zipPlain [BrBlue]@@ -157,10 +161,43 @@   , ikit     = []   } +-- * Assorted tools++jumpingPole = ItemKind+  { isymbol  = symbolTool+  , iname    = "jumping pole"+  , ifreq    = [("useful", 100)]+  , iflavour = zipPlain [White]+  , icount   = 1+  , irarity  = [(1, 2), (10, 1)]+  , iverbHit = "prod"+  , iweight  = 10000+  , iaspects = [Timeout $ (d 2 + 2 - dl 2) |*| 10]+  , ieffects = [Recharging (toOrganActorTurn "fast 20" 1)]+  , ifeature = [Durable, Applicable, Identified]+  , idesc    = "Makes you vulnerable at take-off, but then you are free like a bird."+  , ikit     = []+  }+honingSteel = ItemKind+  { isymbol  = symbolTool+  , iname    = "honing steel"+  , ifreq    = [("useful", 100)]+  , iflavour = zipPlain [Blue]+  , icount   = 1+  , irarity  = [(10, 10)]+  , iverbHit = "smack"+  , iweight  = 400+  , iaspects = [AddHurtMelee $ d 10 |*| 3]+  , ieffects = []+  , ifeature = [EqpSlot EqpSlotAddHurtMelee "", Identified]+  , idesc    = "Originally used for realigning the bent or buckled edges of kitchen knives in the local bars. Now it saves lives by letting you fix your weapons between or even during fights, without the need to set up camp, fish out tools and assemble a proper sharpening workshop."+  , ikit     = []+  }+ -- * Lights  candle = ItemKind-  { isymbol  = '~'+  { isymbol  = symbolLight   , iname    = "candle"   , ifreq    = [("useful", 100), ("light source", 100)]   , iflavour = zipPlain [Brown]@@ -177,7 +214,7 @@   , ikit     = []   } oilLamp = ItemKind-  { isymbol  = '~'+  { isymbol  = symbolLight   , iname    = "oil lamp"   , ifreq    = [("useful", 100), ("light source", 100)]   , iflavour = zipPlain [BrYellow]@@ -193,7 +230,7 @@   , ikit     = []   } crankSpotlight = ItemKind-  { isymbol  = '~'+  { isymbol  = symbolLight   , iname    = "crank spotlight"   , ifreq    = [("useful", 100), ("light source", 100)]   , iflavour = zipPlain [BrWhite]@@ -208,77 +245,37 @@   , ikit     = []   } --- * Treasure--gem = ItemKind-  { isymbol  = '*'-  , iname    = "gem"-  , ifreq    = [("treasure", 100)]  -- x3, but rare on shallow levels-  , iflavour = zipPlain $ delete BrYellow brightCol  -- natural, so not fancy-  , icount   = 1-  , irarity  = []-  , iverbHit = "tap"-  , iweight  = 50-  , iaspects = [AddLight 1, AddSpeed (-1)]  -- reflects strongly, distracts-  , ieffects = []-  , ifeature = [ Durable  -- prevent destruction by evil monsters-               , Precious ]-  , idesc    = "Precious, though useless. Worth around 100 gold grains."-  , ikit     = []-  }-gem1 = gem-  { irarity  = [(2, 0), (10, 10)]-  }-gem2 = gem-  { irarity  = [(5, 0), (10, 10)]-  }-gem3 = gem-  { irarity  = [(8, 0), (10, 10)]-  }-currency = ItemKind-  { isymbol  = '$'-  , iname    = "gold grain"-  , ifreq    = [("treasure", 100), ("currency", 1)]-  , iflavour = zipPlain [BrYellow]-  , icount   = 10 + d 20 + dl 20-  , irarity  = [(1, 0), (2, 15), (5, 25), (10, 10)]-  , iverbHit = "tap"-  , iweight  = 1-  , iaspects = []-  , ieffects = []-  , ifeature = [Durable, Identified, Precious]-  , idesc    = "Reliably valuable in every civilized place."-  , ikit     = []-  }- -- * Periodic jewelry  gorget = ItemKind-  { isymbol  = '"'+  { isymbol  = symbolNecklace   , iname    = "gorget"   , ifreq    = [("useful", 100)]   , iflavour = zipFancy [BrCyan]-  , irarity  = [(4, 1), (10, 2)]   , icount   = 1+  , irarity  = [(4, 1), (10, 2)]   , iverbHit = "whip"   , iweight  = 30-  , iaspects = [Periodic $ d 4 + dl 4, AddArmorMelee 1, AddArmorRanged 1]-  , ieffects = [RefillCalm 1]-  , ifeature = [ Precious, EqpSlot EqpSlotPeriodic "", Identified+  , iaspects = [ Periodic+               , Timeout $ (d 3 + 3 - dl 3) |*| 10+               , AddArmorMelee 1+               , AddArmorRanged 1 ]+  , ieffects = [Recharging (RefillCalm 1)]+  , ifeature = [ Durable, Precious, EqpSlot EqpSlotPeriodic "", Identified                , toVelocity 50 ]  -- not dense enough   , idesc    = "Highly ornamental, cold, large, steel medallion on a chain. Unlikely to offer much protection as an armor piece, but the old, worn engraving reassures you."   , ikit     = []   } necklace = ItemKind-  { isymbol  = '"'+  { isymbol  = symbolNecklace   , iname    = "necklace"   , ifreq    = [("useful", 100)]   , iflavour = zipFancy stdCol ++ zipPlain brightCol-  , irarity  = [(10, 3)]   , icount   = 1+  , irarity  = [(10, 3)]   , iverbHit = "whip"   , iweight  = 30-  , iaspects = []+  , iaspects = [Periodic]   , ieffects = []   , ifeature = [ Precious, EqpSlot EqpSlotPeriodic ""                , toVelocity 50 ]  -- not dense enough@@ -286,45 +283,44 @@   , ikit     = []   } necklace1 = necklace-  { iaspects = [Periodic $ d 2 + dl 2]-  , ieffects = [RefillHP 1]+  { iaspects = (Timeout $ (d 3 + 4 - dl 3) |*| 10) : iaspects necklace+  , ieffects = [Recharging (RefillHP 1)]   } necklace2 = necklace   { irarity  = [(2, 0), (10, 1)]-  , iaspects = [Periodic $ d 4 + dl 2]-  , ieffects = [ Impress-               , Summon [("mobile animal", 1)] $ 1 + dl 2, Explode "waste" ]+  , iaspects = (Timeout $ (d 3 + 3 - dl 3) |*| 10) : iaspects necklace+  , ieffects = [ Recharging (Impress)+               , Recharging (DropItem COrgan "temporary conditions" True)+               , Recharging (Summon [("mobile animal", 1)] $ 1 + dl 2)+               , Recharging (Explode "waste") ]   } necklace3 = necklace-  { iaspects = [Periodic $ d 4 + dl 2]-  , ieffects = [Paralyze $ 5 + d 5 + dl 5, RefillCalm 999]+  { iaspects = (Timeout $ (d 3 + 3 - dl 3) |*| 10) : iaspects necklace+  , ieffects = [Recharging (Paralyze $ 5 + d 5 + dl 5)]   } necklace4 = necklace-  { iaspects = [Periodic $ 2 * d 10 + dl 10]-  , ieffects = [Teleport $ d 3 |*| 3]+  { iaspects = (Timeout $ (d 4 + 4 - dl 4) |*| 2) : iaspects necklace+  , ieffects = [Recharging (Teleport $ d 3 |*| 3)]   } necklace5 = necklace-  { iaspects = [Periodic $ d 4 + dl 2]-  , ieffects = [Teleport $ 12 + d 3 |*| 3]+  { iaspects = (Timeout $ (d 3 + 4 - dl 3) |*| 10) : iaspects necklace+  , ieffects = [Recharging (Teleport $ 12 + d 3 |*| 3)]   } necklace6 = necklace-  { iaspects = [Periodic $ 2 * d 5 + dl 5]-  , ieffects = [PushActor (ThrowMod 100 50)]+  { iaspects = (Timeout $ d 4 |*| 10) : iaspects necklace+  , ieffects = [Recharging (PushActor (ThrowMod 100 50))]   }-necklace7 = necklace+necklace7 = necklace  -- TODO: teach AI to wear only for fight   { irarity  = [(4, 0), (10, 2)]-  , iaspects = [Periodic $ 2 * d 5 + dl 15]-  , ieffects = [InsertMove 1, RefillHP (-1)]-  , ifeature = ifeature necklace ++ [Durable]-      -- evil players would throw before death, to destroy-      -- TODO: teach AI to wear only for fight; prevent players from meleeing-      -- allies with that (Durable)+  , iaspects = [AddSpeed $ d 2, Timeout $ (d 3 + 3 + dl 3) |*| 2]+               ++ iaspects necklace+  , ieffects = [Recharging (RefillHP (-1))]   }  -- * Non-periodic jewelry  contactLens = ItemKind-  { isymbol  = '='+  { isymbol  = symbolRing   , iname    = "contact lens"   , ifreq    = [("useful", 100)]   , iflavour = zipPlain [White]@@ -338,8 +334,11 @@   , idesc    = "Advanced design. Never needs to be taken off."   , ikit     = []   }+-- Don't add standard effects to rings, because they go in and out+-- of eqp and so activating them would require UI tedium: looking for+-- them in eqp and inv or even activating a wrong item via letter by mistake. ring = ItemKind-  { isymbol  = '='+  { isymbol  = symbolRing   , iname    = "ring"   , ifreq    = [("useful", 100)]   , iflavour = zipPlain stdCol ++ zipFancy darkCol@@ -348,15 +347,16 @@   , iverbHit = "knock"   , iweight  = 15   , iaspects = []-  , ieffects = []+  , ieffects = [Explode "blast 2"]   , ifeature = [Precious, Identified]   , idesc    = "A sturdy ring with a softly shining eye. If it contains a body booster unit, beware of the side-effects."   , ikit     = []   } ring1 = ring-  { irarity  = [(2, 0), (10, 2)]+  { irarity  = [(10, 2)]   , iaspects = [AddSpeed $ d 2, AddMaxHP $ dl 3 - 5 - d 3]-  , ifeature = ifeature ring ++ [Durable, EqpSlot EqpSlotAddSpeed ""]+  , ieffects = [Explode "distortion"]  -- strong magic+  , ifeature = ifeature ring ++ [EqpSlot EqpSlotAddSpeed ""]   } ring2 = ring   { iaspects = [AddMaxHP $ 3 + dl 5, AddMaxCalm $ dl 6 - 15 - d 6]@@ -367,14 +367,15 @@   , ifeature = ifeature ring ++ [EqpSlot EqpSlotAddMaxCalm ""]   , idesc    = "Cold, solid to the touch, perfectly round, engraved with solemn, strangely comforting, worn out words."   }-ring4 = ring  -- TODO: move to level-ups and to timed effects-  { irarity  = [(3, 12), (10, 12)]+ring4 = ring+  { irarity  = [(3, 6), (10, 6)]   , iaspects = [AddHurtMelee $ (d 5 + dl 5) |*| 3, AddMaxHP $ dl 3 - 4 - d 2]-  , ifeature = ifeature ring ++ [Durable, EqpSlot EqpSlotAddHurtMelee ""]+  , ifeature = ifeature ring ++ [EqpSlot EqpSlotAddHurtMelee ""]   } ring5 = ring  -- by the time it's found, probably no space in eqp   { irarity  = [(5, 0)]   , iaspects = [AddLight $ d 2]+  , ieffects = [Explode "distortion"]  -- strong magic   , ifeature = ifeature ring ++ [EqpSlot EqpSlotAddLight ""]   , idesc    = "A sturdy ring with a large, shining stone."   }@@ -382,19 +383,19 @@ -- * Exploding consumables, often intended to be thrown  potion = ItemKind-  { isymbol  = '!'+  { isymbol  = symbolPotion   , iname    = "vial"   , ifreq    = [("useful", 100)]-  , iflavour = zipPlain stdCol ++ zipFancy brightCol+  , iflavour = zipLiquid brightCol ++ zipPlain brightCol ++ zipFancy brightCol   , icount   = 1-  , irarity  = [(1, 15), (10, 12)]+  , irarity  = [(1, 12), (10, 9)]   , iverbHit = "splash"   , iweight  = 200   , iaspects = []   , ieffects = []   , ifeature = [ toVelocity 50  -- oily, bad grip                , Applicable, Fragile ]-  , idesc    = "A flask of bubbly, slightly oily liquid of a suspect color."  -- purely natural; no nano, no alien tech  -- TODO: move distortion to a special flask item or trigger when some precious high tech item is destroyed (jewelry?)?+  , idesc    = "A vial of bright, frothing concoction."  -- purely natural; no nano, no alien tech   , ikit     = []   } potion1 = potion@@ -402,62 +403,142 @@                , OnSmash (ApplyPerfume), OnSmash (Explode "fragrance") ]   } potion2 = potion-  { ifreq    = [("useful", 1)]  -- extremely rare+  { ifreq    = [("useful", 10)]  -- extremely rare   , irarity  = [(1, 1)]-  , ieffects = [ NoEffect "of musky concoction", Impress, DropBestWeapon-               , OnSmash (Explode "pheromone")]+  , ieffects = [ NoEffect "of attraction", OnSmash (Explode "pheromone")]   } potion3 = potion-  { ieffects = [RefillHP 5, OnSmash (Explode "healing mist")]+  { irarity  = [(1, 5), (10, 5)]+  , ieffects = [RefillHP 5, OnSmash (Explode "healing mist")]   }-potion4 = potion  -- TODO: a bit boring-  { irarity  = [(1, 7)]-  , ieffects = [RefillHP (-5), OnSmash (Explode "wounding mist")]+potion4 = potion+  { irarity  = [(10, 5)]+  , ieffects = [RefillHP 10, OnSmash (Explode "healing mist 2")]   } potion5 = potion-  { ieffects = [ Explode "explosion blast 10", Impress-               , PushActor (ThrowMod 200 75)-               , OnSmash (Explode "explosion blast 10") ]-  }-potion6 = potion-  { irarity  = [(10, 2)]-  , ieffects = [ NoEffect "of distortion", Impress-               , OnSmash (Explode "distortion")]-  }-potion7 = potion-  { ieffects = [ NoEffect "of bait cocktail", Impress-               , OnSmash (Summon [("mobile animal", 1)] $ 1 + dl 2)-               , OnSmash (Explode "waste") ]-  }-potion8 = potion   { ieffects = [ OneOf [Impress, DropBestWeapon, RefillHP 5, Burn 3]                , OnSmash (OneOf [ Explode "healing mist"                                 , Explode "wounding mist"                                 , Explode "fragrance"-                                , Explode "explosion blast 10" ]) ]+                                , Explode "blast 10" ]) ]   }-potion9 = potion+potion6 = potion   { irarity  = [(3, 3), (10, 6)]   , ieffects = [ OneOf [ Dominate, DropBestWeapon, RefillHP 20, Burn 9-                       , InsertMove 2]+                       , InsertMove 4 ]                , OnSmash (OneOf [ Explode "healing mist 2"                                 , Explode "healing mist 2"                                 , Explode "pheromone"-                                , Explode "distortion"-                                , Explode "explosion blast 20" ]) ]+                                , Explode "distortion"  -- outlier, OK+                                , Explode "blast 20" ]) ]   }-potion10 = potion  -- used only as initial equipmnt; count betray identity-  { ifreq    = [("useful", 100), ("potion of glue", 1)]-  , irarity  = [(1, 1)]-  , icount   = 1 + d 2-  , ieffects = [ NoEffect "of sticky foam", Paralyze (5 + d 5)-               , OnSmash (Explode "glue")]-  , ifeature = [Identified]+potion7 = potion+  { ieffects = [ DropItem COrgan "poisoned" True, RefillHP 1+               , OnSmash (Explode "antidote mist") ]   }-potion11 = potion+potion8 = potion+  { ieffects = [ DropItem COrgan "temporary conditions" True, RefillHP 2+               , OnSmash (Explode "blast 10") ]+  }++-- * Exploding consumables, with temporary aspects+-- TODO: dip projectiles in those+-- TODO: add flavour and realism as in, e.g., "flask of whiskey",+-- which is more flavourful and believable than "flask of strength"++flask = ItemKind+  { isymbol  = symbolFlask+  , iname    = "flask"+  , ifreq    = [("useful", 100)]+  , iflavour = zipLiquid darkCol ++ zipPlain darkCol ++ zipFancy darkCol+  , icount   = 1+  , irarity  = [(1, 9), (10, 6)]+  , iverbHit = "splash"+  , iweight  = 500+  , iaspects = []+  , ieffects = []+  , ifeature = [ toVelocity 50  -- oily, bad grip+               , Applicable, Fragile ]+  , idesc    = "A flask of oily liquid of a suspect color."+  , ikit     = []+  }+flask1 = flask   { irarity  = [(10, 5)]-  , ieffects = [RefillHP 10, OnSmash (Explode "healing mist 2")]+  , ieffects = [ NoEffect "of strength brew"+               , toOrganActorTurn "strengthened" (20 + d 5)+               , OnSmash (Explode "strength mist") ]   }+flask2 = flask+  { ieffects = [ NoEffect "of weakness brew"+               , toOrganGameTurn "weakened" (20 + d 5)+               , OnSmash (Explode "weakness mist") ]+  }+flask3 = flask+  { ieffects = [ NoEffect "of protecting balm"+               , toOrganActorTurn "protected" (20 + d 5)+               , OnSmash (Explode "protecting balm") ]+  }+flask4 = flask+  { ieffects = [ NoEffect "of red paint"+               , toOrganGameTurn "painted red" (20 + d 5)+               , OnSmash (Explode "red paint") ]+  }+flask5 = flask+  { irarity  = [(10, 5)]+  , ieffects = [ NoEffect "of haste brew"+               , toOrganActorTurn "fast 20" (20 + d 5)+               , OnSmash (Explode "haste spray") ]+  }+flask6 = flask+  { ieffects = [ NoEffect "of lethargy brew"+               , toOrganGameTurn "slow 10" (20 + d 5)+               , toOrganNone "regenerating"+               , OnSmash (Explode "slowness spray") ]+  }+flask7 = flask  -- sight can be reduced from Calm, drunk, etc.+  { irarity  = [(10, 7)]+  , ieffects = [ NoEffect "of eye drops"+               , toOrganActorTurn "far-sighted" (20 + d 5)+               , OnSmash (Explode "eye drop") ]+  }+flask8 = flask+  { irarity  = [(10, 3)]+  , ieffects = [ NoEffect "of smelly concoction"+               , toOrganActorTurn "keen-smelling" (20 + d 5)+               , OnSmash (Explode "smelly droplet") ]+  }+flask9 = flask+  { ieffects = [ NoEffect "of bait cocktail", toOrganActorTurn "drunk" (5 + d 5)+               , OnSmash (Summon [("mobile animal", 1)] $ 1 + dl 2)+               , OnSmash (Explode "waste") ]+  }+flask10 = flask+  { ieffects = [ NoEffect "of whiskey", toOrganActorTurn "drunk" (20 + d 5)+               , Burn 2, RefillHP 4, OnSmash (Explode "whiskey spray") ]+  }+flask11 = flask+  { irarity  = [(1, 20), (10, 6)]+  , ieffects = [ NoEffect "of regeneration brew"+               , toOrganNone "regenerating"+               , OnSmash (Explode "healing mist") ]+  }+flask12 = flask  -- but not flask of Calm depletion, since Calm reduced often+  { ieffects = [ NoEffect "of poison"+               , toOrganNone "poisoned"+               , OnSmash (Explode "wounding mist") ]+  }+flask13 = flask+  { irarity  = [(10, 5)]+  , ieffects = [ NoEffect "of slow resistance"+               , toOrganNone "slow resistant"+               , OnSmash (Explode "anti-slow mist") ]+  }+flask14 = flask  -- but not flask of Calm depletion, since Calm reduced often+  { irarity  = [(10, 5)]+  , ieffects = [ NoEffect "of poison resistance"+               , toOrganNone "poison resistant"+               , OnSmash (Explode "antidote mist") ]+  }  -- * Non-exploding consumables, not specifically designed for throwing @@ -473,23 +554,23 @@   , ikit     = []   } scroll = ItemKind-  { isymbol  = '?'-  , iname    = "tablet"+  { isymbol  = symbolScroll+  , iname    = "chip"   , ifreq    = [("useful", 100), ("any scroll", 100)]   , iflavour = zipFancy stdCol ++ zipPlain darkCol  -- arcane and old   , icount   = 1   , irarity  = [(1, 15), (10, 12)]   , iverbHit = "thump"-  , iweight  = 700+  , iweight  = 20   , iaspects = []   , ieffects = []-  , ifeature = [ toVelocity 25  -- bad grip+  , ifeature = [ toVelocity 25  -- too little                , Applicable ]-  , idesc    = "A standard issue spaceship crew tablet displaying a fixed infographic and a big button. Some of these still contain a one-time password authorizing a particular spaceship's infrastructure transition. It is unknown how the infrastructure might respond after so many years."+  , idesc    = "A generic, diposable chip, capable of a one-time holo-display. Some of these also contain a one-time password authorizing a particular spaceship's infrastructure transition. It is unknown how the infrastructure might respond after so many years."   , ikit     = []   } scroll1 = scroll-  { irarity  = [(1, 2), (10, 3)]+  { irarity  = [(3, 6), (10, 6)]   , ieffects = [CallFriend 1]   } scroll2 = scroll@@ -502,33 +583,37 @@   } scroll4 = scroll   { ieffects = [ OneOf [ Teleport $ d 3 |*| 3, RefillCalm 10, RefillCalm (-10)-                       , InsertMove 4, Paralyze 10, Identify CGround ] ]+                       , InsertMove 3, Paralyze 10, Identify CGround ] ]   } scroll5 = scroll-  { irarity  = [(3, 3), (10, 6)]+  { irarity  = [(10, 15)]   , ieffects = [ OneOf [ Summon standardSummon $ d 2                        , CallFriend 1, Ascend (-1), Ascend 1-                       , RefillCalm 30, RefillCalm (-30), CreateItem $ d 2+                       , RefillCalm 30, RefillCalm (-30)+                       , CreateItem CGround "useful" TimerNone                        , PolyItem CGround ] ]                -- TODO: ask player: Escape 1   } scroll6 = scroll-  { ieffects = [Teleport $ d 3 |*| 3]+  { ieffects = [Teleport 5]   } scroll7 = scroll-  { irarity  = [(10, 3)]-  , ieffects = [InsertMove $ d 2 + dl 2]+  { ieffects = [Teleport 20]   } scroll8 = scroll-  { irarity  = [(3, 8), (10, 4)]-  , ieffects = [Identify CGround]  -- TODO: ask player: AskPlayer cstore eff?+  { irarity  = [(10, 3)]+  , ieffects = [InsertMove $ 1 + d 2 + dl 2]   } scroll9 = scroll+  { irarity  = [(1, 15)]+  , ieffects = [Identify CGround]  -- TODO: ask player: AskPlayer cstore eff?+  }+scroll10 = scroll   { irarity  = [(10, 10)]   , ieffects = [PolyItem CGround]   } -standardSummon :: Freqs+standardSummon :: Freqs ItemKind standardSummon = [ ("alien", 20)                  , ("mobile animal", 50)                  , ("mobile robot", 30) ]@@ -536,17 +621,17 @@ -- * Armor  armorLeather = ItemKind-  { isymbol  = '['+  { isymbol  = symbolTorsoArmor   , iname    = "spacesuit breastplate"   , ifreq    = [("useful", 100)]   , iflavour = zipPlain [Brown]   , icount   = 1-  , irarity  = [(3, 6), (10, 3)]+  , irarity  = [(1, 9), (10, 3)]   , iverbHit = "thud"   , iweight  = 7000   , iaspects = [ AddHurtMelee (-3)-               , AddArmorMelee $ (1 + dl 3) |*| 5-               , AddArmorRanged $ (1 + dl 3) |*| 5 ]+               , AddArmorMelee $ (d 2 + dl 3) |*| 5+               , AddArmorRanged $ (d 2 + dl 3) |*| 5 ]   , ieffects = []   , ifeature = [ toVelocity 30  -- unwieldy to throw and blunt                , Durable, EqpSlot EqpSlotAddArmorMelee "", Identified ]@@ -556,20 +641,20 @@ armorMail = armorLeather   { iname    = "bulletproof vest"   , iflavour = zipPlain [Cyan]-  , irarity  = [(6, 6), (10, 6)]+  , irarity  = [(6, 9), (10, 3)]   , iweight  = 12000   , iaspects = [ AddHurtMelee (-3)-               , AddArmorMelee $ (2 + dl 4) |*| 5-               , AddArmorRanged $ (2 + dl 4) |*| 5 ]+               , AddArmorMelee $ (1 + d 2 + dl 4) |*| 5+               , AddArmorRanged $ (1 + d 2 + dl 4) |*| 5 ]   , idesc    = "A civilian bulletproof vest. Discourages foes from attacking your torso, making it harder for them to land a blow."   } gloveFencing = ItemKind-  { isymbol  = ']'+  { isymbol  = symbolMiscArmor   , iname    = "construction glove"   , ifreq    = [("useful", 100)]   , iflavour = zipPlain [BrYellow]   , icount   = 1-  , irarity  = [(5, 8), (10, 8)]+  , irarity  = [(5, 9), (10, 9)]   , iverbHit = "flap"   , iweight  = 100   , iaspects = [ AddHurtMelee $ (d 2 + dl 10) * 3@@ -582,8 +667,8 @@   } gloveGauntlet = gloveFencing   { iname    = "spacesuit glove"-  , irarity  = [(6, 12)]   , iflavour = zipPlain [BrCyan]+  , irarity  = [(1, 9), (10, 3)]   , iweight  = 300   , iaspects = [ AddArmorMelee $ (1 + dl 2) |*| 5                , AddArmorRanged $ (1 + dl 2) |*| 5 ]@@ -591,18 +676,21 @@   } gloveJousting = gloveFencing   { iname    = "welding handgear"-  , irarity  = [(6, 6)]   , iflavour = zipFancy [BrRed]+  , irarity  = [(1, 3), (10, 3)]   , iweight  = 500   , iaspects = [ AddHurtMelee $ (dl 4 - 6) |*| 3                , AddArmorMelee $ (2 + dl 2) |*| 5                , AddArmorRanged $ (2 + dl 2) |*| 5 ]   , idesc    = "Rigid, bulky handgear embedding a welding equipment, complete with an affixed small shield and a darkened visor. Awe-inspiring."   }++-- * Shields+ -- Shield doesn't protect against ranged attacks to prevent -- micromanagement: walking with shield, melee without. buckler = ItemKind-  { isymbol  = ')'+  { isymbol  = symbolShield   , iname    = "buckler"   , ifreq    = [("useful", 100)]   , iflavour = zipPlain [Blue]@@ -610,8 +698,10 @@   , irarity  = [(4, 6)]   , iverbHit = "bash"   , iweight  = 2000-  , iaspects = [AddArmorMelee 40, AddHurtMelee (-30)]-  , ieffects = []+  , iaspects = [ AddArmorMelee 40+               , AddHurtMelee (-30)+               , Timeout $ (d 3 + 3 - dl 3) |*| 2 ]+  , ieffects = []  -- [Recharging (PushActor (ThrowMod 200 50))]   , ifeature = [ toVelocity 30  -- unwieldy to throw and blunt                , Durable, EqpSlot EqpSlotAddArmorMelee "", Identified ]   , idesc    = "Heavy and unwieldy arm protection made from an outer airlock panel. Absorbs a percentage of melee damage, both dealt and sustained. Too small to intercept projectiles with."@@ -622,7 +712,10 @@   , irarity  = [(7, 5)]   , iflavour = zipPlain [Green]   , iweight  = 3000-  , iaspects = [AddArmorMelee 80, AddHurtMelee (-70)]+  , iaspects = [ AddArmorMelee 80+               , AddHurtMelee (-70)+               , Timeout $ (d 3 + 6 - dl 3) |*| 2 ]+  , ieffects = []  -- [Recharging (PushActor (ThrowMod 400 50))]   , ifeature = [ toVelocity 20  -- unwieldy to throw and blunt                , Durable, EqpSlot EqpSlotAddArmorMelee "", Identified ]   , idesc    = "Large and unwieldy rectangle made of anti-meteorite ceramic sheet. Absorbs a percentage of melee damage, both dealt and sustained. Too heavy to intercept projectiles with."@@ -631,7 +724,7 @@ -- * Weapons  dagger = ItemKind-  { isymbol  = '|'+  { isymbol  = symbolEdged   , iname    = "cleaver"   , ifreq    = [("useful", 100), ("starting weapon", 100)]   , iflavour = zipPlain [BrCyan]@@ -646,8 +739,23 @@   , idesc    = "A heavy professional kitchen blade. Will do fine cutting any kind of meat and bone, as well as parrying blows. Does not penetrate deeply, but is hard to block. Especially useful in conjunction with a larger weapon."   , ikit     = []   }+daggerDropBestWeapon = dagger+  { ifreq    = [("useful", 30)]+  , irarity  = [(1, 1), (10, 2)]+  -- The timeout has to be small, so that the player can count on the effect+  -- occuring consistently in any longer fight. Otherwise, the effect will be+  -- absent in some important fights, leading to the feeling of bad luck,+  -- but will manifest sometimes in fights where it doesn't matter,+  -- leading to the feeling of wasted power.+  -- If the effect is very powerful and so the timeout has to be significant,+  -- let's make it really large, for the effect to occur only once in a fight:+  -- as soon as the item is equipped, or just on the first strike.+  , iaspects = iaspects dagger ++ [Timeout $ (d 3 + 4 - dl 3) |*| 2]+  , ieffects = ieffects dagger ++ [Recharging DropBestWeapon]+  , idesc    = "A knife with a forked blade that a focused fencer can use to catch and twist an opponent's weapon occasionally."+  } hammer = ItemKind-  { isymbol  = '\\'+  { isymbol  = symbolHafted   , iname    = "demolition hammer"   , ifreq    = [("useful", 100), ("starting weapon", 100)]   , iflavour = zipPlain [BrMagenta]@@ -662,8 +770,21 @@   , idesc    = "A hammer on a long handle used for construction work. It may not cause grave wounds, but neither does it ricochet or glance off armor. Great sidearm for opportunistic blows against armored foes."   , ikit     = []   }+hammerParalyze = hammer+  { ifreq    = [("useful", 30)]+  , irarity  = [(4, 1), (10, 2)]+  , iaspects = iaspects hammer ++ [Timeout $ (d 2 + 3 - dl 2) |*| 2]+  , ieffects = ieffects hammer ++ [Recharging $ Paralyze 5]+  }+hammerSpark = hammer+  { iname    = "smithhammer"+  , ifreq    = [("useful", 30)]+  , irarity  = [(4, 1), (10, 2)]+  , iaspects = iaspects hammer ++ [Timeout $ (d 4 + 4 - dl 4) |*| 2]+  , ieffects = ieffects hammer ++ [Recharging $ Explode "spark"]+  } sword = ItemKind-  { isymbol  = '/'+  { isymbol  = symbolPolearm   , iname    = "sharpened pipe"   , ifreq    = [("useful", 100), ("starting weapon", 100)]   , iflavour = zipPlain [BrBlue]@@ -678,9 +799,25 @@   , idesc    = "A makeshift weapon of simple design, but great potential. Hard to master, though."   , ikit     = []   }+swordImpress = sword+  { isymbol  = symbolEdged+  , iname    = "an antique sword"+  , ifreq    = [("useful", 30)]+  , irarity  = [(3, 1), (10, 2)]+  , iaspects = iaspects sword ++ [Timeout $ (d 4 + 5 - dl 4) |*| 2]+  , ieffects = ieffects sword ++ [Recharging Impress]+  , idesc    = "An old, dull, but well-balance blade, lending itself to impressive shows of fencing skill."+  }+swordNullify = sword+  { ifreq    = [("useful", 30)]+  , irarity  = [(3, 0), (10, 1)]+  , iaspects = iaspects sword ++ [Timeout $ (d 4 + 5 - dl 4) |*| 2]+  , ieffects = ieffects sword ++ [Recharging $ DropItem COrgan "temporary conditions" True]+  , idesc    = "Cold, thin, ancient blade that pierces deeply and sends its victim into abrupt, sobering shock."+  } halberd = ItemKind-  { isymbol  = '/'-  , iname    = "halberd"+  { isymbol  = symbolPolearm+  , iname    = "pole cleaver"   , ifreq    = [("useful", 100), ("starting weapon", 1)]   , iflavour = zipPlain [BrYellow]   , icount   = 1@@ -688,17 +825,25 @@   , iverbHit = "impale"   , iweight  = 3000   , iaspects = [AddArmorMelee $ (1 + dl 3) |*| 5]-  , ieffects = [Hurt (14 * d 1)]+  , ieffects = [Hurt (12 * d 1)]   , ifeature = [ toVelocity 20  -- not balanced                , Durable, EqpSlot EqpSlotWeapon "", Identified ]-  , idesc    = "A perfect replica made for a reenactor troupe, missing only some sharpening. Versatile, with great reach and leverage. Foes are held at a distance."+  , idesc    = "An improvised but deadly weapon made of a long, sharp kitchen knife glued and bound to a long pole."   , ikit     = []   }+halberdPushActor = halberd+  { iname    = "halberd"+  , ifreq    = [("useful", 30)]+  , irarity  = [(7, 1), (10, 2)]+  , iaspects = iaspects halberd ++ [Timeout $ (d 5 + 5 - dl 5) |*| 2]+  , ieffects = ieffects halberd ++ [Recharging (PushActor (ThrowMod 400 25))]+  , idesc    = "A perfect replica made for a reenactor troupe, missing only some sharpening. Versatile, with great reach and leverage. Foes are held at a distance."+  }  -- * Wands  wand = ItemKind-  { isymbol  = '-'+  { isymbol  = symbolWand   , iname    = "injector"   , ifreq    = [("useful", 100)]   , iflavour = zipFancy brightCol@@ -720,37 +865,44 @@   { ieffects = []   } --- * Assorted tools+-- * Treasure -jumpingPole = ItemKind-  { isymbol  = '~'-  , iname    = "jumping pole"-  , ifreq    = [("useful", 100)]-  , iflavour = zipPlain [White]+gem = ItemKind+  { isymbol  = symbolGem+  , iname    = "gem"+  , ifreq    = [("treasure", 100)]+  , iflavour = zipPlain $ delete BrYellow brightCol  -- natural, so not fancy   , icount   = 1-  , irarity  = [(1, 4), (10, 2)]-  , iverbHit = "prod"-  , iweight  = 10000-  , iaspects = []-  , ieffects = [InsertMove 2]  -- TODO: implement with timed speed instead-                               -- and then make Durable, freq 2, and just trade-                               -- taken turn now for a free turn later-  , ifeature = [Applicable, Identified]-  , idesc    = "Makes you vulnerable at take-off, but then you are free like a bird."+  , irarity  = []+  , iverbHit = "tap"+  , iweight  = 50+  , iaspects = [AddLight 1, AddSpeed (-1)]  -- reflects strongly, distracts+  , ieffects = []+  , ifeature = [Precious]+  , idesc    = "Precious, though useless. Worth around 100 gold grains."   , ikit     = []   }-honingSteel = ItemKind-  { isymbol  = '~'-  , iname    = "honing steel"-  , ifreq    = [("useful", 100)]-  , iflavour = zipPlain [Blue]-  , icount   = 1-  , irarity  = [(10, 10)]-  , iverbHit = "smack"-  , iweight  = 400-  , iaspects = [AddHurtMelee $ d 10 |*| 3]+gem1 = gem+  { irarity  = [(2, 0), (10, 10)]+  }+gem2 = gem+  { irarity  = [(4, 0), (10, 15)]+  }+gem3 = gem+  { irarity  = [(6, 0), (10, 20)]+  }+currency = ItemKind+  { isymbol  = symbolGold+  , iname    = "gold grain"+  , ifreq    = [("treasure", 100), ("currency", 1)]+  , iflavour = zipPlain [BrYellow]+  , icount   = 10 + d 20 + dl 20+  , irarity  = [(1, 10), (6, 25), (10, 10)]+  , iverbHit = "tap"+  , iweight  = 1+  , iaspects = []   , ieffects = []-  , ifeature = [EqpSlot EqpSlotAddHurtMelee "", Identified]-  , idesc    = "Originally used for realigning the bent or buckled edges of kitchen knives in the local bars. Now it saves lives by letting you fix your weapons between or even during fights, without the need to set up camp, fish out tools and assemble a proper sharpening workshop."+  , ifeature = [Identified, Precious]+  , idesc    = "Reliably valuable in every civilized place."   , ikit     = []   }
GameDefinition/Content/ItemKindActor.hs view
@@ -10,16 +10,15 @@  import Game.LambdaHack.Common.Ability import Game.LambdaHack.Common.Color-import Game.LambdaHack.Common.Effect import Game.LambdaHack.Common.Flavour import Game.LambdaHack.Common.Misc import Game.LambdaHack.Content.ItemKind  actors :: [ItemKind] actors =-  [warrior, pilot, engineer, doctor, soldier, clerk, hairdresser, lawyer, peddler, taxCollector, eye, fastEye, nose, elbow, armadillo, gilaMonster, komodoDragon, hyena, alligator, hornetSwarm, thornbush, razorwireFence, electricFence, activeFence, steamFaucet, biogasFaucet, shepherdDrone, huntingDrone, homeRobot, wasteRobot, lightRobot, heavyRobot]+  [warrior, pilot, engineer, doctor, soldier, clerk, hairdresser, lawyer, peddler, taxCollector, eye, fastEye, nose, elbow, armadillo, gilaMonster, rattlesnake, komodoDragon, hyena, alligator, hornetSwarm, thornbush, razorwireFence, electricFence, activeFence, steamFaucet, biogasFaucet, shepherdDrone, huntingDrone, homeRobot, wasteRobot, lightRobot, heavyRobot] -warrior,    pilot, engineer, doctor, soldier, clerk, hairdresser, lawyer, peddler, taxCollector, eye, fastEye, nose, elbow, armadillo, gilaMonster, komodoDragon, hyena, alligator, hornetSwarm, thornbush, razorwireFence, electricFence, activeFence, steamFaucet, biogasFaucet, shepherdDrone, huntingDrone, homeRobot, wasteRobot, lightRobot, heavyRobot :: ItemKind+warrior,    pilot, engineer, doctor, soldier, clerk, hairdresser, lawyer, peddler, taxCollector, eye, fastEye, nose, elbow, armadillo, gilaMonster, rattlesnake, komodoDragon, hyena, alligator, hornetSwarm, thornbush, razorwireFence, electricFence, activeFence, steamFaucet, biogasFaucet, shepherdDrone, huntingDrone, homeRobot, wasteRobot, lightRobot, heavyRobot :: ItemKind  -- * Hunams @@ -32,8 +31,11 @@   , irarity  = [(1, 5)]   , iverbHit = "thud"   , iweight  = 80000-  , iaspects = [ AddMaxHP 50, AddMaxCalm 60, AddSpeed 20-               , AddSight 3 ]  -- no via eyes, but feel, hearing, etc.+  , iaspects = [ AddMaxHP 60  -- partially from clothes and assumed first aid+               , AddMaxCalm 60, AddSpeed 20+               , AddSkills $ EM.fromList [(AbProject, 1), (AbApply, 1)]+                   -- TODO: on a ring?+               , AddSight 3 ]  -- not via eyes, but feel, hearing, etc.   , ieffects = []   , ifeature = [Durable, Identified]   , idesc    = ""@@ -72,11 +74,12 @@   , ifreq    = [("alien", 100), ("horror", 100)]   , iflavour = zipPlain [BrRed]   , icount   = 1-  , irarity  = [(3, 1), (10, 9)]+  , irarity  = [(3, 4), (10, 10)]   , iverbHit = "thud"   , iweight  = 80000-  , iaspects = [ AddMaxHP 20, AddMaxCalm 60, AddSpeed 20-               , AddSight 4 ]  -- can shoot for as long as lives+  , iaspects = [ AddMaxHP 10, AddMaxCalm 60, AddSpeed 20+               , AddSkills $ EM.fromList [(AbProject, 1), (AbApply, 1)]+               , AddSight 4 ]   , ieffects = []   , ifeature = [Durable, Identified]   , idesc    = "Walks with a stately dignity. You read death in the slow beckoning gestures of its revolting upper appendages."@@ -91,11 +94,11 @@   , ifreq    = [("alien", 100), ("horror", 100)]   , iflavour = zipPlain [BrBlue]   , icount   = 1-  , irarity  = [(6, 1), (10, 7)]+  , irarity  = [(3, 2), (10, 8)]   , iverbHit = "thud"   , iweight  = 80000-  , iaspects = [ AddMaxHP 6, AddMaxCalm 60, AddSpeed 30-               , AddSight 4 ]  -- can shoot for as long as lives+  , iaspects = [ AddMaxHP 5, AddMaxCalm 60, AddSpeed 30+               , AddSight 4 ]   , ieffects = []   , ifeature = [Durable, Identified]   , idesc    = "It bites as blindingly fast as it runs. Or rolls? Or crawls? Also, cuts and pierces."@@ -110,10 +113,11 @@   , ifreq    = [("alien", 100), ("horror", 100)]   , iflavour = zipPlain [BrGreen]   , icount   = 1-  , irarity  = [(3, 1), (10, 9)]+  , irarity  = [(3, 4), (10, 6)]   , iverbHit = "thud"   , iweight  = 80000-  , iaspects = [ AddMaxHP 40, AddMaxCalm 30, AddSpeed 18+  , iaspects = [ AddMaxHP 20, AddMaxCalm 30, AddSpeed 18+               , AddSkills $ EM.fromList [(AbProject, -1), (AbApply, -1)]                , AddSmell 3 ]  -- depends solely on smell   , ieffects = []   , ifeature = [Durable, Identified]@@ -132,9 +136,10 @@   , irarity  = [(6, 1), (10, 5)]   , iverbHit = "thud"   , iweight  = 80000-  , iaspects = [ AddMaxHP 15, AddMaxCalm 80, AddSpeed 26-               , AddSkills $ EM.singleton AbMelee (-1)-               , AddSight 15 ]  -- can shoot for as long as lives+  , iaspects = [ AddMaxHP 12, AddMaxCalm 90, AddSpeed 26+               , AddSkills+                 $ EM.fromList [(AbProject, 1), (AbApply, 1), (AbMelee, -1)]+               , AddSight 15 ]   , ieffects = []   , ifeature = [Durable, Identified]   , idesc    = "It moves in sudden jerks and never makes a noise. Speaks in hard objects hurled at deadly speeds."@@ -145,6 +150,13 @@  -- * Animals +-- They need rather strong melee, because they don't use items.+-- Unless/until they level up.++animalSkillMalus :: Skills+animalSkillMalus =+  EM.fromList $ zip [AbDisplace, AbMoveItem, AbProject, AbApply] [-1, -1..]+ armadillo = ItemKind   { isymbol  = 'a'   , iname    = "giant armadillo"@@ -155,7 +167,7 @@   , iverbHit = "thud"   , iweight  = 80000   , iaspects = [ AddMaxHP 30, AddMaxCalm 30, AddSpeed 18-               , AddSkills $ EM.singleton AbAlter (-1)+               , AddSkills $ EM.insert AbAlter (-1) animalSkillMalus                , AddSight 3 ]   , ieffects = []   , ifeature = [Durable, Identified]@@ -173,7 +185,7 @@   , iverbHit = "thud"   , iweight  = 80000   , iaspects = [ AddMaxHP 15, AddMaxCalm 60, AddSpeed 15-               , AddSkills $ EM.singleton AbAlter (-1)+               , AddSkills $ EM.insert AbAlter (-1) animalSkillMalus                , AddSight 3 ]   , ieffects = []   , ifeature = [Durable, Identified]@@ -181,6 +193,24 @@   , ikit     = [ ("venom tooth", COrgan), ("small claw", COrgan)                , ("eye 4", COrgan), ("nostril", COrgan) ]   }+rattlesnake = ItemKind+  { isymbol  = 'r'+  , iname    = "rattlesnake"+  , ifreq    = [("animal", 100), ("horror", 100), ("mobile animal", 100)]+  , iflavour = zipPlain [Brown]+  , icount   = 1+  , irarity  = [(3, 2), (10, 4)]+  , iverbHit = "thud"+  , iweight  = 80000+  , iaspects = [ AddMaxHP 25, AddMaxCalm 60, AddSpeed 15+               , AddSkills $ EM.insert AbAlter (-1) animalSkillMalus+               , AddSight 3 ]+  , ieffects = []+  , ifeature = [Durable, Identified]+  , idesc    = ""+  , ikit     = [ ("venom fang", COrgan)+               , ("eye 4", COrgan), ("nostril", COrgan) ]+  } komodoDragon = ItemKind  -- bad hearing   { isymbol  = 'k'   , iname    = "Komodo dragon"@@ -190,8 +220,8 @@   , irarity  = [(5, 5), (10, 7)]   , iverbHit = "thud"   , iweight  = 80000-  , iaspects = [ AddMaxHP 40, AddMaxCalm 60, AddSpeed 18-               , AddSight 3 ]+  , iaspects = [ AddMaxHP 40, AddMaxCalm 60, AddSpeed 16+               , AddSkills animalSkillMalus, AddSight 3 ]   , ieffects = []   , ifeature = [Durable, Identified]   , idesc    = ""@@ -208,8 +238,8 @@   , irarity  = [(4, 6), (10, 6)]   , iverbHit = "thud"   , iweight  = 80000-  , iaspects = [ AddMaxHP 30, AddMaxCalm 60, AddSpeed 35-               , AddSight 3 ]+  , iaspects = [ AddMaxHP 20, AddMaxCalm 60, AddSpeed 30+               , AddSkills animalSkillMalus, AddSight 3 ]   , ieffects = []   , ifeature = [Durable, Identified]   , idesc    = ""@@ -226,7 +256,7 @@   , iweight  = 80000   , iaspects = [ AddMaxHP 30, AddMaxCalm 60, AddSpeed 17                , AddArmorMelee 30, AddArmorRanged 30-               , AddSight 3 ]+               , AddSkills animalSkillMalus, AddSight 3 ]   , ieffects = []   , ifeature = [Durable, Identified]   , idesc    = ""@@ -246,7 +276,7 @@   , iverbHit = "thud"   , iweight  = 1000   , iaspects = [ AddMaxHP 5, AddMaxCalm 60, AddSpeed 30, AddSight 2-               , AddSkills $ EM.singleton AbAlter (-1)+               , AddSkills $ EM.insert AbAlter (-1) animalSkillMalus                , AddArmorMelee 90, AddArmorRanged 90 ]   , ieffects = []   , ifeature = [Durable, Identified]@@ -275,6 +305,9 @@  -- * Robots +robotSkillMalus :: Skills+robotSkillMalus = EM.fromList $ zip [AbApply] [-1]+ razorwireFence = ItemKind   { isymbol  = 'f'   , iname    = "razorwire fence"@@ -322,17 +355,16 @@   , irarity  = [(4, 0), (5, 1)]   , iverbHit = "thud"   , iweight  = 80000-  , iaspects = [ AddMaxHP 30, AddMaxCalm 999, AddSpeed 20, AddSight 6+  , iaspects = [ AddMaxHP 20, AddMaxCalm 999, AddSpeed 20, AddSight 6                , AddSkills                  $ EM.fromDistinctAscList (zip [minBound..maxBound] [-1, -1..])-                   `addSkills` EM.fromList (zip [AbWait, AbProject]-                                                [1, 1..])+                   `addSkills` EM.fromList [(AbWait, 1), (AbProject, 2)]                , AddArmorMelee 50, AddArmorRanged 50 ]   , ieffects = []   , ifeature = [Durable, Identified]   , idesc    = "Makeshift, mostly non-lethal, autonomous perimeter defense outpost."-  , ikit     = [ ("needle", CInv), ("potion of glue", CInv)-               , ("potion of glue", CInv), ("potion of glue", CInv) ]+  , ikit     = [ ("needle", CInv), ("can of sticky foam", CInv)+               , ("can of sticky foam", CInv), ("can of sticky foam", CInv) ]   } steamFaucet = ItemKind   { isymbol  = 'f'@@ -343,10 +375,11 @@   , irarity  = [(1, 1)]   , iverbHit = "thud"   , iweight  = 80000-  , iaspects = [ AddMaxHP 100, AddMaxCalm 999, AddSpeed 5+  , iaspects = [ AddMaxHP 10, AddMaxCalm 999, AddSpeed 5                , AddSkills                  $ EM.fromDistinctAscList (zip [minBound..maxBound] [-1, -1..])-                   `addSkills` EM.fromList (zip [AbWait, AbMelee] [1, 1..]) ]+                   `addSkills` EM.fromList (zip [AbWait, AbMelee] [1, 1..])+               , AddArmorMelee 80, AddArmorRanged 80 ]   , ieffects = []   , ifeature = [Durable, Identified]   , idesc    = "A cracked valve on one of the superheated water pipes spreading radially outward from the tokamak level."@@ -361,10 +394,11 @@   , irarity  = [(3, 0), (4, 1)]   , iverbHit = "thud"   , iweight  = 80000-  , iaspects = [ AddMaxHP 100, AddMaxCalm 999, AddSpeed 5+  , iaspects = [ AddMaxHP 10, AddMaxCalm 999, AddSpeed 5                , AddSkills                  $ EM.fromDistinctAscList (zip [minBound..maxBound] [-1, -1..])-                   `addSkills` EM.fromList (zip [AbWait] [1, 1..]) ]+                   `addSkills` EM.fromList (zip [AbWait] [1, 1..])+               , AddArmorMelee 80, AddArmorRanged 80 ]   , ieffects = []   , ifeature = [Durable, Identified]   , idesc    = "An emergency pressure-release vent on a liquefied biogas pipe."@@ -381,8 +415,8 @@   , iweight  = 1000   , iaspects = [ AddMaxHP 2, AddMaxCalm 60, AddSpeed 30, AddSight 4                , AddSkills-                 $ EM.fromDistinctAscList-                 $ zip [AbDisplace, AbMoveItem, AbProject] [-1, -1..]+                 $ EM.fromList+                 $ zip [AbApply, AbDisplace, AbMoveItem, AbProject] [-1, -1..]                , AddArmorMelee 90, AddArmorRanged 90 ]   , ieffects = []   , ifeature = [Durable, Identified]@@ -400,8 +434,8 @@   , iweight  = 500   , iaspects = [ AddMaxHP 2, AddMaxCalm 60, AddSpeed 40, AddSight 4                , AddSkills-                 $ EM.fromDistinctAscList-                 $ zip [AbDisplace, AbMoveItem, AbMelee] [-1, -1..]+                 $ EM.fromList+                 $ zip [AbApply, AbDisplace, AbMoveItem, AbMelee] [-1, -1..]                , AddArmorMelee 90, AddArmorRanged 90 ]   , ieffects = []   , ifeature = [Durable, Identified]@@ -419,6 +453,7 @@   , iverbHit = "thud"   , iweight  = 80000   , iaspects = [ AddMaxHP 10, AddMaxCalm 60, AddSpeed 20+               , AddSkills $ EM.insert AbProject (-1) robotSkillMalus                , AddSmell 2 ]   , ieffects = []   , ifeature = [Durable, Identified]@@ -455,6 +490,7 @@   , iverbHit = "thud"   , iweight  = 80000   , iaspects = [ AddMaxHP 20, AddMaxCalm 60, AddSpeed 30+               , AddSkills $ EM.insert AbProject 1 robotSkillMalus                , AddSight 3, AddLight 3 ]  -- light can't be turned off   , ieffects = []   , ifeature = [Durable, Identified]@@ -473,6 +509,7 @@   , iverbHit = "thud"   , iweight  = 800000   , iaspects = [ AddMaxHP 80, AddMaxCalm 60, AddSpeed 20+               , AddSkills $ EM.insert AbProject 1 robotSkillMalus                , AddSight 3, AddLight 4 ]  -- light can't be turned off   , ieffects = []   , ifeature = [Durable, Identified]
+ GameDefinition/Content/ItemKindBlast.hs view
@@ -0,0 +1,460 @@+-- Copyright (c) 2008--2011 Andres Loeh, 2010--2014 Mikolaj Konarski+-- This file is a part of the computer game Allure of the Stars+-- and is released under the terms of the GNU Affero General Public License.+-- For license and copyright information, see the file LICENSE.+--+-- | Blast definitions.+module Content.ItemKindBlast ( blasts ) where++import Game.LambdaHack.Common.Color+import Game.LambdaHack.Common.Dice+import Game.LambdaHack.Common.Flavour+import Game.LambdaHack.Common.Misc+import Game.LambdaHack.Common.Msg+import Game.LambdaHack.Content.ItemKind++blasts :: [ItemKind]+blasts =+  [burningOil2, burningOil3, burningOil4, explosionBlast2, explosionBlast10, explosionBlast20, firecracker2, firecracker3, firecracker4, firecracker5, firecracker6, firecracker7, fragrance, pheromone, mistHealing, mistHealing2, mistWounding, distortion, waste, glassPiece, smoke, boilingWater, glue, spark, mistAntiSlow, mistAntidote, mistStrength, mistWeakness, protectingBalm, redPaint, hasteSpray, slownessSpray, eyeDrop, smellyDroplet, whiskeySpray]++burningOil2,    burningOil3, burningOil4, explosionBlast2, explosionBlast10, explosionBlast20, firecracker2, firecracker3, firecracker4, firecracker5, firecracker6, firecracker7, fragrance, pheromone, mistHealing, mistHealing2, mistWounding, distortion, waste, glassPiece, smoke, boilingWater, glue, spark, mistAntiSlow, mistAntidote, mistStrength, mistWeakness, protectingBalm, redPaint, hasteSpray, slownessSpray, eyeDrop, smellyDroplet, whiskeySpray :: ItemKind++-- * Parameterized immediate effect blasts++burningOil :: Int -> ItemKind+burningOil n = ItemKind+  { isymbol  = '*'+  , iname    = "burning oil"+  , ifreq    = [(toGroupName $ "burning oil" <+> tshow n, 1)]+  , iflavour = zipFancy [BrYellow]+  , icount   = intToDice (n * 4)+  , irarity  = [(1, 1)]+  , iverbHit = "burn"+  , iweight  = 1+  , iaspects = [AddLight 2]+  , ieffects = [ Burn (n `div` 2)+               , Paralyze (intToDice $ n `div` 2) ]  -- tripping on oil+  , ifeature = [ toVelocity (min 100 $ n * 7)+               , Fragile, Identified ]+  , idesc    = "Sticky oil, burning brightly."+  , ikit     = []+  }+burningOil2 = burningOil 2+burningOil3 = burningOil 3+burningOil4 = burningOil 4+explosionBlast :: Int -> ItemKind+explosionBlast n = ItemKind+  { isymbol  = '*'+  , iname    = "blast"+  , ifreq    = [(toGroupName $ "blast" <+> tshow n, 1)]+  , iflavour = zipPlain [BrRed]+  , icount   = 12  -- strong, but few, so not always hits target+  , irarity  = [(1, 1)]+  , iverbHit = "tear apart"+  , iweight  = 1+  , iaspects = [AddLight $ intToDice n]+  , ieffects = [RefillHP (- n `div` 2)]+               ++ [DropBestWeapon | n > 2]+               ++ [DropItem COrgan "temporary conditions" True | n >= 10]+  , ifeature = [Fragile, toLinger 10, Identified]+  , idesc    = ""+  , ikit     = []+  }+explosionBlast2 = explosionBlast 2+explosionBlast10 = explosionBlast 10+explosionBlast20 = explosionBlast 20+firecracker :: Int -> ItemKind+firecracker n = ItemKind+  { isymbol  = '*'+  , iname    = "firecracker"+  , ifreq    = [(toGroupName $ "firecracker" <+> tshow n, 1)]+  , iflavour = zipPlain [brightCol !! (n `mod` length brightCol)]+  , icount   = intToDice (n `div` 6) + d (n `div` 2)+  , irarity  = [(1, 1)]+  , iverbHit = "crack"+  , iweight  = 1+  , iaspects = [AddLight $ intToDice $ n `div` 2]+  , ieffects = [ Burn 1 | n > 5 ]+               ++ [ OnSmash (Explode $ toGroupName+                             $ "firecracker" <+> tshow (n - 1))+                  | n > 2 ]+  , ifeature = [ ToThrow $ ThrowMod (10 + 3 * n) (10 + 100 `div` n)+               , Fragile, Identified ]+  , idesc    = ""+  , ikit     = []+  }+firecracker7 = firecracker 7+firecracker6 = firecracker 6+firecracker5 = firecracker 5+firecracker4 = firecracker 4+firecracker3 = firecracker 3+firecracker2 = firecracker 2++-- * Assorted immediate effect blasts++fragrance = ItemKind+  { isymbol  = '\''+  , iname    = "fragrance"+  , ifreq    = [("fragrance", 1)]+  , iflavour = zipFancy [Magenta]+  , icount   = 15+  , irarity  = [(1, 1)]+  , iverbHit = "engulf"+  , iweight  = 1+  , iaspects = []+  , ieffects = [Impress]+  , ifeature = [ toVelocity 13  -- the slowest that travels at least 2 steps+               , Fragile, Identified ]+  , idesc    = ""+  , ikit     = []+  }+pheromone = ItemKind+  { isymbol  = '\''+  , iname    = "musky whiff"+  , ifreq    = [("pheromone", 1)]+  , iflavour = zipFancy [BrMagenta]+  , icount   = 8+  , irarity  = [(1, 1)]+  , iverbHit = "tempt"+  , iweight  = 1+  , iaspects = []+  , ieffects = [Dominate]+  , ifeature = [ toVelocity 13  -- the slowest that travels at least 2 steps+               , Fragile, Identified ]+  , idesc    = ""+  , ikit     = []+  }+mistHealing = ItemKind+  { isymbol  = '\''+  , iname    = "mist"+  , ifreq    = [("healing mist", 1)]+  , iflavour = zipFancy [White]+  , icount   = 11+  , irarity  = [(1, 1)]+  , iverbHit = "revitalize"+  , iweight  = 1+  , iaspects = [AddLight 1]+  , ieffects = [RefillHP 2]+  , ifeature = [ toVelocity 7  -- the slowest that gets anywhere (1 step only)+               , Fragile, Identified ]+  , idesc    = ""+  , ikit     = []+  }+mistHealing2 = ItemKind+  { isymbol  = '\''+  , iname    = "mist"+  , ifreq    = [("healing mist 2", 1)]+  , iflavour = zipFancy [White]+  , icount   = 12+  , irarity  = [(1, 1)]+  , iverbHit = "revitalize"+  , iweight  = 1+  , iaspects = [AddLight 2]+  , ieffects = [RefillHP 4]+  , ifeature = [ toVelocity 7  -- the slowest that gets anywhere (1 step only)+               , Fragile, Identified ]+  , idesc    = ""+  , ikit     = []+  }+mistWounding = ItemKind+  { isymbol  = '\''+  , iname    = "mist"+  , ifreq    = [("wounding mist", 1)]+  , iflavour = zipFancy [White]+  , icount   = 13+  , irarity  = [(1, 1)]+  , iverbHit = "devitalize"+  , iweight  = 1+  , iaspects = []+  , ieffects = [RefillHP (-2)]+  , ifeature = [ toVelocity 7  -- the slowest that gets anywhere (1 step only)+               , Fragile, Identified ]+  , idesc    = ""+  , ikit     = []+  }+distortion = ItemKind+  { isymbol  = 'v'+  , iname    = "vortex"+  , ifreq    = [("distortion", 1)]+  , iflavour = zipFancy [White]+  , icount   = 4+  , irarity  = [(1, 1)]+  , iverbHit = "engulf"+  , iweight  = 1+  , iaspects = []+  , ieffects = [Teleport $ 15 + d 10]+  , ifeature = [ toVelocity 7  -- the slowest that gets anywhere (1 step only)+               , Fragile, Identified ]+  , idesc    = ""+  , ikit     = []+  }+waste = ItemKind+  { isymbol  = '*'+  , iname    = "waste"+  , ifreq    = [("waste", 1)]+  , iflavour = zipPlain [Brown]+  , icount   = 10+  , irarity  = [(1, 1)]+  , iverbHit = "splosh"+  , iweight  = 50+  , iaspects = []+  , ieffects = [RefillHP (-1)]+  , ifeature = [ ToThrow $ ThrowMod 28 50+               , Fragile, Identified ]+  , idesc    = ""+  , ikit     = []+  }+glassPiece = ItemKind  -- when blowing up windows+  { isymbol  = '*'+  , iname    = "glass piece"+  , ifreq    = [("glass piece", 1)]+  , iflavour = zipPlain [BrBlue]+  , icount   = 17+  , irarity  = [(1, 1)]+  , iverbHit = "cut"+  , iweight  = 10+  , iaspects = []+  , ieffects = [Hurt (1 * d 1)]+  , ifeature = [toLinger 20, Fragile, Identified]+  , idesc    = ""+  , ikit     = []+  }+smoke = ItemKind  -- when stuff burns out+  { isymbol  = '\''+  , iname    = "smoke"+  , ifreq    = [("smoke", 1)]+  , iflavour = zipPlain [BrBlack]+  , icount   = 19+  , irarity  = [(1, 1)]+  , iverbHit = "choke"+  , iweight  = 1+  , iaspects = []+  , ieffects = []+  , ifeature = [ toVelocity 21, Fragile, Identified ]+  , idesc    = ""+  , ikit     = []+  }+boilingWater = ItemKind+  { isymbol  = '*'+  , iname    = "boiling water"+  , ifreq    = [("boiling water", 1)]+  , iflavour = zipPlain [BrWhite]+  , icount   = 10+  , irarity  = [(1, 1)]+  , iverbHit = "boil"+  , iweight  = 5+  , iaspects = []+  , ieffects = [Burn 1]+  , ifeature = [toVelocity 50, Fragile, Identified]+  , idesc    = ""+  , ikit     = []+  }+glue = ItemKind+  { isymbol  = '*'+  , iname    = "sticky foam"+  , ifreq    = [("glue", 1)]+  , iflavour = zipPlain [BrYellow]+  , icount   = 14+  , irarity  = [(1, 1)]+  , iverbHit = "glue"+  , iweight  = 20+  , iaspects = []+  , ieffects = [Paralyze (3 + d 3)]+  , ifeature = [toVelocity 40, Fragile, Identified]+  , idesc    = ""+  , ikit     = []+  }+spark = ItemKind+  { isymbol  = '\''+  , iname    = "spark"+  , ifreq    = [("spark", 1)]+  , iflavour = zipPlain [BrYellow]+  , icount   = 18+  , irarity  = [(1, 1)]+  , iverbHit = "burn"+  , iweight  = 1+  , iaspects = [AddLight 4]+  , ieffects = [Burn 1]+  , ifeature = [Fragile, toLinger 10, Identified]+  , idesc    = ""+  , ikit     = []+  }+mistAntiSlow = ItemKind+  { isymbol  = '\''+  , iname    = "mist"+  , ifreq    = [("anti-slow mist", 1)]+  , iflavour = zipPlain [BrRed]+  , icount   = 11+  , irarity  = [(1, 1)]+  , iverbHit = "propel"+  , iweight  = 1+  , iaspects = []+  , ieffects = [DropItem COrgan "slow 10" True]+  , ifeature = [ toVelocity 7  -- the slowest that gets anywhere (1 step only)+               , Fragile, Identified ]+  , idesc    = ""+  , ikit     = []+  }+mistAntidote = ItemKind+  { isymbol  = '\''+  , iname    = "mist"+  , ifreq    = [("antidote mist", 1)]+  , iflavour = zipPlain [BrBlue]+  , icount   = 11+  , irarity  = [(1, 1)]+  , iverbHit = "cure"+  , iweight  = 1+  , iaspects = []+  , ieffects = [DropItem COrgan "poisoned" True]+  , ifeature = [ toVelocity 7  -- the slowest that gets anywhere (1 step only)+               , Fragile, Identified ]+  , idesc    = ""+  , ikit     = []+  }++-- * Assorted temporary condition blasts++mistStrength = ItemKind+  { isymbol  = '\''+  , iname    = "mist"+  , ifreq    = [("strength mist", 1)]+  , iflavour = zipFancy [Red]+  , icount   = 11+  , irarity  = [(1, 1)]+  , iverbHit = "strengthen"+  , iweight  = 1+  , iaspects = []+  , ieffects = [toOrganActorTurn "strengthened" (3 + d 3)]+  , ifeature = [ toVelocity 7  -- the slowest that gets anywhere (1 step only)+               , Fragile, Identified ]+  , idesc    = ""+  , ikit     = []+  }+mistWeakness = ItemKind+  { isymbol  = '\''+  , iname    = "mist"+  , ifreq    = [("weakness mist", 1)]+  , iflavour = zipFancy [Blue]+  , icount   = 12+  , irarity  = [(1, 1)]+  , iverbHit = "weaken"+  , iweight  = 1+  , iaspects = []+  , ieffects = [toOrganGameTurn "weakened" (3 + d 3)]+  , ifeature = [ toVelocity 7  -- the slowest that gets anywhere (1 step only)+               , Fragile, Identified ]+  , idesc    = ""+  , ikit     = []+  }+protectingBalm = ItemKind+  { isymbol  = '\''+  , iname    = "balm droplet"+  , ifreq    = [("protecting balm", 1)]+  , iflavour = zipPlain [Brown]+  , icount   = 13+  , irarity  = [(1, 1)]+  , iverbHit = "balm"+  , iweight  = 1+  , iaspects = []+  , ieffects = [toOrganActorTurn "protected" (3 + d 3)]+  , ifeature = [ toVelocity 13  -- the slowest that travels at least 2 steps+               , Fragile, Identified ]+  , idesc    = ""+  , ikit     = []+  }+redPaint = ItemKind+  { isymbol  = '\''+  , iname    = "red paint"+  , ifreq    = [("red paint", 1)]+  , iflavour = zipPlain [BrRed]+  , icount   = 14+  , irarity  = [(1, 1)]+  , iverbHit = "paint"+  , iweight  = 1+  , iaspects = []+  , ieffects = [toOrganGameTurn "painted red" (3 + d 3)]+  , ifeature = [ toVelocity 13  -- the slowest that travels at least 2 steps+               , Fragile, Identified ]+  , idesc    = ""+  , ikit     = []+  }+hasteSpray = ItemKind+  { isymbol  = '\''+  , iname    = "haste spray"+  , ifreq    = [("haste spray", 1)]+  , iflavour = zipPlain [BrRed]+  , icount   = 15+  , irarity  = [(1, 1)]+  , iverbHit = "haste"+  , iweight  = 1+  , iaspects = []+  , ieffects = [toOrganActorTurn "fast 20" (3 + d 3)]+  , ifeature = [ toVelocity 13  -- the slowest that travels at least 2 steps+               , Fragile, Identified ]+  , idesc    = ""+  , ikit     = []+  }+slownessSpray = ItemKind+  { isymbol  = '\''+  , iname    = "slowness spray"+  , ifreq    = [("slowness spray", 1)]+  , iflavour = zipPlain [BrBlue]+  , icount   = 16+  , irarity  = [(1, 1)]+  , iverbHit = "slow"+  , iweight  = 1+  , iaspects = []+  , ieffects = [toOrganGameTurn "slow 10" (3 + d 3)]+  , ifeature = [ toVelocity 13  -- the slowest that travels at least 2 steps+               , Fragile, Identified ]+  , idesc    = ""+  , ikit     = []+  }+eyeDrop = ItemKind+  { isymbol  = '\''+  , iname    = "eye drop"+  , ifreq    = [("eye drop", 1)]+  , iflavour = zipPlain [BrGreen]+  , icount   = 17+  , irarity  = [(1, 1)]+  , iverbHit = "cleanse"+  , iweight  = 1+  , iaspects = []+  , ieffects = [toOrganActorTurn "far-sighted" (3 + d 3)]+  , ifeature = [ toVelocity 13  -- the slowest that travels at least 2 steps+               , Fragile, Identified ]+  , idesc    = ""+  , ikit     = []+  }+smellyDroplet = ItemKind+  { isymbol  = '\''+  , iname    = "smelly droplet"+  , ifreq    = [("smelly droplet", 1)]+  , iflavour = zipPlain [Blue]+  , icount   = 18+  , irarity  = [(1, 1)]+  , iverbHit = "sensitize"+  , iweight  = 1+  , iaspects = []+  , ieffects = [toOrganActorTurn "keen-smelling" (3 + d 3)]+  , ifeature = [ toVelocity 13  -- the slowest that travels at least 2 steps+               , Fragile, Identified ]+  , idesc    = ""+  , ikit     = []+  }+whiskeySpray = ItemKind+  { isymbol  = '\''+  , iname    = "whiskey spray"+  , ifreq    = [("whiskey spray", 1)]+  , iflavour = zipPlain [Brown]+  , icount   = 19+  , irarity  = [(1, 1)]+  , iverbHit = "inebriate"+  , iweight  = 1+  , iaspects = []+  , ieffects = [toOrganActorTurn "drunk" (3 + d 3)]+  , ifeature = [ toVelocity 13  -- the slowest that travels at least 2 steps+               , Fragile, Identified ]+  , idesc    = ""+  , ikit     = []+  }
GameDefinition/Content/ItemKindOrgan.hs view
@@ -8,7 +8,6 @@  import Game.LambdaHack.Common.Color import Game.LambdaHack.Common.Dice-import Game.LambdaHack.Common.Effect import Game.LambdaHack.Common.Flavour import Game.LambdaHack.Common.Misc import Game.LambdaHack.Common.Msg@@ -16,43 +15,11 @@  organs :: [ItemKind] organs =-  [fist, foot, tentacle, claw, smallClaw, snout, sting, venomTooth, venomFang, largeTail, jaw, largeJaw, armoredSkin, speedGland2, speedGland4, speedGland6, speedGland8, speedGland10, eye2, eye3, eye4, eye5, nostril, thorn, razor, liveWire, boilingVent, explosionVent, fissure, wasteContainer]--fist,    foot, tentacle, claw, smallClaw, snout, sting, venomTooth, venomFang, largeTail, jaw, largeJaw, armoredSkin, speedGland2, speedGland4, speedGland6, speedGland8, speedGland10, eye2, eye3, eye4, eye5, nostril, thorn, razor, liveWire, boilingVent, explosionVent, fissure, wasteContainer :: ItemKind+  [fist, foot, claw, smallClaw, snout, jaw, largeJaw, tentacle, thorn, razor, fissure, sting, venomTooth, venomFang, largeTail, liveWire, armoredSkin, eye2, eye3, eye4, eye5, nostril, speedGland2, speedGland4, speedGland6, speedGland8, speedGland10, boilingVent, explosionVent, wasteContainer, bonusHP] --- * Parameterized organs+fist,    foot, claw, smallClaw, snout, jaw, largeJaw, tentacle, thorn, razor, fissure, sting, venomTooth, venomFang, largeTail, liveWire, armoredSkin, eye2, eye3, eye4, eye5, nostril, speedGland2, speedGland4, speedGland6, speedGland8, speedGland10, boilingVent, explosionVent, wasteContainer, bonusHP :: ItemKind -speedGland :: Int -> ItemKind-speedGland n = fist-  { iname    = "speed gland"-  , ifreq    = [(toGroupName $ "speed gland" <+> tshow n, 100)]-  , icount   = 1-  , iverbHit = "spit at"-  , iaspects = [AddSpeed $ intToDice n, Periodic $ intToDice n]-  , ieffects = [RefillHP 1]-  , ifeature = [Durable, Identified]-  , idesc    = ""-  }-speedGland2 = speedGland 2-speedGland4 = speedGland 4-speedGland6 = speedGland 6-speedGland8 = speedGland 8-speedGland10 = speedGland 10-eye :: Int -> ItemKind-eye n = fist-  { iname    = "eye"-  , ifreq    = [(toGroupName $ "eye" <+> tshow n, 100)]-  , icount   = 2-  , iverbHit = "glare at"-  , iaspects = [AddSight (intToDice n)]-  , ieffects = []-  , ifeature = [Durable, Identified]-  , idesc    = ""-  }-eye2 = eye 2-eye3 = eye 3-eye4 = eye 4-eye5 = eye 5+-- Weapons  -- * Human weapon organs @@ -60,7 +27,7 @@   { isymbol  = '%'   , iname    = "fist"   , ifreq    = [("fist", 100)]-  , iflavour = zipPlain [BrRed]+  , iflavour = zipPlain [Red]   , icount   = 2   , irarity  = [(1, 1)]   , iverbHit = "punch"@@ -110,7 +77,7 @@   , ifreq    = [("jaw", 20)]   , icount   = 1   , iverbHit = "rip"-  , ieffects = [Hurt (5 * d 1)]+  , ieffects = [Hurt (4 * d 1)]   , idesc    = ""   } largeJaw = fist@@ -121,6 +88,9 @@   , ieffects = [Hurt (12 * d 1)]   , idesc    = ""   }++-- * Monster weapon organs+ tentacle = fist   { iname    = "tentacle"   , ifreq    = [("tentacle", 50)]@@ -138,6 +108,7 @@   , icount   = 7   , iverbHit = "impale"   , ieffects = [Hurt (1 * d 1)]+  , ifeature = [EqpSlot EqpSlotWeapon "", Identified]  -- not Durable   , idesc    = ""   } razor = fist@@ -161,7 +132,8 @@   , ifreq    = [("sting", 100)]   , icount   = 1   , iverbHit = "sting"-  , ieffects = [Burn 1, Paralyze 2]+  , iaspects = [Timeout $ 1 + d 5]+  , ieffects = [Burn 1, Recharging (Paralyze 3)]   , idesc    = ""   } venomTooth = fist@@ -169,15 +141,21 @@   , ifreq    = [("venom tooth", 100)]   , icount   = 2   , iverbHit = "bite"-  , ieffects = [Hurt (3 * d 1), Paralyze 3]+  , iaspects = [Timeout $ 5 + d 3]+  , ieffects = [ Hurt (3 * d 1)+               , Recharging (toOrganGameTurn "slow 10" (3 + d 3)) ]   , idesc    = ""   }+-- TODO: should also confer poison resistance, but current implementation+-- is too costly (poison removal each turn) venomFang = fist   { iname    = "venom fang"   , ifreq    = [("venom fang", 100)]   , icount   = 2   , iverbHit = "bite"-  , ieffects = [Hurt (3 * d 1)]  -- TODO: +12 damage or poison effect+  , iaspects = [Timeout $ 7 + d 5]+  , ieffects = [ Hurt (3 * d 1)+               , Recharging (toOrganNone "poisoned") ]   , idesc    = ""   } largeTail = fist@@ -185,7 +163,8 @@   , ifreq    = [("large tail", 50)]   , icount   = 1   , iverbHit = "knock"-  , ieffects = [Hurt (8 * d 1), PushActor (ThrowMod 400 25)]+  , iaspects = [Timeout $ 1 + d 3]+  , ieffects = [Hurt (8 * d 1), Recharging (PushActor (ThrowMod 400 25))]   , idesc    = ""   } liveWire = fist@@ -193,67 +172,109 @@   , ifreq    = [("live wire", 100)]   , icount   = 4   , iverbHit = "shock"-  , iaspects = []-  , ieffects = [Hurt (1 * d 1), Paralyze 1]+  , iaspects = [Timeout $ 2 + d 2]+  , ieffects = [Hurt (1 * d 1), Recharging (DropItem COrgan "temporary conditions" True)]   , idesc    = ""   } +-- Non-weapons+ -- * Armor organs -armoredSkin = fist-  { iname    = "armored skin"+armoredSkin = ItemKind+  { isymbol  = '%'+  , iname    = "armored skin"   , ifreq    = [("armored skin", 100)]+  , iflavour = zipPlain [Red]   , icount   = 1+  , irarity  = [(1, 1)]   , iverbHit = "bash"+  , iweight  = 2000   , iaspects = [AddArmorMelee 30, AddArmorRanged 30]   , ieffects = []   , ifeature = [Durable, Identified]   , idesc    = ""+  , ikit     = []   }  -- * Sense organs -nostril = fist+eye :: Int -> ItemKind+eye n = armoredSkin+  { iname    = "eye"+  , ifreq    = [(toGroupName $ "eye" <+> tshow n, 100)]+  , icount   = 2+  , iverbHit = "glare at"+  , iaspects = [AddSight (intToDice n)]+  , idesc    = ""+  }+eye2 = eye 2+eye3 = eye 3+eye4 = eye 4+eye5 = eye 5+nostril = armoredSkin   { iname    = "nostril"   , ifreq    = [("nostril", 100)]   , icount   = 2   , iverbHit = "snuff"   , iaspects = [AddSmell 1]-  , ieffects = []-  , ifeature = [Durable, Identified]   , idesc    = ""   }  -- * Assorted -boilingVent = fist+speedGland :: Int -> ItemKind+speedGland n = armoredSkin+  { iname    = "speed gland"+  , ifreq    = [(toGroupName $ "speed gland" <+> tshow n, 100)]+  , icount   = 1+  , iverbHit = "spit at"+  , iaspects = [ AddSpeed $ intToDice n+               , Periodic+               , Timeout $ intToDice $ 100 `div` n ]+  , ieffects = [Recharging (RefillHP 1)]+  , idesc    = ""+  }+speedGland2 = speedGland 2+speedGland4 = speedGland 4+speedGland6 = speedGland 6+speedGland8 = speedGland 8+speedGland10 = speedGland 10+boilingVent = armoredSkin   { iname    = "vent"   , ifreq    = [("boiling vent", 100)]   , icount   = 1   , iverbHit = "menace"-  , iaspects = [Periodic $ 1 + d 2]-  , ieffects = [Explode "boiling water"]-  , ifeature = [Durable, Identified]+  , iaspects = [Periodic, Timeout $ (3 + d 4) |*| 5]+  , ieffects = [Recharging (Explode "boiling water")]   , idesc    = ""   }-explosionVent = fist+explosionVent = armoredSkin   { iname    = "vent"   , ifreq    = [("explosion vent", 100)]   , icount   = 1   , iverbHit = "menace"-  , iaspects = [Periodic $ 2 + d 2]-  , ieffects = [Explode "explosion blast 20"]-  , ifeature = [Durable, Identified]+  , iaspects = [Periodic, Timeout $ (2 + d 4) |*| 5]+  , ieffects = [Recharging (Explode "blast 20")]   , idesc    = ""   }-wasteContainer = fist+wasteContainer = armoredSkin   { iname    = "waste container"   , ifreq    = [("waste container", 100)]   , icount   = 1   , iverbHit = "spill over"-  , iaspects = [Periodic 1]-  , ieffects = [ Summon [("mobile animal", 1)] $ 1 + dl 2, RefillHP 1-               , Explode "waste" ]-  , ifeature = [Durable, Identified]+  , iaspects = [Periodic, Timeout $ (5 + d 5) |*| 10]+  , ieffects = [ Recharging (Summon [("mobile animal", 1)] $ 1 + dl 2)+               , Recharging (RefillHP 1)+               , Recharging (Explode "waste") ]+  , idesc    = ""+  }+bonusHP = armoredSkin+  { iname    = "bonus HP"+  , ifreq    = [("bonus HP", 100)]+  , icount   = 1+  , iverbHit = "intimidate"+  , iweight  = 0+  , iaspects = [AddMaxHP 1]   , idesc    = ""   }
− GameDefinition/Content/ItemKindShrapnel.hs
@@ -1,261 +0,0 @@--- Copyright (c) 2008--2011 Andres Loeh, 2010--2014 Mikolaj Konarski--- This file is a part of the computer game Allure of the Stars--- and is released under the terms of the GNU Affero General Public License.--- For license and copyright information, see the file LICENSE.------ | Shrapnel definitions.-module Content.ItemKindShrapnel ( shrapnels ) where--import Game.LambdaHack.Common.Color-import Game.LambdaHack.Common.Dice-import Game.LambdaHack.Common.Effect-import Game.LambdaHack.Common.Flavour-import Game.LambdaHack.Common.Misc-import Game.LambdaHack.Common.Msg-import Game.LambdaHack.Content.ItemKind--shrapnels :: [ItemKind]-shrapnels =-  [fragrance, pheromone, firecracker2, firecracker3, firecracker4, firecracker5, firecracker6, firecracker7, mistHealing, mistHealing2, mistWounding, distortion, waste, burningOil2, burningOil3, burningOil4, explosionBlast10, explosionBlast20, glassPiece, smoke, boilingWater, glue]--fragrance,    pheromone, firecracker2, firecracker3, firecracker4, firecracker5, firecracker6, firecracker7, mistHealing, mistHealing2, mistWounding, distortion, waste, burningOil2, burningOil3, burningOil4, explosionBlast10, explosionBlast20, glassPiece, smoke, boilingWater, glue :: ItemKind---- * Parameterized shrapnel--burningOil :: Int -> ItemKind-burningOil n = ItemKind-  { isymbol  = '*'-  , iname    = "burning oil"-  , ifreq    = [(toGroupName $ "burning oil" <+> tshow n, 1)]-  , iflavour = zipFancy [BrYellow]-  , icount   = intToDice (n * 4)-  , irarity  = [(1, 1)]-  , iverbHit = "burn"-  , iweight  = 1-  , iaspects = [AddLight 2]-  , ieffects = [ Burn (n `div` 2)-               , Paralyze (intToDice $ n `div` 2) ]  -- tripping on oil-  , ifeature = [ toVelocity (min 100 $ n * 7)-               , Fragile, Identified ]-  , idesc    = "Sticky oil, burning brightly."-  , ikit     = []-  }-burningOil2 = burningOil 2-burningOil3 = burningOil 3-burningOil4 = burningOil 4-explosionBlast :: Int -> ItemKind-explosionBlast n = ItemKind-  { isymbol  = '*'-  , iname    = "explosion blast"-  , ifreq    = [(toGroupName $ "explosion blast" <+> tshow n, 1)]-  , iflavour = zipPlain [BrRed]-  , icount   = 12  -- strong, but few, so not always hits target-  , irarity  = [(1, 1)]-  , iverbHit = "tear apart"-  , iweight  = 1-  , iaspects = [AddLight $ intToDice n]-  , ieffects = [RefillHP (- n `div` 2), DropBestWeapon]-  , ifeature = [Fragile, toLinger 10, Identified]-  , idesc    = ""-  , ikit     = []-  }-explosionBlast10 = explosionBlast 10-explosionBlast20 = explosionBlast 20-firecracker :: Int -> ItemKind-firecracker n = ItemKind-  { isymbol  = '*'-  , iname    = "firecracker"-  , ifreq    = [(toGroupName $ "firecracker" <+> tshow n, 1)]-  , iflavour = zipPlain [stdCol !! (n `mod` length stdCol)]-  , icount   = intToDice $ 2 * n-  , irarity  = [(1, 1)]-  , iverbHit = "crack"-  , iweight  = 1-  , iaspects = [AddLight $ intToDice $ n `div` 2]-  , ieffects = [Burn 1, Explode $ toGroupName $ "firecracker" <+> tshow (n - 1)]-  , ifeature = [ ToThrow $ ThrowMod (n * 10) 20-               , Fragile, Identified ]-  , idesc    = ""-  , ikit     = []-  }-firecracker7 = firecracker 7-firecracker6 = firecracker 6-firecracker5 = firecracker 5-firecracker4 = firecracker 4-firecracker3 = firecracker 3-firecracker2 = firecracker 2---- * Assorted--fragrance = ItemKind-  { isymbol  = '\''-  , iname    = "fragrance"-  , ifreq    = [("fragrance", 1)]-  , iflavour = zipFancy [Magenta]-  , icount   = 15-  , irarity  = [(1, 1)]-  , iverbHit = "engulf"-  , iweight  = 1-  , iaspects = []-  , ieffects = [Impress]-  , ifeature = [ toVelocity 13  -- the slowest that travels at least 2 steps-               , Fragile, Identified ]-  , idesc    = ""-  , ikit     = []-  }-pheromone = ItemKind-  { isymbol  = '\''-  , iname    = "musky whiff"-  , ifreq    = [("pheromone", 1)]-  , iflavour = zipFancy [BrMagenta]-  , icount   = 8-  , irarity  = [(1, 1)]-  , iverbHit = "tempt"-  , iweight  = 1-  , iaspects = []-  , ieffects = [Dominate]-  , ifeature = [ toVelocity 13  -- the slowest that travels at least 2 steps-               , Fragile, Identified ]-  , idesc    = ""-  , ikit     = []-  }-mistHealing = ItemKind-  { isymbol  = '\''-  , iname    = "mist"-  , ifreq    = [("healing mist", 1)]-  , iflavour = zipFancy [White]-  , icount   = 11-  , irarity  = [(1, 1)]-  , iverbHit = "revitalize"-  , iweight  = 1-  , iaspects = [AddLight 1]-  , ieffects = [RefillHP 2]-  , ifeature = [ toVelocity 7  -- the slowest that gets anywhere (1 step only)-               , Fragile, Identified ]-  , idesc    = ""-  , ikit     = []-  }-mistHealing2 = ItemKind-  { isymbol  = '\''-  , iname    = "mist"-  , ifreq    = [("healing mist 2", 1)]-  , iflavour = zipFancy [White]-  , icount   = 12-  , irarity  = [(1, 1)]-  , iverbHit = "revitalize"-  , iweight  = 1-  , iaspects = [AddLight 2]-  , ieffects = [RefillHP 4]-  , ifeature = [ toVelocity 7  -- the slowest that gets anywhere (1 step only)-               , Fragile, Identified ]-  , idesc    = ""-  , ikit     = []-  }-mistWounding = ItemKind-  { isymbol  = '\''-  , iname    = "mist"-  , ifreq    = [("wounding mist", 1)]-  , iflavour = zipFancy [White]-  , icount   = 13-  , irarity  = [(1, 1)]-  , iverbHit = "devitalize"-  , iweight  = 1-  , iaspects = []-  , ieffects = [RefillHP (-2)]-  , ifeature = [ toVelocity 7  -- the slowest that gets anywhere (1 step only)-               , Fragile, Identified ]-  , idesc    = ""-  , ikit     = []-  }-distortion = ItemKind-  { isymbol  = 'v'-  , iname    = "vortex"-  , ifreq    = [("distortion", 1)]-  , iflavour = zipFancy [White]-  , icount   = 4-  , irarity  = [(1, 1)]-  , iverbHit = "engulf"-  , iweight  = 1-  , iaspects = []-  , ieffects = [Teleport $ 15 + d 10]-  , ifeature = [ toVelocity 7  -- the slowest that gets anywhere (1 step only)-               , Fragile, Identified ]-  , idesc    = ""-  , ikit     = []-  }-waste = ItemKind-  { isymbol  = '*'-  , iname    = "waste"-  , ifreq    = [("waste", 1)]-  , iflavour = zipPlain [Brown]-  , icount   = 10-  , irarity  = [(1, 1)]-  , iverbHit = "splosh"-  , iweight  = 50-  , iaspects = []-  , ieffects = [RefillHP (-1)]-  , ifeature = [ ToThrow $ ThrowMod 28 50-               , Fragile, Identified ]-  , idesc    = ""-  , ikit     = []-  }-glassPiece = ItemKind  -- when blowing up windows-  { isymbol  = '*'-  , iname    = "glass piece"-  , ifreq    = [("glass piece", 1)]-  , iflavour = zipPlain [BrBlue]-  , icount   = 17-  , irarity  = [(1, 1)]-  , iverbHit = "cut"-  , iweight  = 10-  , iaspects = []-  , ieffects = [Hurt (1 * d 1)]-  , ifeature = [toLinger 20, Fragile, Identified]-  , idesc    = ""-  , ikit     = []-  }-smoke = ItemKind  -- when stuff burns out-  { isymbol  = '\''-  , iname    = "smoke"-  , ifreq    = [("smoke", 1), ("firecracker 1", 1)]-  , iflavour = zipPlain [BrBlack]-  , icount   = 19-  , irarity  = [(1, 1)]-  , iverbHit = "choke"-  , iweight  = 1-  , iaspects = []-  , ieffects = []-  , ifeature = [ toVelocity 21, Fragile, Identified ]-  , idesc    = ""-  , ikit     = []-  }-boilingWater = ItemKind-  { isymbol  = '*'-  , iname    = "boiling water"-  , ifreq    = [("boiling water", 1)]-  , iflavour = zipPlain [BrWhite]-  , icount   = 9-  , irarity  = [(1, 1)]-  , iverbHit = "boil"-  , iweight  = 5-  , iaspects = []-  , ieffects = [Burn 1]-  , ifeature = [toVelocity 50, Fragile, Identified]-  , idesc    = ""-  , ikit     = []-  }-glue = ItemKind-  { isymbol  = '*'-  , iname    = "sticky foam"-  , ifreq    = [("glue", 1)]-  , iflavour = zipPlain [BrYellow]-  , icount   = 14-  , irarity  = [(1, 1)]-  , iverbHit = "glue"-  , iweight  = 20-  , iaspects = []-  , ieffects = [Paralyze (3 + d 3)]-  , ifeature = [toVelocity 40, Fragile, Identified]-  , idesc    = ""-  , ikit     = []-  }
+ GameDefinition/Content/ItemKindTemporary.hs view
@@ -0,0 +1,80 @@+-- Copyright (c) 2008--2011 Andres Loeh, 2010--2014 Mikolaj Konarski+-- This file is a part of the computer game Allure of the Stars+-- and is released under the terms of the GNU Affero General Public License.+-- For license and copyright information, see the file LICENSE.+--+-- | Temporary aspect pseudo-item definitions.+module Content.ItemKindTemporary ( temporaries ) where++import Data.Text (Text)++import Game.LambdaHack.Common.Color+import Game.LambdaHack.Common.Dice+import Game.LambdaHack.Common.Flavour+import Game.LambdaHack.Common.Misc+import Game.LambdaHack.Common.Msg+import Game.LambdaHack.Content.ItemKind++temporaries :: [ItemKind]+temporaries =+  [tmpStrengthened, tmpWeakened, tmpProtected, tmpPaintedRed, tmpFast20, tmpSlow10, tmpFarSighted, tmpKeenSmelling, tmpDrunk, tmpRegenerating, tmpPoisoned, tmpSlow10Resistant, tmpPoisonResitant]++tmpStrengthened,    tmpWeakened, tmpProtected, tmpPaintedRed, tmpFast20, tmpSlow10, tmpFarSighted, tmpKeenSmelling, tmpDrunk, tmpRegenerating, tmpPoisoned, tmpSlow10Resistant, tmpPoisonResitant :: ItemKind++-- The @name@ is be used in item description, so it should be an adjective+-- describing the temporary set of aspects.+tmpAs :: Text -> [Aspect Dice] -> ItemKind+tmpAs name aspects = ItemKind+  { isymbol  = '.'+  , iname    = name+  , ifreq    = [(toGroupName name, 1), ("temporary conditions", 1)]+  , iflavour = zipPlain [BrWhite]+  , icount   = 1+  , irarity  = [(1, 1)]+  , iverbHit = "affect"+  , iweight  = 1+  , iaspects = [Periodic, Timeout 1]  -- activates and vanishes soon,+                                      -- depending on initial timer setting+               ++ aspects+  , ieffects = let tmp = Temporary $ "be no longer" <+> name+               in [Recharging tmp, OnSmash tmp]+  , ifeature = [Identified]+  , idesc    = ""+  , ikit     = []+  }++tmpStrengthened = tmpAs "strengthened" [AddHurtMelee 20]+tmpWeakened = tmpAs "weakened" [AddHurtMelee (-20)]+tmpProtected = tmpAs "protected" [ AddArmorMelee 30+                                 , AddArmorRanged 30 ]+tmpPaintedRed = tmpAs "painted red" [ AddArmorMelee (-30)+                                    , AddArmorRanged (-30) ]+tmpFast20 = tmpAs "fast 20" [AddSpeed 20]+tmpSlow10 = tmpAs "slow 10" [AddSpeed (-10)]+tmpFarSighted = tmpAs "far-sighted" [AddSight 5]+tmpKeenSmelling = tmpAs "keen-smelling" [AddSmell 1]+tmpDrunk = tmpAs "drunk" [ AddHurtMelee 30  -- fury+                         , AddArmorMelee (-20)+                         , AddArmorRanged (-20)+                         , AddSight (-7)+                         ]+tmpRegenerating =+  let tmp = tmpAs "regenerating" []+  in tmp { icount = 7 + d 5+         , ieffects = [Recharging (RefillHP 1)] ++ ieffects tmp+         }+tmpPoisoned =+  let tmp = tmpAs "poisoned" []+  in tmp { icount = 7 + d 5+         , ieffects = [Recharging (RefillHP (-1))] ++ ieffects tmp+         }+tmpSlow10Resistant =+  let tmp = tmpAs "slow resistant" []+  in tmp { icount = 7 + d 5+         , ieffects = [Recharging (DropItem COrgan "slow 10" True)] ++ ieffects tmp+         }+tmpPoisonResitant =+  let tmp = tmpAs "poison resistant" []+  in tmp { icount = 7 + d 5+         , ieffects = [Recharging (DropItem COrgan "poisoned" True)] ++ ieffects tmp+         }
GameDefinition/Content/ModeKind.hs view
@@ -10,6 +10,7 @@  import Content.ModeKindPlayer import Game.LambdaHack.Common.ContentDef+import Game.LambdaHack.Common.Misc import Game.LambdaHack.Content.ModeKind  cdefs :: ContentDef ModeKind@@ -20,9 +21,9 @@   , validateSingle = validateSingleModeKind   , validateAll = validateAllModeKind   , content =-      [campaign, duel, skirmish, ambush, battle, safari, pvp, coop, defense]+      [campaign, duel, skirmish, ambush, battle, safari, pvp, coop, defense, screensaver]   }-campaign,        duel, skirmish, ambush, battle, safari, pvp, coop, defense :: ModeKind+campaign,        duel, skirmish, ambush, battle, safari, pvp, coop, defense, screensaver :: ModeKind  campaign = ModeKind   { msymbol = 'a'@@ -30,7 +31,7 @@   , mfreq   = [("campaign", 1)]   , mroster = rosterCampaign   , mcaves  = cavesCampaign-  , mdesc   = "You got stranded looting a once luxurious cruise liner and your current plan is to fight through, gathering your spoils, to the bridge at the giant spaceship's opposite end."+  , mdesc   = "You got stranded looting the blasted bridge of a once luxurious cruise liner. Your current plan is to fight through, gathering your spoils, to the shuttle airlock at the giant spaceship's uppermost deck. There are animal cries down below and ominous silence up above."   }  duel = ModeKind@@ -75,7 +76,7 @@   , mfreq   = [("safari", 1)]   , mroster = rosterSafari   , mcaves  = cavesSafari-  , mdesc   = "In this simulation you'll discover the joys of hunting the most exquisite of Earth's flora and fauna, both animal and semi-intelligent (exit at the bottommost level)."+  , mdesc   = "In this simulation you'll discover the joys of hunting the most exquisite of Earth's flora and fauna, both animal and semi-intelligent (exit at the uppermost level)."   }  pvp = ModeKind@@ -105,7 +106,17 @@   , mdesc   = "Don't let the half-witted humans derail your operation and flee, like the puny, naked, tentacle-less beasts that they are!"   } +screensaver = safari+  { mname   = "safari screensaver"+  , mfreq   = [("screensaver", 1), ("starting", 1)]+  , mroster = rosterSafari+      { rosterList = (head (rosterList rosterSafari))+                       {fleaderMode = LeaderAI $ AutoLeader False False }+                     : tail (rosterList rosterSafari)+      }+  } + rosterCampaign, rosterDuel, rosterSkirmish, rosterAmbush, rosterBattle, rosterSafari, rosterPvP, rosterCoop, rosterDefense :: Roster  rosterCampaign = Roster@@ -150,13 +161,13 @@ rosterBattle = Roster   { rosterList = [ playerSoldier { finitialActors = 5                                  , fentryLevel = 5 }-                 , playerMobileMonster { finitialActors = 30+                 , playerMobileMonster { finitialActors = 35                                        , fentryLevel = 5                                        , fneverEmpty = True }-                 , playerMobileAnimal { finitialActors = 10+                 , playerMobileAnimal { finitialActors = 20                                       , fentryLevel = 5                                       , fneverEmpty = True }-                 , playerMobileRobot { finitialActors = 10+                 , playerMobileRobot { finitialActors = 15                                      , fentryLevel = 5                                      , fneverEmpty = True } ]   , rosterEnemy = [ ("Armed Spacefarer Crew", "Alien Hierarchy")@@ -175,6 +186,7 @@                                      , fentryLevel = 4                                      , finitialActors = 15                                      , fleaderMode =+                                         -- no spawning and TFollow                                          LeaderUI $ AutoLeader False False }                  , playerCivilian { fname = "Hunam Convict Pack"                                   , fentryLevel = 4 }@@ -187,7 +199,7 @@                                           "Animal Exquisite Herds and Packs"                                       , fneverEmpty = True                                       , fentryLevel = 10-                                      , finitialActors = 25 } ]+                                      , finitialActors = 30 } ]   , rosterEnemy = [ ("Alien Tourist Office", "Hunam Convict Pack")                   , ("Alien Tourist Office",                      "Animal Magnificent Specimen Variety")@@ -213,8 +225,10 @@                                   , fleaderMode = LeaderNull }                  , playerAntiHero { fname = "Green" }                  , playerAnimal { fhasUI = True }-                 , playerMonster { fname = "Alien Hierarchy" }+                 , playerMonster { fname = "Alien Hierarchy"+                                 , finitialActors = 3 }                  , playerMonster { fname = "Leaderless Alien Hierarchy"+                                 , finitialActors = 1                                  , fleaderMode = LeaderNull }                  , playerRobot ]   , rosterEnemy = [ ("Coral", "Alien Hierarchy")@@ -229,9 +243,8 @@                  , ("Green", "Leaderless Alien Hierarchy") ] }  rosterDefense = Roster-  { rosterList = [ playerAntiMonster { finitialActors = 1 }-                 , playerAntiHero { fname = "Yellow"-                                  , finitialActors = 10 }+  { rosterList = [ playerAntiMonster+                 , playerAntiHero {fname = "Yellow"}                  , playerAnimal                  , playerRobot ]   , rosterEnemy = [ ("Yellow", "Alien Hierarchy")@@ -245,8 +258,11 @@ cavesCampaign, cavesSkirmish, cavesAmbush, cavesBattle, cavesSafari :: Caves  cavesCampaign = IM.fromList-                $ [(1, ("caveRogue", Nothing))]-                  ++ zip [2..11] (repeat ("campaign random", Nothing))+                $ [(1, ("shallow random 1", Nothing))]+                  ++ [(2, ("shallow random 2", Nothing))]+                  ++ [(3, ("caveBridge", Nothing))]+                  ++ [(4, ("caveNoise", Nothing))]+                  ++ zip [5..11] (repeat ("campaign random", Nothing))                   ++ [(12, ("caveNoise", Just True))]  cavesSkirmish = IM.fromList [(3, ("caveSkirmish", Nothing))]
GameDefinition/Content/ModeKindPlayer.hs view
@@ -13,9 +13,11 @@ import qualified Data.EnumMap.Strict as EM  import Game.LambdaHack.Common.Ability+import Game.LambdaHack.Common.Dice+import Game.LambdaHack.Common.Misc import Game.LambdaHack.Content.ModeKind -playerHero, playerSoldier, playerAntiHero, playerCivilian, playerMonster, playerMobileMonster, playerAntiMonster, playerAnimal, playerMobileAnimal, playerRobot, playerMobileRobot, playerHorror :: Player+playerHero, playerSoldier, playerAntiHero, playerCivilian, playerMonster, playerMobileMonster, playerAntiMonster, playerAnimal, playerMobileAnimal, playerRobot, playerMobileRobot, playerHorror :: Player Dice  playerHero = Player   { fname = "Spacefarer Crew"@@ -26,7 +28,7 @@   , fhasNumbers = True   , fhasGender = True   , ftactic = TExplore-  , fentryLevel = 1+  , fentryLevel = 3   , finitialActors = 3   , fleaderMode = LeaderUI $ AutoLeader False False   , fhasUI = True@@ -38,7 +40,7 @@   }  playerAntiHero = playerHero-  { fleaderMode = LeaderAI $ AutoLeader False False+  { fleaderMode = LeaderAI $ AutoLeader True False   , fhasUI = False   } @@ -52,7 +54,7 @@   , fhasGender = True   , ftactic = TPatrol   , fentryLevel = 1-  , finitialActors = 3+  , finitialActors = d 2 + 1   , fleaderMode = LeaderNull  -- unorganized   , fhasUI = False   }@@ -67,8 +69,8 @@   , fhasGender = False   , ftactic = TExplore   , fentryLevel = 4-  , finitialActors = 3-  , fleaderMode = LeaderAI $ AutoLeader True False+  , finitialActors = 0+  , fleaderMode = LeaderAI $ AutoLeader True True   , fhasUI = False   } @@ -76,19 +78,20 @@  playerAntiMonster = playerMonster   { fhasUI = True+  , fleaderMode = LeaderUI $ AutoLeader True True   }  playerAnimal = Player   { fname = "Animal Kingdom"   , fgroup = "animal"-  , fskillsOther = animalSkills+  , fskillsOther = unitSkills   , fcanEscape = False   , fneverEmpty = False   , fhasNumbers = False   , fhasGender = False   , ftactic = TRoam  -- can't pick up, so no point exploring-  , fentryLevel = 2-  , finitialActors = 3+  , fentryLevel = 3+  , finitialActors = 1 + d 2   , fleaderMode = LeaderNull   , fhasUI = False   }@@ -99,14 +102,14 @@ playerRobot = Player   { fname = "Robot Anarchy"   , fgroup = "robot"-  , fskillsOther = robotSkills+  , fskillsOther = unitSkills   , fcanEscape = False   , fneverEmpty = False   , fhasNumbers = False   , fhasGender = False   , ftactic = TFollow  -- coordinated via net, follow alien leader (TODO)   , fentryLevel = 3-  , finitialActors = 3+  , finitialActors = 1 + d 2   , fleaderMode = LeaderNull   , fhasUI = False   }@@ -135,15 +138,14 @@   , fhasUI = False   } +minusHundred, meleeAdjacent, _meleeAndRanged :: Skills -meleeAdjacent, _meleeAndRanged, animalSkills, robotSkills :: Skills+-- To make sure weak items can't override move-only-leader, etc.+minusHundred = EM.fromList $ zip [minBound..maxBound] [-100, -100..] -meleeAdjacent = EM.fromList $ zip [AbWait, AbMelee] [1, 1..]+meleeAdjacent = addSkills minusHundred+                $ EM.fromList $ zip [AbWait, AbMelee] [101, 101..]  -- Melee and reaction fire.-_meleeAndRanged = EM.fromList $ zip [AbWait, AbMelee, AbProject] [1, 1..]--animalSkills =-  EM.fromList $ zip [AbMove, AbMelee, AbAlter, AbWait, AbTrigger] [1, 1..]--robotSkills = EM.delete AbApply unitSkills+_meleeAndRanged = addSkills minusHundred+                  $ EM.fromList $ zip [AbWait, AbMelee, AbProject] [101, 101..]
GameDefinition/Content/TileKind.hs view
@@ -12,10 +12,9 @@  import Game.LambdaHack.Common.Color import Game.LambdaHack.Common.ContentDef-import qualified Game.LambdaHack.Common.Effect as Effect-import Game.LambdaHack.Common.Feature import Game.LambdaHack.Common.Misc import Game.LambdaHack.Common.Msg+import qualified Game.LambdaHack.Content.ItemKind as IK import Game.LambdaHack.Content.TileKind  cdefs :: ContentDef TileKind@@ -48,12 +47,13 @@                , ("legendLit", 100), ("legendDark", 100) ]   , tcolor   = BrWhite   , tcolor2  = defFG-  , tfeature = [Cause $ Effect.CreateItem 1, ChangeTo "cachable"]+  , tfeature = [ Cause $ IK.CreateItem CGround "useful" IK.TimerNone+               , ChangeTo "cachable" ]   } hardRock = TileKind   { tsymbol  = '#'   , tname    = "outer hull"-  , tfreq    = [("basic outer fence", 100), ("oriels fence", 98)]+  , tfreq    = [("basic outer fence", 100), ("oriels fence", 96)]   , tcolor   = BrBlack   , tcolor2  = BrBlack   , tfeature = [Impenetrable]@@ -69,7 +69,7 @@ oriel = TileKind   { tsymbol  = '\''   , tname    = "oriel"-  , tfreq    = [("oriels fence", 2)]+  , tfreq    = [("oriels fence", 4)]   , tcolor   = White   , tcolor2  = Black   , tfeature = [Dark, Impenetrable]@@ -145,7 +145,7 @@   , tfreq    = []  -- TODO: [("legendLit", 100), ("legendDark", 100)]   , tcolor   = BrWhite   , tcolor2  = defFG-  , tfeature = [Walkable, Clear, NoItem, NoActor, Cause $ Effect.Ascend 1]+  , tfeature = [Walkable, Clear, NoItem, NoActor, Cause $ IK.Ascend 1]   } stairsDown = TileKind   { tsymbol  = '>'@@ -153,7 +153,7 @@   , tfreq    = []  -- TODO: [("legendLit", 100), ("legendDark", 100)]   , tcolor   = BrWhite   , tcolor2  = defFG-  , tfeature = [Walkable, Clear, NoItem, NoActor, Cause $ Effect.Ascend (-1)]+  , tfeature = [Walkable, Clear, NoItem, NoActor, Cause $ IK.Ascend (-1)]   } escapeUp = TileKind   { tsymbol  = '<'@@ -161,7 +161,7 @@   , tfreq    = [("legendLit", 100), ("legendDark", 100)]   , tcolor   = BrYellow   , tcolor2  = BrYellow-  , tfeature = [Walkable, Clear, NoItem, NoActor, Cause $ Effect.Escape 1]+  , tfeature = [Walkable, Clear, NoItem, NoActor, Cause $ IK.Escape 1]   } escapeDown = TileKind   { tsymbol  = '>'@@ -169,7 +169,7 @@   , tfreq    = [("legendLit", 100), ("legendDark", 100)]   , tcolor   = BrYellow   , tcolor2  = BrYellow-  , tfeature = [Walkable, Clear, NoItem, NoActor, Cause $ Effect.Escape (-1)]+  , tfeature = [Walkable, Clear, NoItem, NoActor, Cause $ IK.Escape (-1)]   } liftUp = TileKind   { tsymbol  = '<'@@ -177,7 +177,7 @@   , tfreq    = [("legendLit", 100), ("legendDark", 100)]   , tcolor   = BrCyan   , tcolor2  = BrCyan-  , tfeature = [Walkable, Clear, NoItem, NoActor, Cause $ Effect.Ascend 1]+  , tfeature = [Walkable, Clear, NoItem, NoActor, Cause $ IK.Ascend 1]   } lift = TileKind   { tsymbol  = '<'@@ -186,8 +186,8 @@   , tcolor   = BrBlue   , tcolor2  = BrBlue   , tfeature = [ Walkable, Clear, NoItem, NoActor-               , Cause $ Effect.Ascend 1-               , Cause $ Effect.Ascend (-1) ]+               , Cause $ IK.Ascend 1+               , Cause $ IK.Ascend (-1) ]   } liftDown = TileKind   { tsymbol  = '>'@@ -195,7 +195,7 @@   , tfreq    = [("legendLit", 100), ("legendDark", 100)]   , tcolor   = BrCyan   , tcolor2  = BrCyan-  , tfeature = [Walkable, Clear, NoItem, NoActor, Cause $ Effect.Ascend (-1)]+  , tfeature = [Walkable, Clear, NoItem, NoActor, Cause $ IK.Ascend (-1)]   } unknown = TileKind   { tsymbol  = ' '@@ -236,7 +236,7 @@   } floorRedLit = floorCorridorLit   { tname    = "emergency walkway"-  , tfreq    = [("trailLit", 20)]+  , tfreq    = [("emergency walkway", 1), ("trailLit", 20)]   , tcolor   = BrRed   , tcolor2  = Red   , tfeature = Trail : tfeature floorCorridorLit@@ -256,7 +256,7 @@   makeDark :: TileKind -> TileKind-makeDark k = let darkText :: GroupName -> GroupName+makeDark k = let darkText :: GroupName TileKind -> GroupName TileKind                  darkText t = maybe t (toGroupName . (<> "Dark"))                               $ T.stripSuffix "Lit" $ tshow t                  darkFrequency = map (first darkText) $ tfreq k
GameDefinition/PLAYING.md view
@@ -40,8 +40,13 @@ HP (hit points, health). At the end, the personal target of the leader is described, in this case a basilisk monster, with hit points drawn as a bar. -The other status line describes the current location in relation to the party.+Weapon damage and other item stats are displayed using the dice notation `XdY`.+which means X rolls of Y-sided dice. A variant denoted 'XdsY' is additionally+scaled by the level depth in proportion to the maximal spaceship depth. +The second status line describes the current dungeon location in relation+to the party.+     5  Lofty hall   [33% seen] Cursor: exact spot (71,12)  p15 l10  First comes the depth of the current level and its name.@@ -147,9 +152,9 @@ automatically as soon as a monster comes into view). Once in targeting mode, you can move the targeting cursor with arrow keys and switch focus among enemies with `*` (or among friends, projectiles and enemies, depending-on targeting mode set by `/`). The details of the shared cursor position-and of the personal target are described at the bottom of the screen.-All targeting keys are listed below.+on targeting mode toggled by `/`). The details of the shared cursor position+and of the personal target are described in the status lines, at the bottom+of the screen. All targeting keys are listed below.                  keys           command                 KEYPAD_* and \ target enemy@@ -207,17 +212,7 @@                 CTRL-a         new Campaign game                 CTRL-d         cycle next game difficulty -There are also some debug, testing and cheat options and game modes-that can be specified on the command line when starting the game server.-Use at your own peril! :) Of these, you may find the screensaver game modes-the least spoilery and the most fun, e.g.: -    Allure --savePrefix test --newGame --noMore --maxFps 60 --automateAll --gameMode campaign --difficulty 1--The `--automateAll` option strictly corresponds to the `CTRL-A` command,-but most of the debug options have no corresponding commands.-- Monsters -------- @@ -237,12 +232,13 @@ This gives the opponent a free blow, but can improve the tactical situation or aid escape. -Slinging a missile at a target wounds it, consuming the weapon in the process.+Flinging a missile at a target wounds it, consuming the weapon in the process. You may propel any item in your equipment, inventory and on the ground-(press `?` to choose an item and press it again for a non-standard choice).-Only items of a few kinds inflict any damage, but some have other effects.-Whenever the monster's or hero's hit points reach zero, the combatant dies.-When the last hero dies, the game ends in defeat.+(press `?` to see appropriate items in a menu and press it again+for a non-standard choice). Only items of a few kinds inflict any damage,+but some have other effects. Whenever the monster's or hero's hit points+reach zero, the combatant dies. When the last hero dies, the game ends+in defeat.   On Winning and Dying
GameDefinition/config.ui.default view
@@ -4,14 +4,24 @@ ; ; For license and copyright information, see the file LICENSE. ; ; ; ; This is a commented out copy of the default UI settings config file-; ; that is embedded in the binary.-; ; A user config file can overrides these options. The game looks for it at-; ; ~/.Allure/config.ui.ini (or a similar path, depending on the OS).-; ; Warning: options are case-sensitive and only ';' for comments is permitted.+; ; that is embedded in the game binary. A user config file can override+; ; these options. Option names are case-sensitive and only ';' for comments+; ; is permitted.+; ;+; ; The game looks for the config file at the same path where saved games+; ; directory is located. E.g. on Linux the file is at+; ; ~/.Allure/config.ui.ini+; ; and on Windows it can be at+; ; C:\Documents And Settings\user\Application Data\Allure\config.ui.ini+; ; or at+; ; C:\Users\<username>\AppData\Roaming\Allure\config.ui.ini+; ; or elsewhere.  ; [extra_commands]-; ; A handy shorthand with Vi keys:+; ; A handy shorthand with Vi keys ; Macro_1 = ("comma", ([CmdItem], Macro "" ["g"]))+; ; Angband compatibility (accept target)+; Macro_2 = ("KP_Insert", ([CmdMeta], Macro "" ["Return"]))  ; [hero_names] ; HeroName_0 = ("Haskell Alvin", "he")@@ -25,7 +35,9 @@ ; [ui] ; movementViKeys_hjklyubn = False ; movementLaptopKeys_uk8o79jl = True-; font = "Terminus,Monospace normal normal normal normal 12"+; ; Monospace fonts that have fixed size regardless of boldness (on some OSes)+; font = "Terminus,DejaVu Sans Mono,Consolas,Courier New,Liberation Mono,Courier,FreeMono,Monospace normal normal normal normal 16"+; colorIsBold = True ; historyMax = 5000 ; maxFps = 15 ; noAnim = False
Makefile view
@@ -18,250 +18,285 @@ 	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --dumpInitRngs  xcfrontendCampaign:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --maxFps 60 --dumpInitRngs --automateAll --gameMode campaign --difficulty 1+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --maxFps 60 --dumpInitRngs --automateAll --gameMode campaign --difficulty 2  xcfrontendSkirmish:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --maxFps 60 --dumpInitRngs --automateAll --gameMode skirmish+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --maxFps 60 --dumpInitRngs --automateAll --gameMode skirmish  xcfrontendAmbush:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --maxFps 60 --dumpInitRngs --automateAll --gameMode ambush+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --maxFps 60 --dumpInitRngs --automateAll --gameMode ambush  xcfrontendBattle:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --maxFps 60 --dumpInitRngs --automateAll --gameMode battle --difficulty 1+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --maxFps 60 --dumpInitRngs --automateAll --gameMode battle --difficulty 2  xcfrontendSafari:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --maxFps 60 --dumpInitRngs --automateAll --gameMode safari --difficulty 1+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --maxFps 60 --dumpInitRngs --automateAll --gameMode safari --difficulty 2  xcfrontendDefense:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --maxFps 60 --dumpInitRngs --automateAll --gameMode defense --difficulty 9+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --maxFps 60 --dumpInitRngs --automateAll --gameMode defense --difficulty 8  xcbenchCampaign:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfter 60 --automateAll --gameMode campaign --difficulty 1 --setDungeonRng 42 --setMainRng 42+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfter 60 --automateAll --gameMode campaign --difficulty 2 --setDungeonRng 42 --setMainRng 42 +RTS -N1 -RTS  xcbenchBattle:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfter 60 --automateAll --gameMode battle --difficulty 1 --setDungeonRng 42 --setMainRng 42+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfter 60 --automateAll --gameMode battle --difficulty 2 --setDungeonRng 42 --setMainRng 42 +RTS -N1 -RTS  xcbenchFrontendCampaign:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --maxFps 100000 --benchmark --stopAfter 60 --automateAll --gameMode campaign --difficulty 1 --setDungeonRng 42 --setMainRng 42+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --maxFps 100000 --benchmark --stopAfter 60 --automateAll --gameMode campaign --difficulty 2 --setDungeonRng 42 --setMainRng 42 +RTS -N1 -RTS  xcbenchFrontendBattle:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --maxFps 100000 --benchmark --stopAfter 60 --automateAll --gameMode battle --difficulty 1 --setDungeonRng 42 --setMainRng 42+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --maxFps 100000 --benchmark --stopAfter 60 --automateAll --gameMode battle --difficulty 2 --setDungeonRng 42 --setMainRng 42 +RTS -N1 -RTS  xcbenchNull: xcbenchCampaign xcbenchBattle  xcbench: xcbenchCampaign xcbenchFrontendCampaign xcbenchBattle xcbenchFrontendBattle  -xctest-travis-short: xctest-short xcbenchNull+xctest-travis-short: xctest-short -xctest-travis: xctest-short xctest-medium xcbenchNull+xctest-travis: xctest-short xctest-medium -xctest-travis-long: xctest-short xctest-long xcbenchNull+xctest-travis-long: xctest-short xctest-long +xctest-travis-long-no-safari: xctest-short xctest-long-no-safari+ xctest: xctest-short xctest-medium xctest-long  xctest-short: xctest-short-new xctest-short-load  xctest-medium: xctestCampaign-medium xctestSkirmish-medium xctestAmbush-medium xctestBattle-medium xctestSafari-medium xctestPvP-medium xctestCoop-medium xctestDefense-medium -xctest-long: xctestCampaign-long xctestSkirmish-long xctestAmbush-long xctestBattle-long xctestSafari-long xctestPvP-long xctestCoop-long xctestDefense-long+xctest-long: xctestCampaign-long xctestSkirmish-medium xctestAmbush-medium xctestBattle-long xctestSafari-long xctestPvP-medium xctestDefense-long +xctest-long-no-safari: xctestCampaign-long xctestSkirmish-medium xctestAmbush-medium xctestBattle-long xctestPvP-medium xctestDefense-long+ xctestCampaign-long:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 400 --dumpInitRngs --automateAll --gameMode campaign --difficulty 1 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 500 --dumpInitRngs --automateAll --gameMode campaign --difficulty 2 > /tmp/stdtest.log  xctestCampaign-medium:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 250 --dumpInitRngs --automateAll --gameMode campaign --difficulty 1 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 400 --dumpInitRngs --automateAll --gameMode campaign --difficulty 2 > /tmp/stdtest.log  xctestSkirmish-long:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --gameMode skirmish > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --maxFps 100000 --frontendStd --benchmark --stopAfter 60 --dumpInitRngs --automateAll --gameMode skirmish > /tmp/stdtest.log  xctestSkirmish-medium:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --gameMode skirmish > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --gameMode skirmish > /tmp/stdtest.log  xctestAmbush-long:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --gameMode ambush > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 60 --dumpInitRngs --automateAll --gameMode ambush > /tmp/stdtest.log  xctestAmbush-medium:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --gameMode ambush > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --gameMode ambush > /tmp/stdtest.log  xctestBattle-long:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 400 --dumpInitRngs --automateAll --gameMode battle --difficulty 1 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 200 --dumpInitRngs --automateAll --gameMode battle --difficulty 2 > /tmp/stdtest.log  xctestBattle-medium:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 250 --dumpInitRngs --automateAll --gameMode battle --difficulty 1 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 100 --dumpInitRngs --automateAll --gameMode battle --difficulty 2 > /tmp/stdtest.log  xctestSafari-long:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 400 --dumpInitRngs --automateAll --gameMode safari --difficulty 1 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 500 --dumpInitRngs --automateAll --gameMode safari --difficulty 2 > /tmp/stdtest.log  xctestSafari-medium:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 250 --dumpInitRngs --automateAll --gameMode safari --difficulty 1 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 400 --dumpInitRngs --automateAll --gameMode safari --difficulty 2 > /tmp/stdtest.log  xctestPvP-long:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --gameMode PvP > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 60 --dumpInitRngs --automateAll --gameMode PvP > /tmp/stdtest.log  xctestPvP-medium:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --gameMode PvP > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --gameMode PvP > /tmp/stdtest.log  xctestCoop-long:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --gameMode Coop --difficulty 1 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 500 --dumpInitRngs --automateAll --gameMode Coop --difficulty 2 > /tmp/stdtest.log  xctestCoop-medium:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 250 --dumpInitRngs --automateAll --gameMode Coop --difficulty 1 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 300 --dumpInitRngs --automateAll --gameMode Coop --difficulty 2 > /tmp/stdtest.log  xctestDefense-long:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 400 --dumpInitRngs --automateAll --gameMode defense --difficulty 9 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 500 --dumpInitRngs --automateAll --gameMode defense --difficulty 8 > /tmp/stdtest.log  xctestDefense-medium:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 250 --dumpInitRngs --automateAll --gameMode defense --difficulty 9 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 300 --dumpInitRngs --automateAll --gameMode defense --difficulty 8 > /tmp/stdtest.log  xctest-short-new:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --newGame --noMore --savePrefix campaign --dumpInitRngs --automateAll --gameMode campaign --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --newGame --noMore --savePrefix skirmish --dumpInitRngs --automateAll --gameMode skirmish --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --newGame --noMore --savePrefix ambush --dumpInitRngs --automateAll --gameMode ambush --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --newGame --noMore --savePrefix battle --dumpInitRngs --automateAll --gameMode battle --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --newGame --noMore --savePrefix safari --dumpInitRngs --automateAll --gameMode safari --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --newGame --noMore --savePrefix PvP --dumpInitRngs --automateAll --gameMode PvP --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --newGame --noMore --savePrefix Coop --dumpInitRngs --automateAll --gameMode Coop --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --newGame --noMore --savePrefix defense --dumpInitRngs --automateAll --gameMode defense --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --newGame --savePrefix campaign --dumpInitRngs --automateAll --gameMode campaign --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --newGame --savePrefix skirmish --dumpInitRngs --automateAll --gameMode skirmish --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --newGame --savePrefix ambush --dumpInitRngs --automateAll --gameMode ambush --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --newGame --savePrefix battle --dumpInitRngs --automateAll --gameMode battle --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --newGame --savePrefix safari --dumpInitRngs --automateAll --gameMode safari --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --newGame --savePrefix PvP --dumpInitRngs --automateAll --gameMode PvP --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --newGame --savePrefix Coop --dumpInitRngs --automateAll --gameMode Coop --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --newGame --savePrefix defense --dumpInitRngs --automateAll --gameMode defense --frontendStd --stopAfter 2 > /tmp/stdtest.log  xctest-short-load:-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --noMore --savePrefix campaign --dumpInitRngs --automateAll --gameMode campaign --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --noMore --savePrefix skirmish --dumpInitRngs --automateAll --gameMode skirmish --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --noMore --savePrefix ambush --dumpInitRngs --automateAll --gameMode ambush --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --noMore --savePrefix battle --dumpInitRngs --automateAll --gameMode battle --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --noMore --savePrefix safari --dumpInitRngs --automateAll --gameMode safari --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --noMore --savePrefix PvP --dumpInitRngs --automateAll --gameMode PvP --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --noMore --savePrefix Coop --dumpInitRngs --automateAll --gameMode Coop --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --noMore --savePrefix defense --dumpInitRngs --automateAll --gameMode defense --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix campaign --dumpInitRngs --automateAll --gameMode campaign --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix skirmish --dumpInitRngs --automateAll --gameMode skirmish --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix ambush --dumpInitRngs --automateAll --gameMode ambush --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix battle --dumpInitRngs --automateAll --gameMode battle --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix safari --dumpInitRngs --automateAll --gameMode safari --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix PvP --dumpInitRngs --automateAll --gameMode PvP --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix Coop --dumpInitRngs --automateAll --gameMode Coop --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure +RTS -xc -RTS --dbgMsgSer --savePrefix defense --dumpInitRngs --automateAll --gameMode defense --frontendStd --stopAfter 2 > /tmp/stdtest.log   play: 	dist/build/Allure/Allure --dbgMsgSer --dumpInitRngs  frontendCampaign:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --maxFps 60 --dumpInitRngs --automateAll --gameMode campaign --difficulty 1+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --maxFps 60 --dumpInitRngs --automateAll --gameMode campaign --difficulty 2  frontendSkirmish:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --maxFps 60 --dumpInitRngs --automateAll --gameMode skirmish+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --maxFps 60 --dumpInitRngs --automateAll --gameMode skirmish  frontendAmbush:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --maxFps 60 --dumpInitRngs --automateAll --gameMode ambush+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --maxFps 60 --dumpInitRngs --automateAll --gameMode ambush  frontendBattle:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --maxFps 60 --dumpInitRngs --automateAll --gameMode battle --difficulty 1+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --maxFps 60 --dumpInitRngs --automateAll --gameMode battle --difficulty 2  frontendSafari:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --maxFps 60 --dumpInitRngs --automateAll --gameMode safari --difficulty 1+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --maxFps 60 --dumpInitRngs --automateAll --gameMode safari --difficulty 2  frontendDefense:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --maxFps 60 --dumpInitRngs --automateAll --gameMode defense --difficulty 9+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --maxFps 60 --dumpInitRngs --automateAll --gameMode defense --difficulty 8  benchCampaign:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfter 60 --automateAll --gameMode campaign --difficulty 1 --setDungeonRng 42 --setMainRng 42+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfter 60 --automateAll --gameMode campaign --difficulty 2 --setDungeonRng 42 --setMainRng 42 +RTS -N1 -RTS  benchBattle:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfter 60 --automateAll --gameMode battle --difficulty 1 --setDungeonRng 42 --setMainRng 42+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfter 60 --automateAll --gameMode battle --difficulty 2 --setDungeonRng 42 --setMainRng 42 +RTS -N1 -RTS  benchFrontendCampaign:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --maxFps 100000 --benchmark --stopAfter 60 --automateAll --gameMode campaign --difficulty 1 --setDungeonRng 42 --setMainRng 42+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --maxFps 100000 --benchmark --stopAfter 60 --automateAll --gameMode campaign --difficulty 2 --setDungeonRng 42 --setMainRng 42 +RTS -N1 -RTS  benchFrontendBattle:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --maxFps 100000 --benchmark --stopAfter 60 --automateAll --gameMode battle --difficulty 1 --setDungeonRng 42 --setMainRng 42+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --maxFps 100000 --benchmark --stopAfter 60 --automateAll --gameMode battle --difficulty 2 --setDungeonRng 42 --setMainRng 42 +RTS -N1 -RTS  benchNull: benchCampaign benchBattle  bench: benchCampaign benchFrontendCampaign benchBattle benchFrontendBattle  -test-travis-short: test-short benchNull+test-travis-short: test-short -test-travis: test-short test-medium benchNull+test-travis: test-short test-medium -test-travis-long: test-short test-long benchNull+test-travis-long: test-short test-long +test-travis-long-no-safari: test-short test-long-no-safari+ test: test-short test-medium test-long  test-short: test-short-new test-short-load  test-medium: testCampaign-medium testSkirmish-medium testAmbush-medium testBattle-medium testSafari-medium testPvP-medium testCoop-medium testDefense-medium -test-long: testCampaign-long testSkirmish-long testAmbush-long testBattle-long testSafari-long testPvP-long testCoop-long testDefense-long+test-long: testCampaign-long testSkirmish-medium testAmbush-medium testBattle-long testSafari-long testPvP-medium testDefense-long +test-long-no-safari: testCampaign-long testSkirmish-medium testAmbush-medium testBattle-long testPvP-medium testDefense-long+ testCampaign-long:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 400 --dumpInitRngs --automateAll --gameMode campaign --difficulty 1 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 500 --dumpInitRngs --automateAll --gameMode campaign --difficulty 2 > /tmp/stdtest.log  testCampaign-medium:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 250 --dumpInitRngs --automateAll --gameMode campaign --difficulty 1 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 400 --dumpInitRngs --automateAll --gameMode campaign --difficulty 2 > /tmp/stdtest.log  testSkirmish-long:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --gameMode skirmish > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --maxFps 100000 --frontendStd --benchmark --stopAfter 60 --dumpInitRngs --automateAll --gameMode skirmish > /tmp/stdtest.log  testSkirmish-medium:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --gameMode skirmish > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --gameMode skirmish > /tmp/stdtest.log  testAmbush-long:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --gameMode ambush > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 60 --dumpInitRngs --automateAll --gameMode ambush > /tmp/stdtest.log  testAmbush-medium:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --gameMode ambush > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --gameMode ambush > /tmp/stdtest.log  testBattle-long:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 400 --dumpInitRngs --automateAll --gameMode battle --difficulty 1 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 200 --dumpInitRngs --automateAll --gameMode battle --difficulty 2 > /tmp/stdtest.log  testBattle-medium:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 250 --dumpInitRngs --automateAll --gameMode battle --difficulty 1 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 100 --dumpInitRngs --automateAll --gameMode battle --difficulty 2 > /tmp/stdtest.log  testSafari-long:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 400 --dumpInitRngs --automateAll --gameMode safari --difficulty 1 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 500 --dumpInitRngs --automateAll --gameMode safari --difficulty 2 > /tmp/stdtest.log  testSafari-medium:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 250 --dumpInitRngs --automateAll --gameMode safari --difficulty 1 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 400 --dumpInitRngs --automateAll --gameMode safari --difficulty 2 > /tmp/stdtest.log  testPvP-long:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --gameMode PvP > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 60 --dumpInitRngs --automateAll --gameMode PvP > /tmp/stdtest.log  testPvP-medium:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --gameMode PvP > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --gameMode PvP > /tmp/stdtest.log  testCoop-long:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 30 --dumpInitRngs --automateAll --gameMode Coop --difficulty 1 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 500 --dumpInitRngs --automateAll --gameMode Coop --difficulty 2 > /tmp/stdtest.log  testCoop-medium:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 250 --dumpInitRngs --automateAll --gameMode Coop --difficulty 1 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 300 --dumpInitRngs --automateAll --gameMode Coop --difficulty 2 > /tmp/stdtest.log  testDefense-long:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 400 --dumpInitRngs --automateAll --gameMode defense --difficulty 9 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 500 --dumpInitRngs --automateAll --gameMode defense --difficulty 8 > /tmp/stdtest.log  testDefense-medium:-	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 250 --dumpInitRngs --automateAll --gameMode defense --difficulty 9 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendStd --benchmark --stopAfter 300 --dumpInitRngs --automateAll --gameMode defense --difficulty 8 > /tmp/stdtest.log  test-short-new:-	dist/build/Allure/Allure --dbgMsgSer --newGame --noMore --savePrefix campaign --dumpInitRngs --automateAll --gameMode campaign --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure --dbgMsgSer --newGame --noMore --savePrefix skirmish --dumpInitRngs --automateAll --gameMode skirmish --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure --dbgMsgSer --newGame --noMore --savePrefix ambush --dumpInitRngs --automateAll --gameMode ambush --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure --dbgMsgSer --newGame --noMore --savePrefix battle --dumpInitRngs --automateAll --gameMode battle --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure --dbgMsgSer --newGame --noMore --savePrefix safari --dumpInitRngs --automateAll --gameMode safari --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure --dbgMsgSer --newGame --noMore --savePrefix PvP --dumpInitRngs --automateAll --gameMode PvP --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure --dbgMsgSer --newGame --noMore --savePrefix Coop --dumpInitRngs --automateAll --gameMode Coop --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure --dbgMsgSer --newGame --noMore --savePrefix defense --dumpInitRngs --automateAll --gameMode defense --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --newGame --savePrefix campaign --dumpInitRngs --automateAll --gameMode campaign --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --newGame --savePrefix skirmish --dumpInitRngs --automateAll --gameMode skirmish --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --newGame --savePrefix ambush --dumpInitRngs --automateAll --gameMode ambush --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --newGame --savePrefix battle --dumpInitRngs --automateAll --gameMode battle --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --newGame --savePrefix safari --dumpInitRngs --automateAll --gameMode safari --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --newGame --savePrefix PvP --dumpInitRngs --automateAll --gameMode PvP --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --newGame --savePrefix Coop --dumpInitRngs --automateAll --gameMode Coop --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --newGame --savePrefix defense --dumpInitRngs --automateAll --gameMode defense --frontendStd --stopAfter 2 > /tmp/stdtest.log  test-short-load:-	dist/build/Allure/Allure --dbgMsgSer --noMore --savePrefix campaign --dumpInitRngs --automateAll --gameMode campaign --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure --dbgMsgSer --noMore --savePrefix skirmish --dumpInitRngs --automateAll --gameMode skirmish --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure --dbgMsgSer --noMore --savePrefix ambush --dumpInitRngs --automateAll --gameMode ambush --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure --dbgMsgSer --noMore --savePrefix battle --dumpInitRngs --automateAll --gameMode battle --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure --dbgMsgSer --noMore --savePrefix safari --dumpInitRngs --automateAll --gameMode safari --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure --dbgMsgSer --noMore --savePrefix PvP --dumpInitRngs --automateAll --gameMode PvP --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure --dbgMsgSer --noMore --savePrefix Coop --dumpInitRngs --automateAll --gameMode Coop --frontendStd --stopAfter 2 > /tmp/stdtest.log-	dist/build/Allure/Allure --dbgMsgSer --noMore --savePrefix defense --dumpInitRngs --automateAll --gameMode defense --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix campaign --dumpInitRngs --automateAll --gameMode campaign --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix skirmish --dumpInitRngs --automateAll --gameMode skirmish --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix ambush --dumpInitRngs --automateAll --gameMode ambush --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix battle --dumpInitRngs --automateAll --gameMode battle --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix safari --dumpInitRngs --automateAll --gameMode safari --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix PvP --dumpInitRngs --automateAll --gameMode PvP --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix Coop --dumpInitRngs --automateAll --gameMode Coop --frontendStd --stopAfter 2 > /tmp/stdtest.log+	dist/build/Allure/Allure --dbgMsgSer --savePrefix defense --dumpInitRngs --automateAll --gameMode defense --frontendStd --stopAfter 2 > /tmp/stdtest.log   build-binary:-	cabal configure --prefix=/usr/local+	cabal configure -frelease --prefix=/usr/local 	cabal build Allure 	rm -rf /tmp/Allure 	cabal copy --destdir=/tmp/Allure-	tar -czf /tmp/Allure.tar.gz -C /tmp --exclude=Allure/usr/local/lib --exclude=Allure/usr/local/share/doc Allure+	tar -czf /tmp/Allure_x_ubuntu-12.04-amd64.tar.gz -C /tmp --exclude=Allure/usr/local/lib --exclude=Allure/usr/local/share/doc Allure++build-binary-i386:+	cabal configure -frelease --prefix=/usr/local --ghc-option="-optc-m32" --ghc-option="-opta-m32" --ghc-option="-optl-m32" --ld-option="-melf_i386"+	cabal build exe:Allure+	rm -rf /tmp/Allure+	cabal copy --destdir=/tmp/Allure+	tar -czf /tmp/Allure_x_ubuntu-12.04-i386.tar.gz -C /tmp --exclude=Allure/usr/local/lib --exclude=Allure/usr/local/share/doc Allure++# TODO: figure out, whey this must be so different from Linux+build-binary-windows-i386:+	wine cabal configure -frelease+	wine cabal build exe:Allure+	rm -rf /tmp/Allure_x_windows-i386.zip+	rm -rf /tmp/AllureOfTheStarsInstall+	rm -rf /tmp/AllureOfTheStars+	mkdir -p /tmp/AllureOfTheStars/GameDefinition+	wine cabal copy --destdir=Z:/tmp/AllureOfTheStarsInstall+	cp /tmp/AllureOfTheStarsInstall/users/mikolaj/Application\ Data/cabal/bin/Allure.exe /tmp/AllureOfTheStars+	cp GameDefinition/PLAYING.md /tmp/AllureOfTheStars/GameDefinition+	cp GameDefinition/scores /tmp/AllureOfTheStars/GameDefinition+	cp GameDefinition/config.ui.default /tmp/AllureOfTheStars/GameDefinition+	cp CHANGELOG.md /tmp/AllureOfTheStars+	cp CREDITS /tmp/AllureOfTheStars+	cp LICENSE /tmp/AllureOfTheStars+	cp README.md /tmp/AllureOfTheStars+	cp /home/mikolaj/.wine/drive_c/users/mikolaj/gtk/bin/zlib1.dll /tmp/AllureOfTheStars+	wine Z:/home/mikolaj/.local/share/wineprefixes/7zip/drive_c/Program\ Files/7-Zip/7z.exe a -ssc -sfx Z:/tmp/Allure_x_windows-i386.exe Z:/tmp/AllureOfTheStars   # The rest of the makefile is unmaintained at the moment.
README.md view
@@ -1,41 +1,87 @@ Allure of the Stars [![Build Status](https://travis-ci.org/AllureOfTheStars/Allure.svg?branch=master)](https://travis-ci.org/AllureOfTheStars/Allure)[![Build Status](https://drone.io/github.com/AllureOfTheStars/Allure/status.png)](https://drone.io/github.com/AllureOfTheStars/Allure/latest) =================== -[Allure of the Stars] [8] is a near-future Sci-Fi [roguelike] [2]+[Allure of the Stars] [6] is a near-future Sci-Fi [roguelike] [2] and tactical squad game. Have a look at [PLAYING.md](GameDefinition/PLAYING.md) or jump straight into the fray.  ![gameplay screenshot](GameDefinition/screenshot.png?raw=true) -The game is written in [Haskell] [1] using the [LambdaHack] [5]+The game is written in [Haskell] [1] using the [LambdaHack] [10] roguelike game engine. Long-term goals of the project are high replayability and auto-balancing through procedural content generation and persistent content modification based on player behaviour.  -Compilation and installation-----------------------------+Installation from binary archives+--------------------------------- +Pre-compiled game binaries for some platforms are available through+the [release page] [11] and from the [Nix Packages Collection] [12].+To manually install a binary archive, make sure you have the GTK+libraries suite on your system, unpack the LambdaHack archive+and run the executable in the unpacked directory.++On Windows, if you don't already have GTK installed (e.g., for the GIMP+picture editor) please download and run (with default settings)+the GTK installer from++http://sourceforge.net/projects/gtk-win/+++Screen and keyboard configuration+---------------------------------++The game UI can be configured via a config file.+The commented out version of this file with the default settings is in+[GameDefinition/config.ui.default](GameDefinition/config.ui.default).+When the game is run for the first time, the file is copied to the official+location, which is `~/.Allure/config.ui.ini` on Linux and+`C:\Users\<username>\AppData\Roaming\Allure\config.ui.ini`+(or `C:\Documents And Settings\user\Application Data\Allure\config.ui.ini`+or something else altogether) on Windows.++Screen font can be changed and enlarged by uncommenting and editing+the config file at its official location or by right-clicking+on the game window.++If you use the numeric keypad, use the NumLock key on your keyboard+to toggle the game keyboard mode. With NumLock off, you walk with the numeric+keys and run with Shift (or Control) and the keys. When you turn NumLock on,+the reversed key setup enforces good playing habits by setting as the default+the run command (which automatically stops at threats, keeping you safe)+and requiring Shift for the error-prone step by step walking.++If you don't have a numeric keypad, you can use laptop keys (uk8o79jl)+or you can enable the Vi keys (aka roguelike keys) in the config file.+++Compilation from source+-----------------------+ The game is best compiled and installed via Cabal (already a part of your OS distribution, or available within [The Haskell Platform] [7]),-which also takes care of all the dependencies. The latest official-version of the game can be downloaded, compiled and installed-automatically by Cabal from [Hackage] [4] as follows+which also takes care of all the dependencies. You also need+the GTK libraries for your OS. On Linux, remember to install the -dev+versions as well. On Windows follow [the same steps as for Wine] [13].+On OSX, if you encounter problems, you may want to+[compile the GTK libraries from sources] [14]. +The latest official version of the game can be downloaded,+compiled and installed automatically by Cabal from [Hackage] [3] as follows+     cabal install gtk2hs-buildtools     cabal install Allure  For a newer version, install a matching LambdaHack library snapshot-from a development branch, download the game source from [github] [3]+from a development branch, download the game source from [github] [5] and run `cabal install` from the main directory. -Some pre-compiled game binaries may be available from the [releases] [9] page.- Compatibility notes -------------------  The current code was tested with GHC 7.6 and 7.8,-but should also work with other GHC versions.+but should also work with other GHC versions, with minor modifications.  If you are using the terminal frontends, numerical keypad may not work correctly depending on versions of the libraries, terminfo and terminal@@ -50,11 +96,11 @@ ---------------------  The [Makefile](Makefile) contains many sample test commands.-All commands that use the screensaver game modes (AI vs. AI)- and the dumb `stdout` frontend are gathered in `make test`.+Many tests that use the screensaver game modes (AI vs. AI)+and the dumb `stdout` frontend are gathered in `make test`. Of these, travis runs `test-travis-*` on each push to the repo. Test commands with prefix `frontend` start AI vs. AI games-with the standard, user-friendly frontend.+with the standard, user-friendly gtk frontend.  Run `Allure --help` to see a brief description of all debug options. Of these, `--sniffIn` and `--sniffOut` are very useful (though verbose@@ -67,7 +113,7 @@ Further information ------------------- -For more information, visit the [wiki] [6]+For more information, visit the [wiki] [4] and see [PLAYING.md](GameDefinition/PLAYING.md), [CREDITS](CREDITS) and [LICENSE](LICENSE). @@ -97,10 +143,14 @@  [1]: http://www.haskell.org/ [2]: http://roguebasin.roguelikedevelopment.org/index.php?title=Berlin_Interpretation-[3]: http://github.com/AllureOfTheStars/Allure-[4]: http://hackage.haskell.org/package/Allure-[5]: http://github.com/LambdaHack/LambdaHack-[6]: https://github.com/AllureOfTheStars/Allure/wiki+[3]: http://hackage.haskell.org/package/Allure+[4]: https://github.com/AllureOfTheStars/Allure/wiki+[5]: http://github.com/AllureOfTheStars/Allure+[6]: http://allureofthestars.com [7]: http://www.haskell.org/platform-[8]: http://allureofthestars.com-[9]: https://github.com/AllureOfTheStars/Allure/releases++[10]: http://github.com/LambdaHack/LambdaHack+[11]: https://github.com/AllureOfTheStars/Allure/releases/latest+[12]: http://hydra.cryp.to/search?query=Allure+[13]: http://www.haskell.org/haskellwiki/GHC_under_Wine#Code_that_uses_gtk2hs+[14]: http://www.edsko.net/2014/04/27/haskell-including-gtk-on-mavericks
test/test.hs view
@@ -2,5 +2,5 @@  main :: IO () main = do-  tieKnot $ tail $ words "dist/build/LambdaHack/LambdaHack --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfter 6 --automateAll --gameMode campaign --difficulty 1 --setDungeonRng 42 --setMainRng 42"-  -- tieKnot $ tail $ words "dist/build/LambdaHack/LambdaHack --dbgMsgSer --savePrefix test --newGame --noMore --noDelay --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfter 6 --automateAll --gameMode battle --difficulty 1 --setDungeonRng 42 --setMainRng 42"+  tieKnot $ tail $ words "dist/build/LambdaHack/LambdaHack --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfter 6 --automateAll --gameMode campaign --setDungeonRng 42 --setMainRng 42"+  -- tieKnot $ tail $ words "dist/build/LambdaHack/LambdaHack --dbgMsgSer --savePrefix test --newGame --noDelay --noAnim --maxFps 100000 --frontendNull --benchmark --stopAfter 6 --automateAll --gameMode battle --setDungeonRng 42 --setMainRng 42"