###
# V for Volcano!
#
# A combined effort of ideas, execution and tweaking by Jude, dpeg, and Zaba!
###
#
# i. Threats
#
# Initial threat is the volcano itself; while there is quite a
# delay between explosions, the flame clouds are quite powerful
# and cover quite a large area; this could kill an early level
# character easily, so beware!
#
# Loot-guard threats are defined in the fiery_guardians function.
# Please see the comments there for explanations, and lists of
# possible threats.
#
# Extra threats will be listed as MONS: lines.
#
# ii. Loot
#
# All volcanoes have a combination of the following items, though
# the amounts of each usually vary. In addition, they also have
# whatever armour or weapons have been created for the monsters that
# populate the level.
#
#   Fire resistance ego armour (any type of armour; this also
#                               includes dragon armour, which is not
#                               given extra rF+)
#   Flaming ego weapons        (a selection of high-damage weapons)
#   Gold
#   "Good" potions with fire themes (see setup_loot() for the list)
#
# In addition, some volcanos have extra items taken from:
#   "Random item"
#   "Bad items"                (see setup_loot() for the list)
#   "Fruit"
#
# See setup_loot() for more information.
#
###
# Index:
#   volcano_grotto   - forgotten grotto "temple" volcano; a temple to
#                      the side of a volcano, line 472-523
#   volcano_lake     - lava lake "temple" volcano; a temple suspended
#                      in the middle of a volcano, line 531-591
#   volcano_pools    - many pools "pyramid"; some caves off a central
#                      chamber, but no pyramid?, line 599-658
#   volcano_tomb     - volcano "tomb"; based of Tutankhamun's burial
#                      chamber, has mummies and fire. Line 666-709.
#   volcano_aerie    - "aerie"; two paths to the loot, including lindwurm
#                      island! Line 717-775.
#   volcano_bunker   - "hidden bunker"; "science"-ish portal vault with
#                      golems and a "conservatory". Line 783-823.
#   volcano_caves    - "collapsing caverns", you can choose which one you
#                      want! maybe more than one? Line 830-902.
#   volcano_village  - by zaba! villagerrs are kinda scary, actually!
#                      Line 912-967.
#   volcano_overflow - overflowing lava! idea by dpeg, code by Jude.
#                      Line 1034+.
###

