File: vault.lua

package info (click to toggle)
crawl 2%3A0.33.1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 95,264 kB
  • sloc: cpp: 358,145; ansic: 27,203; javascript: 9,491; python: 8,359; perl: 3,327; java: 2,667; xml: 2,191; makefile: 1,830; sh: 611; objc: 250; cs: 15; sed: 9; lisp: 3
file content (383 lines) | stat: -rw-r--r-- 15,110 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
--------------------------------------------------------------------------
-- vault.lua: Vault helper functions from more than one file.
--------------------------------------------------------------------------

-- Counting Pan runes for exits.
function count_pan_runes()
  local runes = 0
  for _, r in ipairs({"demonic","glowing","magical","fiery","dark"}) do
    if you.have_rune(r) then
      runes = runes + 1
    end
  end
  return runes
end

-- Functionality for some of HangedMan's decor vaults.
function init_hm_decor_walldepth(e, variables)
local a = you.absdepth() * 5
  if a - 75 > 0 then
    e.subst(variables .. " : x:50 c:" .. a .. " b:" .. a - 75)
  else
    e.subst(variables .. " : x:50 c:" .. a)
  end
end

-- Functionality for Kennysheep vaults.
-- c: outer vault walls
-- x: inner vault walls (could be see-through blocks, or not there at all)
-- t: doodads. fountains, statues or the more decorative walls. Sometimes get replaced by normal walls
-- w: water or lava or trees. or nothing
-- D/F opposite/adjacent vault entrances, that may or may not be there
-- E/H placed in front of the alternate doors. become w tiles if there's no door there

function ks_random_setup(e, norandomexits)
    e.tags("no_pool_fixup")
    -- 1/2 chance the adjacent door is there, followed by a 1/2 chance every
    -- side has a door.
    if norandomexits == nil then
        e.tags("transparent")
        if crawl.one_chance_in(2) then
            e.subst("D : +")
            e.subst("E : .")
            if crawl.one_chance_in(2) then
                e.subst("F : +")
                e.subst("H : .")
            else
                e.subst("F : c")
                e.subst("H : w")
            end
        else
            e.subst("DF : c")
            e.subst("EH : w")
        end
    end
    --rooms have a 1/2 chance of being bordered by water or trees
    --q is used as a placeholder for trees to keep them from being
    -- re-selected in the next step.
    e.subst("w : w.")
    e.subst("w : wwwWWqq")
    --room setups:
    --0 : doodads replaced with walls
    --1 : walls replaced with water/lava or removed. doodads may or may not be walls
    --2 : doodads picked from more obvious vault decorations
    selected = crawl.random2(3)
    if selected == 0 then
        e.subst("t : x")
        e.subst("x : cvbttm")
    elseif selected == 1 then
        e.subst("x : ..wW")
        e.subst("t : .TmbttwG")
    elseif selected == 2 then
        e.subst("t : .TttG")
        e.subst("x : cvbtt")
    end
    -- Turn q into t for tree borders.
    e.subst("q : t")
    -- The outer walls are probably stone or rock, but can be metal or crystal.
    e.subst("c : ccccxxxxvb")
    -- One chance in three of turning all water on the floor into lava.
    -- Tree and fountain tiles are changed so the vault looks normal.
    if crawl.one_chance_in(3) then
        e.subst("Wwt : l")
        e.subst("T : V")
    end
end

function zot_entry_setup(e)
  e.tags("zot_entry")
  e.place("Depths:$")
  e.orient("float")
  e.kitem("R = midnight gem")
  e.kfeat("O = enter_zot")
  e.mons("patrolling base draconian")
  e.mons("fire dragon w:12 / ice dragon w:12 / storm dragon / \
          shadow dragon / golden dragon w:12 / wyrmhole w:4")
  e.mons("patrolling nonbase draconian")
  e.kmons("0 = ettin / rakshasa / glowing shapeshifter w:5 / \
              stone giant w:12 / spriggan berserker w:8 / hell knight w:5")
  e.kmons("9 = fire giant w:12 / titan w:8 / vampire knight / \
              spriggan air mage w:8 / deep troll earth mage w:8 / \
              tengu reaver w:12 / tentacled monstrosity / lich w:2")
end

function soh_hangout()
  if dgn.persist.soh_hangout == nil then
    local hell_branches = { "Geh", "Coc", "Dis", "Tar" }
    dgn.persist.soh_hangout = util.random_from(hell_branches)
  end
  return dgn.persist.soh_hangout
end

