diff options
author | zelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573> | 2008-11-26 04:49:33 +0000 |
---|---|---|
committer | zelgadis <zelgadis@c06c8d41-db1a-0410-9941-cceddc491573> | 2008-11-26 04:49:33 +0000 |
commit | 9629076ee9f0b7a88048c0eb6d979c5d86a7a3d2 (patch) | |
tree | cb7381ef2ff5a76c88624a951070e3495b15e5fb /crawl-ref/source | |
parent | 300286dd913491e4869d56078d42bab7c47c40db (diff) | |
download | crawl-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.lua | 2 | ||||
-rw-r--r-- | crawl-ref/source/dat/rooms.des | 19 | ||||
-rw-r--r-- | crawl-ref/source/dungeon.cc | 268 | ||||
-rw-r--r-- | crawl-ref/source/dungeon.h | 11 | ||||
-rw-r--r-- | crawl-ref/source/luadgn.cc | 20 | ||||
-rw-r--r-- | crawl-ref/source/mapdef.cc | 14 | ||||
-rw-r--r-- | crawl-ref/source/mapdef.h | 2 | ||||
-rw-r--r-- | crawl-ref/source/maps.cc | 14 |
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; } } |