{{
-- ####
-- # General setup and design functions: (head to line 382 for the maps)

function volcano_portal (e)
    local desc_long = "Leading directly into the rock is a dark and " ..
                      "forbidding tunnel. Every so often air, hot enough " ..
                      "to singe your face, blasts from within, and, as " ..
                      "though triggered by the air, rocks fall from the roof " ..
                      "and sides of the tunnel, slowly filling the entry."

    local timeout_turns = crawl.random_range(1200, 1700)
    local messager =
        timed_msg {
            visible = true,
            -- $F{xxx} will be substituted with the 'entity' property of the timed
            -- marker, or with the desc property (if entity is not set).
            messages = time_messages(timeout_turns,
                            "Rocks fall inside $F{the}.",
                            "Debris falls inside $F{the}, filling the entry.",
                            "More rocks fall inside $F{the}, blocking the entry.",
                            "Rocks have almost completely blocked $F{the}.")
    }

    e.lua_marker('O',
      timed_marker {
        disappear = "There is a deep roar from within the tunnel. Moments " ..
                    "later, a river of lava pours forth, sealing it permanently.",
        desc = "A dark tunnel",
        desc_long = desc_long,
        entity = 'tunnel',
        dst = "volcano",
        dstname_abbrev = "Volcano",
        dstorigin = "in a volcano",
        overview = "dark tunnel",
        turns = timeout_turns,
        msg = messager })
    e.kfeat("O = enter_portal_vault")
    e.tile("O = dngn_portal_volcano")
    e.kfeat("S = .")
    e.colour("O = red")
    e.rtile("X = wall_pebble_red")
    e.ftile("OS = floor_rough_red")
    e.tags("layout_caves")
end

function volcano_feat_descs()
    dgn.set_feature_desc_short("gate leading back to the Dungeon",
                               "rocky tunnel leading out of here")
    dgn.set_feature_desc_short("empty arch of ancient stone",
                               "rock-blocked tunnel")
end

dgn.set_lt_callback("volcano", "volcano_feat_descs")

-- Destinations:
function volcano_setup (e, metal)
    setup_loot(e)
    e.kfeat("< = exit_portal_vault")
    e.kfeat("I = exit_portal_vault")
    e.tile("< = dngn_portal_volcano")
    e.tile("I = dngn_portal_volcano")
    e.kfeat("^ = known alarm trap")
    e.subst("L : LLL.l")
    e.subst("L = lll.")
    e.subst("y : yyy.x")
    e.subst("y = xxx.")
    e.colour("< = red")
    e.lrockcol("red")
    e.lrocktile("wall_pebble_red")
    if metal == nil then
        e.colour("c = lightred")
        e.colour("G = lightred")
        e.colour("= = lightred")
        e.lfloorcol("red")
        e.lfloortile("floor_rough_red")
    end
    e.set_random_mon_list([[hog / fire elemental / fire vortex / giant ant /
                            bumblebee / fire drake / lindwurm / imp / redback /
                            manticore / hell hound / hell hog / ghoul /
                            flayed ghost / pulsating lump / toenail golem /
                            efreet / vampire]])
end

function volcano_milestone(e)
    crawl.mark_milestone("br.enter", "entered a Volcano.", true)
end

-- "Volcano" functions. While the sizes may appear extreme, they are carefully
-- weighted and balanced and have been tested extensively.

local function in_radius_12 (x, y)
  return dgn.point_in_radius(dgn.point(x, y), dgn.point(you.pos()), 12)
end

local large_warning = tw_machine(3, "The air gets thick with the scent of sulphur.",
                                 "In the distance, the volcano erupts with a roar.",
                                 "The volcano comes to life with a roar!")

local small_warning = tw_machine(3, nil, nil, nil, "The volcano roars to life, " ..
                                 "belching forth lava!", "The air gets thick with " ..
                                 "the scent of sulphur.", in_radius_12)

function place_large_volcano(e)
    e.kfeat("V = l")
    e.lua_marker('V', fog_machine { cloud_type = "flame", walk_dist=15, pow_max=6,
                                   delay = 300, size = 10000, spread_rate = 30,
                                   listener = large_warning})
end

function place_chained_volcano(e)
    e.kfeat("V = l")
    e.lua_marker('V', chained_fog_machine { cloud_type = "flame", walk_dist=15, pow_max=6,
                                            delay = 300, size = 3000, spread_rate = 30,
                                            listener = large_warning } )
end


function place_small_volcano(e)
    e.kfeat("V = l")
    e.lua_marker('V', fog_machine { cloud_type = "flame", walk_dist=15, pow_max=6,
                                   delay = 300, size = 800, spread_rate = 30,
                                   listener = small_warning})
end

function place_lake_volcanoes (e, glyphs)
    for _, glyph in ipairs(glyphs) do
        place_lake_volcano(e, glyph)
    end
end

function place_lake_volcano (e, glyph)
    e.kfeat(glyph .. " = l")
    e.lua_marker(glyph, chained_fog_machine { cloud_type = "flame", walk_dist=0,
                            pow_max=6, delay_min = 300, delay_max = 800,
                            size = 300, spread_rate = 5,
                            listener = small_warning})
end

function place_tiny_volcano(e)
    e.kfeat("V = l")
    e.lua_marker('V', fog_machine { cloud_type = "flame", walk_dist=10, pow_max=6,
                                   delay = 800, size = 80, spread_rate = 10,
                                   listener = large_warning})
end
-- #
-- ###

-- ###
-- # Loot functions:

function make_fiery_armour (e, armour)
    local armour_string = ""
    for _, at in ipairs(armour) do
        armour_string = armour_string .. " / " .. at .. " ego:fire_resistance good_item"
    end
    return string.gsub(armour_string, "%s*\/$", "")
end

function make_fiery_weapon (e, weapon)
    local weapon_string = ""
    for _, wt in ipairs(weapon) do
        if string.find(wt, "bow") == nil
          then weapon_string = weapon_string .. " / " .. wt .. " ego:flaming good_item"
          else weapon_string = weapon_string .. " / " .. wt .. " ego:flame good_item"
        end
    end
    local n_weapon = string.gsub(weapon_string, "%s*\/$", "")
    e.item(n_weapon)
end

function setup_loot (e)
    e.item(make_fiery_armour(e,  {"robe w:30", "animal skin w:30", "leather armour w:30",
                                  "ring mail w:30", "scale mail w:20", "chain mail w:20",
                                  "banded mail w:20", "plate mail w:10", "pair of gloves w:5",
                                  "helmet w:6", "pair of boots w:3", "cap w:2", "wizard hat w:2",
                                  "shield w:1", "buckler w:3"}) ..
                                  " / dragon armour w:5")
    e.item([[potion of berserk rage w:20 / potion of poison w:2 / potion of might w:5 / potion of brilliance w:5 /
             potion of agility w:5 / potion of experience w:1 / potion of resistance]])
    e.item(make_fiery_weapon(e, {"demon whip w:2", "dire flail w:4", "ankus w:20", "dagger w:20",
                                 "sabre w:20", "scimitar w:20", "katana w:1", "demon blade w:1",
                                 "triple sword w:1", "broad axe w:20", "battleaxe w:10",
                                 "executioner's axe w:1", "spear w:20", "trident w:20", "demon " ..
                                 "trident w:1", "glaive w:1", "halberd w:10", "lajatang w:10",
                                 "longbow w:5", "crossbow w:5"}))
    e.item("any")
    e.item([[potion of decay / potion of degeneration / potion of mutation /
             scroll of immolation / scroll of curse weapon / scroll of curse armour /
             potion of confusion / potion of paralysis / scroll of paper /
             scroll of random uselessness]])
end

-- #
-- ###

-- ###
-- # Monster functions:

-- This function sets up two slots of monsters: in general, the first
-- slot (say, 1) is the "surrounding" guardians, while the third slot
-- is a "levelled" up version of the 1s. It's currently balanced for
-- two or three 1s, and one 2.
--
-- Packs are basically as follows:
--  ("intelligent" packs; packs involving uniques)
--  orc warrior, orc warrior, orc warrior, Urug; orc warrior, orc warrior,
--  orc warrior, Blork the orc; orc warrior, orc warrior, orc warrior,
--  orc warrior/orc knight.
--  human, human, human, Edmund; human, human, human, human.
--  big kobold, big kobold, big kobold, Sonja; big kobold, big kobold,
--  big kobold, big kobold.
--  gnoll, gnoll, gnoll, Grum + war dogs; gnoll, gnoll, gnoll, gnoll.
--  (in "Tomb") mummy, mummy, mummy, Menkaure; mummy, mummy, mummy,
--  guardian mummy.
--  (no-unique packs, but still "intelligent")
--  deep elf fighter, deep elf fighter, deep elf fighter, deep elf
--  knight;
--  nothing, minotaur (all on its lonesome)
--
-- Natural "packs" usually consist of a few fire/red-themed monsters
-- surrounding either a lindwurm, fire drake, or manticore.
--
-- Demonic "packs" usually consist high chance of imps, toenail golems
-- and pulsating lumps, lower chance of red devils, hell hounds and ghouls
-- which are then surrounding either a hell hog, a hell knight (with
-- watered-down equipment), flayed ghost or flaming corpse.
--
-- Mixed demonic/natural packs consist of mixes of the above.
--
-- Non-living packs consist of fire vortices and elementals, and are usually
-- mixed in with the above demonic packs.

local urug = "Urug ; spear ego:flaming race:orcish . leather armour ego:fire_resistance race:orcish"
local blork = "Blork the orc ; short sword race:orcish ego:flaming . leather armour ego:fire_resistance race:orcish"
local edmund = "Edmund ; flail ego:flaming . leather armour ego:fire_resistance"
local grum  = "Grum ; animal skin ego:fire_resistance"
local hellknight = "hell knight w:1 ; hand axe ego:flaming . ring mail ego:fire_resistance"

function fiery_humans (e)
    -- This is for the village! Wargs and orcs if you came from orc
    if you.in_branch("orc") then
        local orc = "orc warrior ; ring mail ego:fire_resistance race:orcish | leather armour ego:fire_resistance \
                     race:orcish"
        e.mons("warg / " .. orc)
        e.mons(orc)
    -- But hogs and humans if you came from anywhere else.
    else
        local human = "human ; short sword ego:flaming | long sword ego:flaming . ring mail ego:fire_resistance"
        e.mons("hog / " .. human)
        e.mons(human)
    end
end

function fiery_guardians (e)
    local guard_type = ""
    local main_guard = ""
    -- If we came from orc, we expect to only see orcs.
    if you.in_branch("orc") then
        -- We did, and maybe we'll place a unique.
        if crawl.one_chance_in(9) then
            e.mons("orc warrior ; spear race:orcish ego:flaming . leather armour ego:fire_resistance")
            e.mons(urug .. " / " .. blork .. " / orc warrior ; trident race:orcish ego:flaming . ring mail ego:fire_resistance")
            return
        end
    -- We didn't, and maybe we'll place a unique.
    elseif crawl.one_chance_in(9) then
        -- We decided to use a unique.
        local unq_weight = crawl.random2(40)
        if unq_weight < 10 then
            e.mons("human ; scimitar ego:flaming . leather armour ego:fire_resistance")
            e.mons(edmund .. " / human ; falchion ego:flaming . scale mail ego:fire_resistance")
        elseif unq_weight < 20 then
            e.mons("big kobold ; short sword ego:flaming . leather armour ego:fire_resistance")
            e.mons("Sonja / big kobold ; long sword ego:flaming . ring mail ego:fire_resistance")
        elseif unq_weight <= 40 then
            e.mons("gnoll ; halberd ego:flaming | w:2 scythe ego:flaming . scale mail ego:fire_resistance | \
                    banded mail ego:fire_resistance")
            e.mons(grum .. " / gnoll ; glaive ego:flaming . banded mail \
                            ego:fire_resistance | plate mail ego:fire_resistance")
        end
    end

    -- No unique, orcs!
    if you.in_branch("orc") then
        e.mons("orc warrior ; spear race:orcish ego:flaming . leather armour ego:fire_resistance")
        e.mons("orc warrior ; trident race:orcish ego:flaming . ring mail ego:fire_resistance / \
                orc knight ; scythe race:orcish ego:flaming . banded mail ego:fire_resistance")
        return
    end

    -- No unique, minotaur!
    if crawl.one_chance_in(10) then
        -- It's a lone minotaur! labyrinth-esque.
        e.mons("nothing")
        e.mons("minotaur ; trident ego:flaming . banded mail ego:fire_resistance")
        return
    end

    if crawl.one_chance_in(4) then
        if crawl.coinflip() then
            e.mons("big kobold ; short sword ego:flaming . leather armour ego:fire_resistance")
            e.mons("big kobold ; long sword ego:flaming . ring mail ego:fire_resistance / kobold demonologist w:2")
        else
            e.mons("deep elf fighter ; sabre ego:flaming race:elven")
            e.mons("deep elf fighter ; sabre ego:flaming race:elven . chain mail ego:fire_resistance \
                    race:elven / deep elf knight w:3 ; sabre ego:flaming race:elven . chain mail \
                    ego:fire_resistance race:elven")
        end
        return
    end

    -- Unintelligent map!
    -- We are now going to use a mixed pack.
    if crawl.one_chance_in(3) then
        -- "Lair"-esque fire-themed monster pack.
        e.mons("hog / giant ant / redback w:1 / bumblebee w:1 / manticore")
        e.mons("fire drake / lindwurm w:1")
        return
    end

    if crawl.one_chance_in(3) then
        -- "Demonic" fire-themed monster pack.
        e.mons("imp w:20 / pulsating lump / toenail golem / hell hound w:9 / \
                ghoul w:9 / red devil ; trident ego:flaming")
        e.mons("efreet / flaming corpse / flayed ghost / hell hog / vampire / " .. hellknight)
        return
    end

    if crawl.coinflip() then
        -- Demonic/unliving themed pack.
        e.mons("imp / fire elemental / toenail golem / pulsating lump / hell hound / fire vortex")
        e.mons("efreet / vampire / " .. hellknight)
        return
    end

    -- Finally, if we reach this stage, let's go all out.
    e.mons("hell hound / hog / toenail golem / fire elemental / imp")
    e.mons(hellknight)
    return

end
}}