-- the Serpent should appear in exactly one hell end. Vaults that call this
-- should guarantee that `D` is present.
function serpent_of_hell_setup(e)
  local b = soh_hangout()
  if not you.uniques("the Serpent of Hell")
        and you.in_branch(b)
        and you.depth() == dgn.br_depth(b) then
    e.kmons('D = the Serpent of Hell')
  end
end

-- Guarantee two or three rare base types with a brand
function hall_of_blades_weapon(e)
  local long_blade_type = crawl.one_chance_in(2) and "double sword"
                                                  or "triple sword"
  local polearm_type = crawl.one_chance_in(2) and "partisan"
                                               or "bardiche"
  local types = {"eveningstar", "executioner's axe", polearm_type,
                 "lajatang",  "quick blade", long_blade_type}
  local egos = {"flaming", "freezing", "electrocution", "heavy",
                "holy_wrath", "pain", "vampirism",
                "antimagic", "distortion", "spectral"}
  local weapon_t = util.random_subset(types, 3)
  local weapon_e = util.random_subset(egos, 3)
  e.mons("dancing weapon; good_item " .. weapon_t[1] .. " ego:" .. weapon_e[1])
  e.mons("dancing weapon; good_item " .. weapon_t[2] .. " ego:" .. weapon_e[2])
  e.mons("dancing weapon; good_item " .. weapon_t[3] .. " ego:" ..
          weapon_e[3] .. " / nothing")
end

-- Setup for door vaults to define a common loot set and create the door
-- markers.
function door_vault_setup(e)
  -- Don't generate loot in Hells, generate down hatches instead.
  if you.in_branch("Geh") or you.in_branch("Tar") or you.in_branch("Coc")
     or you.in_branch("Dis") then
    e.kfeat("23 = >")
  else
    e.kitem("1 = * / nothing")
    e.kitem("23 = | / nothing")
  end

  -- The marker affects find_connected_range() so that each door opens and
  -- closes separately rather than all of them joining together into a huge
  -- gate that opens all at once.
  e.lua_marker('+',  props_marker { connected_exclude="true" })
  e.lua_marker('a',
               props_marker { stop_explore="strange structure made of doors" })
  e.kfeat("a = runed_clear_door")
end

--[[
Set up a KMONS for a master elementalist vault-defined monster. This monster
will have either the elemental staff or a staff of air and a robe of
resistance, so it has all of the elemental resistances.

@tab e The map environment.
@string glyph The glyph on which to define the KMONS.
]]
function master_elementalist_setup(e, glyph, ele_staff)
    local equip_def = " ; elemental staff . robe ego:willpower good_item"
    -- Don't want to use the fallback here, so we can know to give resistance
    -- ego robe if the elemental staff isn't available.
    if you.unrands("elemental staff") then
        equip_def = " ; staff of air . robe ego:resistance good_item"
    end

    e.kmons(glyph .. " = occultist hd:18 name:master_elementalist n_rpl" ..
        " n_des n_noc tile:mons_master_elementalist" ..
        " spells:lehudib's_crystal_spear.11.wizard;" ..
            "chain_lightning.11.wizard;" ..
            "fire_storm.11.wizard;" ..
            "ozocubu's_refrigeration.11.wizard;" ..
            "haste.11.wizard;" ..
            "repel_missiles.11.wizard" .. equip_def)
end

-- Three sets of reusable vault feature redefines scattered across the game,
-- kept in this one function for both consistency and ease of use.
function vault_granite_statue_setup(e, glyph, type)
  e.kfeat(glyph .. " = granite_statue")

  -- Feature name, console colour, tile name.
  local statues = {
    ["broken pillar"] = {"lightgrey", "dngn_crumbled_column"},
    ["gravestone"] = {"lightgrey", "dngn_gravestone"},
    ["sarcophagus"] = {"yellow", "dngn_sarcophagus_pedestal_right"},
    ["scintillating statue"] = {"mountain", "dngn_scintillating_statue"},
  }

  for name, contents in pairs(statues) do
    if type == name then
      e.colour(glyph .. " = " .. contents[1])
      e.tile(glyph .. " = " .. contents[2])
    end
  end

  e.set_feature_name("granite_statue", type)
end

