git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@5176 c06c8d41-db1a-0410-9941-cceddc491573
PRG7UT7G56GT4W3FQ3KG5JRPGMKKJBFDLVHDLYFQK6IZW25JQLBQC
QTAXF435XPFZWNFZHMUKPQ7UVNLUK6TG5ER4MKDY25BZF5PZ4JLAC
NVSFIV2ZKP44XHCSCXG6OZVGL67OIFINC34J2EMKTA4KULCERUEAC
SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC
AUXHSGS4EFOPZ6TVZYWNVOUDO7NYKUKE3HBKGQQWTALSVFOE3HAAC
ZLQAAP55CJ77XIJN3DZVPT4GTTVLIBFJLIJJKI6L5UBSHX7VUK6AC
7Y5HSDFKA5TPLS2TWTRFMQVX6UXUDHXU5MUMXQSDFAIY4THQ3BIQC
ED62QWGKBPORWVKDFOQRKJXEIWZVNGR3O4KWQBDSRNPT36AYOQYAC
TLA5UN6LZPXGKERI27EFY4HKIIU3VU5Y7ZU54WXL6ANBUV2VOTMQC
W45PMU4HNPSAMMEBJ4XH4MTHLPVIASZT4FXTBPID5LFXKIMNUBKAC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
KCHX2F3JFEWOZT3WMJVZAAQUU2QSZ5Q7RDCD7WUJ7VE65J52JFUQC
77H4BWWPPGLM3PLZH4QTAJRXIZTSDVNCOKZE223I437FN2UJ34RQC
B7MSPF6X2RLGWN4M6ZZF3WSOPKGYPTTD7LIJVST7DXN27DG6JHNAC
TZ55IZNANEJO2WDTKYWVLY2W2VV6BR7WKIN7XLNISAMMFT6LG2WQC
BTO5WE4OEK64DZQVNYLOESM74KKQNE7KSNMQVF5UDB26OBKP7ORQC
3XZOL3FFQZITUJIGDD6B6V6ZYMBN524JKNN6ZPJAXEC7RY433I3QC
MSQI3TH6T62JAXQGLL52QZCWAMC372TGB6ZNNRDGUGMJKBNNV2VAC
4WOHWWHMQPU22PK6TN5KIFCB4G22NDF5OQ3ZEYDK4Z5U7XCB5IWQC
FSD7GIK3YLZXWLEH37BU6KV3IUCFGXPQL6IZ7H65YWNRBEKDBX5AC
FZAQNANLZOQHX675KR5GE2ZAVNT4AWX4TWEUJXXEZMOXWQ5FDHOAC
2C6B6QRTOK2ZMK2ZOF3EPSFUZTKG5B3IZXWBWIUYC4ZOVGQ2OV2QC
QIDA6PWWBPR6IJOXFCSPCGWV45PVRZ4TPWSL2TDATNVTYLDMVESQC
B3SRWSFITQMJRVEBHGQQJARETYPSSDV6XKMQSSUTXEHTXRZKIQJQC
SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC
}
static dungeon_feature_type _get_lua_feature(lua_State *ls, int idx)
{
dungeon_feature_type feat = (dungeon_feature_type)0;
if (lua_isnumber(ls, idx))
feat = (dungeon_feature_type)luaL_checkint(ls, idx);
else if (lua_isstring(ls, idx))
feat = dungeon_feature_by_name(luaL_checkstring(ls, idx));
else
luaL_argerror(ls, idx, "Feature must be a string or a feature index.");
return feat;
}
static void _clamp_to_bounds(int &x, int &y)
{
x = std::min(std::max(x, X_BOUND_1+1), X_BOUND_2-1);
y = std::min(std::max(y, Y_BOUND_1+1), Y_BOUND_2-1);
}
static int dgn_fill_area(lua_State *ls)
{
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 = _get_lua_feature(ls, 5);
if (!feat)
{
luaL_argerror(ls, 5, "Invalid feature.");
return 0;
}
_clamp_to_bounds(x1, y1);
_clamp_to_bounds(x2, y2);
if (x2 < x1)
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;
return 0;
}
static int dgn_replace_area(lua_State *ls)
{
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 = _get_lua_feature(ls, 5);
if (!search)
{
luaL_argerror(ls, 5, "Invalid feature.");
return 0;
}
dungeon_feature_type replace = _get_lua_feature(ls, 6);
if (!replace)
{
luaL_argerror(ls, 6, "Invalid feature.");
return 0;
}
// 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);
for (int y = y1; y <= y2; y++)
for (int x = x1; x <= x2; x++)
if (grd[x][y] == search)
grd[x][y] = replace;
return 0;
}
static int dgn_octa_room(lua_State *ls)
{
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 = _get_lua_feature(ls, 6);
if (!fill)
{
luaL_argerror(ls, 6, "Invalid feature.");
return 0;
}
spec_room sr;
sr.x1 = x1;
sr.x2 = x2;
sr.y1 = y1;
sr.y2 = y2;
octa_room(sr, oblique, fill);
return 0;
}
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 = _get_lua_feature(ls, 8);
if (!fill)
{
luaL_argerror(ls, 8, "Invalid feature.");
return 0;
}
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);
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);
lua_call(ls, 4, 0);
}
return 0;
}
static int dgn_make_square(lua_State *ls)
{
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 = _get_lua_feature(ls, 4);
if (!fill)
{
luaL_argerror(ls, 4, "Invalid feature.");
return 0;
}
for (int x = -radius; x <= radius; x++)
for (int y = -radius; y <= radius; y++)
grd[center_x + x][center_y + y] = fill;
return 0;
}
static int dgn_make_rounded_square(lua_State *ls)
{
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 = _get_lua_feature(ls, 4);
if (!fill)
{
luaL_argerror(ls, 4, "Invalid feature.");
return 0;
}
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;
return 0;
}
static int dgn_make_circle(lua_State *ls)
{
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 = _get_lua_feature(ls, 4);
if (!fill)
{
luaL_argerror(ls, 4, "Invalid feature.");
return 0;
}
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;
return 0;
}
static int dgn_in_bounds(lua_State *ls)
{
int x = luaL_checkint(ls, 1);
int y = luaL_checkint(ls, 2);
lua_pushboolean(ls, in_bounds(x, y));
return 1;
}
static int dgn_replace_first(lua_State *ls)
{
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 = _get_lua_feature(ls, 5);
if (!search)
{
luaL_argerror(ls, 5, "Invalid feature.");
lua_pushboolean(ls, false);
return 1;
}
dungeon_feature_type replace = _get_lua_feature(ls, 6);
if (!replace)
{
luaL_argerror(ls, 6, "Invalid feature.");
lua_pushboolean(ls, false);
return 1;
}
_clamp_to_bounds(x, y);
bool found = false;
while (in_bounds(x, y))
{
if (grd[x][y] == search)
{
grd[x][y] = replace;
found = true;
break;
}
x += dx;
y += dy;
}
lua_pushboolean(ls, found);
return 1;
}
static int dgn_replace_random(lua_State *ls)
{
dungeon_feature_type search = _get_lua_feature(ls, 1);
if (!search)
{
luaL_argerror(ls, 1, "Invalid feature.");
return 0;
}
dungeon_feature_type replace = _get_lua_feature(ls, 2);
if (!replace)
{
luaL_argerror(ls, 2, "Invalid feature.");
return 0;
}
int x, y;
do
{
x = random2(GXM);
y = random2(GYM);
}
while (grd[x][y] != search);
grd[x][y] = replace;
return 0;
}
static int dgn_spotty_level(lua_State *ls)
{
bool seeded = lua_toboolean(ls, 1);
int iterations = luaL_checkint(ls, 2);
bool boxy = lua_toboolean(ls, 3);
spotty_level(seeded, iterations, boxy);
return 0;
}
static int dgn_smear_feature(lua_State *ls)
{
int iterations = luaL_checkint(ls, 1);
bool boxy = lua_toboolean(ls, 2);
dungeon_feature_type feat = _get_lua_feature(ls, 3);
if (!feat)
{
luaL_argerror(ls, 3, "Invalid feature.");
return 0;
}
int x1 = luaL_checkint(ls, 4);
int y1 = luaL_checkint(ls, 5);
int x2 = luaL_checkint(ls, 6);
int y2 = luaL_checkint(ls, 7);
_clamp_to_bounds(x1, y1);
_clamp_to_bounds(x2, y2);
smear_feature(iterations, boxy, feat, x1, y1, x2, y2);
return 0;
}
static int dgn_count_feature_in_box(lua_State *ls)
{
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 = _get_lua_feature(ls, 5);
if (!feat)
{
luaL_argerror(ls, 5, "Invalid feature.");
lua_pushnil(ls);
return 1;
}
lua_pushnumber(ls, count_feature_in_box(x1, y1, x2, y2, feat));
return 1;
}
static int dgn_count_antifeature_in_box(lua_State *ls)
{
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 = _get_lua_feature(ls, 5);
if (!feat)
{
luaL_argerror(ls, 5, "Invalid feature.");
lua_pushnil(ls);
return 1;
}
lua_pushnumber(ls, count_antifeature_in_box(x1, y1, x2, y2, feat));
return 1;
}
static int dgn_count_neighbours(lua_State *ls)
{
int x = luaL_checkint(ls, 1);
int y = luaL_checkint(ls, 2);
dungeon_feature_type feat = _get_lua_feature(ls, 3);
if (!feat)
{
luaL_argerror(ls, 3, "Invalid feature.");
lua_pushnil(ls);
return 1;
}
lua_pushnumber(ls, count_neighbours(x, y, feat));
return 1;
}
static int dgn_join_the_dots(lua_State *ls)
{
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);
coord_def from(from_x, from_y);
coord_def to(to_x, to_y);
bool ret = join_the_dots(from, to, map_mask, early_exit);
lua_pushboolean(ls, ret);
return 1;
{ "change_level_flags", dgn_change_level_flags},
{ "change_branch_flags", dgn_change_branch_flags},
{ "get_floor_colour", dgn_get_floor_colour},
{ "get_rock_colour", dgn_get_rock_colour},
{ "change_floor_colour", dgn_change_floor_colour},
{ "change_rock_colour", dgn_change_rock_colour},
{ "set_lt_callback", lua_dgn_set_lt_callback},
{ "fixup_stairs", dgn_fixup_stairs},
{ "floor_halo", dgn_floor_halo},
{ "random_walk", dgn_random_walk},
{ "apply_area_cloud", dgn_apply_area_cloud},
{ "change_level_flags", dgn_change_level_flags },
{ "change_branch_flags", dgn_change_branch_flags },
{ "get_floor_colour", dgn_get_floor_colour },
{ "get_rock_colour", dgn_get_rock_colour },
{ "change_floor_colour", dgn_change_floor_colour },
{ "change_rock_colour", dgn_change_rock_colour },
{ "set_lt_callback", lua_dgn_set_lt_callback },
{ "fixup_stairs", dgn_fixup_stairs },
{ "floor_halo", dgn_floor_halo },
{ "random_walk", dgn_random_walk },
{ "apply_area_cloud", dgn_apply_area_cloud },
// building routines
{ "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 },
struct spec_room
{
bool created;
bool hooked_up;
int x1;
int y1;
int x2;
int y2;
spec_room() : created(false), hooked_up(false), x1(0), y1(0), x2(0), y2(0)
{
}
};
bool join_the_dots(const coord_def &from, const coord_def &to,
unsigned mmask, bool early_exit = false);
void spotty_level(bool seeded, int iterations, bool boxy);
void smear_feature(int iterations, bool boxy, dungeon_feature_type feature,
int x1, int y1, int x2, int y2);
bool octa_room(spec_room &sr, int oblique_max,
dungeon_feature_type type_floor);
int count_feature_in_box(int x0, int y0, int x1, int y1,
dungeon_feature_type feat);
int count_antifeature_in_box(int x0, int y0, int x1, int y1,
dungeon_feature_type feat);
int count_neighbours(int x, int y, dungeon_feature_type feat);
};
struct spec_room
{
bool created;
bool hooked_up;
int x1;
int y1;
int x2;
int y2;
spec_room() : created(false), hooked_up(false), x1(0), y1(0), x2(0), y2(0)
{
}
_count_feature_in_box(px-2, py-2, px+3, py+3, DNGN_ROCK_WALL) +
_count_feature_in_box(px-2, py-2, px+3, py+3, DNGN_CLOSED_DOOR) +
_count_feature_in_box(px-2, py-2, px+3, py+3, DNGN_SECRET_DOOR) +
_count_feature_in_box(px-2, py-2, px+3, py+3, DNGN_FLOOR);
count_feature_in_box(px-2, py-2, px+3, py+3, DNGN_ROCK_WALL) +
count_feature_in_box(px-2, py-2, px+3, py+3, DNGN_CLOSED_DOOR) +
count_feature_in_box(px-2, py-2, px+3, py+3, DNGN_SECRET_DOOR) +
count_feature_in_box(px-2, py-2, px+3, py+3, DNGN_FLOOR);
void smear_feature(int iterations, bool boxy, dungeon_feature_type feature,
int x1, int y1, int x2, int y2)
{
for (int i = 0; i < iterations; i++)
{
int x, y;
bool diagonals, straights;
do
{
x = random_range(x1+1, x2-1);
y = random_range(y1+1, y2-1);
diagonals = grd[x+1][y+1] == feature ||
grd[x-1][y+1] == feature ||
grd[x-1][y-1] == feature ||
grd[x+1][y-1] == feature;
straights = grd[x+1][y] == feature ||
grd[x-1][y] == feature ||
grd[x][y+1] == feature ||
grd[x][y-1] == feature;
}
while (grd[x][y] == feature || !straights && (boxy || !diagonals));
lua {{
-- TODO enne - most of these should probably get moved back into C++
function fill_area(x1, y1, x2, y2, feature)
for x = x1, x2 do
for y = y1, y2 do
dgn.grid(x, y, feature)
end
end
end
function octa_room(x1, y1, x2, y2, oblique, fill)
local ob_temp = oblique
local rock_wall = dgn.feature_number("rock_wall")
local shallow_water = dgn.feature_number("shallow_water")
local deep_water = dgn.feature_number("deep_water")
local floor = dgn.feature_number("floor")
for x = x1, x2 do
for y = y1 + ob_temp, y2 - ob_temp do
if dgn.grid(x, y) == rock_wall then
dgn.grid(x, y, fill)
end
if dgn.grid(x, y) == floor and (fill == shallow_water or fill == deep_water) then
dgn.grid(x, y, shallow_water)
end
end
if x > x2 - oblique then
ob_temp = ob_temp + 1
elseif ob_temp > 0 then
ob_temp = ob_temp - 1
end
end
end
function pillars(center_x, center_y, num, flip_x, big_radius,
pillar_radius, pillar_routine, fill)
for i = 0, num - 1 do
local angle = i * 2 * math.pi / num
local x = math.floor(math.cos(angle) * big_radius * flip_x + 0.5)
local y = math.floor(math.sin(angle) * big_radius + 0.5)
pillar_routine(center_x + x, center_y + y, pillar_radius, fill)
end
end
-- begin pillar functions
function pillar_square(center_x, center_y, radius, fill)
for x = -radius, radius do
for y = -radius, radius do
dgn.grid(center_x + x, center_y + y, fill)
end
end
end
function pillar_rounded_square(center_x, center_y, radius, fill)
for x = -radius, radius do
for y = -radius, radius do
if math.abs(x) ~= radius or math.abs(y) ~= radius then
dgn.grid(center_x + x, center_y + y, fill)
end
end
end
end
function pillar_circle(center_x, center_y, radius, fill)
for x = -radius, radius do
for y = -radius, radius do
if x * x + y * y < radius * radius then
dgn.grid(center_x + x, center_y + y, fill)
end
end
end
end
-- end pillar functions
function select_from_weighted_table(tb)
local value = nil
local rollsize = 0
for temp_val, temp_weight in pairs (tb) do
if rollsize == 0 then
value = temp_val
rollsize = temp_weight
else
rollsize = rollsize + temp_weight
if crawl.random2(rollsize) < temp_weight then
value = temp_val
end
end
end
return value
end
-- Randomly selects a grid with feature 'search' and sets it to 'replace'
function replace_random(search, replace)
local gxm, gym = dgn.max_bounds()
local feature = nil, x, y
while feature ~= search do
x = crawl.random2(gxm)
y = crawl.random2(gym)
feature = dgn.grid(x, y)
end
dgn.grid(x, y, replace)
end
function valid(x, y)
local gxm, gym = dgn.max_bounds()
return (x >= 0 and y >= 0 and x < gxm and y < gym)
end
-- Walks from x, y along dx,dy until it finds 'search'
function replace_first(x, y, dx, dy, search, replace)
local feature = dgn.grid(x, y)
while feature ~= search and valid(x,y) do
x = x + dx
y = y + dy
feature = dgn.grid(x, y)
end
if valid(x, y) then
dgn.grid(x, y, replace)
return true
else
return false
end
end
function spotty_level(boxy, x1, y1, x2, y2)
local iterations
-- boxy levels have more clearing, so they get fewer iterations
if boxy then
iterations = 200 + crawl.random2(750)
else
iterations = 200 + crawl.random2(1500)
end
make_spotty(iterations, boxy, x1, y1, x2, y2)
end
-- randomly turns walls into floors
function make_spotty(iterations, boxy, x1, y1, x2, y2)
if x2 - x1 - 8 <= 0 or y2 - y1 - 8 <= 0 then
return
end
local wall = dgn.feature_number("rock_wall")
local floor = dgn.feature_number("floor")
for i = 1, iterations do
local x, y
repeat
x = crawl.random2(x2 - x1 - 7) + x1 + 4
y = crawl.random2(y2 - y1 - 7) + y1 + 4
until dgn.grid(x, y) ~= wall or
dgn.grid(x-1, y) ~= wall or
dgn.grid(x+1, y) ~= wall or
dgn.grid(x, y-1) ~= wall or
dgn.grid(x, y+1) ~= wall or
dgn.grid(x-2, y) ~= wall or
dgn.grid(x+2, y) ~= wall or
dgn.grid(x, y-2) ~= wall or
dgn.grid(x, y+2) ~= wall
-- convenience function
function replace_grid(x, y, search, replace)
if dgn.grid(x, y) == search then
dgn.grid(x, y, replace)
end
end
replace_grid(x, y, wall, floor)
replace_grid(x, y-1, wall, floor)
replace_grid(x, y+1, wall, floor)
replace_grid(x-1, y, wall, floor)
replace_grid(x+1, y, wall, floor)
if boxy then
replace_grid(x-1, y-1, wall, floor)
replace_grid(x+1, y+1, wall, floor)
replace_grid(x-1, y+1, wall, floor)
replace_grid(x+1, y-1, wall, floor)
end
end
end
-- randomly extends walls onto floors
function smear_feature(iterations, boxy, feature, x1, y1, x2, y2)
for i = 1, iterations do
local x, y
function check_box(x, y, feature)
return dgn.grid(x+1, y) == feature or
dgn.grid(x-1, y) == feature or
dgn.grid(x, y+1) == feature or
dgn.grid(x, y-1) == feature
end
function check_diagonal(x, y, feature)
return dgn.grid(x+1, y+1) == feature or
dgn.grid(x-1, y+1) == feature or
dgn.grid(x-1, y-1) == feature or
dgn.grid(x+1, y-1) == feature
end
repeat
x = crawl.random2(x2 - x1 - 2) + x1 + 1
y = crawl.random2(y2 - y1 - 2) + y1 + 1
until dgn.grid(x, y) ~= feature and
(check_box(x, y, feature) or
not boxy and check_diagonal(x, y, feature))
dgn.grid(x, y, feature)
end
end
}}
fill_area(10, 10, gxm - 10, 10 + width, floor)
fill_area(10, 60 - width, gxm - 10, gym - 10, floor)
fill_area(10, 10, 10 + width, gym - 10, floor)
fill_area(60 - width, 10, gxm - 10, gym - 10, floor)
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(10, gym/2 - width2, gxm - 10, gym/2 + width2, floor)
fill_area(gxm/2 - width2, 10, gxm/2 + width2, gym - 10, floor)
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(10, gym/2 - height - 1, gxm - 10, gym/2 - height - 1, clear)
fill_area(10, gym/2 + height + 1, gxm - 10, gym/2 + height + 1, clear)
fill_area(gxm/2 - width - 1, 10, gxm/2 - width - 1, gym - 10, clear)
fill_area(gxm/2 + width + 1, 10, gxm/2 + width + 1, gym - 10, clear)
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)
fill_area(10, gym/2 - height, gxm - 10, gym/2 + height, floor)
fill_area(gxm/2 - width, 10, gxm/2 + width, gym - 10, floor)
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)
// Only the first arg does anything now. Maybe this should
// select from a variable number of table args?
lua_pop(ls, lua_gettop(ls) - 1);
// Keep max value on the stack, as it could be any type of value.
lua_pushnil(ls);
int rollsize = 0;
lua_pushnil(ls);
while (lua_next(ls, table_idx) != 0)
{
const int weight_idx = -1;
const int key_idx = -2;
int this_weight = lua_isnil(ls, weight_idx) ?
1 : (int)lua_tonumber(ls, weight_idx);
if (rollsize > 0)
{
rollsize += this_weight;
if (random2(rollsize) < this_weight)
{
lua_pushvalue(ls, key_idx);
lua_replace(ls, value_idx);
}
}
else
{
lua_pushvalue(ls, key_idx);
lua_replace(ls, value_idx);
rollsize = this_weight;
}
lua_pop(ls, 1);
}
lua_pushvalue(ls, value_idx);
return 1;
}