default-depth: Lair:1-8, Orc:1-4, Hive:1

###############################################################################
# Entries:

# [ds] A dummy entry that's a proof-of-concept for synchronized fog machines
# that trigger at multiple places at the same instant, but still have a random
# delay.
NAME: enter_volcano_snarktest101
TAGS: uniq_volcano
ORIENT: float
WEIGHT: 0
{{
  local fog = chained_fog_machine {
                            cloud_type = 'flame',
                            size = 3, pow_min=2,
                            pow_max = 5, delay_min = 22, delay_max = 120
                          }
  lua_marker('m', fog)
}}
SUBST: m = .
:           volcano_portal(_G)
MAP
.......
...m...
.......
.m.O.m.
.......
...m...
.......
ENDMAP

NAME:       enter_volcano_1
TAGS:       uniq_volcano chance_volcano
CHANCE:     5%
ORIENT:     float
COLOUR:     X = red
COLOUR:     S = red
:           volcano_portal(_G)
MAP
 xx
xXX..
XXS..@
XOSS...
XXSS...
xXXx.xx
 xxxxxx
ENDMAP

NAME:       enter_volcano_2
TAGS:       uniq_volcano chance_volcano
CHANCE:     5%
ORIENT:     float
COLOUR:     X = red
COLOUR:     S = red
:           volcano_portal(_G)
MAP
xxxxx
xXXXx
xXOXx
xSSSx
xx.Sxx
 x.S.xx
 xx.@.x
ENDMAP

NAME:       enter_volcano_3
TAGS:       uniq_volcano chance_volcano
CHANCE:     5%
ORIENT:     float
MONS:       patrolling fire drake
#           His name is Robby.
COLOUR:     X = red
COLOUR:     S = red
:           volcano_portal(_G)
MAP
  xxxxx
 xxXXXxx
 xXXOXXx
 xxSSSxx
 xx.1xx
