lua {{

function fill_special_room(mon, lord_mon, pack)
    local level, tl_x, tl_y, br_x, br_y = dgn.get_special_room_info()

    -- Return early if we're being called during map validation.
    if not level then
        return
    end

    if type(mon) == "table" then
        mon = util.join(" / ", mon)
    end

    if type(mon) == "string" then
        mon = dgn.monster_spec(mon)
    end

    local lord_x, los_y = -1, -1
    if lord_mon then
        lord_x = crawl.random_range(tl_x, br_x)
        lord_y = crawl.random_range(tl_y, br_y)
    end

    for x = tl_x, br_x do
        for y = tl_y, br_y do
            if (pack or not crawl.one_chance_in(4))
               and not (lord_x == x and lord_y == y)
            then
                dgn.create_monster(x, y, mon)
            end
        end
    end

    if lord_mon then
        dgn.create_monster(lord_x, lord_y, lord_mon)
    end
end

-- NOTE: To make beehives occur in the Lair with the same absolute frequency
-- as in 0.4, the special room definitions which don't fit there should
-- just do nothing. Can't use dummy vaults to do this since vault
-- frequency is controlled by absolute depth rather than by branch depth.
function is_in_lair()
    local l_name = dgn.level_name(dgn.level_id())
    return string.find(dgn.level_name(dgn.level_id()), "Lair")
end

function sroom_kobold_lair()
    local level = dgn.get_special_room_info()

    -- Return early if we're being called during map validation.
    if not level then
        return
    end

    if is_in_lair() then
        return
    end

    local level_mons = 3

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

    local big_freq   = 3 + level_mons
    local small_freq = 10 - big_freq

    local mon = "kobold w:" .. small_freq .. " / big kobold w:" .. big_freq

    fill_special_room(mon, "big kobold")
end

function sroom_orc_lair()
    local level = dgn.get_special_room_info()

    -- Return early if we're being called during map validation.
    if not level then
        return
    end

    if is_in_lair() then
        return
    end

    local mon
    if level > 24 then
        mon = "orc w:2 / orc warrior w:3 / orc knight w:2 / ogre w:2 / "
              .. "troll w:1"
    elseif level > 15 then
        mon = "orc w:6 / orc knight w:1 / orc warrior w:2 / ogre w:1"
    elseif level > 9 then
        mon = "orc w:8 / orc warrior w:2"
    else
        mon = "orc w:9 / orc warrior w:1"
    end

    fill_special_room(mon)
end

function sroom_beehive()
    local level, tl_x, tl_y, br_x, br_y = dgn.get_special_room_info()

    -- Return early if we're being called during map validation.
    if not level then
        return
    end
    fill_special_room("patrolling killer bee larva w:1 / "
                      .. "patrolling killer bee w:6",
                      "patrolling queen bee", true)

    local food = dgn.item_spec("royal jelly w:1 / honeycomb w:24")
    for x = tl_x, br_x do
        for y = tl_y, br_y do
            if crawl.one_chance_in(2) then
                dgn.create_item(x, y, food)
            end
        end
    end
end

function sroom_morgue()
    if is_in_lair() then
        return
    end

    fill_special_room("small zombie w:500 / wight w:167 / necrophage w:167 / "
                      .. "wraith w:125 / vampire w:42", nil, true)
end

function sroom_jelly_pit()
    local level, tl_x, tl_y, br_x, br_y = dgn.get_special_room_info()

    -- Return early if we're being called during map validation.
    if not level then
        return
    end

    local mons = {}

    mons[1] = "ooze w:" .. (27 - math.floor(level / 5))
    mons[2] = "jelly w:20"
    mons[3] = "brown_ooze w:" .. (3 + level)
    mons[4] = "death ooze w:" .. (2 + (2 * math.floor(level / 3)))

    if level >= 12 then
        mons[5] = "azure jelly w:" .. (1 + math.floor((level - 12)/3))
    end

    if level >= 15 then
        mons[6] = "acid blob w:" .. (1 + math.floor((level - 15) / 4))
    end

    -- XXX: This may leave behind random Jiyva altars when the vault is veto'd.
    -- It really shouldn't, though!
    local jiyva_placed = false
    local jiyva_altar = dgn.fnum("altar_jiyva")
    for x = tl_x, br_x do
        for y = tl_y, br_y do
            if not jiyva_placed and crawl.one_chance_in(30) then
                dgn.grid(x, y, jiyva_altar)
                jiyva_placed = true
            end
        end
    end

    fill_special_room(mons, nil, true)
end
}}

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

