diff options
-rw-r--r-- | crawl-ref/source/Kills.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/acr.cc | 4 | ||||
-rw-r--r-- | crawl-ref/source/chardump.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/clua.cc | 123 | ||||
-rw-r--r-- | crawl-ref/source/clua.h | 47 | ||||
-rw-r--r-- | crawl-ref/source/dat/clua/dungeon.lua | 41 | ||||
-rw-r--r-- | crawl-ref/source/dat/ebranch.des | 2 | ||||
-rw-r--r-- | crawl-ref/source/makefile.obj | 1 | ||||
-rw-r--r-- | crawl-ref/source/mapdef.cc | 386 | ||||
-rw-r--r-- | crawl-ref/source/mapdef.h | 77 | ||||
-rw-r--r-- | crawl-ref/source/maps.cc | 13 | ||||
-rw-r--r-- | crawl-ref/source/mutation.cc | 4 | ||||
-rw-r--r-- | crawl-ref/source/output.cc | 2 | ||||
-rw-r--r-- | crawl-ref/source/util/levcomp.lpp | 89 | ||||
-rw-r--r-- | crawl-ref/source/util/levcomp.ypp | 305 |
15 files changed, 742 insertions, 356 deletions
diff --git a/crawl-ref/source/Kills.cc b/crawl-ref/source/Kills.cc index 3652662dde..14516c5010 100644 --- a/crawl-ref/source/Kills.cc +++ b/crawl-ref/source/Kills.cc @@ -933,7 +933,7 @@ static const struct luaL_reg kill_lib[] = { NULL, NULL } }; -void lua_open_kills(lua_State *ls) +void luaopen_kills(lua_State *ls) { luaL_openlib(ls, "kills", kill_lib, 0); } diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc index e8adf54bc1..4cafa0a2f7 100644 --- a/crawl-ref/source/acr.cc +++ b/crawl-ref/source/acr.cc @@ -98,6 +98,7 @@ #include "itemprop.h" #include "items.h" #include "lev-pand.h" +#include "luadgn.h" #include "macro.h" #include "makeitem.h" #include "maps.h" @@ -2971,6 +2972,9 @@ static bool initialise(void) // initialize tag system before we try loading anything! tag_init(); + // set up the Lua interpreter for the dungeon builder. + init_dungeon_lua(); + // Read special levels and vaults. read_maps(); diff --git a/crawl-ref/source/chardump.cc b/crawl-ref/source/chardump.cc index 73d1c2ff7d..6fe73c96f5 100644 --- a/crawl-ref/source/chardump.cc +++ b/crawl-ref/source/chardump.cc @@ -907,7 +907,7 @@ static void sdump_mutations(const std::string &, std::string & text) // Can't use how_mutated() here, as it doesn't count demonic powers int xz = 0; - for (int xy = 0; xy < 100; xy++) + for (int xy = 0; xy < NUM_MUTATIONS; ++xy) { if (you.mutation[xy] > 0) xz++; diff --git a/crawl-ref/source/clua.cc b/crawl-ref/source/clua.cc index da7c886541..15c0bbbfc4 100644 --- a/crawl-ref/source/clua.cc +++ b/crawl-ref/source/clua.cc @@ -21,6 +21,7 @@ #include "item_use.h" #include "libutil.h" #include "macro.h" +#include "mapdef.h" #include "message.h" #include "mon-util.h" #include "output.h" @@ -201,15 +202,20 @@ void CLua::init_throttle() } } +int CLua::loadstring(const char *s, const char *context) +{ + const int err = luaL_loadbuffer(state(), s, strlen(s), context); + set_error(err, state()); + return err; +} + int CLua::execstring(const char *s, const char *context) { + int err = 0; + if ((err = loadstring(s, context))) + return (err); + lua_State *ls = state(); - int err = luaL_loadbuffer(ls, s, strlen(s), context); - if (err) - { - set_error(err, ls); - return err; - } lua_call_throttle strangler(this); err = lua_pcall(ls, 0, 0, 0); set_error(err, ls); @@ -248,7 +254,7 @@ int CLua::execfile(const char *filename, bool trusted) sourced_files.insert(filename); lua_State *ls = state(); - int err = loadfile(ls, filename, trusted); + int err = loadfile(ls, filename, trusted || !managed_vm); lua_call_throttle strangler(this); if (!err) err = lua_pcall(ls, 0, 0, 0); @@ -354,6 +360,7 @@ void CLua::vfnreturns(const char *format, va_list args) } static void push_monster(lua_State *ls, monsters *mons); +static void push_map(lua_State *ls, map_def *map); static int push_activity_interrupt(lua_State *ls, activity_interrupt_data *t); int CLua::push_args(lua_State *ls, const char *format, va_list args, va_list *targ) @@ -400,6 +407,9 @@ int CLua::push_args(lua_State *ls, const char *format, va_list args, case 'b': lua_pushboolean(ls, va_arg(args, int)); break; + case 'm': + push_map(ls, va_arg(args, map_def *)); + break; case 'M': push_monster(ls, va_arg(args, monsters *)); break; @@ -541,17 +551,16 @@ bool CLua::callfn(const char *fn, int nargs, int nret) // Defined in Kills.cc because the kill bindings refer to Kills.cc local // structs -extern void lua_open_kills(lua_State *ls); - -void lua_open_you(lua_State *ls); -void lua_open_item(lua_State *ls); -void lua_open_food(lua_State *ls); -void lua_open_crawl(lua_State *ls); -void lua_open_file(lua_State *ls); -void lua_open_options(lua_State *ls); -void lua_open_monsters(lua_State *ls); -void lua_open_globals(lua_State *ls); +extern void luaopen_kills(lua_State *ls); +void luaopen_you(lua_State *ls); +void luaopen_item(lua_State *ls); +void luaopen_food(lua_State *ls); +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_globals(lua_State *ls); void CLua::init_lua() { @@ -569,16 +578,16 @@ void CLua::init_lua() luaopen_table(_state); // Open Crawl bindings - lua_open_kills(_state); - lua_open_you(_state); - lua_open_item(_state); - lua_open_food(_state); - lua_open_crawl(_state); - lua_open_file(_state); - lua_open_options(_state); - lua_open_monsters(_state); + luaopen_kills(_state); + luaopen_you(_state); + luaopen_item(_state); + luaopen_food(_state); + luaopen_crawl(_state); + luaopen_file(_state); + luaopen_options(_state); + luaopen_monsters(_state); - lua_open_globals(_state); + luaopen_globals(_state); load_cmacro(); load_chooks(); @@ -609,40 +618,6 @@ void CLua::load_cmacro() ///////////////////////////////////////////////////////////////////// -#define LUAWRAP(name, wrapexpr) \ - static int name(lua_State *ls) \ - { \ - wrapexpr; \ - return (0); \ - } - -#define LUARET1(name, type, val) \ - static int name(lua_State *ls) \ - { \ - lua_push##type(ls, val); \ - return (1); \ - } - -#define LUARET2(name, type, val1, val2) \ - static int name(lua_State *ls) \ - { \ - lua_push##type(ls, val1); \ - lua_push##type(ls, val2); \ - return (2); \ - } - -template <class T> T *util_get_userdata(lua_State *ls, int ndx) -{ - return (lua_islightuserdata(ls, ndx))? - static_cast<T *>( lua_touserdata(ls, ndx) ) - : NULL; -} - -template <class T> T *clua_get_userdata(lua_State *ls, const char *mt) -{ - return static_cast<T*>( luaL_checkudata( ls, 1, mt ) ); -} - static void clua_register_metatable(lua_State *ls, const char *tn, const luaL_reg *lr, int (*gcfn)(lua_State *ls) = NULL) @@ -806,7 +781,7 @@ static const struct luaL_reg you_lib[] = { NULL, NULL }, }; -void lua_open_you(lua_State *ls) +void luaopen_you(lua_State *ls) { luaL_openlib(ls, "you", you_lib, 0); } @@ -1395,7 +1370,7 @@ static const struct luaL_reg item_lib[] = { NULL, NULL }, }; -void lua_open_item(lua_State *ls) +void luaopen_item(lua_State *ls) { luaL_openlib(ls, "item", item_lib, 0); } @@ -1536,7 +1511,7 @@ static const struct luaL_reg food_lib[] = { NULL, NULL }, }; -void lua_open_food(lua_State *ls) +void luaopen_food(lua_State *ls) { luaL_openlib(ls, "food", food_lib, 0); } @@ -1862,7 +1837,7 @@ static const struct luaL_reg crawl_lib[] = { NULL, NULL }, }; -void lua_open_crawl(lua_State *ls) +void luaopen_crawl(lua_State *ls) { clua_register_metatable(ls, REGEX_METATABLE, crawl_regex_ops, crawl_regex_gc); @@ -1882,7 +1857,7 @@ static const struct luaL_reg file_lib[] = { NULL, NULL }, }; -void lua_open_file(lua_State *ls) +void luaopen_file(lua_State *ls) { luaL_openlib(ls, "file", file_lib, 0); } @@ -2002,7 +1977,7 @@ static int option_set(lua_State *ls) } #define OPT_METATABLE "options.optaccess" -void lua_open_options(lua_State *ls) +void luaopen_options(lua_State *ls) { int top = lua_gettop(ls); @@ -2136,7 +2111,13 @@ static void push_monster(lua_State *ls, monsters *mons) mw->mons = mons; } -void lua_open_monsters(lua_State *ls) +static void push_map(lua_State *ls, map_def *map) +{ + map_def **mapref = clua_new_userdata<map_def *>(ls, MAP_METATABLE); + *mapref = map; +} + +void luaopen_monsters(lua_State *ls) { luaL_newmetatable(ls, MONS_METATABLE); lua_pushstring(ls, "__index"); @@ -2191,13 +2172,12 @@ static int lua_pmatch(lua_State *ls) return (1); } -void lua_open_globals(lua_State *ls) +void luaopen_globals(lua_State *ls) { lua_pushcfunction(ls, lua_pmatch); lua_setglobal(ls, "pmatch"); } - //////////////////////////////////////////////////////////////////////// // lua_text_pattern @@ -2525,3 +2505,8 @@ static int clua_dofile(lua_State *ls) lua_call(ls, 0, LUA_MULTRET); return (lua_gettop(ls)); } + +std::string quote_lua_string(const std::string &s) +{ + return replace_all_of(replace_all_of(s, "\\", "\\\\"), "\"", "\\\""); +} diff --git a/crawl-ref/source/clua.h b/crawl-ref/source/clua.h index 0ec9723544..6759687494 100644 --- a/crawl-ref/source/clua.h +++ b/crawl-ref/source/clua.h @@ -41,7 +41,7 @@ private: class CLua { public: - CLua(bool managed); + CLua(bool managed = true); ~CLua(); lua_State *state(); @@ -63,6 +63,7 @@ public: void setregistry(const char *name); void getregistry(const char *name); + int loadstring(const char *str, const char *context); int execstring(const char *str, const char *context = "init.txt"); int execfile(const char *filename, bool trusted = false); @@ -161,4 +162,48 @@ extern CLua clua; void lua_set_exclusive_item(const item_def *item = NULL); +#define LUAWRAP(name, wrapexpr) \ + static int name(lua_State *ls) \ + { \ + wrapexpr; \ + return (0); \ + } + +#define PLUARET(type, val) \ + lua_push##type(ls, val); \ + return (1); + +#define LUARET1(name, type, val) \ + static int name(lua_State *ls) \ + { \ + lua_push##type(ls, val); \ + return (1); \ + } + +#define LUARET2(name, type, val1, val2) \ + static int name(lua_State *ls) \ + { \ + lua_push##type(ls, val1); \ + lua_push##type(ls, val2); \ + return (2); \ + } + +template <class T> +inline static T *util_get_userdata(lua_State *ls, int ndx) +{ + return (lua_islightuserdata(ls, ndx))? + static_cast<T *>( lua_touserdata(ls, ndx) ) + : NULL; +} + +template <class T> +inline static T *clua_get_userdata(lua_State *ls, const char *mt) +{ + return static_cast<T*>( luaL_checkudata( ls, 1, mt ) ); +} + +std::string quote_lua_string(const std::string &s); + +#define MAP_METATABLE "dgn.mtmap" + #endif diff --git a/crawl-ref/source/dat/clua/dungeon.lua b/crawl-ref/source/dat/clua/dungeon.lua new file mode 100644 index 0000000000..c25e06c4df --- /dev/null +++ b/crawl-ref/source/dat/clua/dungeon.lua @@ -0,0 +1,41 @@ +------------------------------------------------------------------------------ +-- dungeon.lua: +-- Dungeoneering functions. +------------------------------------------------------------------------------ + +-- Given an object and a table (dgn), returns a table with functions +-- that translate into method calls on the object. This table is +-- suitable for setfenv() on a function that expects to directly +-- address a map object. +function dgn_map_meta_wrap(obj, tab) + local meta = { } + for fn, val in pairs(tab) do + meta[fn] = function (...) + return val(obj, ...) + end + end + meta.wrapped_instance = obj + + local meta_meta = { __index = _G } + setmetatable(meta, meta_meta) + return meta +end + +function dgn_set_map(map) + g_dgn_curr_map = map +end + +function dgn_run_map(prelude, main) + if prelude or main then + env = dgn_map_meta_wrap(g_dgn_curr_map, dgn) + if prelude then + setfenv(prelude, env)() + end + if main then + setfenv(main, env)() + end + -- Return the environment in case we want to chain further + -- calls. + return env + end +end
\ No newline at end of file diff --git a/crawl-ref/source/dat/ebranch.des b/crawl-ref/source/dat/ebranch.des index e3e069278e..612e79f677 100644 --- a/crawl-ref/source/dat/ebranch.des +++ b/crawl-ref/source/dat/ebranch.des @@ -111,7 +111,9 @@ NAME: temple_statues TAGS: temple_entry ORIENT: float MAP +... GOG +... ENDMAP ############################################################################## diff --git a/crawl-ref/source/makefile.obj b/crawl-ref/source/makefile.obj index 20e016dc9b..40d159c842 100644 --- a/crawl-ref/source/makefile.obj +++ b/crawl-ref/source/makefile.obj @@ -35,6 +35,7 @@ itemprop.o \ items.o \ lev-pand.o \ libutil.o \ +luadgn.o \ macro.o \ makeitem.o \ mapdef.o \ diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc index b670527ef2..65f7e322f2 100644 --- a/crawl-ref/source/mapdef.cc +++ b/crawl-ref/source/mapdef.cc @@ -1,3 +1,4 @@ +#include <iostream> #include <cstdarg> #include <cstdio> #include <cctype> @@ -140,8 +141,8 @@ std::string level_range::str_depth_range() const if (shallowest == -1) return (":??"); - if (shallowest == 1 && deepest >= branches[branch].depth) - return (""); + if (deepest >= branches[branch].depth) + return (shallowest == 1? "" : make_stringf("%d-", shallowest)); if (shallowest == deepest) return make_stringf(":%d", shallowest); @@ -187,6 +188,76 @@ void level_range::set(const std::string &br, int s, int d) br.c_str(), s, d); } +level_range level_range::parse(std::string s) throw (std::string) +{ + level_range lr; + trim_string(s); + + if (s[0] == '!') + { + lr.deny = true; + s = trimmed_string(s.substr(1)); + } + + std::string::size_type cpos = s.find(':'); + if (cpos == std::string::npos) + parse_partial(lr, s); + else + { + std::string branch = trimmed_string(s.substr(0, cpos)); + std::string depth = trimmed_string(s.substr(cpos + 1)); + parse_depth_range(depth, &lr.shallowest, &lr.deepest); + + lr.set(branch, lr.shallowest, lr.deepest); + } + + return (lr); +} + +void level_range::parse_partial(level_range &lr, const std::string &s) + throw (std::string) +{ + if (isdigit(s[0])) + { + lr.branch = NUM_BRANCHES; + parse_depth_range(s, &lr.shallowest, &lr.deepest); + } + else + lr.set(s, 1, 100); +} + +void level_range::parse_depth_range(const std::string &s, int *l, int *h) + throw (std::string) +{ + if (s == "*") + { + *l = 1; + *h = 100; + return; + } + + std::string::size_type hy = s.find('-'); + if (hy == std::string::npos) + { + *l = *h = atoi(s.c_str()); + if (!*l) + throw std::string("Bad depth: ") + s; + } + else + { + *l = atoi(s.substr(0, hy).c_str()); + + std::string tail = s.substr(hy + 1); + if (tail.empty()) + *h = 100; + else + *h = atoi(tail.c_str()); + + if (!*l || !*h || *l > *h) + throw std::string("Bad depth: ") + s; + } +} + void level_range::set(int s, int d) { shallowest = s; @@ -216,6 +287,12 @@ bool level_range::matches(int x) const return (x >= shallowest && x <= deepest); } +bool level_range::operator == (const level_range &lr) const +{ + return (deny == lr.deny && shallowest == lr.shallowest + && deepest == lr.deepest && branch == lr.branch); +} + bool level_range::valid() const { return (shallowest > 0 && deepest >= shallowest); @@ -287,6 +364,11 @@ const std::vector<std::string> &map_lines::get_lines() const return (lines); } +std::vector<std::string> &map_lines::get_lines() +{ + return (lines); +} + void map_lines::add_line(const std::string &s) { lines.push_back(s); @@ -390,6 +472,79 @@ std::string map_lines::add_shuffle(const std::string &raws) return (err); } +void map_lines::remove_shuffle(const std::string &raw) +{ + std::string s = raw; + const std::string err = check_shuffle(s); + if (err.empty()) + { + const shuffle_spec ss(s); + for (int i = 0, size = transforms.size(); i < size; ++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; + } + } + } + } +} + +void map_lines::remove_subst(const std::string &raw) +{ + // 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, size = transforms.size(); i < size; ++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; + } + } + } + } +} + +void map_lines::clear_transforms(map_transformer::transform_type tt) +{ + 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 ); + } +} + +void map_lines::clear_shuffles() +{ + clear_transforms(map_transformer::TT_SHUFFLE); +} + +void map_lines::clear_substs() +{ + clear_transforms(map_transformer::TT_SUBST); +} + int map_lines::width() const { return map_width; @@ -616,31 +771,145 @@ 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, size = transforms.size(); i < size; ++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, size = transforms.size(); i < size; ++i) + if (transforms[i]->type() == map_transformer::TT_SUBST) + substs.push_back( transforms[i]->describe() ); + return (substs); +} + /////////////////////////////////////////////// // map_def // +map_def::map_def() + : name(), tags(), place(), depths(), orient(), chance(), + map(), mons(), items(), keyspecs(), prelude(), main(), + index_only(false), cache_offset(0L) +{ + init(); +} + void map_def::init() { + orient = MAP_NONE; name.clear(); tags.clear(); place.clear(); + depths.clear(); + prelude.clear(); + main.clear(); + reinit(); +} + +void map_def::reinit() +{ items.clear(); keyspecs.clear(); - depths.clear(); - orient = MAP_NONE; // Base chance; this is not a percentage. chance = 10; - // The map designer must explicitly disallow these if unwanted. - flags = MAPF_MIRROR_VERTICAL | MAPF_MIRROR_HORIZONTAL - | MAPF_ROTATE; - + // Clearing the map also zaps map transforms. map.clear(); mons.clear(); } +void map_def::set_file(const std::string &s) +{ + prelude.set_file(s); + main.set_file(s); +} + +void map_def::run_strip_prelude() +{ + run_lua(false); + prelude.clear(); +} + +void map_def::strip_lua() +{ + prelude.clear(); + main.clear(); +} + +std::string map_def::run_lua(bool run_main) +{ + dlua.callfn("dgn_set_map", "m", this); + int err = prelude.load(&dlua); + if (err == -1000) + lua_pushnil(dlua); + else if (err) + return (prelude.orig_error()); + + if (!run_main) + lua_pushnil(dlua); + else + { + err = main.load(&dlua); + if (err == -1000) + lua_pushnil(dlua); + else if (err) + return (main.orig_error()); + } + + if (!dlua.callfn("dgn_run_map", 2, 0)) + return (dlua.error); + + // Clear the map setting. + dlua.callfn("dgn_set_map", 0, 0); + + return (dlua.error); +} + +std::string map_def::validate() +{ + std::string err = run_lua(true); + if (!err.empty()) + return (err); + + if (orient == MAP_FLOAT || is_minivault()) + { + if (map.width() > GXM - MAPGEN_BORDER * 2 + || map.height() > GYM - MAPGEN_BORDER * 2) + { + return make_stringf( + "%s is too big: %dx%d - max %dx%d", + is_minivault()? "Minivault" : "Float", + map.width(), map.height(), + GXM - MAPGEN_BORDER * 2, + GYM - MAPGEN_BORDER * 2); + } + } + else + { + if (map.width() > GXM + || map.height() > GYM) + { + return make_stringf( + "Map is too big: %dx%d - max %dx%d", + map.width(), map.height(), + GXM, GYM); + } + } + + if (map.height() == 0) + return ("Must define map."); + + return (""); +} + bool map_def::is_usable_in(const level_id &lid) const { bool any_matched = false; @@ -790,7 +1059,7 @@ coord_def map_def::float_place() void map_def::hmirror() { - if (!(flags & MAPF_MIRROR_HORIZONTAL)) + if (has_tag("no_hmirror")) return; #ifdef DEBUG_DIAGNOSTICS @@ -812,7 +1081,7 @@ void map_def::hmirror() void map_def::vmirror() { - if (!(flags & MAPF_MIRROR_VERTICAL)) + if (has_tag("no_vmirror")) return; #ifdef DEBUG_DIAGNOSTICS @@ -835,7 +1104,7 @@ void map_def::vmirror() void map_def::rotate(bool clock) { - if (!(flags & MAPF_ROTATE)) + if (has_tag("no_rotate")) return; #define GMINM ((GXM) < (GYM)? (GXM) : (GYM)) @@ -940,6 +1209,16 @@ std::string map_def::add_key_mons(const std::string &s) return add_key_field(s, &keyed_mapspec::set_mons); } +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 // @@ -1095,6 +1374,26 @@ std::string mons_list::add_mons(const std::string &s, bool fix) return (error); } +std::string mons_list::set_mons(int index, const std::string &s) +{ + error.clear(); + + if (index < 0) + return (error = make_stringf("Index out of range: %d", index)); + + mons_spec_slot slotmons = parse_mons_spec(s); + if (!error.empty()) + return (error); + + if (index >= (int) mons.size()) + { + mons.reserve(index + 1); + mons.resize(index + 1, mons_spec_slot()); + } + mons[index] = slotmons; + return (error); +} + void mons_list::get_zombie_type(std::string s, mons_spec &spec) const { static const char *zombie_types[] = @@ -1276,6 +1575,25 @@ std::string item_list::add_item(const std::string &spec, bool fix) return (error); } +std::string item_list::set_item(int index, const std::string &spec) +{ + error.clear(); + if (index < 0) + return (error = make_stringf("Index %d out of range", index)); + item_spec_slot sp = parse_item_spec(spec); + if (error.empty()) + { + if (index >= (int) items.size()) + { + items.reserve(index + 1); + items.resize(index + 1, item_spec_slot()); + } + items.push_back(sp); + } + + return (error); +} + item_spec item_list::parse_single_spec(std::string s) { item_spec result; @@ -1460,6 +1778,42 @@ map_transformer *subst_spec::clone() const return new subst_spec(*this); } +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); +} + ////////////////////////////////////////////////////////////////////////// // shuffle_spec @@ -1473,6 +1827,16 @@ map_transformer *shuffle_spec::clone() const return new shuffle_spec(*this); } +map_transformer::transform_type shuffle_spec::type() const +{ + return (TT_SHUFFLE); +} + +std::string shuffle_spec::describe() const +{ + return (shuffle); +} + ////////////////////////////////////////////////////////////////////////// // keyed_mapspec diff --git a/crawl-ref/source/mapdef.h b/crawl-ref/source/mapdef.h index 6b951237a7..bf6251597e 100644 --- a/crawl-ref/source/mapdef.h +++ b/crawl-ref/source/mapdef.h @@ -12,18 +12,10 @@ #include <string> #include <vector> +#include "luadgn.h" #include "enum.h" #include "externs.h" -enum map_flags -{ - MAPF_PANDEMONIUM_VAULT = 0x01, // A pandemonium minivault. - - MAPF_MIRROR_VERTICAL = 0x10, // The map may be mirrored vertically - MAPF_MIRROR_HORIZONTAL = 0x20, // may be mirrored horizontally. - MAPF_ROTATE = 0x40 // may be rotated -}; - struct raw_range { branch_type branch; @@ -52,14 +44,24 @@ public: bool valid() const; int span() const; + static level_range parse(std::string lr) throw (std::string); + std::string describe() const; std::string str_depth_range() const; + bool operator == (const level_range &lr) const; + operator raw_range () const; operator std::string () const { return describe(); } + +private: + static void parse_partial(level_range &lr, const std::string &s) + throw (std::string); + static void parse_depth_range(const std::string &s, int *low, int *high) + throw (std::string); }; typedef std::pair<int,int> glyph_weighted_replacement_t; @@ -69,9 +71,18 @@ class map_lines; class map_transformer { public: + enum transform_type + { + TT_SHUFFLE, + TT_SUBST + }; + +public: virtual ~map_transformer() = 0; virtual void apply_transform(map_lines &map) = 0; virtual map_transformer *clone() const = 0; + virtual transform_type type() const = 0; + virtual std::string describe() const = 0; }; class subst_spec : public map_transformer @@ -88,6 +99,10 @@ public: void apply_transform(map_lines &map); map_transformer *clone() const; + transform_type type() const; + std::string describe() const; + + bool operator == (const subst_spec &other) const; private: int foo; // The thing to replace. @@ -108,6 +123,12 @@ struct shuffle_spec : public map_transformer void apply_transform(map_lines &map); map_transformer *clone() const; + transform_type type() const; + std::string describe() const; + bool operator == (const shuffle_spec &other) const + { + return (shuffle == other.shuffle); + } }; class map_lines @@ -122,6 +143,10 @@ public: void add_line(const std::string &s); std::string add_subst(const std::string &st); std::string add_shuffle(const std::string &s); + void remove_shuffle(const std::string &s); + void remove_subst(const std::string &s); + void clear_shuffles(); + void clear_substs(); void set_orientation(const std::string &s); @@ -146,6 +171,9 @@ public: void clear(); 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; private: void init_from(const map_lines &map); @@ -155,6 +183,7 @@ private: void subst(std::string &s, subst_spec &spec); void subst(subst_spec &); 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); @@ -203,6 +232,7 @@ public: // Returns an error string if the monster is unrecognised. std::string add_mons(const std::string &s, bool fix_slot = false); + std::string set_mons(int slot, const std::string &s); size_t size() const { return mons.size(); } @@ -275,6 +305,7 @@ public: size_t size() const { return items.size(); } std::string add_item(const std::string &spec, bool fix = false); + std::string set_item(int index, const std::string &spec); private: struct item_spec_slot @@ -359,7 +390,6 @@ typedef std::map<int, keyed_mapspec> keyed_specs; typedef std::vector<level_range> depth_ranges; -// Not providing a constructor to make life easy for C-style initialisation. class map_def { public: @@ -369,8 +399,7 @@ public: depth_ranges depths; map_section_type orient; - int chance; - long flags; + int chance; map_lines map; mons_list mons; @@ -378,8 +407,28 @@ public: keyed_specs keyspecs; + dlua_chunk prelude, main; + +private: + // This map has been loaded from an index, and not fully realised. + bool index_only; + long cache_offset; + public: + map_def(); void init(); + void reinit(); + + void set_file(const std::string &s); + std::string run_lua(bool skip_main); + void run_strip_prelude(); + void strip_lua(); + + std::string validate(); + + void add_prelude_line(int line, const std::string &s); + void add_main_line(int line, const std::string &s); + void hmirror(); void vmirror(); void rotate(bool clockwise); @@ -410,6 +459,9 @@ public: bool has_tag(const std::string &tag) const; bool has_tag_prefix(const std::string &tag) const; + std::vector<std::string> get_shuffle_strings() const; + std::vector<std::string> get_subst_strings() const; + private: std::string add_key_field( const std::string &s, @@ -419,5 +471,6 @@ private: std::string escape_string(std::string in, const std::string &toesc, const std::string &escapewith); +const char *map_section_name(int msect); #endif diff --git a/crawl-ref/source/maps.cc b/crawl-ref/source/maps.cc index 7c1ff8421f..97a2eec5d8 100644 --- a/crawl-ref/source/maps.cc +++ b/crawl-ref/source/maps.cc @@ -102,6 +102,8 @@ static int write_vault(const map_def &mdef, map_type map, // Mirror the map if appropriate, resolve substitutable symbols (?), static void resolve_map(map_def &map) { + map.reinit(); + map.run_lua(true); map.resolve(); // Mirroring is possible for any map that does not explicitly forbid it. @@ -370,10 +372,13 @@ static void parse_maps(const std::string &s) void read_maps() { - parse_maps( lc_desfile = datafile_path( "splev.des" ) ); - parse_maps( lc_desfile = datafile_path( "vaults.des" ) ); - parse_maps( lc_desfile = datafile_path( "entry.des" ) ); - parse_maps( lc_desfile = datafile_path( "ebranch.des" ) ); + static const char *map_files[] = + { + "entry.des", "splev.des", "vaults.des", "ebranch.des" + }; + + for (unsigned i = 0; i < ARRAYSIZE(map_files); ++i) + parse_maps( lc_desfile = datafile_path( map_files[i] ) ); for (int i = 0, size = Options.extra_levels.size(); i < size; ++i) { diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc index 79c993acbd..281f3f0d4f 100644 --- a/crawl-ref/source/mutation.cc +++ b/crawl-ref/source/mutation.cc @@ -1087,7 +1087,7 @@ formatted_string describe_mutations() textcolor(LIGHTGREY); - for (i = 0; i < 100; i++) + for (i = 0; i < NUM_MUTATIONS; i++) { if (you.mutation[i] != 0) { @@ -1691,7 +1691,7 @@ int how_mutated(void) { int j = 0; - for (int i = 0; i < 100; i++) + for (int i = 0; i < NUM_MUTATIONS; i++) { if (you.mutation[i] && you.demon_pow[i] < you.mutation[i]) { diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc index a66b85619e..f564944522 100644 --- a/crawl-ref/source/output.cc +++ b/crawl-ref/source/output.cc @@ -1694,7 +1694,7 @@ std::string status_mut_abilities() have_any = true; } - for (unsigned i = 0; i < 100; i++) + for (unsigned i = 0; i < NUM_MUTATIONS; i++) { if (!you.mutation[i]) continue; diff --git a/crawl-ref/source/util/levcomp.lpp b/crawl-ref/source/util/levcomp.lpp index a97e58c6da..401403ac0d 100644 --- a/crawl-ref/source/util/levcomp.lpp +++ b/crawl-ref/source/util/levcomp.lpp @@ -39,16 +39,35 @@ static void clean() alloced = false; } -static void settext() +static void settext(bool trim_right = false, int strip_trailing = 0) { clean(); - if ((yylval.text = strdup(yytext))) + char *newstring = NULL; + if ((yylval.text = newstring = strdup(yytext))) + { alloced = true; + + char *s = NULL; + if (trim_right) + { + s = newstring + strlen(newstring) - 1; + while (isspace(*s) && s >= newstring) + *s-- = 0; + } + if (strip_trailing) + { + if (!s) + s = newstring + strlen(newstring) - 1; + while (s >= newstring && --strip_trailing >= 0) + *s-- = 0; + } + } } %} %x MAPDEF +%x LUA %s ARGUMENT %s MNAME %s KEYWORDS @@ -74,6 +93,18 @@ NSPACE [^\ \t\r\n] <MAPDEF>[ ]*\r?\n ; +<LUA>\s*\}\}[ \t]*$ { BEGIN(INITIAL); } +<LUA>[^\r\n]+\}\}[ \t]*$ { + settext(true, 2); + BEGIN(INITIAL); + return LUA_LINE; + } +<LUA>[^\r\n]+ { + settext(); + return LUA_LINE; + } +<LUA>\r?\n ; + <KEYWORDS>[A-Za-z_0-9\-]+ { settext(); return STRING; @@ -116,16 +147,20 @@ NSPACE [^\ \t\r\n] ^[ \t]*#.* ; -^\s*MAP { BEGIN(MAPDEF); } +^\s*MAP { BEGIN(MAPDEF); } +^prelude[ \t]*\{\{ { BEGIN(LUA); return PRELUDE; } +^lua[ \t]*\{\{ { BEGIN(LUA); return MAIN; } +^[ \t]*\{\{ { BEGIN(LUA); return MAIN; } NAME: { BEGIN(ARGUMENT); return NAME; } -default-depth: return DEFAULT_DEPTH; -DEPTH: return DEPTH; -ORIENT: return ORIENT; +default-depth: { BEGIN(ARGUMENT); return DEFAULT_DEPTH; } +DEPTH: { BEGIN(ARGUMENT); return DEPTH; } +ORIENT: { BEGIN(ARGUMENT); return ORIENT; } PLACE: { BEGIN(ARGUMENT); return PLACE; } CHANCE: return CHANCE; -FLAGS: return FLAGS; +WEIGHT: return CHANCE; +FLAGS: { BEGIN(KEYWORDS); return TAGS; } TAGS: { BEGIN(KEYWORDS); return TAGS; } SUBST: { BEGIN(ITEM_LIST); return SUBST; } MONS: { BEGIN(MNAME); return MONS; } @@ -136,42 +171,6 @@ KFEAT: { BEGIN(ARGUMENT); return KFEAT; } KITEM: { BEGIN(ARGUMENT); return KITEM; } KMONS: { BEGIN(ARGUMENT); return KMONS; } -BRANCHDEF: return BRANCH; -DEFAULT return DEFAULT; -DESC: return DESC; -BRANCH: return BRANCH; -ROOT_DEPTH: return ROOT_DEPTH; -FLOOR_COLOUR: return FLOOR_COLOUR; -ROCK_COLOUR: return ROCK_COLOUR; - -LEVEL return LEVEL; -END return END; -PVAULT: return PVAULT; -PMINIVAULT: return PMINIVAULT; - -ENTRY_MSG: { BEGIN(ARGUMENT); return ENTRY_MSG; } -EXIT_MSG: { BEGIN(ARGUMENT); return EXIT_MSG; } - -MONSTERS return MONSTERS; -ENDMONSTERS return ENDMONSTERS; - - -pandemonic return PANDEMONIC; -no_hmirror return NO_HMIRROR; -no_vmirror return NO_VMIRROR; -no_rotate return NO_ROTATE; - -encompass return ENCOMPASS; -north return NORTH; -south return SOUTH; -east return EAST; -west return WEST; -northeast return NORTHEAST; -northwest return NORTHWEST; -southeast return SOUTHEAST; -southwest return SOUTHWEST; -float return FLOAT; - - return DASH; , return COMMA; @@ -189,10 +188,6 @@ float return FLOAT; \" return QUOTE; -: return COLON; -\* return STAR; -! return NOT; - [a-zA-Z_][a-zA-Z_0-9]* { settext(); return IDENTIFIER; diff --git a/crawl-ref/source/util/levcomp.ypp b/crawl-ref/source/util/levcomp.ypp index d62800845e..757fc02504 100644 --- a/crawl-ref/source/util/levcomp.ypp +++ b/crawl-ref/source/util/levcomp.ypp @@ -1,8 +1,10 @@ %{ #include "AppHdr.h" +#include "clua.h" #include "libutil.h" #include "levcomp.h" +#include "luadgn.h" #include "mapdef.h" #include "stuff.h" #include <map> @@ -59,28 +61,16 @@ level_range set_range(const char *s, int start, int end) %token <i> BRANCHDEF BRANCH DESC DEFAULT %token <i> DEFAULT_DEPTH SHUFFLE SUBST TAGS KFEAT KITEM KMONS -%token <i> NAME DEPTH ORIENT PLACE CHANCE FLAGS MONS ITEM -%token <i> ROOT_DEPTH ENTRY_MSG EXIT_MSG -%token <i> ROCK_COLOUR FLOOR_COLOUR -%token <i> ENCOMPASS FLOAT -%token <i> NORTH EAST SOUTH WEST -%token <i> NORTHEAST SOUTHEAST SOUTHWEST NORTHWEST - -%token <i> LEVEL END PVAULT PMINIVAULT MONSTERS ENDMONSTERS +%token <i> NAME DEPTH ORIENT PLACE CHANCE MONS ITEM +%token <i> PRELUDE MAIN %token <i> CHARACTER -%token <i> NO_HMIRROR NO_VMIRROR NO_ROTATE - -%token <i> PANDEMONIC -%token <i> DASH COMMA QUOTE OPAREN CPAREN COLON STAR NOT +%token <i> DASH COMMA QUOTE OPAREN CPAREN %token <i> INTEGER -%type <i> orient_name flagname -%type <range> lev_range ext_range - %token <text> STRING MAP_LINE MONSTER_NAME ITEM_INFO -%token <text> IDENTIFIER +%token <text> IDENTIFIER LUA_LINE %% @@ -98,50 +88,24 @@ definition : def {} def : defdepth {} ; -defdepth : DEFAULT_DEPTH - { lc_default_depths.clear(); } - default_depth_ranges +defdepth : DEFAULT_DEPTH STRING + { + dgn_reset_default_depth(); + std::string err = dgn_set_default_depth($2); + if (!err.empty()) + yyerror(make_stringf("Bad default-depth: %s (%s)", + $2, err.c_str()).c_str()); + } ; level : name metalines map_def metalines { - if (lc_map.orient == MAP_FLOAT - || lc_map.is_minivault()) - { - if (lc_map.map.width() > GXM - MAPGEN_BORDER * 2 - || lc_map.map.height() > GYM - MAPGEN_BORDER * 2) - { - char buf[300]; - snprintf(buf, sizeof buf, - "%s is too big: %dx%d - max %dx%d", - lc_map.is_minivault()? "Minivault" : "Float", - lc_map.map.width(), lc_map.map.height(), - GXM - MAPGEN_BORDER * 2, - GYM - MAPGEN_BORDER * 2); - yyerror(buf); - } - } - else - { - if (lc_map.map.width() > GXM - || lc_map.map.height() > GYM) - { - char buf[300]; - snprintf(buf, sizeof buf, - "Map is too big: %dx%d - max %dx%d", - lc_map.map.width(), lc_map.map.height(), - GXM, GYM); - yyerror(buf); - } - } - - if (lc_map.map.height() == 0) - yyerror("Must define map."); - + std::string err = lc_map.validate(); + if (!err.empty()) + yyerror(err.c_str()); if (!lc_map.has_depth() && !lc_default_depths.empty()) lc_map.add_depths(lc_default_depths.begin(), lc_default_depths.end()); - add_parsed_map( lc_map ); } ; @@ -176,7 +140,6 @@ metaline : place | depth | chance | orientation - | flags | mons | items | subst @@ -185,36 +148,57 @@ metaline : place | kfeat | kitem | kmons + | main_lua + | prelude_lua + ; + +main_lua : MAIN main_lua_lines { } + +main_lua_lines : /* empty */ { } + | main_lua_lines main_lua_line { } + ; + +main_lua_line : LUA_LINE + { + lc_map.main.add(yylineno, $1); + } + +prelude_lua : PRELUDE prelude_lua_lines { } + +prelude_lua_lines : /* empty */ { } + | prelude_lua_lines prelude_lua_line { } ; +prelude_lua_line : LUA_LINE + { + lc_map.prelude.add(yylineno, $1); + } + kfeat : KFEAT { } | KFEAT STRING { - std::string err = lc_map.add_key_feat($2); - if (!err.empty()) - yyerror( - make_stringf("Bad arg to KFEAT: '%s' (%s)", - $2, err.c_str()).c_str()); + lc_map.main.add( + yylineno, + make_stringf("kfeat(\"%s\")", + quote_lua_string($2).c_str())); } kmons : KMONS { } | KMONS STRING { - std::string err = lc_map.add_key_mons($2); - if (!err.empty()) - yyerror( - make_stringf("Bad arg to KMONS: '%s' (%s)", - $2, err.c_str()).c_str()); + lc_map.main.add( + yylineno, + make_stringf("kmons(\"%s\")", + quote_lua_string($2).c_str())); } kitem : KITEM { } | KITEM STRING { - std::string err = lc_map.add_key_item($2); - if (!err.empty()) - yyerror( - make_stringf("Bad arg to KITEM: '%s' (%s)", - $2, err.c_str()).c_str()); + lc_map.main.add( + yylineno, + make_stringf("kitem(\"%s\")", + quote_lua_string($2).c_str())); } shuffle : SHUFFLE shuffle_specifiers {} @@ -226,23 +210,25 @@ shuffle_specifiers : shuffle_spec shuffle_spec : ITEM_INFO { - std::string err = lc_map.map.add_shuffle($1); - if (!err.empty()) - yyerror( - make_stringf( - "Bad shuffle argument: '%s' (%s)", - $1, err.c_str() ).c_str() ); + lc_map.main.add( + yylineno, + make_stringf("shuffle(\"%s\")", + quote_lua_string($1).c_str())); } tags : TAGS tagstrings {} ; tagstrings : /* empty */ - | STRING tagstrings + | tagstrings tagstring + ; + +tagstring : STRING { - lc_map.tags += " "; - lc_map.tags += $1; - lc_map.tags += " "; + lc_map.main.add( + yylineno, + make_stringf("tags(\"%s\")", + quote_lua_string($1).c_str())); } ; @@ -255,12 +241,10 @@ subst_specifiers : subst_spec subst_spec : ITEM_INFO { - std::string err = lc_map.map.add_subst($1); - if (!err.empty()) - yyerror( - make_stringf( - "Bad SUBST argument: '%s' (%s)", - $1, err.c_str() ).c_str() ); + lc_map.main.add( + yylineno, + make_stringf("subst(\"%s\")", + quote_lua_string($1).c_str())); } ; @@ -274,17 +258,10 @@ item_specifiers : item_specifier COMMA item_specifiers item_specifier : ITEM_INFO { - std::string error = lc_map.items.add_item($1); - if (error.size()) - { - char errbuf[300]; - snprintf(errbuf, sizeof errbuf, - "Invalid item descriptor: '%s' (%s)", - $1, error.c_str()); - yyerror(errbuf); - } - if (lc_map.items.size() > 8) - yyerror("Too many items specified (max 8)"); + lc_map.main.add( + yylineno, + make_stringf("item(\"%s\")", + quote_lua_string($1).c_str())); } mons : MONS {} @@ -297,139 +274,50 @@ mnames : mname COMMA mnames mname : MONSTER_NAME { - std::string err = lc_map.mons.add_mons($1); - if (!err.empty()) - { - char buf[300]; - snprintf(buf, sizeof buf, - "bad monster spec '%s' (%s)", - $1, err.c_str()); - yyerror(buf); - } - if (lc_map.mons.size() > 7) - yyerror("Too many monsters specified (max 7)"); + lc_map.main.add( + yylineno, + make_stringf("mons(\"%s\")", + quote_lua_string($1).c_str())); } ; place : PLACE STRING { - lc_map.place = $2; + lc_map.main.add( + yylineno, + make_stringf("place(\"%s\")", + quote_lua_string($2).c_str())); } ; depth : DEPTH {} - | DEPTH extended_depth_ranges {} - ; - -default_depth_ranges : - ext_range - { - lc_default_depths.push_back($1); - } - - | default_depth_ranges COMMA ext_range - { - lc_default_depths.push_back($3); - } - ; - -extended_depth_ranges : - ext_range - { - lc_map.add_depth($1); - } - - | extended_depth_ranges COMMA ext_range - { - lc_map.add_depth($3); - } - ; - -ext_range : lev_range { $$ = $1; } - | NOT lev_range { $$ = $2; $$.deny = true; } - ; - -lev_range : IDENTIFIER - { - $$ = set_range($1, 1, 100); - } - - | IDENTIFIER COLON STAR + | DEPTH STRING { - $$ = set_range($1, 1, 100); - } - - | IDENTIFIER COLON INTEGER DASH INTEGER - { - $$ = set_range($1, $3, $5); - } - - | IDENTIFIER COLON INTEGER - { - $$ = set_range($1, $3, $3); - } - - | INTEGER DASH INTEGER - { - $$ = set_range("Any", $1, $3); - } - - | INTEGER - { - $$ = set_range("Any", $1, $1); + lc_map.main.add( + yylineno, + make_stringf("depth(\"%s\")", + quote_lua_string($2).c_str())); } ; chance : CHANCE INTEGER { - lc_map.chance = $2; + lc_map.main.add( + yylineno, + make_stringf("chance(\"%d\")", $2)); } ; orientation : ORIENT {} - | ORIENT orient_name + | ORIENT STRING { - lc_map.orient = (map_section_type) $2; + lc_map.main.add( + yylineno, + make_stringf("orient(\"%s\")", + quote_lua_string($2).c_str())); } ; -orient_name : ENCOMPASS { $$ = MAP_ENCOMPASS; } - | NORTH { $$ = MAP_NORTH; } - | EAST { $$ = MAP_EAST; } - | SOUTH { $$ = MAP_SOUTH; } - | WEST { $$ = MAP_WEST; } - | NORTHEAST { $$ = MAP_NORTHEAST; } - | SOUTHEAST { $$ = MAP_SOUTHEAST; } - | SOUTHWEST { $$ = MAP_SOUTHWEST; } - | NORTHWEST { $$ = MAP_NORTHWEST; } - | FLOAT { $$ = MAP_FLOAT; } - ; - -flags : FLAGS flagnames {} - ; - -flagnames : /* empty */ - | flagname flagnames - { - switch ($1) { - case NO_HMIRROR: - lc_map.flags &= ~MAPF_MIRROR_HORIZONTAL; - break; - case NO_VMIRROR: - lc_map.flags &= ~MAPF_MIRROR_VERTICAL; - break; - case NO_ROTATE: - lc_map.flags &= ~MAPF_ROTATE; - break; - } - } - ; - -flagname : NO_HMIRROR { $$ = NO_HMIRROR; } - | NO_VMIRROR { $$ = NO_VMIRROR; } - | NO_ROTATE { $$ = NO_ROTATE; } - ; - map_def : map_lines ; @@ -439,7 +327,10 @@ map_lines : map_line map_line : MAP_LINE { - lc_map.map.add_line($1); + lc_map.main.add( + yylineno, + make_stringf("map(\"%s\")", + quote_lua_string($1).c_str())); } ; |