xx...x
x..xxx.
xx....@
 xxxxx.
ENDMAP

# This is the "large" one. You might get a clear path, but then again...
NAME:       enter_volcano_4
TAGS:       uniq_volcano chance_volcano
CHANCE:     5%
ORIENT:     float
COLOUR:     X = red
COLOUR:     S = red
NSUBST:     L = 4:. / *:l
:           volcano_portal(_G)
MAP
 xxxxx
 xXXXx
 xXOXx
xxSSSxx
xxxSxxx
 xxx.xx
  xxx.x
   xxLxx
  xxLlLxx
 xxLlllLxx
 xLlllllLx
 xxLlllLxx
  xxLlLxx
   x.@.x
ENDMAP
###############################################################################

default-depth:

###############################################################################
# "Forgotten grotto Temple"
#
# In the bowels of a volcano, some renegade priests of
# makhleb/trog/vehumet have built a temple, which has
# since been forgotten... the temple guardians still remain
# and are ready to fight to the death.
NAME:       volcano_grotto
WEIGHT:     60
ORIENT:     encompass
TAGS:       volcano no_item_gen no_monster_gen
KFEAT:      _ = altar_makhleb / altar_trog / altar_vehumet
KMONS:      l = lava snake w:2 / lava fish w:5 / nothing w:120
KFEAT:      l = l
#           Sets up the temple guardians.
:           fiery_guardians(_G)
MONS:       clay golem w:50 / molten gargoyle w:2
#           Loot: 9 items, 8 gold.
:           volcano_setup(_G)
:           place_large_volcano(_G)
epilogue{{
volcano_milestone(_G)
}}
MAP
                         xxxx
                    xxxxxxyyxxxx
                 xxxxy......yyyxx
              xxxxyyy.LLLLL....yxxx
            xxxyyy...LlllllL.....Gxxxxxxxx
          xxxyy....LLlllllllL...........yxxx
        xxxyy....LLlllllllllL....Gxxxyy..yyxx
       xxyy.....LllllllllllllL..yxx xxy.y..yxx
      xxy......LlllllllllllllL..yxxx xxyxx.yyx
     xxy......LlllllllllllllllL..yyxx xxy..yxx
    xxy.....LllllllllllllllllllL..yyxxxxxy.xx
   xxy.....LllllllllllllllllllllL....yx xxy.xx
  xxy....LllllllllllVlllllllllllL...yxx  xxy.x
  xy....LlllllllllllllllllllllLL...yxx    xx.x
  xxy....LlllllllllllllllllllL....yxx    xx.xx
   xy.....LlllllllllllllllllLL...yxx     xx.x
   xy.y...LllllllllllllllllLL...yxx      x.yx
   xxyxy...LllllllllllllllL...yyxx      xx+xx
    xxxxy...LllllllllllllL...yxxx      xx...xx
       xxy...LL....LlllllL..yxx   cccccx.....xccccc
        xxy....xxx..LlllL...yx   ccd$ecc..<..ccd$fcc
         xy.yxxx<xxy.LLL...yxx   c.$f$.c.....c.$e$.c
         xx.xx....xxx.....yxx    c.g$g.ccc+ccc.g$g.c
          x.xxx.....xxy....yx    c..3..c.....c..3..c
          xx..xxxAxx.xxy..yxx    cc...c=.111.=c...cc
           xxx..xxx.xxxx..xx      cccccc.G_G.cccccc
             xxx.x.xx  xxxx            cc.2.cc
               x...x                    ccccc
               xxxxx
ENDMAP
###############################################################################

###############################################################################
# "Lava lake Temple"
#
# Somehow, some priests have constructed a temple right over the lava! Who kows
# what magic spells keep this structure afloat, and its occupants from roasting
# to death!
NAME:       volcano_lake
WEIGHT:     60
ORIENT:     encompass
TAGS:       volcano no_item_gen no_monster_gen no_rotate
KFEAT:      _ = altar_makhleb / altar_trog / altar_vehumet
KMONS:      l = lava snake w:2 / lava fish w:5 / nothing w:900
KFEAT:      l = l
#           Let's choose a path from m, u, z, i, r, y
SHUFFLE:    m/u/z/i/r/n
SUBST:      m = .
SUBST:      u = l, z = l, i = l, r = l, n = l
#           Sets up the temple guardians.
:           fiery_guardians(_G)
MONS:       clay golem w:50 / molten gargoyle w:2
#           Loot: 10 items, 6 gold.
:           volcano_setup(_G)
:           place_lake_volcanoes(_G, {"M", "E", "V", "Q", "T", "S"})
epilogue{{
volcano_milestone(_G)
}}
MAP
                      xxxx     xxxxx xxxxx xxxxxx
                    xxxyyxxx  xxyyxxxxyyyxxxyyyyxx
             xxxx  xxx....xxxxx....xx.....xxx...xxxxxx
             xyyxxxxyyy.yyyyyyyy.y....yyy...yyyy...yyxx
           xxxx..yyy.................................yxx
         xxxyyy.......................................yxxx
       xxxyyy...........................................yxxx
    xxxxy...............LLLllLLllLLLllllLLllLLlllL........yxxxx
    xy..............LllllllllllllllllllllllllllllllLL........yxxx
   xxxy............LlllllllllllllllllllllllMiiilllllliL........yxxx
  xxy............LLllllllllllllllllllllllliiMlliilliilllLLL......<x
  xy............Lmmllllllllllllllllllllliillllllliilllllll.......yxx
  xxxy........LllllmmlEllllllllllllllliillllllllllllllllllL.......yx
 xxy...........Llllllmmllllllllllllllilllllllllllllllllllll.....yxxx
  xxy.........LlllllEllmmllLlLLllLLlillLLLllLllllllllllllLL......yx
   xxy.....LlllllllllllllmL..................LlllllllllllllL.....yxxxx
   xy......Lllllllllllllll.ccccccccccccccccc.lllllllllllllllL.......yx
   xy.......LllllllllllllL.c....+.111.+....c.LllllllllllllllL......yxx
   xxy.....Lrrllllllllllll.c.<1.c.G_G.c.1<.c.llllllllllllllLL.......yx
   xy......LllrrVllllllllL.c....c..2..c....c.Lllllllllllluuu.......yxx
   xxy.....Lllllrrllllllll.ccc==ccc+ccc==ccc.LllllllllluullL......yxx
   xy.....LlllllllrllllllL.c......c.c......c.lllllllQuullllL.....yxx
   xxy.....LllllllVrllllll.cccccc.c.c.cccccc.LllllluulllllllL.....yxx
   xy......LllllllllrrlllL.c.$f$c.c.c.cgd$.c.lllluulQlllllllL......yxx
   xxy......Lllllllllrllll.c.$gec.c.c.c$e$.c.LluulllllllllllL......yxx
   xxy.......LllllllllrllL.c.3dgc.c.c.cfg3.c.uullllllllllllL.....yxxx
   xy........LlllllllllrlL.c......c.c......c.LllllllllllllL......yxx
   xxy.....Lllllllllllllrr.cccccccc+cccccccc.llllllllllllllL......yxx
    xy.....LllllllSnnnllnnL.................LLllllllllllllL.....yxxx
    xxxy....LllllnnSllnnlllLllLlLllllLllLlLlzlllllllllllllL.......yxx
     xA.......nnnllllllllllLlllllllllllllllllzzllllllllllllL.......yxx
     xxxxy.....LllllllllllllllllllllllllllllllTzzTllllllllllL.....yxx
       xy........LLllllllllllllllllllllllllllllllzzllllllllL.....yxx
       xxxy..........LllllllllllllllllllLllllllllllzlllllLL......yxx
         xxxy.........LLlllllllllllllLL...LLllllllllzzzL......yxxxx
           xxxy.........LLlLLlLllllLL.......LLllLlLlLL.......yxxx
             xxxxxxxy...................yy.................yxxx
                   xxxxy..............yxxxxxy.............yxxx
                      xxxyyy.yy.yy.yyyxx   xxy..........yxxx
                        xxxxxxxxxxxxxxx     xxyyyy.yyy.yxxx
                                             xxxxxxxxxxxx