NAME:   special_room_kobold
DEPTH:  6-14, !Lair, !Crypt
TAGS:   special_room allow_dup
WEIGHT: 11
: sroom_kobold_lair()
MAP
ENDMAP

NAME:   special_room_orc_a
DEPTH:  8-14, !Lair, !Crypt
TAGS:   special_room allow_dup
WEIGHT: 59
: sroom_orc_lair()
MAP
ENDMAP

NAME:   special_room_bee_a
DEPTH:  8-14, !Crypt
TAGS:   special_room allow_dup
WEIGHT: 30
: sroom_beehive()
MAP
ENDMAP
################################
NAME:   special_room_orc_b
DEPTH:  15-16, !Lair, !Crypt
TAGS:   special_room allow_dup
WEIGHT: 50
: sroom_orc_lair()
MAP
ENDMAP

NAME:   special_room_bee_b
DEPTH:  15-16, !Crypt
TAGS:   special_room allow_dup
WEIGHT: 25
: sroom_beehive()
MAP
ENDMAP

NAME:   special_room_morgue_b
DEPTH:  15-16, !Lair
TAGS:   special_room allow_dup
WEIGHT: 25
: sroom_morgue()
MAP
ENDMAP
#################################
NAME:   special_room_orc_c
DEPTH:  17, !Lair, !Crypt
TAGS:   special_room allow_dup
WEIGHT: 40
: sroom_orc_lair()
MAP
ENDMAP

NAME:   special_room_bee_c
DEPTH:  17, !Crypt
TAGS:   special_room allow_dup
WEIGHT: 25
: sroom_beehive()
MAP
ENDMAP

NAME:   special_room_morgue_c
DEPTH:  17, !Lair
TAGS:   special_room allow_dup
WEIGHT: 27
: sroom_morgue()
MAP
ENDMAP

NAME:   special_room_jelly_c
DEPTH:  17, !Crypt
TAGS:   special_room allow_dup
WEIGHT: 9
: sroom_jelly_pit()
MAP
ENDMAP
#################################
NAME:   special_room_orc_d
DEPTH:  18-20, !Lair, !Crypt
TAGS:   special_room allow_dup
WEIGHT: 25
: sroom_orc_lair()
MAP
ENDMAP

NAME:   special_room_bee_d
DEPTH:  18-20, !Crypt
TAGS:   special_room allow_dup
WEIGHT: 33
: sroom_beehive()
MAP
ENDMAP

NAME:   special_room_morgue_d
DEPTH:  18-20, !Lair
TAGS:   special_room allow_dup
WEIGHT: 29
: sroom_morgue()
MAP
ENDMAP

NAME:   special_room_jelly_d
DEPTH:  18-20, !Crypt
TAGS:   special_room allow_dup
WEIGHT: 13
: sroom_jelly_pit()
MAP
ENDMAP
#################################
NAME:   special_room_orc_e
DEPTH:  21-, !Lair, !Crypt
TAGS:   special_room allow_dup
WEIGHT: 15
: sroom_orc_lair()
MAP
ENDMAP

NAME:   special_room_bee_e
DEPTH:  21-, !Crypt
TAGS:   special_room allow_dup
WEIGHT: 8
: sroom_beehive()
MAP
ENDMAP

NAME:   special_room_morgue_e
DEPTH:  21-, !Lair
TAGS:   special_room allow_dup
WEIGHT: 32
: sroom_morgue()
MAP
ENDMAP

NAME:   special_room_jelly_e
DEPTH:  21-, !Crypt
TAGS:   special_room allow_dup
WEIGHT: 45
: sroom_jelly_pit()
MAP
ENDMAP

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

