SpacePrivateers (empty) → 0.1.0.0
raw patch · 23 files changed
+2773/−0 lines, 23 filesdep +LambdaHackdep +basedep +containerssetup-changedbinary-added
Dependencies added: LambdaHack, base, containers, enummapset-th, filepath, template-haskell, text
Files
- CREDITS +3/−0
- GameDefinition/Client/UI/Content/KeyKind.hs +171/−0
- GameDefinition/Content/CaveKind.hs +69/−0
- GameDefinition/Content/FactionKind.hs +73/−0
- GameDefinition/Content/ItemKind.hs +688/−0
- GameDefinition/Content/ItemKindActor.hs +165/−0
- GameDefinition/Content/ItemKindOrgan.hs +259/−0
- GameDefinition/Content/ItemKindShrapnel.hs +239/−0
- GameDefinition/Content/ModeKind.hs +113/−0
- GameDefinition/Content/PlaceKind.hs +185/−0
- GameDefinition/Content/RuleKind.hs +54/−0
- GameDefinition/Content/TileKind.hs +307/−0
- GameDefinition/Main.hs +13/−0
- GameDefinition/MainMenu.ascii +26/−0
- GameDefinition/PLAYING.md +242/−0
- GameDefinition/TieKnot.hs +38/−0
- GameDefinition/config.ui.default +28/−0
- GameDefinition/scores binary
- LICENSE +32/−0
- README.md +8/−0
- Setup.hs +2/−0
- SpacePrivateers.cabal +56/−0
- changelog +2/−0
+ CREDITS view
@@ -0,0 +1,3 @@+Space Privateers use LambdaHack engine. Many thanks to all people who have+contributed on it. Space Privateers used original LambdaHack files as a +starting point for game definition.
+ GameDefinition/Client/UI/Content/KeyKind.hs view
@@ -0,0 +1,171 @@+-- | The default game key-command mapping to be used for UI. Can be overriden+-- via macros in the config file.+module Client.UI.Content.KeyKind ( standardKeys ) where++import Control.Arrow (first)++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++standardKeys :: KeyKind+standardKeys = KeyKind+ { rhumanCommands = map (first K.mkKM)+ -- All commands are defined here, except some movement and leader picking+ -- commands. All commands are shown on help screens except debug commands+ -- and macros with empty descriptions.+ -- The order below determines the order on the help screens.+ -- Remember to put commands that show information (e.g., enter targeting+ -- mode) first.++ -- Main Menu, which apart of these includes a few extra commands+ [ ("CTRL-x", ([CmdMenu], GameExit))+ , ("CTRL-a", ([CmdMenu], GameRestart "campaign"))+ , ("CTRL-d", ([CmdMenu], GameDifficultyCycle))++ -- Movement and terrain alteration+ , ("less", ([CmdMove, CmdMinimal], TriggerTile+ [ TriggerFeature { verb = "ascend"+ , object = "a level"+ , feature = F.Cause (Effect.Ascend 1) }+ , TriggerFeature { verb = "escape"+ , object = "dungeon"+ , feature = F.Cause (Effect.Escape 1) } ]))+ , ("CTRL-less", ([CmdMove], TriggerTile+ [ TriggerFeature { verb = "ascend"+ , object = "10 levels"+ , feature = F.Cause (Effect.Ascend 10) } ]))+ , ("greater", ([CmdMove, CmdMinimal], TriggerTile+ [ TriggerFeature { verb = "descend"+ , object = "a level"+ , feature = F.Cause (Effect.Ascend (-1)) }+ , TriggerFeature { verb = "escape"+ , object = "dungeon"+ , feature = F.Cause (Effect.Escape (-1)) } ]))+ , ("CTRL-greater", ([CmdMove], TriggerTile+ [ TriggerFeature { verb = "descend"+ , object = "10 levels"+ , feature = F.Cause (Effect.Ascend (-10)) } ]))+ , ("semicolon", ([CmdMove], StepToTarget))+ , ("colon", ([CmdMove], Macro "go to target for 100 steps"+ ["semicolon", "V"]))+ , ("CTRL-colon", ([CmdMove], Macro "go to target for 10 steps"+ ["semicolon", "CTRL-V"]))+ , ("x", ([CmdMove], Macro "explore the closest unknown spot"+ [ "BackSpace"+ , "CTRL-question", "semicolon", "V" ]))+ , ("X", ([CmdMove], Macro "autoexplore 100 times"+ [ "BackSpace"+ , "'", "CTRL-question", "semicolon", "'"+ , "V" ]))+ , ("CTRL-X", ([CmdMove], Macro "autoexplore 10 times"+ [ "BackSpace"+ , "'", "CTRL-question", "semicolon", "'"+ , "CTRL-V" ]))+ , ("R", ([CmdMove], Macro "rest (wait 100 times)"+ ["KP_Begin", "V"]))+ , ("CTRL-R", ([CmdMove], Macro "rest (wait 10 times)"+ ["KP_Begin", "CTRL-V"]))+ , ("c", ([CmdMove], AlterDir+ [ AlterFeature { verb = "close"+ , object = "door"+ , feature = F.CloseTo "vertical closed door Lit" }+ , AlterFeature { verb = "close"+ , object = "door"+ , feature = F.CloseTo "horizontal closed door Lit" }+ , AlterFeature { verb = "close"+ , object = "door"+ , feature = F.CloseTo "vertical closed door Dark" }+ , AlterFeature { verb = "close"+ , object = "door"+ , feature = F.CloseTo "horizontal closed door Dark" }+ ]))+ , ("period", ([CmdMove], Macro "" ["KP_Begin"]))+ , ("i", ([CmdMove], Macro "" ["KP_Begin"]))++ -- Item use+ , ("E", ([CmdItem], DescribeItem CEqp))+ , ("P", ([CmdItem], DescribeItem CInv))+ , ("S", ([CmdItem], DescribeItem CSha))+ , ("G", ([CmdItem], DescribeItem CGround))+ , ("A", ([CmdItem], AllOwned))+ , ("g", ([CmdItem, CmdMinimal],+ MoveItem [CGround] CEqp "get" "an item" True))+ , ("d", ([CmdItem], MoveItem [CEqp, CInv, CSha] CGround+ "drop" "an item" False))+ , ("e", ([CmdItem], MoveItem [CInv, CSha] CEqp+ "equip" "an item" False))+ , ("p", ([CmdItem], MoveItem [CEqp, CSha] CInv+ "pack" "an item into inventory backpack"+ False))+ , ("s", ([CmdItem], MoveItem [CEqp, CInv] CSha+ "stash" "and share an item" False))+ , ("a", ([CmdItem, CmdMinimal], Apply+ [ ApplyItem { verb = "activate"+ , object = "applicable item"+ , symbol = ' ' }+ , ApplyItem { verb = "quaff"+ , object = "potion"+ , symbol = '!' }+ , ApplyItem { verb = "read"+ , object = "scroll"+ , symbol = '?' }+ ]))+ , ("q", ([CmdItem], Apply [ApplyItem { verb = "quaff"+ , object = "potion"+ , symbol = '!' }]))+ , ("r", ([CmdItem], Apply [ApplyItem { verb = "read"+ , object = "scroll"+ , symbol = '?' }]))+ , ("f", ([CmdItem, CmdMinimal], Project+ [ApplyItem { verb = "fling"+ , object = "projectable item"+ , symbol = ' ' }]))+ , ("t", ([CmdItem], Project [ApplyItem { verb = "throw"+ , object = "missile"+ , symbol = '|' }]))+ , ("z", ([CmdItem], Project [ApplyItem { verb = "zap"+ , object = "wand"+ , symbol = '/' }]))++ -- Targeting+ , ("KP_Multiply", ([CmdTgt, CmdMinimal], TgtEnemy))+ , ("backslash", ([CmdTgt], Macro "" ["KP_Multiply"]))+ , ("slash", ([CmdTgt], TgtFloor))+ , ("plus", ([CmdTgt], EpsIncr True))+ , ("minus", ([CmdTgt], EpsIncr False))+ , ("BackSpace", ([CmdTgt], TgtClear))+ , ("CTRL-question", ([CmdTgt], TgtUnknown))+ , ("CTRL-I", ([CmdTgt], TgtItem))+ , ("CTRL-braceleft", ([CmdTgt], TgtStair True))+ , ("CTRL-braceright", ([CmdTgt], TgtStair False))++ -- Automation+ , ("equal", ([CmdAuto], SelectActor))+ , ("underscore", ([CmdAuto], SelectNone))+ , ("v", ([CmdAuto], Repeat 1))+ , ("V", ([CmdAuto], Repeat 100))+ , ("CTRL-v", ([CmdAuto], Repeat 1000))+ , ("CTRL-V", ([CmdAuto], Repeat 10))+ , ("apostrophe", ([CmdAuto], Record))+ , ("CTRL-A", ([CmdAuto], Automate))++ -- Assorted+ , ("question", ([CmdMeta], Help))+ , ("D", ([CmdMeta], History))+ , ("T", ([CmdMeta], MarkSuspect))+ , ("Z", ([CmdMeta], MarkVision))+ , ("C", ([CmdMeta], MarkSmell))+ , ("Tab", ([CmdMeta], MemberCycle))+ , ("ISO_Left_Tab", ([CmdMeta], MemberBack))+ , ("space", ([CmdMeta], Clear))+ , ("Escape", ([CmdMeta, CmdMinimal], Cancel))+ , ("Return", ([CmdMeta], Accept))++ -- Debug and others not to display in help screens+ , ("CTRL-s", ([CmdDebug], GameSave))+ ]+ }
+ GameDefinition/Content/CaveKind.hs view
@@ -0,0 +1,69 @@+-- | Cave layouts for Space Privateers.+module Content.CaveKind ( cdefs ) where++import Data.Ratio++import Game.LambdaHack.Common.ContentDef+import Game.LambdaHack.Common.Dice+import Game.LambdaHack.Common.Misc+import Game.LambdaHack.Content.CaveKind++cdefs :: ContentDef CaveKind+cdefs = ContentDef+ { getSymbol = csymbol+ , getName = cname+ , getFreq = cfreq+ , validate = validateCaveKind+ , content =+ [rogue, munitorium]+ }+rogue, munitorium :: CaveKind++rogue = CaveKind+ { csymbol = 'R'+ , cname = "General quarters"+ , cfreq = [("dng", 100), ("caveRogue", 1)]+ , cxsize = fst normalLevelBound + 1+ , cysize = snd normalLevelBound + 1+ , cgrid = DiceXY (3 * d 2) (d 2 + 2)+ , cminPlaceSize = DiceXY (2 * d 2 + 2) 4+ , cmaxPlaceSize = DiceXY 15 10+ , cdarkChance = d 54 + dl 20+ , cnightChance = 51+ , cauxConnects = 1%3+ , cmaxVoid = 1%6+ , cminStairDist = 30+ , cdoorChance = 1%2+ , copenChance = 1%10+ , chidden = 8+ , cactorFreq = [("merchant", 50), ("chaos", 45), ("spawn", 5)]+ , citemNum = 10 * d 2+ , citemFreq = [("useful", 70), ("treasure", 30)]+ , cplaceFreq = [("rogue", 100)]+ , cpassable = False+ , cdefTile = "fillerWall"+ , cdarkCorTile = "floorCorridorDark"+ , clitCorTile = "floorCorridorLit"+ , cfillerTile = "fillerWall"+ , couterFenceTile = "basic outer fence"+ , clegendDarkTile = "legendDark"+ , clegendLitTile = "legendLit"+ }+munitorium = rogue+ { csymbol = 'M'+ , cname = "Munitorium"+ , cfreq = [("dng", 15), ("munitorium", 1)]+ , cgrid = DiceXY 3 3+ , cminPlaceSize = DiceXY 15 4+ , cmaxPlaceSize = DiceXY 25 10+ , cdarkChance = dl 5+ , cnightChance = d 20+ , cactorFreq = [("merchant", 80), ("chaos", 5), ("spawn", 15)]+ , citemNum = 8 * d 2+ , citemFreq = [("weapon", 70), ("armour", 20), ("useful", 10)]+ , cplaceFreq = [("rogue", 100)]+ , cpassable = True+ , cdefTile = "arenaSet"+ , cdarkCorTile = "floorArenaDark"+ , clitCorTile = "floorArenaLit"+}
+ GameDefinition/Content/FactionKind.hs view
@@ -0,0 +1,73 @@+-- | The type of kinds of game factions (heroes, enemies, NPCs, etc.)+-- for Space Privateers.+module Content.FactionKind ( cdefs ) where++import qualified Data.EnumMap.Strict as EM++import Game.LambdaHack.Common.Ability+import Game.LambdaHack.Common.ContentDef+import Game.LambdaHack.Content.FactionKind++cdefs :: ContentDef FactionKind+cdefs = ContentDef+ { getSymbol = fsymbol+ , getName = fname+ , getFreq = ffreq+ , validate = validateFactionKind+ , content =+ [hero, merchant, chaos, spawn, horror]+ }+hero, merchant, chaos, spawn, horror :: FactionKind++hero = FactionKind+ { fsymbol = '1'+ , fname = "hero"+ , ffreq = [("hero", 1)]+ , fSkillsLeader = allSkills+ , fSkillsOther = meleeAdjacent+ }++merchant = FactionKind+ { fsymbol = '@'+ , fname = "merchant"+ , ffreq = [("merchant", 1)]+ , fSkillsLeader = allSkills+ , fSkillsOther = allSkills+ }++chaos = FactionKind+ { fsymbol = 'c'+ , fname = "chaos"+ , ffreq = [("chaos", 1)]+ , fSkillsLeader = allSkills+ , fSkillsOther = allSkills+ }++spawn = FactionKind+ { fsymbol = 's'+ , fname = "spawn"+ , ffreq = [("spawn", 1)]+ , fSkillsLeader = animalSkills+ , fSkillsOther = animalSkills+ } ++horror = FactionKind+ { fsymbol = 'h'+ , fname = "horror"+ , ffreq = [("horror", 1)]+ , fSkillsLeader = animalSkills+ , fSkillsOther = animalSkills+ }+++meleeAdjacent, _meleeAndRanged, animalSkills, allSkills :: Skills++meleeAdjacent = EM.fromList $ zip [AbWait, AbMelee] [1, 1..]++-- Melee and reaction fire.+_meleeAndRanged = EM.fromList $ zip [AbWait, AbMelee, AbProject] [1, 1..]++animalSkills =+ EM.fromList $ zip [AbMove, AbMelee, AbAlter, AbWait, AbTrigger] [1, 1..]++allSkills = unitSkills
+ GameDefinition/Content/ItemKind.hs view
@@ -0,0 +1,688 @@+-- | Weapon and treasure definitions.+module Content.ItemKind ( cdefs ) where++import Data.List++import Content.ItemKindActor+import Content.ItemKindOrgan+import Content.ItemKindShrapnel+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++cdefs :: ContentDef ItemKind+cdefs = ContentDef+ { getSymbol = isymbol+ , getName = iname+ , getFreq = ifreq+ , validate = validateItemKind+ , content = items ++ organs ++ shrapnels ++ actors+ }++items :: [ItemKind]+items =+ [decipulum, brassLantern, buckler, dart, dart200, gem1, gem2, gem3, gloveFencing, gloveGauntlet, gloveJousting, currency, gorget, harpoon, oculus, necklace1, necklace2, necklace3, necklace4, necklace5, necklace6, necklace7, net, oilLamp, potion1, potion2, potion3, potion4, potion5, potion6, potion7, potion8, potion9, potion10, ring1, ring2, ring3, ring4, ring5, scroll1, scroll2, scroll3, scroll4, scroll5, scroll6, scroll7, scroll8, scroll9, shield, dagger, hammer, sword, halberd, wand1, wand2, armorLeather, armorMail, whetstone, grenade1, grenade2]++decipulum, brassLantern, buckler, dart, dart200, gem1, gem2, gem3, gloveFencing, gloveGauntlet, gloveJousting, currency, gorget, harpoon, oculus, necklace1, necklace2, necklace3, necklace4, necklace5, necklace6, necklace7, net, oilLamp, potion1, potion2, potion3, potion4, potion5, potion6, potion7, potion8, potion9, potion10, ring1, ring2, ring3, ring4, ring5, scroll1, scroll2, scroll3, scroll4, scroll5, scroll6, scroll7, scroll8, scroll9, shield, dagger, hammer, sword, halberd, wand1, wand2, armorLeather, armorMail, whetstone, grenade1, grenade2 :: ItemKind++gem, grenade, necklace, potion, ring, scroll, wand :: ItemKind -- generic templates++-- * Thrown weapons++dart = ItemKind+ { isymbol = '|'+ , iname = "dart"+ , ifreq = [("useful", 100), ("any arrow", 100), ("weapon", 100)]+ , iflavour = zipPlain [Cyan]+ , icount = 3 * d 3+ , irarity = [(1, 20)]+ , iverbHit = "prick"+ , iweight = 50+ , iaspects = [AddHurtRanged ((d 6 + dl 6) |*| 10)]+ , ieffects = [Hurt (d 2)]+ , ifeature = []+ , idesc = "Little, but sharp and sturdy."+ , ikit = []+ }+dart200 = ItemKind+ { isymbol = '|'+ , iname = "fine dart"+ , ifreq = [("useful", 100), ("any arrow", 50), ("weapon", 75)]+ , iflavour = zipPlain [BrRed]+ , icount = 3 * d 3+ , irarity = [(4, 20)]+ , iverbHit = "prick"+ , iweight = 50+ , iaspects = [AddHurtRanged ((d 6 + dl 6) |*| 10)]+ , ieffects = [Hurt (d 2)]+ , ifeature = [toVelocity 200]+ , idesc = "Finely balanced for throws of great speed."+ , ikit = []+ }++-- * Exotic thrown weapons++decipulum = ItemKind+ { isymbol = '|'+ , iname = "decipulum majoris"+ , ifreq = [("useful", 100), ("weapon", 50)]+ , iflavour = zipPlain [BrYellow]+ , icount = dl 4+ , irarity = [(5, 5), (10, 5)]+ , iverbHit = "entangle"+ , iweight = 500+ , iaspects = []+ , ieffects = [Hurt (d 2), Paralyze (5 + d 5), ActivateInv '!']+ , ifeature = []+ , idesc = "A web of springs in form of spheres. When thrown, this weapon can trip unwary opponents."+ , ikit = []+ }+harpoon = ItemKind+ { isymbol = '|'+ , iname = "Force spear"+ , ifreq = [("useful", 100), ("starting weapon", 100), ("weapon", 50)]+ , iflavour = zipPlain [Brown]+ , icount = dl 5+ , irarity = [(5, 5), (10, 20)]+ , iverbHit = "hook"+ , iweight = 4000+ , iaspects = [AddHurtRanged ((d 2 + 2 * dl 5) |*| 10)]+ , ieffects = [Hurt (d 4), PullActor (ThrowMod 200 50)]+ , ifeature = []+ , idesc = "The cruel, barbed head lodges in its victim so painfully that the weakest tug of the thin line sends the victim flying."+ , ikit = []+ }+net = ItemKind+ { isymbol = '|'+ , iname = "net"+ , ifreq = [("useful", 100), ("weapon", 60)]+ , iflavour = zipPlain [White]+ , icount = dl 3+ , irarity = [(3, 5), (10, 4)]+ , iverbHit = "entangle"+ , iweight = 1000+ , iaspects = []+ , ieffects = [ Hurt (d 2)+ , Paralyze (5 + d 5)+ , DropBestWeapon, DropEqp ']' False ]+ , ifeature = []+ , idesc = "A web made of monofilaments. Will both cut and entagle the prey."+ , ikit = []+ }++-- * Lights++oilLamp = ItemKind+ { isymbol = '('+ , iname = "oil lamp"+ , ifreq = [("useful", 100)]+ , iflavour = zipPlain [BrYellow]+ , icount = 1+ , irarity = [(5, 4), (10, 4)]+ , iverbHit = "burn"+ , iweight = 1000+ , iaspects = [AddLight 3, AddSight (-1)]+ , ieffects = [Burn 3, Paralyze 3, OnSmash (Explode "burning ignisium 3")]+ , ifeature = [ toVelocity 70+ , Fragile, EqpSlot EqpSlotAddLight "", Identified ]+ , idesc = "A clay lamp filled with ignisium feeding a tiny wick."+ , ikit = []+ }+brassLantern = ItemKind+ { isymbol = '('+ , iname = "brass lantern"+ , ifreq = [("useful", 100)]+ , iflavour = zipPlain [BrWhite]+ , icount = 1+ , irarity = [(10, 3)]+ , iverbHit = "burn"+ , iweight = 2400+ , iaspects = [AddLight 4, AddSight (-1)]+ , ieffects = [Burn 4, Paralyze 4, OnSmash (Explode "burning ignisium 4")]+ , ifeature = [ toVelocity 70 -- hard to throw so that it opens and burns+ , Fragile, EqpSlot EqpSlotAddLight "", Identified ]+ , idesc = "Very bright and very heavy brass lantern."+ , ikit = []+ }++-- * Treasure++gem = ItemKind+ { isymbol = '*'+ , iname = "gem"+ , ifreq = [("treasure", 100)]+ , iflavour = zipPlain $ delete BrYellow brightCol+ , icount = 1+ , irarity = []+ , iverbHit = "tap"+ , iweight = 50+ , iaspects = [AddLight 1, AddSpeed (-1)]+ , ieffects = []+ , ifeature = [ Durable+ , Precious ]+ , idesc = "Useless, and still worth around 100 gold each. Would gems of thought and pearls of artful design be valued that much in our age of Science and Progress!"+ , 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 piece"+ , ifreq = [("treasure", 100), ("currency", 1)]+ , iflavour = zipPlain [BrYellow]+ , icount = 10 + d 20 + dl 20+ , irarity = [(1, 0), (5, 20), (10, 10)]+ , iverbHit = "tap"+ , iweight = 31+ , iaspects = []+ , ieffects = []+ , ifeature = [Durable, Identified, Precious]+ , idesc = "Reliably valuable in every civilized plane of existence."+ , ikit = []+ }++-- * Periodic jewelry++gorget = ItemKind+ { isymbol = '"'+ , iname = "gorget"+ , ifreq = [("useful", 100)]+ , iflavour = zipFancy [BrCyan]+ , irarity = [(4, 1), (10, 2)]+ , icount = 1+ , iverbHit = "whip"+ , iweight = 30+ , iaspects = [Periodic $ d 4 + dl 4, AddArmorMelee 1, AddArmorRanged 1]+ , ieffects = [RefillCalm 1]+ , ifeature = [ Precious, EqpSlot EqpSlotPeriodic "", Identified+ , toVelocity 50 ]+ , 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 = '"'+ , iname = "necklace"+ , ifreq = [("useful", 100)]+ , iflavour = zipFancy stdCol ++ zipPlain brightCol+ , irarity = [(4, 2), (10, 5)]+ , icount = 1+ , iverbHit = "whip"+ , iweight = 30+ , iaspects = []+ , ieffects = []+ , ifeature = [ Precious, EqpSlot EqpSlotPeriodic ""+ , toVelocity 50 ]+ , idesc = "Menacing Greek symbols shimmer with increasing speeds along a chain of fine encrusted links. After a tense build-up, a prismatic arc shoots towards the ground and the iridescence subdues, becomes ordered and resembles a harmless ornament again, for a time."+ , ikit = []+ }+necklace1 = necklace+ { iaspects = [Periodic $ d 2 + dl 2]+ , ieffects = [RefillHP 1]+ , idesc = "A cord of dried herbs and healing berries."+ }+necklace2 = necklace+ { irarity = [(2, 0), (10, 1)]+ , iaspects = [Periodic $ d 4 + dl 2]+ , ieffects = [ Impress+ , Summon [("summonable animal", 1)] $ 1 + dl 2, Explode "waste" ]+ }+necklace3 = necklace+ { iaspects = [Periodic $ d 4 + dl 2]+ , ieffects = [Paralyze $ 5 + d 5 + dl 5, RefillCalm 999]+ }+necklace4 = necklace+ { iaspects = [Periodic $ 2 * d 10 + dl 10]+ , ieffects = [Teleport $ 2 + d 3]+ }+necklace5 = necklace+ { iaspects = [Periodic $ d 4 + dl 2]+ , ieffects = [Teleport $ 10 + d 10]+ }+necklace6 = necklace+ { iaspects = [Periodic $ 2 * d 5 + dl 5]+ , ieffects = [PushActor (ThrowMod 100 50)]+ }+necklace7 = necklace+ { 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)+ }++-- * Non-periodic jewelry++oculus = ItemKind+ { isymbol = '='+ , iname = "oculus cursus"+ , ifreq = [("useful", 100)]+ , iflavour = zipPlain [White]+ , icount = 1+ , irarity = [(6, 0), (10, 1)]+ , iverbHit = "rap"+ , iweight = 50+ , iaspects = [AddSight $ dl 3]+ , ieffects = []+ , ifeature = [Precious, Identified, Durable, EqpSlot EqpSlotAddSight ""]+ , idesc = "Arcane device to boost your sight."+ , ikit = []+ }+ring = ItemKind+ { isymbol = '='+ , iname = "ring"+ , ifreq = [("useful", 100)]+ , iflavour = zipPlain stdCol ++ zipFancy darkCol+ , icount = 1+ , irarity = [(6, 2), (10, 5)]+ , iverbHit = "knock"+ , iweight = 15+ , iaspects = []+ , ieffects = []+ , ifeature = [Precious, Identified]+ , idesc = "It looks like an ordinary object, but it's in fact a generator of exceptional effects: adding to some of your natural abilities and subtracting from others. You'd profit enormously if you could find a way to multiply such generators..."+ , ikit = []+ }+ring1 = ring+ { irarity = [(2, 0), (10, 2)]+ , iaspects = [AddSpeed 1, AddMaxHP $ dl 3 - 5 - d 3]+ , ifeature = ifeature ring ++ [Durable, EqpSlot EqpSlotAddSpeed ""]+ }+ring2 = ring+ { iaspects = [AddMaxHP $ 3 + dl 5, AddMaxCalm $ dl 6 - 15 - d 6]+ , ifeature = ifeature ring ++ [EqpSlot EqpSlotAddMaxHP ""]+ }+ring3 = ring+ { iaspects = [AddMaxCalm $ 10 + dl 10]+ , 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, 8), (10, 12)]+ , iaspects = [AddHurtMelee $ 3 * d 4 + dl 15, AddMaxHP $ dl 3 - 4 - d 2]+ , ifeature = ifeature ring ++ [Durable, EqpSlot EqpSlotAddHurtMelee ""]+ }+ring5 = ring -- by the time it's found, probably no space in eqp+ { irarity = [(5, 0), (10, 1)]+ , iaspects = [AddLight $ d 2]+ , ifeature = ifeature ring ++ [EqpSlot EqpSlotAddLight ""]+ , idesc = "A sturdy ring with a large, shining stone."+ }++-- * Exploding consumables, often intended to be thrown++potion = ItemKind+ { isymbol = '!'+ , iname = "vial"+ , ifreq = [("useful", 100), ("any vial", 100)]+ , iflavour = zipPlain stdCol ++ zipFancy brightCol+ , icount = 1+ , irarity = [(1, 10), (10, 8)]+ , iverbHit = "splash"+ , iweight = 200+ , iaspects = []+ , ieffects = []+ , ifeature = [ toVelocity 50+ , Applicable, Fragile ]+ , idesc = "A flask of bubbly, slightly oily liquid of a suspect color."+ , ikit = []+ }+potion1 = potion+ { ieffects = [ NoEffect "of rose water", Impress+ , OnSmash (ApplyPerfume), OnSmash (Explode "fragrance") ]+ }+potion2 = potion+ { ifreq = [("useful", 1)]+ , irarity = [(10, 1)]+ , ieffects = [ NoEffect "of musky concoction", Impress, DropBestWeapon+ , OnSmash (Explode "pheromone")]+ }+potion3 = potion+ { ieffects = [RefillHP 5, OnSmash (Explode "healing mist")]+ }+potion4 = potion+ { irarity = [(1, 5)]+ , ieffects = [RefillHP (-5), OnSmash (Explode "wounding mist")]+ }+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"+ , OnSmash (Explode "distortion")]+ }+potion7 = potion+ { ieffects = [ NoEffect "of bait cocktail", Impress+ , OnSmash (Summon [("summonable 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" ]) ]+ }+potion9 = potion+ { irarity = [(4, 1), (10, 2)]+ , ieffects = [ OneOf [ Dominate, DropBestWeapon, RefillHP 15, Burn 9+ , InsertMove 2]+ , OnSmash (OneOf [ Explode "healing mist"+ , Explode "healing mist"+ , Explode "pheromone"+ , Explode "distortion"+ , Explode "explosion blast 20" ]) ]+ }+potion10 = potion+ { ifreq = [("useful", 100), ("potion of glue", 1)]+ , irarity = [(1, 1)]+ , icount = 1 + d 2+ , ieffects = [ NoEffect "of glue", Paralyze (5 + d 5)+ , OnSmash (Explode "glue")]+ }+grenade = ItemKind+ { isymbol = '*'+ , iname = "grenade"+ , ifreq = [("useful", 100), ("weapon", 25)]+ , iflavour = zipPlain stdCol ++ zipFancy brightCol+ , icount = 1+ , irarity = [(1, 1), (10, 3)]+ , iverbHit = "explode"+ , iweight = 200+ , iaspects = []+ , ieffects = []+ , ifeature = [ toVelocity 200+ , Fragile + , Identified ]+ , idesc = "Small metal canister, with safety latch and finely engraved surface."+ , ikit = []+ }+grenade1 = grenade+ { irarity = [(1, 1), (10, 3)]+ , ieffects = [ NoEffect "of explosionis"+ , OnSmash (Explode "explosion blast 10") ]+ }+grenade2 = grenade+ { irarity = [(1, 1), (10, 3)]+ , ieffects = [ NoEffect "of ignisium"+ , OnSmash (Explode "burning ignisium 2") ]+ }+-- * Non-exploding consumables, not specifically designed for throwing++scroll = ItemKind+ { isymbol = '?'+ , iname = "scroll"+ , ifreq = [("useful", 100), ("any scroll", 100)]+ , iflavour = zipFancy stdCol ++ zipPlain darkCol+ , icount = 1+ , irarity = [(1, 10), (10, 7)]+ , iverbHit = "thump"+ , iweight = 50+ , iaspects = []+ , ieffects = []+ , ifeature = [ toVelocity 25+ , Applicable ]+ , idesc = "Scraps of haphazardly scribbled mysteries from beyond. Is this equation an alchemical recipe? Is this diagram an extradimensional map? Is this formula a secret call sign?"+ , ikit = []+ }+scroll1 = scroll+ { irarity = [(10, 2)]+ , ieffects = [CallFriend 1]+ }+scroll2 = scroll+ { irarity = [(1, 5), (10, 3)]+ , ieffects = [NoEffect "of fireworks", Explode "firecracker 7"]+ }+scroll3 = scroll+ { irarity = [(1, 4), (10, 2)]+ , ieffects = [Ascend (-1)]+ }+scroll4 = scroll+ { ieffects = [ OneOf [ Teleport $ 2 + d 5, RefillCalm 10, RefillCalm (-10)+ , InsertMove 4, Paralyze 10, Identify CGround ] ]+ }+scroll5 = scroll+ { irarity = [(1, 4), (10, 6)]+ , ieffects = [ OneOf [ Summon standardSummon $ d 2+ , CallFriend 1, Ascend (-1), Ascend 1+ , RefillCalm 30, RefillCalm (-30), CreateItem $ d 2+ , PolyItem CGround ] ]+ -- TODO: ask player: Escape 1+ }+scroll6 = scroll+ { ieffects = [Teleport $ 2 + d 5]+ }+scroll7 = scroll+ { irarity = [(10, 2)]+ , ieffects = [InsertMove $ d 2 + dl 2]+ }+scroll8 = scroll+ { irarity = [(3, 6), (10, 3)]+ , ieffects = [Identify CGround] -- TODO: ask player: AskPlayer cstore eff?+ }+scroll9 = scroll+ { irarity = [(3, 3), (10, 9)]+ , ieffects = [PolyItem CGround]+ }++standardSummon :: Freqs+standardSummon = [("monster", 30), ("summonable animal", 70)]++-- * Armor++armorLeather = ItemKind+ { isymbol = '['+ , iname = "leather armor"+ , ifreq = [("useful", 100), ("armour", 100)]+ , iflavour = zipPlain [Brown]+ , icount = 1+ , irarity = [(4, 9)]+ , iverbHit = "thud"+ , iweight = 7000+ , iaspects = [ AddHurtMelee (-3)+ , AddArmorMelee $ (1 + dl 3) |*| 5+ , AddArmorRanged $ (1 + dl 3) |*| 5 ]+ , ieffects = []+ , ifeature = [ toVelocity 30+ , Durable, EqpSlot EqpSlotAddArmorMelee "", Identified ]+ , idesc = "A stiff jacket formed from leather boiled in bee wax. Smells much better than the rest of your garment."+ , ikit = []+ }+armorMail = armorLeather+ { iname = "mail armor"+ , iflavour = zipPlain [Cyan]+ , irarity = [(7, 9)]+ , iweight = 12000+ , iaspects = [ AddHurtMelee (-3)+ , AddArmorMelee $ (2 + dl 3) |*| 5+ , AddArmorRanged $ (2 + dl 3) |*| 5 ]+ , idesc = "A long shirt woven from iron rings. Discourages foes from attacking your torso, making it harder for them to land a blow."+ }+gloveFencing = ItemKind+ { isymbol = '['+ , iname = "leather gauntlet"+ , ifreq = [("useful", 100), ("armour", 100)]+ , iflavour = zipPlain [BrYellow]+ , icount = 1+ , irarity = [(4, 6), (10, 12)]+ , iverbHit = "flap"+ , iweight = 100+ , iaspects = [ AddHurtMelee $ 2 * (d 3 + 2 * dl 5)+ , AddArmorRanged $ d 2 + dl 2 ]+ , ieffects = []+ , ifeature = [ toVelocity 30+ , Durable, EqpSlot EqpSlotAddArmorRanged "", Identified ]+ , idesc = "A fencing glove from rough leather ensuring a good grip. Also quite effective in deflecting or even catching slow projectiles."+ , ikit = []+ }+gloveGauntlet = gloveFencing+ { iname = "steel gauntlet"+ , irarity = [(6, 12)]+ , iflavour = zipPlain [BrCyan]+ , iweight = 300+ , iaspects = [ AddArmorMelee $ 2 * (d 2 + dl 2)+ , AddArmorRanged $ 2 * (d 2 + dl 2) ]+ , idesc = "Long leather gauntlet covered in overlapping steel plates."+ }+gloveJousting = gloveFencing+ { iname = "jousting gauntlet"+ , irarity = [(6, 6)]+ , iflavour = zipFancy [BrRed]+ , iweight = 500+ , iaspects = [ AddHurtMelee $ - 10 - d 5 + dl 5+ , AddArmorMelee $ 2 * (d 2 + dl 3)+ , AddArmorRanged $ 2 * (d 2 + dl 3) ]+ , idesc = "Rigid, steel, jousting handgear. If only you had a lance. And a horse."+ }++buckler = ItemKind+ { isymbol = '['+ , iname = "buckler"+ , ifreq = [("useful", 100), ("armour", 100)]+ , iflavour = zipPlain [Blue]+ , icount = 1+ , irarity = [(4, 7)]+ , iverbHit = "bash"+ , iweight = 2000+ , iaspects = [AddArmorMelee 40, AddHurtMelee (-30)]+ , ieffects = []+ , ifeature = [ toVelocity 30+ , Durable, EqpSlot EqpSlotAddArmorMelee "", Identified ]+ , idesc = "Heavy and unwieldy. Absorbs a percentage of melee damage, both dealt and sustained. Too small to intercept projectiles with."+ , ikit = []+ }+shield = buckler+ { iname = "shield"+ , irarity = [(7, 7)]+ , iflavour = zipPlain [Green]+ , iweight = 3000+ , iaspects = [AddArmorMelee 80, AddHurtMelee (-70)]+ , ifeature = [ toVelocity 20+ , Durable, EqpSlot EqpSlotAddArmorMelee "", Identified ]+ , idesc = "Large and unwieldy. Absorbs a percentage of melee damage, both dealt and sustained. Too heavy to intercept projectiles with."+ }++-- * Weapons++dagger = ItemKind+ { isymbol = ')'+ , iname = "dagger"+ , ifreq = [("useful", 100), ("starting weapon", 100), ("weapon", 100)]+ , iflavour = zipPlain [BrCyan]+ , icount = 1+ , irarity = [(1, 20), (10, 4)]+ , iverbHit = "stab"+ , iweight = 1000+ , iaspects = [AddHurtMelee $ 2 * (d 3 + 2 * dl 5), AddArmorMelee $ d 4 + dl 4]+ , ieffects = [Hurt (d 4)]+ , ifeature = [ toVelocity 40+ , Durable, EqpSlot EqpSlotWeapon "", Identified ]+ , idesc = "A short dagger for thrusting and parrying blows. Does not penetrate deeply, but is hard to block. Especially useful in conjunction with a larger weapon."+ , ikit = []+ }+hammer = ItemKind+ { isymbol = ')'+ , iname = "storm hammer"+ , ifreq = [("useful", 100), ("weapon", 60), ("starting weapon", 100)]+ , iflavour = zipPlain [BrMagenta]+ , icount = 1+ , irarity = [(4, 12), (10, 2)]+ , iverbHit = "club"+ , iweight = 1500+ , iaspects = [AddHurtMelee $ d 3 + 2 * dl 5]+ , ieffects = [Hurt (d 6), PushActor (ThrowMod 200 50)]+ , ifeature = [ toVelocity 20+ , Durable, EqpSlot EqpSlotWeapon "", Identified ]+ , idesc = "Mighty hammer that releases blast of electricity when it hits target."+ , ikit = []+ }+sword = ItemKind+ { isymbol = ')'+ , iname = "sword"+ , ifreq = [("useful", 100), ("starting weapon", 100), ("weapon", 75)]+ , iflavour = zipPlain [BrBlue]+ , icount = 1+ , irarity = [(3, 1), (6, 20), (10, 10)]+ , iverbHit = "slash"+ , iweight = 2000+ , iaspects = []+ , ieffects = [Hurt (d 8)]+ , ifeature = [ toVelocity 20+ , Durable, EqpSlot EqpSlotWeapon "", Identified ]+ , idesc = "Common vibroblade, favoured by those who like to get close and personal."+ , ikit = []+ }+halberd = ItemKind+ { isymbol = ')'+ , iname = "halberd"+ , ifreq = [("useful", 100), ("weapon", 50)]+ , iflavour = zipPlain [BrYellow]+ , icount = 1+ , irarity = [(7, 1), (10, 10)]+ , iverbHit = "impale"+ , iweight = 3000+ , iaspects = [AddArmorMelee $ 2 * (d 4 + dl 4)]+ , ieffects = [Hurt (d 12)]+ , ifeature = [ toVelocity 20+ , Durable, EqpSlot EqpSlotWeapon "", Identified ]+ , idesc = "Versatile, with great reach and leverage. Foes are held at a distance."+ , ikit = []+ }++-- * Wands++wand = ItemKind+ { isymbol = '/'+ , iname = "wand"+ , ifreq = [("useful", 100)]+ , iflavour = zipFancy brightCol+ , icount = 1+ , irarity = [] -- TODO: add charges, etc.+ , iverbHit = "club"+ , iweight = 300+ , iaspects = [AddLight 1, AddSpeed (-1)]+ , ieffects = []+ , ifeature = [ toVelocity 125+ , Applicable, Durable ]+ , idesc = "Buzzing with dazzling light that shines even through appendages that handle it."+ , ikit = []+ }+wand1 = wand+ { ieffects = []+ }+wand2 = wand+ { ieffects = []+ }++-- * Assorted tools++whetstone = ItemKind+ { isymbol = '~'+ , iname = "whetstone"+ , ifreq = [("useful", 100)]+ , iflavour = zipPlain [Blue]+ , icount = 1+ , irarity = [(5, 5)]+ , iverbHit = "smack"+ , iweight = 400+ , iaspects = [AddHurtMelee $ 2 * (d 3 + 2 * dl 5)]+ , ieffects = []+ , ifeature = [EqpSlot EqpSlotAddHurtMelee "", Identified]+ , idesc = "A portable sharpening stone that lets 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 = []+ }
+ GameDefinition/Content/ItemKindActor.hs view
@@ -0,0 +1,165 @@+-- | Actor (or rather actor body trunk) definitions.+module Content.ItemKindActor ( actors ) where++import qualified Data.EnumMap.Strict as EM++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 = privateers ++ merchants ++ forcesOfChaos ++ spawns ++ animals++privateers, merchants, forcesOfChaos, spawns, animals :: [ItemKind]++privateers = [warrior, scout]+merchants = [merchant, merchantSgt]+forcesOfChaos = [chaosWarrior, chaosLord]+spawns = [warpBeast]+animals = [ventLizard]++warrior, scout :: ItemKind+merchant, merchantSgt :: ItemKind+chaosWarrior, chaosLord :: ItemKind+warpBeast :: ItemKind+ventLizard :: ItemKind++-- * Heroes (hero)++warrior = ItemKind+ { isymbol = '@'+ , iname = "warrior"+ , ifreq = [("hero", 100)]+ , iflavour = zipPlain [BrBlack]+ , icount = 1+ , irarity = [(1, 5)]+ , iverbHit = "thud"+ , iweight = 80000+ , iaspects = [ AddMaxHP 50, AddMaxCalm 60, AddSpeed 20+ , AddSight 3 ]+ , ieffects = []+ , ifeature = [Durable, Identified]+ , idesc = "PBI, ready to take the next city vessel."+ , ikit = [("fist", COrgan), ("foot", COrgan), ("eye 4", COrgan),+ ("starting weapon", CEqp)]+ }++scout = warrior+ { iname = "scout"+ , iaspects = [ AddMaxHP 40, AddMaxCalm 60, AddSpeed 25+ , AddSight 4 ]+ , idesc = "Fast and keen scouts are essential any fighting force."+ , ikit = [("fist", COrgan), ("foot", COrgan), ("eye 5", COrgan),+ ("any arrow", CInv), ("any vial", CInv), ("any vial", CInv)]+ }++-- * Merchant Mariners (merchant)++merchant = ItemKind+ { isymbol = '@'+ , iname = "merchant mariner"+ , ifreq = [("merchant", 100)]+ , iflavour = zipPlain [Blue]+ , icount = 1+ , irarity = [(1, 10)]+ , iverbHit = "thud"+ , iweight = 80000+ , iaspects = [ AddMaxHP 30, AddMaxCalm 40, AddSpeed 20+ , AddSight 3 ]+ , ieffects = []+ , ifeature = [Durable, Identified]+ , idesc = "Merchant mariners are operating city vessels on their endless journey to stars."+ , ikit = [("fist", COrgan), ("foot", COrgan), ("eye 4", COrgan)]+ }++merchantSgt = merchant+ { iname = "merchant mariner sgt"+ , ifreq = [("merchant", 100)]+ , iflavour = zipPlain [BrBlue]+ , icount = 1+ , irarity = [(1, 1), (10, 3)]+ , iverbHit = "thud"+ , iweight = 80000+ , iaspects = [ AddMaxHP 40, AddMaxCalm 60, AddSpeed 20+ , AddSight 3 ]+ , ieffects = []+ , ifeature = [Durable, Identified]+ , idesc = "Squad leader for merchant mariners"+ , ikit = [("fist", COrgan), ("foot", COrgan), ("eye 4", COrgan),+ ("starting weapon", CEqp)]+ }++-- * Forces of Chaos (chaos)++chaosWarrior = ItemKind+ { isymbol = 'c'+ , iname = "chaos warrior"+ , ifreq = [("chaos", 100)]+ , iflavour = zipPlain [BrBlack]+ , icount = 1+ , irarity = [(1, 5)]+ , iverbHit = "thud"+ , iweight = 100000+ , iaspects = [ AddMaxHP 40, AddMaxCalm 70, AddSpeed 20+ , AddSight 3 ]+ , ieffects = []+ , ifeature = [Durable, Identified]+ , idesc = "Warrior of Chaos, ready to wreck havoc."+ , ikit = [("fist", COrgan), ("foot", COrgan), ("eye 4", COrgan),+ ("starting weapon", CEqp)]+ }++chaosLord = chaosWarrior+ { isymbol = 'c'+ , iname = "chaos lord"+ , ifreq = [("chaos", 100)]+ , irarity = [(5, 1), (10, 3)]+ , iflavour = zipPlain [BrRed]+ , iaspects = [ AddMaxHP 60, AddMaxCalm 70, AddSpeed 20+ , AddSight 3 ]+ , idesc = "Lord of Chaos, leader of warriors"+ }++-- * Horrors (spawn)++warpBeast = ItemKind+ { isymbol = 'w'+ , iname = "warp beast"+ , ifreq = [("spawn", 100)]+ , iflavour = zipPlain [BrRed]+ , icount = 1+ , irarity = [(1, 5)]+ , iverbHit = "thud"+ , iweight = 40000+ , iaspects = [ AddMaxHP 20, AddMaxCalm 30, AddSpeed 20+ , AddSight 1 ]+ , ieffects = []+ , ifeature = [Durable, Identified]+ , idesc = "Shambling beast of warp has phased into this corporeal realm."+ , ikit = [("small claw", COrgan), ("foot", COrgan), ("eye 2", COrgan),+ ("nostril", COrgan)]+ }++-- * Animals++ventLizard = ItemKind+ { isymbol = ':'+ , iname = "vent lizard"+ , ifreq = [("summonable animal", 100)]+ , iflavour = zipPlain [Green]+ , icount = 1+ , irarity = [(1, 5)]+ , iverbHit = "thud"+ , iweight = 25000+ , iaspects = [ AddMaxHP 15, AddMaxCalm 30, AddSpeed 18+ , AddSkills $ EM.singleton AbAlter (-1)+ , AddSight 3 ]+ , ieffects = []+ , ifeature = [Durable, Identified]+ , idesc = ""+ , ikit = [ ("claw", COrgan), ("snout", COrgan), ("armored skin", COrgan)+ , ("nostril", COrgan) ]+ }
+ GameDefinition/Content/ItemKindOrgan.hs view
@@ -0,0 +1,259 @@+-- | Organ definitions.+module Content.ItemKindOrgan ( organs ) 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.Msg+import Game.LambdaHack.Content.ItemKind++organs :: [ItemKind]+organs =+ [fist, foot, tentacle, lash, noseTip, lip, claw, smallClaw, snout, sting, venomTooth, venomFang, largeTail, jaw, largeJaw, tooth, pupil, armoredSkin, speedGland2, speedGland4, speedGland6, speedGland8, speedGland10, eye2, eye3, eye4, eye5, nostril, thorn, vent, fissure]++fist, foot, tentacle, lash, noseTip, lip, claw, smallClaw, snout, sting, venomTooth, venomFang, largeTail, jaw, largeJaw, tooth, pupil, armoredSkin, speedGland2, speedGland4, speedGland6, speedGland8, speedGland10, eye2, eye3, eye4, eye5, nostril, thorn, vent, fissure :: ItemKind++-- * Parameterized organs++speedGland :: Int -> ItemKind+speedGland n = fist+ { iname = "speed gland"+ , ifreq = [("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 = [("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++-- * Human weapon organs++fist = ItemKind+ { isymbol = '%'+ , iname = "fist"+ , ifreq = [("fist", 100)]+ , iflavour = zipPlain [BrRed]+ , icount = 2+ , irarity = [(1, 1)]+ , iverbHit = "punch"+ , iweight = 2000+ , iaspects = []+ , ieffects = [Hurt (d 2)]+ , ifeature = [Durable, EqpSlot EqpSlotWeapon "", Identified]+ , idesc = ""+ , ikit = []+ }+foot = fist+ { iname = "foot"+ , ifreq = [("foot", 50)]+ , icount = 2+ , iverbHit = "kick"+ , ieffects = [Hurt (d 2)]+ , idesc = ""+ }++-- * Universal weapon organs++claw = fist+ { iname = "claw"+ , ifreq = [("claw", 50)]+ , icount = 2+ , iverbHit = "slash"+ , ieffects = [Hurt (d 4)]+ , idesc = ""+ }+smallClaw = fist+ { iname = "small claw"+ , ifreq = [("small claw", 50)]+ , icount = 2+ , iverbHit = "slash"+ , ieffects = [Hurt (d 2)]+ , idesc = ""+ }+snout = fist+ { iname = "snout"+ , ifreq = [("snout", 10)]+ , iverbHit = "bite"+ , ieffects = [Hurt (d 2)]+ , idesc = ""+ }+jaw = fist+ { iname = "jaw"+ , ifreq = [("jaw", 20)]+ , icount = 1+ , iverbHit = "rip"+ , ieffects = [Hurt (d 4)]+ , idesc = ""+ }+largeJaw = fist+ { iname = "large jaw"+ , ifreq = [("large jaw", 100)]+ , icount = 1+ , iverbHit = "crush"+ , ieffects = [Hurt (d 6)]+ , idesc = ""+ }+tooth = fist+ { iname = "tooth"+ , ifreq = [("tooth", 20)]+ , icount = 3+ , iverbHit = "nail"+ , ieffects = [Hurt (d 4)]+ , idesc = ""+ }++-- * Monster weapon organs++tentacle = fist+ { iname = "tentacle"+ , ifreq = [("tentacle", 50)]+ , icount = 4+ , iverbHit = "slap"+ , ieffects = [Hurt (d 4)]+ , idesc = ""+ }+lash = fist+ { iname = "lash"+ , ifreq = [("lash", 100)]+ , icount = 1+ , iverbHit = "lash"+ , ieffects = [Hurt (d 6)]+ , idesc = ""+ }+noseTip = fist+ { iname = "tip"+ , ifreq = [("nose tip", 50)]+ , icount = 1+ , iverbHit = "poke"+ , ieffects = [Hurt (d 4)]+ , idesc = ""+ }+lip = fist+ { iname = "lip"+ , ifreq = [("lip", 10)]+ , icount = 2+ , iverbHit = "lap"+ , ieffects = [Hurt (d 2)]+ , idesc = ""+ }++-- * Special weapon organs++thorn = fist+ { iname = "thorn"+ , ifreq = [("thorn", 100)]+ , icount = 7+ , iverbHit = "impale"+ , ieffects = [Hurt (d 2)]+ , idesc = ""+ }+fissure = fist+ { iname = "fissure"+ , ifreq = [("fissure", 100)]+ , icount = 2+ , iverbHit = "hiss at"+ , ieffects = [Burn 1]+ , idesc = ""+ }+sting = fist+ { iname = "sting"+ , ifreq = [("sting", 100)]+ , icount = 1+ , iverbHit = "sting"+ , ieffects = [Burn 1, Paralyze 2]+ , idesc = ""+ }+venomTooth = fist+ { iname = "venom tooth"+ , ifreq = [("venom tooth", 100)]+ , icount = 2+ , iverbHit = "bite"+ , ieffects = [Hurt (d 2), Paralyze 3]+ , idesc = ""+ }+venomFang = fist+ { iname = "venom fang"+ , ifreq = [("venom fang", 100)]+ , icount = 2+ , iverbHit = "bite"+ , ieffects = [Hurt (d 4)]+ , idesc = ""+ }+largeTail = fist+ { iname = "large tail"+ , ifreq = [("large tail", 50)]+ , icount = 1+ , iverbHit = "knock"+ , ieffects = [Hurt (d 8), PushActor (ThrowMod 400 25)]+ , idesc = ""+ }+pupil = fist+ { iname = "pupil"+ , ifreq = [("pupil", 100)]+ , icount = 1+ , iverbHit = "gaze at"+ , iaspects = [AddSight 7]+ , ieffects = [Hurt (d 2), Paralyze 1]+ , idesc = ""+ }++-- * Armor organs++armoredSkin = fist+ { iname = "armored skin"+ , ifreq = [("armored skin", 100)]+ , icount = 1+ , iverbHit = "bash"+ , iaspects = [AddArmorMelee 33, AddArmorRanged 33]+ , ieffects = []+ , ifeature = [Durable, Identified]+ , idesc = ""+ }++-- * Sense organs++nostril = fist+ { iname = "nostril"+ , ifreq = [("nostril", 100)]+ , icount = 2+ , iverbHit = "snuff"+ , iaspects = [AddSmell 1]+ , ieffects = []+ , ifeature = [Durable, Identified]+ , idesc = ""+ }++-- * Assorted++vent = fist+ { iname = "vent"+ , ifreq = [("vent", 100)]+ , icount = 1+ , iverbHit = "menace"+ , iaspects = [Periodic $ 1 + d 2]+ , ieffects = [Explode "boiling water"]+ , ifeature = [Durable, Identified]+ , idesc = ""+ }
+ GameDefinition/Content/ItemKindShrapnel.hs view
@@ -0,0 +1,239 @@+-- | 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.Msg+import Game.LambdaHack.Content.ItemKind++shrapnels :: [ItemKind]+shrapnels =+ [fragrance, pheromone, firecracker2, firecracker3, firecracker4, firecracker5, firecracker6, firecracker7, mistHealing, mistWounding, distortion, waste, burningIgnisium2, burningIgnisium3, burningIgnisium4, explosionBlast10, explosionBlast20, glassPiece, smoke, boilingWater, glue]++fragrance, pheromone, firecracker2, firecracker3, firecracker4, firecracker5, firecracker6, firecracker7, mistHealing, mistWounding, distortion, waste, burningIgnisium2, burningIgnisium3, burningIgnisium4, explosionBlast10, explosionBlast20, glassPiece, smoke, boilingWater, glue :: ItemKind++-- * Parameterized shrapnel++burningIgnisium :: Int -> ItemKind+burningIgnisium n = ItemKind+ { isymbol = '*'+ , iname = "burning ignisium"+ , ifreq = [("burning ignisium" <+> tshow n, 1)]+ , iflavour = zipFancy [BrYellow]+ , icount = intToDice (n * 5)+ , irarity = [(1, 1)]+ , iverbHit = "burn"+ , iweight = 1+ , iaspects = [AddLight 3]+ , ieffects = [ Burn (n `div` 2)+ , Paralyze (intToDice $ n `div` 2) ]+ , ifeature = [ toVelocity (min 100 $ n * 7)+ , Fragile, Identified ]+ , idesc = "Flaming ignisium, burning brightly."+ , ikit = []+ }+burningIgnisium2 = burningIgnisium 2+burningIgnisium3 = burningIgnisium 3+burningIgnisium4 = burningIgnisium 4+explosionBlast :: Int -> ItemKind+explosionBlast n = ItemKind+ { isymbol = '*'+ , iname = "explosion blast"+ , ifreq = [("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 = [("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 $ "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 = []+ }+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 = "hoof glue"+ , 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/ModeKind.hs view
@@ -0,0 +1,113 @@+-- | The type of kinds of game modes for Space Privateers.+module Content.ModeKind ( cdefs ) where++import qualified Data.IntMap.Strict as IM++import Game.LambdaHack.Common.ContentDef+import Game.LambdaHack.Content.ModeKind++cdefs :: ContentDef ModeKind+cdefs = ContentDef+ { getSymbol = msymbol+ , getName = mname+ , getFreq = mfreq+ , validate = validateModeKind+ , content =+ [campaign]+ }+campaign :: ModeKind++campaign = ModeKind+ { msymbol = 'a'+ , mname = "campaign"+ , mfreq = [("campaign", 1)]+ , mplayers = playersCampaign+ , mcaves = cavesCampaign+ , mdesc = "Get ready to assault the city vessel and plunder some loot!"+ }++playersCampaign :: Players++playersCampaign = Players+ { playersList = [ playerHero+ , playerMerchant+ , playerChaos+ , playerHorror+ , playerSpawn ]+ , playersEnemy = [ ("Space Privateers", "Merchant Mariners")+ , ("Space Privateers", "Forces of Chaos") + , ("Space Privateers", "Spawns of Warp")+ , ("Merchant Mariners", "Forces of Chaos") + , ("Merchant Mariners", "Spawns of Warp") ]+ , playersAlly = [("Forces of Chaos", "Spawns of Warp")] }++playerHero, playerMerchant, playerChaos, playerSpawn, playerHorror :: Player++playerHero = Player+ { playerName = "Space Privateers"+ , playerFaction = "hero"+ , playerIsSpawn = False+ , playerIsHero = True+ , playerEntry = -1+ , playerInitial = 3+ , playerLeader = True+ , playerAI = False+ , playerUI = True+ }++playerMerchant = Player+ { playerName = "Merchant Mariners"+ , playerFaction = "merchant"+ , playerIsSpawn = True+ , playerIsHero = False+ , playerEntry = -1+ , playerInitial = 3+ , playerLeader = False+ , playerAI = True+ , playerUI = False+ }++playerChaos = Player+ { playerName = "Forces of Chaos"+ , playerFaction = "chaos"+ , playerIsSpawn = True+ , playerIsHero = False+ , playerEntry = -1+ , playerInitial = 5+ , playerLeader = False+ , playerAI = True+ , playerUI = False+ }++playerHorror = Player+ { playerName = "Horrors of Warp"+ , playerFaction = "horror"+ , playerIsSpawn = True+ , playerIsHero = False+ , playerEntry = -1+ , playerInitial = 0+ , playerLeader = False+ , playerAI = True+ , playerUI = False+ }++playerSpawn = Player+ { playerName = "Spawns of Warp"+ , playerFaction = "spawn"+ , playerIsSpawn = True+ , playerIsHero = False+ , playerEntry = -1+ , playerInitial = 0+ , playerLeader = False+ , playerAI = True+ , playerUI = False+ }++cavesCampaign :: Caves++cavesCampaign = IM.fromList $ [ (-1, ("caveRogue", Just True))+ , (-2, ("caveRogue", Nothing))+ , (-3, ("caveRogue", Nothing)) ]+ ++ zip [-4, -5..(-9)] (repeat ("dng", Nothing))+ ++ [(-10, ("caveRogue", Nothing))]+
+ GameDefinition/Content/PlaceKind.hs view
@@ -0,0 +1,185 @@+-- | Rooms, halls and passages for Space Privateers.+module Content.PlaceKind ( cdefs ) where++import Game.LambdaHack.Common.ContentDef+import Game.LambdaHack.Content.PlaceKind++cdefs :: ContentDef PlaceKind+cdefs = ContentDef+ { getSymbol = psymbol+ , getName = pname+ , getFreq = pfreq+ , validate = validatePlaceKind+ , content =+ [rect, ruin, collapsed, collapsed2, collapsed3, collapsed4, pillar, pillarC, pillar3, colonnade, colonnade2, colonnade3, lampPost, lampPost2, lampPost3, lampPost4, treeShade, treeShade2, treeShade3]+ }+rect, ruin, collapsed, collapsed2, collapsed3, collapsed4, pillar, pillarC, pillar3, colonnade, colonnade2, colonnade3, lampPost, lampPost2, lampPost3, lampPost4, treeShade, treeShade2, treeShade3 :: PlaceKind++rect = PlaceKind -- Valid for any nonempty area, hence low frequency.+ { psymbol = 'r'+ , pname = "room"+ , pfreq = [("rogue", 100), ("ambush", 8)]+ , prarity = [(1, 1)]+ , pcover = CStretch+ , pfence = FNone+ , ptopLeft = [ "--"+ , "|."+ ]+ , poverride = []+ }+ruin = PlaceKind+ { psymbol = 'R'+ , pname = "ruin"+ , pfreq = [("ambush", 17), ("battle", 100)]+ , prarity = [(1, 1)]+ , pcover = CStretch+ , pfence = FNone+ , ptopLeft = [ "--"+ , "|X"+ ]+ , poverride = []+ }+collapsed = PlaceKind+ { psymbol = 'c'+ , pname = "collapsed cavern"+ , pfreq = [("noise", 1)]+ , prarity = [(1, 1)]+ , pcover = CStretch+ , pfence = FNone+ , ptopLeft = [ "O"+ ]+ , poverride = []+ }+collapsed2 = collapsed+ { pfreq = [("noise", 100), ("battle", 50)]+ , ptopLeft = [ "XXO"+ , "XOO"+ ]+ }+collapsed3 = collapsed+ { pfreq = [("noise", 200), ("battle", 50)]+ , ptopLeft = [ "XXXO"+ , "XOOO"+ ]+ }+collapsed4 = collapsed+ { pfreq = [("noise", 400), ("battle", 200)]+ , ptopLeft = [ "XXXO"+ , "XXXO"+ , "XOOO"+ ]+ }+pillar = PlaceKind+ { psymbol = 'p'+ , pname = "pillar room"+ , pfreq = [("rogue", 1000)] -- larger rooms require support pillars+ , prarity = [(1, 1)]+ , pcover = CStretch+ , pfence = FNone+ , ptopLeft = [ "-----"+ , "|...."+ , "|.O.."+ , "|...."+ , "|...."+ ]+ , poverride = []+ }+pillarC = pillar+ { ptopLeft = [ "-----"+ , "|O..."+ , "|...."+ , "|...."+ , "|...."+ ]+ }+pillar3 = pillar+ { ptopLeft = [ "-----"+ , "|&.O."+ , "|...."+ , "|O..."+ , "|...."+ ]+ }+colonnade = PlaceKind+ { psymbol = 'c'+ , pname = "colonnade"+ , pfreq = [("rogue", 60)]+ , prarity = [(1, 1)]+ , pcover = CAlternate+ , pfence = FFloor+ , ptopLeft = [ "O."+ , ".O"+ ]+ , poverride = []+ }+colonnade2 = colonnade+ { ptopLeft = [ "O."+ , ".."+ ]+ }+colonnade3 = colonnade+ { pfreq = [("rogue", 6)]+ , ptopLeft = [ ".."+ , ".O"+ ]+ }+lampPost = PlaceKind+ { psymbol = 'l'+ , pname = "lamp post"+ , pfreq = [("ambush", 30), ("battle", 10)]+ , prarity = [(1, 1)]+ , pcover = CVerbatim+ , pfence = FNone+ , ptopLeft = [ "X.X"+ , ".O."+ , "X.X"+ ]+ , poverride = [('O', "lampPostOver_O")]+ }+lampPost2 = lampPost+ { ptopLeft = [ "..."+ , ".O."+ , "..."+ ]+ }+lampPost3 = lampPost+ { ptopLeft = [ "XX.XX"+ , "X...X"+ , "..O.."+ , "X...X"+ , "XX.XX"+ ]+ }+lampPost4 = lampPost+ { ptopLeft = [ "X...X"+ , "....."+ , "..O.."+ , "....."+ , "X...X"+ ]+ }+treeShade = PlaceKind+ { psymbol = 't'+ , pname = "tree shade"+ , pfreq = [("skirmish", 100)]+ , prarity = [(1, 1)]+ , pcover = CVerbatim+ , pfence = FNone+ , ptopLeft = [ "sss"+ , "XOs"+ , "XXs"+ ]+ , poverride = [('O', "treeShadeOver_O"), ('s', "treeShadeOver_s")]+ }+treeShade2 = treeShade+ { ptopLeft = [ "sss"+ , "XOs"+ , "Xss"+ ]+ }+treeShade3 = treeShade+ { ptopLeft = [ "sss"+ , "sOs"+ , "XXs"+ ]+ }
+ GameDefinition/Content/RuleKind.hs view
@@ -0,0 +1,54 @@+{-# LANGUAGE TemplateHaskell #-}+-- | Game rules and assorted game setup data for Space Privateer.+module Content.RuleKind ( cdefs ) where++import Language.Haskell.TH.Syntax+import System.FilePath++-- Cabal+import qualified Paths_SpacePrivateers as Self (getDataFileName, version)++import Game.LambdaHack.Common.ContentDef+import Game.LambdaHack.Common.Vector+import Game.LambdaHack.Content.RuleKind++cdefs :: ContentDef RuleKind+cdefs = ContentDef+ { getSymbol = rsymbol+ , getName = rname+ , getFreq = rfreq+ , validate = validateRuleKind+ , content =+ [standard]+ }++standard :: RuleKind+standard = RuleKind+ { rsymbol = 's'+ , rname = "standard Space Privateers ruleset"+ , rfreq = [("standard", 100)]+ , raccessible = Nothing+ , raccessibleDoor =+ Just $ \spos tpos -> not $ isDiagonal $ spos `vectorToFrom` tpos+ , rtitle = "Space Privateers"+ , rpathsDataFile = Self.getDataFileName+ , rpathsVersion = Self.version+ , rcfgUIName = "config.ui"+ , rcfgUIDefault = $(do+ let path = "GameDefinition" </> "config.ui" <.> "default"+ qAddDependentFile path+ x <- qRunIO (readFile path)+ lift x)+ , rmainMenuArt = $(do+ let path = "GameDefinition/MainMenu.ascii"+ qAddDependentFile path+ x <- qRunIO (readFile path)+ lift x)+ , rfirstDeathEnds = False+ , rfovMode = Digital+ , rsaveBkpClips = 500+ , rleadLevelClips = 100+ , rscoresFile = "scores"+ , rsavePrefix = "save"+ , rsharedStash = True+ }
+ GameDefinition/Content/TileKind.hs view
@@ -0,0 +1,307 @@+-- | Terrain tiles for Space Privateers+module Content.TileKind ( cdefs ) where++import Control.Arrow (first)+import Data.Maybe+import Data.Text (Text)+import qualified Data.Text as T++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.Msg+import Game.LambdaHack.Content.TileKind++cdefs :: ContentDef TileKind+cdefs = ContentDef+ { getSymbol = tsymbol+ , getName = tname+ , getFreq = tfreq+ , validate = validateTileKind+ , content =+ [wall, hardRock, pillar, pillarCache, lampPost, burningBush, bush, tree, wallV, wallSuspectV, doorClosedV, doorOpenV, wallH, wallSuspectH, doorClosedH, doorOpenH, stairsUpLit, stairsLit, stairsDownLit, escapeUpLit, escapeDownLit, unknown, floorCorridorLit, floorArenaLit, floorArenaShade, floorActorLit, floorItemLit, floorActorItemLit, floorRedLit, floorBlueLit, floorGreenLit, floorBrownLit]+ ++ map makeDark [wallV, wallSuspectV, doorClosedV, doorOpenV, wallH, wallSuspectH, doorClosedH, doorOpenH, stairsLit, escapeUpLit, escapeDownLit, floorCorridorLit]+ ++ map makeDarkColor [stairsUpLit, stairsDownLit, floorArenaLit, floorActorLit, floorItemLit, floorActorItemLit]+ }+wall, hardRock, pillar, pillarCache, lampPost, burningBush, bush, tree, wallV, wallSuspectV, doorClosedV, doorOpenV, wallH, wallSuspectH, doorClosedH, doorOpenH, stairsUpLit, stairsLit, stairsDownLit, escapeUpLit, escapeDownLit, unknown, floorCorridorLit, floorArenaLit, floorArenaShade, floorActorLit, floorItemLit, floorActorItemLit, floorRedLit, floorBlueLit, floorGreenLit, floorBrownLit :: TileKind++wall = TileKind+ { tsymbol = ' '+ , tname = "bedrock"+ , tfreq = [("fillerWall", 1), ("legendLit", 100), ("legendDark", 100)]+ , tcolor = defBG+ , tcolor2 = defBG+ , tfeature = [Dark]+ -- Bedrock being dark is bad for AI (forces it to backtrack to explore+ -- bedrock at corridor turns) and induces human micromanagement+ -- if there can be corridors joined diagonally (humans have to check+ -- with the cursor if the dark space is bedrock or unexplored).+ -- Lit bedrock would be even worse for humans, because it's harder+ -- to guess which tiles are unknown and which can be explored bedrock.+ -- The setup of Allure is ideal, with lit bedrock that is easily+ -- distinguished from an unknown tile. However, LH follows the NetHack,+ -- not the Angband, visual tradition, so we can't improve the situation,+ -- unless we turn to subtle shades of black or non-ASCII glyphs,+ -- but that is yet different aesthetics and it's inconsistent+ -- with console frontends.+ }+hardRock = TileKind+ { tsymbol = ' '+ , tname = "impenetrable bedrock"+ , tfreq = [("basic outer fence", 1)]+ , tcolor = BrWhite+ , tcolor2 = BrWhite+ , tfeature = [Dark, Impenetrable]+ }+pillar = TileKind+ { tsymbol = 'O'+ , tname = "rock"+ , tfreq = [ ("cachable", 70)+ , ("legendLit", 100), ("legendDark", 100)+ , ("noiseSet", 100), ("skirmishSet", 5)+ , ("battleSet", 250) ]+ , tcolor = BrWhite+ , tcolor2 = defFG+ , tfeature = []+ }+pillarCache = TileKind+ { tsymbol = '&'+ , tname = "cache"+ , tfreq = [ ("cachable", 30)+ , ("legendLit", 100), ("legendDark", 100) ]+ , tcolor = BrWhite+ , tcolor2 = defFG+ , tfeature = [Cause $ Effect.CreateItem 1, ChangeTo "cachable"]+ }+lampPost = TileKind+ { tsymbol = 'O'+ , tname = "lamp post"+ , tfreq = [("lampPostOver_O", 90)]+ , tcolor = BrYellow+ , tcolor2 = Brown+ , tfeature = []+ }+burningBush = TileKind+ { tsymbol = 'O'+ , tname = "burning bush"+ , tfreq = [("lampPostOver_O", 10), ("ambushSet", 3), ("battleSet", 2)]+ , tcolor = BrRed+ , tcolor2 = Red+ , tfeature = []+ }+bush = TileKind+ { tsymbol = 'O'+ , tname = "bush"+ , tfreq = [("ambushSet", 100) ]+ , tcolor = Green+ , tcolor2 = BrBlack+ , tfeature = [Dark]+ }+tree = TileKind+ { tsymbol = 'O'+ , tname = "tree"+ , tfreq = [("skirmishSet", 14), ("battleSet", 20), ("treeShadeOver_O", 1)]+ , tcolor = BrGreen+ , tcolor2 = Green+ , tfeature = []+ }+wallV = TileKind+ { tsymbol = '|'+ , tname = "granite wall"+ , tfreq = [("legendLit", 100)]+ , tcolor = BrWhite+ , tcolor2 = defFG+ , tfeature = [HideAs "suspect vertical wall Lit"]+ }+wallSuspectV = TileKind+ { tsymbol = '|'+ , tname = "moldy wall"+ , tfreq = [("suspect vertical wall Lit", 1)]+ , tcolor = BrWhite+ , tcolor2 = defFG+ , tfeature = [Suspect, RevealAs "vertical closed door Lit"]+ }+doorClosedV = TileKind+ { tsymbol = '+'+ , tname = "closed door"+ , tfreq = [("vertical closed door Lit", 1)]+ , tcolor = Brown+ , tcolor2 = BrBlack+ , tfeature = [ OpenTo "vertical open door Lit"+ , HideAs "suspect vertical wall Lit"+ ]+ }+doorOpenV = TileKind+ { tsymbol = '-'+ , tname = "open door"+ , tfreq = [("vertical open door Lit", 1)]+ , tcolor = Brown+ , tcolor2 = BrBlack+ , tfeature = [ Walkable, Clear, NoItem, NoActor+ , CloseTo "vertical closed door Lit"+ ]+ }+wallH = TileKind+ { tsymbol = '-'+ , tname = "granite wall"+ , tfreq = [("legendLit", 100)]+ , tcolor = BrWhite+ , tcolor2 = defFG+ , tfeature = [HideAs "suspect horizontal wall Lit"]+ }+wallSuspectH = TileKind+ { tsymbol = '-'+ , tname = "scratched wall"+ , tfreq = [("suspect horizontal wall Lit", 1)]+ , tcolor = BrWhite+ , tcolor2 = defFG+ , tfeature = [Suspect, RevealAs "horizontal closed door Lit"]+ }+doorClosedH = TileKind+ { tsymbol = '+'+ , tname = "closed door"+ , tfreq = [("horizontal closed door Lit", 1)]+ , tcolor = Brown+ , tcolor2 = BrBlack+ , tfeature = [ OpenTo "horizontal open door Lit"+ , HideAs "suspect horizontal wall Lit"+ ]+ }+doorOpenH = TileKind+ { tsymbol = '|'+ , tname = "open door"+ , tfreq = [("horizontal open door Lit", 1)]+ , tcolor = Brown+ , tcolor2 = BrBlack+ , tfeature = [ Walkable, Clear, NoItem, NoActor+ , CloseTo "horizontal closed door Lit"+ ]+ }+stairsUpLit = TileKind+ { tsymbol = '<'+ , tname = "staircase up"+ , tfreq = [("legendLit", 100)]+ , tcolor = BrWhite+ , tcolor2 = defFG+ , tfeature = [Walkable, Clear, NoItem, NoActor, Cause $ Effect.Ascend 1]+ }+stairsLit = TileKind+ { tsymbol = '>'+ , tname = "staircase"+ , tfreq = [("legendLit", 100)]+ , tcolor = BrCyan+ , tcolor2 = Cyan -- TODO+ , tfeature = [ Walkable, Clear, NoItem, NoActor+ , Cause $ Effect.Ascend 1+ , Cause $ Effect.Ascend (-1) ]+ }+stairsDownLit = TileKind+ { tsymbol = '>'+ , tname = "staircase down"+ , tfreq = [("legendLit", 100)]+ , tcolor = BrWhite+ , tcolor2 = defFG+ , tfeature = [Walkable, Clear, NoItem, NoActor, Cause $ Effect.Ascend (-1)]+ }+escapeUpLit = TileKind+ { tsymbol = '<'+ , tname = "exit trapdoor up"+ , tfreq = [("legendLit", 100)]+ , tcolor = BrYellow+ , tcolor2 = BrYellow+ , tfeature = [Walkable, Clear, NoItem, NoActor, Cause $ Effect.Escape 1]+ }+escapeDownLit = TileKind+ { tsymbol = '>'+ , tname = "exit trapdoor down"+ , tfreq = [("legendLit", 100)]+ , tcolor = BrYellow+ , tcolor2 = BrYellow+ , tfeature = [Walkable, Clear, NoItem, NoActor, Cause $ Effect.Escape (-1)]+ }+unknown = TileKind+ { tsymbol = ' '+ , tname = "unknown space"+ , tfreq = [("unknown space", 1)]+ , tcolor = defFG+ , tcolor2 = defFG+ , tfeature = [Dark]+ }+floorCorridorLit = TileKind+ { tsymbol = '#'+ , tname = "corridor"+ , tfreq = [("floorCorridorLit", 1)]+ , tcolor = BrWhite+ , tcolor2 = defFG+ , tfeature = [Walkable, Clear]+ }+floorArenaLit = floorCorridorLit+ { tsymbol = '.'+ , tname = "stone floor"+ , tfreq = [ ("floorArenaLit", 1)+ , ("arenaSet", 1), ("emptySet", 1), ("noiseSet", 50)+ , ("battleSet", 1000), ("skirmishSet", 100)+ , ("ambushSet", 1000) ]+ }+floorActorLit = floorArenaLit+ { tfreq = []+ , tfeature = OftenActor : tfeature floorArenaLit+ }+floorItemLit = floorArenaLit+ { tfreq = []+ , tfeature = OftenItem : tfeature floorArenaLit+ }+floorActorItemLit = floorItemLit+ { tfreq = [("legendLit", 100)] -- no OftenItem in legendDark+ , tfeature = OftenActor : tfeature floorItemLit+ }+floorArenaShade = floorActorLit+ { tname = "stone floor" -- TODO: "shaded ground"+ , tfreq = [("treeShadeOver_s", 1)]+ , tcolor2 = BrBlack+ , tfeature = Dark : tfeature floorActorLit -- no OftenItem+ }+floorRedLit = floorArenaLit+ { tname = "brick pavement"+ , tfreq = [("trailLit", 30)]+ , tcolor = BrRed+ , tcolor2 = Red+ , tfeature = Trail : tfeature floorArenaLit+ }+floorBlueLit = floorRedLit+ { tname = "granite cobblestones"+ , tfreq = [("trailLit", 100)]+ , tcolor = BrBlue+ , tcolor2 = Blue+ }+floorGreenLit = floorRedLit+ { tname = "mossy stone path"+ , tfreq = [("trailLit", 100)]+ , tcolor = BrGreen+ , tcolor2 = Green+ }+floorBrownLit = floorRedLit+ { tname = "rotting mahogany deck"+ , tfreq = [("trailLit", 10)]+ , tcolor = BrMagenta+ , tcolor2 = Magenta+ }++makeDark :: TileKind -> TileKind+makeDark k = let darkText :: Text -> Text+ darkText t = maybe t (<> "Dark") $ T.stripSuffix "Lit" t+ darkFrequency = map (first darkText) $ tfreq k+ darkFeat (OpenTo t) = Just $ OpenTo $ darkText t+ darkFeat (CloseTo t) = Just $ CloseTo $ darkText t+ darkFeat (ChangeTo t) = Just $ ChangeTo $ darkText t+ darkFeat (HideAs t) = Just $ HideAs $ darkText t+ darkFeat (RevealAs t) = Just $ RevealAs $ darkText t+ darkFeat OftenItem = Nothing+ darkFeat feat = Just $ feat+ in k { tfreq = darkFrequency+ , tfeature = Dark : mapMaybe darkFeat (tfeature k)+ }++makeDarkColor :: TileKind -> TileKind+makeDarkColor k = (makeDark k) {tcolor2 = BrBlack}
+ GameDefinition/Main.hs view
@@ -0,0 +1,13 @@+-- | The main source code file of Space Privateers the game.+module Main ( main ) where++import System.Environment (getArgs)++import TieKnot++-- | Tie the LambdaHack engine client, server and frontend code+-- with the game-specific content definitions, and run the game.+main :: IO ()+main = do+ args <- getArgs+ tieKnot args
+ GameDefinition/MainMenu.ascii view
@@ -0,0 +1,26 @@+----------------------------------------------------------------------------------+| |+| |+| |+| |+| |+| >> Space Privateers << |+| |+| |+| {{{{{{{{{{{{{{{{{{{{{{{{{ |+| |+| {{{{{{{{{{{{{{{{{{{{{{{{{ |+| |+| {{{{{{{{{{{{{{{{{{{{{{{{{ |+| |+| {{{{{{{{{{{{{{{{{{{{{{{{{ |+| |+| {{{{{{{{{{{{{{{{{{{{{{{{{ |+| |+| |+| |+| |+| |+| |+| Version X.X.X (frontend: gtk, engine: LambdaHack X.X.X) |+----------------------------------------------------------------------------------
+ GameDefinition/PLAYING.md view
@@ -0,0 +1,242 @@+Playing Space Privateers+========================++Space Privateers is a dungeon crawler set in space. Playing the game involves+exploring corridors of a city vessel and plundering as much loot as possible.++Once the few basic command keys and on-screen symbols are learned,+mastery and enjoyment of the game is the matter of tactical skill+and literary imagination. To be honest, a lot of imagination is required+for this rudimentary game, but it's playable and winnable.+Contributions are welcome.++Space Privateers uses LambdaHack engine and lot of content in the game is+derived from it.++Heroes+------++The heroes are marked on the map with symbols `@` and `1` through `9`.+Their goal is to explore the city vessel, battle the horrors within,+gather as much gold and gems as possible, and escape to tell the tale.++The currently chosen party leader is highlighted on the screen+and his attributes are displayed at the bottommost status line,+which in its most complex form may look as follows.++ *@12 Captain 4d1+5% Calm: 20/60 HP: 33/50 Target: merchant [**___]++The line starts with the list of party members (unless only one member+resides on the currently displayed level) and the shortened name of the team.+Then comes the damage of the leader's weapon (but regardless of the figures,+each attack inflicts at least 1 damage), then his current and maximum+Calm (composure, focus, attentiveness), then his current and maximum+HP (hit points, health). At the end, the personal target of the leader+is described, in this case a merchant mariner, with hit points drawn as a bar.++The other status line describes the current 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.+Then the percentage of its explorable tiles already seen by the heroes.+The 'cursor' is the common target of the whole party,+directly manipulated with movement keys in the targeting mode.+At the end comes the length of the shortest path from the leader+to the cursor position and the straight-line distance between the two points.+++City vessel+-----------++The city vessel consists of 10 levels and each level consists of a large number+of tiles. The basic tile kinds are as follows.++ terrain type on-screen symbol+ ground .+ corridor #+ wall (horizontal and vertical) - and |+ rock or tree O+ cache &+ stairs up <+ stairs down >+ open door | and -+ closed door ++ vessel hull blank++The game world is persistent, i.e., every time the player visits a level+during a single game, its layout is the same.+++Commands+--------++You move throughout the level using the numerical keypad (left diagram)+or its compact laptop replacement (middle) or Vi text editor keys+(right, also known as "Rogue-like keys", which have to be enabled+in config.ui.ini).++ 7 8 9 7 8 9 y k u+ \|/ \|/ \|/+ 4-5-6 u-i-o h-.-l+ /|\ /|\ /|\+ 1 2 3 j k l b j n++In targeting mode the keys above move the targeting cursor. In normal mode,+`SHIFT` (or `CTRL`) and a movement key make the current party leader+(and currently selected party members, if any) run in the indicated+direction, until anything of interest is spotted.+The '5', 'i' and '.' keys consume a turn and make you brace for combat,+which reduces any damage taken for a turn and makes it impossible+for foes to displace you. You displace enemies or friends by bumping+into them with SHIFT (or CTRL).++Melee, searching for secret doors, looting and opening closed doors+can be done by bumping into a monster, a wall and a door, respectively.+Few commands other than movement, 'g'etting an item from the floor,+'a'pplying an item and 'f'linging an item are necessary for casual play.+Some are provided only as specialized versions of more general commands+or as building blocks for more complex convenience commands,+e.g., the autoexplore command (key `X`) could be defined+by the player as a macro using `BACKSPACE`, `CTRL-?`, `;` and `V`.++Below are the remaining keys for terrain exploration and alteration.++ keys command+ < ascend a level+ CTRL-< ascend 10 levels+ > descend a level+ CTRL-> descend 10 levels+ ; make one step towards the target+ : go to target for 100 steps+ CTRL-: go to target for 10 steps+ x explore the closest unknown spot+ X autoexplore 100 times+ CTRL-X autoexplore 10 times+ R rest (wait 100 times)+ CTRL-R rest (wait 10 times)+ c close door++Item-use related keys are as follows.++ keys command+ E describe equipment of the leader+ P describe backpack inventory of the leader+ S describe the shared party stash+ G describe items on the ground+ A describe all owned items+ g and , get an item+ d drop an item+ e equip an item+ p pack an item into inventory backpack+ s stash and share an item+ a activate applicable item+ q quaff potion+ r read scroll+ f fling projectable item+ t throw missile+ z zap wand++To make a ranged attack, as in the last few commands above,+you need to set your target first (however, initial target is set+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.++ keys command+ KEYPAD_* and \ target enemy+ / cycle targeting mode+ + swerve targeting line+ - unswerve targeting line+ BACKSPACE clear target/cursor+ CTRL-? target the closest unknown spot+ CTRL-I target the closest item+ CTRL-{ target the closest stairs up+ CTRL-} target the closest stairs down++Here are the commands for automating the actions of one or more members+of the team.++ keys command+ = select (or deselect) a party member+ _ deselect (or select) all on the level+ v voice again the recorded commands+ V voice the recorded commands 100 times+ CTRL-v voice the recorded commands 1000 times+ CTRL-V voice the recorded commands 10 times+ ' start recording commands+ CTRL-A automate faction (ESC to retake control)++Assorted remaining keys and commands follow.++ keys command+ ? display help+ D display player diary+ T mark suspect terrain+ Z mark visible zone+ C mark smell clues+ TAB cycle among party members on the level+ SHIFT-TAB cycle among all party members+ SPACE clear messages+ ESC cancel action, open Main Menu+ RET accept choice+ 0--6 pick a new hero leader anywhere in the dungeon++Commands for saving and exiting the current game, starting a new game, etc.,+are listed in the Main Menu, brought up by the `ESC` key.+Game difficulty setting affects hitpoints at birth for any actors+of any UI-using faction. For a person new to roguelikes, the Duel game mode+offers a gentle introduction. The subsequent game modes gradually introduce+squad combat, stealth, asymmetric battles and more game elements.++ keys command+ CTRL-x save and exit+ CTRL-u new Duel game+ CTRL-k new Skirmish game+ CTRL-m new Ambush game+ CTRL-b new Battle game+ CTRL-a new Campaign game+ CTRL-d cycle next game difficulty++Monsters+--------++Heroes are not alone in the city vessel. Monstrosities, natural+and out of this world, roam the dark caves and crawl from damp holes+day and night. While heroes pay attention to all other party members+and take care to move one at a time, monsters don't care about each other+and all move at once, sometimes brutally colliding by accident.++When the hero bumps into a monster or a monster attacks the hero,+melee combat occurs. The best equipped weapon or the best fighting organ+of each opponent is taken into account for calculating damage.+The damage the current hero can potentially inflict is displayed+at the bottom of the screen, but the actual damage depends also+on the monster's armor. Heroes and monsters running into one another+(with the `SHIFT` key) do not inflict damage, but change places.+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.+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.+++On Winning and Dying+--------------------++You win the game if you escape the city vessel alive. Your score is based on the+gold and precious gems you've plundered, plus a bonus based on the number of+heroes you lost.++If all your heroes fall, you are awarded a score for your valiant deeds,+but no winning bonus. When, invariably, a new overconfident party+of adventurers storms the dungeon, they start from a new entrance,+with no experience and no equipment, and new, undaunted enemies+bar their way.
+ GameDefinition/TieKnot.hs view
@@ -0,0 +1,38 @@+-- | Here the knot of engine code pieces and the game-specific+-- content definitions is tied, resulting in an executable game.+module TieKnot ( tieKnot ) where++import qualified Client.UI.Content.KeyKind as Content.KeyKind+import qualified Content.CaveKind+import qualified Content.FactionKind+import qualified Content.ItemKind+import qualified Content.ModeKind+import qualified Content.PlaceKind+import qualified Content.RuleKind+import qualified Content.TileKind+import Game.LambdaHack.Client (exeFrontend)+import qualified Game.LambdaHack.Common.Kind as Kind+import Game.LambdaHack.SampleImplementation.SampleMonadClient (executorCli)+import Game.LambdaHack.SampleImplementation.SampleMonadServer (executorSer)+import Game.LambdaHack.Server (mainSer)++-- | Tie the LambdaHack engine client, server and frontend code+-- with the game-specific content definitions, and run the game.+tieKnot :: [String] -> IO ()+tieKnot args =+ let -- Common content operations, created from content definitions.+ copsServer = Kind.COps+ { cocave = Kind.createOps Content.CaveKind.cdefs+ , cofaction = Kind.createOps Content.FactionKind.cdefs+ , coitem = Kind.createOps Content.ItemKind.cdefs+ , comode = Kind.createOps Content.ModeKind.cdefs+ , coplace = Kind.createOps Content.PlaceKind.cdefs+ , corule = Kind.createOps Content.RuleKind.cdefs+ , cotile = Kind.createOps Content.TileKind.cdefs+ }+ -- Client content operations.+ copsClient = Content.KeyKind.standardKeys+ -- A single frontend is currently started by the server,+ -- instead of each client starting it's own.+ startupFrontend = exeFrontend executorCli executorCli copsClient+ in mainSer args copsServer executorSer startupFrontend
+ GameDefinition/config.ui.default view
@@ -0,0 +1,28 @@+; ; 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+; ; ~/.SpacePrivateers/config.ui.ini (or a similar path, depending on the OS).+; ; Warning: options are case-sensitive and only ';' for comments is permitted.++; [extra_commands]+; ; A handy shorthand with Vi keys:+; Macro_1 = ("comma", ([CmdItem], Macro "" ["g"]))++; [hero_names]+; HeroName_0 = ("Regulus Secundinus", "he")+; HeroName_1 = ("Sabina Petronia", "she")+; HeroName_2 = ("Titus Severus", "he")+; HeroName_3 = ("Blandina Domitius", "she")+; HeroName_4 = ("Lucretius Caelius", "he")+; HeroName_5 = ("Tacita Aurelia", "she")+; HeroName_6 = ("Vitus Antoninus", "he")++; [ui]+; movementViKeys_hjklyubn = False+; movementLaptopKeys_uk8o79jl = True+; font = "Terminus,Monospace normal normal normal normal 12"+; historyMax = 5000+; maxFps = 15+; noAnim = False+; runStopMsgs = False+[dummy]
+ GameDefinition/scores view
binary file changed (absent → 701 bytes)
+ LICENSE view
@@ -0,0 +1,32 @@+Copyright (c) 2008--2014 Andres Loeh+Copyright (c) 2010--2014 Mikolaj Konarski+Copyright (c) 2014, Tuukka Turto++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Tuukka Turto nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,8 @@+Space Privateers is a adventure game set in far future. Player plays a space+privateer who has recently docked with a merchant city vessel and plans to+plunder some of the loot before escaping. The task will not be easy and there+are many dangers awaiting in the deep corridors and rooms of the city vessel.++Space Privateers uses [LambdaHack] [1] engine.++[1]: https://github.com/LambdaHack/LambdaHack/
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ SpacePrivateers.cabal view
@@ -0,0 +1,56 @@+name: SpacePrivateers+version: 0.1.0.0+synopsis: Simple space pirate roguelike+description: Space Privateers is a roguelike game set in space.+homepage: https://github.com/tuturto/space-privateers+license: BSD3+license-file: LICENSE+author: Tuukka Turto+maintainer: tuukka.turto@oktaeder.net+category: Game+build-type: Simple+data-files: GameDefinition/config.ui.default,+ GameDefinition/scores+extra-source-files: GameDefinition/PLAYING.md, GameDefinition/MainMenu.ascii,+ README.md, LICENSE, CREDITS, changelog+cabal-version: >= 1.10+source-repository head+ type: git+ location: git://github.com/tuturto/space-privateers.git++executable SpacePrivateers+ hs-source-dirs: GameDefinition+ main-is: Main.hs+ other-modules: Client.UI.Content.KeyKind,+ Content.CaveKind,+ Content.FactionKind,+ Content.ItemKind,+ Content.ItemKindActor,+ Content.ItemKindOrgan,+ Content.ItemKindShrapnel,+ Content.ModeKind,+ Content.PlaceKind,+ Content.RuleKind,+ Content.TileKind,+ TieKnot,+ Paths_SpacePrivateers++ build-depends: base >=4.7 && <4.8,+ LambdaHack >= 0.2.14 && < 0.2.15,+ containers >= 0.5 && < 1,+ enummapset-th >= 0.6.0.0 && < 1,+ filepath >= 1.2.0.1 && < 2,+ template-haskell >= 2.6 && < 3,+ text >= 0.11.2.3 && < 2+ default-language: Haskell2010++ default-extensions: MonoLocalBinds, ScopedTypeVariables, OverloadedStrings+ BangPatterns, RecordWildCards, NamedFieldPuns+ other-extensions: TemplateHaskell+ ghc-options: -Wall -fwarn-orphans -fwarn-tabs -fwarn-incomplete-uni-patterns+ ghc-options: -fwarn-incomplete-record-updates -fwarn-monomorphism-restriction+ ghc-options: -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+
+ changelog view
@@ -0,0 +1,2 @@+v0.1.0+ * Initial version