ENDMAP
###############################################################################

###############################################################################
# "Many pools Pyramid"
#
# There's no pyramid as such, but it was originally supposed to be a pyramid!
# Instead, we have randomly placed loot in little rooms off the central chamber.
# Nice place to take a holiday, wouldn't want to live here...
NAME:       volcano_pools
WEIGHT:     60
ORIENT:     encompass
TAGS:       volcano no_item_gen no_monster_gen no_rotate
#           Sets up the temple guardians.
:           fiery_guardians(_G)
MONS:       clay golem w:50 / molten gargoyle w:2
#           Loot: 10 items, 6 gold; done in volcano_setup.
SHUFFLE:    T/Q/B/Y/R
#           Do the loot first, 10 objects: two monsters (1, 2)
NSUBST:     T = 2:1 / 1:2 / 1:d / 1:e / 2:$ / 2:f / 2:g
NSUBST:     Q = 2:1 / 1:1 / 2:d / 2:e / 2:$ / 1:f / 1:g
#           Now the entrance:
NSUBST:     B = 1:A / *:.
#           Loot + 10 trashy items.
SUBST:      R = h
NSUBST:     Y = 2:1 / *:.
#           And the exit
SHUFFLE:    <<<
NSUBST:     < = 4:.
:           volcano_setup(_G)
:           place_tiny_volcano(_G)
KFEAT:      J = l
MARKER:     J = lua:fog_machine { size = 3, pow_min = 7, pow_max = 7, delay = 80, \
                                  start_clouds = 1, cloud_type = "flame"}
epilogue{{
volcano_milestone(_G)
}}
MAP
          xxx
         xxyxx
        xxyTyxx  xxx
       xxTTTTyxxxxxxxx
      xxlLTTTy.xx...yxx                                xxx
     xxlllTT<.y..yxx.xxx                              xxyxx
     xxllllLTLxxxxxy.x.xx                    xxxxxxxxxxyQyxx
      xxJlllllxx  xxy..yxx                  xxy...xyQyQQ.LLxx
       xxxxllxx    xxxy..xx              xxxy..yxx.QQQQ.LllLxx
          xxxx       xxyy.x            xxxy..yxxxxlLQQ<Llllllxx
                      xyy.x          xxxy..yxxxxxlllLlLllllllJxx
                     xx..xxxxx      xxy..yxxxx xxlllllllllllxxx
                     x.yxxxxyxxxxxxxxy.yxxxxx   xxlllllllxxxx
                     x...xy..xxy..yxx.yx         xxxJllxxx
                    xx.............y.xxx           xxxxx
                   xxy...LlLlLlL....xyxx          xxx
                  xxy...LllllllllL....yx          xJx
                  xy...LllllllllllL....x         xxllx
                 xy...LlllllVllllL....xx        xxlllxx
                 xy...LlllllllllllL....x       xxlLLllx
               xxx....LlllllllllL....yxxxx    xxlLRRLlx
            xxxxy.xy....LllLlLlL.......xyxx  xxy<RRRRyx
           xxy...yxxyy..............yxx..yxxxxy.RRRRyxx
         xxxy.xxxxxxxxyyxxxyyxy.yyyxxxxxx..xy..yy.Ryxx
      xxxxx..yx      xxxx xxxxxx.xxxxxx xxy..yxxxxxxx
     xxyxy.Lyxxxxx            xx.y<yYyx  xxyxxx
     xyByy.LllllJx           xxyyYYYyyx   xxx
    xy<BBB.Lllllx           xxyYYYYYyxx
    xLBBBBLlllllx           xxllLYYlLLx
    xxLBBBLllllxx            xxllLlllxx
    xlllLLlllxx               xxllllxx
    xlllllllxx                 xxxllx
    xxllllxxx                    xJxx
     xxxJlxx                     xxx
       xxxx
ENDMAP
###############################################################################

