summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authorEnne Walker <ennewalker@users.sourceforge.net>2009-11-02 08:51:09 -0500
committerEnne Walker <ennewalker@users.sourceforge.net>2009-11-02 09:00:06 -0500
commitf8f1e6fb68e2cfd7d725f4fdde94d6d45545f30b (patch)
tree260177da8227675fd57a7301f9a97c0c84c57cb2 /crawl-ref
parent0ba4567b4b44c9332bd978ef266f4af41c052779 (diff)
downloadcrawl-ref-f8f1e6fb68e2cfd7d725f4fdde94d6d45545f30b.tar.gz
crawl-ref-f8f1e6fb68e2cfd7d725f4fdde94d6d45545f30b.zip
Lua builder funcs act on map_lines, not grd.
This lets regular vaults use the same Lua functions that layout vaults do. Convert functions in l_dgnbld that acted on grd. Update layout vaults to use these new functions. Also, remove l_dgn_bf, as all of its functionality is now in l_dgnbld.
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/Crawl.xcodeproj/project.pbxproj6
-rw-r--r--crawl-ref/source/MSVC/crawl.vcproj4
-rw-r--r--crawl-ref/source/cluautil.h4
-rw-r--r--crawl-ref/source/dat/entry.des4
-rw-r--r--crawl-ref/source/dat/layout.des312
-rw-r--r--crawl-ref/source/dlua.cc2
-rw-r--r--crawl-ref/source/l_dgn_bf.cc225
-rw-r--r--crawl-ref/source/l_dgnbld.cc845
-rw-r--r--crawl-ref/source/makefile.obj1
-rw-r--r--crawl-ref/source/mapdef.cc81
-rw-r--r--crawl-ref/source/mapdef.h11
11 files changed, 882 insertions, 613 deletions
diff --git a/crawl-ref/source/Crawl.xcodeproj/project.pbxproj b/crawl-ref/source/Crawl.xcodeproj/project.pbxproj
index 49b76aeeb4..5b183caf87 100644
--- a/crawl-ref/source/Crawl.xcodeproj/project.pbxproj
+++ b/crawl-ref/source/Crawl.xcodeproj/project.pbxproj
@@ -412,7 +412,6 @@
B0F01D31108DDEBF00A53656 /* dlua.cc in Sources */ = {isa = PBXBuildFile; fileRef = B0F01D20108DDEBF00A53656 /* dlua.cc */; };
B0F01D32108DDEBF00A53656 /* l_crawl.cc in Sources */ = {isa = PBXBuildFile; fileRef = B0F01D22108DDEBF00A53656 /* l_crawl.cc */; };
B0F01D33108DDEBF00A53656 /* l_debug.cc in Sources */ = {isa = PBXBuildFile; fileRef = B0F01D23108DDEBF00A53656 /* l_debug.cc */; };
- B0F01D34108DDEBF00A53656 /* l_dgn_bf.cc in Sources */ = {isa = PBXBuildFile; fileRef = B0F01D24108DDEBF00A53656 /* l_dgn_bf.cc */; };
B0F01D35108DDEBF00A53656 /* l_dgn.cc in Sources */ = {isa = PBXBuildFile; fileRef = B0F01D25108DDEBF00A53656 /* l_dgn.cc */; };
B0F01D36108DDEBF00A53656 /* l_dgnbld.cc in Sources */ = {isa = PBXBuildFile; fileRef = B0F01D26108DDEBF00A53656 /* l_dgnbld.cc */; };
B0F01D37108DDEBF00A53656 /* l_dgnevt.cc in Sources */ = {isa = PBXBuildFile; fileRef = B0F01D27108DDEBF00A53656 /* l_dgnevt.cc */; };
@@ -427,7 +426,6 @@
B0F01D40108DDEBF00A53656 /* dlua.cc in Sources */ = {isa = PBXBuildFile; fileRef = B0F01D20108DDEBF00A53656 /* dlua.cc */; };
B0F01D41108DDEBF00A53656 /* l_crawl.cc in Sources */ = {isa = PBXBuildFile; fileRef = B0F01D22108DDEBF00A53656 /* l_crawl.cc */; };
B0F01D42108DDEBF00A53656 /* l_debug.cc in Sources */ = {isa = PBXBuildFile; fileRef = B0F01D23108DDEBF00A53656 /* l_debug.cc */; };
- B0F01D43108DDEBF00A53656 /* l_dgn_bf.cc in Sources */ = {isa = PBXBuildFile; fileRef = B0F01D24108DDEBF00A53656 /* l_dgn_bf.cc */; };
B0F01D44108DDEBF00A53656 /* l_dgn.cc in Sources */ = {isa = PBXBuildFile; fileRef = B0F01D25108DDEBF00A53656 /* l_dgn.cc */; };
B0F01D45108DDEBF00A53656 /* l_dgnbld.cc in Sources */ = {isa = PBXBuildFile; fileRef = B0F01D26108DDEBF00A53656 /* l_dgnbld.cc */; };
B0F01D46108DDEBF00A53656 /* l_dgnevt.cc in Sources */ = {isa = PBXBuildFile; fileRef = B0F01D27108DDEBF00A53656 /* l_dgnevt.cc */; };
@@ -1137,7 +1135,6 @@
B0F01D21108DDEBF00A53656 /* dlua.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dlua.h; sourceTree = "<group>"; };
B0F01D22108DDEBF00A53656 /* l_crawl.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = l_crawl.cc; sourceTree = "<group>"; };
B0F01D23108DDEBF00A53656 /* l_debug.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = l_debug.cc; sourceTree = "<group>"; };
- B0F01D24108DDEBF00A53656 /* l_dgn_bf.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = l_dgn_bf.cc; sourceTree = "<group>"; };
B0F01D25108DDEBF00A53656 /* l_dgn.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = l_dgn.cc; sourceTree = "<group>"; };
B0F01D26108DDEBF00A53656 /* l_dgnbld.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = l_dgnbld.cc; sourceTree = "<group>"; };
B0F01D27108DDEBF00A53656 /* l_dgnevt.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = l_dgnevt.cc; sourceTree = "<group>"; };
@@ -1488,7 +1485,6 @@
B0F01D22108DDEBF00A53656 /* l_crawl.cc */,
B0F01D23108DDEBF00A53656 /* l_debug.cc */,
B0F01D25108DDEBF00A53656 /* l_dgn.cc */,
- B0F01D24108DDEBF00A53656 /* l_dgn_bf.cc */,
B0F01D26108DDEBF00A53656 /* l_dgnbld.cc */,
B0F01D27108DDEBF00A53656 /* l_dgnevt.cc */,
B0F01D28108DDEBF00A53656 /* l_dgngrd.cc */,
@@ -2251,7 +2247,6 @@
B0F01D41108DDEBF00A53656 /* l_crawl.cc in Sources */,
B0F01D42108DDEBF00A53656 /* l_debug.cc in Sources */,
B0F01D44108DDEBF00A53656 /* l_dgn.cc in Sources */,
- B0F01D43108DDEBF00A53656 /* l_dgn_bf.cc in Sources */,
B0F01D45108DDEBF00A53656 /* l_dgnbld.cc in Sources */,
B0F01D46108DDEBF00A53656 /* l_dgnevt.cc in Sources */,
B0F01D47108DDEBF00A53656 /* l_dgngrd.cc in Sources */,
@@ -2389,7 +2384,6 @@
B0F01D32108DDEBF00A53656 /* l_crawl.cc in Sources */,
B0F01D33108DDEBF00A53656 /* l_debug.cc in Sources */,
B0F01D35108DDEBF00A53656 /* l_dgn.cc in Sources */,
- B0F01D34108DDEBF00A53656 /* l_dgn_bf.cc in Sources */,
B0F01D36108DDEBF00A53656 /* l_dgnbld.cc in Sources */,
B0F01D37108DDEBF00A53656 /* l_dgnevt.cc in Sources */,
B0F01D38108DDEBF00A53656 /* l_dgngrd.cc in Sources */,
diff --git a/crawl-ref/source/MSVC/crawl.vcproj b/crawl-ref/source/MSVC/crawl.vcproj
index a4f46ef72e..83ecc61d16 100644
--- a/crawl-ref/source/MSVC/crawl.vcproj
+++ b/crawl-ref/source/MSVC/crawl.vcproj
@@ -1245,10 +1245,6 @@
>
</File>
<File
- RelativePath="..\l_dgn_bf.cc"
- >
- </File>
- <File
RelativePath="..\l_dgnbld.cc"
>
</File>
diff --git a/crawl-ref/source/cluautil.h b/crawl-ref/source/cluautil.h
index 0f02555750..8b3a91937b 100644
--- a/crawl-ref/source/cluautil.h
+++ b/crawl-ref/source/cluautil.h
@@ -168,8 +168,10 @@ branch_type br = str_to_branch(branch_name); \
if (lev == LEVEL_DUNGEON && br == NUM_BRANCHES) \
luaL_error(ls, "Expected branch name");
-#define MAP(ls, n, var) \
+#define MAP(ls, n, var) \
map_def *var = *(map_def **) luaL_checkudata(ls, n, MAP_METATABLE)
+#define LINES(ls, n, var) \
+map_lines &var = (*(map_def **) luaL_checkudata(ls, n, MAP_METATABLE))->map
#define DEVENT(ls, n, var) \
dgn_event *var = *(dgn_event **) luaL_checkudata(ls, n, DEVENT_METATABLE)
#define MAPMARKER(ls, n, var) \
diff --git a/crawl-ref/source/dat/entry.des b/crawl-ref/source/dat/entry.des
index f450e26af3..11f4c40f99 100644
--- a/crawl-ref/source/dat/entry.des
+++ b/crawl-ref/source/dat/entry.des
@@ -4934,14 +4934,14 @@ TAGS: entry no_monster_gen
FTILE: '[({ = floor_sand_stone
SUBST: ' = .
{{
- map_octa_room({
+ octa_room({
oblique = crawl.random_range(3,7),
replace = '.',
outside = 'W',
inside = '.'
})
if crawl.coinflip() then
- map_smear({iterations=20, smear='x', onto='.W', boxy=true})
+ smear_map({iterations=20, smear='x', onto='.W', boxy=true})
end
}}
SUBST: W:xw
diff --git a/crawl-ref/source/dat/layout.des b/crawl-ref/source/dat/layout.des
index 0166e93227..64fe16d2be 100644
--- a/crawl-ref/source/dat/layout.des
+++ b/crawl-ref/source/dat/layout.des
@@ -7,14 +7,19 @@
###############################################################################
{{
- function dgn.random_room_point(room)
- return dgn.point(room.x1 + crawl.random2(room.x2 - room.x1),
- room.y1 + crawl.random2(room.y2 - room.y1))
- end
+ -- Call func num times around a circle of radius centered at (x, y)
+ function apply_circle(x, y, num, radius, scale_x, scale_y, func)
+ radius = math.floor(radius)
+ for n = 1, num do
+ local rad = n * 2 * math.pi / num
+
+ local rx = math.floor(math.cos(rad) * radius * scale_x + 0.5)
+ local ry = math.floor(math.sin(rad) * radius * scale_y + 0.5)
+
+ func(x + rx, y + ry)
+ end
+ end
- function dgn.join_the_dots_p(start, finish)
- return dgn.join_the_dots(start.x, start.y, finish.x, finish.y)
- end
}}
##############################################################
@@ -26,20 +31,21 @@
NAME: layout_forbidden_donut
ORIENT: encompass
TAGS: layout allow_dup
-
{{
local gxm, gym = dgn.max_bounds()
- local wall = dgn.feature_number("rock_wall")
- local floor = dgn.feature_number("floor")
- dgn.fill_area(0, 0, gxm - 1, gym - 1, wall)
+ extend_map{width=gxm, height=gym, fill='x'}
+ fill_area{fill='x'}
local width = (10 - crawl.random2(7))
+ local floor = '.'
+ local wall = 'x'
+
-- construct donut
- dgn.fill_area(10, 10, gxm - 10, 10 + width, floor)
- dgn.fill_area(10, 60 - width, gxm - 10, gym - 10, floor)
- dgn.fill_area(10, 10, 10 + width, gym - 10, floor)
- dgn.fill_area(60 - width, 10, gxm - 10, gym - 10, floor)
+ fill_area{x1=10, y1=10, x2=gxm-10, y2=10+width, fill=floor}
+ fill_area{x1=10, y1=60-width, x2=gxm-10, y2=gym-10, fill=floor}
+ fill_area{x1=10, y1=10, x2=10+width, y2=gym-10, fill=floor}
+ fill_area{x1=60-width, y1=10, x2=gxm-10, y2=gym-10, fill=floor}
local spotty = crawl.coinflip()
local smears = crawl.random2(300)
@@ -48,22 +54,22 @@ TAGS: layout allow_dup
if crawl.coinflip() then
local width2 = 1 + crawl.random2(5)
- dgn.fill_area(10, gym/2 - width2, gxm - 10, gym/2 + width2, floor)
- dgn.fill_area(gxm/2 - width2, 10, gxm/2 + width2, gym - 10, floor)
+ fill_area{x1=10, y1=gym/2-width2, x2=gxm-10, y2=gym/2+width2, fill=floor}
+ fill_area{x1=gxm/2-width2, y1=10, x2=gxm/2+width2, y2=gym-10, fill=floor}
-- sometimes add a small octagon room
- if crawl.coinflip() and crawl.random2(15) > 7 then
- local oblique = 0
+ if crawl.coinflip() then
+ local obl = 0
if crawl.coinflip() then
- oblique = 5 + crawl.random2(20)
+ obl = 5 + crawl.random2(20)
end
- local feature_name = crawl.random_element({
- ["floor"] = 5,
- ["deep_water"] = 1,
- ["lava"] = 1,
+ local fill = crawl.random_element({
+ ["."] = 10,
+ ["w"] = 5,
+ ["l"] = 1,
})
- dgn.octa_room(25, 25, gxm - 25, gym - 25, oblique, feature_name)
+ octa_room{x1=25, y1=25, x2=gxm-25, y2=gym-25, oblique=obl, replace='x', inside=fill}
-- decrease spotty chance
spotty = crawl.one_chance_in(5)
@@ -74,10 +80,10 @@ TAGS: layout allow_dup
local smear_boxy = crawl.coinflip()
if spotty then
- dgn.spotty_level(true, 0, spotty_boxy)
+ spotty_map{boxy=spotty_boxy}
end
if not spotty and crawl.one_chance_in(4) or spotty then
- dgn.smear_feature(smears, smear_boxy, wall, 0, 0, gxm - 1, gym - 1)
+ smear_map{iterations=smears, smear='x', onto='.', boxy=smear_boxy}
end
}}
MAP
@@ -94,45 +100,45 @@ ORIENT: encompass
TAGS: layout allow_dup
{{
- local width = 5 - crawl.random2(5)
- local height = 5 - crawl.random2(5)
-
local gxm, gym = dgn.max_bounds()
+ extend_map{width = gxm, height = gym, fill = 'x'}
- local wall = dgn.feature_number("rock_wall")
- local floor = dgn.feature_number("floor")
+ local floor = '.'
+ local wall = 'x'
+
+ local width = 5 - crawl.random2(5)
+ local height = 5 - crawl.random2(5)
-- Include a small possibility of adding windows around the cross.
-- This layout can get used with spotty_level, so don't make this
-- chance too large as lava/water prevents that from happening.
local window = crawl.one_chance_in(20)
- if window or crawl.one_chance_in(20) then
+ if window then
if crawl.coinflip() then
- wall = dgn.feature_number("lava")
+ wall = 'l'
else
- wall = dgn.feature_number("deep_water")
+ wall = 'w'
end
end
- -- fill with rock
- dgn.fill_area(0, 0, gxm-1, gym-1, wall)
+ fill_area{fill=wall}
-- create window
if window then
- local clear = dgn.feature_number("clear_rock_wall")
- dgn.fill_area(10, gym/2 - height - 1, gxm - 10, gym/2 - height - 1, clear)
- dgn.fill_area(10, gym/2 + height + 1, gxm - 10, gym/2 + height + 1, clear)
- dgn.fill_area(gxm/2 - width - 1, 10, gxm/2 - width - 1, gym - 10, clear)
- dgn.fill_area(gxm/2 + width + 1, 10, gxm/2 + width + 1, gym - 10, clear)
+ local clear = 'm'
+ fill_area{x1=10, y1=gym/2-height-1, x2=gxm-10, y2=gym/2-height-1, fill=clear}
+ fill_area{x1=10, y1=gym/2+height+1, x2=gxm-10, y2=gym/2+height+1, fill=clear}
+ fill_area{x1=gxm/2-width-1, y1=10, x2=gxm/2-width-1, y2=gym-10, fill=clear}
+ fill_area{x1=gxm/2+width+1, y1=10, x2=gxm/2+width+1, y2=gym-10, fill=clear}
end
-- create a cross
- dgn.fill_area(10, gym/2 - height, gxm - 10, gym/2 + height, floor)
- dgn.fill_area(gxm/2 - width, 10, gxm/2 + width, gym - 10, floor)
+ fill_area{x1=10, y1=gym/2-height, x2=gxm-10, y2=gym/2+height, fill=floor}
+ fill_area{x1=gxm/2-width, y1=10, x2=gxm/2+width, y2=gym-10, fill=floor}
if not crawl.one_chance_in(4) then
- dgn.spotty_level(true, 0, crawl.coinflip())
+ spotty_map{boxy = crawl.coinflip()}
end
}}
MAP
@@ -151,58 +157,83 @@ ORIENT: encompass
TAGS: layout allow_dup
{{
+ -- Step 1: Big octagon.
+
local gxm, gym = dgn.max_bounds()
- local wall = dgn.feature_number("rock_wall")
- local floor = dgn.feature_number("floor")
+ extend_map{width = gxm, height = gym, fill = 'x'}
+ fill_area{fill = 'x'}
local oblique = 10 + crawl.random2(20)
-
- dgn.fill_area(0, 0, gxm - 1, gym - 1, "rock_wall")
- dgn.octa_room(10, 10, gxm - 10, gym - 10, oblique, "floor")
-
- local smear = crawl.coinflip()
- if smear then
- local iterations = 100 + crawl.random2(500 - oblique * 12)
- dgn.smear_feature(iterations, false, wall, 0, 0, gxm - 1, gym - 1)
+ octa_room{
+ x1 = 10,
+ y1 = 10,
+ x2 = gxm-10,
+ y2 = gym-10,
+ oblique = oblique,
+ replace = 'x',
+ inside = '.'}
+
+ local do_smear = crawl.coinflip()
+ if do_smear then
+ local iterations = 100 + crawl.random2(800)
+ smear_map{iterations = iterations, boxy = false}
+
+ --Fill in disconnected zones now, prior to adding the stairs.
+ --Temporarily set a (passable) unique symbol in the middle of the map,
+ --to guarantee everything is connected to it after smearing.
+ mapgrd[gxm/2][gym/2] = '@'
+ fill_disconnected{wanted = '@'}
+ mapgrd[gxm/2][gym/2] = '.'
end
-- Step 2: Add pillars
-- pillar types and relative weights
local pillar_fill = {
- ["rock_wall"] = 15,
- ["green_crystal_wall"] = 5,
- ["metal_wall"] = 4,
- ["clear_rock_wall"] = 3,
- ["deep_water"] = 2,
- ["lava"] = 1,
+ ["x"] = 15,
+ ["b"] = 5,
+ ["v"] = 4,
+ ["m"] = 3,
+ ["w"] = 2,
+ ["l"] = 1,
}
- local fill = dgn.feature_number(crawl.random_element(pillar_fill))
+ if (you.in_branch("lair")) then
+ pillar_fill["t"] = 15
+ end
-- Potential pillar drawing routines
local pillar_func = {
- dgn.make_circle,
- dgn.make_square,
- dgn.make_rounded_square
- }
+ make_circle,
+ make_diamond,
+ make_square,
+ make_rounded_square}
-- Pillar size params
-- NOTE: Be careful about tweaking the ranges here. Pillars that are
-- too large, close, or large in number can entirely surround the center.
- local type = crawl.random2(#pillar_func) + 1
+
+ local pfunc = pillar_func[crawl.random2(#pillar_func) + 1]
+ pfunc = make_diamond
local num = 3 + crawl.random2(9)
local pillar_radius = 1 + crawl.random2(3)
local circle_radius = 2 + crawl.random2(6) + pillar_radius * 2 + num / 2
-
+ local fill = crawl.random_element(pillar_fill)
-- beautification hack: no "circle" pillars of radius 1
- if type == 1 and pillar_radius == 1 then
- fill = dgn.feature_number("stone_arch")
+ if pfunc == make_circle and pillar_radius == 1 then
+ fill = crawl.random_element({"G", "X", "t"})
+ kfeat("X = stone_arch")
end
-- Finally, make the pillars
- dgn.make_pillars(gxm/2, gym/2, num, 1, circle_radius, pillar_radius,
- pillar_func[type], fill)
+ local make_pillar = function(x, y)
+ return pfunc({
+ x = x,
+ y = y,
+ radius = pillar_radius,
+ fill = fill})
+ end
+ apply_circle(gxm/2, gym/2, num, circle_radius, 1, 1, make_pillar)
-- Step 3: Create stairs
@@ -220,44 +251,57 @@ TAGS: layout allow_dup
down_loc = crawl.random2(6)
end
- local up_stairs = {
- dgn.feature_number("stone_stairs_up_i"),
- dgn.feature_number("stone_stairs_up_ii"),
- dgn.feature_number("stone_stairs_up_iii"),
- }
- local down_stairs = {
- dgn.feature_number("stone_stairs_down_i"),
- dgn.feature_number("stone_stairs_down_ii"),
- dgn.feature_number("stone_stairs_down_iii"),
- }
+ local up_stairs = {"{", "(", "["}
+ local down_stairs = {"}", ")", "]"}
local full_stair_set = {[up_loc] = up_stairs, [down_loc] = down_stairs}
for loc, stair_list in pairs (full_stair_set) do
for i = 1, #stair_list do
local st = stair_list[i]
- local ret = true
if loc == 0 then
- dgn.replace_random(floor, stair_list[i])
+ replace_random({find = ".", replace = st, required = true})
elseif loc == 1 then
- dgn.grid(gxm/2 + i - 2, gym/2 + 1 - math.abs(i - 2), st)
+ mapgrd[gxm/2 + i - 2][gym/2 + 1 - math.abs(i - 2)] = st
elseif loc == 2 then
- ret = dgn.replace_first(gxm/2 + i-2, 0, 0, 1, floor, st)
+ replace_first({
+ required = true,
+ x = gxm/2 + i - 2,
+ y = 1,
+ xdir = 0,
+ ydir = 1,
+ find = ".",
+ replace = st})
elseif loc == 3 then
- ret = dgn.replace_first(gxm - 1, gym/2 + i-2, -1, 0, floor, st)
+ replace_first({
+ required = true,
+ x = gxm,
+ y = gym/2 + i - 2,
+ xdir = -1,
+ ydir = 0,
+ find = ".",
+ replace = st})
elseif loc == 4 then
- ret = dgn.replace_first(gxm/2 + i-2, gym - 1, 0, -1, floor, st)
+ replace_first({
+ required = true,
+ x = gxm/2 + i - 2,
+ y = gym,
+ xdir = 0,
+ ydir = -1,
+ find = ".",
+ replace = st})
elseif loc == 5 then
- ret = dgn.replace_first(0, gym/2 + i-2, 1, 0, floor, st)
+ replace_first({
+ required = true,
+ x = 1,
+ y = gym/2 + i - 2,
+ xdir = 1,
+ ydir = 0,
+ find = ".",
+ replace = st})
end
-
- assert(ret)
end
end
-
- if smear then
- dgn.fill_disconnected_zones(0, 0, gxm - 1, gym - 1, wall)
- end
}}
MAP
ENDMAP
@@ -271,8 +315,22 @@ NAME: layout_rooms
ORIENT: encompass
TAGS: layout allow_dup
{{
- local wall = dgn.feature_number("rock_wall")
- local floor = dgn.feature_number("floor")
+ function random_room_point(room)
+ return dgn.point(room.x1 + crawl.random2(room.x2 - room.x1),
+ room.y1 + crawl.random2(room.y2 - room.y1))
+ end
+
+ function join_the_dots_p(start, finish)
+ return join_the_dots({
+ x1 = start.x,
+ y1 = start.y,
+ x2 = finish.x,
+ y2 = finish.y})
+ end
+
+ local gxm, gym = dgn.max_bounds()
+ extend_map{width = gxm, height = gym, fill = 'x'}
+ fill_area{fill = 'x'}
local num_rooms = 30 + crawl.random2(90)
local exclusive = not crawl.one_chance_in(10)
@@ -281,36 +339,46 @@ TAGS: layout allow_dup
local rooms = {}
for i = 0, num_rooms do
- local new_room = {
- x1 = 10 + crawl.random2(50),
- y1 = 10 + crawl.random2(40)
- }
- new_room.x2 = new_room.x1 + 2 + crawl.random2(8)
- new_room.y2 = new_room.y1 + 2 + crawl.random2(8)
-
- local not_walls = dgn.count_antifeature_in_box(new_room.x1 - 1,
- new_room.y1 - 1, new_room.x2 + 1, new_room.y2 + 1, wall)
- if (not exclusive or not_walls == 0) then
- dgn.replace_area(new_room.x1, new_room.y1, new_room.x2,
- new_room.y2, wall, floor);
-
- if #rooms > 0 and not exclusive2 then
- dgn.join_the_dots_p(dgn.random_room_point(new_room),
- dgn.random_room_point(rooms[#rooms]))
- end
+ local new_room = {
+ x1 = 10 + crawl.random2(50),
+ y1 = 10 + crawl.random2(40)
+ }
+ new_room.x2 = new_room.x1 + 2 + crawl.random2(8)
+ new_room.y2 = new_room.y1 + 2 + crawl.random2(8)
+
+ local not_walls = count_antifeature_in_box({
+ x1 = new_room.x1,
+ y1 = new_room.y1,
+ x2 = new_room.x2,
+ y2 = new_room.y2,
+ feat = "x"})
+
+ if (not exclusive or not_walls == 0) then
+ replace_area({
+ x1 = new_room.x1,
+ y1 = new_room.y1,
+ x2 = new_room.x2,
+ y2 = new_room.y2,
+ find = "x",
+ replace = "."})
+
+ if #rooms > 0 and not exclusive2 then
+ join_the_dots_p(random_room_point(new_room),
+ random_room_point(rooms[#rooms]))
+ end
- table.insert(rooms, new_room)
- if #rooms >= 30 then
- break
+ table.insert(rooms, new_room)
+ if #rooms >= 30 then
+ break
+ end
end
- end
end
if exclusive2 then
- for i = 2, #rooms do
- dgn.join_the_dots_p(dgn.random_room_point(rooms[i]),
- dgn.random_room_point(rooms[i - 1]))
- end
+ for i = 2, #rooms do
+ join_the_dots_p(random_room_point(rooms[i]),
+ random_room_point(rooms[i - 1]))
+ end
end
}}
MAP
diff --git a/crawl-ref/source/dlua.cc b/crawl-ref/source/dlua.cc
index 24fd13356f..256f3210bf 100644
--- a/crawl-ref/source/dlua.cc
+++ b/crawl-ref/source/dlua.cc
@@ -296,8 +296,6 @@ void init_dungeon_lua()
luaopen_mapmarker(dlua);
luaopen_ray(dlua);
- register_builder_funcs(dlua);
-
register_itemlist(dlua);
register_monslist(dlua);
}
diff --git a/crawl-ref/source/l_dgn_bf.cc b/crawl-ref/source/l_dgn_bf.cc
deleted file mode 100644
index 1d9ee8e5b0..0000000000
--- a/crawl-ref/source/l_dgn_bf.cc
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * File: l_dgn_bf.cc
- * Summary: Dungeon lua builder functions.
- */
-
-#include "AppHdr.h"
-
-#include "cluautil.h"
-#include "l_libs.h"
-#include "mapdef.h"
-#include "random.h"
-
-// Return the integer stored in the table (on the stack) with the key name.
-// If the key doesn't exist or the value is the wrong type, return defval.
-static int _table_int(lua_State *ls, int idx, const char *name, int defval)
-{
- lua_pushstring(ls, name);
- lua_gettable(ls, idx < 0 ? idx - 1 : idx);
- bool nil = lua_isnil(ls, idx);
- bool valid = lua_isnumber(ls, idx);
- if (!nil && !valid)
- luaL_error(ls, "'%s' in table, but not an int.", name);
- int ret = (!nil && valid ? luaL_checkint(ls, idx) : defval);
- lua_pop(ls, 1);
- return (ret);
-}
-
-// Return the character stored in the table (on the stack) with the key name.
-// If the key doesn't exist or the value is the wrong type, return defval.
-static char _table_char(lua_State *ls, int idx, const char *name, char defval)
-{
- lua_pushstring(ls, name);
- lua_gettable(ls, idx < 0 ? idx - 1 : idx);
- bool nil = lua_isnil(ls, idx);
- bool valid = lua_isstring(ls, idx);
- if (!nil && !valid)
- luaL_error(ls, "'%s' in table, but not a string.", name);
-
- char ret = defval;
- if (!nil && valid)
- {
- const char *str = lua_tostring(ls, idx);
- if (str[0] && !str[1])
- ret = str[0];
- else
- luaL_error(ls, "'%s' has more than one character.", name);
- }
- lua_pop(ls, 1);
- return (ret);
-}
-
-// Return the string stored in the table (on the stack) with the key name.
-// If the key doesn't exist or the value is the wrong type, return defval.
-static const char* _table_str(lua_State *ls, int idx, const char *name, const char *defval)
-{
- lua_pushstring(ls, name);
- lua_gettable(ls, idx < 0 ? idx - 1 : idx);
- bool nil = lua_isnil(ls, idx);
- bool valid = lua_isstring(ls, idx);
- if (!nil && !valid)
- luaL_error(ls, "'%s' in table, but not a string.", name);
- const char *ret = (!nil && valid ? lua_tostring(ls, idx) : defval);
- lua_pop(ls, 1);
- return (ret);
-}
-
-// Return the boolean stored in the table (on the stack) with the key name.
-// If the key doesn't exist or the value is the wrong type, return defval.
-static bool _table_bool(lua_State *ls, int idx, const char *name, bool defval)
-{
- lua_pushstring(ls, name);
- lua_gettable(ls, idx < 0 ? idx - 1 : idx);
- bool nil = lua_isnil(ls, idx);
- bool valid = lua_isboolean(ls, idx);
- if (!nil && !valid)
- luaL_error(ls, "'%s' in table, but not a bool.", name);
- bool ret = (!nil && valid ? lua_toboolean(ls, idx) : defval);
- lua_pop(ls, 1);
- return (ret);
-}
-
-#define BF_INT(ls, val, def) int val = _table_int(ls, -1, #val, def);
-#define BF_CHAR(ls, val, def) char val = _table_char(ls, -1, #val, def);
-#define BF_STR(ls, val, def) const char *val = _table_str(ls, -1, #val, def);
-#define BF_BOOL(ls, val, def) bool val = _table_bool(ls, -1, #val, def);
-
-static void bf_octa_room(lua_State *ls, map_lines &lines)
-{
- int default_oblique = std::min(lines.width(), lines.height()) / 2 - 1;
- BF_INT(ls, oblique, default_oblique);
- BF_CHAR(ls, outside, 'x');
- BF_CHAR(ls, inside, '.');
- BF_STR(ls, replace, ".");
-
- coord_def tl, br;
- if (!lines.find_bounds(replace, tl, br))
- return;
-
- for (rectangle_iterator ri(tl, br); ri; ++ri)
- {
- const coord_def mc = *ri;
- char glyph = lines(mc);
- if (replace[0] && !strchr(replace, glyph))
- continue;
-
- int ob = 0;
- ob += std::max(oblique + tl.x - mc.x, 0);
- ob += std::max(oblique + mc.x - br.x, 0);
-
- bool is_inside = (mc.y >= tl.y + ob && mc.y <= br.y - ob);
- lines(mc) = is_inside ? inside : outside;
- }
-}
-
-static void bf_smear(lua_State *ls, map_lines &lines)
-{
- BF_INT(ls, iterations, 1);
- BF_CHAR(ls, smear, 'x');
- BF_STR(ls, onto, ".");
- BF_BOOL(ls, boxy, false);
-
- const int max_test_per_iteration = 10;
- int sanity = 0;
- int max_sanity = iterations * max_test_per_iteration;
-
- for (int i = 0; i < iterations; i++)
- {
- bool diagonals, straights;
- coord_def mc;
-
- do
- {
- do
- {
- sanity++;
- mc.x = random_range(1, lines.width() - 2);
- mc.y = random_range(1, lines.height() - 2);
- }
- while (onto[0] && !strchr(onto, lines(mc)));
-
- // Prevent too many iterations.
- if (sanity > max_sanity)
- return;
-
- // Is there a "smear" feature along the diagonal from mc?
- diagonals = lines(coord_def(mc.x+1, mc.y+1)) == smear ||
- lines(coord_def(mc.x-1, mc.y+1)) == smear ||
- lines(coord_def(mc.x-1, mc.y-1)) == smear ||
- lines(coord_def(mc.x+1, mc.y-1)) == smear;
-
- // Is there a "smear" feature up, down, left, or right from mc?
- straights = lines(coord_def(mc.x+1, mc.y)) == smear ||
- lines(coord_def(mc.x-1, mc.y)) == smear ||
- lines(coord_def(mc.x, mc.y+1)) == smear ||
- lines(coord_def(mc.x, mc.y-1)) == smear;
- }
- while (!straights && (boxy || !diagonals));
-
- lines(mc) = smear;
- }
-}
-
-static void bf_extend(lua_State *ls, map_lines &lines)
-{
- BF_INT(ls, height, 1);
- BF_INT(ls, width, 1);
- BF_CHAR(ls, fill, 'x');
-
- lines.extend(width, height, fill);
-}
-
-typedef void (*bf_func)(lua_State *ls, map_lines &lines);
-struct bf_entry
-{
- const char* name;
- bf_func func;
-};
-
-// Create a separate list of builder funcs so that we can automatically
-// generate a list of closures for them, rather than individually
-// and explicitly exposing them to the dgn namespace.
-static struct bf_entry bf_map[] =
-{
- { "map_octa_room", &bf_octa_room },
- { "map_smear", &bf_smear },
- { "map_extend", &bf_extend }
-};
-
-static int dgn_call_builder_func(lua_State *ls)
-{
- // This function gets called for all the builder functions that
- // operate on map_lines.
-
- MAP(ls, 1, map);
- if (!lua_istable(ls, 2) && !lua_isfunction(ls, 2))
- return luaL_argerror(ls, 2, "Expected table");
-
- bf_func *func = (bf_func *)lua_topointer(ls, lua_upvalueindex(1));
- if (!func)
- return luaL_error(ls, "Expected C function in closure upval");
-
- // Put the table on top.
- lua_settop(ls, 2);
-
- // Call the builder func itself.
- (*func)(ls, map->map);
-
- return (0);
-}
-
-void register_builder_funcs(lua_State *ls)
-{
- lua_getglobal(ls, "dgn");
-
- const size_t num_entries = sizeof(bf_map) / sizeof(bf_entry);
- for (size_t i = 0; i < num_entries; i++)
- {
- // Push a closure with the C function into the dgn table.
- lua_pushlightuserdata(ls, &bf_map[i].func);
- lua_pushcclosure(ls, &dgn_call_builder_func, 1);
- lua_setfield(ls, -2, bf_map[i].name);
- }
-
- lua_pop(ls, 1);
-}
diff --git a/crawl-ref/source/l_dgnbld.cc b/crawl-ref/source/l_dgnbld.cc
index 6a3d0da004..61de206aee 100644
--- a/crawl-ref/source/l_dgnbld.cc
+++ b/crawl-ref/source/l_dgnbld.cc
@@ -8,360 +8,709 @@
#include <cmath>
#include "cluautil.h"
-#include "l_libs.h"
-
#include "coord.h"
#include "dungeon.h"
+#include "l_libs.h"
+#include "mapdef.h"
#include "random.h"
-// Return a metatable for a point on the map_lines grid.
-static int dgn_mapgrd_table(lua_State *ls)
-{
- MAP(ls, 1, map);
+static const char *traversable_glyphs =
+ ".+=w@{}()[]<>BC^~TUVY$%*|Odefghijk0123456789";
- map_def **mapref = clua_new_userdata<map_def *>(ls, MAPGRD_METATABLE);
- *mapref = map;
+static const char *exit_glyphs = "{}()[]<>@";
- return (1);
+// Return the integer stored in the table (on the stack) with the key name.
+// If the key doesn't exist or the value is the wrong type, return defval.
+static int _table_int(lua_State *ls, int idx, const char *name, int defval)
+{
+ if (!lua_istable(ls, idx))
+ return defval;
+ lua_pushstring(ls, name);
+ lua_gettable(ls, idx < 0 ? idx - 1 : idx);
+ bool nil = lua_isnil(ls, idx);
+ bool valid = lua_isnumber(ls, idx);
+ if (!nil && !valid)
+ luaL_error(ls, "'%s' in table, but not an int.", name);
+ int ret = (!nil && valid ? luaL_checkint(ls, idx) : defval);
+ lua_pop(ls, 1);
+ return (ret);
}
-static int dgn_width(lua_State *ls)
+// Return the character stored in the table (on the stack) with the key name.
+// If the key doesn't exist or the value is the wrong type, return defval.
+static char _table_char(lua_State *ls, int idx, const char *name, char defval)
{
- MAP(ls, 1, map);
-
- lua_pushnumber(ls, map->map.width());
- return (1);
+ if (!lua_istable(ls, idx))
+ return defval;
+ lua_pushstring(ls, name);
+ lua_gettable(ls, idx < 0 ? idx - 1 : idx);
+ bool nil = lua_isnil(ls, idx);
+ bool valid = lua_isstring(ls, idx);
+ if (!nil && !valid)
+ luaL_error(ls, "'%s' in table, but not a string.", name);
+
+ char ret = defval;
+ if (!nil && valid)
+ {
+ const char *str = lua_tostring(ls, idx);
+ if (str[0] && !str[1])
+ ret = str[0];
+ else
+ luaL_error(ls, "'%s' has more than one character.", name);
+ }
+ lua_pop(ls, 1);
+ return (ret);
}
-static int dgn_height(lua_State *ls)
+// Return the string stored in the table (on the stack) with the key name.
+// If the key doesn't exist or the value is the wrong type, return defval.
+static const char* _table_str(lua_State *ls, int idx, const char *name, const char *defval)
{
- MAP(ls, 1, map);
-
- lua_pushnumber(ls, map->map.height());
- return (1);
+ if (!lua_istable(ls, idx))
+ return defval;
+ lua_pushstring(ls, name);
+ lua_gettable(ls, idx < 0 ? idx - 1 : idx);
+ bool nil = lua_isnil(ls, idx);
+ bool valid = lua_isstring(ls, idx);
+ if (!nil && !valid)
+ luaL_error(ls, "'%s' in table, but not a string.", name);
+ const char *ret = (!nil && valid ? lua_tostring(ls, idx) : defval);
+ lua_pop(ls, 1);
+ return (ret);
}
-static void _clamp_to_bounds(int &x, int &y, bool edge_ok = false)
+// Return the boolean stored in the table (on the stack) with the key name.
+// If the key doesn't exist or the value is the wrong type, return defval.
+static bool _table_bool(lua_State *ls, int idx, const char *name, bool defval)
{
- const int edge_offset = edge_ok ? 0 : 1;
- x = std::min(std::max(x, X_BOUND_1 + edge_offset), X_BOUND_2 - edge_offset);
- y = std::min(std::max(y, Y_BOUND_1 + edge_offset), Y_BOUND_2 - edge_offset);
+ if (!lua_istable(ls, idx))
+ return defval;
+ lua_pushstring(ls, name);
+ lua_gettable(ls, idx < 0 ? idx - 1 : idx);
+ bool nil = lua_isnil(ls, idx);
+ bool valid = lua_isboolean(ls, idx);
+ if (!nil && !valid)
+ luaL_error(ls, "'%s' in table, but not a bool.", name);
+ bool ret = (!nil && valid ? lua_toboolean(ls, idx) : defval);
+ lua_pop(ls, 1);
+ return (ret);
}
-static int dgn_fill_area(lua_State *ls)
+// These macros all assume the table is on the top of the lua stack.
+#define TABLE_INT(ls, val, def) int val = _table_int(ls, -1, #val, def);
+#define TABLE_CHAR(ls, val, def) char val = _table_char(ls, -1, #val, def);
+#define TABLE_STR(ls, val, def) const char *val = _table_str(ls, -1, #val, def);
+#define TABLE_BOOL(ls, val, def) bool val = _table_bool(ls, -1, #val, def);
+
+// Read a set of box coords (x1, y1, x2, y2) from the table.
+// Return true if coords are valid.
+static bool _coords(lua_State *ls, map_lines &lines,
+ int &x1, int &y1, int &x2, int &y2, int border = 0)
{
- int x1 = luaL_checkint(ls, 1);
- int y1 = luaL_checkint(ls, 2);
- int x2 = luaL_checkint(ls, 3);
- int y2 = luaL_checkint(ls, 4);
- dungeon_feature_type feat = check_lua_feature(ls, 5);
-
- _clamp_to_bounds(x1, y1);
- _clamp_to_bounds(x2, y2);
+ const int idx = -1;
+ x1 = _table_int(ls, idx, "x1", 1);
+ y1 = _table_int(ls, idx, "y1", 1);
+ x2 = _table_int(ls, idx, "x2", lines.width());
+ y2 = _table_int(ls, idx, "y2", lines.height());
+
if (x2 < x1)
- std::swap(x1, x2);
+ std::swap(x1, x2);
if (y2 < y1)
std::swap(y1, y2);
- for (int y = y1; y <= y2; y++)
- for (int x = x1; x <= x2; x++)
- grd[x][y] = feat;
+ x1--;
+ y1--;
+ x2--;
+ y2--;
- return 0;
+ return (x1 + border <= x2 - border && y1 + border <= y2 - border);
}
-static int dgn_replace_area(lua_State *ls)
+// Check if a given coordiante is valid for lines.
+static bool _valid_coord(lua_State *ls, map_lines &lines, int x, int y)
{
- int x1 = luaL_checkint(ls, 1);
- int y1 = luaL_checkint(ls, 2);
- int x2 = luaL_checkint(ls, 3);
- int y2 = luaL_checkint(ls, 4);
- dungeon_feature_type search = check_lua_feature(ls, 5);
- dungeon_feature_type replace = check_lua_feature(ls, 6);
-
- // gracefully handle out of bound areas by truncating them.
- _clamp_to_bounds(x1, y1);
- _clamp_to_bounds(x2, y2);
- if (x2 < x1)
- std::swap(x1, x2);
- if (y2 < y1)
- std::swap(y1, y2);
+ if (x < 0 || x >= lines.width())
+ {
+ luaL_error(ls, "Invalid x coordinate: %d", x);
+ return false;
+ }
- for (int y = y1; y <= y2; y++)
- for (int x = x1; x <= x2; x++)
- if (grd[x][y] == search)
- grd[x][y] = replace;
+ if (y < 0 || y >= lines.height())
+ {
+ luaL_error(ls, "Invalid y coordinate: %d", y);
+ return false;
+ }
- return 0;
+ return true;
}
-static int dgn_octa_room(lua_State *ls)
+LUAFN(dgn_count_feature_in_box)
{
- int x1 = luaL_checkint(ls, 1);
- int y1 = luaL_checkint(ls, 2);
- int x2 = luaL_checkint(ls, 3);
- int y2 = luaL_checkint(ls, 4);
- int oblique = luaL_checkint(ls, 5);
- dungeon_feature_type fill = check_lua_feature(ls, 6);
-
- spec_room sr;
- sr.tl.x = x1;
- sr.br.x = x2;
- sr.tl.y = y1;
- sr.br.y = y2;
-
- octa_room(sr, oblique, fill);
-
- return 0;
-}
+ LINES(ls, 1, lines);
-static int dgn_make_pillars(lua_State *ls)
-{
- int center_x = luaL_checkint(ls, 1);
- int center_y = luaL_checkint(ls, 2);
- int num = luaL_checkint(ls, 3);
- int scale_x = luaL_checkint(ls, 4);
- int big_radius = luaL_checkint(ls, 5);
- int pillar_radius = luaL_checkint(ls, 6);
- dungeon_feature_type fill = check_lua_feature(ls, 8);
-
- // [enne] The underscore is for DJGPP's brain damage.
- const float _PI = 3.14159265f;
- for (int n = 0; n < num; n++)
- {
- float angle = n * 2 * _PI / (float)num;
- int x = (int)std::floor(std::cos(angle) * big_radius * scale_x + 0.5f);
- int y = (int)std::floor(std::sin(angle) * big_radius + 0.5f);
+ int x1, y1, x2, y2;
+ if (!_coords(ls, lines, x1, y1, x2, y2))
+ return (0);
- lua_pushvalue(ls, 7);
- lua_pushnumber(ls, center_x + x);
- lua_pushnumber(ls, center_y + y);
- lua_pushnumber(ls, pillar_radius);
- lua_pushnumber(ls, fill);
+ TABLE_STR(ls, feat, "");
- lua_call(ls, 4, 0);
- }
+ coord_def tl(x1, y1);
+ coord_def br(x2, y2);
- return 0;
+ PLUARET(number, lines.count_feature_in_box(tl, br, feat));
}
-static int dgn_make_square(lua_State *ls)
+LUAFN(dgn_count_antifeature_in_box)
{
- int center_x = luaL_checkint(ls, 1);
- int center_y = luaL_checkint(ls, 2);
- int radius = std::abs(luaL_checkint(ls, 3));
- dungeon_feature_type fill = check_lua_feature(ls, 4);
+ LINES(ls, 1, lines);
+
+ int x1, y1, x2, y2;
+ if (!_coords(ls, lines, x1, y1, x2, y2))
+ return (0);
- for (int x = -radius; x <= radius; x++)
- for (int y = -radius; y <= radius; y++)
- grd[center_x + x][center_y + y] = fill;
+ TABLE_STR(ls, feat, "");
- return 0;
+ coord_def tl(x1, y1);
+ coord_def br(x2, y2);
+
+ int sum = (br.x - tl.x + 1) * (br.y - tl.y + 1);
+ PLUARET(number, sum - lines.count_feature_in_box(tl, br, feat));
}
-static int dgn_make_rounded_square(lua_State *ls)
+LUAFN(dgn_count_neighbors)
{
- int center_x = luaL_checkint(ls, 1);
- int center_y = luaL_checkint(ls, 2);
- int radius = std::abs(luaL_checkint(ls, 3));
- dungeon_feature_type fill = check_lua_feature(ls, 4);
+ LINES(ls, 1, lines);
+
+ TABLE_STR(ls, feat, "");
+ TABLE_INT(ls, x, -1);
+ TABLE_INT(ls, y, -1);
- for (int x = -radius; x <= radius; x++)
- for (int y = -radius; y <= radius; y++)
- if (std::abs(x) != radius || std::abs(y) != radius)
- grd[center_x + x][center_y + y] = fill;
+ if (!_valid_coord(ls, lines, --x, --y))
+ return (0);
- return 0;
+ coord_def tl(x-1, y-1);
+ coord_def br(x+1, y+1);
+
+ PLUARET(number, lines.count_feature_in_box(tl, br, feat));
}
-static int dgn_make_circle(lua_State *ls)
+LUAFN(dgn_extend_map)
{
- int center_x = luaL_checkint(ls, 1);
- int center_y = luaL_checkint(ls, 2);
- int radius = std::abs(luaL_checkint(ls, 3));
- dungeon_feature_type fill = check_lua_feature(ls, 4);
+ LINES(ls, 1, lines);
+
+ TABLE_INT(ls, height, 1);
+ TABLE_INT(ls, width, 1);
+ TABLE_CHAR(ls, fill, 'x');
- for (int x = -radius; x <= radius; x++)
- for (int y = -radius; y <= radius; y++)
- if (x * x + y * y < radius * radius)
- grd[center_x + x][center_y + y] = fill;
+ lines.extend(width, height, fill);
- return 0;
+ return (0);
}
-static int dgn_in_bounds(lua_State *ls)
+LUAFN(dgn_fill_area)
{
- int x = luaL_checkint(ls, 1);
- int y = luaL_checkint(ls, 2);
+ LINES(ls, 1, lines);
+
+ int x1, y1, x2, y2;
+ if (!_coords(ls, lines, x1, y1, x2, y2))
+ return (0);
+
+ TABLE_CHAR(ls, fill, 'x');
- lua_pushboolean(ls, in_bounds(x, y));
- return 1;
+ for (int y = y1; y <= y2; ++y)
+ for (int x = x1; x <= x2; ++x)
+ {
+ lines(x, y) = fill;
+ }
+
+ return (0);
}
-static int dgn_replace_first(lua_State *ls)
+LUAFN(dgn_fill_disconnected)
{
- int x = luaL_checkint(ls, 1);
- int y = luaL_checkint(ls, 2);
- int dx = luaL_checkint(ls, 3);
- int dy = luaL_checkint(ls, 4);
- dungeon_feature_type search = check_lua_feature(ls, 5);
- dungeon_feature_type replace = check_lua_feature(ls, 6);
-
- _clamp_to_bounds(x, y);
- bool found = false;
- while (in_bounds(x, y))
+ LINES(ls, 1, lines);
+
+ int x1, y1, x2, y2;
+ if (!_coords(ls, lines, x1, y1, x2, y2))
+ return (0);
+
+ TABLE_CHAR(ls, fill, 'x');
+ TABLE_STR(ls, passable, traversable_glyphs);
+ TABLE_STR(ls, wanted, exit_glyphs);
+
+ coord_def tl(x1, y1);
+ coord_def br(x2, y2);
+
+ travel_distance_grid_t tpd;
+ memset(tpd, 0, sizeof(tpd));
+
+ int nzones = 0;
+ for (rectangle_iterator ri(tl, br); ri; ++ri)
{
- if (grd[x][y] == search)
+ const coord_def c = *ri;
+ if (tpd[c.x][c.y] || passable && !strchr(passable, lines(c)))
+ continue;
+
+ if (lines.fill_zone(tpd, c, tl, br, ++nzones, wanted, passable))
+ continue;
+
+ // If wanted wasn't found, fill every passable square that
+ // we just found with the 'fill' glyph.
+ for (rectangle_iterator f(tl, br); f; ++f)
{
- grd[x][y] = replace;
- found = true;
- break;
+ const coord_def fc = *f;
+ if (tpd[fc.x][fc.y] == nzones)
+ lines(fc) = fill;
}
-
- x += dx;
- y += dy;
}
- lua_pushboolean(ls, found);
- return 1;
+ return (0);
+}
+
+LUAFN(dgn_height)
+{
+ LINES(ls, 1, lines);
+ PLUARET(number, lines.height());
}
-static int dgn_replace_random(lua_State *ls)
+LUAFN(dgn_join_the_dots)
{
- dungeon_feature_type search = check_lua_feature(ls, 1);
- dungeon_feature_type replace = check_lua_feature(ls, 2);
+ LINES(ls, 1, lines);
- int x, y;
+ TABLE_INT(ls, x1, -1);
+ TABLE_INT(ls, y1, -1);
+ TABLE_INT(ls, x2, -1);
+ TABLE_INT(ls, y2, -1);
+ TABLE_STR(ls, passable, traversable_glyphs);
+ TABLE_CHAR(ls, fill, '.');
+
+ if (!_valid_coord(ls, lines, --x1, --y1))
+ return (0);
+ if (!_valid_coord(ls, lines, --x2, --y2))
+ return (0);
+
+ coord_def from(x1, y1);
+ coord_def to(x2, y2);
+
+ if (from == to)
+ return (0);
+
+ coord_def at = from;
do
{
- x = random2(GXM);
- y = random2(GYM);
+ char glyph = lines(at);
+
+ if (!strchr(passable, glyph))
+ lines(at) = fill;
+
+ if (at == to)
+ break;
+
+ if (at.x < to.x)
+ {
+ at.x++;
+ continue;
+ }
+
+ if (at.x > to.x)
+ {
+ at.x--;
+ continue;
+ }
+
+ if (at.y > to.y)
+ {
+ at.y--;
+ continue;
+ }
+
+ if (at.y < to.y)
+ {
+ at.y++;
+ continue;
+ }
}
- while (grd[x][y] != search);
+ while (true);
+
+ return (0);
+}
+
+LUAFN(dgn_make_circle)
+{
+ LINES(ls, 1, lines);
+
+ TABLE_INT(ls, x, -1);
+ TABLE_INT(ls, y, -1);
+ TABLE_INT(ls, radius, 1);
+ TABLE_CHAR(ls, fill, 'x');
- grd[x][y] = replace;
+ if (!_valid_coord(ls, lines, --x, --y))
+ return (0);
- return 0;
+ for (int ry = -radius; ry <= radius; ++ry)
+ for (int rx = -radius; rx <= radius; ++rx)
+ if (rx * rx + ry * ry < radius * radius)
+ lines(x + rx, y + ry) = fill;
+
+ return (0);
}
-static int dgn_spotty_level(lua_State *ls)
+LUAFN(dgn_make_diamond)
{
- bool seeded = lua_toboolean(ls, 1);
- int iterations = luaL_checkint(ls, 2);
- bool boxy = lua_toboolean(ls, 3);
+ LINES(ls, 1, lines);
+
+ TABLE_INT(ls, x, -1);
+ TABLE_INT(ls, y, -1);
+ TABLE_INT(ls, radius, 1);
+ TABLE_CHAR(ls, fill, 'x');
+
+ if (!_valid_coord(ls, lines, --x, --y))
+ return (0);
- spotty_level(seeded, iterations, boxy);
- return 0;
+ for (int ry = -radius; ry <= radius; ++ry)
+ for (int rx = -radius; rx <= radius; ++rx)
+ if (std::abs(rx) + std::abs(ry) <= radius)
+ lines(x + rx, y + ry) = fill;
+
+ return (0);
}
-static int dgn_smear_feature(lua_State *ls)
+LUAFN(dgn_make_rounded_square)
{
- int iterations = luaL_checkint(ls, 1);
- bool boxy = lua_toboolean(ls, 2);
- dungeon_feature_type feat = check_lua_feature(ls, 3);
+ LINES(ls, 1, lines);
- int x1 = luaL_checkint(ls, 4);
- int y1 = luaL_checkint(ls, 5);
- int x2 = luaL_checkint(ls, 6);
- int y2 = luaL_checkint(ls, 7);
+ TABLE_INT(ls, x, -1);
+ TABLE_INT(ls, y, -1);
+ TABLE_INT(ls, radius, 1);
+ TABLE_CHAR(ls, fill, 'x');
- _clamp_to_bounds(x1, y1, true);
- _clamp_to_bounds(x2, y2, true);
+ if (!_valid_coord(ls, lines, --x, --y))
+ return (0);
- smear_feature(iterations, boxy, feat, x1, y1, x2, y2);
+ for (int ry = -radius; ry <= radius; ++ry)
+ for (int rx = -radius; rx <= radius; ++rx)
+ if (std::abs(rx) != radius || std::abs(ry) != radius)
+ lines(x + rx, y + ry) = fill;
- return 0;
+ return (0);
}
-static int dgn_count_feature_in_box(lua_State *ls)
+LUAFN(dgn_make_square)
{
- int x1 = luaL_checkint(ls, 1);
- int y1 = luaL_checkint(ls, 2);
- int x2 = luaL_checkint(ls, 3);
- int y2 = luaL_checkint(ls, 4);
- dungeon_feature_type feat = check_lua_feature(ls, 5);
-
- lua_pushnumber(ls, count_feature_in_box(x1, y1, x2, y2, feat));
- return 1;
+ LINES(ls, 1, lines);
+
+ TABLE_INT(ls, x, -1);
+ TABLE_INT(ls, y, -1);
+ TABLE_INT(ls, radius, 1);
+ TABLE_CHAR(ls, fill, 'x');
+
+ if (!_valid_coord(ls, lines, --x, --y))
+ return (0);
+
+ for (int ry = -radius; ry <= radius; ++ry)
+ for (int rx = -radius; rx <= radius; ++rx)
+ lines(x + rx, y + ry) = fill;
+
+ return (0);
}
-static int dgn_count_antifeature_in_box(lua_State *ls)
+// Return a metatable for a point on the map_lines grid.
+LUAFN(dgn_mapgrd_table)
{
- int x1 = luaL_checkint(ls, 1);
- int y1 = luaL_checkint(ls, 2);
- int x2 = luaL_checkint(ls, 3);
- int y2 = luaL_checkint(ls, 4);
- dungeon_feature_type feat = check_lua_feature(ls, 5);
-
- lua_pushnumber(ls, count_antifeature_in_box(x1, y1, x2, y2, feat));
- return 1;
+ MAP(ls, 1, map);
+
+ map_def **mapref = clua_new_userdata<map_def *>(ls, MAPGRD_METATABLE);
+ *mapref = map;
+
+ return (1);
}
-static int dgn_count_neighbours(lua_State *ls)
+LUAFN(dgn_octa_room)
{
- int x = luaL_checkint(ls, 1);
- int y = luaL_checkint(ls, 2);
- dungeon_feature_type feat = check_lua_feature(ls, 3);
+ LINES(ls, 1, lines);
+
+ int default_oblique = std::min(lines.width(), lines.height()) / 2 - 1;
+ TABLE_INT(ls, oblique, default_oblique);
+ TABLE_CHAR(ls, outside, 'x');
+ TABLE_CHAR(ls, inside, '.');
+ TABLE_STR(ls, replace, "");
+
+ int x1, y1, x2, y2;
+ if (!_coords(ls, lines, x1, y1, x2, y2))
+ return (0);
+
+ coord_def tl(x1, y1);
+ coord_def br(x2, y2);
+
+ for (rectangle_iterator ri(tl, br); ri; ++ri)
+ {
+ const coord_def mc = *ri;
+ char glyph = lines(mc);
+ if (replace[0] && !strchr(replace, glyph))
+ continue;
+
+ int ob = 0;
+ ob += std::max(oblique + tl.x - mc.x, 0);
+ ob += std::max(oblique + mc.x - br.x, 0);
+
+ bool is_inside = (mc.y >= tl.y + ob && mc.y <= br.y - ob);
+ lines(mc) = is_inside ? inside : outside;
+ }
+
+ return (0);
+}
+
+LUAFN(dgn_replace_area)
+{
+ LINES(ls, 1, lines);
+
+ TABLE_STR(ls, find, '\0');
+ TABLE_CHAR(ls, replace, '\0');
+
+ int x1, y1, x2, y2;
+ if (!_coords(ls, lines, x1, y1, x2, y2))
+ return (0);
+
+ for (int y = y1; y <= y2; ++y)
+ for (int x = x1; x <= x2; ++x)
+ if (strchr(find, lines(x, y)))
+ lines(x, y) = replace;
+
+ return (0);
+}
+
+LUAFN(dgn_replace_first)
+{
+ LINES(ls, 1, lines);
+
+ TABLE_INT(ls, x, 0);
+ TABLE_INT(ls, y, 0);
+ TABLE_INT(ls, xdir, 2);
+ TABLE_INT(ls, ydir, 2);
+ TABLE_CHAR(ls, find, '\0');
+ TABLE_CHAR(ls, replace, '\0');
+ TABLE_BOOL(ls, required, false);
+
+ if (!_valid_coord(ls, lines, --x, --y))
+ return (0);
+
+ if (xdir < -1 || xdir > 1)
+ {
+ return (luaL_error(ls, "Invalid xdir: %d", xdir));
+ }
- lua_pushnumber(ls, count_neighbours(x, y, feat));
- return 1;
+ if (ydir < -1 || ydir > 1)
+ {
+ return (luaL_error(ls, "Invalid ydir: %d", ydir));
+ }
+
+ while (lines.in_bounds(coord_def(x, y)))
+ {
+ if (lines(x, y) == find)
+ {
+ lines(x, y) = replace;
+ return (0);
+ }
+
+ x += xdir;
+ y += ydir;
+ }
+
+ if (required)
+ return (luaL_error(ls, "Could not find feature '%c' to replace", find));
+
+ return (0);
}
-static int dgn_join_the_dots(lua_State *ls)
+LUAFN(dgn_replace_random)
{
- int from_x = luaL_checkint(ls, 1);
- int from_y = luaL_checkint(ls, 2);
- int to_x = luaL_checkint(ls, 3);
- int to_y = luaL_checkint(ls, 4);
- // TODO enne - push map masks to lua?
- unsigned map_mask = MMT_VAULT;
- bool early_exit = lua_toboolean(ls, 5);
+ LINES(ls, 1, lines);
- coord_def from(from_x, from_y);
- coord_def to(to_x, to_y);
+ TABLE_CHAR(ls, find, '\0');
+ TABLE_CHAR(ls, replace, '\0');
+ TABLE_BOOL(ls, required, false);
- bool ret = join_the_dots(from, to, map_mask, early_exit);
- lua_pushboolean(ls, ret);
+ int x1, y1, x2, y2;
+ if (!_coords(ls, lines, x1, y1, x2, y2))
+ return (0);
- return 1;
+ int count = (x2 - x1) * (y2 - y1);
+ if (!count)
+ {
+ if (required)
+ luaL_error(ls, "%s", "No elements to replace");
+ return (0);
+ }
+
+ std::vector<coord_def> loc;
+ loc.reserve(count);
+
+ for (int y = y1; y <= y2; ++y)
+ for (int x = x1; x <= x2; ++x)
+ if (lines(x, y) == find)
+ loc.push_back(coord_def(x, y));
+
+ if (!loc.size())
+ {
+ if (required)
+ return (luaL_error(ls, "Could not find '%c'", find));
+ }
+
+ int idx = random2(loc.size());
+ lines(loc[idx]) = replace;
+
+ return (0);
}
-static int dgn_fill_disconnected_zones(lua_State *ls)
+LUAFN(dgn_smear_map)
{
- int from_x = luaL_checkint(ls, 1);
- int from_y = luaL_checkint(ls, 2);
- int to_x = luaL_checkint(ls, 3);
- int to_y = luaL_checkint(ls, 4);
+ LINES(ls, 1, lines);
+
+ TABLE_INT(ls, iterations, 1);
+ TABLE_CHAR(ls, smear, 'x');
+ TABLE_STR(ls, onto, ".");
+ TABLE_BOOL(ls, boxy, false);
- dungeon_feature_type feat = check_lua_feature(ls, 5);
+ const int border = 1;
+ int x1, y1, x2, y2;
+ if (!_coords(ls, lines, x1, y1, x2, y2, border))
+ return (0);
- process_disconnected_zones(from_x, from_y, to_x, to_y, true, feat);
+ const int max_test_per_iteration = 10;
+ int sanity = 0;
+ int max_sanity = iterations * max_test_per_iteration;
- return 0;
+ for (int i = 0; i < iterations; i++)
+ {
+ bool diagonals, straights;
+ coord_def mc;
+
+ do
+ {
+ do
+ {
+ if (sanity++ > max_sanity)
+ return (0);
+
+ mc.x = random_range(x1+border, y2-border);
+ mc.y = random_range(y1+border, y2-border);
+ }
+ while (onto[0] && !strchr(onto, lines(mc)));
+
+ // Is there a "smear" feature along the diagonal from mc?
+ diagonals = lines(mc.x+1, mc.y+1) == smear ||
+ lines(mc.x-1, mc.y+1) == smear ||
+ lines(mc.x-1, mc.y-1) == smear ||
+ lines(mc.x+1, mc.y-1) == smear;
+
+ // Is there a "smear" feature up, down, left, or right from mc?
+ straights = lines(mc.x+1, mc.y) == smear ||
+ lines(mc.x-1, mc.y) == smear ||
+ lines(mc.x, mc.y+1) == smear ||
+ lines(mc.x, mc.y-1) == smear;
+ }
+ while (!straights && (boxy || !diagonals));
+
+ lines(mc) = smear;
+ }
+
+ return (0);
+}
+
+LUAFN(dgn_spotty_map)
+{
+ LINES(ls, 1, lines);
+
+ TABLE_STR(ls, replace, "x");
+ TABLE_CHAR(ls, fill, '.');
+ TABLE_BOOL(ls, boxy, true);
+ TABLE_INT(ls, iterations, random2(boxy ? 750 : 1500));
+
+ const int border = 4;
+ int x1, y1, x2, y2;
+ if (!_coords(ls, lines, x1, y1, x2, y2, border))
+ return (0);
+
+ const int max_test_per_iteration = 10;
+ int sanity = 0;
+ int max_sanity = iterations * max_test_per_iteration;
+
+ for (int i = 0; i < iterations; i++)
+ {
+ int x, y;
+ do
+ {
+ if (sanity++ > max_sanity)
+ return (0);
+
+ x = random_range(x1 + border, x2 - border);
+ y = random_range(y1 + border, y2 - border);
+ }
+ while (strchr(replace, lines(x, y))
+ && strchr(replace, lines(x-1, y))
+ && strchr(replace, lines(x+1, y))
+ && strchr(replace, lines(x, y-1))
+ && strchr(replace, lines(x, y+1))
+ && strchr(replace, lines(x-2, y))
+ && strchr(replace, lines(x+2, y))
+ && strchr(replace, lines(x, y-2))
+ && strchr(replace, lines(x, y+2)));
+
+ if (strchr(replace, lines(x, y)))
+ lines(x, y) = fill;
+ if (strchr(replace, lines(x, y-1)))
+ lines(x, y-1) = fill;
+ if (strchr(replace, lines(x, y+1)))
+ lines(x, y+1) = fill;
+ if (strchr(replace, lines(x-1, y)))
+ lines(x-1, y) = fill;
+ if (strchr(replace, lines(x+1, y)))
+ lines(x+1, y) = fill;
+
+ if (boxy)
+ {
+ if (strchr(replace, lines(x-1, y-1)))
+ lines(x-1, y-1) = fill;
+ if (strchr(replace, lines(x+1, y+1)))
+ lines(x+1, y+1) = fill;
+ if (strchr(replace, lines(x-1, y+1)))
+ lines(x-1, y+1) = fill;
+ if (strchr(replace, lines(x+1, y-1)))
+ lines(x+1, y-1) = fill;
+ }
+ }
+
+ return (0);
+}
+
+static int dgn_width(lua_State *ls)
+{
+ LINES(ls, 1, lines);
+ PLUARET(number, lines.width());
}
const struct luaL_reg dgn_build_dlib[] =
{
-{ "mapgrd_table", dgn_mapgrd_table },
-{ "width", dgn_width },
-{ "height", dgn_height },
-{ "fill_area", dgn_fill_area },
-{ "replace_area", dgn_replace_area },
-{ "octa_room", dgn_octa_room },
-{ "make_pillars", dgn_make_pillars },
-{ "make_square", dgn_make_square },
-{ "make_rounded_square", dgn_make_rounded_square },
-{ "make_circle", dgn_make_circle },
-{ "in_bounds", dgn_in_bounds },
-{ "replace_first", dgn_replace_first },
-{ "replace_random", dgn_replace_random },
-{ "spotty_level", dgn_spotty_level },
-{ "smear_feature", dgn_smear_feature },
-{ "count_feature_in_box", dgn_count_feature_in_box },
-{ "count_antifeature_in_box", dgn_count_antifeature_in_box },
-{ "count_neighbours", dgn_count_neighbours },
-{ "join_the_dots", dgn_join_the_dots },
-{ "fill_disconnected_zones", dgn_fill_disconnected_zones },
-
-{ NULL, NULL }
+ { "count_feature_in_box", &dgn_count_feature_in_box },
+ { "count_antifeature_in_box", &dgn_count_antifeature_in_box },
+ { "count_neighbors", &dgn_count_neighbors },
+ { "extend_map", &dgn_extend_map },
+ { "fill_area", &dgn_fill_area },
+ { "fill_disconnected", &dgn_fill_disconnected },
+ { "height", dgn_height },
+ { "join_the_dots", &dgn_join_the_dots },
+ { "make_circle", &dgn_make_circle },
+ { "make_diamond", &dgn_make_diamond },
+ { "make_rounded_square", &dgn_make_rounded_square },
+ { "make_square", &dgn_make_square },
+ { "mapgrd_table", dgn_mapgrd_table },
+ { "octa_room", &dgn_octa_room },
+ { "replace_area", &dgn_replace_area },
+ { "replace_first", &dgn_replace_first },
+ { "replace_random", &dgn_replace_random },
+ { "smear_map", &dgn_smear_map },
+ { "spotty_map", &dgn_spotty_map },
+ { "width", dgn_width },
+
+ { NULL, NULL }
};
diff --git a/crawl-ref/source/makefile.obj b/crawl-ref/source/makefile.obj
index 0ecee6cd2e..183a392cd3 100644
--- a/crawl-ref/source/makefile.obj
+++ b/crawl-ref/source/makefile.obj
@@ -51,7 +51,6 @@ kills.o \
l_crawl.o \
l_debug.o \
l_dgn.o \
-l_dgn_bf.o \
l_dgnbld.o \
l_dgnevt.o \
l_dgngrd.o \
diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc
index b34a05fe59..84506d5a8e 100644
--- a/crawl-ref/source/mapdef.cc
+++ b/crawl-ref/source/mapdef.cc
@@ -365,14 +365,30 @@ rectangle_iterator map_lines::get_iter() const
char map_lines::operator () (const coord_def &c) const
{
- return lines[c.y][c.x];
+ return (lines[c.y][c.x]);
}
char& map_lines::operator () (const coord_def &c)
{
- return lines[c.y][c.x];
+ return (lines[c.y][c.x]);
}
+char map_lines::operator () (int x, int y) const
+{
+ return (lines[y][x]);
+}
+
+char& map_lines::operator () (int x, int y)
+{
+ return (lines[y][x]);
+}
+
+bool map_lines::in_bounds(const coord_def &c) const
+{
+ return (c.x >= 0 && c.y >= 0 && c.x < width() && c.y < height());
+}
+
+
bool map_lines::in_map(const coord_def &c) const
{
return (lines[c.y][c.x] != ' ');
@@ -1353,6 +1369,67 @@ std::string map_lines::add_floortile(const std::string &sub)
return add_tile(sub, true);
}
+bool map_lines::fill_zone(travel_distance_grid_t &tpd, const coord_def &start,
+ const coord_def &tl, const coord_def &br, int zone,
+ const char *wanted, const char *passable) const
+{
+ // This is the map_lines equivalent of _dgn_fill_zone.
+ // It's unfortunately extremely similar, but not close enough to combine.
+
+ bool ret = false;
+ std::list<coord_def> points[2];
+ int cur = 0;
+
+ for (points[cur].push_back(start); !points[cur].empty(); )
+ {
+ for (std::list<coord_def>::const_iterator i = points[cur].begin();
+ i != points[cur].end(); ++i)
+ {
+ const coord_def &c(*i);
+
+ tpd[c.x][c.y] = zone;
+
+ ret |= (wanted && strchr(wanted, (*this)(c)) != NULL);
+
+ for (int yi = -1; yi <= 1; ++yi)
+ for (int xi = -1; xi <= 1; ++xi)
+ {
+ if (!xi && !yi)
+ continue;
+
+ const coord_def cp(c.x + xi, c.y + yi);
+ if (cp.x < tl.x || cp.x > br.x
+ || cp.y < tl.y || cp.y > br.y
+ || !in_bounds(cp) || tpd[cp.x][cp.y]
+ || passable && !strchr(passable, (*this)(cp)))
+ {
+ continue;
+ }
+
+ tpd[cp.x][cp.y] = zone;
+ points[!cur].push_back(cp);
+ }
+ }
+
+ points[cur].clear();
+ cur = !cur;
+ }
+ return (ret);
+}
+
+int map_lines::count_feature_in_box(const coord_def &tl, const coord_def &br,
+ const char *feat) const
+{
+ int result = 0;
+ for (rectangle_iterator ri(tl, br); ri; ++ri)
+ {
+ if (strchr(feat, (*this)(*ri)))
+ result++;
+ }
+
+ return (result);
+}
+
//////////////////////////////////////////////////////////////////////////
// tile_spec
diff --git a/crawl-ref/source/mapdef.h b/crawl-ref/source/mapdef.h
index c08093243c..de55bd511c 100644
--- a/crawl-ref/source/mapdef.h
+++ b/crawl-ref/source/mapdef.h
@@ -302,10 +302,21 @@ public:
rectangle_iterator get_iter() const;
char operator () (const coord_def &c) const;
char& operator () (const coord_def &c);
+ char operator () (int x, int y) const;
+ char& operator () (int x, int y);
+
+ bool in_bounds(const coord_def &c) const;
// Extend map dimensions with glyph 'fill' to minimum width and height.
void extend(int min_width, int min_height, char fill);
+ bool fill_zone(travel_distance_grid_t &tpd, const coord_def &start,
+ const coord_def &tl, const coord_def &br, int zone,
+ const char *wanted, const char *passable) const;
+
+ int count_feature_in_box(const coord_def &tl, const coord_def &br,
+ const char *feat) const;
+
private:
void init_from(const map_lines &map);
template <typename V> void clear_vector(V &vect);