summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/dat/vaults.des2
-rw-r--r--crawl-ref/source/dungeon.cc133
-rw-r--r--crawl-ref/source/dungeon.h2
-rw-r--r--crawl-ref/source/misc.cc6
-rw-r--r--crawl-ref/source/misc.h1
-rw-r--r--crawl-ref/source/travel.cc38
-rw-r--r--crawl-ref/source/travel.h13
7 files changed, 175 insertions, 20 deletions
diff --git a/crawl-ref/source/dat/vaults.des b/crawl-ref/source/dat/vaults.des
index 462daef33c..d6120a354d 100644
--- a/crawl-ref/source/dat/vaults.des
+++ b/crawl-ref/source/dat/vaults.des
@@ -2323,6 +2323,7 @@ TAGS: entry no_monster_gen
# damn those fish!
ORIENT: float
ITEM: ring of levitation, potion of levitation
+FLAGS: no_rotate
MAP
xxxxccccccccwwwww..wwww..wwwwwww....wwwwwww..wwww...wccccxxxxxx
@@ -2535,6 +2536,7 @@ ENDMAP
NAME: erik_entry_18
TAGS: entry
ORIENT: float
+FLAGS: no_rotate
MONS: giant bat, small snake, worm, gnoll, imp, orc
ITEM: stone, scroll of paper, banana, potion of healing
diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc
index 3c246cb906..34e1b81903 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -52,6 +52,7 @@
#include "randart.h"
#include "spl-book.h"
#include "stuff.h"
+#include "travel.h"
#define MAX_PIT_MONSTERS 10
@@ -72,6 +73,9 @@ struct spec_t {
typedef struct spec_t spec_room;
// DUNGEON BUILDERS
+static void build_dungeon_level(int level_number, int level_type);
+static bool valid_dungeon_level(int level_number, int level_type);
+
static bool find_in_area(int sx, int sy, int ex, int ey, unsigned char feature);
static bool make_box(int room_x1, int room_y1, int room_x2, int room_y2,
unsigned char floor=0, unsigned char wall=0, unsigned char avoid=0);
@@ -165,6 +169,8 @@ static dgn_region_list no_monster_zones;
static dgn_region_list no_pool_fixup_zones;
static dgn_region_list no_door_fixup_zones;
+static std::vector<vault_placement> level_vaults;
+
static std::string level_name(int subdepth)
{
return place_name(
@@ -211,11 +217,132 @@ static void place_altars()
/**********************************************************************
* builder() - kickoff for the dungeon generator.
*********************************************************************/
-void builder(int level_number, char level_type)
+void builder(int level_number, int level_type)
+{
+ do
+ build_dungeon_level(level_number, level_type);
+ while (!valid_dungeon_level(level_number, level_type));
+}
+
+static coord_def find_level_feature(int feat)
+{
+ for (int y = 1; y < GYM; ++y)
+ {
+ for (int x = 1; x < GXM; ++x)
+ {
+ if (grd[x][y] == feat)
+ return coord_def(x, y);
+ }
+ }
+ return coord_def(0, 0);
+}
+
+class feature_find : public travel_pathfind
+{
+public:
+ feature_find();
+
+ void add_feat(int feat);
+ coord_def find_first_from(const coord_def &c);
+
+ bool did_leave_vault() const { return left_vault; }
+
+protected:
+ bool path_flood(const coord_def &c, const coord_def &dc);
+protected:
+ bool needed_features[NUM_FEATURES];
+ bool left_vault;
+ dgn_region_list vaults;
+};
+
+feature_find::feature_find()
+ : travel_pathfind(), needed_features(), left_vault(false), vaults()
+{
+ memset(needed_features, false, sizeof needed_features);
+}
+
+void feature_find::add_feat(int feat)
+{
+ if (feat >= 0 && feat < NUM_FEATURES)
+ needed_features[feat] = true;
+}
+
+coord_def feature_find::find_first_from(const coord_def &c)
+{
+ set_floodseed(c);
+
+ for (int i = 0, size = level_vaults.size(); i < size; ++i)
+ {
+ const vault_placement &p = level_vaults[i];
+ vaults.push_back( dgn_region(p.x, p.y, p.width, p.height) );
+ }
+
+ return pathfind(RMODE_EXPLORE);
+}
+
+bool feature_find::path_flood(const coord_def &c, const coord_def &dc)
+{
+ if (!in_bounds(dc))
+ return (false);
+
+ const int grid = grd(dc);
+ if (needed_features[ grid ])
+ {
+ unexplored_place = dc;
+ unexplored_dist = traveled_distance;
+ return (true);
+ }
+
+ if (!is_travelsafe_square(dc.x, dc.y, false, true)
+ && grid != DNGN_SECRET_DOOR
+ && !grid_is_trap(grid))
+ {
+ return (false);
+ }
+
+ if (unforbidden(dc, vaults))
+ left_vault = true;
+
+ good_square(dc);
+
+ return (false);
+}
+
+static bool has_connected_downstairs_from(const coord_def &c)
+{
+ feature_find ff;
+ ff.add_feat(DNGN_STONE_STAIRS_DOWN_I);
+ ff.add_feat(DNGN_STONE_STAIRS_DOWN_II);
+ ff.add_feat(DNGN_STONE_STAIRS_DOWN_III);
+ ff.add_feat(DNGN_ROCK_STAIRS_DOWN);
+
+ coord_def where = ff.find_first_from(c);
+ return (where.x || !ff.did_leave_vault());
+}
+
+static bool is_level_stair_connected()
+{
+ coord_def up = find_level_feature(DNGN_STONE_STAIRS_UP_I);
+ if (up.x && up.y)
+ return has_connected_downstairs_from(up);
+
+ return (false);
+}
+
+static bool valid_dungeon_level(int level_number, int level_type)
+{
+ if (level_number == 0 && level_type == LEVEL_DUNGEON)
+ return is_level_stair_connected();
+
+ return (true);
+}
+
+static void build_dungeon_level(int level_number, int level_type)
{
int i; // generic loop variable
int x,y; // generic map loop variables
+ level_vaults.clear();
no_monster_zones.clear();
no_pool_fixup_zones.clear();
no_door_fixup_zones.clear();
@@ -5192,6 +5319,8 @@ static void build_minivaults(int level_number, int force_vault)
vault_placement place;
vault_main(vgrid, place, force_vault, level_number);
+ level_vaults.push_back(place);
+
int vx, vy;
int v1x, v1y;
@@ -5492,6 +5621,8 @@ static void build_vaults(int level_number, int force_vault)
int gluggy = vault_main(vgrid, place, force_vault, level_number);
+ level_vaults.push_back(place);
+
int vx, vy;
int num_runes = 0;
diff --git a/crawl-ref/source/dungeon.h b/crawl-ref/source/dungeon.h
index c2122f8c37..2e06159615 100644
--- a/crawl-ref/source/dungeon.h
+++ b/crawl-ref/source/dungeon.h
@@ -33,7 +33,7 @@ void item_colour( item_def &item );
/* ***********************************************************************
* called from: files
* *********************************************************************** */
-void builder(int level_number, char level_type);
+void builder(int level_number, int level_type);
// last updated 12may2000 {dlb}
diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc
index af5174d97f..3c9f0755fa 100644
--- a/crawl-ref/source/misc.cc
+++ b/crawl-ref/source/misc.cc
@@ -173,6 +173,12 @@ bool grid_is_solid(const coord_def &c)
return (grid_is_solid(grd(c)));
}
+bool grid_is_trap(int grid)
+{
+ return (grid == DNGN_TRAP_MECHANICAL || grid == DNGN_TRAP_MAGICAL
+ || grid == DNGN_TRAP_III);
+}
+
bool grid_is_water( int grid )
{
return (grid == DNGN_SHALLOW_WATER || grid == DNGN_DEEP_WATER);
diff --git a/crawl-ref/source/misc.h b/crawl-ref/source/misc.h
index 4106ee231a..10d168a06c 100644
--- a/crawl-ref/source/misc.h
+++ b/crawl-ref/source/misc.h
@@ -136,6 +136,7 @@ bool grid_is_opaque(int grid);
bool grid_is_solid(int grid);
bool grid_is_solid(int x, int y);
bool grid_is_solid(const coord_def &c);
+bool grid_is_trap(int grid);
bool grid_is_water(int grid);
bool grid_is_watery( int grid );
diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc
index 57cc5d0d60..a3983a4145 100644
--- a/crawl-ref/source/travel.cc
+++ b/crawl-ref/source/travel.cc
@@ -128,25 +128,19 @@ bool is_player_mapped(unsigned char envch)
return envch && envch != get_magicmap_char(DNGN_FLOOR) && envch != '~';
}
-inline bool is_trap(unsigned char grid)
-{
- return (grid == DNGN_TRAP_MECHANICAL || grid == DNGN_TRAP_MAGICAL
- || grid == DNGN_TRAP_III);
-}
-
// Returns true if there is a known trap at (x,y). Returns false for non-trap
// squares as also for undiscovered traps.
//
inline bool is_trap(int x, int y)
{
- return is_trap( grd[x][y] );
+ return grid_is_trap( grd[x][y] );
}
// Returns true if this feature takes extra time to cross.
inline int feature_traverse_cost(unsigned char feature)
{
return (feature == DNGN_SHALLOW_WATER || feature == DNGN_CLOSED_DOOR? 2 :
- is_trap(feature) ? 3 : 1);
+ grid_is_trap(feature) ? 3 : 1);
}
// Returns true if the dungeon feature supplied is an altar.
@@ -362,9 +356,10 @@ static bool is_reseedable(int x, int y)
* is true, returns true even for dungeon features the character can normally
* not cross safely (deep water, lava, traps).
*/
-static bool is_travel_ok(int x, int y, bool ignore_hostile)
+bool is_travelsafe_square(int x, int y, bool ignore_hostile,
+ bool ignore_terrain_knowledge)
{
- if (!is_terrain_known(x, y))
+ if (!ignore_terrain_knowledge && !is_terrain_known(x, y))
return (false);
const int grid = grd[x][y];
@@ -1110,6 +1105,10 @@ travel_pathfind::travel_pathfind()
{
}
+travel_pathfind::~travel_pathfind()
+{
+}
+
static bool is_greed_inducing_square(const LevelStashes *ls, const coord_def &c)
{
if (ls && ls->needs_visit(c.x, c.y))
@@ -1249,7 +1248,7 @@ const coord_def travel_pathfind::pathfind(run_mode_type rmode)
// Abort run if we're trying to go someplace evil. Travel to traps is
// specifically allowed here if the player insists on it.
if (!floodout
- && !is_travel_ok(start.x, start.y, false)
+ && !is_travelsafe_square(start.x, start.y, false)
&& !is_trap(start.x, start.y)) // The player likes pain
{
return coord_def(0, 0);
@@ -1367,7 +1366,7 @@ void travel_pathfind::check_square_greed(const coord_def &c)
{
if (greedy_dist == UNFOUND_DIST
&& is_greed_inducing_square(c)
- && is_travel_ok(c.x, c.y, ignore_hostile))
+ && is_travelsafe_square(c.x, c.y, ignore_hostile))
{
greedy_place = c;
greedy_dist = traveled_distance;
@@ -1429,7 +1428,7 @@ bool travel_pathfind::path_flood(const coord_def &c, const coord_def &dc)
return (true);
}
- if (dc != dest && !is_travel_ok(dc.x, dc.y, ignore_hostile))
+ if (dc != dest && !is_travelsafe_square(dc.x, dc.y, ignore_hostile))
{
// This point is not okay to travel on, but if this is a
// trap, we'll want to put it on the feature vector anyway.
@@ -1504,6 +1503,17 @@ bool travel_pathfind::path_flood(const coord_def &c, const coord_def &dc)
return (false);
}
+void travel_pathfind::good_square(const coord_def &c)
+{
+ if (!point_distance[c.x][c.y])
+ {
+ // This point is going to be on the agenda for the next
+ // iteration
+ circumference[!circ_index][next_iter_points++] = c;
+ point_distance[c.x][c.y] = traveled_distance;
+ }
+}
+
bool travel_pathfind::path_examine_point(const coord_def &c)
{
if (square_slows_movement(c))
@@ -2411,7 +2421,7 @@ void start_travel(int x, int y)
if (travel_point_distance[x][y] == 0
&& (x != you.x_pos || you.running.y != you.y_pos)
- && is_travel_ok(x, y, false)
+ && is_travelsafe_square(x, y, false)
&& can_travel_interlevel())
{
// We'll need interlevel travel to get here.
diff --git a/crawl-ref/source/travel.h b/crawl-ref/source/travel.h
index 6493e37209..97491884c1 100644
--- a/crawl-ref/source/travel.h
+++ b/crawl-ref/source/travel.h
@@ -42,6 +42,9 @@ bool is_player_mapped(int grid_x, int grid_y);
void find_travel_pos(int you_x, int you_y, char *move_x, char *move_y,
std::vector<coord_def>* coords = NULL);
+bool is_travelsafe_square(int x, int y, bool ignore_hostile = false,
+ bool ignore_terrain_knowledge = false);
+
/* ***********************************************************************
* Initiates explore - the character runs around the level to map it. Note
* that the caller has to ensure that the level is mappable before calling
@@ -423,6 +426,7 @@ class travel_pathfind
{
public:
travel_pathfind();
+ virtual ~travel_pathfind();
// Finds travel direction or explore target.
const coord_def pathfind(run_mode_type rt);
@@ -461,18 +465,19 @@ public:
// RMODE_EXPLORE_GREEDY.
const coord_def unexplored_square() const;
-private:
+protected:
bool is_greed_inducing_square(const coord_def &c) const;
bool path_examine_point(const coord_def &c);
- bool path_flood(const coord_def &c, const coord_def &dc);
+ virtual bool path_flood(const coord_def &c, const coord_def &dc);
bool square_slows_movement(const coord_def &c);
void check_square_greed(const coord_def &c);
+ void good_square(const coord_def &c);
-private:
+protected:
static const int UNFOUND_DIST = -10000;
static const int INFINITE_DIST = 10000;
-private:
+protected:
run_mode_type runmode;
// Where pathfinding starts, and the destination. Note that dest is not