summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/dungeon.cc
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-07-28 08:42:47 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-07-28 08:42:47 +0000
commit5549c15ba74e62433508e9bbaa23d117610f81e2 (patch)
tree8f462e0f7b7f516629af0b773fc5a7a176060f4e /crawl-ref/source/dungeon.cc
parent9b909453a2e070df3ac33277d0a7f07deb6e9132 (diff)
downloadcrawl-ref-5549c15ba74e62433508e9bbaa23d117610f81e2.tar.gz
crawl-ref-5549c15ba74e62433508e9bbaa23d117610f81e2.zip
Added wizmode &L command to place a map on the current level by name. This
only really works for non-encompass vaults, and dungeon fixups are not applied (so random deep water -> shallow water conversion, auto-placement of water creatures, etc. will not happen). git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1942 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/dungeon.cc')
-rw-r--r--crawl-ref/source/dungeon.cc190
1 files changed, 155 insertions, 35 deletions
diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc
index 1738b6483f..6a77697fef 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -59,6 +59,7 @@
#include "stuff.h"
#include "tags.h"
#include "travel.h"
+#include "view.h"
#define MAX_PIT_MONSTERS 10
@@ -193,11 +194,16 @@ 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, int vault, int rune_subst = -1);
+static bool build_secondary_vault(int level_number, int vault,
+ int rune_subst = -1,
+ bool generating_level = true,
+ bool clobber = false);
static bool build_vaults(int level_number, int vault_number,
int rune_subst = -1, bool build_only = false,
- bool check_vault_place = false);
+ bool check_vault_place = false,
+ bool generating_level = true, bool clobber = false);
static bool build_minivaults(int level_number, int force_vault,
+ bool level_builder = true, bool clobber = false,
coord_def where = coord_def() );
static int vault_grid( vault_placement &,
int level_number, int vx, int vy, int altar_count,
@@ -221,7 +227,6 @@ typedef std::list<coord_def> coord_list;
map_mask dgn_map_mask;
std::vector<vault_placement> level_vaults;
-static dgn_region_list vault_zones;
static int vault_chance = 9;
static int minivault_chance = 3;
static bool dgn_level_vetoed = false;
@@ -289,6 +294,12 @@ void level_welcome_messages()
}
}
+void level_clear_vault_memory()
+{
+ level_vaults.clear();
+ dgn_map_mask.init(0);
+}
+
static void dgn_register_vault(const map_def &map)
{
if (map.has_tag("uniq"))
@@ -494,9 +505,7 @@ static bool valid_dungeon_level(int level_number, int level_type)
static void reset_level()
{
- dgn_map_mask.init(0);
- level_vaults.clear();
- vault_zones.clear();
+ level_clear_vault_memory();
vault_chance = 9;
minivault_chance = 3;
use_random_maps = true;
@@ -1090,7 +1099,7 @@ static void prepare_shoals(int level_number)
} while ( vaultidx == -1 ||
!map_by_index(vaultidx)->has_tag("has_rune") );
- build_minivaults( level_number, vaultidx,
+ build_minivaults( level_number, vaultidx, true, false,
centres[1] - coord_def(3,3) );
for ( int i = 2; i < num_islands; ++i )
@@ -1100,7 +1109,7 @@ static void prepare_shoals(int level_number)
vaultidx = dgn_random_map_for_place(true);
} while ( vaultidx == -1 ||
map_by_index(vaultidx)->has_tag("has_rune") );
- build_minivaults( level_number, vaultidx,
+ build_minivaults( level_number, vaultidx, true, false,
centres[i] - coord_def(3,3) );
}
}
@@ -2868,7 +2877,8 @@ static void beehive(spec_room &sr)
} // end beehive()
static bool safe_minivault_place(int v1x, int v1y,
- const vault_placement &place)
+ const vault_placement &place,
+ bool clobber)
{
const bool water_ok = place.map.has_tag("water_ok");
const std::vector<std::string> &lines = place.map.map.get_lines();
@@ -2881,16 +2891,22 @@ static bool safe_minivault_place(int v1x, int v1y,
if (dgn_map_mask[vx][vy])
return (false);
+
+ const dungeon_feature_type dfeat = grd[vx][vy];
- if ((grd[vx][vy] != DNGN_FLOOR
- && grd[vx][vy] != DNGN_ROCK_WALL
- && grd[vx][vy] != DNGN_CLOSED_DOOR
- && grd[vx][vy] != DNGN_SECRET_DOOR
- && (!water_ok ||
- (grd[vx][vy] != DNGN_DEEP_WATER
- && grd[vx][vy] != DNGN_SHALLOW_WATER)))
- || igrd[vx][vy] != NON_ITEM
- || mgrd[vx][vy] != NON_MONSTER)
+ if ((dfeat != DNGN_FLOOR
+ && dfeat != DNGN_ROCK_WALL
+ && dfeat != DNGN_CLOSED_DOOR
+ && dfeat != DNGN_SECRET_DOOR
+ && (!water_ok
+ || (dfeat != DNGN_DEEP_WATER
+ && dfeat != DNGN_SHALLOW_WATER))
+ && (!clobber
+ || (!grid_is_solid(dfeat) && dfeat != DNGN_LAVA
+ && !grid_is_watery(dfeat))))
+ || (!clobber
+ && (igrd[vx][vy] != NON_ITEM
+ || mgrd[vx][vy] != NON_MONSTER)))
{
return (false);
}
@@ -2925,7 +2941,7 @@ static bool connected_minivault_place(int v1x, int v1y,
}
static bool find_minivault_place(const vault_placement &place,
- int &v1x, int &v1y)
+ int &v1x, int &v1y, bool clobber)
{
// [ds] The margin around the edges of the map where the minivault
// won't be placed. Purely arbitrary as far as I can see.
@@ -2937,7 +2953,7 @@ static bool find_minivault_place(const vault_placement &place,
v1x = random_range( margin, GXM - margin - place.width );
v1y = random_range( margin, GYM - margin - place.height );
- if (!safe_minivault_place( v1x, v1y, place ))
+ if (!safe_minivault_place( v1x, v1y, place, clobber ))
continue;
if (connected_minivault_place(v1x, v1y, place))
@@ -2947,6 +2963,7 @@ static bool find_minivault_place(const vault_placement &place,
}
static bool build_minivaults(int level_number, int force_vault,
+ bool building_level, bool clobber,
coord_def where)
{
// for some weird reason can't put a vault on level 1, because monster equip
@@ -2978,17 +2995,13 @@ static bool build_minivaults(int level_number, int force_vault,
v1x = where.x;
v1y = where.y;
}
- else if (!find_minivault_place(place, v1x, v1y))
+ else if (!find_minivault_place(place, v1x, v1y, clobber))
return (false);
place.x = v1x;
place.y = v1y;
- place.map.map.apply_markers(coord_def(v1x, v1y));
-
level_vaults.push_back(place);
- vault_zones.push_back(
- dgn_region(place.x, place.y, place.width, place.height));
#ifdef DEBUG_DIAGNOSTICS
if (crawl_state.map_stat_gen)
@@ -3010,14 +3023,25 @@ static bool build_minivaults(int level_number, int force_vault,
const int feat = vgrid[vy - v1y][vx - v1x];
if (feat == ' ')
continue;
+ const dungeon_feature_type oldgrid = grd[vx][vy];
altar_count = vault_grid( place,
level_number, vx, vy, altar_count,
acq_item_class,
feat, target_connections,
num_runes );
+ if (!building_level)
+ {
+ link_items();
+ const dungeon_feature_type newgrid = grd[vx][vy];
+ grd[vx][vy] = oldgrid;
+ dungeon_terrain_changed(coord_def(vx, vy), newgrid);
+ env_remove_markers_at(coord_def(vx, vy), MAT_ANY);
+ }
}
}
+ place.map.map.apply_markers(coord_def(v1x, v1y));
+
if (target_connections.empty() && place.map.has_tag("mini_float"))
pick_float_exits(place, target_connections);
@@ -3351,13 +3375,97 @@ static void connect_vault(const vault_placement &vp)
}
}
+static dungeon_feature_type dgn_find_rune_subst(const std::string &tag)
+{
+ const std::string suffix("_entry");
+ const std::string::size_type psuffix = tag.find(suffix);
+ if (psuffix == std::string::npos)
+ return (DNGN_FLOOR);
+ const std::string key = tag.substr(0, psuffix);
+ if (key == "bzr")
+ return (DNGN_ENTER_PORTAL_VAULT);
+ else if (key == "lab")
+ return (DNGN_ENTER_LABYRINTH);
+ else if (key == "hell")
+ return (DNGN_ENTER_HELL);
+ else if (key == "pan")
+ return (DNGN_ENTER_PANDEMONIUM);
+ else if (key == "abyss")
+ return (DNGN_ENTER_ABYSS);
+ else
+ {
+ for (int i = 0; i < NUM_BRANCHES; ++i)
+ {
+ if (branches[i].entry_stairs != NUM_FEATURES
+ && !strcasecmp(branches[i].abbrevname, key.c_str()))
+ {
+ return (branches[i].entry_stairs);
+ }
+ }
+ }
+ return (DNGN_FLOOR);
+}
+
+static dungeon_feature_type dgn_find_rune_subst_tags(const std::string &tags)
+{
+ std::vector<std::string> words = split_string(" ", tags);
+ for (int i = 0, size = words.size(); i < size; ++i)
+ {
+ const dungeon_feature_type feat = dgn_find_rune_subst(words[i]);
+ if (feat != DNGN_FLOOR)
+ return (feat);
+ }
+ return (DNGN_FLOOR);
+}
+
+bool dgn_place_map(int map, bool generating_level, bool clobber)
+{
+ const map_def *mdef = map_by_index(map);
+ bool did_map = false;
+
+ if (mdef->is_minivault())
+ did_map =
+ build_minivaults(you.your_level, map, generating_level, clobber);
+ else
+ {
+ dungeon_feature_type rune_subst = DNGN_FLOOR;
+ if (mdef->has_tag_suffix("_entry"))
+ rune_subst = dgn_find_rune_subst_tags(mdef->tags);
+ did_map = build_secondary_vault(you.your_level, map, rune_subst,
+ generating_level, clobber);
+ }
+
+ // Activate any markers within the map.
+ if (did_map)
+ {
+ const vault_placement &vp = level_vaults[level_vaults.size() - 1];
+ for (int y = vp.y; y < vp.y + vp.height; ++y)
+ {
+ for (int x = vp.x; x < vp.x + vp.width; ++x)
+ {
+ std::vector<map_marker *> markers =
+ env_get_markers(coord_def(x, y));
+ for (int i = 0, size = markers.size(); i < size; ++i)
+ markers[i]->activate();
+
+ if (!see_grid(x, y))
+ set_terrain_changed(x, y);
+ }
+ }
+ }
+ return (did_map);
+}
+
/*
* Places a vault somewhere in an already built level if possible.
* Returns true if the vault was successfully placed.
*/
-static bool build_secondary_vault(int level_number, int vault, int rune_subst)
+static bool build_secondary_vault(int level_number, int vault,
+ int rune_subst, bool generating_level,
+ bool clobber)
{
- if (build_vaults(level_number, vault, rune_subst, true, true))
+ if (build_vaults(level_number, vault, rune_subst, true, true,
+ generating_level, clobber))
{
const vault_placement &vp = level_vaults[ level_vaults.size() - 1 ];
connect_vault(vp);
@@ -3368,7 +3476,8 @@ static bool build_secondary_vault(int level_number, int vault, int rune_subst)
}
static bool build_vaults(int level_number, int force_vault, int rune_subst,
- bool build_only, bool check_collisions)
+ bool build_only, bool check_collisions,
+ bool generating_level, bool clobber)
{
int altar_count = 0;
FixedVector < char, 10 > stair_exist;
@@ -3392,13 +3501,12 @@ static bool build_vaults(int level_number, int force_vault, int rune_subst,
vault_placement place;
std::vector<coord_def> &target_connections = place.exits;
- const int gluggy = vault_main(vgrid, place, force_vault, check_collisions);
+ const int gluggy = vault_main(vgrid, place, force_vault,
+ check_collisions, clobber);
if (gluggy == MAP_NONE || !gluggy)
return (false);
- place.map.map.apply_markers(coord_def(place.x, place.y));
-
int vx, vy;
int num_runes = 0;
@@ -3411,6 +3519,8 @@ static bool build_vaults(int level_number, int force_vault, int rune_subst,
{
if (vgrid[vy][vx] == ' ')
continue;
+
+ const dungeon_feature_type oldgrid = grd[vx][vy];
altar_count = vault_grid( place,
level_number, vx, vy, altar_count,
acq_item_class,
@@ -3418,9 +3528,20 @@ static bool build_vaults(int level_number, int force_vault, int rune_subst,
target_connections,
num_runes,
rune_subst );
+ if (!generating_level)
+ {
+ // Have to link items each square at a time, or
+ // dungeon_terrain_changed could blow up.
+ link_items();
+ const dungeon_feature_type newgrid = grd[vx][vy];
+ grd[vx][vy] = oldgrid;
+ dungeon_terrain_changed(coord_def(vx, vy), newgrid);
+ env_remove_markers_at(coord_def(vx, vy), MAT_ANY);
+ }
}
}
+ place.map.map.apply_markers(coord_def(place.x, place.y));
register_place(place);
if (gluggy == MAP_FLOAT && target_connections.empty())
@@ -3429,8 +3550,6 @@ static bool build_vaults(int level_number, int force_vault, int rune_subst,
// Must do this only after target_connections is finalised, or the vault
// exits will not be correctly set.
level_vaults.push_back(place);
- vault_zones.push_back(
- dgn_region(place.x, place.y, place.width, place.height));
#ifdef DEBUG_DIAGNOSTICS
if (crawl_state.map_stat_gen)
@@ -4125,10 +4244,11 @@ static bool join_the_dots(
{
join_count++;
- if (early_exit && at != from && grd(at) == DNGN_FLOOR)
+ const dungeon_feature_type feat = grd(at);
+ if (early_exit && at != from && is_traversable(feat))
return (true);
- if (unforbidden(at, MMT_VAULT))
+ if (unforbidden(at, MMT_VAULT) && !is_traversable(feat))
grd(at) = DNGN_FLOOR;
if (join_count > 10000) // just insurance