# 0.4 crawl C code for randomly determining which special room type to
# use

#    if (level_number < 7)
#        spec_room_type = SROOM_LAIR_KOBOLD;
#    else
#    {
#        spec_room_type = random2(NUM_SPECIAL_ROOMS);
#
#        if (level_number < 23 && one_chance_in(4))
#            spec_room_type = SROOM_BEEHIVE;
#
#        // Replace overly dangerous special rooms with a room full of orcs.
#        if (level_number > 13 && spec_room_type == SROOM_LAIR_KOBOLD
#            || level_number < 16 && spec_room_type == SROOM_MORGUE
#            || level_number < 14 && spec_room_type == SROOM_JELLY_PIT
#            || level_number < 17 && one_chance_in(4))
#        {
#            spec_room_type = SROOM_LAIR_ORC;
#        }
#
#        if (level_number > 19 && coinflip())
#            spec_room_type = SROOM_MORGUE;
#
#        if (level_number > 13 &&
#            one_chance_in(6 - (level_number > 23) - (level_number > 18)))
#        {
#            spec_room_type = SROOM_JELLY_PIT;
#        }
#    }
#

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

# 0.4 crawl percentages for each room type generated per level (for 10,000
# randomly generated vaults per level)

#  |   K   |    O   |    B   |    M   |    J   |
#-----------------------------------------------
# 0|  0.00 |   0.00 |   0.00 |   0.00 |   0.00 |
# 1|  0.00 |   0.00 |   0.00 |   0.00 |   0.00 |
# 2|  0.00 |   0.00 |   0.00 |   0.00 |   0.00 |
# 3|  0.00 |   0.00 |   0.00 |   0.00 |   0.00 |
# 4|  0.00 |   0.00 |   0.00 |   0.00 |   0.00 |
# 5|  0.00 |   0.00 |   0.00 |   0.00 |   0.00 |
# 6|100.00 |   0.00 |   0.00 |   0.00 |   0.00 |
# 7| 11.39 |  59.25 |  29.36 |   0.00 |   0.00 |
# 8| 11.07 |  58.43 |  30.50 |   0.00 |   0.00 |
# 9| 11.23 |  57.98 |  30.79 |   0.00 |   0.00 |
#10| 11.46 |  58.39 |  30.15 |   0.00 |   0.00 |
#11| 11.30 |  58.78 |  29.92 |   0.00 |   0.00 |
#12| 11.21 |  58.65 |  30.14 |   0.00 |   0.00 |
#13| 10.92 |  58.96 |  30.12 |   0.00 |   0.00 |
#14|  0.00 |  49.58 |  24.99 |  25.43 |   0.00 |
#15|  0.00 |  49.74 |  24.56 |  25.70 |   0.00 |
#16|  0.00 |  39.51 |  24.77 |  27.04 |   8.68 |
#17|  0.00 |  24.23 |  33.07 |  29.57 |  13.13 |
#18|  0.00 |  25.31 |  32.99 |  29.06 |  12.64 |
#19|  0.00 |  24.52 |  32.53 |  31.09 |  11.86 |
#20|  0.00 |  11.63 |  15.84 |  25.52 |  47.01 |
#21|  0.00 |  12.06 |  17.33 |  25.60 |  45.01 |
#22|  0.00 |  12.12 |  15.97 |  25.50 |  46.41 |
#23|  0.00 |  14.94 |   8.64 |  27.63 |  48.79 |
#24|  0.00 |  15.20 |   7.29 |  32.14 |  45.37 |
#25|  0.00 |  14.82 |   7.88 |  33.04 |  44.26 |
#26|  0.00 |  14.99 |   7.91 |  31.94 |  45.16 |
#27|  0.00 |  14.96 |   7.28 |  32.06 |  45.70 |
#28|  0.00 |  15.12 |   7.88 |  32.11 |  44.89 |
#29|  0.00 |  15.48 |   7.40 |  33.17 |  43.95 |
#30|  0.00 |  15.08 |   7.84 |  31.97 |  45.11 |