function vault_metal_statue_setup(e, glyph, type)
  e.kfeat(glyph .. " = metal_statue")

  local statues = {
    ["golden statue"] = {"yellow", "dngn_golden_statue"},
    ["silver statue"] = {"silver", "dngn_silver_statue"},
    ["iron statue"] = {"cyan", "dngn_statue_iron"},
    ["mystic cage"] = {"mist", "dngn_mystic_cage"},
    ["arcane conduit"] = {"vehumet", "arcane_conduit"},
    ["misfortune conduit"] = {"shimmer_blue", "misfortune_conduit"},
    ["dimensional conduit"] = {"warp", "dimensional_conduit"},
    ["soul conduit"] = {"smoke", "soul_conduit"},
    ["alchemical conduit"] = {"poison", "alchemical_conduit"},
    ["fiery conduit"] = {"fire", "fiery_conduit"},
    ["icy conduit"] = {"ice", "icy_conduit"},
    ["earthen conduit"] = {"earth", "earthen_conduit"},
    ["storm conduit"] = {"electricity", "storm_conduit"},
    ["enigmatic dynamo"] = {"magic", "dngn_enigmatic_dynamo"},
    ["nascence circuit"] = {"magic", "dngn_nascence_circuit"}
  }

  for name, contents in pairs(statues) do
    if type == name then
      e.colour(glyph .. " = " .. contents[1])
      e.tile(glyph .. " = " .. contents[2])
    end
  end

  e.set_feature_name("metal_statue", type)
end

function decorative_floor (e, glyph, type)
  e.kfeat(glyph .. ' = decorative_floor')

  local dec = {
    ["flower patch"] = {"green", "dngn_flower_patch"},
    ["garden patch"] = {"yellow", "dngn_garden_patch"},
    ["floral vase"] = {"yellow", "dngn_flower_pot"},
    ["mourning vase"] = {"magenta", "dngn_dark_flower_pot"},
    ["broken floral vase"] = {"magenta", "dngn_flower_pot_broken / " ..
                              "dngn_dark_flower_pot_broken"},
    ["orcish standard"] = {"lightcyan", "dngn_ensign_beogh"},
    ["infernal standard"] = {"red", "dngn_ensign_gehenna"},
    ["fur brush"] = {"brown", "dngn_yak_fur"},
    ["mop and bucket"] = {"lightblue", "dngn_mop"},
    ["bloodied mop and bucket"] = {"lightred", "dngn_mop_bloody"}
  }

  for name, contents in pairs(dec) do
    if type == name then
      e.colour(glyph .. " = " .. contents[1])
      e.tile(glyph .. " = " .. contents[2])
    end
  end

  e.set_feature_name('decorative_floor', type)
end

-- A reusable poison / fire / snake theming for statues that show up in Snake.
function snake_statue_setup (e, glyph)
  if crawl.x_chance_in_y(2, 3) then
    vault_metal_statue_setup(e, glyph, "alchemical conduit")
  else
    vault_metal_statue_setup(e, glyph, "fiery conduit")
  end
  e.tile("G : dngn_statue_naga / dngn_statue_archer w:7")
end

