diff options
author | dshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573> | 2008-11-23 18:58:31 +0000 |
---|---|---|
committer | dshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573> | 2008-11-23 18:58:31 +0000 |
commit | be8748fa444e6813e09ef959f5ee4b88b67dd68e (patch) | |
tree | 0ed8640d1756cbfbd02091d0c74d7b47a7b0eec8 /crawl-ref/source | |
parent | 1392155c0cb7acb6224a39611102e46460a06e5b (diff) | |
download | crawl-ref-be8748fa444e6813e09ef959f5ee4b88b67dd68e.tar.gz crawl-ref-be8748fa444e6813e09ef959f5ee4b88b67dd68e.zip |
More steps toward ziggurats.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7553 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source')
-rw-r--r-- | crawl-ref/source/abyss.cc | 4 | ||||
-rw-r--r-- | crawl-ref/source/cloud.cc | 34 | ||||
-rw-r--r-- | crawl-ref/source/clua.cc | 78 | ||||
-rw-r--r-- | crawl-ref/source/clua.h | 2 | ||||
-rw-r--r-- | crawl-ref/source/dat/clua/dungeon.lua | 105 | ||||
-rw-r--r-- | crawl-ref/source/dat/clua/util.lua | 67 | ||||
-rw-r--r-- | crawl-ref/source/dat/clua/ziggurat.lua | 247 | ||||
-rw-r--r-- | crawl-ref/source/dungeon.cc | 19 | ||||
-rw-r--r-- | crawl-ref/source/dungeon.h | 5 | ||||
-rw-r--r-- | crawl-ref/source/food.cc | 11 | ||||
-rw-r--r-- | crawl-ref/source/luadgn.cc | 200 | ||||
-rw-r--r-- | crawl-ref/source/makeitem.cc | 4 | ||||
-rw-r--r-- | crawl-ref/source/mapdef.cc | 1 | ||||
-rw-r--r-- | crawl-ref/source/mapdef.h | 3 | ||||
-rw-r--r-- | crawl-ref/source/mon-pick.cc | 4 | ||||
-rw-r--r-- | crawl-ref/source/monplace.cc | 24 | ||||
-rw-r--r-- | crawl-ref/source/monplace.h | 3 | ||||
-rw-r--r-- | crawl-ref/source/traps.cc | 34 | ||||
-rw-r--r-- | crawl-ref/source/travel.cc | 13 | ||||
-rw-r--r-- | crawl-ref/source/travel.h | 4 |
20 files changed, 678 insertions, 184 deletions
diff --git a/crawl-ref/source/abyss.cc b/crawl-ref/source/abyss.cc index 34a44c16ad..5f84370253 100644 --- a/crawl-ref/source/abyss.cc +++ b/crawl-ref/source/abyss.cc @@ -681,9 +681,7 @@ static bool _spawn_corrupted_servant_near(const coord_def &pos) } // Got a place, summon the beast. - int level = 51; - monster_type mons = pick_random_monster(level_id(LEVEL_ABYSS), level, - level); + monster_type mons = pick_random_monster(level_id(LEVEL_ABYSS)); if (mons == MONS_PROGRAM_BUG) return (false); diff --git a/crawl-ref/source/cloud.cc b/crawl-ref/source/cloud.cc index 5c1f6a7512..daed16067d 100644 --- a/crawl-ref/source/cloud.cc +++ b/crawl-ref/source/cloud.cc @@ -815,22 +815,7 @@ bool valid_fog_machine_data(fog_machine_data data) int num_fogs_for_place(int level_number, const level_id &place) { if (level_number == -1) - { - switch(place.level_type) - { - case LEVEL_DUNGEON: - level_number = absdungeon_depth(place.branch, place.depth); - break; - case LEVEL_ABYSS: - level_number = 51; - break; - case LEVEL_PANDEMONIUM: - level_number = 52; - break; - default: - level_number = you.your_level; - } - } + level_number = place.absdepth(); switch(place.level_type) { @@ -865,22 +850,7 @@ fog_machine_data random_fog_for_place(int level_number, const level_id &place) fog_machine_data data = {NUM_FOG_MACHINE_TYPES, CLOUD_NONE, -1, -1}; if (level_number == -1) - { - switch(place.level_type) - { - case LEVEL_DUNGEON: - level_number = absdungeon_depth(place.branch, place.depth); - break; - case LEVEL_ABYSS: - level_number = 51; - break; - case LEVEL_PANDEMONIUM: - level_number = 52; - break; - default: - level_number = you.your_level; - } - } + level_number = place.absdepth(); switch(place.level_type) { diff --git a/crawl-ref/source/clua.cc b/crawl-ref/source/clua.cc index c0c6e6845f..fac00a74dd 100644 --- a/crawl-ref/source/clua.cc +++ b/crawl-ref/source/clua.cc @@ -32,6 +32,7 @@ #include "macro.h" #include "mapdef.h" #include "message.h" +#include "monstuff.h" #include "mon-util.h" #include "newgame.h" #include "output.h" @@ -636,6 +637,8 @@ void CLua::init_lua() lua_register(_state, "loadfile", _clua_loadfile); lua_register(_state, "dofile", _clua_dofile); + execfile("clua/util.lua", true, true); + if (managed_vm) { lua_register(_state, "pcall", _clua_guarded_pcall); @@ -945,6 +948,17 @@ void lua_set_exclusive_item(const item_def *item) excl_item = item; } +void lua_push_items(lua_State *ls, int link) +{ + lua_newtable(ls); + int index = 0; + for ( ; link != NON_ITEM; link = mitm[link].link) + { + lua_pushlightuserdata(ls, &mitm[link]); + lua_rawseti(ls, -2, ++index); + } +} + static int l_item_inventory(lua_State *ls) { lua_push_inv_items(ls); @@ -2382,22 +2396,65 @@ struct MonsterWrap long turn; }; -static int l_mons_name(lua_State *ls, monsters *mons, const char *attr) +#define MDEF(name) \ + static int l_mons_##name(lua_State *ls, monsters *mons, \ + const char *attr) \ + +#define MDEFN(name, closure) \ + static int l_mons_##name(lua_State *ls, monsters *mons, const char *attrs) \ + { \ + lua_pushlightuserdata(ls, mons); \ + lua_pushcclosure(ls, l_mons_do_dismiss, 1); \ + return (1); \ + } + +#define ASSERT_DLUA \ + do { \ + if (CLua::get_vm(ls).managed_vm) \ + luaL_error(ls, "Operation forbidden in end-user script"); \ + } while (false) + +MDEF(name) { - lua_pushstring(ls, mons_type_name(mons->type, DESC_PLAIN).c_str()); - return (1); + PLUARET(string, mons_type_name(mons->type, DESC_PLAIN).c_str()); } -static int l_mons_x(lua_State *ls, monsters *mons, const char *attr) +MDEF(x) { - lua_pushnumber(ls, int(mons->pos().x) - int(you.pos().x)); - return (1); + PLUARET(number, int(mons->pos().x) - int(you.pos().x)); } -static int l_mons_y(lua_State *ls, monsters *mons, const char *attr) +MDEF(y) { - lua_pushnumber(ls, int(mons->pos().y) - int(you.pos().y)); - return (1); + PLUARET(number, int(mons->pos().y) - int(you.pos().y)); +} + +MDEF(hd) +{ + PLUARET(number, mons->hit_dice); +} + +static int l_mons_do_dismiss(lua_State *ls) +{ + // dismiss is only callable from dlua, not from managed VMs (i.e. + // end-user scripts cannot dismiss monsters). + ASSERT_DLUA; + monsters *mons = + util_get_userdata<monsters>(ls, lua_upvalueindex(1)); + if (mons->alive()) + { + mons->flags |= MF_HARD_RESET; + monster_die(mons, KILL_DISMISSED, NON_MONSTER); + } + return (0); +} + +MDEFN(dismiss, do_dismiss) + +MDEF(experience) +{ + ASSERT_DLUA; + PLUARET(number, exper_value(mons)); } struct MonsAccessor @@ -2411,6 +2468,9 @@ static MonsAccessor mons_attrs[] = { "name", l_mons_name }, { "x" , l_mons_x }, { "y" , l_mons_y }, + { "hd" , l_mons_hd }, + { "dismiss", l_mons_dismiss }, + { "experience", l_mons_experience }, }; static int monster_get(lua_State *ls) diff --git a/crawl-ref/source/clua.h b/crawl-ref/source/clua.h index a2de0f4f2c..e1499675a8 100644 --- a/crawl-ref/source/clua.h +++ b/crawl-ref/source/clua.h @@ -280,6 +280,8 @@ class dgn_event; void clua_push_map(lua_State *ls, map_def *map); void clua_push_dgn_event(lua_State *ls, const dgn_event *devent); +void lua_push_items(lua_State *ls, int link); + template <class T> T *clua_new_userdata( lua_State *ls, const char *mt) { diff --git a/crawl-ref/source/dat/clua/dungeon.lua b/crawl-ref/source/dat/clua/dungeon.lua index 66148a3708..2736e1f372 100644 --- a/crawl-ref/source/dat/clua/dungeon.lua +++ b/crawl-ref/source/dat/clua/dungeon.lua @@ -4,8 +4,8 @@ ------------------------------------------------------------------------------ dgn.GXM, dgn.GYM = dgn.max_bounds() -dgn.f_rockwall = dgn.feature_number("rock_wall") -dgn.f_floor = dgn.feature_number("floor") + +dgn.f_map = { } -- Table that will be saved in <foo>.sav. dgn.persist = { } @@ -18,6 +18,15 @@ function dgn_load_data(th) dgn.persist = lmark.unmarshall_table(th) or { } end +function dgn.fnum(name) + local fnum = dgn.f_map[name] + if not fnum then + fnum = dgn.feature_number(name) + dgn.f_map[name] = fnum + end + return fnum +end + -- Wraps a map_def into a Lua environment (a table) such that -- functions run in the environment (with setfenv) can directly -- address the map with function calls such as name(), tags(), etc. @@ -34,7 +43,7 @@ function dgn_map_meta_wrap(map, tab) if not meta then meta = { } - + local meta_meta = { __index = _G } setmetatable(meta, meta_meta) dgn._map_envs[name] = meta @@ -94,7 +103,7 @@ function dgn.places_connected(map, map_glyph, test_connect, ...) end function dgn.any_glyph_connected(map, ...) - return dgn.places_connected(map, dgn.gly_points, + return dgn.places_connected(map, dgn.gly_points, dgn.any_point_connected, ...) end @@ -144,7 +153,7 @@ function dgn.fnum_map(map) return fnmap end --- Replaces all features matching +-- Replaces all features matching function dgn.replace_feat(rmap) local cmap = dgn.fnum_map(rmap) @@ -159,6 +168,92 @@ function dgn.replace_feat(rmap) end end +function dgn.adjacent_points(c, faccept) + local plist = { } + + local compass = { + { 0, -1 }, { 1, 0 }, { 0, 1 }, { -1, 0 }, + { -1, -1 }, { 1, -1 }, { 1, 1 }, { -1, 1 } + } + + for _, cp in ipairs(compass) do + local p = { x = c.x + cp[1], y = c.y + cp[2] } + if dgn.in_bounds(p.x, p.y) and faccept(p) then + table.insert(plist, p) + end + end + return plist +end + +function dgn.find_adjacent_point(c, fcondition, fpassable) + local mapped_points = { } + + local function pstr(p) + return p.x .. "," .. p.y + end + + local function seen(p) + return mapped_points[pstr(p)] + end + + local function record(p, val) + mapped_points[pstr(p)] = val or 1 + end + + if not fpassable then + fpassable = function (p) + return dgn.is_passable(p.x, p.y) + end + end + + local iter_points = { { }, { } } + local iter = 1 + table.insert(iter_points[iter], c) + + local function next_iter() + if iter == 1 then + return 2 + else + return 1 + end + end + + local distance = 1 + record(c, distance) + + while #iter_points[iter] > 0 do + for _, p in ipairs(iter_points[iter]) do + if fcondition(p) then + return p + end + + -- Add adjacent points to queue. + for _, np in ipairs(dgn.adjacent_points(p, fpassable)) do + if not seen(np) then + table.insert(iter_points[next_iter()], np) + record(np, distance + 1) + end + end + end + iter_points[iter] = { } + iter = next_iter() + distance = distance + 1 + end + + -- No suitable point. + return nil +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 + dgn.colour_at(x, y, colour) + end + end + end +end + ---------------------------------------------------------------------- -- Convenience functions for vaults. diff --git a/crawl-ref/source/dat/clua/util.lua b/crawl-ref/source/dat/clua/util.lua new file mode 100644 index 0000000000..0c327fd194 --- /dev/null +++ b/crawl-ref/source/dat/clua/util.lua @@ -0,0 +1,67 @@ +------------------------------------------------------------------------------ +-- util.lua +-- Lua utilities. +------------------------------------------------------------------------------ + +util = { } + +function util.catlist(...) + local res = { } + local tables = { ... } + if #tables == 1 then + return tables[1] + else + for _, tab in ipairs(tables) do + for _, val in ipairs(tab) do + table.insert(res, val) + end + end + end + return res +end + +function util.cathash(...) + local res = { } + local tables = { ... } + if #tables == 1 then + return tables[1] + else + for _, tab in ipairs(tables) do + for key, val in ipairs(tab) do + res[key] = val + end + end + end + return res +end + +function util.map(fn, ...) + local lists = { ... } + local res = { } + if #lists == 0 then + return res + elseif #lists == 1 then + for _, val in ipairs(lists[1]) do + table.insert(res, fn(val)) + end + else + for i = 1, #lists[1] do + local args = { } + for _, list in ipairs(lists) do + if not list[i] then + break + end + table.insert(args, list[i]) + end + if #args < #lists then + break + end + table.insert(res, fn(unpack(args))) + end + end + return res +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 1b8439a0cf..8629eeabd3 100644 --- a/crawl-ref/source/dat/clua/ziggurat.lua +++ b/crawl-ref/source/dat/clua/ziggurat.lua @@ -17,18 +17,34 @@ function zig() return dgn.persist.ziggurat end --- Returns a function that changes the depth in the ziggurat to the depth --- specified. -local function zig_depth_increment() - return function (...) - zig().depth = zig().depth + 1 - end +local wall_colours = { + "blue", "red", "lightblue", "magenta", "green", "white" +} + +local function wall_colour() + return util.random_from(wall_colours) +end + +local function random_floor_colour() + return wall_colour() end function ziggurat_initializer() local z = zig() z.depth = 1 + + -- Any given ziggurat will use the same builder for all its levels. z.builder = ziggurat_choose_builder() + + z.colour = wall_colour() + z.level = { } +end + +-- Returns a function that changes the depth in the ziggurat to the depth +-- specified. +function zig_depth_increment() + zig().depth = zig().depth + 1 + zig().level = { } end -- Returns the current depth in the ziggurat. @@ -84,24 +100,225 @@ end -- Creates a Lua marker table that increments ziggurat depth. local function zig_go_deeper() return one_way_stair { - onclimb = zig_depth_increment() + onclimb = zig_depth_increment } end +local function map_area() + local base_area = 20 + 8 * zig_depth() + return 2 * base_area + crawl.random2(base_area) +end + +local function clamp_in(val, low, high) + if val < low then + return low + elseif val > high then + return high + else + return val + end +end + +local function clamp_in_bounds(x, y) + return clamp_in(x, 1, dgn.GXM - 2), clamp_in(y, 1, dgn.GYM - 2) +end + +local function rectangle_dimensions() + local area = map_area() + + local cx, cy = dgn.GXM / 2, dgn.GYM / 2 + + local asqrt = math.sqrt(area) + local b = crawl.random_range(1 + asqrt / 2, asqrt + 1) + local a = math.floor((area + b - 1) / b) + + local a2 = math.floor(a / 2) + (a % 2); + local b2 = math.floor(b / 2) + (b % 2); + local x1, y1 = clamp_in_bounds(cx - a2, cy - b2) + local x2, y2 = clamp_in_bounds(cx + a2, cy + b2) + return x1, y1, x2, y2 +end + +local mons_populations = { + "Elf:7", "Orc:4", "Vault:8", "Slime:6", + "Snake:5", "Lair:10", "Tomb:3", "Crypt:5", + "Abyss", "Shoal:5", "Pan" +} + +local function set_floor_colour(colour) + if not zig().level.floor_colour then + zig().level.floor_colour = colour + dgn.change_floor_colour(colour) + end +end + +local function set_random_floor_colour() + set_floor_colour( random_floor_colour() ) +end + +local function mons_random_gen(x, y, nth) + set_random_floor_colour() + return dgn.create_monster(x, y, "place:" .. + util.random_from(mons_populations)) +end + +local function mons_drac_gen(x, y, nth) + set_random_floor_colour() + return dgn.create_monster(x, y, "random draconian") +end + +local function mons_panlord_gen(x, y, nth) + set_random_floor_colour() + if nth == 1 then + return dgn.create_monster(x, y, "pandemonium lord band") + else + return dgn.create_monster(x, y, "place:Pan") + end +end + +local mons_generators = { + mons_random_gen, + mons_drac_gen, + mons_panlord_gen +} + +local function monster_creator_fn(arg) + if type(arg) == "string" then + local _, _, branch = string.find(arg, "^(%w+):") + return function (x, y, nth) + if branch then + set_floor_colour(dgn.br_floorcol(branch)) + end + + return dgn.create_monster(x, y, "place:" .. arg) + end + else + return arg + end +end + +local monster_creators = + util.map(monster_creator_fn, util.catlist(mons_populations, mons_generators)) + +local function ziggurat_vet_monster(fn) + return function (x, y, nth) + while true do + local mons = fn(x, y, nth) + if mons then + if mons.experience == 0 then + mons.dismiss() + else + -- Monster is ok! + return mons + end + end + end + end +end + +local function choose_monster_set() + return ziggurat_vet_monster(util.random_from(monster_creators)) +end + +local function ziggurat_create_monsters(p) + 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 mfn = choose_monster_set() + local nth = 1 + + -- No monsters + while hd_pool > 0 do + local place = dgn.find_adjacent_point(p, mons_place_p) + local mons = mfn(place.x, place.y, nth) + + if mons then + nth = nth + 1 + hd_pool = hd_pool - mons.hd + end + end +end + +local function flip_rectangle(x1, y1, x2, y2) + local cx = math.floor((x1 + x2) / 2) + local cy = math.floor((y1 + y2) / 2) + local nx1 = cx + y1 - cy + local nx2 = cx + y2 - cy + local ny1 = cy + x1 - cx + local ny2 = cy + x2 - cx + return { nx1, ny1, nx2, ny2 } +end + +local function ziggurat_create_loot(c) + local nloot = zig_depth() + local depth = zig_depth() + + local function is_free_space(p) + return dgn.grid(p.x, p.y) == dgn.fnum("floor") and + #dgn.items_at(p.x, p.y) == 0 + end + + local function free_space_do(fn) + local p = dgn.find_adjacent_point(c, is_free_space) + if p then + fn(p) + end + end + + for i = 1, nloot do + if crawl.one_chance_in(depth) then + for j = 1, 4 do + free_space_do(function (p) + dgn.create_item(p.x, p.y, "*", 20) + end) + end + else + free_space_do(function (p) + dgn.create_item(p.x, p.y, "|", 20) + end) + end + end +end + local function ziggurat_rectangle_builder(e) local grid = dgn.grid - -- FIXME: Cool code goes here. - local x1, y1 = 20, 20 - local x2, y2 = dgn.GXM - 20, dgn.GYM - 20 + dgn.fill_area(0, 0, dgn.GXM - 1, dgn.GYM - 1, "stone_wall") + + local x1, y1, x2, y2 = rectangle_dimensions() dgn.fill_area(x1, y1, x2, y2, "floor") - local my = math.floor((y1 + y2) / 2) - zigstair(x1, my, "stone_arch", "stone_stairs_up_i") - zigstair(x2, my, "stone_stairs_down_i", zig_go_deeper) - grid(x2, my + 1, "exit_portal_vault") + dgn.fill_area(unpack( util.catlist(flip_rectangle(x1, y1, x2, y2), + { "floor" }) ) ) + + local cy = math.floor((y1 + y2) / 2) + + local entry = { x = x1, y = cy } + local exit = { x = x2, y = cy } + + if zig_depth() % 2 == 0 then + entry, exit = exit, entry + end + + zigstair(entry.x, entry.y, "stone_arch", "stone_stairs_up_i") + zigstair(exit.x, exit.y, "stone_stairs_down_i", zig_go_deeper) + grid(exit.x, exit.y + 1, "exit_portal_vault") + grid(exit.x, exit.y - 1, "exit_portal_vault") + + 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) - crawl.mpr("Ziggurat depth is now " .. zig_depth()) + crawl.mpr("Ziggurat depth is now " .. zig_depth(), "diagnostic") end ---------------------------------------------------------------------- diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 9d8bc2c6f7..f78a65de55 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -4759,8 +4759,8 @@ static void _dgn_place_item_explicit(const item_spec &spec, grd(where) = DNGN_FLOOR; } -static void _dgn_place_multiple_items(item_list &list, - const coord_def& where, int level) +void dgn_place_multiple_items(item_list &list, + const coord_def& where, int level) { const int size = list.size(); for (int i = 0; i < size; ++i) @@ -4885,6 +4885,7 @@ bool dgn_place_monster(mons_spec &mspec, const int mid = mspec.mid; const bool m_generate_awake = (generate_awake || mspec.generate_awake); const bool m_patrolling = (patrolling || mspec.patrolling); + const bool m_band = mspec.band; const int mlev = mspec.mlevel; if (mlev) @@ -4924,7 +4925,7 @@ bool dgn_place_monster(mons_spec &mspec, int lev = monster_level; if (mspec.place.level_type == LEVEL_DUNGEON) - lev = absdungeon_depth(mspec.place.branch, mspec.place.depth); + lev = mspec.place.absdepth(); if (mlev == -8) lev = 4 + lev * 2; @@ -4966,12 +4967,12 @@ bool dgn_place_monster(mons_spec &mspec, if (m_patrolling) mg.flags |= MG_PATROLLING; + if (m_band) + mg.flags |= MG_PERMIT_BANDS; + const int mindex = place_monster(mg, true); - if (mindex != -1) - { - if (mspec.items.size() > 0) - _dgn_give_mon_spec_items(mspec, mindex, mid, monster_level); - } + if (mindex != -1 && mspec.items.size() > 0) + _dgn_give_mon_spec_items(mspec, mindex, mid, monster_level); return (mindex != -1); } return (false); @@ -5123,7 +5124,7 @@ static int _vault_grid( vault_placement &place, _dgn_place_one_monster(place, mons, level_number, where); item_list &items = mapsp->get_items(); - _dgn_place_multiple_items(items, where, level_number); + dgn_place_multiple_items(items, where, level_number); return (altar_count); } diff --git a/crawl-ref/source/dungeon.h b/crawl-ref/source/dungeon.h index 756c431ab3..ece814c54f 100644 --- a/crawl-ref/source/dungeon.h +++ b/crawl-ref/source/dungeon.h @@ -331,6 +331,11 @@ bool dgn_place_monster(mons_spec &mspec, bool force_pos = false, bool generate_awake = false, bool patrolling = false); +class item_list; +void dgn_place_multiple_items(item_list &list, + const coord_def& where, + int level); + bool set_level_flags(unsigned long flags, bool silent = false); bool unset_level_flags(unsigned long flags, bool silent = false); diff --git a/crawl-ref/source/food.cc b/crawl-ref/source/food.cc index 14bbd41261..69a1cb036f 100644 --- a/crawl-ref/source/food.cc +++ b/crawl-ref/source/food.cc @@ -702,17 +702,6 @@ bool butchery(int which_corpse) return (success); } -void lua_push_items(lua_State *ls, int link) -{ - lua_newtable(ls); - int index = 0; - for ( ; link != NON_ITEM; link = mitm[link].link) - { - lua_pushlightuserdata(ls, &mitm[link]); - lua_rawseti(ls, -2, ++index); - } -} - void lua_push_floor_items(lua_State *ls) { lua_push_items(ls, igrd(you.pos())); diff --git a/crawl-ref/source/luadgn.cc b/crawl-ref/source/luadgn.cc index 229fc9946d..60834c3c64 100644 --- a/crawl-ref/source/luadgn.cc +++ b/crawl-ref/source/luadgn.cc @@ -26,6 +26,7 @@ #include "mapmark.h" #include "maps.h" #include "misc.h" +#include "mon-util.h" #include "spl-util.h" #include "stuff.h" #include "tags.h" @@ -315,6 +316,8 @@ std::string dlua_chunk::get_chunk_prefix(const std::string &sorig) const #define MAPMARKER(ls, n, var) \ map_marker *var = *(map_marker **) luaL_checkudata(ls, n, MAPMARK_METATABLE) +#define LUAFN(name) static int name(lua_State *ls) + static dungeon_feature_type _get_lua_feature(lua_State *ls, int idx) { dungeon_feature_type feat = (dungeon_feature_type)0; @@ -336,15 +339,19 @@ static dungeon_feature_type _check_lua_feature(lua_State *ls, int idx) return (f); } -#define COORDS(c, p1, p2) \ +#define GETCOORD(c, p1, p2, boundfn) \ coord_def c; \ c.x = luaL_checkint(ls, p1); \ c.y = luaL_checkint(ls, p2); \ - if (!in_bounds(c)) \ - luaL_error( \ + if (!boundfn(c)) \ + luaL_error( \ ls, \ - make_stringf("Point (%d,%d) is out of map bounds", \ - c.x, c.y).c_str()); + make_stringf("Point (%d,%d) is out of bounds", \ + c.x, c.y).c_str()); \ + else ; \ + +#define COORDS(c, p1, p2) \ + GETCOORD(c, p1, p2, in_bounds) #define FEAT(f, pos) \ dungeon_feature_type f = _check_lua_feature(ls, pos) @@ -908,7 +915,7 @@ static int dgn_welcome(lua_State *ls) static int dgn_grid(lua_State *ls) { - COORDS(c, 1, 2); + GETCOORD(c, 1, 2, map_bounds); if (!lua_isnone(ls, 3)) { @@ -1094,70 +1101,53 @@ static int dgn_get_rock_colour(lua_State *ls) PLUARET(string, colour_to_str(env.rock_colour).c_str()); } -static int dgn_change_floor_colour(lua_State *ls) +static int _lua_colour(lua_State *ls, int ndx, + int forbidden_colour = -1) { - const char *s = luaL_checkstring(ls, 1); - int colour = str_to_colour(s); - - if (colour < 0 || colour == BLACK) + if (lua_isnumber(ls, ndx)) + return lua_tonumber(ls, ndx); + else if (const char *s = luaL_checkstring(ls, ndx)) { - std::string error; + const int colour = str_to_colour(s); - if (colour == BLACK) - { - error = "Can't set floor to black."; - } - else + if (colour < 0 || colour == forbidden_colour) { - error = "No such colour as '"; - error += s; - error += "'"; + std::string error; + if (colour == forbidden_colour) + error = std::string("Can't set floor to ") + s; + else + error = std::string("Unknown colour: '") + s + "'"; + return luaL_argerror(ls, 1, error.c_str()); } - - luaL_argerror(ls, 1, error.c_str()); - - return (0); + return (colour); } + return luaL_argerror(ls, ndx, "Expected colour name or number"); +} +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); - return (0); } static int dgn_change_rock_colour(lua_State *ls) { - const char *s = luaL_checkstring(ls, 1); - int colour = str_to_colour(s); - - if (colour < 0 || colour == BLACK) - { - std::string error; - - if (colour == BLACK) - { - error = "Can't set rock to black."; - } - else - { - error = "No such colour as '"; - error += s; - error += "'"; - } - - luaL_argerror(ls, 1, error.c_str()); - - return (0); - } - + const int colour = _lua_colour(ls, 1, BLACK); env.rock_colour = (unsigned char) colour; - viewwindow(true, false); - return (0); } +static int dgn_colour_at(lua_State *ls) +{ + COORDS(c, 1, 2); + if (!lua_isnone(ls, 3)) + env.grid_colours(c) = _lua_colour(ls, 3); + PLUARET(string, colour_to_str(env.grid_colours(c)).c_str()); +} + const char *dngn_feature_names[] = { "unseen", "closed_door", "secret_door", "wax_wall", "metal_wall", @@ -1437,6 +1427,25 @@ static int dgn_mons_from_index(lua_State *ls) return (1); } +static int dgn_mons_at(lua_State *ls) +{ + COORDS(c, 1, 2); + + monsters *mon = monster_at(c); + if (mon && mon->alive()) + push_monster(ls, mon); + else + lua_pushnil(ls); + return (1); +} + +static int dgn_items_at(lua_State *ls) +{ + COORDS(c, 1, 2); + lua_push_items(ls, env.igrid(c)); + return (1); +} + static int lua_dgn_set_lt_callback(lua_State *ls) { const char *level_type = luaL_checkstring(ls, 1); @@ -2054,6 +2063,13 @@ static int dgn_fill_disconnected_zones(lua_State *ls) return 0; } +static int _dgn_is_passable(lua_State *ls) +{ + COORDS(c, 1, 2); + lua_pushboolean(ls, is_travelsafe_square(c.x, c.y, false, true)); + return (1); +} + static int dgn_register_feature_marker(lua_State *ls) { COORDS(c, 1, 2); @@ -2075,6 +2091,74 @@ static int dgn_register_lua_marker(lua_State *ls) return (0); } +static int dgn_create_monster(lua_State *ls) +{ + COORDS(c, 1, 2); + + if (const char *spec = lua_tostring(ls, 3)) + { + 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)) + { + push_monster(ls, &menv[mgrd(c)]); + return (1); + } + } + } + lua_pushnil(ls); + return (1); +} + +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; + + dgn_place_multiple_items(ilist, c, level); + link_items(); + } + return (0); +} + + +#define BRANCH(br, pos) \ + const char *branch_name = luaL_checkstring(ls, pos); \ + branch_type req_branch_type = str_to_branch(branch_name); \ + if (req_branch_type == NUM_BRANCHES) \ + luaL_error(ls, "Expected branch name"); \ + Branch &br = branches[req_branch_type] + +#define BRANCHFN(name, type, expr) \ + LUAFN(dgn_br_##name) { \ + BRANCH(br, 1); \ + PLUARET(type, expr); \ + } + +BRANCHFN(floorcol, number, br.floor_colour) +BRANCHFN(rockcol, number, br.rock_colour) +BRANCHFN(has_shops, boolean, br.has_shops) +BRANCHFN(has_uniques, boolean, br.has_uniques) +BRANCHFN(parent_branch, string, + br.parent_branch == NUM_BRANCHES ? "" + : branches[br.parent_branch].abbrevname) + static int dgn_debug_dump_map(lua_State *ls) { const int pos = lua_isuserdata(ls, 1) ? 2 : 1; @@ -2118,6 +2202,7 @@ static const struct luaL_reg dgn_lib[] = { "grid", dgn_grid }, { "max_bounds", dgn_max_bounds }, + { "colour_at", dgn_colour_at }, { "terrain_changed", dgn_terrain_changed }, { "points_connected", dgn_points_connected }, @@ -2138,6 +2223,8 @@ static const struct luaL_reg dgn_lib[] = { "feature_desc_at", dgn_feature_desc_at }, { "item_from_index", dgn_item_from_index }, { "mons_from_index", dgn_mons_from_index }, + { "mons_at", dgn_mons_at }, + { "items_at", dgn_items_at }, { "change_level_flags", dgn_change_level_flags }, { "change_branch_flags", dgn_change_branch_flags }, { "get_floor_colour", dgn_get_floor_colour }, @@ -2169,9 +2256,20 @@ static const struct luaL_reg dgn_lib[] = { "join_the_dots", dgn_join_the_dots }, { "fill_disconnected_zones", dgn_fill_disconnected_zones }, + { "is_passable", _dgn_is_passable }, + { "register_feature_marker", dgn_register_feature_marker }, { "register_lua_marker", dgn_register_lua_marker }, + { "create_monster", dgn_create_monster }, + { "create_item", dgn_create_item }, + + { "br_floorcol", dgn_br_floorcol }, + { "br_rockcol", dgn_br_rockcol }, + { "br_has_shops", dgn_br_has_shops }, + { "br_has_uniques", dgn_br_has_uniques }, + { "br_parent_branch", dgn_br_parent_branch }, + { "debug_dump_map", dgn_debug_dump_map }, { NULL, NULL } diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc index d992d0af7c..bf05dbe144 100644 --- a/crawl-ref/source/makeitem.cc +++ b/crawl-ref/source/makeitem.cc @@ -950,7 +950,9 @@ static bool _try_make_weapon_artefact(item_def& item, int force_type, #ifdef DEBUG_DIAGNOSTICS mprf(MSGCH_DIAGNOSTICS, "Making fixed artefact."); #endif - if (make_item_fixed_artefact( item, (item_level == 51) )) + if (make_item_fixed_artefact( + item, + (item_level == level_id(LEVEL_ABYSS).absdepth()) )) return (true); } diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc index 9058fde162..3ff9a014c6 100644 --- a/crawl-ref/source/mapdef.cc +++ b/crawl-ref/source/mapdef.cc @@ -1989,6 +1989,7 @@ mons_list::mons_spec_slot mons_list::parse_mons_spec(std::string spec) mspec.fix_mons = strip_tag(mon_str, "fix_mons"); mspec.generate_awake = strip_tag(mon_str, "generate_awake"); mspec.patrolling = strip_tag(mon_str, "patrolling"); + mspec.band = strip_tag(mon_str, "band"); // place:Elf:7 to choose monsters appropriate for that level, // for example. diff --git a/crawl-ref/source/mapdef.h b/crawl-ref/source/mapdef.h index 1b9dd721dc..8612eaae04 100644 --- a/crawl-ref/source/mapdef.h +++ b/crawl-ref/source/mapdef.h @@ -419,6 +419,7 @@ class mons_spec bool fix_mons; bool generate_awake; bool patrolling; + bool band; int colour; item_list items; @@ -430,7 +431,7 @@ class mons_spec bool _fixmons = false, bool awaken = false, bool patrol = false) : mid(id), place(), monbase(base), number(num), genweight(gw), mlevel(ml), fix_mons(_fixmons), generate_awake(awaken), - patrolling(false), colour(BLACK), items() + patrolling(false), band(false), colour(BLACK), items() { } }; diff --git a/crawl-ref/source/mon-pick.cc b/crawl-ref/source/mon-pick.cc index bb4e392c2e..d608352219 100644 --- a/crawl-ref/source/mon-pick.cc +++ b/crawl-ref/source/mon-pick.cc @@ -22,9 +22,9 @@ int mons_level(int mcls, const level_id &place) int monster_level = 0; if (place.level_type == LEVEL_ABYSS) - monster_level = ((mons_abyss(mcls)) ? 51 : 0); + monster_level = ((mons_abyss(mcls)) ? place.absdepth() : 0); else if (place.level_type == LEVEL_PANDEMONIUM) - monster_level = ((mons_pan(mcls)) ? 52 : 0); + monster_level = ((mons_pan(mcls)) ? place.absdepth() : 0); else if (place.level_type == LEVEL_DUNGEON) monster_level = branches[place.branch].mons_level_function(mcls); diff --git a/crawl-ref/source/monplace.cc b/crawl-ref/source/monplace.cc index 48f43a7b76..49769d06e4 100644 --- a/crawl-ref/source/monplace.cc +++ b/crawl-ref/source/monplace.cc @@ -262,6 +262,12 @@ void spawn_random_monsters() // No monsters in the Labyrinth, or the Ecumenical Temple, or in Bazaars. } +monster_type pick_random_monster(const level_id &place) +{ + int level = place.absdepth(); + return pick_random_monster(place, level, level); +} + monster_type pick_random_monster(const level_id &place, int power, int &lev_mons) { @@ -1906,16 +1912,14 @@ int mons_place( mgen_data mg ) // Translate level_type. switch (mg.level_type) { - case LEVEL_PANDEMONIUM: - mg.power = 52; // sigh.. - break; - case LEVEL_ABYSS: - mg.power = 51; - break; - case LEVEL_DUNGEON: - default: - mg.power = you.your_level; - break; + case LEVEL_PANDEMONIUM: + case LEVEL_ABYSS: + mg.power = level_id(mg.level_type).absdepth(); + break; + case LEVEL_DUNGEON: + default: + mg.power = you.your_level; + break; } int mid = place_monster(mg); diff --git a/crawl-ref/source/monplace.h b/crawl-ref/source/monplace.h index 0539686f95..bbb1c80ce4 100644 --- a/crawl-ref/source/monplace.h +++ b/crawl-ref/source/monplace.h @@ -254,6 +254,9 @@ int place_monster( mgen_data mg, bool force_pos = false ); * *********************************************************************** */ class level_id; + +monster_type pick_random_monster(const level_id &place); + monster_type pick_random_monster(const level_id &place, int power, int &lev_mons); diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc index 796b3f61f7..89f35f7a6c 100644 --- a/crawl-ref/source/traps.cc +++ b/crawl-ref/source/traps.cc @@ -1388,22 +1388,7 @@ static int num_traps_default(int level_number, const level_id &place) int num_traps_for_place(int level_number, const level_id &place) { if (level_number == -1) - { - switch(place.level_type) - { - case LEVEL_DUNGEON: - level_number = absdungeon_depth(place.branch, place.depth); - break; - case LEVEL_ABYSS: - level_number = 51; - break; - case LEVEL_PANDEMONIUM: - level_number = 52; - break; - default: - level_number = you.your_level; - } - } + level_number = place.absdepth(); switch (place.level_type) { @@ -1473,22 +1458,7 @@ static trap_type random_trap_default(int level_number, const level_id &place) trap_type random_trap_for_place(int level_number, const level_id &place) { if (level_number == -1) - { - switch (place.level_type) - { - case LEVEL_DUNGEON: - level_number = absdungeon_depth(place.branch, place.depth); - break; - case LEVEL_ABYSS: - level_number = 51; - break; - case LEVEL_PANDEMONIUM: - level_number = 52; - break; - default: - level_number = you.your_level; - } - } + level_number = place.absdepth(); switch (place.level_type) { diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc index 9d11cdb4b9..7291a98c78 100644 --- a/crawl-ref/source/travel.cc +++ b/crawl-ref/source/travel.cc @@ -3022,7 +3022,18 @@ level_id level_id::current() int level_id::absdepth() const { - return absdungeon_depth(branch, depth); + switch (level_type) + { + case LEVEL_DUNGEON: + return absdungeon_depth(branch, depth); + case LEVEL_PANDEMONIUM: + return 52; + case LEVEL_ABYSS: + return 51; + default: + // No true notion of depth here. + return you.your_level; + } } level_id level_id::get_next_level_id(const coord_def &pos) diff --git a/crawl-ref/source/travel.h b/crawl-ref/source/travel.h index 9f998ec188..c5a12529dc 100644 --- a/crawl-ref/source/travel.h +++ b/crawl-ref/source/travel.h @@ -225,6 +225,8 @@ public: level_type = LEVEL_DUNGEON; } + int absdepth() const; + bool is_valid() const { return (branch != NUM_BRANCHES && depth != -1) @@ -265,8 +267,6 @@ public: } - int absdepth() const; - void save(writer&) const; void load(reader&); }; |