summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authorzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2008-11-26 04:49:33 +0000
committerzelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573>2008-11-26 04:49:33 +0000
commit9629076ee9f0b7a88048c0eb6d979c5d86a7a3d2 (patch)
treecb7381ef2ff5a76c88624a951070e3495b15e5fb /crawl-ref/source
parent300286dd913491e4869d56078d42bab7c47c40db (diff)
downloadcrawl-ref-9629076ee9f0b7a88048c0eb6d979c5d86a7a3d2.tar.gz
crawl-ref-9629076ee9f0b7a88048c0eb6d979c5d86a7a3d2.zip
Start of moving special room definitions (monster lairs and monster pits)
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
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/dat/clua/loadmaps.lua2
-rw-r--r--crawl-ref/source/dat/rooms.des19
-rw-r--r--crawl-ref/source/dungeon.cc268
-rw-r--r--crawl-ref/source/dungeon.h11
-rw-r--r--crawl-ref/source/luadgn.cc20
-rw-r--r--crawl-ref/source/mapdef.cc14
-rw-r--r--crawl-ref/source/mapdef.h2
-rw-r--r--crawl-ref/source/maps.cc14
8 files changed, 208 insertions, 142 deletions
diff --git a/crawl-ref/source/dat/clua/loadmaps.lua b/crawl-ref/source/dat/clua/loadmaps.lua
index 867c78fe0d..881f0dd8f2 100644
--- a/crawl-ref/source/dat/clua/loadmaps.lua
+++ b/crawl-ref/source/dat/clua/loadmaps.lua
@@ -13,7 +13,7 @@ local des_files = {
"altar.des", "bazaar.des", "entry.des", "elf.des", "float.des", "hells.des",
"hive.des", "icecave.des", "lab.des", "lair.des", "large.des", "layout.des",
"mini.des", "orc.des", "pan.des", "sewer.des", "temple.des", "vaults.des",
- "crypt.des", "ziggurat.des", "zot.des"
+ "crypt.des", "ziggurat.des", "zot.des", "rooms.des"
}
for _, file in ipairs(des_files) do
diff --git a/crawl-ref/source/dat/rooms.des b/crawl-ref/source/dat/rooms.des
new file mode 100644
index 0000000000..960426f671
--- /dev/null
+++ b/crawl-ref/source/dat/rooms.des
@@ -0,0 +1,19 @@
+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
diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc
index a10f46b80b..5255a053fe 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -58,13 +58,8 @@
#include "cio.h" // for cancelable_get_line()
#endif
-#define MAX_PIT_MONSTERS 10
-
-struct pit_mons_def
-{
- monster_type type;
- int rare;
-};
+spec_room lua_special_room_spec;
+int lua_special_room_level;
struct dist_feat
{
@@ -189,9 +184,6 @@ static void _chequerboard(spec_room &sr, dungeon_feature_type target,
dungeon_feature_type floor1,
dungeon_feature_type floor2);
static void _roguey_level(int level_number, spec_room &sr, bool make_stairs);
-static void _morgue(spec_room &sr);
-static void _beehive(spec_room &sr);
-static void _jelly_pit(int level_number, spec_room &sr);
// VAULT FUNCTIONS
static bool _build_secondary_vault(int level_number, const map_def *vault,
@@ -925,6 +917,10 @@ static void _reset_level()
env.floor_colour = BLACK;
env.rock_colour = BLACK;
+
+ lua_special_room_spec.created = false;
+ lua_special_room_spec.tl.set(-1, -1);
+ lua_special_room_level = -1;
}
static void _build_layout_skeleton(int level_number, int level_type,
@@ -3524,83 +3520,9 @@ static void _specr_2(spec_room &sr)
sr.hooked_up = true;
}
-// 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;
- }
- }
- }
-}
-
static void _special_room(int level_number, spec_room &sr)
{
+#if 0 // MATT
char spec_room_type = SROOM_LAIR_KOBOLD;
int lev_mons;
int thing_created = 0;
@@ -3611,6 +3533,7 @@ static void _special_room(int level_number, spec_room &sr)
FixedVector < monster_type, 10 > mons_alloc; // was [20] {dlb}
coord_def lordpos;
+#endif
// Overwrites anything: this function better be called early on during
// creation.
@@ -3629,6 +3552,25 @@ static void _special_room(int level_number, spec_room &sr)
sr.tl.set(room_x1 + 1, room_y1 + 1);
sr.br.set(room_x2 - 1, room_y2 - 1);
+ 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
if (level_number < 7)
spec_room_type = SROOM_LAIR_KOBOLD;
else
@@ -3774,47 +3716,9 @@ static void _special_room(int level_number, spec_room &sr)
_jelly_pit(level_number, sr);
break;
}
+#endif
} // end special_room()
-// 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));
-}
-
// Used for placement of vaults.
static bool _may_overwrite_feature(const dungeon_feature_type grid,
bool water_ok, bool rock_ok = true)
@@ -7462,6 +7366,82 @@ static void _roguey_level(int level_number, spec_room &sr, bool make_stairs)
}
} // end roguey_level()
+#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;
+ }
+ }
+ }
+}
+
static void _morgue(spec_room &sr)
{
for (rectangle_iterator ri(sr.tl, sr.br); ri; ++ri)
@@ -7523,6 +7503,46 @@ static void _jelly_pit(int level_number, spec_room &sr)
_fill_monster_pit( sr, pit_list, 90, MONS_PROGRAM_BUG, lordpos );
}
+// 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
+
bool place_specific_trap(const coord_def& where, trap_type spec_type)
{
if (spec_type == TRAP_RANDOM || spec_type == TRAP_NONTELEPORT)
diff --git a/crawl-ref/source/dungeon.h b/crawl-ref/source/dungeon.h
index e0b2c9b31b..bcfa1d6d16 100644
--- a/crawl-ref/source/dungeon.h
+++ b/crawl-ref/source/dungeon.h
@@ -32,17 +32,6 @@ enum portal_type
NUM_PORTALS
};
-enum special_room_type
-{
- SROOM_LAIR_ORC, // 0
- SROOM_LAIR_KOBOLD,
- SROOM_TREASURY,
- SROOM_BEEHIVE,
- SROOM_JELLY_PIT,
- SROOM_MORGUE,
- NUM_SPECIAL_ROOMS // 5 - must remain final member {dlb}
-};
-
const int MAKE_GOOD_ITEM = 351;
// Should be the larger of GXM/GYM
diff --git a/crawl-ref/source/luadgn.cc b/crawl-ref/source/luadgn.cc
index 3fd5b55e86..d75ea8f2fd 100644
--- a/crawl-ref/source/luadgn.cc
+++ b/crawl-ref/source/luadgn.cc
@@ -2464,6 +2464,24 @@ LUAFN(_dgn_in_vault)
return (1);
}
+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);
+}
+
LUAFN(_dgn_resolve_map)
{
if (lua_isnil(ls, 1))
@@ -2660,6 +2678,8 @@ static const struct luaL_reg dgn_lib[] =
{ "resolve_map", _dgn_resolve_map },
{ "in_vault", _dgn_in_vault },
+ { "get_special_room_info", dgn_get_special_room_info },
+
{ "debug_dump_map", dgn_debug_dump_map },
{ NULL, NULL }
diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc
index 57302d789f..9954147c62 100644
--- a/crawl-ref/source/mapdef.cc
+++ b/crawl-ref/source/mapdef.cc
@@ -1184,10 +1184,10 @@ dlua_set_map::~dlua_set_map()
map_def::map_def()
: name(), tags(), place(), depths(), orient(), chance(), weight(),
- 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)
{
init();
}
@@ -1239,6 +1239,12 @@ void map_def::reinit()
// eligible vaults).
weight = 10;
+ // How to modify weight based on absolte dungeon depth. This
+ // needs to be done in the C++ code since the map's lua code doesnt'
+ // get called again each time the depth changes.
+ weight_depth_mult = 0;
+ weight_depth_div = 1;
+
// Clearing the map also zaps map transforms.
map.clear();
mons.clear();
diff --git a/crawl-ref/source/mapdef.h b/crawl-ref/source/mapdef.h
index 36238a2ba0..44d067fe8e 100644
--- a/crawl-ref/source/mapdef.h
+++ b/crawl-ref/source/mapdef.h
@@ -629,6 +629,8 @@ public:
int chance_priority;
int chance;
int weight;
+ int weight_depth_mult;
+ int weight_depth_div;
std::vector<std::string> welcome_messages;
diff --git a/crawl-ref/source/maps.cc b/crawl-ref/source/maps.cc
index 1549039ee0..37dab0e197 100644
--- a/crawl-ref/source/maps.cc
+++ b/crawl-ref/source/maps.cc
@@ -556,13 +556,23 @@ static const map_def *_random_map_in_list(const map_selector &sel,
if (mapindex == -1)
{
+ int absdepth = 0;
+ if (sel.place.level_type == LEVEL_DUNGEON && sel.place.is_valid())
+ absdepth = sel.place.absdepth();
+
for (vault_indices::const_iterator i = eligible.begin();
i != eligible.end(); ++i)
{
const map_def &map(vdefs[*i]);
- rollsize += map.weight;
+ const int weight = map.weight
+ + absdepth * map.weight_depth_mult / map.weight_depth_div;
+
+ if (weight <= 0)
+ continue;
+
+ rollsize += weight;
- if (rollsize && x_chance_in_y(map.weight, rollsize))
+ if (rollsize && x_chance_in_y(weight, rollsize))
mapindex = *i;
}
}