File: vault.lua

package info (click to toggle)
crawl 2%3A0.34.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 100,204 kB
  • sloc: cpp: 363,900; ansic: 27,765; javascript: 9,516; python: 8,463; perl: 3,293; java: 3,132; xml: 2,380; makefile: 1,835; sh: 611; objc: 250; cs: 15; sed: 9; lisp: 3
file content (485 lines) | stat: -rw-r--r-- 18,775 bytes parent folder | download | duplicates (3)
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
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
--------------------------------------------------------------------------
-- 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, extra, norandomexits)
    e.tags("no_pool_fixup")
    if extra then
      e.tags("extra")
      e.depth_weight("Depths", 5)
      e.depth_weight("D", 10)
    end
    -- 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, use_default_mons)
  e.tags("zot_entry")
  e.place("Depths:$")
  e.orient("float")
  e.kitem("R = midnight gem")
  e.kfeat("O = enter_zot")
  e.kfeat("Z = zot_statue")
  e.kmask("R = no_item_gen")
  if use_default_mons then
    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
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("Serpent of Hell")
        and you.in_branch(b)
        and you.depth() == dgn.br_depth(b) then
    e.kmons('D = 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 string 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, sprintscale)
    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 randart artprops:rF&&rC&&Will"
    end

    pow = "hd:18"
    name = ""

    -- For use in arenasprint.
    if sprintscale then
        pow = pow .. " hp:200 exp:3950"
        name = "name:grandmaster_elementalist n_rpl n_des n_noc"
    else
        pow = pow .. " hp:100 exp:1425"
        name = "name:master_elementalist n_rpl n_des n_noc"
    end

    return "occultist " .. pow .. " " .. name .. " " ..
           "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;" ..
           "deflect_missiles.11.wizard" .. equip_def .. " . ring of willpower"
end

-- A function to reduce all the scythe definition boilerplate.
function scythe(ego)
  local s = "halberd itemname:scythe tile:wpn_scythe wtile:scythe"
  if ego ~= nil then
    s = s .. " ego:" .. ego
  end
  return s
end

-- A handy boilerplate-reducing function for getting a cloud generator to place
-- just a single cloud in-place. @fade makes it rarely briefly fade away.
function single_cloud(e, glyph, cloud, fade)
  local pow = ""
  if fade == nil then fade = false end
  if fade then
    pow = "pow_min = 5, pow_max = 7, delay_min = 55, delay_max = 75, excl_rad = 0"
  else
    pow = "pow_min = 90, pow_max = 100, delay = 10, excl_rad = -1"
  end
  e.marker(glyph .. ' = lua:fog_machine { cloud_type = "' .. cloud .. '", ' ..
          "size = 1, " .. pow .. ", walk_dist = 0, " ..
          "start_clouds = 1, spread_rate = 0 }")
end

-- A function to crunch down decorative skeletons.
-- Vaults that only want to place regular branch skeletons or given vault
-- theme skeletons don't need to call this whole function.
function vault_species_skeletons(e, category)
-- (Djinni, gargoyles, mummies, octopodes, poltergeists, revenants don't leave
-- corpses. I don't want to think about how one recognizes vine stalkers
-- post-rotting. Orcs are included to cover Beogh's popularity in the Dungeon.
-- Coglins have their exoskeletons stolen. Species that only show up
-- in extended are counted as the rarest type.
  local s1 = {"goblin", "gnoll", "elf", "kobold", "troll", "orc"}
  local s2 = {"draconian", "naga", "merfolk", "minotaur", "spriggan", "tengu"}
  local s3 = {"armataur", "barachi", "demigod", "dwarf",
              "demonspawn", "felid", "oni"}
  local output = "human skeleton"
  if category == "early" or category == "dungeon" or category == "all" then
    output = output .. " / " .. table.concat(s1, " skeleton / ")
  end
  if category == "late" or category == "dungeon" or category == "all" then
    output = output .. " / " .. table.concat(s2, " skeleton / ")
  end
  if category == "all" then
    output = output .. " / " .. table.concat(s3, " skeleton / ")
  end
  return output  .. " skeleton"
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"},
    ["caliginous standard"] = {"magenta", "dngn_ensign_dark"},
    ["fur brush"] = {"brown", "dngn_yak_fur"},
    ["set of bottled spirits"] = {"lightgreen", "dngn_bottled_spirits"},
    ["djembe set"] = {"brown", "dngn_djembe"},
    ["skull pike"] = {"lightgrey", "dngn_skull_pike"},
    ["mop and bucket"] = {"lightblue", "dngn_mop"},
    ["bloodied mop and bucket"] = {"lightred", "dngn_mop_bloody"},
    ["weapon-inlaid floor"] = {"lightgrey", "floor_blade"}
  }

  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

-- The animation implementation for these tiles needs to be each discrete
-- tiles, alas, so to help shorten its use, just use this each time.
function crackle_def(e)
  return "wall_stone_crackle_1 / wall_stone_crackle_2 / " ..
         "wall_stone_crackle_3 / wall_stone_crackle_4"
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 for standardizing some tags and some floor tiles for vaults_hard
-- subvaults.
function vaults_hard_standard(e, ngen, ft)
  e.tags('vaults_hard')
  if ngen == nil then
    ngen = false
  end
  if ngen then
    e.tags('no_monster_gen')
    e.tags('no_item_gen')
  end
  if you.in_branch("Vaults") then
    if not ft then
      e.ftile('0123456789._^~$%*|defghijkmnFGITUVY+mn{([<})]}> = floor_metal_gold')
    else
      e.ftile(ft .. ' = floor_metal_gold')
    end
  end
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('lindwurm w:' .. 7 - d .. ' / crawling flesh cage w:5 / ' ..
           '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('parchment slevel:' .. 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 .. ' / ' ..
           'harpy simulacrum w:' .. 8 - d * 2 .. ' / ' ..
           'freezing wraith w:2 / guardian sphinx simulacrum w:' .. d - 1)
    e.mons('arcanist / crawling flesh cage')
    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 .. ' / ' ..
           '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_sprouting_stone')
    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('phantasmal warrior w:' .. 10 - d .. ' / ' ..
           'flayed ghost w:' .. 10 - d .. ' / ' ..
           'death knight 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