###############################################################################
# Special rooms code.
# A simple rectangular box filled to the walls with a fair bit of a themed
# monster set, the contents of which are usually scaled versus depth.
# This file contains the monster selection for said boxes: the special_room
# box creation and placement code is off in mini_monsters.des.
#
# Current sets: Kobolds, Orcs, Bees, Undead, Slimes,
# Mythological Zoo, Spellcasters, Greater Demons.
#

lua {{

crawl_require('dlua/vault.lua')

function fill_special_room(e, mon, lord_mon, pack)
    if type(mon) == "table" then
        mon = util.join(" / ", mon)
    end

    e.default_subvault_glyphs()

    if pack then
        e.subst('. : 1')
    else
        e.subst('. = 1:30 .')
    end

    -- Limit the number of monsters.
    e.nsubst('1 = 24:1 / 3 = 1. / *:.')

    if lord_mon then
        e.nsubst('1 = 1:2 / *:1')
        e.kmons('2 = ' .. lord_mon)
    end

    e.kmons('1 = ' .. mon)
end

function sroom_kobold_lair(e)
    local level = you.absdepth() - 1

    -- Return early if we're being called during map validation.
    if e.is_validating() then return end

    local level_mons = 6

    if level < 6 then
        level_mons = 2
    elseif level < 9 then
        level_mons = 4
    end

    local big_freq   = 3 + level_mons
    local small_freq = 12 - big_freq
    local mon = "kobold w:" .. small_freq .. " / kobold brigand w:" .. big_freq

    lord_mon = "kobold demonologist"

    fill_special_room(e, mon, lord_mon)
end

function sroom_orc_lair(e)
    local level = you.absdepth() - 1

    -- Return early if we're being called during map validation.
    if e.is_validating() then return end

    local mon

    if level > 20 or you.in_branch("Elf") then
        mon = "orc priest w:7 / orc warrior w:12 / orc knight w:8 / "
              .. " orc high priest w:2 / two-headed ogre w:1"
        lord_mon = "orc warlord"
    elseif level > 14 or you.in_branch("Orc") then
        mon = "orc w:6 / orc warrior w:8 / orc priest w:2 /  "
              .. "orc knight w:3 / troll w:1 "
        lord_mon = "orc knight / orc high priest w:6 / orc warlord w:4"
    elseif level > 9 then
        mon = "orc w:25 / orc warrior / orc priest w:3 / ogre w:2"
        lord_mon = "orc priest w:7 / orc knight w:3"
    else
        mon = "orc w:44 / orc warrior w:5 / ogre w:1"
        lord_mon = "orc priest"
    end

    fill_special_room(e, mon, lord_mon, true)
    if crawl.coinflip() then
        e.kfeat('2 = altar_beogh')
    end
    e.kitem('1. = gold level:' .. level - 4 .. ' w:1 / nothing w:8')
    e.kitem('2 = gold')
end

function sroom_beehive(e)
    if e.is_validating() then return end

    local level = you.absdepth()

    if you.in_branch("Lair") then
        level = you.absdepth() - 2
    end

    fill_special_room(e, "patrolling killer bee",
                      "patrolling queen bee", true)

    e.kmons('M = meliai')
    if level > 11 then
        e.nsubst('1 = 3:M / *:1')
    end

    e.kitem('12M = never_decay yak corpse / potion of ambrosia ident:all /\
                   nothing w:20')
end

function sroom_morgue(e)

    if e.is_validating() then return end

    local bodies
    local bodies_chance
    local weap = ""
    if you.in_branch("Geh") then
        weap = " ego:flaming ident:type"
    elseif you.in_branch("Coc") then
        weap = " ego:freezing ident:type"
    elseif you.in_branch("Dis") then
        weap = " good_item"
    elseif you.in_branch("Tar") then
        weap = " ego:draining ident:type"
    end

    local mons = {}

    mons[1] = "zombie w:9 / skeleton w:5 / spectral thing w:1"
    mons[2] = "shadow wraith w:3 / soul eater w:4 / vampire mage w:3 / "
              .. "flayed ghost w:4 / death knight w:1"
    mons[3] = "skeletal warrior w:15 ; great mace" .. weap
              .. " | glaive" .. weap .. " | battleaxe" .. weap
    mons[4] = "vampire knight ; chain mail . great mace" .. weap
              .. " | glaive" .. weap .. " | battleaxe" .. weap
    if you.in_branch("Geh") then
        mons[5] = "fire giant zombie w:3 / fire giant skeleton w:3 / "
                 .. "fire dragon zombie w:2 / fire dragon skeleton w:2"
        mons[6] = "flayed ghost"
        bodies = "fire giant corpse / fire giant skeleton / "
                 .. "fire dragon corpse / fire dragon skeleton"
        bodies_chance = 40
    elseif you.in_branch("Coc") then
        mons[5] = "hydra zombie w:3 / hydra simulacrum w:3 / "
                 .. "alligator snapping turtle zombie w:2 / "
                 .. "alligator snapping turtle skeleton w:2"
        mons[6] = "freezing wraith w:7 / bog body w:3"
        bodies = "frost giant corpse / frost giant skeleton / "
                 .. "ice dragon corpse / ice dragon skeleton / "
                 .. "alligator snapping turtle corpse / "
                 .. "alligator snapping turtle skeleton / "
                 .. "hydra corpse / hydra skeleton"
        bodies_chance = 40
    elseif you.in_branch("Dis") then
        mons[5] = "iron troll zombie w:2 / iron troll skeleton w:2 / "
                 .. "iron dragon zombie w:3 / iron dragon skeleton w:3"
        mons[6] = "ancient champion w:7 / phantasmal warrior w:3"
        bodies = "iron dragon corpse / iron dragon skeleton / "
                 .. "iron troll corpse / iron troll skeleton"
        bodies_chance = 40
    elseif you.in_branch("Tar") or you.in_branch("Crypt") then
        mons[5] = "eidolon w:6 / jiangshi w:6"
        mons[6] = "mummy priest w:2 / revenant w:6"
        bodies = "shadow dragon corpse / base draconian corpse / "
                 .. "dire elephant corpse"
        bodies_chance = 33
    else
        mons[5] = "necromancer w:5 / deep elf death mage w:5"
        mons[6] = "shadow dragon"
        bodies = "any corpse / any skeleton"
        bodies_chance = 33
    end

    if you.absdepth() > 27 then
        mons[7] = "reaper w:16 / bone dragon w:4"
    end

    if you.absdepth() > 24 or crawl.x_chance_in_y(you.absdepth() - 20, 5) then
        lord_mon = "ancient lich / dread lich"
    else
        lord_mon = "lich"
    end

    fill_special_room(e, mons, lord_mon, true)
    if you.in_branch("Depths") or you.in_branch("Crypt") then
         e.kitem('2 = randbook disc:necromancy')
    else
         e.nsubst('1. = 1:})]>.')
    end

    e.subst(". = .:" .. (100 - bodies_chance) .. " _:" .. bodies_chance)
    e.subst("1 = 1:" .. (100 - bodies_chance) .. " !:" .. bodies_chance)
    -- XXX: Clean up this dirty hack.
    e.kmons("! = " .. mons[1] .. " / " .. mons[2] .. " / " .. mons[3] ..
            " / " .. mons[4] .. " / " .. mons[5] .. " / " .. mons[6])
    e.kfeat("_ = .")

    dgn.delayed_decay(e, '!_', bodies)
end

function sroom_jelly_pit(e)

    -- Return early if we're being called during map validation.
    if e.is_validating() then return end

    local level = you.absdepth()

    if you.in_branch("Lair") then
        level = you.absdepth() - 7
    elseif you.in_branch("Slime") then
        level = you.absdepth() + 10
    end

    local mons = {}

    mons[1] = "endoplasm w:" .. math.max(72 - level * 2, 1)
    mons[2] = "jelly w:54"
    mons[3] = "great orb of eyes w:" .. (1 + level)
    mons[4] = "large slime creature w:" .. (2 + level)
    mons[5] = "rockslime w:" .. (9 + level * 2)
    mons[6] = "azure jelly w:" .. math.max(level * 2 - 13, 1)
    mons[7] = "acid blob w:" .. math.max(level * 2 - 16, 1)

    lord_mon = "rockslime w:6 / azure jelly / acid blob"

    fill_special_room(e, mons, lord_mon, true)

    e.nsubst('1. = 2 = x1')

    if crawl.coinflip() and not you.in_branch("Slime") then
        e.nsubst('1. = 1:A')
        e.kfeat('A = altar_jiyva')
    end
end

function sroom_mythical_zoo(e)

    -- Return early if we're being called during map validation.
    if e.is_validating() then return end

    local Z = you.absdepth()

    if you.in_branch("Elf") then
        Z = Z + 5
    elseif you.in_branch("Lair") then
        Z = Z - 2
    end

    local mons = {}
    mons[1] = "rime drake w:" .. math.max(38 - Z * 2, 1)
    mons[2] = "basilisk w:" .. math.max(38 - Z * 2, 1)
    mons[3] = "wyvern w:" .. math.max(44 - Z * 2, 1)
    mons[4] = "hell rat w:" .. math.max(44 - Z * 2, 1)
    mons[5] = "hell hound w:" .. math.max(Z - 11, 1)
    mons[6] = "hydra w:" .. math.max(Z * 2 - 26, 1)

    if Z >= 16 then
        mons[7] = "manticore w:" .. (Z * 2 - 24)
        mons[8] = "harpy w:" .. (Z - 15)
    end
    if Z >= 19 then
        mons[9] = "fire dragon w:" .. (Z * 2 - 37)
        mons[10] = "sphinx w:" .. (Z - 16)
    end

    if Z >= 21 then
       lord_mon = "catoblepas / sphinx w:60 / hell beast w:20"
    elseif Z >= 16 then
       lord_mon = "catoblepas / hydra w:40 / hell beast w:40"
    else
       lord_mon = "catoblepas / manticore w:40 / hydra w:40"
    end

    fill_special_room(e, mons, lord_mon, true)

    e.kitem('2 = gold good_item w:' .. Z - 7 .. ' / gold w:' .. Z + 7 .. ', ' ..
            'box of beasts w:3 / nothing w:17')
end

function sroom_magic_class(e)

    -- Return early if we're being called during map validation.
    if e.is_validating() then return end

    local mons = {}
    mons[1] = "wizard w:8"
    mons[2] = "ogre mage w:7"
    mons[3] = "deep elf annihilator w:6"
    mons[4] = "deep troll earth mage w:5"
    mons[5] = "vampire knight w:5"
    mons[6] = "spriggan air mage w:5"
    mons[7] = "necromancer w:4"
    mons[8] = "deep elf death mage w:3"
    mons[9] = "deep elf sorcerer w:3"
    mons[10] = "deep elf demonologist w:2"
    mons[11] = "deep elf elementalist w:1"
    mons[12] = "vampire mage w:1"

    local absdepth = you.absdepth()
    if absdepth == 27 then
        mons[13] = "draconian annihilator w:5"
        lord_mon = "draconian shifter / ancient lich / Jory w:1 / " ..
                   "Frederick w:1 / Boris w:1, draconian shifter / " ..
                   "ancient lich / dread lich"
    elseif crawl.x_chance_in_y(absdepth - 20, 5) then
        lord_mon = "ancient lich / Jory w:1 / Frederick w:1 / Boris w:1" ..
                   ", ancient lich / dread lich"
    else
        lord_mon = "lich / tengu reaver"
    end

    fill_special_room(e, mons, lord_mon, true)

    e.kitem('2 = any randbook')

end

function sroom_demon_pit(e)

    -- Return early if we're being called during map validation.
    if e.is_validating() then return end

    local runes = count_pan_runes()
    local weight_a = 30 - runes * 5
    local weight_b = 20 - runes * 2
    local weight_c = 10 + runes * 2
    local weight_d = 5 + runes

    local tier_twos = {
        {"hell_beast", weight_a},
        {"green_death", weight_a},
        {"reaper", weight_b},
        {"lorocyproca", weight_b},
        {"balrug", weight_c},
        {"blizzard_demon", weight_c},
        {"hellion", weight_d},
        {"tormentor", weight_d},
        {"cacodemon", 5},
    }

    -- Choose three demons as weighted above,
    -- and don't choose the same one twice.
    local mons = {}
    for mon_num=1,3 do
        local chosen = util.random_choose_weighted_i(tier_twos)
        mons[mon_num] = tier_twos[chosen][1]
        tier_twos[chosen][2] = 0
    end

    lord_mon = "brimstone fiend / ice fiend / tzitzimitl / " ..
               "hell sentinel / nonbase demonspawn w:20"

    fill_special_room(e, mons, lord_mon, true)

    e.kitem('2 = *')
    e.kfeat('2 = transit_pandemonium')
end

}}

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

