summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-07-29 17:10:16 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-07-29 17:10:16 +0000
commit199d107c9f40413126a31fcc843f5c54608bc73c (patch)
tree444c9eb8c251d8d365e542e6cbbf3a8fd387138d /crawl-ref
parent1fef821214bcc2300fd2346c05cffb1b800104c5 (diff)
downloadcrawl-ref-199d107c9f40413126a31fcc843f5c54608bc73c.tar.gz
crawl-ref-199d107c9f40413126a31fcc843f5c54608bc73c.zip
&L can place encompass levels, and is more aggressive about overwriting
existing dungeon features. Dungeon features of importance - such as stairs, shops, and altars - and map markers are shifted out of the way, to the nearest free floor square. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1947 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/dungeon.cc51
-rw-r--r--crawl-ref/source/mapmark.cc21
-rw-r--r--crawl-ref/source/mapmark.h1
-rw-r--r--crawl-ref/source/maps.cc5
-rw-r--r--crawl-ref/source/misc.cc116
-rw-r--r--crawl-ref/source/shopping.cc2
-rw-r--r--crawl-ref/source/shopping.h2
7 files changed, 158 insertions, 40 deletions
diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc
index 58a2870d98..937482cb7a 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -55,6 +55,7 @@
#include "notes.h"
#include "player.h"
#include "randart.h"
+#include "spells3.h"
#include "spl-book.h"
#include "stuff.h"
#include "tags.h"
@@ -2880,6 +2881,9 @@ static bool safe_minivault_place(int v1x, int v1y,
const vault_placement &place,
bool clobber)
{
+ if (clobber)
+ return (true);
+
const bool water_ok = place.map.has_tag("water_ok");
const std::vector<std::string> &lines = place.map.map.get_lines();
for (int vx = v1x; vx < v1x + place.width; vx++)
@@ -2893,20 +2897,16 @@ static bool safe_minivault_place(int v1x, int v1y,
return (false);
const dungeon_feature_type dfeat = grd[vx][vy];
-
+
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)))
+ && dfeat != DNGN_SHALLOW_WATER)))
+ || igrd[vx][vy] != NON_ITEM
+ || mgrd[vx][vy] != NON_MONSTER)
{
return (false);
}
@@ -3419,6 +3419,9 @@ static dungeon_feature_type dgn_find_rune_subst_tags(const std::string &tags)
}
// Places a map on the current level (minivault or regular vault).
+//
+// NOTE: encompass maps will destroy the existing level!
+//
// generating_level: If true, assumes that this is in the middle of normal
// level generation, and does not link items or handle
// changing terrain.
@@ -3429,6 +3432,26 @@ bool dgn_place_map(int map, bool generating_level, bool clobber)
{
const map_def *mdef = map_by_index(map);
bool did_map = false;
+ bool fixup = false;
+
+ if (mdef->orient == MAP_ENCOMPASS && !generating_level)
+ {
+ if (clobber)
+ {
+ // For encompass maps, clear the entire level.
+ generating_level = true;
+ fixup = true;
+ reset_level();
+ dungeon_events.clear();
+ }
+ else
+ {
+ mprf(MSGCH_DIAGNOSTICS,
+ "Cannot generate encompass map '%s' without clobber=true",
+ mdef->name.c_str());
+ return (false);
+ }
+ }
if (mdef->is_minivault())
did_map =
@@ -3460,6 +3483,18 @@ bool dgn_place_map(int map, bool generating_level, bool clobber)
}
}
}
+
+ if (fixup)
+ {
+ link_items();
+ env_activate_markers();
+
+ // Force teleport to place the player somewhere sane.
+ you_teleport_now(false, false);
+ }
+
+ if (fixup || !generating_level)
+ setup_environment_effects();
return (did_map);
}
diff --git a/crawl-ref/source/mapmark.cc b/crawl-ref/source/mapmark.cc
index 2f2dc84a6b..191466f9e2 100644
--- a/crawl-ref/source/mapmark.cc
+++ b/crawl-ref/source/mapmark.cc
@@ -421,6 +421,27 @@ map_marker *env_find_marker(const coord_def &c, map_marker_type type)
return (NULL);
}
+void env_move_markers(const coord_def &from, const coord_def &to)
+{
+ std::pair<dgn_marker_map::iterator, dgn_marker_map::iterator>
+ els = env.markers.equal_range(from);
+
+ std::list<map_marker*> markers;
+ for (dgn_marker_map::iterator i = els.first; i != els.second; )
+ {
+ dgn_marker_map::iterator curr = i++;
+ markers.push_back(curr->second);
+ env.markers.erase(curr);
+ }
+
+ for (std::list<map_marker*>::iterator i = markers.begin();
+ i != markers.end(); ++i)
+ {
+ (*i)->pos = to;
+ env_add_marker(*i);
+ }
+}
+
std::vector<map_marker*> env_get_markers(const coord_def &c)
{
std::pair<dgn_marker_map::const_iterator, dgn_marker_map::const_iterator>
diff --git a/crawl-ref/source/mapmark.h b/crawl-ref/source/mapmark.h
index dc18f77946..49983e8017 100644
--- a/crawl-ref/source/mapmark.h
+++ b/crawl-ref/source/mapmark.h
@@ -109,5 +109,6 @@ std::vector<map_marker*> env_get_markers(const coord_def &c);
void env_clear_markers();
std::string env_property_at(const coord_def &c, map_marker_type,
const std::string &key);
+void env_move_markers(const coord_def &from, const coord_def &to);
#endif
diff --git a/crawl-ref/source/maps.cc b/crawl-ref/source/maps.cc
index 8599c2efe2..859e6fe211 100644
--- a/crawl-ref/source/maps.cc
+++ b/crawl-ref/source/maps.cc
@@ -161,7 +161,7 @@ static bool bad_map_place(const map_def &map,
int sx, int sy, int width, int height,
bool check_place, bool clobber)
{
- if (!check_place)
+ if (!check_place || clobber)
return (false);
const std::vector<std::string> &lines = map.map.get_lines();
@@ -175,8 +175,7 @@ static bool bad_map_place(const map_def &map,
if (dgn_map_mask[x][y])
return (true);
- if (!clobber
- && (igrd[x][y] != NON_ITEM || mgrd[x][y] != NON_MONSTER))
+ if (igrd[x][y] != NON_ITEM || mgrd[x][y] != NON_MONSTER)
return (true);
const dungeon_feature_type grid = grd[x][y];
diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc
index 328f46617d..372dbebb84 100644
--- a/crawl-ref/source/misc.cc
+++ b/crawl-ref/source/misc.cc
@@ -451,49 +451,110 @@ void search_around( bool only_adjacent )
return;
} // end search_around()
-static bool dgn_shift_item_around(const coord_def &pos, item_def &item)
+static coord_def dgn_find_nearest_square(
+ const coord_def &pos,
+ bool (*acceptable)(const coord_def &),
+ bool (*traversable)(const coord_def &) = NULL)
{
- std::list<coord_def> points;
- for (int yi = -1; yi <= 1; ++yi)
+ memset(travel_point_distance, 0, sizeof(travel_distance_grid_t));
+
+ std::list<coord_def> points[2];
+ int iter = 0;
+ points[iter].push_back(pos);
+
+ while (!points[iter].empty())
{
- for (int xi = -1; xi <= 1; ++xi)
+ for (std::list<coord_def>::iterator i = points[iter].begin();
+ i != points[iter].end(); ++i)
{
- if (!xi && !yi)
- continue;
+ const coord_def &p = *i;
- const coord_def np(pos.x + xi, pos.y + yi);
- if (!in_bounds(np) || travel_point_distance[np.x][np.y])
- continue;
+ if (p != pos && acceptable(p))
+ return (p);
+
+ travel_point_distance[p.x][p.y] = 1;
+ for (int yi = -1; yi <= 1; ++yi)
+ {
+ for (int xi = -1; xi <= 1; ++xi)
+ {
+ if (!xi && !yi)
+ continue;
- travel_point_distance[np.x][np.y] = 1;
+ const coord_def np = p + coord_def(xi, yi);
+ if (!in_bounds(np) || travel_point_distance[np.x][np.y])
+ continue;
- const dungeon_feature_type feat = grd(np);
- if (!grid_is_solid(feat) && !grid_destroys_items(feat))
- {
- int index = item.index();
- move_item_to_grid(&index, np.x, np.y);
- return (true);
+ if (traversable && !traversable(np))
+ continue;
+
+ points[!iter].push_back(np);
+ }
}
-
- points.push_back(np);
}
+
+ points[iter].clear();
+ iter = !iter;
}
- for (std::list<coord_def>::iterator i = points.begin(); i != points.end();
- ++i)
+ return (coord_def());
+}
+
+static bool item_safe_square(const coord_def &pos)
+{
+ const dungeon_feature_type feat = grd(pos);
+ return (is_traversable(feat) && !grid_destroys_items(feat));
+}
+
+// Moves an item on the floor to the nearest adjacent floor-space.
+static bool dgn_shift_item(const coord_def &pos, item_def &item)
+{
+ const coord_def np = dgn_find_nearest_square(pos, item_safe_square);
+ if (in_bounds(np) && np != pos)
{
- if (dgn_shift_item_around(*i, item))
- return (true);
+ int index = item.index();
+ move_item_to_grid(&index, np.x, np.y);
+ return (true);
}
return (false);
}
-// Moves an item on the floor to the nearest adjacent floor-space.
-static bool dgn_shift_item(const coord_def &pos, item_def &item)
+static bool is_critical_feature(dungeon_feature_type feat)
{
- memset(travel_point_distance, 0, sizeof(travel_distance_grid_t));
- travel_point_distance[pos.x][pos.y] = 0;
- return (dgn_shift_item_around(pos, item));
+ return (grid_stair_direction(feat) != CMD_NO_CMD
+ || grid_altar_god(feat) != GOD_NO_GOD);
+}
+
+static bool is_feature_shift_target(const coord_def &pos)
+{
+ return (grd(pos) == DNGN_FLOOR);
+}
+
+static bool dgn_shift_feature(const coord_def &pos)
+{
+ const dungeon_feature_type dfeat = grd(pos);
+ if (!is_critical_feature(dfeat) && !env_find_marker(pos, MAT_ANY))
+ return (false);
+
+ const coord_def dest =
+ dgn_find_nearest_square(pos, is_feature_shift_target);
+ if (in_bounds(dest) && dest != pos)
+ {
+ grd(dest) = dfeat;
+
+ if (dfeat == DNGN_ENTER_SHOP)
+ {
+ if (shop_struct *s = get_shop(pos.x, pos.y))
+ {
+ s->x = dest.x;
+ s->y = dest.y;
+ }
+ }
+ env_move_markers(pos, dest);
+
+ if (see_grid(dest) && is_notable_terrain(dfeat))
+ seen_notable_thing(dfeat, dest.x, dest.y);
+ }
+ return (true);
}
static void dgn_check_terrain_items(const coord_def &pos)
@@ -541,6 +602,7 @@ void dungeon_terrain_changed(const coord_def &pos,
{
if (nfeat != DNGN_UNSEEN)
{
+ dgn_shift_feature(pos);
unnotice_feature(level_pos(level_id::current(), pos));
grd(pos) = nfeat;
if (is_notable_terrain(nfeat) && see_grid(pos))
diff --git a/crawl-ref/source/shopping.cc b/crawl-ref/source/shopping.cc
index fce0a7cab6..9873fcec93 100644
--- a/crawl-ref/source/shopping.cc
+++ b/crawl-ref/source/shopping.cc
@@ -1485,7 +1485,7 @@ void shop()
redraw_screen();
} // end shop()
-const shop_struct *get_shop(int sx, int sy)
+shop_struct *get_shop(int sx, int sy)
{
if (grd[sx][sy] != DNGN_ENTER_SHOP)
return (NULL);
diff --git a/crawl-ref/source/shopping.h b/crawl-ref/source/shopping.h
index b558fed97b..f91e14a111 100644
--- a/crawl-ref/source/shopping.h
+++ b/crawl-ref/source/shopping.h
@@ -24,7 +24,7 @@ int randart_value( const item_def &item );
unsigned int item_value( item_def item, bool ident = false );
void shop();
-const shop_struct *get_shop(int sx, int sy);
+shop_struct *get_shop(int sx, int sy);
std::string shop_name(int sx, int sy);
std::string shop_name(int sx, int sy, bool add_stop);