diff options
author | dshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573> | 2008-11-28 21:29:47 +0000 |
---|---|---|
committer | dshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573> | 2008-11-28 21:29:47 +0000 |
commit | fde21eb9a22782da835911ea2a0d3b70836a81a5 (patch) | |
tree | c3fbd63c29e39a71cea9d5a7fe4d8d3a345e89a9 | |
parent | c8e9d5bb28e0c9d478d97b329ad504958a9ccc84 (diff) | |
download | crawl-ref-fde21eb9a22782da835911ea2a0d3b70836a81a5.tar.gz crawl-ref-fde21eb9a22782da835911ea2a0d3b70836a81a5.zip |
Fixed slow ziggurat level build, fixed ziggurat dismissals of simulacra resulting in messages.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7679 c06c8d41-db1a-0410-9941-cceddc491573
-rw-r--r-- | crawl-ref/source/clua.cc | 42 | ||||
-rw-r--r-- | crawl-ref/source/clua.h | 17 | ||||
-rw-r--r-- | crawl-ref/source/dat/clua/dungeon.lua | 8 | ||||
-rw-r--r-- | crawl-ref/source/dat/clua/util.lua | 24 | ||||
-rw-r--r-- | crawl-ref/source/dat/clua/ziggurat.lua | 128 | ||||
-rw-r--r-- | crawl-ref/source/luadgn.cc | 157 | ||||
-rw-r--r-- | crawl-ref/source/monstuff.cc | 25 |
7 files changed, 284 insertions, 117 deletions
diff --git a/crawl-ref/source/clua.cc b/crawl-ref/source/clua.cc index a87a1070f5..a2cd62d2c4 100644 --- a/crawl-ref/source/clua.cc +++ b/crawl-ref/source/clua.cc @@ -706,12 +706,11 @@ void CLua::remove_shutdown_listener(lua_shutdown_listener *listener) ///////////////////////////////////////////////////////////////////// -static void _clua_register_metatable(lua_State *ls, const char *tn, - const luaL_reg *lr, - int (*gcfn)(lua_State *ls) = NULL) +void clua_register_metatable(lua_State *ls, const char *tn, + const luaL_reg *lr, + int (*gcfn)(lua_State *ls)) { - int top = lua_gettop(ls); - + lua_stack_cleaner clean(ls); luaL_newmetatable(ls, tn); lua_pushstring(ls, "__index"); lua_pushvalue(ls, -2); @@ -724,9 +723,10 @@ static void _clua_register_metatable(lua_State *ls, const char *tn, lua_settable(ls, -3); } - luaL_openlib(ls, NULL, lr, 0); - - lua_settop(ls, top); + if (lr) + { + luaL_openlib(ls, NULL, lr, 0); + } } ///////////////////////////////////////////////////////////////////// @@ -2069,15 +2069,6 @@ static int crawl_regex_find(lua_State *ls) return (1); } -static int crawl_regex_gc(lua_State *ls) -{ - text_pattern **pattern = - static_cast<text_pattern **>( lua_touserdata(ls, 1) ); - if (pattern) - delete *pattern; - return (0); -} - static const luaL_reg crawl_regex_ops[] = { { "matches", crawl_regex_find }, @@ -2119,15 +2110,6 @@ static int crawl_messf_matches(lua_State *ls) return (0); } -static int crawl_messf_gc(lua_State *ls) -{ - message_filter **pattern = - static_cast<message_filter**>( lua_touserdata(ls, 1) ); - if (pattern) - delete *pattern; - return (0); -} - static const luaL_reg crawl_messf_ops[] = { { "matches", crawl_messf_matches }, @@ -2318,10 +2300,10 @@ static const struct luaL_reg crawl_lib[] = void luaopen_crawl(lua_State *ls) { - _clua_register_metatable(ls, REGEX_METATABLE, crawl_regex_ops, - crawl_regex_gc); - _clua_register_metatable(ls, MESSF_METATABLE, crawl_messf_ops, - crawl_messf_gc); + clua_register_metatable(ls, REGEX_METATABLE, crawl_regex_ops, + lua_object_gc<text_pattern>); + clua_register_metatable(ls, MESSF_METATABLE, crawl_messf_ops, + lua_object_gc<message_filter>); luaL_openlib(ls, "crawl", crawl_lib, 0); } diff --git a/crawl-ref/source/clua.h b/crawl-ref/source/clua.h index 014939c92a..7880eabcb6 100644 --- a/crawl-ref/source/clua.h +++ b/crawl-ref/source/clua.h @@ -280,9 +280,18 @@ inline static T *util_get_userdata(lua_State *ls, int ndx) } template <class T> -inline static T *clua_get_userdata(lua_State *ls, const char *mt) +inline static T *clua_get_userdata(lua_State *ls, const char *mt, int ndx = 1) { - return static_cast<T*>( luaL_checkudata( ls, 1, mt ) ); + return static_cast<T*>( luaL_checkudata( ls, ndx, mt ) ); +} + +template <class T> +static int lua_object_gc(lua_State *ls) +{ + T **pptr = static_cast<T**>( lua_touserdata(ls, 1) ); + if (pptr) + delete *pptr; + return (0); } std::string quote_lua_string(const std::string &s); @@ -306,6 +315,10 @@ template <class T> T *clua_new_userdata( void push_monster(lua_State *ls, monsters *mons); +void clua_register_metatable(lua_State *ls, const char *tn, + const luaL_reg *lr, + int (*gcfn)(lua_State *ls) = NULL); + #define MAP_METATABLE "dgn.mtmap" #define DEVENT_METATABLE "dgn.devent" #define MAPMARK_METATABLE "dgn.mapmark" diff --git a/crawl-ref/source/dat/clua/dungeon.lua b/crawl-ref/source/dat/clua/dungeon.lua index ef602034a3..12b1af5665 100644 --- a/crawl-ref/source/dat/clua/dungeon.lua +++ b/crawl-ref/source/dat/clua/dungeon.lua @@ -6,6 +6,7 @@ require("clua/point.lua") dgn.GXM, dgn.GYM = dgn.max_bounds() +dgn.MAX_MONSTERS = dgn.max_monsters() dgn.f_map = { } @@ -29,6 +30,13 @@ function dgn.fnum(name) return fnum end +function dgn.monster_fn(spec) + local mspec = dgn.monster_spec(spec) + return function (x, y) + return dgn.create_monster(x, y, mspec) + end +end + -- Given a feature name or number, returns a feature number. function dgn.find_feature_number(name_num) if type(name_num) == "number" then diff --git a/crawl-ref/source/dat/clua/util.lua b/crawl-ref/source/dat/clua/util.lua index c627047d52..c9d6a9af3c 100644 --- a/crawl-ref/source/dat/clua/util.lua +++ b/crawl-ref/source/dat/clua/util.lua @@ -189,4 +189,28 @@ function util.random_weighted_from(weightfn, list) end end) return chosen +end + +---------------------------------------------------------- + +util.Timer = { } +util.Timer.__index = util.Timer + +function util.Timer:new(pars) + self.__index = self + local timer = pars or { } + setmetatable(timer, self) + timer:init() + return timer +end + +function util.Timer:init() + self.epoch = crawl.millis() +end + +function util.Timer:mark(what) + local last = self.last or self.epoch + local now = crawl.millis() + crawl.mpr(what .. ": " .. (now - last) .. " ms") + self.last = now 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 707c13366f..64323bee99 100644 --- a/crawl-ref/source/dat/clua/ziggurat.lua +++ b/crawl-ref/source/dat/clua/ziggurat.lua @@ -211,12 +211,12 @@ local function monster_creator_fn(arg) local atyp = type(arg) if atyp == "string" then local _, _, branch = string.find(arg, "^place:(%w+):") + local mcreator = dgn.monster_fn(arg) local function mspec(x, y, nth) if branch then set_floor_colour(dgn.br_floorcol(branch)) end - - return dgn.create_monster(x, y, arg) + return mcreator(x, y) end return { fn = mspec } elseif atyp == "table" then @@ -259,17 +259,21 @@ mset("place:Elf:$ w:300 / deep elf blademaster / deep elf master archer / " .. mset_if(depth_ge(6), "place:Pan w:400 / w:15 pandemonium lord") mset_if(depth_lt(6), "place:Pan") +local drac_creator = dgn.monster_fn("random draconian") local function mons_drac_gen(x, y, nth) set_random_floor_colour() - return dgn.create_monster(x, y, "random draconian") + return drac_creator(x, y) end +local pan_lord_fn = dgn.monster_fn("pandemonium lord") +local pan_critter_fn = dgn.monster_fn("place:Pan") + local function mons_panlord_gen(x, y, nth) set_random_floor_colour() if nth == 1 then - return dgn.create_monster(x, y, "pandemonium lord") + return pan_lord_fn(x, y) else - return dgn.create_monster(x, y, "place:Pan") + return pan_critter_fn(x, y) end end @@ -283,7 +287,10 @@ end local function ziggurat_vet_monster(fmap) local fn = fmap.fn fmap.fn = function (x, y, nth, hdmax) - for i = 1, 100 do + if nth >= dgn.MAX_MONSTERS then + return nil + end + for i = 1, 10 do local mons = fn(x, y, nth) if mons then -- Discard zero-exp monsters, and monsters that explode @@ -319,29 +326,40 @@ local function ziggurat_create_monsters(p, mfn) local depth = zig_depth() local hd_pool = depth * (depth + 8) - local function mons_place_p(point) - return not dgn.mons_at(point.x, point.y) - end - local nth = 1 - while hd_pool > 0 do - local place = dgn.find_adjacent_point(p, mons_place_p, dgn_passable) - local mons = mfn(place.x, place.y, nth, hd_pool) + local function mons_do_place(p) + if hd_pool > 0 then + local mons = mfn(p.x, p.y, nth, hd_pool) - if mons then - nth = nth + 1 - hd_pool = hd_pool - mons.hd - else - -- Can't find any suitable monster for the HD we have left. - break + if mons then + nth = nth + 1 + hd_pool = hd_pool - mons.hd + + if nth >= dgn.MAX_MONSTERS then + hd_pool = 0 + end + else + -- Can't find any suitable monster for the HD we have left. + hd_pool = 0 + end + end + end + + local function mons_place(point) + if hd_pool <= 0 then + return true + elseif not dgn.mons_at(point.x, point.y) then + mons_do_place(point) end end + + dgn.find_adjacent_point(p, mons_place, dgn_passable) end local function ziggurat_create_loot_at(c) - local nloot = zig_depth() local depth = zig_depth() + local nloot = depth local function free_space_threshold(max) local function is_free_space(p) @@ -351,15 +369,18 @@ local function ziggurat_create_loot_at(c) return is_free_space end - local function free_space_do(fn) - for i = 0, 20 do - local p = - dgn.find_adjacent_point(c, free_space_threshold(i), dgn_passable) - if p then - fn(p) - break + local function find_free_space(nspaces) + local spaces = { } + local function add_spaces(p) + if nspaces <= 0 then + return true + else + table.insert(spaces, p) + nspaces = nspaces - 1 end end + dgn.find_adjacent_point(c, add_spaces, dgn_passable) + return spaces end local loot_depth = 20 @@ -367,19 +388,36 @@ local function ziggurat_create_loot_at(c) loot_depth = you.absdepth() - 1 end + local good_loot = dgn.item_spec("*") + local super_loot = dgn.item_spec("|") + + local loot_spots = find_free_space(nloot * 4) + + if #loot_spots == 0 then + return + end + + local curspot = 0 + local function next_loot_spot() + curspot = curspot + 1 + if curspot > #loot_spots then + curspot = 1 + end + return loot_spots[curspot] + end + local function place_loot(what) - free_space_do(function (p) - dgn.create_item(p.x, p.y, what, loot_depth) - end) + local p = next_loot_spot() + dgn.create_item(p.x, p.y, what, loot_depth) end for i = 1, nloot do if crawl.one_chance_in(depth) then for j = 1, 4 do - place_loot("*") + place_loot(good_loot) end else - place_loot("|") + place_loot(super_loot) end end end @@ -406,14 +444,8 @@ local function ziggurat_create_loot_vault(entry, exit) local map = dgn.map_by_tag("ziggurat_loot_chamber", false) - local function loot_fallback() - --crawl.mpr("Failed to create loot vault, giving up", "diagnostic") - -- FAIL, generate loot the usual way. - ziggurat_create_loot_at(exit) - end - if not map then - return loot_fallback() + return exit end local function place_loot_chamber() @@ -452,24 +484,24 @@ local function ziggurat_create_loot_vault(entry, exit) local res = dgn.with_map_anchors(connect_point.x, connect_point.y, connect_loot_chamber) if not res then - loot_fallback() + return exit else -- Find the square to drop the loot. local lootx, looty = dgn.find_marker_prop("ziggurat_loot") if lootx and looty then - ziggurat_create_loot_at(dgn.point(lootx, looty)) + return dgn.point(lootx, looty) else - loot_fallback() + return exit end end end -local function ziggurat_create_loot(entrance, exit) +local function ziggurat_locate_loot(entrance, exit) if zig().level.jelly_protect then - ziggurat_create_loot_vault(entrance, exit) + return ziggurat_create_loot_vault(entrance, exit) else - ziggurat_create_loot_at(exit) + return exit end end @@ -557,13 +589,17 @@ local function ziggurat_furnish(centre, entry, exit) zig().level.jelly_protect = true end - ziggurat_create_loot(entry, exit) + -- Identify where we're going to place loot, but don't actually put + -- anything down until we've placed pillars. + local lootspot = ziggurat_locate_loot(entry, exit) if not zig().level.loot_chamber then -- Place pillars if we did not create a loot chamber. ziggurat_place_pillars(centre) end + ziggurat_create_loot_at(lootspot) + ziggurat_create_monsters(exit, monster_generation.fn) local function needs_colour(p) diff --git a/crawl-ref/source/luadgn.cc b/crawl-ref/source/luadgn.cc index 564556ed71..8f0b3fc1fd 100644 --- a/crawl-ref/source/luadgn.cc +++ b/crawl-ref/source/luadgn.cc @@ -35,6 +35,24 @@ #include "terrain.h" #include "view.h" +#ifdef UNIX +#include <sys/time.h> +#include <time.h> +#endif + +#define MONSLIST_METATABLE "crawldgn.monster_list" +#define ITEMLIST_METATABLE "crawldgn.item_list" + +static mons_list _lua_get_mlist(lua_State *ls, int ndx); +static item_list _lua_get_ilist(lua_State *ls, int ndx); + +template <class T> +static void _push_object_type(lua_State *ls, const char *meta, const T &data) +{ + T **ptr = clua_new_userdata<T*>(ls, meta); + *ptr = new T(data); +} + template <typename list, typename lpush> static int dlua_gentable(lua_State *ls, const list &strings, lpush push) { @@ -2133,45 +2151,47 @@ static int dgn_create_monster(lua_State *ls) { COORDS(c, 1, 2); - if (const char *spec = lua_tostring(ls, 3)) + mons_list mlist = _lua_get_mlist(ls, 3); + for (int i = 0, size = mlist.size(); i < size; ++i) { - mons_list mlist; - const std::string err = mlist.add_mons(spec); - if (!err.empty()) - luaL_error(ls, err.c_str()); - - for (int i = 0, size = mlist.size(); i < size; ++i) + mons_spec mspec = mlist.get_monster(i); + if (dgn_place_monster(mspec, you.your_level, c, + false, false, false)) { - mons_spec mspec = mlist.get_monster(i); - if (dgn_place_monster(mspec, you.your_level, c, - false, false, false)) - { - push_monster(ls, &menv[mgrd(c)]); - return (1); - } + push_monster(ls, &menv[mgrd(c)]); + return (1); } } lua_pushnil(ls); return (1); } +static int _dgn_monster_spec(lua_State *ls) +{ + const mons_list mlist = _lua_get_mlist(ls, 1); + _push_object_type<mons_list>(ls, MONSLIST_METATABLE, mlist); + return (1); +} + +static int _dgn_item_spec(lua_State *ls) +{ + const item_list ilist = _lua_get_ilist(ls, 1); + _push_object_type<item_list>(ls, ITEMLIST_METATABLE, ilist); + return (1); +} + +LUARET1(_dgn_max_monsters, number, MAX_MONSTERS) + static int dgn_create_item(lua_State *ls) { COORDS(c, 1, 2); - if (const char *spec = lua_tostring(ls, 3)) - { - item_list ilist; - const std::string err = ilist.add_item(spec); - if (!err.empty()) - luaL_error(ls, err.c_str()); - - const int level = - lua_isnumber(ls, 4) ? lua_tointeger(ls, 4) : you.your_level; + item_list ilist = _lua_get_ilist(ls, 3); + const int level = + lua_isnumber(ls, 4) ? lua_tointeger(ls, 4) : you.your_level; - dgn_place_multiple_items(ilist, c, level); - link_items(); - } + dgn_place_multiple_items(ilist, c, level); + link_items(); return (0); } @@ -2672,6 +2692,11 @@ static const struct luaL_reg dgn_lib[] = { "create_monster", dgn_create_monster }, { "create_item", dgn_create_item }, + { "monster_spec", _dgn_monster_spec }, + { "item_spec", _dgn_item_spec }, + + { "max_monsters", _dgn_max_monsters }, + { "with_map_bounds_fn", dgn_with_map_bounds_fn }, { "with_map_anchors", dgn_with_map_anchors }, @@ -2703,14 +2728,32 @@ static const struct luaL_reg dgn_lib[] = { NULL, NULL } }; -static int crawl_args(lua_State *ls) +LUAFN(_crawl_args) { return dlua_stringtable(ls, SysEnv.cmd_args); } +#ifdef UNIX +LUAFN(_crawl_millis) +{ + struct timeval tv; + struct timezone tz; + const int error = gettimeofday(&tv, &tz); + if (error) + luaL_error(ls, make_stringf("Failed to get time: %s", + strerror(error)).c_str()); + + lua_pushnumber(ls, tv.tv_sec * 1000 + tv.tv_usec / 1000); + return (1); +} +#endif + static const struct luaL_reg crawl_lib[] = { - { "args", crawl_args }, + { "args", _crawl_args }, +#ifdef UNIX + { "millis", _crawl_millis }, +#endif { NULL, NULL } }; @@ -2949,6 +2992,62 @@ static int mapmarker_move(lua_State *ls) return (0); } +static mons_list _lua_get_mlist(lua_State *ls, int ndx) +{ + if (lua_isstring(ls, ndx)) + { + const char *spec = lua_tostring(ls, ndx); + mons_list mlist; + const std::string err = mlist.add_mons(spec); + if (!err.empty()) + luaL_error(ls, err.c_str()); + return (mlist); + } + else + { + mons_list **mlist( + clua_get_userdata<mons_list*>(ls, MONSLIST_METATABLE, ndx)); + if (mlist) + return (**mlist); + + luaL_argerror(ls, ndx, "Expected monster list object or string"); + return mons_list(); + } +} + +static item_list _lua_get_ilist(lua_State *ls, int ndx) +{ + if (lua_isstring(ls, ndx)) + { + const char *spec = lua_tostring(ls, ndx); + + item_list ilist; + const std::string err = ilist.add_item(spec); + if (!err.empty()) + luaL_error(ls, err.c_str()); + + return (ilist); + } + else + { + item_list **ilist( + clua_get_userdata<item_list*>(ls, ITEMLIST_METATABLE, ndx)); + if (ilist) + return (**ilist); + + luaL_argerror(ls, ndx, "Expected item list object or string"); + return item_list(); + } +} + +static void _register_mapdef_tables(lua_State *ls) +{ + clua_register_metatable(ls, MONSLIST_METATABLE, NULL, + lua_object_gc<mons_list>); + clua_register_metatable(ls, ITEMLIST_METATABLE, NULL, + lua_object_gc<item_list>); +} + static const struct luaL_reg mapmarker_lib[] = { { "pos", mapmarker_pos }, @@ -2980,6 +3079,8 @@ void init_dungeon_lua() luaopen_dgnevent(dlua); luaopen_mapmarker(dlua); + + _register_mapdef_tables(dlua); } // Can be called from within a debugger to look at the current Lua diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc index 79342c2e84..6dacc24f2b 100644 --- a/crawl-ref/source/monstuff.cc +++ b/crawl-ref/source/monstuff.cc @@ -887,8 +887,11 @@ void monster_die(monsters *monster, killer_type killer, const bool gives_xp = !mons_is_summoned(monster) && !mons_enslaved_body_and_soul(monster); - bool in_transit = false; - bool drop_items = !hard_reset && !mons_is_holy(monster); + const bool drop_items = !hard_reset && !mons_is_holy(monster); + + const bool mons_reset( killer == KILL_RESET || killer == KILL_DISMISSED ); + + bool in_transit = false; #ifdef DGL_MILESTONES _check_kill_milestone(monster, killer, killer_index); @@ -905,7 +908,7 @@ void monster_die(monsters *monster, killer_type killer, killer = KILL_YOU_CONF; // Well, it was confused in a sense... (jpeg) // Take note! - if (killer != KILL_RESET && killer != KILL_DISMISSED) + if (!mons_reset) { if (MONST_INTERESTING(monster)) { @@ -961,7 +964,7 @@ void monster_die(monsters *monster, killer_type killer, else if (monster->type == MONS_FIRE_VORTEX || monster->type == MONS_SPATIAL_VORTEX) { - if (!silent && killer != KILL_RESET) + if (!silent && !mons_reset) { simple_monster_message( monster, " dissipates!", MSGCH_MONSTER_DAMAGE, MDAM_DEAD ); @@ -969,7 +972,7 @@ void monster_die(monsters *monster, killer_type killer, } if (monster->type == MONS_FIRE_VORTEX && !wizard - && killer != KILL_RESET) + && !mons_reset) { place_cloud(CLOUD_FIRE, monster->pos(), 2 + random2(4), monster->kill_alignment()); @@ -981,14 +984,14 @@ void monster_die(monsters *monster, killer_type killer, else if (monster->type == MONS_SIMULACRUM_SMALL || monster->type == MONS_SIMULACRUM_LARGE) { - if (!silent && killer != KILL_RESET) + if (!silent && !mons_reset) { simple_monster_message( monster, " vapourises!", MSGCH_MONSTER_DAMAGE, MDAM_DEAD ); silent = true; } - if (!wizard && killer != KILL_RESET) + if (!wizard && !mons_reset) place_cloud(CLOUD_COLD, monster->pos(), 2 + random2(4), monster->kill_alignment()); @@ -1366,9 +1369,9 @@ void monster_die(monsters *monster, killer_type killer, break; case KILL_RESET: - // Monster doesn't die, just goes back to wherever it came from - // This must only be called by monsters running out of time (or - // abjuration), because it uses the beam variables! Or does it??? + // Monster doesn't die, just goes back to wherever it came from + // This must only be called by monsters running out of time (or + // abjuration), because it uses the beam variables! Or does it??? if (!silent) { simple_monster_message( monster, @@ -1433,7 +1436,7 @@ void monster_die(monsters *monster, killer_type killer, } } - if (killer != KILL_RESET && killer != KILL_DISMISSED) + if (!mons_reset) { you.kills->record_kill(monster, killer, pet_kill); |