NAME:   special_room_kobold
DEPTH:  D:7-11, Orc, !Orc:$
TAGS:   special_room unrand
WEIGHT: 11
: sroom_kobold_lair(_G)
MAP
ENDMAP

NAME:   special_room_orc
DEPTH:  D:8-, Orc, !Orc:$, Elf, Vaults
TAGS:   special_room allow_dup unrand
WEIGHT: 59 (D:8-12, Orc), 40 (D:13-, Elf:1), 32
: sroom_orc_lair(_G)
MAP
ENDMAP

NAME:   special_room_bee
DEPTH:  D:9-, Lair, Orc, !Orc:$, Spider
TAGS:   special_room unrand uniq_beehive
WEIGHT: 30 (D:9-12, Orc, Lair:1-3), 24 (D:13-, Lair:4-), 20
: sroom_beehive(_G)
MAP
ENDMAP

NAME:   special_room_morgue
DEPTH:  Depths, Crypt, Dis, Tar, Coc, Geh
TAGS:   special_room allow_dup unrand
WEIGHT: 29 (Depths:1-3), 34
: sroom_morgue(_G)
MAP
ENDMAP

NAME:   special_room_jelly
DEPTH:  Depths, Lair:$, Slime
TAGS:   special_room allow_dup unrand
WEIGHT: 9 (Lair:$), 13 (Depths:1-3), 40
: sroom_jelly_pit(_G)
MAP
ENDMAP

NAME:   special_room_mythical_zoo
DEPTH:  D:14-, Depths, Lair:4-, Elf
TAGS:   special_room allow_dup unrand
WEIGHT: 20 (D:14-, Lair:4-5), 25 (Depths:1-3, Lair:$, Elf), 28
: sroom_mythical_zoo(_G)
MAP
ENDMAP

NAME:   special_room_magic_class
DEPTH:  Depths
TAGS:   special_room allow_dup unrand
: sroom_magic_class(_G)
MAP
ENDMAP

NAME:   special_room_demon_pit
DEPTH:  Pan
TAGS:   special_room allow_dup unrand
WEIGHT: 20
: sroom_demon_pit(_G)
MAP
ENDMAP
