summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/dungeon.cc
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-07-21 12:17:29 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-07-21 12:17:29 +0000
commit9843737e73a47ef6f1da0554b7ca73018d52d345 (patch)
tree9381ef8b914bc801386f62ce2713c59c17b6a9e8 /crawl-ref/source/dungeon.cc
parentb27a757b68bf8a1dcbcb9b3a5cfea5c1278c9bb4 (diff)
downloadcrawl-ref-9843737e73a47ef6f1da0554b7ca73018d52d345.tar.gz
crawl-ref-9843737e73a47ef6f1da0554b7ca73018d52d345.zip
Updated level-design.txt.
Moved map markers to mapmark.cc. Added support for timer markers that remove a feature after a certain timeout. Need to hook up messaging to Lua. Added bazaars (need more bazaar layouts). git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1899 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/dungeon.cc')
-rw-r--r--crawl-ref/source/dungeon.cc255
1 files changed, 131 insertions, 124 deletions
diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc
index 311ea74805..176fa6f714 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -45,6 +45,7 @@
#include "items.h"
#include "makeitem.h"
#include "mapdef.h"
+#include "mapmark.h"
#include "maps.h"
#include "misc.h"
#include "mon-util.h"
@@ -116,10 +117,13 @@ static void builder_items(int level_number, char level_type, int items_wanted);
static void builder_monsters(int level_number, char level_type, int mon_wanted);
static void place_specific_stair(dungeon_feature_type stair,
const std::string &tag = "",
- int dl = 0);
+ int dl = 0,
+ bool vault_only = false);
static void place_branch_entrances(int dlevel, char level_type);
static void place_extra_vaults();
-static void place_minivaults(int level_number, int level_type);
+static void place_minivaults(const std::string &tag = "",
+ int fewest = -1, int most = -1,
+ bool force = false);
static void place_traps( int level_number );
static void prepare_swamp();
static void prepare_shoals( int level_number );
@@ -147,7 +151,7 @@ static void build_lake(dungeon_feature_type lake_type); //mv
static void spotty_level(bool seeded, int iterations, bool boxy);
static void bigger_room();
-static void plan_main(int level_number, char force_plan);
+static void plan_main(int level_number, int force_plan);
static char plan_1();
static char plan_2();
static char plan_3();
@@ -157,6 +161,7 @@ static char plan_5();
static char plan_6(int level_number);
static bool octa_room(spec_room &sr, int oblique_max,
dungeon_feature_type type_floor);
+static void bazaar_level(int level_number);
static void labyrinth_level(int level_number);
static void box_room(int bx1, int bx2, int by1, int by2,
dungeon_feature_type wall_type);
@@ -169,7 +174,7 @@ static void pick_float_exits(vault_placement &place,
static void connect_vault(const vault_placement &vp);
// ITEM & SHOP FUNCTIONS
-static void place_shops(int level_number);
+static void place_shops(int level_number, int nshops = 0);
static object_class_type item_in_shop(unsigned char shop_type);
static bool treasure_area(int level_number, unsigned char ta1_x,
unsigned char ta2_x, unsigned char ta1_y,
@@ -296,7 +301,7 @@ static inline bool dgn_grid_is_passable(dungeon_feature_type grid)
static inline bool dgn_square_is_passable(const coord_def &c)
{
- return (dgn_map_mask(c) && dgn_grid_is_passable(grd(c)));
+ return ((dgn_map_mask(c) & MMT_OPAQUE) && dgn_grid_is_passable(grd(c)));
}
static inline void dgn_point_record_stub(const coord_def &) { }
@@ -363,10 +368,8 @@ static int dgn_count_disconnected_zones()
{
for (int x = 0; x < GXM; ++x)
{
- if (travel_point_distance[x][y] || dgn_map_mask[x][y])
- continue;
-
- if (!dgn_grid_is_passable(grd[x][y]))
+ if (travel_point_distance[x][y]
+ || !dgn_square_is_passable(coord_def(x, y)))
continue;
dgn_fill_zone(coord_def(x, y), ++nzones, dgn_point_record_stub);
@@ -421,6 +424,9 @@ static void register_place(const vault_placement &place)
if (place.map.has_tag("no_pool_fixup"))
mask_vault(place, MMT_NO_POOL);
+
+ if (!place.map.has_tag("transparent"))
+ mask_vault(place, MMT_OPAQUE);
}
static bool ensure_vault_placed(bool vault_success)
@@ -510,11 +516,11 @@ static void reset_level()
}
// reset all shops
- for (unsigned char shcount = 0; shcount < 5; shcount++)
+ for (int shcount = 0; shcount < MAX_SHOPS; shcount++)
env.shop[shcount].type = SHOP_UNASSIGNED;
// clear all markers
- env.clear_markers();
+ env_clear_markers();
}
static void build_layout_skeleton(int level_number, int level_type,
@@ -628,7 +634,7 @@ static void fixup_branch_stairs()
&& grd[x][y] <= DNGN_ROCK_STAIRS_UP)
{
if (grd[x][y] == DNGN_STONE_STAIRS_UP_I)
- env.add_marker(
+ env_add_marker(
new map_feature_marker(coord_def(x,y),
grd[x][y]));
grd[x][y] = exit;
@@ -699,7 +705,8 @@ static void build_dungeon_level(int level_number, int level_type)
build_layout_skeleton(level_number, level_type, sr);
- if (you.level_type == LEVEL_LABYRINTH || dgn_level_vetoed)
+ if (you.level_type == LEVEL_LABYRINTH || you.level_type == LEVEL_BAZAAR
+ || dgn_level_vetoed)
return;
// hook up the special room (if there is one, and it hasn't
@@ -737,7 +744,7 @@ static void build_dungeon_level(int level_number, int level_type)
// Try to place minivaults that really badly want to be placed. Still
// no guarantees, seeing this is a minivault.
if (!player_in_branch(BRANCH_SHOALS))
- place_minivaults(level_number, level_type);
+ place_minivaults();
place_branch_entrances( level_number, level_type );
place_extra_vaults();
dgn_verify_connectivity(nvaults);
@@ -1242,16 +1249,22 @@ static bool make_box(int room_x1, int room_y1, int room_x2, int room_y2,
// -1 if we should immediately quit, and 0 otherwise.
static builder_rc_type builder_by_type(int level_number, char level_type)
{
+ if (level_type == LEVEL_BAZAAR)
+ {
+ bazaar_level(level_number);
+ return (BUILD_QUIT);
+ }
+
if (level_type == LEVEL_LABYRINTH)
{
labyrinth_level(level_number);
- return BUILD_QUIT;
+ return (BUILD_QUIT);
}
if (level_type == LEVEL_ABYSS)
{
generate_abyss();
- return BUILD_SKIP;
+ return (BUILD_SKIP);
}
if (level_type == LEVEL_PANDEMONIUM)
@@ -1311,6 +1324,50 @@ static builder_rc_type builder_by_type(int level_number, char level_type)
return BUILD_CONTINUE;
}
+static void fixup_bazaar_stairs()
+{
+ for (int y = 0; y < GYM; ++y)
+ {
+ for (int x = 0; x < GXM; ++x)
+ {
+ const dungeon_feature_type feat = grd[x][y];
+ if (grid_is_stone_stair(feat) || grid_is_rock_stair(feat))
+ {
+ if (grid_stair_direction(feat) == CMD_GO_DOWNSTAIRS)
+ grd[x][y] = DNGN_EXIT_BAZAAR;
+ else
+ grd[x][y] = DNGN_STONE_ARCH;
+ }
+ }
+ }
+}
+
+static void bazaar_level(int level_number)
+{
+ int vault = random_map_for_place(level_id::current(), false);
+ if (vault == -1)
+ vault = random_map_for_tag("bazaar", false);
+
+ if (vault != -1)
+ {
+ ensure_vault_placed( build_vaults(level_number, vault) );
+ link_items();
+ fixup_bazaar_stairs();
+ return;
+ }
+
+ // No primary Bazaar vaults (ugh).
+ plan_main(level_number, 0);
+ place_minivaults("bazaar", 1, 1, true);
+
+ // No vaults placed yet? Place some shops of our own.
+ if (level_vaults.empty())
+ place_shops(level_number, random_range(5, MAX_SHOPS));
+
+ link_items();
+ fixup_bazaar_stairs();
+}
+
static int random_portal_vault(const std::string &tag)
{
return random_map_for_tag(tag, false, true);
@@ -1371,11 +1428,28 @@ static builder_rc_type builder_by_branch(int level_number)
return BUILD_CONTINUE;
}
-static void place_minivaults(int level_number, int level_type)
+static void place_minivaults(const std::string &tag, int lo, int hi, bool force)
{
+ const level_id curr = level_id::current();
// Dungeon-style branches only, thankyouverymuch.
- if (level_type != LEVEL_DUNGEON)
+ if (curr.level_type != LEVEL_DUNGEON && !force)
+ return;
+
+ if (lo == -1)
+ lo = hi = 1;
+
+ int nvaults = random_range(lo, hi);
+ if (!tag.empty())
+ {
+ for (int i = 0; i < nvaults; ++i)
+ {
+ const int vault = random_map_for_tag(tag, true);
+ if (vault == -1)
+ return;
+ build_minivaults(you.your_level, vault);
+ }
return;
+ }
std::set<int> used;
if (use_random_maps && minivault_chance && one_chance_in(minivault_chance))
@@ -1383,13 +1457,13 @@ static void place_minivaults(int level_number, int level_type)
const int vault = random_map_in_depth(level_id::current(), true);
if (vault != -1)
{
- build_minivaults(level_number, vault);
+ build_minivaults(you.your_level, vault);
used.insert(vault);
}
}
- int chance = level_number == 0? 50 : 100;
- while (chance && random2(100) < chance)
+ int chance = you.your_level == 0? 50 : 100;
+ while ((chance && random2(100) < chance) || nvaults-- > 0)
{
const int vault = dgn_random_map_for_place(true);
if (vault == -1)
@@ -1403,7 +1477,7 @@ static void place_minivaults(int level_number, int level_type)
break;
}
- build_minivaults(level_number, vault);
+ build_minivaults(you.your_level, vault);
used.insert(vault);
chance /= 4;
}
@@ -1616,8 +1690,13 @@ static void builder_extras( int level_number, int level_type )
{
UNUSED( level_type );
- if (level_number >= 11 && level_number <= 23 && one_chance_in(15))
- place_specific_stair(DNGN_ENTER_LABYRINTH);
+ if (one_chance_in(15))
+ place_specific_stair(DNGN_ENTER_LABYRINTH, "lab_entry",
+ level_number, true);
+
+ if (one_chance_in(20))
+ place_specific_stair(DNGN_ENTER_BAZAAR, "bzr_entry",
+ level_number, true);
if (level_number > 6 && one_chance_in(10))
{
@@ -1747,10 +1826,14 @@ static void place_specific_feature(dungeon_feature_type feat)
static void place_specific_stair(dungeon_feature_type stair,
const std::string &tag,
- int dlevel)
+ int dlevel,
+ bool vault_only)
{
- if (tag.empty() || !place_portal_vault(stair, tag, dlevel))
+ if ((tag.empty() || !place_portal_vault(stair, tag, dlevel))
+ && !vault_only)
+ {
place_specific_feature(stair);
+ }
}
static void place_extra_vaults()
@@ -3178,7 +3261,12 @@ static void pick_float_exits(vault_placement &place,
pick_internal_float_exits(place, possible_exits);
if (possible_exits.empty())
+ {
+#ifdef DEBUG_DIAGNOSTICS
+ mprf(MSGCH_WARN, "Unable to find exit from %s", place.map.name.c_str());
+#endif
return;
+ }
const int npoints = possible_exits.size();
int nexits = npoints < 6? npoints : npoints / 8 + 1;
@@ -4295,29 +4383,31 @@ static void place_altar()
}
} // end place_altar()
-static void place_shops(int level_number)
+static void place_shops(int level_number, int nshops)
{
int temp_rand = 0; // probability determination {dlb}
int timeout = 0;
- unsigned char no_shops = 0;
unsigned char shop_place_x = 0;
unsigned char shop_place_y = 0;
temp_rand = random2(125);
+ if (!nshops)
+ {
#if DEBUG_SHOPS
- no_shops = MAX_SHOPS;
+ nshops = MAX_SHOPS;
#else
- no_shops = ((temp_rand > 28) ? 0 : // 76.8%
- (temp_rand > 4) ? 1 // 19.2%
- : 1 + random2( MAX_SHOPS )); // 4.0%
+ nshops = ((temp_rand > 28) ? 0 : // 76.8%
+ (temp_rand > 4) ? 1 // 19.2%
+ : random_range(1, MAX_RANDOM_SHOPS)); // 4.0%
- if (no_shops == 0 || level_number < 3)
- return;
+ if (nshops == 0 || level_number < 3)
+ return;
#endif
+ }
- for (int i = 0; i < no_shops; i++)
+ for (int i = 0; i < nshops; i++)
{
timeout = 0;
@@ -4624,14 +4714,14 @@ static void bigger_room()
} // end bigger_room()
// various plan_xxx functions
-static void plan_main(int level_number, char force_plan)
+static void plan_main(int level_number, int force_plan)
{
// possible values for do_stairs:
// 0 - stairs already done
// 1 - stairs already done, do spotty
// 2 - no stairs
// 3 - no stairs, do spotty
- char do_stairs = 0;
+ int do_stairs = 0;
dungeon_feature_type special_grid = (one_chance_in(3) ? DNGN_METAL_WALL
: DNGN_STONE_WALL);
int i,j;
@@ -4999,11 +5089,11 @@ static char plan_6(int level_number)
// Note, that although "level_number > 20" will work for most
// trips to pandemonium (through regular portals), it won't work
// for demonspawn who gate themselves there. -- bwr
- if (((player_in_branch( BRANCH_MAIN_DUNGEON ) && level_number > 20)
- || you.level_type == LEVEL_PANDEMONIUM)
+ if (((player_in_branch( BRANCH_MAIN_DUNGEON ) && level_number > 20)
+ || you.level_type == LEVEL_PANDEMONIUM)
&& (coinflip() || you.mutation[ MUT_PANDEMONIUM ]))
{
- grd[40][36] = DNGN_ENTER_ABYSS;
+ grd[40][36] = DNGN_ENTER_ABYSS;
grd[41][36] = DNGN_ENTER_ABYSS;
}
@@ -6520,7 +6610,7 @@ coord_def dgn_find_nearby_stair(int stair_to_find, bool find_closest)
if (grd[xpos][ypos] == stair_to_find
&& (!branch_exit
- || env.find_marker(coord_def(xpos, ypos),
+ || env_find_marker(coord_def(xpos, ypos),
MAT_FEATURE)))
{
found++;
@@ -6680,86 +6770,3 @@ coord_def dgn_region::random_point() const
{
return coord_def( pos.x + random2(size.x), pos.y + random2(size.y) );
}
-
-////////////////////////////////////////////////////////////////////////
-// Dungeon markers
-
-map_marker::marker_reader
-map_marker::readers[NUM_MAP_MARKER_TYPES] =
-{
- &map_feature_marker::read,
-};
-
-map_marker::map_marker(map_marker_type t, const coord_def &p)
- : pos(p), type(t)
-{
-}
-
-map_marker::~map_marker()
-{
-}
-
-void map_marker::write(tagHeader &outf) const
-{
- marshallShort(outf, type);
- marshallCoord(outf, pos);
-}
-
-void map_marker::read(tagHeader &inf)
-{
- // Don't read type! The type has to be read by someone who knows how
- // to look up the unmarshall function.
- unmarshallCoord(inf, pos);
-}
-
-map_marker *map_marker::read_marker(tagHeader &inf)
-{
- const map_marker_type type =
- static_cast<map_marker_type>(unmarshallShort(inf));
- return readers[type]? (*readers[type])(inf, type) : NULL;
-}
-
-////////////////////////////////////////////////////////////////////////////
-// map_feature_marker
-
-map_feature_marker::map_feature_marker(
- const coord_def &p,
- dungeon_feature_type _feat)
- : map_marker(MAT_FEATURE, p), feat(_feat)
-{
-}
-
-map_feature_marker::map_feature_marker(
- const map_feature_marker &other)
- : map_marker(MAT_FEATURE, other.pos), feat(other.feat)
-{
-}
-
-void map_feature_marker::write(tagHeader &outf) const
-{
- this->map_marker::write(outf);
- marshallShort(outf, feat);
-}
-
-void map_feature_marker::read(tagHeader &inf)
-{
- map_marker::read(inf);
- feat = static_cast<dungeon_feature_type>(unmarshallShort(inf));
-}
-
-map_marker *map_feature_marker::read(tagHeader &inf, map_marker_type)
-{
- map_marker *mapf = new map_feature_marker();
- mapf->read(inf);
- return (mapf);
-}
-
-map_marker *map_feature_marker::clone() const
-{
- return new map_feature_marker(pos, feat);
-}
-
-std::string map_feature_marker::describe() const
-{
- return make_stringf("feature (%s)", dungeon_feature_name(feat));
-}