summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/acr.cc3
-rw-r--r--crawl-ref/source/clua.cc17
-rw-r--r--crawl-ref/source/clua.h3
-rw-r--r--crawl-ref/source/dat/clua/dungeon.lua42
-rw-r--r--crawl-ref/source/dat/splev.des3
-rw-r--r--crawl-ref/source/dungeon.cc137
-rw-r--r--crawl-ref/source/dungeon.h128
-rw-r--r--crawl-ref/source/externs.h5
-rw-r--r--crawl-ref/source/initfile.cc4
-rw-r--r--crawl-ref/source/libunix.h1
-rw-r--r--crawl-ref/source/luadgn.cc93
-rw-r--r--crawl-ref/source/luadgn.h4
-rw-r--r--crawl-ref/source/mapdef.cc51
-rw-r--r--crawl-ref/source/mapdef.h36
-rw-r--r--crawl-ref/source/maps.cc1
-rw-r--r--crawl-ref/source/stuff.cc8
-rw-r--r--crawl-ref/source/stuff.h17
-rw-r--r--crawl-ref/source/travel.cc14
-rw-r--r--crawl-ref/source/travel.h2
-rw-r--r--crawl-ref/source/util/levcomp.lpp12
-rw-r--r--crawl-ref/source/util/levcomp.ypp27
21 files changed, 462 insertions, 146 deletions
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index 9a5cb5df02..c91ce1fe86 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -1871,7 +1871,8 @@ static void decrement_durations()
else if (you.duration[DUR_TELEPORT] == 1)
{
// only to a new area of the abyss sometimes (for abyss teleports)
- you_teleport_now( true, one_chance_in(5) );
+ you_teleport_now( true, one_chance_in(5) );
+ untag_followers();
you.duration[DUR_TELEPORT] = 0;
}
diff --git a/crawl-ref/source/clua.cc b/crawl-ref/source/clua.cc
index 6a4e54074e..33047c504e 100644
--- a/crawl-ref/source/clua.cc
+++ b/crawl-ref/source/clua.cc
@@ -315,9 +315,7 @@ void CLua::fnreturns(const char *format, ...)
va_list args;
va_start(args, format);
-
vfnreturns(format, args);
-
va_end(args);
}
@@ -367,7 +365,6 @@ void CLua::vfnreturns(const char *format, va_list args)
}
static void push_monster(lua_State *ls, monsters *mons);
-static void push_map(lua_State *ls, map_def *map);
static int push_activity_interrupt(lua_State *ls, activity_interrupt_data *t);
int CLua::push_args(lua_State *ls, const char *format, va_list args,
va_list *targ)
@@ -415,7 +412,7 @@ int CLua::push_args(lua_State *ls, const char *format, va_list args,
lua_pushboolean(ls, va_arg(args, int));
break;
case 'm':
- push_map(ls, va_arg(args, map_def *));
+ clua_push_map(ls, va_arg(args, map_def *));
break;
case 'M':
push_monster(ls, va_arg(args, monsters *));
@@ -583,7 +580,7 @@ void CLua::init_lua()
return;
lua_atpanic(_state, clua_panic);
-
+
luaopen_base(_state);
luaopen_string(_state);
luaopen_table(_state);
@@ -611,6 +608,8 @@ void CLua::init_lua()
execfile("clua/userbase.lua", true, true);
}
+
+ lua_settop(_state, 1);
}
void CLua::load_chooks()
@@ -1830,6 +1829,7 @@ static int crawl_split(lua_State *ls)
}
LUARET1(crawl_game_started, boolean, crawl_state.need_save)
+LUARET1(crawl_random2, number, random2( luaL_checkint(ls, 1) ))
static int crawl_err_trace(lua_State *ls)
{
@@ -1860,14 +1860,15 @@ static int crawl_err_trace(lua_State *ls)
// What's on top should be the error.
lua_error(ls);
}
-
- return (lua_gettop(ls));
+
+ return (lua_gettop(ls));
}
static const struct luaL_reg crawl_lib[] =
{
{ "mpr", crawl_mpr },
{ "mesclr", crawl_mesclr },
+ { "random2", crawl_random2 },
{ "redraw_screen", crawl_redraw_screen },
{ "input_line", crawl_input_line },
{ "c_input_line", crawl_c_input_line},
@@ -2166,7 +2167,7 @@ static void push_monster(lua_State *ls, monsters *mons)
mw->mons = mons;
}
-static void push_map(lua_State *ls, map_def *map)
+void clua_push_map(lua_State *ls, map_def *map)
{
map_def **mapref = clua_new_userdata<map_def *>(ls, MAP_METATABLE);
*mapref = map;
diff --git a/crawl-ref/source/clua.h b/crawl-ref/source/clua.h
index b9190021b6..44da65b057 100644
--- a/crawl-ref/source/clua.h
+++ b/crawl-ref/source/clua.h
@@ -207,6 +207,9 @@ inline static T *clua_get_userdata(lua_State *ls, const char *mt)
std::string quote_lua_string(const std::string &s);
+class map_def;
+void clua_push_map(lua_State *ls, map_def *map);
+
#define MAP_METATABLE "dgn.mtmap"
#endif
diff --git a/crawl-ref/source/dat/clua/dungeon.lua b/crawl-ref/source/dat/clua/dungeon.lua
index 7fe2b30a22..d26bba984b 100644
--- a/crawl-ref/source/dat/clua/dungeon.lua
+++ b/crawl-ref/source/dat/clua/dungeon.lua
@@ -59,4 +59,46 @@ function dgn_run_map(prelude, main)
return setfenv(main, env)()
end
end
+end
+
+--------------------------------------------------------------------
+
+function dgn.places_connected(map, map_glyph, test_connect, ...)
+ local points = { }
+ for _, glyph in ipairs( { ... } ) do
+ local x, y = map_glyph(map, glyph)
+ if x and y then
+ table.insert(points, x)
+ table.insert(points, y)
+ else
+ error("Can't find coords for '" .. glyph .. "'")
+ end
+ end
+ return test_connect(map, unpack(points))
+end
+
+function dgn.glyphs_connected(map, ...)
+ return dgn.places_connected(map, dgn.gly_point, dgn.points_connected, ...)
+end
+
+function dgn.orig_glyphs_connected(map, ...)
+ return dgn.places_connected(map, dgn.orig_gly_point,
+ dgn.points_connected, ...)
+end
+
+function dgn.orig_fn(map, fnx, ...)
+ local original = dgn.original_map(map)
+ if not original then
+ error("Can't find original map for map '" .. dgn.name(map) .. "'")
+ end
+
+ return fnx(original, ...)
+end
+
+function dgn.orig_gly_point(map, glyph)
+ return dgn.orig_fn(map, dgn.gly_point, glyph)
+end
+
+function dgn.orig_gly_points(map, glyph)
+ return dgn.orig_fn(map, dgn.gly_points, glyph)
end \ No newline at end of file
diff --git a/crawl-ref/source/dat/splev.des b/crawl-ref/source/dat/splev.des
index 8f5c3b7965..5f85e274ea 100644
--- a/crawl-ref/source/dat/splev.des
+++ b/crawl-ref/source/dat/splev.des
@@ -935,6 +935,9 @@ SUBST: X=xc.+, Y=xc+
SUBST: T : T U V .:30 b
SUBST: _:.!, !:!.x, !=x .:2
SHUFFLE: 123, 45, ([<
+
+validate {{ return glyphs_connected('{', 'O') }}
+
MAP
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc
index a454c25770..df8dae0ae2 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -280,86 +280,15 @@ static coord_def find_level_feature(int feat)
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(true), 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 dungeon_feature_type 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 (!left_vault && unforbidden(dc, vaults))
- left_vault = true;
-
- good_square(dc);
-
- return (false);
-}
-
static bool has_connected_downstairs_from(const coord_def &c)
{
- feature_find ff;
+ flood_find<feature_grid, coord_predicate> ff(env.grid, in_bounds);
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);
+ coord_def where = ff.find_first_from(c, vault_zones);
return (where.x || !ff.did_leave_vault());
}
@@ -3353,6 +3282,62 @@ static monster_type random_evil_statue()
return (MONS_PROGRAM_BUG);
}
+// Grr, keep this in sync with vault_grid.
+dungeon_feature_type map_feature(map_def *map, const coord_def &c, int rawfeat)
+{
+ if (rawfeat == -1)
+ rawfeat = map->glyph_at(c);
+
+ keyed_mapspec *mapsp = map? map->mapspec_for_key(rawfeat) : NULL;
+ if (mapsp)
+ {
+ const feature_spec f = mapsp->get_feat();
+ if (f.feat >= 0)
+ return static_cast<dungeon_feature_type>(f.feat);
+ else if (f.glyph >= 0)
+ return map_feature(NULL, c, rawfeat);
+ else if (f.shop >= 0)
+ return (DNGN_ENTER_SHOP);
+ else if (f.trap >= 0)
+ return (DNGN_UNDISCOVERED_TRAP);
+
+ return (DNGN_FLOOR);
+ }
+
+ return ((rawfeat == 'x') ? DNGN_ROCK_WALL :
+ (rawfeat == 'X') ? DNGN_PERMAROCK_WALL :
+ (rawfeat == 'c') ? DNGN_STONE_WALL :
+ (rawfeat == 'v') ? DNGN_METAL_WALL :
+ (rawfeat == 'b') ? DNGN_GREEN_CRYSTAL_WALL :
+ (rawfeat == 'a') ? DNGN_WAX_WALL :
+ (rawfeat == '+') ? DNGN_CLOSED_DOOR :
+ (rawfeat == '=') ? DNGN_SECRET_DOOR :
+ (rawfeat == 'w') ? DNGN_DEEP_WATER :
+ (rawfeat == 'W') ? DNGN_SHALLOW_WATER :
+ (rawfeat == 'l') ? DNGN_LAVA :
+ (rawfeat == '>') ? DNGN_ROCK_STAIRS_DOWN :
+ (rawfeat == '<') ? DNGN_ROCK_STAIRS_UP :
+ (rawfeat == '}') ? DNGN_STONE_STAIRS_DOWN_I :
+ (rawfeat == '{') ? DNGN_STONE_STAIRS_UP_I :
+ (rawfeat == ')') ? DNGN_STONE_STAIRS_DOWN_II :
+ (rawfeat == '(') ? DNGN_STONE_STAIRS_UP_II :
+ (rawfeat == ']') ? DNGN_STONE_STAIRS_DOWN_III :
+ (rawfeat == '[') ? DNGN_STONE_STAIRS_UP_III :
+ (rawfeat == 'A') ? DNGN_STONE_ARCH :
+ (rawfeat == 'B') ? DNGN_ALTAR_ZIN :
+ (rawfeat == 'C') ? pick_an_altar() : // f(x) elsewhere {dlb}
+ (rawfeat == 'F') ? DNGN_GRANITE_STATUE :
+ (rawfeat == 'I') ? DNGN_ORCISH_IDOL :
+ (rawfeat == 'S') ? DNGN_SILVER_STATUE :
+ (rawfeat == 'G') ? DNGN_GRANITE_STATUE :
+ (rawfeat == 'H') ? DNGN_ORANGE_CRYSTAL_STATUE :
+ (rawfeat == 'T') ? DNGN_BLUE_FOUNTAIN :
+ (rawfeat == 'U') ? DNGN_SPARKLING_FOUNTAIN :
+ (rawfeat == 'V') ? DNGN_PERMADRY_FOUNTAIN :
+ (rawfeat == '\0')? DNGN_ROCK_WALL :
+ DNGN_FLOOR); // includes everything else
+}
+
// returns altar_count - seems rather odd to me to force such a return
// when I believe the value is only used in the case of the ecumenical
// temple - oh, well... {dlb}
@@ -3954,8 +3939,8 @@ static void place_shops(int level_number)
} // end place_shops()
void place_spec_shop( int level_number,
- unsigned char shop_x, unsigned char shop_y,
- unsigned char force_s_type, bool representative )
+ int shop_x, int shop_y,
+ int force_s_type, bool representative )
{
int orb = 0;
int i = 0;
@@ -5885,7 +5870,7 @@ static void jelly_pit(int level_number, spec_room &sr)
fill_monster_pit( sr, pit_list, 90, MONS_PROGRAM_BUG, lordx, lordy );
}
-bool place_specific_trap(unsigned char spec_x, unsigned char spec_y,
+bool place_specific_trap(int spec_x, int spec_y,
trap_type spec_type)
{
if (spec_type == TRAP_RANDOM)
diff --git a/crawl-ref/source/dungeon.h b/crawl-ref/source/dungeon.h
index f46106a3ed..04f013b655 100644
--- a/crawl-ref/source/dungeon.h
+++ b/crawl-ref/source/dungeon.h
@@ -16,6 +16,9 @@
#include "FixVec.h"
#include "externs.h"
+#include "misc.h"
+#include "travel.h"
+#include "stuff.h"
const int MAKE_GOOD_ITEM = 351;
@@ -89,18 +92,127 @@ struct dgn_region
};
void builder(int level_number, int level_type);
-
void define_zombie(int mid, int ztype, int cs, int power);
-
bool is_wall(int feature);
+bool place_specific_trap(int spec_x, int spec_y, trap_type spec_type);
+void place_spec_shop(int level_number, int shop_x, int shop_y,
+ int force_s_type, bool representative = false);
+bool unforbidden(const coord_def &c, const dgn_region_list &forbidden);
+
-bool place_specific_trap(unsigned char spec_x, unsigned char spec_y,
- trap_type spec_type);
+//////////////////////////////////////////////////////////////////////////
+template <typename fgrd, typename bound_check>
+class flood_find : public travel_pathfind
+{
+public:
+ flood_find(const fgrd &f, const bound_check &bc);
-void place_spec_shop(int level_number, unsigned char shop_x,
- unsigned char shop_y, unsigned char force_s_type,
- bool representative = false );
+ void add_feat(int feat);
+ void add_point(const coord_def &pos);
+ coord_def find_first_from(const coord_def &c, const dgn_region_list &vlts);
+ bool points_connected_from(const coord_def &start);
-bool unforbidden(const coord_def &c, const dgn_region_list &forbidden);
+ bool did_leave_vault() const { return left_vault; }
+
+protected:
+ bool path_flood(const coord_def &c, const coord_def &dc);
+protected:
+ bool point_hunt;
+ bool needed_features[NUM_FEATURES];
+ std::vector<coord_def> needed_points;
+ bool left_vault;
+ dgn_region_list vaults;
+
+ const fgrd &fgrid;
+ const bound_check &bcheck;
+};
+
+template <typename fgrd, typename bound_check>
+flood_find<fgrd, bound_check>::flood_find(const fgrd &f, const bound_check &bc)
+ : travel_pathfind(), point_hunt(false), needed_features(),
+ needed_points(), left_vault(true), vaults(),
+ fgrid(f), bcheck(bc)
+{
+ memset(needed_features, false, sizeof needed_features);
+}
+
+template <typename fgrd, typename bound_check>
+void flood_find<fgrd, bound_check>::add_feat(int feat)
+{
+ if (feat >= 0 && feat < NUM_FEATURES)
+ needed_features[feat] = true;
+}
+
+template <typename fgrd, typename bound_check>
+coord_def
+flood_find<fgrd, bound_check>::find_first_from(
+ const coord_def &c,
+ const dgn_region_list &vlts)
+{
+ set_floodseed(c);
+ vaults = vlts;
+ return pathfind(RMODE_EXPLORE);
+}
+
+template <typename fgrd, typename bound_check>
+void flood_find<fgrd, bound_check>::add_point(const coord_def &c)
+{
+ needed_points.push_back(c);
+}
+
+template <typename fgrd, typename bound_check>
+bool flood_find<fgrd, bound_check>::points_connected_from(
+ const coord_def &sp)
+{
+ if (needed_points.empty())
+ return (true);
+ set_floodseed(sp);
+ pathfind(RMODE_EXPLORE);
+ return (needed_points.empty());
+}
+
+template <typename fgrd, typename bound_check>
+bool flood_find<fgrd, bound_check>::path_flood(
+ const coord_def &c,
+ const coord_def &dc)
+{
+ if (!bcheck(dc))
+ return (false);
+
+ if (!needed_points.empty())
+ {
+ std::vector<coord_def>::iterator i =
+ std::find(needed_points.begin(), needed_points.end(), dc);
+ if (i != needed_points.end())
+ {
+ needed_points.erase(i);
+ if (needed_points.empty())
+ return (true);
+ }
+ }
+
+ const dungeon_feature_type grid = fgrid(dc);
+ if (needed_features[ grid ])
+ {
+ unexplored_place = dc;
+ unexplored_dist = traveled_distance;
+ return (true);
+ }
+
+ if (!is_traversable(grid)
+ && grid != DNGN_SECRET_DOOR
+ && !grid_is_trap(grid))
+ {
+ return (false);
+ }
+
+ if (!left_vault && unforbidden(dc, vaults))
+ left_vault = true;
+
+ good_square(dc);
+
+ return (false);
+}
+//////////////////////////////////////////////////////////////////////////
#endif
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index a2ee9c7f01..25ce05cba4 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -340,6 +340,7 @@ struct coord_def
return (MAXIMUM(::abs(x), ::abs(y)));
}
};
+typedef bool (*coord_predicate)(const coord_def &c);
struct dice_def
{
@@ -1164,6 +1165,7 @@ struct map_cell
bool seen() const;
};
+typedef FixedArray<dungeon_feature_type, GXM, GYM> feature_grid;
struct crawl_environment
{
unsigned char rock_colour;
@@ -1172,7 +1174,7 @@ struct crawl_environment
FixedVector< item_def, MAX_ITEMS > item; // item list
FixedVector< monsters, MAX_MONSTERS > mons; // monster list
- FixedArray<dungeon_feature_type, GXM, GYM> grid; // terrain grid
+ feature_grid grid; // terrain grid
FixedArray< unsigned char, GXM, GYM > mgrid; // monster grid
FixedArray< int, GXM, GYM > igrid; // item grid
FixedArray< unsigned char, GXM, GYM > cgrid; // cloud grid
@@ -1286,6 +1288,7 @@ struct system_environment
#endif
std::string scorefile;
+ std::vector<std::string> cmd_args;
};
extern system_environment SysEnv;
diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc
index 142048120e..3e48ec5640 100644
--- a/crawl-ref/source/initfile.cc
+++ b/crawl-ref/source/initfile.cc
@@ -2566,6 +2566,10 @@ bool parse_args( int argc, char **argv, bool rc_only )
for(int i=0; i<num_cmd_ops; i++)
arg_seen[i] = false;
+ if (SysEnv.cmd_args.empty())
+ for (int i = 1; i < argc; ++i)
+ SysEnv.cmd_args.push_back(argv[i]);
+
while(current < argc)
{
// get argument
diff --git a/crawl-ref/source/libunix.h b/crawl-ref/source/libunix.h
index 03d63a8be4..cee2e6577e 100644
--- a/crawl-ref/source/libunix.h
+++ b/crawl-ref/source/libunix.h
@@ -1,7 +1,6 @@
#ifndef LIBUNIX_H
#define LIBUNIX_H
-
// Some replacement routines missing in gcc
#ifndef O_BINARY
diff --git a/crawl-ref/source/luadgn.cc b/crawl-ref/source/luadgn.cc
index 3c73a194c7..ba8fb5fa98 100644
--- a/crawl-ref/source/luadgn.cc
+++ b/crawl-ref/source/luadgn.cc
@@ -11,6 +11,7 @@
#include "luadgn.h"
#include "mapdef.h"
#include "stuff.h"
+#include "dungeon.h"
#include <sstream>
// Lua interpreter for the dungeon builder.
@@ -33,7 +34,7 @@ inline static void dlua_pushcxxstring(lua_State *ls, const std::string &s)
lua_pushstring(ls, s.c_str());
}
-static int dlua_stringtable(lua_State *ls, const std::vector<std::string> &s)
+int dlua_stringtable(lua_State *ls, const std::vector<std::string> &s)
{
return dlua_gentable(ls, s, dlua_pushcxxstring);
}
@@ -50,7 +51,7 @@ dlua_chunk::dlua_chunk(const std::string &_context)
void dlua_chunk::write(FILE *outf) const
{
- if (compiled.empty() && chunk.empty())
+ if (empty())
{
writeByte(outf, CT_EMPTY);
return;
@@ -186,13 +187,14 @@ std::string dlua_chunk::orig_error() const
bool dlua_chunk::empty() const
{
- return trimmed_string(chunk).empty();
+ return compiled.empty() && trimmed_string(chunk).empty();
}
bool dlua_chunk::rewrite_chunk_errors(std::string &s) const
{
const std::string contextm = "[string \"" + context + "\"]:";
std::string::size_type dlwhere = s.find(contextm);
+
if (dlwhere == std::string::npos)
return (false);
@@ -645,6 +647,70 @@ static int dgn_grid(lua_State *ls)
PLUARET(number, grd[x][y]);
}
+static int dgn_points_connected(lua_State *ls)
+{
+ MAP(ls, 1, map);
+ const int nargs = lua_gettop(ls);
+ if (nargs < 5)
+ return luaL_error(ls,
+ "Not enough points to test connectedness "
+ "(need at least two)");
+
+ map_def::map_feature_finder feat_finder(*map);
+ map_def::map_bounds_check bounds_checker(*map);
+ flood_find<map_def::map_feature_finder, map_def::map_bounds_check>
+ finder(feat_finder, bounds_checker);
+
+ for (int i = 4; i < nargs; i += 2)
+ {
+ const coord_def c(luaL_checkint(ls, i),
+ luaL_checkint(ls, i + 1));
+ finder.add_point(c);
+ }
+
+ const coord_def pos(luaL_checkint(ls, 2), luaL_checkint(ls, 3));
+ const bool connected = finder.points_connected_from(pos);
+ PLUARET(boolean, connected);
+}
+
+static void dlua_push_coord(lua_State *ls, const coord_def &c)
+{
+ lua_pushnumber(ls, c.x);
+ lua_pushnumber(ls, c.y);
+}
+
+static int dgn_gly_point(lua_State *ls)
+{
+ MAP(ls, 1, map);
+ coord_def c = map->find_first_glyph(*luaL_checkstring(ls, 2));
+ if (c.x != -1 && c.y != -1)
+ {
+ dlua_push_coord(ls, c);
+ return (2);
+ }
+ return (0);
+}
+
+static int dgn_gly_points(lua_State *ls)
+{
+ MAP(ls, 1, map);
+ std::vector<coord_def> cs = map->find_glyph(*luaL_checkstring(ls, 2));
+
+ for (int i = 0, size = cs.size(); i < size; ++i)
+ dlua_push_coord(ls, cs[i]);
+ return (cs.size() * 2);
+}
+
+static int dgn_original_map(lua_State *ls)
+{
+ MAP(ls, 1, map);
+ if (map->original)
+ clua_push_map(ls, map->original);
+ else
+ lua_pushnil(ls);
+ return (1);
+}
+
static const struct luaL_reg dgn_lib[] =
{
{ "default_depth", dgn_default_depth },
@@ -667,14 +733,31 @@ static const struct luaL_reg dgn_lib[] =
{ "kitem", dgn_kitem },
{ "kmons", dgn_kmons },
{ "grid", dgn_grid },
+ { "points_connected", dgn_points_connected },
+ { "gly_point", dgn_gly_point },
+ { "gly_points", dgn_gly_points },
+ { "original_map", dgn_original_map },
+ { NULL, NULL }
+};
+
+static int crawl_args(lua_State *ls)
+{
+ return dlua_stringtable(ls, SysEnv.cmd_args);
+}
+
+static const struct luaL_reg crawl_lib[] =
+{
+ { "args", crawl_args },
{ NULL, NULL }
};
void init_dungeon_lua()
{
+ luaL_openlib(dlua, "dgn", dgn_lib, 0);
+ // Add additional function to the Crawl module.
+ luaL_openlib(dlua, "crawl", crawl_lib, 0);
dlua.execfile("clua/dungeon.lua", true, true);
luaopen_debug(dlua);
luaL_newmetatable(dlua, MAP_METATABLE);
- lua_pop(dlua, 1);
- luaL_openlib(dlua, "dgn", dgn_lib, 0);
+ lua_settop(dlua, 1);
}
diff --git a/crawl-ref/source/luadgn.h b/crawl-ref/source/luadgn.h
index 241983c0ba..9573fb5a67 100644
--- a/crawl-ref/source/luadgn.h
+++ b/crawl-ref/source/luadgn.h
@@ -36,7 +36,6 @@ private:
int check_op(CLua &, int);
std::string rewrite_chunk_prefix(const std::string &line) const;
std::string get_chunk_prefix(const std::string &s) const;
- void release_compiled_chunk();
public:
mutable std::string error;
@@ -64,5 +63,8 @@ public:
void init_dungeon_lua();
std::string dgn_set_default_depth(const std::string &s);
void dgn_reset_default_depth();
+int dlua_stringtable(lua_State *ls, const std::vector<std::string> &s);
+
+//////////////////////////////////////////////////////////////////////////
#endif
diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc
index 9c3a7953b7..857e93af08 100644
--- a/crawl-ref/source/mapdef.cc
+++ b/crawl-ref/source/mapdef.cc
@@ -343,6 +343,11 @@ map_lines::map_lines(const map_lines &map)
init_from(map);
}
+int map_lines::operator () (const coord_def &c) const
+{
+ return lines[c.y][c.x];
+}
+
map_lines &map_lines::operator = (const map_lines &map)
{
if (this != &map)
@@ -827,7 +832,8 @@ dlua_set_map::~dlua_set_map()
map_def::map_def()
: name(), tags(), place(), depths(), orient(), chance(),
map(), mons(), items(), keyspecs(), prelude("dlprelude"), main("dlmain"),
- index_only(false), cache_offset(0L)
+ validate("dlvalidate"), veto("dlveto"), index_only(false),
+ cache_offset(0L)
{
init();
}
@@ -859,6 +865,11 @@ void map_def::reinit()
mons.clear();
}
+int map_def::glyph_at(const coord_def &c) const
+{
+ return map(c);
+}
+
void map_def::write_full(FILE *outf)
{
cache_offset = ftell(outf);
@@ -906,6 +917,36 @@ void map_def::load()
index_only = false;
}
+std::vector<coord_def> map_def::find_glyph(int glyph) const
+{
+ std::vector<coord_def> points;
+ for (int y = map.height() - 1; y >= 0; --y)
+ {
+ for (int x = map.width() - 1; x >= 0; --x)
+ {
+ const coord_def c(x, y);
+ if (map(c) == glyph)
+ points.push_back(c);
+ }
+ }
+ return (points);
+}
+
+coord_def map_def::find_first_glyph(int glyph) const
+{
+ for (int y = 0, height = map.height(); y < height; ++y)
+ {
+ for (int x = 0, width = map.width(); x < width; ++x)
+ {
+ const coord_def c(x, y);
+ if (map(c) == glyph)
+ return (c);
+ }
+ }
+
+ return coord_def(-1, -1);
+}
+
void map_def::write_index(FILE *outf) const
{
if (!cache_offset)
@@ -953,6 +994,8 @@ void map_def::set_file(const std::string &s)
{
prelude.set_file(s);
main.set_file(s);
+ validate.set_file(s);
+ veto.set_file(s);
file = get_base_filename(s);
}
@@ -987,7 +1030,7 @@ bool map_def::test_lua_boolchunk(dlua_chunk &chunk)
{
bool result = true;
dlua_set_map mset(this);
-
+
int err = chunk.load(dlua);
if (err == -1000)
return (true);
@@ -996,13 +1039,11 @@ bool map_def::test_lua_boolchunk(dlua_chunk &chunk)
mprf(MSGCH_WARN, "Lua error: %s", validate.orig_error().c_str());
return (true);
}
-
if (dlua.callfn("dgn_run_map", 1, 1))
- dlua.fnreturns("b", &result);
+ dlua.fnreturns(">b", &result);
else
mprf(MSGCH_WARN, "Lua error: %s",
rewrite_chunk_errors(dlua.error).c_str());
-
return (result);
}
diff --git a/crawl-ref/source/mapdef.h b/crawl-ref/source/mapdef.h
index 307b9bfd3e..623b97dd55 100644
--- a/crawl-ref/source/mapdef.h
+++ b/crawl-ref/source/mapdef.h
@@ -179,6 +179,8 @@ public:
std::vector<std::string> get_shuffle_strings() const;
std::vector<std::string> get_subst_strings() const;
+ int operator () (const coord_def &c) const;
+
private:
void init_from(const map_lines &map);
void release_transforms();
@@ -401,6 +403,9 @@ struct dlua_set_map
~dlua_set_map();
};
+class map_def;
+dungeon_feature_type map_feature(map_def *map, const coord_def &c, int rawfeat);
+
class map_def
{
public:
@@ -420,6 +425,8 @@ public:
dlua_chunk prelude, main, validate, veto;
+ map_def *original;
+
private:
// This map has been loaded from an index, and not fully realised.
bool index_only;
@@ -432,6 +439,9 @@ public:
void reinit();
void load();
+
+ std::vector<coord_def> find_glyph(int glyph) const;
+ coord_def find_first_glyph(int glyph) const;
void write_index(FILE *) const;
void write_full(FILE *);
@@ -485,6 +495,32 @@ public:
std::vector<std::string> get_shuffle_strings() const;
std::vector<std::string> get_subst_strings() const;
+
+ int glyph_at(const coord_def &c) const;
+
+public:
+ struct map_feature_finder
+ {
+ map_def &map;
+ map_feature_finder(map_def &map_) : map(map_) { }
+ // This may actually modify the underlying map by fixing KFEAT:
+ // feature slots, but that's fine by us.
+ dungeon_feature_type operator () (const coord_def &c) const
+ {
+ return (map_feature(&map, c, -1));
+ }
+ };
+
+ struct map_bounds_check
+ {
+ map_def &map;
+ map_bounds_check(map_def &map_) : map(map_) { }
+ bool operator () (const coord_def &c) const
+ {
+ return (c.x >= 0 && c.x < map.map.width()
+ && c.y >= 0 && c.y < map.map.height());
+ }
+ };
private:
void write_depth_ranges(FILE *) const;
diff --git a/crawl-ref/source/maps.cc b/crawl-ref/source/maps.cc
index e60031195d..8b89d52115 100644
--- a/crawl-ref/source/maps.cc
+++ b/crawl-ref/source/maps.cc
@@ -87,6 +87,7 @@ static int write_vault(map_def &mdef, map_type map,
// Copy the map so we can monkey with it.
place.map = mdef;
+ place.map.original = &mdef;
// Try so many times to place the map. This will always succeed
// unless there are conflicting map placements in 'avoid', or there
diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc
index d6821315ca..b28e57ef03 100644
--- a/crawl-ref/source/stuff.cc
+++ b/crawl-ref/source/stuff.cc
@@ -146,7 +146,13 @@ void tag_followers( void )
}
}
-unsigned char get_ch(void)
+void untag_followers()
+{
+ for (int m = 0; m < MAX_MONSTERS; m++)
+ menv[m].flags &= (~MF_TAKING_STAIRS);
+}
+
+unsigned char get_ch()
{
unsigned char gotched = getch();
diff --git a/crawl-ref/source/stuff.h b/crawl-ref/source/stuff.h
index 812a089a74..618f83d38f 100644
--- a/crawl-ref/source/stuff.h
+++ b/crawl-ref/source/stuff.h
@@ -20,20 +20,21 @@
std::string make_time_string(time_t abs_time, bool terse = false);
void set_redraw_status( unsigned long flags );
-void tag_followers( void );
+void tag_followers();
+void untag_followers();
-void seed_rng(void);
+void seed_rng();
void seed_rng(long seed);
void push_rng_state();
void pop_rng_state();
-void cf_setseed(void);
-bool coinflip(void);
+void cf_setseed();
+bool coinflip();
int div_rand_round( int num, int den );
bool one_chance_in(int a_million);
int random2(int randmax);
int random_range(int low, int high);
-unsigned long random_int(void);
+unsigned long random_int();
int random2avg( int max, int rolls );
int bestroll(int max, int rolls);
@@ -47,7 +48,7 @@ int stepdown_value(int base_value, int stepping, int first_step, int last_step,
int stat_mult( int stat_level, int value, int div = 20, int shift = 3 );
int stat_div( int stat_level, int value, int div = 20, int shift = 3 );
int skill_bump( int skill );
-unsigned char get_ch(void);
+unsigned char get_ch();
void cio_init();
void cio_cleanup();
@@ -56,7 +57,7 @@ void end(int exit_code, bool print_err = false,
void modify_all_stats(int STmod, int IQmod, int DXmod);
-void redraw_screen(void);
+void redraw_screen();
void canned_msg(canned_message_type which_message);
@@ -89,7 +90,7 @@ bool silenced(char x, char y);
bool player_can_hear(char x, char y);
-unsigned char random_colour(void);
+unsigned char random_colour();
unsigned char random_uncommon_colour();
bool is_element_colour( int col );
int element_colour( int element, bool no_random = false );
diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc
index 74a30dd9a2..297d953cfe 100644
--- a/crawl-ref/source/travel.cc
+++ b/crawl-ref/source/travel.cc
@@ -186,7 +186,7 @@ static const char *trap_name(int x, int y)
/*
* Returns true if the character can cross this dungeon feature.
*/
-inline bool is_traversable(int grid)
+bool is_traversable(int grid)
{
return traversable_terrain[grid] == TRAVERSABLE;
}
@@ -1536,16 +1536,24 @@ void travel_pathfind::good_square(const coord_def &c)
}
}
-bool travel_pathfind::path_examine_point(const coord_def &c)
+bool travel_pathfind::point_traverse_delay(const coord_def &c)
{
if (square_slows_movement(c))
- return (false);
+ return (true);
// Greedy explore check should happen on (x,y), not (dx,dy) as for
// regular explore.
if (need_for_greed)
check_square_greed(c);
+ return (false);
+}
+
+bool travel_pathfind::path_examine_point(const coord_def &c)
+{
+ if (point_traverse_delay(c))
+ return (false);
+
// For each point, we look at all surrounding points. Take them orthogonals
// first so that the travel path doesn't zigzag all over the map. Note the
// (dir = 1) is intentional assignment.
diff --git a/crawl-ref/source/travel.h b/crawl-ref/source/travel.h
index 3ed894ecee..37a54b9d67 100644
--- a/crawl-ref/source/travel.h
+++ b/crawl-ref/source/travel.h
@@ -38,6 +38,7 @@ command_type stair_direction(int stair_feat);
command_type direction_to_command( char x, char y );
bool is_resting( void );
bool can_travel_interlevel();
+bool is_traversable(int grid);
void find_travel_pos(int you_x, int you_y, char *move_x, char *move_y,
std::vector<coord_def>* coords = NULL);
@@ -518,6 +519,7 @@ public:
protected:
bool is_greed_inducing_square(const coord_def &c) const;
bool path_examine_point(const coord_def &c);
+ virtual bool point_traverse_delay(const coord_def &c);
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);
diff --git a/crawl-ref/source/util/levcomp.lpp b/crawl-ref/source/util/levcomp.lpp
index 6df93afa7c..96331e45d1 100644
--- a/crawl-ref/source/util/levcomp.lpp
+++ b/crawl-ref/source/util/levcomp.lpp
@@ -183,7 +183,6 @@ KFEAT: { BEGIN(ARGUMENT); return KFEAT; }
KITEM: { BEGIN(ARGUMENT); return KITEM; }
KMONS: { BEGIN(ARGUMENT); return KMONS; }
-- return DASH;
, return COMMA;
[0-9]+ {
@@ -194,17 +193,6 @@ KMONS: { BEGIN(ARGUMENT); return KMONS; }
[\ \t]+ ;
\r?\n ;
-
-\( return OPAREN;
-\) return CPAREN;
-
-\" return QUOTE;
-
-[a-zA-Z_][a-zA-Z_0-9]* {
- settext();
- return IDENTIFIER;
- }
-
. return CHARACTER;
%%
diff --git a/crawl-ref/source/util/levcomp.ypp b/crawl-ref/source/util/levcomp.ypp
index aec084fb22..4a319c94f4 100644
--- a/crawl-ref/source/util/levcomp.ypp
+++ b/crawl-ref/source/util/levcomp.ypp
@@ -62,18 +62,17 @@ level_range set_range(const char *s, int start, int end)
raw_range range;
}
-%token <i> BRANCHDEF BRANCH DESC DEFAULT
+/* Two harmless shift/reduce conflicts */
+%expect 2
+
%token <i> DEFAULT_DEPTH SHUFFLE SUBST TAGS KFEAT KITEM KMONS
%token <i> NAME DEPTH ORIENT PLACE CHANCE MONS ITEM
%token <i> PRELUDE MAIN VALIDATE VETO
-%token <i> CHARACTER
-
-%token <i> DASH COMMA QUOTE OPAREN CPAREN
-%token <i> INTEGER
+%token <i> COMMA INTEGER CHARACTER
%token <text> STRING MAP_LINE MONSTER_NAME ITEM_INFO
-%token <text> IDENTIFIER LUA_LINE
+%token <text> LUA_LINE
%%
@@ -124,12 +123,12 @@ level : name map_specs
}
;
-map_specs : /* nothing */
+map_specs : /* nothing */ { }
| map_specs map_spec { }
;
-map_spec : metalines { }
- | map_def { }
+map_spec : metaline { }
+ | map_def { }
;
name : NAME STRING
@@ -154,10 +153,6 @@ name : NAME STRING
}
;
-metalines : /* no metadata */
- | metalines metaline
- ;
-
metaline : place
| depth
| chance
@@ -176,7 +171,7 @@ metaline : place
| veto_lua
;
-global_lua : MAIN global_lua_lines { }
+global_lua : MAIN global_lua_lines { }
global_lua_lines : /* empty */ { }
| global_lua_lines global_lua_line { }
@@ -378,8 +373,8 @@ orientation : ORIENT {}
map_def : map_lines
;
-map_lines : map_line
- | map_line map_lines
+map_lines : map_lines map_line
+ | map_line
;
map_line : MAP_LINE