###############################################################################
# "Volcano tomb"
#
# Some forgotten emperor was buried here! His tomb is guarded by mummies, flying
# skulls and clouds of flame. Perhaps there is loot!
NAME:       volcano_tomb
WEIGHT:     30
ORIENT:     encompass
TAGS:       volcano no_item_gen no_monster_gen no_rotate
#           Sets up the temple guardians, 1s and 2s.
#           The flying skulls on lava.
KFEAT:      u = lava
KMONS:      u = flying skull
#           We have a specific monster set for this vault.
MONS:       mummy
MONS:       menkaure / guardian mummy
MONS:       fire drake skeleton w:5 / lindwurm skeleton w:1 / hog skeleton / hound skeleton
MONS:       mummy
#           Loot: 4 gold, 8 items.
SHUFFLE:    12K
:           volcano_setup(_G)
:           place_large_volcano(_G)
KFEAT:      JK = l
MARKER:     J = lua:fog_machine { size = 3, pow_min = 7, pow_max = 7, delay = 80, \
                                  start_clouds = 1, cloud_type = "flame"}
MARKER:     K = lua:fog_machine { size = 3, pow_min = 7, pow_max = 7, delay = 80, \
                                  start_clouds = 1, cloud_type = "flame"}
epilogue{{
volcano_milestone(_G)
}}
MAP
                 xxxx
            xxxxxxyyxxxxx
          xxxy..yy.....yxxxx
         xxy........yyx...yxxx                             xxxx
       xxxy.................yxxx                        xxxxyyxx
     xxxy.........LLLL........yxxx                     xxy.y..Lxx
    xxy.........LLllllLL........yxxx            cccccccxy.y.3Lllx
   xxy..<..A...LllllllllLLL.......yxxx          c..Y..cy.xxxLlllx
  xxy.........LlllllllllllllLLL.....yxc       ccc.....=.xx xxllJx
 xxy........LLlllllllllllllllllLLL...lcccccccccGc..3..ccc   xxxxx
xxy....LLlLlllllllllllllllllllllllL........+....+.3<3.+Kc
xy....LlllllllllllllllllllllllllL....lcccccccccGc..3..ccc
xLl.LllllllllllllllllllllllllllllL..yxc       ccc.....c
xlllllllllllllllllGlllllllllllllllLLxx        c1c..Y..c
xxlllllllllllllGlllllGlllllllllllllxx        cc+ccccc=cc cccccc
 xxlllllllllllllllllllllllllllllllxx       ccc.........ccc$defc
  xxullllllllGllllVllllGlllllllluxx        c2+.lllllll.+4=ge$fc
   xxxlllllllllllllllllllllllllxxx         ccc.........ccc$defc
     xxllllllllGlllllGlllllllxxx             cc+ccccc+cc cccccc
      xxllllllllllGlllllllllxxx               c1c   cKc
       xxllllllllllllllllllxxx                ccc   ccc
        xxxllllllllllllllxxx
          xxxlxxlxxxxlxxxx
            xxxxxx  xxx
ENDMAP
###############################################################################

###############################################################################
# Lava "aerie".
#
# It doesn't look much like an aerie these days, but it still has some of
# the "aerie"-ish effects: flame clouds, flame elementals, lava and vortices!
NAME:       volcano_aerie
WEIGHT:     30
ORIENT:     encompass
MONS:       lindwurm
MONS:       toenail golem / molten gargoyle
MONS:       fire elemental / fire vortex
NSUBST:     R = 1:1 / 1:L / 1:l / 1:.
NSUBST:     Y = 8:3 / 6:J / *:.
SUBST:      X = lx
KPROP:      l = no_cloud_gen
COLOUR:     m = blue
TAGS:       volcano no_item_gen no_monster_gen
:           volcano_setup(_G)
:           place_small_volcano(_G)
MARKER:     J = lua:fog_machine { size = 3, pow_min = 7, pow_max = 7, delay = 80, \
                                  start_clouds = 1, cloud_type = "flame"}
KFEAT:      K = l
MARKER:     K = lua:fog_machine { size = 3, pow_min = 7, pow_max = 7, delay = 80, \
                                  start_clouds = 1, cloud_type = "flame"}
# Sides:    Lindwurm # Vortex/elemental
epilogue{{
volcano_milestone(_G)
}}
MAP
                 xxxxxxxxx
                xxKlllllKxx
               xxllLLLLLllxx
              xxXl.d$$ef.lXxx
             xxy...$f<g$...yxx
              xxy..g$de$..yxx
               xxy..yyy..yxx
                xxx+mxm+xxxx
               xxy.xxllLYyxx
              xxy.yxXlllLYyxx
             xxy.2yxXllllLYyx
              xxy2yxXlllLYyxx
               xxy.xxllLYyxx
                xxy.xxLYyxx
                 xxy.xYyxx
                xxxx+x+xxxx
              xxxy..xxxYYyxxx
            xxxy..LlXxXlLYYyxxx
           xxy..LlllXxXlllLYYyxx
           xy.LlllRRXxXlVlllLYyx
           xy.LlllRRXxXlllllLYyx
           xxy..LlllXxXlllLYYyxx
            xxxy..LLXxXlLYYyxxx
              xxxy..xxxYYyxxx
               xxxxx+x+xxxx
                 xxy.xYyxx
                xxy.xxlYyxx
               xxy.xxllLYyxx
              xxy.yxXlllLYyxx
             xxy.2yxXKlllLYyx
              xxy2yxXlllLYyxx
               xxy.xxllLYyxx
                xxx+mxm+xxx
               xxy..yyy..yxx
              xxy.........yxx
             xxy...<...A...yxx
              xxy...LLL...yxx
               xxllLlllLllxx
                xxKlllllKxx
                 xxxxxxxxx
ENDMAP
###############################################################################

###############################################################################
# Hidden bunker!
#
# There are scientists about; beware, as they may wish to experiment on you! The
# idea was by Zaba, and the execution by due!
NAME:       volcano_bunker
WEIGHT:     30
ORIENT:     encompass
TAGS:       volcano no_item_gen no_monster_gen no_rotate
#           Loot: 11 items, 8 gold.
:           volcano_setup(_G, true)
ITEM:       apple / choko
COLOUR:     m = blue
COLOUR:     = = cyan
COLOUR:     + = cyan
MONS:       dragon
MONS:       human ; robe ego:fire_resistance
MONS:       toenail golem
:           place_chained_volcano(_G)
:           dgn.set_feature_desc_short("translucent rock wall",
:                                      "glass window")
:           dgn.set_feature_desc_long("translucent rock wall",
:                                     "A pockmarked, ultra-hard glass window.")
KFEAT:      K = .
MARKER:     K = lua:fog_machine ( { cloud_type = "rain", walk_dist=3, pow_max=2, \
                                    delay=300, size=3 } )
