to lua. As of now all special rooms are filled with rats.
Introduces two new members to map_def, weight_depth_mult and weight_depth_div, which change a map's weight based on the absolute dungeon depth (not yet accesible via lua or vault definitions). This needs to be done in C++ rather than in lua since a map's lua isn't re-invoked every time a random map is chosen, but only when the map is placed.
NOTE: When I first made this change crawl started crashing until I manually forced the recompilation of util/levcomp.lex.o and util/levcomp.tab.o; if crawl starts crashing after this change, try doing that.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7629 c06c8d41-db1a-0410-9941-cceddc491573
FKRLQJYHK3GB6HHSNNFQ7L57ZAR52LSTBG5B6SNJBYZ2LQ36P67AC
4N5PW5S3OV25HFN634NNWMMYX26NA2TB6TVFG4UMYSZ2VBJWKE4QC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
FQ7XALBL6NZAGBKKYIFHYQ7MUWIHR4TEU4TCS33EG4I3JTND5SQAC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
TLO257LZSB6ZO36STDUEWJBO2LETXFKTFGXELA6Y4BZBVAEIIINAC
W52PCSHX72WAMWKG6L4BPUBVMO6E72KYYBNKAA7554KNOTY6V7WQC
TLA5UN6LZPXGKERI27EFY4HKIIU3VU5Y7ZU54WXL6ANBUV2VOTMQC
AUXHSGS4EFOPZ6TVZYWNVOUDO7NYKUKE3HBKGQQWTALSVFOE3HAAC
RN242L3YZK35BFY7JRTCSYWD6FWDCRFUFDI7PKYFUCA2UPX6ZEAQC
SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC
EJ4GIPFSSQCQASUMRF4CR2WPUQOTEHFRGLOYEZ7BH6YEMIR6DN4QC
77H4BWWPPGLM3PLZH4QTAJRXIZTSDVNCOKZE223I437FN2UJ34RQC
GPEJOT73KMACP33IPAKFR5ROGHCOIP22VXZMQNYTGLEA2OSZUM2AC
KCHX2F3JFEWOZT3WMJVZAAQUU2QSZ5Q7RDCD7WUJ7VE65J52JFUQC
R5JKQLY5QE6UBG3RH3Y5ZRSX6H35CHYI2HYNDZF6ZHVRULUORXBQC
2EUWVLBXTKBIYLS7HVCIL6R7EERHRAIVFAXQPBRKDEMH5BGFEDQQC
B7MSPF6X2RLGWN4M6ZZF3WSOPKGYPTTD7LIJVST7DXN27DG6JHNAC
SIDH2P7NBIG5KEOE27XHD3ZT2NQ2OJZFN6VZXWNWYFFY5YVXSSVQC
45EMD3KLQPMERNMIKU5G76H6556XOMIW352TSBP7VLWJX2YYGS7AC
3UKFCWWS5BLFQWZRB5FUA46CE2XGX5VRCEWC3K3XH5RCGQK64N2AC
7XJLSTDZDOSHW6JF3Y4545YGGK5BC2SOXJVQXXVOFR3I7PXYUJZQC
NVSFIV2ZKP44XHCSCXG6OZVGL67OIFINC34J2EMKTA4KULCERUEAC
E5DMZFW6WCFAKTKKOQPYTQXZ2CGLWMVH64LRXDUI2UIG4VYUHIVQC
P5TRGRH7XMQSPCZKM5IEEO34TY6WMLGHHX7BU6Y453JFRXLUR2VQC
ZGUJWUFJ4NFFJ6PGXLFGQWCWBCZHPWGWI44NJHJEVPRG5L36PADQC
UEI5JAVCMN7Y2SACTEZPZSNFJWOJTC55G24Q6LKQCT4XNDH5ZQIAC
S7T5CO7QMCIK6QSVVB76GNOAQ6QNJOOINGMLFWRC26VK276R3QCAC
5KTPCJG42MF2B34CEH6VXAJIOZR6QOS2BWYNW7DXM3WA7N3GH4HQC
YMKHC3DZYD4GAQRPZHOZ6RPPNX7ZIEMHBZJ4OKF7HJEHO4SQR7LAC
X7MFMKQTNZ2IWBFVGS6WQV7NRNKJ3DWQAW2X7IQMFQQXW24AHPZQC
UBQTNLYGD3SNWMUNGWUPX7EXEGQXOXCFCPWIVWBFE7ID7DJLPFWAC
welcome_messages(), map(), mons(), items(), keyspecs(),
prelude("dlprelude"), main("dlmain"), validate("dlvalidate"),
veto("dlveto"), rock_colour(BLACK), floor_colour(BLACK),
index_only(false), cache_offset(0L)
weight_depth_mult(), weight_depth_div(), welcome_messages(), map(),
mons(), items(), keyspecs(), prelude("dlprelude"), main("dlmain"),
validate("dlvalidate"), veto("dlveto"), rock_colour(BLACK),
floor_colour(BLACK), index_only(false), cache_offset(0L)
}
extern spec_room lua_special_room_spec;
extern int lua_special_room_level;
LUAFN(dgn_get_special_room_info)
{
if (!lua_special_room_spec.created || !in_bounds(lua_special_room_spec.tl)
|| lua_special_room_level == -1)
{
return (0);
}
lua_pushnumber(ls, lua_special_room_level);
dlua_push_coord(ls, lua_special_room_spec.tl);
dlua_push_coord(ls, lua_special_room_spec.br);
return (5);
}
// Fill special room sr with monsters from the pit_list at density%...
// then place a "lord of the pit" of lord_type at (lordx, lordy).
static void _fill_monster_pit( spec_room &sr, FixedVector<pit_mons_def,
MAX_PIT_MONSTERS> &pit_list, int density,
monster_type lord_type, const coord_def& lordpos)
{
int i;
// Make distribution cumulative.
for (i = 1; i < MAX_PIT_MONSTERS; ++i)
{
// assuming that the first zero rarity is the end of the list:
if (!pit_list[i].rare)
break;
pit_list[i].rare = pit_list[i].rare + pit_list[i - 1].rare;
}
const int num_types = i;
const int rare_sum = pit_list[num_types - 1].rare;
// Calculate die_size, factoring in the density% of the pit.
const int die_size = (rare_sum * 100) / density;
#if DEBUG_DIAGNOSTICS
for (i = 0; i < num_types; ++i)
{
const int delta = ((i > 0) ? pit_list[i].rare - pit_list[i - 1].rare
: pit_list[i].rare);
const float perc = (static_cast<float>( delta ) * 100.0)
/ static_cast<float>( rare_sum );
mprf( MSGCH_DIAGNOSTICS, "%6.2f%%: %s", perc,
mons_type_name( pit_list[i].type, DESC_PLAIN).c_str() );
}
#endif
// Put the boss monster down.
if (lord_type != MONS_PROGRAM_BUG)
{
mgen_data mg;
mg.cls = lord_type;
mg.behaviour = BEH_SLEEP;
mg.pos = lordpos;
mons_place(mgen_data::sleeper_at(lord_type, lordpos));
}
// Place monsters and give them items {dlb}:
for ( rectangle_iterator ri(sr.tl, sr.br); ri; ++ri )
{
// Avoid the boss (or anyone else we may have dropped already).
if (mgrd(*ri) != NON_MONSTER)
continue;
const int roll = random2( die_size );
// Density skip (no need to iterate).
if (roll >= rare_sum)
continue;
// Run through the cumulative chances and place a monster.
for (i = 0; i < num_types; ++i)
{
if (roll < pit_list[i].rare)
{
mons_place(
mgen_data::sleeper_at(pit_list[i].type, *ri));
break;
}
}
}
const map_def *vault = random_map_for_tag("special_room", true, true);
ASSERT(vault);
if (!vault)
{
mpr("ERROR: failed to create special room.", MSGCH_ERROR);
return;
}
lua_special_room_spec = sr;
lua_special_room_level = level_number;
_build_minivaults( level_number, vault, false, false, sr.tl);
lua_special_room_spec.created = false;
lua_special_room_spec.tl.set(-1, -1);
lua_special_room_level = -1;
#if 0 // MATT
// Fills a special room with bees.
static void _beehive(spec_room &sr)
{
for ( rectangle_iterator ri(sr.tl, sr.br); ri; ++ri )
{
if (coinflip())
continue;
const int i = get_item_slot();
if (i == NON_ITEM)
continue;
item_def& item(mitm[i]);
item.quantity = 1;
item.base_type = OBJ_FOOD;
item.sub_type = (one_chance_in(25) ? FOOD_ROYAL_JELLY : FOOD_HONEYCOMB);
item.pos = *ri;
item_colour( item );
}
const coord_def queenpos(sr.random_spot());
// Mark all kinds of bees at patrolling to make them return to their hive.
for ( rectangle_iterator ri(sr.tl, sr.br); ri; ++ri )
{
if (*ri == queenpos)
continue;
// The hive is chock full of bees!
mons_place(mgen_data::sleeper_at(
one_chance_in(7) ? MONS_KILLER_BEE_LARVA
: MONS_KILLER_BEE,
*ri, MG_PATROLLING));
}
mons_place(mgen_data::sleeper_at(MONS_QUEEN_BEE, queenpos, MG_PATROLLING));
}
#if 0 // MATT
// Fill special room sr with monsters from the pit_list at density%...
// then place a "lord of the pit" of lord_type at (lordx, lordy).
static void _fill_monster_pit( spec_room &sr, FixedVector<pit_mons_def,
MAX_PIT_MONSTERS> &pit_list, int density,
monster_type lord_type, const coord_def& lordpos)
{
int i;
// Make distribution cumulative.
for (i = 1; i < MAX_PIT_MONSTERS; ++i)
{
// assuming that the first zero rarity is the end of the list:
if (!pit_list[i].rare)
break;
pit_list[i].rare = pit_list[i].rare + pit_list[i - 1].rare;
}
const int num_types = i;
const int rare_sum = pit_list[num_types - 1].rare;
// Calculate die_size, factoring in the density% of the pit.
const int die_size = (rare_sum * 100) / density;
#if DEBUG_DIAGNOSTICS
for (i = 0; i < num_types; ++i)
{
const int delta = ((i > 0) ? pit_list[i].rare - pit_list[i - 1].rare
: pit_list[i].rare);
const float perc = (static_cast<float>( delta ) * 100.0)
/ static_cast<float>( rare_sum );
mprf( MSGCH_DIAGNOSTICS, "%6.2f%%: %s", perc,
mons_type_name( pit_list[i].type, DESC_PLAIN).c_str() );
}
#endif
// Put the boss monster down.
if (lord_type != MONS_PROGRAM_BUG)
{
mgen_data mg;
mg.cls = lord_type;
mg.behaviour = BEH_SLEEP;
mg.pos = lordpos;
mons_place(mgen_data::sleeper_at(lord_type, lordpos));
}
// Place monsters and give them items {dlb}:
for ( rectangle_iterator ri(sr.tl, sr.br); ri; ++ri )
{
// Avoid the boss (or anyone else we may have dropped already).
if (mgrd(*ri) != NON_MONSTER)
continue;
const int roll = random2( die_size );
// Density skip (no need to iterate).
if (roll >= rare_sum)
continue;
// Run through the cumulative chances and place a monster.
for (i = 0; i < num_types; ++i)
{
if (roll < pit_list[i].rare)
{
mons_place(
mgen_data::sleeper_at(pit_list[i].type, *ri));
break;
}
}
}
}
// Fills a special room with bees.
static void _beehive(spec_room &sr)
{
for ( rectangle_iterator ri(sr.tl, sr.br); ri; ++ri )
{
if (coinflip())
continue;
const int i = get_item_slot();
if (i == NON_ITEM)
continue;
item_def& item(mitm[i]);
item.quantity = 1;
item.base_type = OBJ_FOOD;
item.sub_type = (one_chance_in(25) ? FOOD_ROYAL_JELLY : FOOD_HONEYCOMB);
item.pos = *ri;
item_colour( item );
}
const coord_def queenpos(sr.random_spot());
// Mark all kinds of bees at patrolling to make them return to their hive.
for ( rectangle_iterator ri(sr.tl, sr.br); ri; ++ri )
{
if (*ri == queenpos)
continue;
// The hive is chock full of bees!
mons_place(mgen_data::sleeper_at(
one_chance_in(7) ? MONS_KILLER_BEE_LARVA
: MONS_KILLER_BEE,
*ri, MG_PATROLLING));
}
mons_place(mgen_data::sleeper_at(MONS_QUEEN_BEE, queenpos, MG_PATROLLING));
}
#endif
NAME: special_room_test
TAGS: special_room allow_dup
{{
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
for x = tl_x, br_x do
for y = tl_y, br_y do
dgn.create_monster(x, y, "rat")
end
end
}}
MAP
ENDMAP