diff options
Diffstat (limited to 'crawl-ref')
-rw-r--r-- | crawl-ref/source/clua.cc | 17 | ||||
-rw-r--r-- | crawl-ref/source/dat/clua/dungeon.lua | 18 | ||||
-rw-r--r-- | crawl-ref/source/dat/clua/point.lua | 57 | ||||
-rw-r--r-- | crawl-ref/source/dat/clua/util.lua | 18 | ||||
-rw-r--r-- | crawl-ref/source/dat/clua/ziggurat.lua | 87 | ||||
-rw-r--r-- | crawl-ref/source/dat/ziggurat.des | 10 | ||||
-rw-r--r-- | crawl-ref/source/dungeon.cc | 21 | ||||
-rw-r--r-- | crawl-ref/source/dungeon.h | 19 | ||||
-rw-r--r-- | crawl-ref/source/luadgn.cc | 105 |
9 files changed, 301 insertions, 51 deletions
diff --git a/crawl-ref/source/clua.cc b/crawl-ref/source/clua.cc index fac00a74dd..ae30763ab3 100644 --- a/crawl-ref/source/clua.cc +++ b/crawl-ref/source/clua.cc @@ -69,6 +69,7 @@ static int _clua_panic(lua_State *); static void _clua_throttle_hook(lua_State *, lua_Debug *); static void *_clua_allocator(void *ud, void *ptr, size_t osize, size_t nsize); static int _clua_guarded_pcall(lua_State *); +static int _clua_require(lua_State *); static int _clua_dofile(lua_State *); static int _clua_loadfile(lua_State *); @@ -637,6 +638,8 @@ void CLua::init_lua() lua_register(_state, "loadfile", _clua_loadfile); lua_register(_state, "dofile", _clua_dofile); + lua_register(_state, "require", _clua_require); + execfile("clua/util.lua", true, true); if (managed_vm) @@ -2929,6 +2932,20 @@ static int _clua_loadfile(lua_State *ls) return (1); } +static int _clua_require(lua_State *ls) +{ + const char *file = luaL_checkstring(ls, 1); + if (!file) + return (0); + + CLua &vm(CLua::get_vm(ls)); + if (vm.execfile(file, false, false) != 0) + luaL_error(ls, vm.error.c_str()); + + lua_pushboolean(ls, true); + return (1); +} + static int _clua_dofile(lua_State *ls) { const char *file = luaL_checkstring(ls, 1); diff --git a/crawl-ref/source/dat/clua/dungeon.lua b/crawl-ref/source/dat/clua/dungeon.lua index 2736e1f372..4c8d5ddc86 100644 --- a/crawl-ref/source/dat/clua/dungeon.lua +++ b/crawl-ref/source/dat/clua/dungeon.lua @@ -3,6 +3,8 @@ -- Dungeoneering functions. ------------------------------------------------------------------------------ +require("clua/point.lua") + dgn.GXM, dgn.GYM = dgn.max_bounds() dgn.f_map = { } @@ -247,13 +249,27 @@ end function dgn.colour_map(fselect, colour) for x = 0, dgn.GXM - 1 do for y = 0, dgn.GYM - 1 do - if fselect(x, y) then + if fselect(dgn.point(x, y)) then dgn.colour_at(x, y, colour) end end end end +-- Returns true if fpred returns true for all squares in the rectangle +-- whose top-left corner is tl and bottom right corner is br (br.x >= +-- tl.x and br.y >= tl.y). +function dgn.rectangle_forall(tl, br, fpred) + for x = tl.x, br.x do + for y = tl.y, br.y do + if not fpred(dgn.point(x, y)) then + return false + end + end + end + return true +end + ---------------------------------------------------------------------- -- Convenience functions for vaults. diff --git a/crawl-ref/source/dat/clua/point.lua b/crawl-ref/source/dat/clua/point.lua new file mode 100644 index 0000000000..e57115e033 --- /dev/null +++ b/crawl-ref/source/dat/clua/point.lua @@ -0,0 +1,57 @@ +-------------------------------------------------------------------------- +-- point.lua +-------------------------------------------------------------------------- + +local point_metatable = { } + +function dgn.point(x, y) + local pt = { x = x, y = y } + setmetatable(pt, point_metatable) + return pt +end + +point_metatable.__add = function (a, b) + if type(b) == "number" then + return dgn.point(a.x + b, a.y + b) + else + return dgn.point(a.x + b.x, a.y + b.y) + end + end + +point_metatable.__sub = function (a, b) + if type(b) == "number" then + return dgn.point(a.x - b, a.y - b) + else + return dgn.point(a.x - b.x, a.y - b.y) + end + end + +point_metatable.__div = function (a, b) + if type(b) ~= "number" then + error("Can only divide by numbers.") + end + return dgn.point(math.floor(a.x / b), + math.floor(a.y / b)) + end + +point_metatable.__mul = function (a, b) + if type(b) ~= "number" then + error("Can only multiply by numbers.") + end + return dgn.point(a.x * b, a.y * b) + end + +point_metatable.__unm = function (a) + return dgn.point(-a.x, -a.y) + end + +point_metatable.__concat = function (pre, post) + local function pstr(p) + return "(" .. p.x .. "," .. p.y .. ")" + end + if getmetatable(pre) == point_metatable then + return pstr(pre) .. post + else + return pre .. pstr(post) + end + end diff --git a/crawl-ref/source/dat/clua/util.lua b/crawl-ref/source/dat/clua/util.lua index 0c327fd194..950449f94e 100644 --- a/crawl-ref/source/dat/clua/util.lua +++ b/crawl-ref/source/dat/clua/util.lua @@ -62,6 +62,24 @@ function util.map(fn, ...) return res end +function util.forall(list, pred) + for _, value in ipairs(list) do + if not pred(value) then + return false + end + end + return true +end + +function util.exists(list, pred) + for _, value in ipairs(list) do + if pred(value) then + return true + end + end + return false +end + function util.random_from(list) return list[ crawl.random2(#list) + 1 ] end
\ No newline at end of file diff --git a/crawl-ref/source/dat/clua/ziggurat.lua b/crawl-ref/source/dat/clua/ziggurat.lua index dbeb8eb001..182f0f6d5e 100644 --- a/crawl-ref/source/dat/clua/ziggurat.lua +++ b/crawl-ref/source/dat/clua/ziggurat.lua @@ -309,29 +309,65 @@ end local function ziggurat_place_pillars(c) local range = crawl.random_range + local floor = dgn.fnum("floor") - local function pillar_spot() - local floor = dgn.fnum("floor") - for i = 1, 100 do - local place = { x = c.x + range(-30, 30), y = c.y + range(-30, 30) } - if (dgn.grid(place.x, place.y) == floor) then - return place - end + local map, vplace = dgn.resolve_map(dgn.map_by_tag("ziggurat_pillar")) + + if not map then + return + end + + local name = dgn.name(map) + + local size = dgn.point(dgn.mapsize(map)) + + -- Does the pillar want to be centered? + local centered = string.find(dgn.tags(map), " centered ") + + local function good_place(p) + local function good_square(where) + return dgn.grid(where.x, where.y) == floor end - return nil + return dgn.rectangle_forall(p, p + size - 1, good_square) end - local function place_pillar(p) - local map = dgn.map_by_tag("ziggurat_pillar") - if map then - dgn.place_map(map, false, true, p.x, p.y) + local function place_pillar() + if centered then + if good_place(c) then + return dgn.place_map(map, false, true, c.x, c.y) + end + else + for i = 1, 100 do + local offset = range(-15, -size.x) + local offsets = { + dgn.point(offset, offset) - size + 1, + dgn.point(offset - size.x + 1, -offset), + dgn.point(-offset, -offset), + dgn.point(-offset, offset - size.y + 1) + } + + offsets = util.map(function (o) + return o + c + end, offsets) + + if util.forall(offsets, good_place) then + local function replace(at, hflip, vflip) + dgn.reuse_map(vplace, at.x, at.y, hflip, vflip) + end + + replace(offsets[1], false, false) + replace(offsets[2], false, true) + replace(offsets[3], true, false) + replace(offsets[4], false, true) + return true + end + end end end - for i = 1, crawl.random_range(1,3) do - local p = pillar_spot() - if p then - place_pillar(p) + for i = 1, 5 do + if place_pillar() then + break end end end @@ -347,11 +383,10 @@ local function ziggurat_rectangle_builder(e) dgn.fill_area(unpack( util.catlist(flip_rectangle(x1, y1, x2, y2), { "floor" }) ) ) - local cx = math.floor((x1 + x2) / 2) - local cy = math.floor((y1 + y2) / 2) + local c = dgn.point(x1 + x2, y1 + y2) / 2 - local entry = { x = x1, y = cy } - local exit = { x = x2, y = cy } + local entry = { x = x1, y = c.y } + local exit = { x = x2, y = c.y } if zig_depth() % 2 == 0 then entry, exit = exit, entry @@ -362,16 +397,18 @@ local function ziggurat_rectangle_builder(e) zigstair(exit.x, exit.y + 1, "exit_portal_vault", cleanup_ziggurat()) zigstair(exit.x, exit.y - 1, "exit_portal_vault", cleanup_ziggurat()) - ziggurat_place_pillars { x = cx, y = cy } + ziggurat_place_pillars(c) ziggurat_create_loot(exit) ziggurat_create_monsters(exit) - dgn.colour_map(function (x, y) - return dgn.grid(x, y) == dgn.fnum("stone_wall") - end, - zig().colour) + local function needs_colour(p) + return not dgn.in_vault(p.x, p.y) + and dgn.grid(p.x, p.y) == dgn.fnum("stone_wall") + end + + dgn.colour_map(needs_colour, zig().colour) crawl.mpr("Ziggurat depth is now " .. zig_depth(), "diagnostic") end diff --git a/crawl-ref/source/dat/ziggurat.des b/crawl-ref/source/dat/ziggurat.des index 886f7514f1..e2f30776d3 100644 --- a/crawl-ref/source/dat/ziggurat.des +++ b/crawl-ref/source/dat/ziggurat.des @@ -17,6 +17,10 @@ ENDMAP ####################################################################### # Pillars for ziggurats. +# Ziggurat pillars are handled specially in ziggurat.lua. In particular: +# - ziggurat pillars do not need allow_dup. The pillar map is never +# registered as used. +# - ziggurat pillars cannot use map markers. ####################################################################### NAME: ziggurat_pillar_a TAGS: ziggurat_pillar @@ -29,18 +33,20 @@ NAME: ziggurat_pillar_b TAGS: ziggurat_pillar SUBST: c : cxv MAP -cc +c cc ENDMAP NAME: ziggurat_pillar_c -TAGS: ziggurat_pillar +TAGS: ziggurat_pillar centered MAP lll lGl lll ENDMAP +####################################################################### + NAME: ziggurat1 : ziggurat_level(_G) MAP diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 4217c8bcd0..8cde1a11b4 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -236,6 +236,7 @@ static bool _fixup_interlevel_connectivity(); // A mask of vaults and vault-specific flags. map_mask dgn_Map_Mask; std::vector<vault_placement> Level_Vaults; +std::vector<vault_placement> Temp_Vaults; std::set<std::string> Level_Unique_Maps; std::set<std::string> Level_Unique_Tags; std::string dgn_Build_Method; @@ -298,10 +299,6 @@ bool builder(int level_number, int level_type) mapgen_report_map_build_start(); #endif - dgn_level_vetoed = false; - Level_Unique_Maps.clear(); - Level_Unique_Tags.clear(); - _reset_level(); // If we're getting low on available retries, disable random vaults @@ -356,6 +353,7 @@ void level_welcome_messages() void level_clear_vault_memory() { Level_Vaults.clear(); + Temp_Vaults.clear(); dgn_Map_Mask.init(0); } @@ -467,7 +465,7 @@ static void _dgn_register_vault(const map_def &map) if (!map.has_tag("allow_dup")) you.uniq_map_names.insert(map.name); - if (map.has_tag("uniq")) + if (map.has_tag("luniq")) Level_Unique_Maps.insert(map.name); std::vector<std::string> tags = split_string(" ", map.tags); @@ -755,9 +753,10 @@ static void _mask_vault(const vault_placement &place, unsigned mask) } } -static void _register_place(const vault_placement &place) +void dgn_register_place(const vault_placement &place, bool register_vault) { - _dgn_register_vault(place.map); + if (register_vault) + _dgn_register_vault(place.map); if (!place.map.has_tag("layout")) _mask_vault(place, MMT_VAULT | MMT_NO_DOOR); @@ -869,6 +868,10 @@ static bool _valid_dungeon_level(int level_number, int level_type) static void _reset_level() { + dgn_level_vetoed = false; + Level_Unique_Maps.clear(); + Level_Unique_Tags.clear(); + dgn_Build_Method.clear(); dgn_Layout_Type.clear(); level_clear_vault_memory(); @@ -3963,7 +3966,7 @@ static bool _build_minivaults(int level_number, const map_def *vault, mapgen_report_map_use(place.map); #endif - _register_place(place); + dgn_register_place(place, true); place.apply_grid(); @@ -4488,7 +4491,7 @@ static bool _build_vaults(int level_number, const map_def *vault, return (false); place.apply_grid(); - _register_place(place); + dgn_register_place(place, true); std::vector<coord_def> &target_connections = place.exits; if (target_connections.empty() && gluggy != MAP_ENCOMPASS) diff --git a/crawl-ref/source/dungeon.h b/crawl-ref/source/dungeon.h index 3d01688f29..e0b2c9b31b 100644 --- a/crawl-ref/source/dungeon.h +++ b/crawl-ref/source/dungeon.h @@ -50,13 +50,6 @@ const int MAKE_GOOD_ITEM = 351; typedef FixedArray<unsigned short, GXM, GYM> map_mask; -extern map_mask dgn_Map_Mask; -extern bool Generating_Level; -extern std::string dgn_Layout_Type; - -extern std::set<std::string> Level_Unique_Maps; -extern std::set<std::string> Level_Unique_Tags; - // Map mask constants. enum map_mask_type @@ -168,6 +161,16 @@ public: void draw_at(const coord_def &c); }; +extern map_mask dgn_Map_Mask; +extern bool Generating_Level; +extern std::string dgn_Layout_Type; + +extern std::set<std::string> Level_Unique_Maps; +extern std::set<std::string> Level_Unique_Tags; + +extern std::vector<vault_placement> Level_Vaults; +extern std::vector<vault_placement> Temp_Vaults; + ////////////////////////////////////////////////////////////////////////// template <typename fgrd, typename bound_check> class flood_find : public travel_pathfind @@ -375,6 +378,8 @@ void dgn_set_lt_callback(std::string level_type_name, // vaults used in the current level). bool dgn_square_is_passable(const coord_def &c); +void dgn_register_place(const vault_placement &place, bool register_vault); + struct spec_room { bool created; diff --git a/crawl-ref/source/luadgn.cc b/crawl-ref/source/luadgn.cc index 483164951d..152368bb6a 100644 --- a/crawl-ref/source/luadgn.cc +++ b/crawl-ref/source/luadgn.cc @@ -28,6 +28,7 @@ #include "misc.h" #include "mon-util.h" #include "spl-util.h" +#include "state.h" #include "stuff.h" #include "tags.h" #include "terrain.h" @@ -900,6 +901,14 @@ static int dgn_kmask(lua_State *ls) return (0); } +static int dgn_map_size(lua_State *ls) +{ + MAP(ls, 1, map); + lua_pushnumber(ls, map->map.width()); + lua_pushnumber(ls, map->map.height()); + return (2); +} + static int dgn_name(lua_State *ls) { MAP(ls, 1, map); @@ -1128,7 +1137,8 @@ static int dgn_change_floor_colour(lua_State *ls) { const int colour = _lua_colour(ls, 1, BLACK); env.floor_colour = (unsigned char) colour; - viewwindow(true, false); + if (crawl_state.need_save) + viewwindow(true, false); return (0); } @@ -1136,7 +1146,8 @@ static int dgn_change_rock_colour(lua_State *ls) { const int colour = _lua_colour(ls, 1, BLACK); env.rock_colour = (unsigned char) colour; - viewwindow(true, false); + if (crawl_state.need_save) + viewwindow(true, false); return (0); } @@ -2230,7 +2241,7 @@ static inline bool _lua_boolean(lua_State *ls, int ndx, bool defval) static int _lua_push_map(lua_State *ls, const map_def *map) { if (map) - lua_pushlightuserdata(ls, const_cast<map_def*>(map)); + clua_push_map(ls, const_cast<map_def*>(map)); else lua_pushnil(ls); return (1); @@ -2263,9 +2274,7 @@ LUAFN(dgn_map_by_place) LUAFN(_dgn_place_map) { - if (!lua_isuserdata(ls, 1)) - luaL_argerror(ls, 1, "Expected map"); - const map_def *map = static_cast<map_def *>(lua_touserdata(ls, 1)); + MAP(ls, 1, map); const bool clobber = _lua_boolean(ls, 2, false); const bool no_exits = _lua_boolean(ls, 3, false); coord_def where(-1, -1); @@ -2274,10 +2283,88 @@ LUAFN(_dgn_place_map) COORDS(c, 4, 5); where = c; } - lua_pushboolean(ls, dgn_place_map(map, clobber, no_exits, where)); + if (dgn_place_map(map, clobber, no_exits, where) && !Level_Vaults.empty()) + lua_pushlightuserdata(ls, &Level_Vaults[Level_Vaults.size() - 1]); + else + lua_pushnil(ls); return (1); } +LUAFN(_dgn_in_vault) +{ + GETCOORD(c, 1, 2, map_bounds); + const int mask = lua_isnone(ls, 3) ? MMT_VAULT : lua_tointeger(ls, 3); + lua_pushboolean(ls, dgn_Map_Mask(c) & mask); + return (1); +} + +LUAFN(_dgn_resolve_map) +{ + if (lua_isnil(ls, 1)) + { + lua_pushnil(ls); + return (1); + } + + MAP(ls, 1, map); + const bool check_collisions = _lua_boolean(ls, 2, true); + + // Save the vault_placement into Temp_Vaults because the map_def + // will need to be alive through to the end of dungeon gen. + Temp_Vaults.push_back(vault_placement()); + + vault_placement &place(Temp_Vaults[Temp_Vaults.size() - 1]); + + if (vault_main(place, map, check_collisions) != MAP_NONE) + { + clua_push_map(ls, &place.map); + lua_pushlightuserdata(ls, &place); + } + else + { + lua_pushnil(ls); + lua_pushnil(ls); + } + return (2); +} + +LUAFN(_dgn_reuse_map) +{ + if (!lua_isuserdata(ls, 1)) + luaL_argerror(ls, 1, "Expected vault_placement"); + + vault_placement &vp( + *static_cast<vault_placement*>(lua_touserdata(ls, 1))); + + COORDS(place, 2, 3); + + const bool flip_horiz = _lua_boolean(ls, 4, false); + const bool flip_vert = _lua_boolean(ls, 5, false); + + // 1 for clockwise, -1 for anticlockwise, 0 for no rotation. + const int rotate_dir = lua_isnone(ls, 6) ? 0 : luaL_checkint(ls, 6); + + const bool register_place = _lua_boolean(ls, 7, true); + const bool register_vault = register_place && _lua_boolean(ls, 8, false); + + if (flip_horiz) + vp.map.hmirror(); + if (flip_vert) + vp.map.vmirror(); + if (rotate_dir) + vp.map.rotate(rotate_dir == 1); + + vp.size = vp.map.map.size(); + + // draw_at changes vault_placement. + vp.draw_at(place); + + if (register_place) + dgn_register_place(vp, register_vault); + + return (0); +} + static int dgn_debug_dump_map(lua_State *ls) { const int pos = lua_isuserdata(ls, 1) ? 2 : 1; @@ -2318,6 +2405,7 @@ static const struct luaL_reg dgn_lib[] = { "kitem", dgn_kitem }, { "kmons", dgn_kmons }, { "kmask", dgn_kmask }, + { "mapsize", dgn_map_size }, { "grid", dgn_grid }, { "max_bounds", dgn_max_bounds }, @@ -2395,6 +2483,9 @@ static const struct luaL_reg dgn_lib[] = { "map_in_depth", dgn_map_in_depth }, { "map_by_place", dgn_map_by_place }, { "place_map", _dgn_place_map }, + { "reuse_map", _dgn_reuse_map }, + { "resolve_map", _dgn_resolve_map }, + { "in_vault", _dgn_in_vault }, { "debug_dump_map", dgn_debug_dump_map }, |