summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/docs/develop/level_design.txt14
-rw-r--r--crawl-ref/source/clua.cc105
-rw-r--r--crawl-ref/source/clua.h2
-rw-r--r--crawl-ref/source/dat/clua/dungeon.lua24
-rw-r--r--crawl-ref/source/dat/entry.des50
-rw-r--r--crawl-ref/source/luadgn.cc314
-rw-r--r--crawl-ref/source/mapdef.cc411
-rw-r--r--crawl-ref/source/mapdef.h108
-rw-r--r--crawl-ref/source/maps.h2
-rw-r--r--crawl-ref/source/util/levcomp.ypp2
10 files changed, 614 insertions, 418 deletions
diff --git a/crawl-ref/docs/develop/level_design.txt b/crawl-ref/docs/develop/level_design.txt
index f68a1b166f..0788a355f7 100644
--- a/crawl-ref/docs/develop/level_design.txt
+++ b/crawl-ref/docs/develop/level_design.txt
@@ -736,6 +736,9 @@ FTILE: . = floor_grass:20 / floor_dirt / none
destroyed, this floor tile will be used in place of the normal floor.
Thus, it can be useful even for non-floor features.
+ For convenience, multiple glyphs can be specified together as a
+ group, e.g. ".[{( = floor_orc".
+
Like COLOUR, this should be used sparingly.
RTILE: x = wall_hive:15 / wall_lair / none
@@ -1847,6 +1850,17 @@ mons_from_index, change_level_flags, change_branch_flags,
set_random_mon_list
+Additionally, the dgn module provides a global "grd" variable that
+can access the current map glyphs. The top left symbol in the map
+can be assigned like this:
+
+ grd[1][1] = 'x'
+
+The bottom right symbol can be assigned like this:
+
+ grd[width()][height()] = "."
+
+
Lua API - global game state
---------------------------
diff --git a/crawl-ref/source/clua.cc b/crawl-ref/source/clua.cc
index 9743019e9d..44f4cd0393 100644
--- a/crawl-ref/source/clua.cc
+++ b/crawl-ref/source/clua.cc
@@ -597,6 +597,7 @@ void luaopen_crawl(lua_State *ls);
void luaopen_file(lua_State *ls);
void luaopen_options(lua_State *ls);
void luaopen_monsters(lua_State *ls);
+void luaopen_grd(lua_State *ls);
void luaopen_globals(lua_State *ls);
void CLua::init_lua()
@@ -626,6 +627,7 @@ void CLua::init_lua()
luaopen_file(_state);
luaopen_options(_state);
luaopen_monsters(_state);
+ luaopen_grd(_state);
luaopen_globals(_state);
@@ -2788,6 +2790,109 @@ void luaopen_monsters(lua_State *ls)
luaL_openlib(ls, "mons", mons_lib, 0);
}
+/////////////////////////////////////////////////////////////////////
+// grd and grd_col handling (i.e. map_lines in a metatable)
+
+struct mapcolumn
+{
+ map_def* map;
+ int col;
+};
+
+static int grd_get(lua_State *ls)
+{
+ // Return a metatable for this column in the map grid.
+ map_def *map = *(map_def **) luaL_checkudata(ls, 1, GRD_METATABLE);
+
+ int column = luaL_checkint(ls, 2);
+
+ mapcolumn *mapref = clua_new_userdata<mapcolumn>(ls, GRD_COL_METATABLE);
+ mapref->map = map;
+ mapref->col = column;
+
+ return (1);
+}
+
+static int grd_set(lua_State *ls)
+{
+ return (luaL_error(ls, "%s", "Cannot assign to read-only table."));
+}
+
+static char* grd_glyph(lua_State *ls, int &col, int &row)
+{
+ mapcolumn *mapc = (mapcolumn *)luaL_checkudata(ls, 1, GRD_COL_METATABLE);
+ row = luaL_checkint(ls, 2);
+ col = mapc->col;
+
+ map_lines &lines = mapc->map->map;
+ if (row < 1 || col < 1 || col > lines.width() || row > lines.height())
+ {
+ return (NULL);
+ }
+
+ coord_def mc(col - 1, row - 1);
+ return (&lines(mc));
+}
+
+static int grd_col_get(lua_State *ls)
+{
+ int col, row;
+ char *gly = grd_glyph(ls, col, row);
+ if (!gly)
+ return (luaL_error(ls, "Invalid coords: %d, %d", col, row));
+
+ char buf[2];
+ buf[0] = *gly;
+ buf[1] = '\0';
+
+ lua_pushstring(ls, buf);
+
+ return (1);
+}
+
+static int grd_col_set(lua_State *ls)
+{
+ int col, row;
+ char *gly = grd_glyph(ls, col, row);
+ if (!gly)
+ return (luaL_error(ls, "Invalid coords: %d, %d", col, row));
+
+ const char *str = luaL_checkstring(ls, 3);
+ if (!str[0] || str[1])
+ return (luaL_error(ls, "%s", "grd must be set to a single char."));
+
+ (*gly) = str[0];
+
+ return (0);
+}
+
+void luaopen_grd(lua_State *ls)
+{
+ // grd table
+ luaL_newmetatable(ls, GRD_METATABLE);
+ lua_pushstring(ls, "__index");
+ lua_pushcfunction(ls, grd_get);
+ lua_settable(ls, -3);
+
+ lua_pushstring(ls, "__newindex");
+ lua_pushcfunction(ls, grd_set);
+ lua_settable(ls, -3);
+
+ lua_pop(ls, 1);
+
+ // grd col table
+ luaL_newmetatable(ls, GRD_COL_METATABLE);
+ lua_pushstring(ls, "__index");
+ lua_pushcfunction(ls, grd_col_get);
+ lua_settable(ls, -3);
+
+ lua_pushstring(ls, "__newindex");
+ lua_pushcfunction(ls, grd_col_set);
+ lua_settable(ls, -3);
+
+ lua_pop(ls, 1);
+}
+
//////////////////////////////////////////////////////////////////////
// Miscellaneous globals
diff --git a/crawl-ref/source/clua.h b/crawl-ref/source/clua.h
index a6ed4ac413..f98e80076f 100644
--- a/crawl-ref/source/clua.h
+++ b/crawl-ref/source/clua.h
@@ -320,5 +320,7 @@ void print_clua_stack();
#define MAP_METATABLE "dgn.mtmap"
#define DEVENT_METATABLE "dgn.devent"
#define MAPMARK_METATABLE "dgn.mapmark"
+#define GRD_METATABLE "dgn.grd"
+#define GRD_COL_METATABLE "dgn.grdcol"
#endif
diff --git a/crawl-ref/source/dat/clua/dungeon.lua b/crawl-ref/source/dat/clua/dungeon.lua
index 5d178b891d..b1cc8de795 100644
--- a/crawl-ref/source/dat/clua/dungeon.lua
+++ b/crawl-ref/source/dat/clua/dungeon.lua
@@ -75,6 +75,10 @@ function dgn_map_meta_wrap(map, tab)
return crawl.err_trace(val, map, ...)
end
end
+
+ -- Convenience global variable, e.g. grd[x][y] = 'x'
+ meta['grd'] = dgn.grd_table(map)
+
meta['_G'] = meta
meta.wrapped_instance = map
return meta
@@ -89,19 +93,21 @@ function dgn_set_map(map)
g_dgn_curr_map = map
end
-function dgn_run_map(prelude, main)
- if prelude or main then
+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
- local fn = setfenv(prelude, env)
- if not main then
- return fn()
- end
- fn()
+ ret = setfenv(prelude, env)()
+ end
+ if map then
+ ret = setfenv(map, env)()
+ dgn.normalise(g_dgn_curr_map)
end
if main then
- return setfenv(main, env)()
+ ret = setfenv(main, env)()
end
+ return ret
end
end
@@ -387,4 +393,4 @@ dgn.good_scrolls = [[
w:5 scroll of vorpalise weapon /
w:5 scroll of immolation /
w:5 scroll of vulnerability
- ]] \ No newline at end of file
+ ]]
diff --git a/crawl-ref/source/dat/entry.des b/crawl-ref/source/dat/entry.des
index a1c3d59a0e..591e284510 100644
--- a/crawl-ref/source/dat/entry.des
+++ b/crawl-ref/source/dat/entry.des
@@ -2484,7 +2484,7 @@ ORIENT: float
MONS: plant
SHUFFLE: 1x
SUBST: x = '
-FTILE: ' = floor_grass, 1 = floor_grass, { = floor_grass
+FTILE: '1{ = floor_grass
FTILE: . = floor_grass / floor_normal
COLOUR: ' = green
COLOUR: . = green / none
@@ -3495,9 +3495,7 @@ MONS: w:30 nothing / ooze / w:2 jelly / giant cockroach / w:2 worm / \
# There is a very slight chance that a jelly or an intelligent monster
# (hobgoblin) might spawn inside near the door. This is okay; added an exit.
ORIENT: float
-FTILE: 1=floor_dirt, 2=floor_dirt, 3=floor_dirt, 4=floor_dirt, +=floor_dirt
-FTILE: A=floor_dirt, B=floor_dirt, C=floor_dirt, D=floor_dirt, E=floor_dirt
-FTILE: a=floor_dirt, b=floor_dirt, c=floor_dirt, d=floor_dirt, e=floor_dirt
+FTILE: 1234+ABCDEabcde = floor_dirt
SHUFFLE: abcde / fghij
SUBST: f=A, g=B, h=C, i=D, j=E
SUBST: a=mx, b=mx, c=mx, d=mx, e=mx
@@ -4822,7 +4820,7 @@ ENDMAP
NAME: misc_entry_001
TAGS: entry no_monster_gen
RTILE: x = wall_hall
-FTILE: . = floor_hall, ( = floor_hall, [ = floor_hall, { = floor_hall
+FTILE: .([{ = floor_hall
ORIENT: float
MAP
@@ -4885,9 +4883,7 @@ NAME: exit_the_forest
TAGS: entry no_rotate no_pool_fixup
ORIENT: northwest
MONS: plant
-FTILE: . = floor_lair
-FTILE: t = floor_lair
-FTILE: 1 = floor_lair
+FTILE: .t1 = floor_lair
MAP
ttttttttttttttttttttttttttttttttttttttttttt
tttttttttttt1ttttttwwtttttttttttttttttttttt
@@ -4916,3 +4912,41 @@ tt....
t..
t.
ENDMAP
+
+###########################################################
+# Basic island, with variations
+#
+NAME: enne_octagon_isle
+ORIENT: float
+TAGS: entry
+FTILE: '[({ = floor_sand_stone
+SUBST: ' = .
+{{
+ map_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})
+ end
+}}
+SUBST: W:xw
+MAP
+ xxxxxxxxxxxxx
+x.............x
+x.............x
+x.............x
+x.............x
+......www......
+.....w[''w.....
+@....w'{'w....@
+.....w''(w.....
+......www......
+x.............x
+x.............x
+x.............x
+x.............x
+ xxxxxxxxxxxxx
+ENDMAP
diff --git a/crawl-ref/source/luadgn.cc b/crawl-ref/source/luadgn.cc
index 226138780f..5e7a366039 100644
--- a/crawl-ref/source/luadgn.cc
+++ b/crawl-ref/source/luadgn.cc
@@ -832,46 +832,20 @@ static int dgn_orient(lua_State *ls)
PLUARET(string, map_section_name(map->orient));
}
-static int dgn_shuffle(lua_State *ls)
+static int dgn_map_add_transform(
+ lua_State *ls,
+ std::string (map_lines::*add)(const std::string &s))
{
MAP(ls, 1, map);
if (lua_gettop(ls) == 1)
- return dlua_stringtable(ls, map->get_shuffle_strings());
+ luaL_error(ls, "Expected args, got none.");
for (int i = 2, size = lua_gettop(ls); i <= size; ++i)
{
if (lua_isnil(ls, i))
- map->map.clear_shuffles();
- else
{
- std::string err = map->map.add_shuffle(luaL_checkstring(ls, i));
- if (!err.empty())
- luaL_error(ls, err.c_str());
+ luaL_error(ls, "Unexpected nil.");
}
- }
-
- return (0);
-}
-
-static int dgn_shuffle_remove(lua_State *ls)
-{
- MAP(ls, 1, map);
- for (int i = 2, size = lua_gettop(ls); i <= size; ++i)
- map->map.remove_shuffle(luaL_checkstring(ls, i));
- return (0);
-}
-
-static int dgn_map_add_transform(
- lua_State *ls,
- std::string (map_lines::*add)(const std::string &s),
- void (map_lines::*erase)())
-{
- MAP(ls, 1, map);
-
- for (int i = 2, size = lua_gettop(ls); i <= size; ++i)
- {
- if (lua_isnil(ls, i))
- (map->map.*erase)();
else
{
std::string err = (map->map.*add)(luaL_checkstring(ls, i));
@@ -883,30 +857,30 @@ static int dgn_map_add_transform(
return (0);
}
+static int dgn_shuffle(lua_State *ls)
+{
+ return dgn_map_add_transform(ls, &map_lines::add_shuffle);
+}
+
static int dgn_subst(lua_State *ls)
{
- return dgn_map_add_transform(ls, &map_lines::add_subst,
- &map_lines::clear_substs);
+ return dgn_map_add_transform(ls, &map_lines::add_subst);
}
static int dgn_nsubst(lua_State *ls)
{
- return dgn_map_add_transform(ls, &map_lines::add_nsubst,
- &map_lines::clear_nsubsts);
+ return dgn_map_add_transform(ls, &map_lines::add_nsubst);
}
static int dgn_colour(lua_State *ls)
{
- return dgn_map_add_transform(ls,
- &map_lines::add_colour,
- &map_lines::clear_colours);
+ return dgn_map_add_transform(ls, &map_lines::add_colour);
}
-static int dgn_subst_remove(lua_State *ls)
+static int dgn_normalise(lua_State *ls)
{
MAP(ls, 1, map);
- for (int i = 2, size = lua_gettop(ls); i <= size; ++i)
- map->map.remove_subst(luaL_checkstring(ls, i));
+ map->map.normalise();
return (0);
}
@@ -2082,6 +2056,33 @@ static void _clamp_to_bounds(int &x, int &y, bool edge_ok = false)
y = std::min(std::max(y, Y_BOUND_1 + edge_offset), Y_BOUND_2 - edge_offset);
}
+// Return a metatable for a point on the map_lines grid.
+static int dgn_grd_table(lua_State *ls)
+{
+ MAP(ls, 1, map);
+
+ map_def **mapref = clua_new_userdata<map_def *>(ls, GRD_METATABLE);
+ *mapref = map;
+
+ return (1);
+}
+
+static int dgn_width(lua_State *ls)
+{
+ MAP(ls, 1, map);
+
+ lua_pushnumber(ls, map->map.width());
+ return (1);
+}
+
+static int dgn_height(lua_State *ls)
+{
+ MAP(ls, 1, map);
+
+ lua_pushnumber(ls, map->map.height());
+ return (1);
+}
+
static int dgn_fill_area(lua_State *ls)
{
int x1 = luaL_checkint(ls, 1);
@@ -2950,9 +2951,7 @@ LUAFN(dgn_change_floor_tile)
LUAFN(dgn_ftile)
{
#ifdef USE_TILE
- return dgn_map_add_transform(ls,
- &map_lines::add_floortile,
- &map_lines::clear_floortiles);
+ return dgn_map_add_transform(ls, &map_lines::add_floortile);
#else
return 0;
#endif
@@ -2961,9 +2960,7 @@ LUAFN(dgn_ftile)
LUAFN(dgn_rtile)
{
#ifdef USE_TILE
- return dgn_map_add_transform(ls,
- &map_lines::add_rocktile,
- &map_lines::clear_rocktiles);
+ return dgn_map_add_transform(ls, &map_lines::add_rocktile);
#else
return 0;
#endif
@@ -3025,13 +3022,12 @@ static const struct luaL_reg dgn_lib[] =
{ "welcome", dgn_welcome },
{ "orient", dgn_orient },
{ "shuffle", dgn_shuffle },
- { "shuffle_remove", dgn_shuffle_remove },
{ "subst", dgn_subst },
{ "nsubst", dgn_nsubst },
{ "colour", dgn_colour },
{ "lfloorcol", dgn_lfloorcol},
{ "lrockcol", dgn_lrockcol},
- { "subst_remove", dgn_subst_remove },
+ { "normalise", dgn_normalise },
{ "map", dgn_map },
{ "mons", dgn_mons },
{ "item", dgn_item },
@@ -3085,6 +3081,9 @@ static const struct luaL_reg dgn_lib[] =
{ "apply_area_cloud", dgn_apply_area_cloud },
// building routines
+ { "grd_table", dgn_grd_table },
+ { "width", dgn_width },
+ { "height", dgn_height },
{ "fill_area", dgn_fill_area },
{ "replace_area", dgn_replace_area },
{ "octa_room", dgn_octa_room },
@@ -3540,6 +3539,221 @@ static void luaopen_mapmarker(lua_State *ls)
luaopen_setmeta(ls, "mapmarker", mapmarker_lib, MAPMARK_METATABLE);
}
+
+// 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 ? lua_tonumber(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);
+}
+
+static 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);
+}
+
void init_dungeon_lua()
{
lua_stack_cleaner clean(dlua);
@@ -3562,6 +3776,8 @@ void init_dungeon_lua()
luaopen_mapmarker(dlua);
luaopen_ray(dlua);
+ _register_builder_funcs(dlua);
+
_register_mapdef_tables(dlua);
}
diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc
index 20c5ceaf3e..0d2b5f6864 100644
--- a/crawl-ref/source/mapdef.cc
+++ b/crawl-ref/source/mapdef.cc
@@ -335,17 +335,10 @@ int level_range::span() const
}
////////////////////////////////////////////////////////////////////////
-// map_transformer
-
-map_transformer::~map_transformer()
-{
-}
-
-////////////////////////////////////////////////////////////////////////
// map_lines
map_lines::map_lines()
- : transforms(), markers(), lines(), overlay(),
+ : markers(), lines(), overlay(),
map_width(0), solid_north(false), solid_east(false),
solid_south(false), solid_west(false), solid_checked(false)
{
@@ -356,7 +349,22 @@ map_lines::map_lines(const map_lines &map)
init_from(map);
}
-int map_lines::operator () (const coord_def &c) const
+rectangle_iterator map_lines::get_iter() const
+{
+ ASSERT(width() > 0);
+ ASSERT(height() > 0);
+
+ coord_def tl(0, 0);
+ coord_def br(width() - 1, height() - 1);
+ return rectangle_iterator(tl, br);
+}
+
+char map_lines::operator () (const coord_def &c) const
+{
+ return lines[c.y][c.x];
+}
+
+char& map_lines::operator () (const coord_def &c)
{
return lines[c.y][c.x];
}
@@ -375,14 +383,12 @@ map_lines &map_lines::operator = (const map_lines &map)
map_lines::~map_lines()
{
- clear_transforms();
clear_markers();
}
void map_lines::init_from(const map_lines &map)
{
- // Transforms and markers have to be regenerated, they will not be copied.
- clear_transforms();
+ // Markers have to be regenerated, they will not be copied.
clear_markers();
overlay.reset(NULL);
lines = map.lines;
@@ -402,11 +408,6 @@ void map_lines::clear_vector(V &vect)
vect.clear();
}
-void map_lines::clear_transforms()
-{
- clear_vector(transforms);
-}
-
void map_lines::clear_markers()
{
clear_vector(markers);
@@ -425,14 +426,17 @@ std::string map_lines::add_feature_marker(const std::string &s)
if (!err.empty())
return (err);
- transforms.push_back(new map_marker_spec(key[0], arg));
+ map_marker_spec spec(key[0], arg);
+ spec.apply_transform(*this);
+
return ("");
}
std::string map_lines::add_lua_marker(const std::string &key,
const lua_datum &function)
{
- transforms.push_back(new map_marker_spec(key[0], function));
+ map_marker_spec spec(key[0], function);
+ spec.apply_transform(*this);
return ("");
}
@@ -452,6 +456,7 @@ void map_lines::apply_grid_overlay(const coord_def &c)
{
if (!overlay.get())
return;
+
for (int y = height() - 1; y >= 0; --y)
for (int x = width() - 1; x >= 0; --x)
{
@@ -624,7 +629,9 @@ std::string map_lines::add_colour(const std::string &sub)
if (!err.empty())
return (err);
- transforms.push_back( new colour_spec( key[0], sep == ':', colours ) );
+ colour_spec spec(key[0], sep == ':', colours);
+ overlay_colours(spec);
+
return ("");
}
@@ -648,7 +655,8 @@ std::string map_lines::add_subst(const std::string &sub)
if (!err.empty())
return (err);
- transforms.push_back( new subst_spec( key[0], sep == ':', repl ) );
+ subst_spec spec(key[0], sep == ':', repl);
+ subst(spec);
return ("");
}
@@ -705,7 +713,9 @@ std::string map_lines::add_nsubst(const std::string &s)
substs.push_back(spec);
}
- transforms.push_back( new nsubst_spec(key[0], substs) );
+ nsubst_spec spec(key[0], substs);
+ nsubst(spec);
+
return ("");
}
@@ -715,114 +725,61 @@ std::string map_lines::add_shuffle(const std::string &raws)
const std::string err = check_shuffle(s);
if (err.empty())
- transforms.push_back( new shuffle_spec(s) );
+ resolve_shuffle(s);
return (err);
}
-void map_lines::remove_shuffle(const std::string &raw)
+int map_lines::width() const
{
- std::string s = raw;
- const std::string err = check_shuffle(s);
- if (err.empty())
- {
- const shuffle_spec ss(s);
- for (int i = 0, vsize = transforms.size(); i < vsize; ++i)
- {
- if (transforms[i]->type() == map_transformer::TT_SHUFFLE)
- {
- const shuffle_spec *other =
- dynamic_cast<shuffle_spec*>(transforms[i]);
- if (ss == *other)
- {
- delete transforms[i];
- transforms.erase( transforms.begin() + i );
- return;
- }
- }
- }
- }
+ return map_width;
}
-void map_lines::remove_subst(const std::string &raw)
+int map_lines::height() const
{
- // Parsing subst specs is a pain, so we just let add_subst do the
- // work, then pop the subst off the end of the vector.
- if (add_subst(raw).empty())
- {
- map_transformer *sub = *transforms.rbegin();
- subst_spec spec = *dynamic_cast<subst_spec*>(sub);
- delete sub;
- transforms.pop_back();
-
- for (int i = 0, vsize = transforms.size(); i < vsize; ++i)
- {
- if (transforms[i]->type() == map_transformer::TT_SUBST)
- {
- subst_spec *cand = dynamic_cast<subst_spec*>(transforms[i]);
- if (spec == *cand)
- {
- delete cand;
- transforms.erase( transforms.begin() + i );
- return;
- }
- }
- }
- }
+ return lines.size();
}
-void map_lines::clear_transforms(map_transformer::transform_type tt)
+void map_lines::extend(int min_width, int min_height, char fill)
{
- if (transforms.empty())
- return;
- for (int i = transforms.size() - 1; i >= 0; --i)
- if (transforms[i]->type() == tt)
- {
- delete transforms[i];
- transforms.erase( transforms.begin() + i );
- }
-}
+ min_width = std::max(1, min_width);
+ min_height = std::max(1, min_height);
-void map_lines::clear_colours()
-{
- clear_transforms(map_transformer::TT_COLOUR);
-}
+ bool dirty = false;
+ int old_width = width();
+ int old_height = height();
-#ifdef USE_TILE
-void map_lines::clear_rocktiles()
-{
- clear_transforms(map_transformer::TT_ROCKTILE);
-}
+ if (static_cast<int>(lines.size()) < min_height)
+ {
+ dirty = true;
+ while (static_cast<int>(lines.size()) < min_height)
+ add_line(std::string(min_width, fill));
+ }
-void map_lines::clear_floortiles()
-{
- clear_transforms(map_transformer::TT_FLOORTILE);
-}
-#endif
+ if (width() < min_width)
+ {
+ dirty = true;
+ lines[0] += std::string(min_width - width(), fill);
+ map_width = std::max(map_width, min_width);
+ }
-void map_lines::clear_shuffles()
-{
- clear_transforms(map_transformer::TT_SHUFFLE);
-}
+ if (!dirty)
+ return;
-void map_lines::clear_nsubsts()
-{
- clear_transforms(map_transformer::TT_NSUBST);
-}
+ normalise(fill);
-void map_lines::clear_substs()
-{
- clear_transforms(map_transformer::TT_SUBST);
-}
+ // Extend overlay matrix as well.
+ if (overlay.get())
+ {
+ std::auto_ptr<overlay_matrix> new_overlay(
+ new overlay_matrix(width(), height()));
-int map_lines::width() const
-{
- return map_width;
-}
+ for (int y = 0; y < old_height; ++y)
+ for (int x = 0; x < old_width; ++x)
+ (*new_overlay)(x, y) = (*overlay)(x, y);
-int map_lines::height() const
-{
- return lines.size();
+ overlay = new_overlay;
+ }
}
coord_def map_lines::size() const
@@ -892,7 +849,6 @@ bool map_lines::solid_borders(map_section_type border)
void map_lines::clear()
{
- clear_transforms();
clear_markers();
lines.clear();
overlay.reset(NULL);
@@ -938,7 +894,7 @@ void map_lines::overlay_tiles(tile_spec &spec)
for (int y = 0, ysize = lines.size(); y < ysize; ++y)
{
std::string::size_type pos = 0;
- while ((pos = lines[y].find(spec.key, pos)) != std::string::npos)
+ while ((pos = lines[y].find_first_of(spec.key, pos)) != std::string::npos)
{
if (spec.floor)
(*overlay)(pos, y).floortile = spec.get_tile();
@@ -1036,21 +992,6 @@ void map_lines::resolve_shuffle(const std::string &shufflage)
}
}
-std::string map_lines::apply_transforms()
-{
- std::string error;
- for (int i = 0, vsize = transforms.size(); i < vsize; ++i)
- {
- error = transforms[i]->apply_transform(*this);
- if (!error.empty())
- return (error);
- }
-
- // Release the transforms so we don't try them again.
- clear_transforms();
- return ("");
-}
-
void map_lines::normalise(char fillch)
{
for (int i = 0, vsize = lines.size(); i < vsize; ++i)
@@ -1196,24 +1137,6 @@ void map_lines::hmirror()
solid_checked = false;
}
-std::vector<std::string> map_lines::get_shuffle_strings() const
-{
- std::vector<std::string> shuffles;
- for (int i = 0, vsize = transforms.size(); i < vsize; ++i)
- if (transforms[i]->type() == map_transformer::TT_SHUFFLE)
- shuffles.push_back( transforms[i]->describe() );
- return (shuffles);
-}
-
-std::vector<std::string> map_lines::get_subst_strings() const
-{
- std::vector<std::string> substs;
- for (int i = 0, vsize = transforms.size(); i < vsize; ++i)
- if (transforms[i]->type() == map_transformer::TT_SUBST)
- substs.push_back( transforms[i]->describe() );
- return (substs);
-}
-
std::vector<coord_def> map_lines::find_glyph(int gly) const
{
std::vector<coord_def> points;
@@ -1252,6 +1175,58 @@ coord_def map_lines::find_first_glyph(const std::string &glyphs) const
return coord_def(-1, -1);
}
+bool map_lines::find_bounds(int gly, coord_def &tl, coord_def &br) const
+{
+ tl = coord_def(width(), height());
+ br = coord_def(-1, -1);
+
+ if (width() == 0 || height() == 0)
+ return false;
+
+ for (rectangle_iterator ri(get_iter()); ri; ++ri)
+ {
+ const coord_def mc = *ri;
+ if ((*this)(mc) != gly)
+ continue;
+
+ tl.x = std::min(tl.x, mc.x);
+ tl.y = std::min(tl.y, mc.y);
+ br.x = std::max(br.x, mc.x);
+ br.y = std::max(br.y, mc.y);
+ }
+
+ return (br.x >= 0);
+}
+
+bool map_lines::find_bounds(const char *str, coord_def &tl, coord_def &br) const
+{
+ tl = coord_def(width(), height());
+ br = coord_def(-1, -1);
+
+ if (width() == 0 || height() == 0)
+ return false;
+
+ for (rectangle_iterator ri(get_iter()); ri; ++ri)
+ {
+ ASSERT(ri);
+ const coord_def &mc = *ri;
+ const size_t len = strlen(str);
+ for (size_t i = 0; i < len; ++i)
+ {
+ if ((*this)(mc) == str[i])
+ {
+ tl.x = std::min(tl.x, mc.x);
+ tl.y = std::min(tl.y, mc.y);
+ br.x = std::max(br.x, mc.x);
+ br.y = std::max(br.y, mc.y);
+ break;
+ }
+ }
+ }
+
+ return (br.x >= 0);
+}
+
#ifdef USE_TILE
bool map_tile_list::parse(const std::string &s, int weight)
{
@@ -1274,7 +1249,7 @@ std::string map_lines::add_tile(const std::string &sub, bool is_floor)
std::string key;
std::string substitute;
- std::string err = mapdef_split_key_item(sub, &key, &sep, &substitute);
+ std::string err = mapdef_split_key_item(sub, &key, &sep, &substitute, -1);
if (!err.empty())
return (err);
@@ -1283,7 +1258,9 @@ std::string map_lines::add_tile(const std::string &sub, bool is_floor)
if (!err.empty())
return (err);
- transforms.push_back(new tile_spec(key[0], sep == ':', is_floor, list));
+ tile_spec spec(key, sep == ':', is_floor, list);
+ overlay_tiles(spec);
+
return ("");
}
@@ -1300,17 +1277,6 @@ std::string map_lines::add_floortile(const std::string &sub)
//////////////////////////////////////////////////////////////////////////
// tile_spec
-std::string tile_spec::apply_transform(map_lines &map)
-{
- map.overlay_tiles(*this);
- return ("");
-}
-
-std::string tile_spec::describe() const
-{
- return ("");
-}
-
int tile_spec::get_tile()
{
if (chose_fixed)
@@ -1353,7 +1319,8 @@ map_def::map_def()
: name(), tags(), place(), depths(), orient(), chance(), weight(),
weight_depth_mult(), weight_depth_div(), welcome_messages(), map(),
mons(), items(), random_mons(), keyspecs(), prelude("dlprelude"),
- main("dlmain"), validate("dlvalidate"), veto("dlveto"),
+ mapchunk("dlmapchunk"), main("dlmain"),
+ validate("dlvalidate"), veto("dlveto"),
rock_colour(BLACK), floor_colour(BLACK), rock_tile(0), floor_tile(0),
index_only(false), cache_offset(0L)
{
@@ -1368,6 +1335,7 @@ void map_def::init()
place.clear();
depths.clear();
prelude.clear();
+ mapchunk.clear();
main.clear();
validate.clear();
veto.clear();
@@ -1436,6 +1404,7 @@ void map_def::write_full(writer& outf)
marshallShort(outf, MAP_CACHE_VERSION); // Level indicator.
marshallString4(outf, name);
prelude.write(outf);
+ mapchunk.write(outf);
main.write(outf);
validate.write(outf);
veto.write(outf);
@@ -1463,6 +1432,7 @@ void map_def::read_full(reader& inf)
}
prelude.read(inf);
+ mapchunk.read(inf);
main.read(inf);
validate.read(inf);
veto.read(inf);
@@ -1558,6 +1528,7 @@ void map_def::read_depth_ranges(reader& inf)
void map_def::set_file(const std::string &s)
{
prelude.set_file(s);
+ mapchunk.set_file(s);
main.set_file(s);
validate.set_file(s);
veto.set_file(s);
@@ -1575,9 +1546,18 @@ std::string map_def::run_lua(bool run_main)
return (prelude.orig_error());
if (!run_main)
+ {
lua_pushnil(dlua);
+ lua_pushnil(dlua);
+ }
else
{
+ err = mapchunk.load(dlua);
+ if (err == -1000)
+ lua_pushnil(dlua);
+ else if (err)
+ return (mapchunk.orig_error());
+
err = main.load(dlua);
if (err == -1000)
lua_pushnil(dlua);
@@ -1585,7 +1565,7 @@ std::string map_def::run_lua(bool run_main)
return (main.orig_error());
}
- if (!dlua.callfn("dgn_run_map", 2, 0))
+ if (!dlua.callfn("dgn_run_map", 3, 0))
return rewrite_chunk_errors(dlua.error);
return (dlua.error);
@@ -1636,6 +1616,8 @@ std::string map_def::rewrite_chunk_errors(const std::string &s) const
std::string res = s;
if (prelude.rewrite_chunk_errors(res))
return (res);
+ if (mapchunk.rewrite_chunk_errors(res))
+ return (res);
if (main.rewrite_chunk_errors(res))
return (res);
if (validate.rewrite_chunk_errors(res))
@@ -1704,7 +1686,7 @@ std::string map_def::validate_map_def()
}
dlua_set_map dl(this);
- return (map.apply_transforms());
+ return ("");
}
bool map_def::is_usable_in(const level_id &lid) const
@@ -1993,7 +1975,7 @@ void map_def::normalise()
std::string map_def::resolve()
{
dlua_set_map dl(this);
- return map.apply_transforms();
+ return ("");
}
void map_def::fixup()
@@ -2079,16 +2061,6 @@ std::string map_def::add_key_mask(const std::string &s)
return add_key_field(s, &keyed_mapspec::set_mask);
}
-std::vector<std::string> map_def::get_shuffle_strings() const
-{
- return map.get_shuffle_strings();
-}
-
-std::vector<std::string> map_def::get_subst_strings() const
-{
- return map.get_subst_strings();
-}
-
///////////////////////////////////////////////////////////////////
// mons_list
//
@@ -3147,48 +3119,6 @@ int subst_spec::value()
return (chosen);
}
-std::string subst_spec::apply_transform(map_lines &map)
-{
- map.subst(*this);
- return ("");
-}
-
-map_transformer::transform_type subst_spec::type() const
-{
- return (TT_SUBST);
-}
-
-std::string subst_spec::describe() const
-{
- std::string subst(1, foo);
- subst += std::string(" ") + (fix? ':' : '=');
- for (int i = 0, size = repl.size(); i < size; ++i)
- {
- const glyph_weighted_replacement_t &gly = repl[i];
- subst += " ";
- subst += static_cast<char>(gly.first);
- if (gly.second != 10)
- subst += make_stringf(":%d", gly.second);
- }
- return (subst);
-}
-
-bool subst_spec::operator == (const subst_spec &other) const
-{
- if (foo != other.foo || fix != other.fix)
- return (false);
-
- if (repl.size() != other.repl.size())
- return (false);
-
- for (int i = 0, size = repl.size(); i < size; ++i)
- {
- if (repl[i] != other.repl[i])
- return (false);
- }
- return (true);
-}
-
//////////////////////////////////////////////////////////////////////////
// nsubst_spec
@@ -3197,31 +3127,9 @@ nsubst_spec::nsubst_spec(int _key, const std::vector<subst_spec> &_specs)
{
}
-std::string nsubst_spec::apply_transform(map_lines &map)
-{
- map.nsubst(*this);
- return ("");
-}
-
-std::string nsubst_spec::describe() const
-{
- return ("");
-}
-
//////////////////////////////////////////////////////////////////////////
// colour_spec
-std::string colour_spec::apply_transform(map_lines &map)
-{
- map.overlay_colours(*this);
- return ("");
-}
-
-std::string colour_spec::describe() const
-{
- return ("");
-}
-
int colour_spec::get_colour()
{
if (fixed_colour != BLACK)
@@ -3238,25 +3146,6 @@ int colour_spec::get_colour()
}
//////////////////////////////////////////////////////////////////////////
-// shuffle_spec
-
-std::string shuffle_spec::apply_transform(map_lines &map)
-{
- map.resolve_shuffle(shuffle);
- return ("");
-}
-
-map_transformer::transform_type shuffle_spec::type() const
-{
- return (TT_SHUFFLE);
-}
-
-std::string shuffle_spec::describe() const
-{
- return (shuffle);
-}
-
-//////////////////////////////////////////////////////////////////////////
// map_marker_spec
std::string map_marker_spec::apply_transform(map_lines &map)
@@ -3293,16 +3182,6 @@ map_marker *map_marker_spec::create_marker()
: map_marker::parse_marker(marker);
}
-map_transformer::transform_type map_marker_spec::type() const
-{
- return (TT_MARKER);
-}
-
-std::string map_marker_spec::describe() const
-{
- return ("unimplemented");
-}
-
//////////////////////////////////////////////////////////////////////////
// map_flags
map_flags::map_flags()
diff --git a/crawl-ref/source/mapdef.h b/crawl-ref/source/mapdef.h
index 33452a712e..a7b9bc4d9b 100644
--- a/crawl-ref/source/mapdef.h
+++ b/crawl-ref/source/mapdef.h
@@ -15,12 +15,13 @@
#include <cstdio>
#include <memory>
-#include "luadgn.h"
#include "enum.h"
#include "externs.h"
+#include "fixary.h"
+#include "luadgn.h"
#include "makeitem.h"
+#include "stuff.h"
#include "travel.h"
-#include "fixary.h"
// [dshaligram] Maps can be mirrored; for every orientation, there must be
// a suitable mirror.
@@ -100,28 +101,8 @@ typedef std::pair<int,int> glyph_weighted_replacement_t;
typedef std::vector<glyph_weighted_replacement_t> glyph_replacements_t;
class map_lines;
-class map_transformer
-{
-public:
- enum transform_type
- {
- TT_SHUFFLE,
- TT_SUBST,
- TT_NSUBST,
- TT_MARKER,
- TT_COLOUR,
- TT_ROCKTILE,
- TT_FLOORTILE
- };
-
-public:
- virtual ~map_transformer() = 0;
- virtual std::string apply_transform(map_lines &map) = 0;
- virtual transform_type type() const = 0;
- virtual std::string describe() const = 0;
-};
-class subst_spec : public map_transformer
+class subst_spec
{
public:
subst_spec(int torepl, bool fix, const glyph_replacements_t &repls);
@@ -134,12 +115,6 @@ public:
int value();
- std::string apply_transform(map_lines &map);
- transform_type type() const;
- std::string describe() const;
-
- bool operator == (const subst_spec &other) const;
-
private:
int foo; // The thing to replace.
bool fix; // If true, the first replacement fixes the value.
@@ -148,14 +123,10 @@ private:
glyph_replacements_t repl;
};
-class nsubst_spec : public map_transformer
+class nsubst_spec
{
public:
nsubst_spec(int key, const std::vector<subst_spec> &specs);
- std::string apply_transform(map_lines &map);
- transform_type type() const { return TT_NSUBST; }
- std::string describe() const;
-
public:
int key;
std::vector<subst_spec> specs;
@@ -167,16 +138,13 @@ class map_colour_list : public std::vector<map_weighted_colour>
public:
bool parse(const std::string &s, int weight);
};
-class colour_spec : public map_transformer
+class colour_spec
{
public:
colour_spec(int _key, bool _fix, const map_colour_list &clist)
: key(_key), fix(_fix), fixed_colour(BLACK), colours(clist)
{
}
- std::string apply_transform(map_lines &map);
- transform_type type() const { return TT_COLOUR; }
- std::string describe() const;
int get_colour();
@@ -194,23 +162,20 @@ class map_tile_list : public std::vector<map_weighted_colour>
public:
bool parse(const std::string &s, int weight);
};
-class tile_spec : public map_transformer
+
+class tile_spec
{
public:
- tile_spec(int _key, bool _fix, bool _floor, const map_tile_list &_tiles)
+ tile_spec(const std::string &_key, bool _fix, bool _floor, const map_tile_list &_tiles)
: key(_key), fix(_fix), chose_fixed(false), floor(_floor),
fixed_tile(0), tiles(_tiles)
{
}
- std::string apply_transform(map_lines &map);
- transform_type type() const { return (floor ? TT_FLOORTILE : TT_ROCKTILE); }
- std::string describe() const;
-
int get_tile();
public:
- int key;
+ std::string key;
bool fix;
bool chose_fixed;
bool floor;
@@ -219,26 +184,7 @@ public:
};
#endif
-class shuffle_spec : public map_transformer
-{
- public:
- std::string shuffle;
-
- shuffle_spec(const std::string &spec)
- : shuffle(spec)
- {
- }
-
- std::string apply_transform(map_lines &map);
- transform_type type() const;
- std::string describe() const;
- bool operator == (const shuffle_spec &other) const
- {
- return (shuffle == other.shuffle);
- }
-};
-
-class map_marker_spec : public map_transformer
+class map_marker_spec
{
public:
int key;
@@ -254,8 +200,6 @@ public:
: key(_key), marker(), lua_fn(new lua_datum(fn)) { }
std::string apply_transform(map_lines &map);
- transform_type type() const;
- std::string describe() const;
private:
map_marker *create_marker();
@@ -278,25 +222,23 @@ public:
std::string add_subst(const std::string &st);
std::string add_shuffle(const std::string &s);
std::string add_colour(const std::string &col);
- void remove_shuffle(const std::string &s);
- void remove_subst(const std::string &s);
- void clear_shuffles();
- void clear_substs();
- void clear_nsubsts();
void clear_markers();
- void clear_colours();
#ifdef USE_TILE
std::string add_floortile(const std::string &s);
std::string add_rocktile(const std::string &s);
- void clear_rocktiles();
- void clear_floortiles();
#endif
std::vector<coord_def> find_glyph(int glyph) const;
coord_def find_first_glyph(int glyph) const;
coord_def find_first_glyph(const std::string &glyphs) const;
+ // Find rectangular bounds (inclusive) for uses of the glyph in the map.
+ // Returns false if glyph could not be found.
+ bool find_bounds(int glyph, coord_def &tl, coord_def &br) const;
+ // Same as above, but for any of the glyphs in glyph_str.
+ bool find_bounds(const char *glyph_str, coord_def &tl, coord_def &br) const;
+
void set_orientation(const std::string &s);
int width() const;
@@ -309,8 +251,6 @@ public:
bool solid_borders(map_section_type border);
- std::string apply_transforms();
-
// Make all lines the same length.
void normalise(char fillc = ' ');
@@ -332,14 +272,16 @@ public:
const std::vector<std::string> &get_lines() const;
std::vector<std::string> &get_lines();
- std::vector<std::string> get_shuffle_strings() const;
- std::vector<std::string> get_subst_strings() const;
- int operator () (const coord_def &c) const;
+ rectangle_iterator get_iter() const;
+ char operator () (const coord_def &c) const;
+ char& operator () (const coord_def &c);
+
+ // Extend map dimensions with glyph 'fill' to minimum width and height.
+ void extend(int min_width, int min_height, char fill);
private:
void init_from(const map_lines &map);
- void clear_transforms();
template <typename V> void clear_vector(V &vect);
void vmirror_markers();
void hmirror_markers();
@@ -359,7 +301,6 @@ private:
void overlay_tiles(tile_spec &);
#endif
void check_borders();
- void clear_transforms(map_transformer::transform_type);
std::string shuffle(std::string s);
std::string block_shuffle(const std::string &s);
std::string check_shuffle(std::string &s);
@@ -386,7 +327,6 @@ private:
friend class tile_spec;
private:
- std::vector<map_transformer *> transforms;
std::vector<map_marker *> markers;
std::vector<std::string> lines;
struct overlay_def
@@ -713,7 +653,7 @@ public:
keyed_specs keyspecs;
- dlua_chunk prelude, main, validate, veto;
+ dlua_chunk prelude, mapchunk, main, validate, veto;
map_file_place place_loaded_from;
diff --git a/crawl-ref/source/maps.h b/crawl-ref/source/maps.h
index 3d0994dd02..484e3a0f01 100644
--- a/crawl-ref/source/maps.h
+++ b/crawl-ref/source/maps.h
@@ -62,7 +62,7 @@ typedef std::vector<coord_def> point_vector;
extern map_place_check_t map_place_valid;
extern point_vector map_anchor_points;
-const int MAP_CACHE_VERSION = 1010;
+const int MAP_CACHE_VERSION = 1011;
#ifdef DEBUG_DIAGNOSTICS
diff --git a/crawl-ref/source/util/levcomp.ypp b/crawl-ref/source/util/levcomp.ypp
index 3567083a4a..1aa82e25b1 100644
--- a/crawl-ref/source/util/levcomp.ypp
+++ b/crawl-ref/source/util/levcomp.ypp
@@ -589,7 +589,7 @@ map_lines : map_lines map_line
map_line : MAP_LINE
{
- lc_map.main.add(
+ lc_map.mapchunk.add(
yylineno,
make_stringf("map(\"%s\")",
quote_lua_string($1).c_str()));