epilogue{{
volcano_milestone(_G)
}}
MAP
      xxxx                  vvvvvvvvvvvvv
   xxxxllxxx xxx            v...........v
 xxxlllllllxxxlxxx          v.vvvvvvvvv.v
xxlllVlllllllllllxxxx       v.v33$e$$fv.v
 xxlllllllllllllllllxxx     v.v$$$gddgv.v
xxllllllllllllllllllllxx    v.+ggdf$$ev.v
 xxllllllllvmvmvmvmvmvvvvvvvvvvvvvvvvvv.v
 xxllllllllm.....vKiii...2...v...=......v
  xxlllllllv.232.viWtWW......+.<.vvvvvvvv
   xxllllllm.....vllttW..2...v...vxxx
    xxxllllvvv+vvvvvvvvvvvvvvvv+vv.yxx
      xxlllm.....v.v..2v2.....v..m..yxx
     xxllllv.<.A.+.v+vvvvv+v+vvv.=..Lyxxx
    xxlllllm.....v...............mLLllllxx
    xxlllllvmvmvmvmvmvmvmvmvmvmvmvlllllxxx
   xxllVlllllllllllllllllllllllllllllllllxx
    xxxlllllllllllllllllllllllllllllVlllxx
      xxllllllllllllllllxxllxxxllllllllxx
       xxxxlllllVllllllxxxxxx xxxlllllxx
          xxxllllllllxxx        xxxllxx
            xxxlllllxx            xxxx
              xxxxxxxx
ENDMAP
###############################################################################

###############################################################################
# Collapsing caverns! These don't actually have flame clouds. Wow!
# idea by dpeg, execution by due. One entrance will close when you enter the
# portal, leaving you with 7 to discover. Quickly, now!
NAME:       volcano_caves
WEIGHT:     30
ORIENT:     encompass
TAGS:       volcano no_item_gen no_monster_gen no_rotate
LFLAGS:     no_tele_control
:           volcano_setup(_G, true)
{{
local function collapse_doorways (data, triggerable, triggerer, marker, ev)
  if triggerer.type ~= "turn" or triggerer.sub_type ~= "countdown" then
    return
  end

  local x, y = marker:pos()
  local you_x, you_y = you.pos()

  if you_x == x and you_y == y then
    crawl.mpr("There is a rumble as the volcano erupts. The roof shakes.",
              "warning")
    return
  end

  if you.see_cell(marker:pos()) then
    crawl.mpr("The volcano erupts! Nearby, a roof collapses.", "warning")
  else
    crawl.mpr("There is a rumble as the volcano erupts. The roof shakes.",
              "warning")
  end
  dgn.terrain_changed(x, y, "stone_wall", false, false, false)
  dgn.colour_at(x, y, "lightred")
  dgn.apply_area_cloud(x, y, 1, 6, 1, 10, "grey smoke", "other", -1)

  -- Don't collapse same doorway twice.
  triggerable:remove(marker)
end

local collapse_marker = TriggerableFunction:new (
  {
    func=collapse_doorways,
    repeated=true,
    props = {
      -- Only collapse one doorway at a time, randomly.
      single_random_slave="true"
    }
  }
)

collapse_marker:add_triggerer(DgnTriggerer:new {
  type="turn",
  delay_min=50,
  delay_max=200
})

}}
KPROP:      RXZ12< = no_rtele_into
SUBST:      X = .
SUBST:      ZY = c.
SUBST:      R = defg$
:           fiery_guardians(_G)
:           lua_marker("M", Triggerable.synchronized_markers(collapse_marker))
:           volcano_setup(_G)
#           There are eight oportunities for loot! Seven single threat (1) plus two items,
#           and one triple threat (121), plus six items. items can be any of: 1 armour,
#           1 weapon, 1 potion, 1 any, 1 gold)
epilogue{{
volcano_milestone(_G)
}}
MAP
               cccc ccc
             ccc<XcccZcccccc
           cccZcccXRRX1ccZZccc
           c<XXZZccXXZccZ1X<cc
           ccc1RRZcZXccXRRXcccc
          cc<ccZXXccMcXZZXccZZcc
         ccZXZccZMcY.cMccccZ1X<c
        ccZ121ZcccY...ccMXXRRccc
       ccZXRRRRccY....Y.cccccc
       cZXXXXXccY..A<....ccZZccc
       ccZRRXXXM.....YcccMXRR1Zcc
        cccZXcccMY..YMc1ccZXXXX<c
          ccccXXccYcccZXXcccZZccc
           ccZXXZccccZXRRXZcccc
          ccZRRX1XX<cccZZXZcc
           ccZXZXZccc cccMcc
            ccccXcc     ccc
             ccccc
ENDMAP
###############################################################################