-- A function that uses what's in the mon-pick-data (and bands) for V in 0.32
-- for several distinct, tiered, depths-scaling themes + decorations.
function index_vaults_room_themes (e, set, hard)
  e.tags('luniq_vaults_room_' .. set)

  local d = you.depth() + 1
  if hard then
    e.tags("vaults_hard")
    d = d + 1
  else
    e.tags("vaults_room")
  end

  if set == 'magic' then
    local sl = 1
    if crawl.x_chance_in_y(d, 10) then
      sl = sl + 1
    end
    e.mons('ugly thing w:' .. 7 - d .. ' / lindwurm w:4 / ' ..
           'freezing wraith w:4 / crystal guardian w:' .. d)
    e.mons('great orb of eyes w:' .. 7 - d .. ' / ' ..
           'boggart band w:5 / glowing orange brain w:' .. d + 1)
    e.mons('arcanist w:' .. 14 - d * 2 .. ' / sphinx marauder w:8 / ' ..
           'ironbound convoker w:4 / ironbound mechanist w:4')
    e.mons('deep elf annihilator / deep elf sorcerer / lich / ' ..
           'guardian sphinx w:5 / tengu reaver')
    e.item('robe / mundane hat')
    e.item('randbook numspells:1 slevels:' .. sl  .. ' / ' ..
           'mundane ring of magical power w:2')
    e.tile('c = wall_studio')
  elseif set == 'icebox' then
    e.tags('no_wall_fixup')
    local f = 'ego:freezing pre_id'
    local c = 'ego:cold_resistance pre_id'
    e.mons('white ugly thing w:' .. 8 - d * 2 .. ' / ' ..
           'redback simulacrum w:' .. 8 - d * 2 .. ' / ' ..
           'freezing wraith w:2 / guardian sphinx simulacrum w:' .. d - 1)
    e.mons('necromancer w:2 / arcanist / white very ugly thing')
    e.mons('ironbound frostheart / frost giant w:1')
    e.mons('golden dragon / tengu reaver w:25 ; halberd ' .. f .. ' | war axe ' .. f ..
                                            ' . ring mail ' .. c)
    e.kitem('d : dagger ' .. f .. ' no_pickup / ' ..
                'long sword ' .. f .. ' no_pickup/ ' ..
                'mace ' .. f .. ' no_pickup')
    e.kitem('e = robe ' .. c .. ' / leather armour ' .. c)
    e.kfeat('m = cache of meat')
    e.kfeat('I = rock_wall')
    e.tile('I = wall_ice_block')
    e.tile('v = dngn_metal_wall_lightblue')
    e.set_feature_name("rock_wall", "ice covered rock wall")
  elseif set == 'garden' then
    e.tags('no_pool_fixup')
    e.mons('harpy w:' .. 80 - d * 20 .. ' / ' ..
           'redback w:' .. 100 - d * 16 .. ' / ' ..
           'wolf spider w:' .. 20 - d * 3 .. ' / ' ..
           'lindwurm w:' .. 140 - d * 20 .. ' / ' ..
           'dire elephant w:' .. d * 3 )
    e.mons('dire elephant w:' .. 18 - d * 3 .. ' / ' ..
           'formless jellyfish w:' .. 2 + d * 4 .. ' / ' ..
           'guardian sphinx w:' .. 2 + d * 2)
    e.mons('ironbound preserver w:' .. 10 - d * 2 .. ' / ' ..
           'entropy weaver w:' .. 2 + d * 3 .. ' / ' ..
           'ironbound beastmaster w:' .. -2 + d * 4)
    e.kmons('S = bush')
    e.kfeat('F = cache of fruit')
    e.ftile('`SF = floor_lair')
    e.tile('T = dngn_fountain_novelty_fancy')
    e.kitem('d = animal skin / club / whip w:5 / quarterstaff w:5')
    decorative_floor(e, 'p', "garden patch")
  elseif set == 'rangers' then
    local eq = "arbalest w:29 | hand cannon w:1 . " ..
               " scimitar . ring mail | scale mail"
    e.mons('centaur warrior w:' .. 6 - d * 2 .. ' / ' ..
           'yaktaur w:' .. 6 - d * 2 .. ' / ' ..
           'polterguardian w:' .. 6 - d * 2 )
    e.mons('vault sentinel w:' .. 8 - d * 2 .. ' ; '  .. eq .. ' / ' ..
           'orc knight w:' .. 2 + d * 2 .. ' ; '  .. eq .. ' / ' ..
           'yaktaur captain w:' .. 2 + d * 2)
    e.mons('orc warlord w:' .. 2 + d * 2 .. ' ; '  .. eq .. ' / ' ..
           'deep elf high priest w:' .. 2 + d * 3 .. ' / ' ..
           'vault warden w:' .. 2 + d * 4 .. ' ; ' .. eq)
    e.mons('stone giant')
    e.kmons('U = training dummy ; nothing')
    e.item('sling no_pickup w:5 / shortbow no_pickup / arbalest no_pickup')
  elseif set == 'warriorcrypt' then
    e.tags('no_wall_fixup')
    e.mons('vault guard w:' .. 14 - d .. ' / ' ..
           'vault sentinel w:' .. 10 - d .. ' / ' ..
           'orc knight')
    e.mons('necromancer w:' .. 10 - d .. ' / ' ..
           'flayed ghost w:' .. 10 - d .. ' / ' ..
           'phantasmal warrior w:' .. d + 2)
    e.mons('war gargoyle w:' .. 16 - d * 2 .. ' / ' ..
           'deep elf death mage w:4 / ' ..
           'undying armoury w:' .. -2 + d)
    e.mons('deep elf death mage w:5 / lich / ancient lich')
    e.item('human skeleton / ogre skeleton w:1 / orc skeleton w:1')
    e.kfeat('u = rock_wall')
    e.tile('u = wall_undead')
    e.tile('c = wall_crypt')
    e.tile('G = dngn_statue_angel / dngn_statue_wraith / dngn_statue_twins / ' ..
               'dngn_statue_dwarf / dngn_statue_sword / dngn_statue_centaur')
  end
end