require("clua/point.lua")
dgn.GXM, dgn.GYM = dgn.max_bounds()
dgn.MAX_MONSTERS = dgn.max_monsters()
dgn.f_map = { }
dgn.persist = { }
function dgn_save_data(th)
lmark.marshall_table(th, dgn.persist)
end
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
function dgn.monster_fn(spec)
local mspec = dgn.monster_spec(spec)
return function (x, y)
return dgn.create_monster(x, y, mspec)
end
end
function dgn.find_feature_number(name_num)
if type(name_num) == "number" then
return name_num
else
return dgn.fnum(name_num)
end
end
function dgn_map_meta_wrap(map, tab)
if not dgn._map_envs then
dgn._map_envs = { }
end
local name = dgn.name(map)
local meta = dgn._map_envs[name]
if not meta then
meta = { }
local meta_meta = { __index = _G }
setmetatable(meta, meta_meta)
dgn._map_envs[name] = meta
end
for fn, val in pairs(tab) do
meta[fn] = function (...)
return crawl.err_trace(val, map, ...)
end
end
meta['mapgrd'] = dgn.mapgrd_table(map)
meta['_G'] = meta
meta.wrapped_instance = map
return meta
end
function dgn_flush_map_environments()
dgn._map_envs = nil
end
function dgn_set_map(map)
g_dgn_curr_map = map
end
function dgn_run_map(prelude, map, main)
if prelude or map or main then
local env = dgn_map_meta_wrap(g_dgn_curr_map, dgn)
local ret
if prelude then
ret = setfenv(prelude, env)()
end
if map then
ret = setfenv(map, env)()
dgn.normalise(g_dgn_curr_map)
end
if main then
ret = setfenv(main, env)()
end
return ret
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.any_glyph_connected(map, ...)
return dgn.places_connected(map, dgn.gly_points,
dgn.any_point_connected, ...)
end
function dgn.has_exit_from_glyph(map, glyph)
return dgn.places_connected(map, dgn.gly_point, dgn.has_exit_from, glyph)
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
function dgn.fnum(feat)
if type(feat) == 'string' then
return dgn.feature_number(feat)
else
return feat
end
end
function dgn.fnum_map(map)
local fnmap = { }
for k, v in pairs(map) do
fnmap[dgn.fnum(k)] = dgn.fnum(v)
end
return fnmap
end
function dgn.replace_feat(rmap)
local cmap = dgn.fnum_map(rmap)
for x = 0, dgn.GXM - 1 do
for y = 0, dgn.GYM - 1 do
local grid = dgn.grid(x, y)
local repl = cmap[grid]
if repl then
dgn.terrain_changed(x, y, repl)
end
end
end
end
function dgn.passable_excluding(...)
local forbidden_features =
util.set(util.map(dgn.find_feature_number, { ... }))
return function (p)
local x, y = p.x, p.y
return dgn.is_passable(x, y) and
not forbidden_features[dgn.grid(x, y)]
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 = dgn.point(c.x + cp[1], 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)
c = dgn.point(c.x, c.y)
local mapped_points = { }
local function seen(p)
return mapped_points[p:str()]
end
local function record(p, val)
mapped_points[p:str()] = 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
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
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(dgn.point(x, y)) then
dgn.colour_at(x, y, colour)
end
end
end
end
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
function dgn.gridmark(x, y, grid, marker)
dgn.grid(x, y, grid)
if marker then
local t = type(marker)
if t == "function" or t == "table" then
dgn.register_lua_marker(x, y, marker)
else
dgn.register_feature_marker(x, y, marker)
end
end
end
function portal_stair_dst(dst)
return one_way_stair { dst = dst }
end
function portal_vault(e, tag)
if tag then
e.tags(tag)
end
e.orient("encompass")
end
function portal_next(e, next)
for _, feat in ipairs({ "]", ")", "}" }) do
e.lua_marker(feat, portal_stair_dst(next))
end
end
function persist_to_string()
return table_to_string(dgn.persist)
end
dgn.good_scrolls = [[
w:80 scroll of identify / scroll of identify q:2 w:30 /
scroll of identify q:3 w:10 /
w:80 scroll of teleportation / scroll of teleportation q:2 w:30 /
/ scroll of teleportation q:3 w:10 /
w:80 scroll of fog / scroll of fog q:2 w:30 / scroll of fog q:3 w:10 /
w:50 scroll of remove curse / scroll of remove curse q:2 w:20 /
w:50 scroll of enchant weapon I / scroll of enchant weapon I q:2 w:20 /
w:50 scroll of enchant weapon II / scroll of enchant weapon II q:2 w:20 /
w:50 scroll of blinking / scroll of blinking q:2 w:20 /
w:50 scroll of enchant armour / scroll of enchant armour q:2 w:20 /
w:50 scroll of recharging / scroll of recharging q:2 w:20 /
w:50 scroll of silence / scroll of silence q:2 w:20 /
w:20 scroll of magic mapping / scroll of magic mapping q:2 w:10 /
w:20 scroll of detect curse / scroll of detect curse q:2 w:10 /
w:20 scroll of holy word / scroll of holy word q:2 w:10 /
w:20 scroll of enchant weapon III / scroll of enchant weapon III q:2 w:10 /
w:10 scroll of acquirement / scroll of acquirement q:2 w:4 /
scroll of acquirement q:3 w:1/
w:5 scroll of vorpalise weapon /
w:5 scroll of immolation /
w:5 scroll of vulnerability
]]