###############################################################################
# Zaba's village!
#
# These stupid humans have built their village right next to a dormant volcano.
# It has erupted! Most have fled, but some have stayed behind to guard their
# hard-earned loot. Idea kinda by dpeg, execution by Zaba.
NAME:       volcano_village
WEIGHT:     30
ORIENT:     encompass
TAGS:       volcano no_item_gen no_monster_gen no_rotate
SUBST:      S = lw
SUBST:      W = wW.
SUBST:      L = ll.
SUBST:      R = lx
KFEAT:      # = open_sea
SHUFFLE:    MIN
SUBST:      I = $def
NSUBST:     M = 4:1 / 1:2 / *:.
NSUBST:     N = 6:1 / *:.
SUBST:      " = ..'
KFEAT:      ' = alarm trap
:           set_border_fill_type("open_sea")
:           fiery_humans(_G)
:           volcano_setup(_G)
:           place_chained_volcano(_G)
epilogue{{
volcano_milestone(_G)
}}
MAP
###########################################
#wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww#
#wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww#
#wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww#
#wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww#
#wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww#
#wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww#
#wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww#
#wwwwwwwwWwWwWwWwWwWwWwWwWwWwWwWwWwwwwwwww#
#wwwwwwwWWWWWWWWWWWWWWWWWWWWWWWWWWWwwwwwww#
#wwwwwwx...."""....."""....."""....xxwwwww#
#wwwxxxx...xx+xx...xxxxx...xx+xx...'xxwwww#
#wwxx.xx..xxMMMxx.xxIIIxx.xxNNNxx..x.xxxww#
#SSx.x.x..xMMMMMx.xIIIIIx.xNNNNNx..x.xAxSS#
xSSx<x.x..xMMMMMx.xIIIIIx.xNNNNNx..x.x<xSSx
xlRxxx.x..xxMMMxx.xxIIIxx.xxNNNxx..xx.xxRlx
xRlllxx....xxxxx...xx+xx...xxxxx...xxxxllRx
xlRlllxx...."""....."""....."""....xllllRlx
xRllllllLLLLLLLLLLLLLLLLLLLLLLLLLLLllllllRx
xlRllllllLlLlLlLlLlLlLlLlLlLlLlLlLllllllRlx
xRlllVllllllllllllllllllllllllllllllVllllRx
xlRlllllllllllVllllllVllllllllVlllllllllRlx
xRlRlllllllllllllllllllllllllllllllllllRlRx
xRlllRlllRlllRlllRlllRlllRlllRlllRlllRlllRx
xlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlx
xRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRlRx
xRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ENDMAP
###############################################################################

###############################################################################

###############################################################################
# Let's go, Overflow!
#
# You don't have much time to get the loot, as the Volcano is spitting out lava
# like there's no tomorrow! Of course, if you can levitate or fly, you've got a
# good chance of getting everything. If you get stuck, you can just wait it out.
#
# No monsters, only lava and loot. Original idea by dpeg.
#
# TODO: Come up with a better way to indicate to the player that the lava does
#       eventually recede.
NAME:       volcano_overflow
WEIGHT:     10
ORIENT:     encompass
TAGS:       volcano no_item_gen no_monster_gen no_rotate
MONS:       nothing, nothing, nothing
{{

function convert_lava (data, triggerable, triggerer, marker, ev)
  if triggerer.type ~= "turn" or triggerer.sub_type ~= "countdown" then
    return
  end

  data.lava_phase = data.lava_phase + 1
  local lp = data.lava_phase
  local my_slaves = {}

  -- So we don't have to duplicate code too much.
  local function convert_slaves_to_lava (mslaves, opposite)
   local yp = dgn.point(you.pos())
    for _, pos in ipairs(mslaves) do
      if pos ~= yp then
        if opposite then
          dgn.terrain_changed(pos.x, pos.y, "floor", false, false, false)
        else
          dgn.terrain_changed(pos.x, pos.y, "lava", false, false, false)
        end
      end
    end
  end

  if lp == 1 then
    crawl.mpr("The ground shudders ominously.", "warning")
  elseif lp == 2 then
    my_slaves = dgn.find_marker_positions_by_prop("lava_phase", 2)
    crawl.mpr("In the distance, the volcano explodes with a roar! Lava spreads "
               .. "onto the path.", "warning")
    convert_slaves_to_lava(my_slaves)
  elseif lp == 3 then
    crawl.mpr("The air is thick with the scent of sulphur.", "warning")
  elseif lp == 4 then
    my_slaves = dgn.find_marker_positions_by_prop("lava_phase", 4)
    crawl.mpr("There is another distant roar. More lava overflows!", "warning")
    convert_slaves_to_lava(my_slaves)
  elseif lp == 5 then
    crawl.mpr("The ground moves violently!", "warning")
  elseif lp == 6 then
    my_slaves = dgn.find_marker_positions_by_prop("lava_phase", 6)
    crawl.mpr("The volcano erupts again! A thin layer of lava overflows to " ..
              "fill the cavern.", "warning")
    convert_slaves_to_lava(my_slaves)
  elseif lp == 7 then
    my_slaves = dgn.find_marker_positions_by_prop("lava_phase", 6)
    crawl.mpr("The ground shudders. Some of the lava has hardened enough to walk " ..
              "over!", "warning")
    convert_slaves_to_lava(my_slaves, true)
  end
end

-- So we know what to convert.
lua_marker("1", portal_desc { lava_phase=2 })
lua_marker("2", portal_desc { lava_phase=4 })
lua_marker("3", portal_desc { lava_phase=6 })

-- And finally, let's convert it
local sink_marker = TriggerableFunction:new {
  func = convert_lava,
  repeated = true,
  data = {lava_phase=0}
}

sink_marker:add_triggerer(DgnTriggerer:new {
  type="turn",
  delay_min=50,
  delay_max=200, })

lua_marker("M", sink_marker)
}}
SUBST:      M = c
NSUBST:     123 = 8:d / 8:e / 8:f / 8:g / 8:h / *:.
:           volcano_setup(_G)
epilogue{{
volcano_milestone(_G)
}}
MAP
                xxxx         xxx xxx                   xxx
        xxxxx  xx33xxx     xxx3xxx3xxxx xxxxx xxx     xx3xx
       xx333xxxx32233xxx xxx3323332333xxxx33xxx3xxx xxx323xx
     xxx321133332112233xxx332211221121333322333233xxx332123xx
   xxx3321l122221ll11133333311ll111l111222212211223332211123xx
 xxx3321llll1111llllll111111lllllllllll11111111111222111123xx
xx3321llllllllllllllllllllllllllllllllllll11233321111ll123xx
 xx3321lllllllllllllllllllllllllllllllllll123xxx3321lll123xx
  xxx321lllllllllllllllllllllllllllllllll123xxAxxx321lll123xx
    xx321lllllllllllllllll111lllllllllll123xx<...xx3211ll123xx
     xx321lll11llllllll122333221lllllllll123xxx...xx321lll123x
      x321ll1221llllll1223xxx3211llllllll11233x....3321llll13xx
    xxx321l133321llll1233xx xx3221llllllll123xx...xx321ll1123xx
   xx3321133xxx33211123xxx   xx3321llll11233333.xxx322111233xx
   x332233xxx xxx33233xx      xxx332111233xxxxxxx xx332233xxx
   xxx33xxx     xxx3xxx    M    xxx33233xxx        xxx33xxx
     xxxx         xxx             xxx3xxx            xxxx
                                    xxx
ENDMAP
###############################################################################
