diff options
-rw-r--r-- | crawl-ref/source/acr.cc | 3 | ||||
-rw-r--r-- | crawl-ref/source/clua.cc | 17 | ||||
-rw-r--r-- | crawl-ref/source/clua.h | 3 | ||||
-rw-r--r-- | crawl-ref/source/dat/clua/dungeon.lua | 42 | ||||
-rw-r--r-- | crawl-ref/source/dat/splev.des | 3 | ||||
-rw-r--r-- | crawl-ref/source/dungeon.cc | 137 | ||||
-rw-r--r-- | crawl-ref/source/dungeon.h | 128 | ||||
-rw-r--r-- | crawl-ref/source/externs.h | 5 | ||||
-rw-r--r-- | crawl-ref/source/initfile.cc | 4 | ||||
-rw-r--r-- | crawl-ref/source/libunix.h | 1 | ||||
-rw-r--r-- | crawl-ref/source/luadgn.cc | 93 | ||||
-rw-r--r-- | crawl-ref/source/luadgn.h | 4 | ||||
-rw-r--r-- | crawl-ref/source/mapdef.cc | 51 | ||||
-rw-r--r-- | crawl-ref/source/mapdef.h | 36 | ||||
-rw-r--r-- | crawl-ref/source/maps.cc | 1 | ||||
-rw-r--r-- | crawl-ref/source/stuff.cc | 8 | ||||
-rw-r--r-- | crawl-ref/source/stuff.h | 17 | ||||
-rw-r--r-- | crawl-ref/source/travel.cc | 14 | ||||
-rw-r--r-- | crawl-ref/source/travel.h | 2 | ||||
-rw-r--r-- | crawl-ref/source/util/levcomp.lpp | 12 | ||||
-rw-r--r-- | crawl-ref/source/util/levcomp.ypp | 27 |
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_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_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 |