summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-06-23 19:58:45 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-06-23 19:58:45 +0000
commit32ba97b96685241b1e30299f313c15d20d103998 (patch)
tree8ab81f56171f4a2f179f24db66d4794f9908770d /crawl-ref
parentd09478f5fd2fbbc23a3d0785d201ab7e7c8e2d8f (diff)
downloadcrawl-ref-32ba97b96685241b1e30299f313c15d20d103998.tar.gz
crawl-ref-32ba97b96685241b1e30299f313c15d20d103998.zip
Step 1 of .des file Lua-isation. The dungeon compiler converts .des files to
Lua (Lua code can be embedded with {{ <lua code here> }} constructs) that is run to produce the final map. Some maps may be broken, this is untested, lots more work needs to be done. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1629 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/Kills.cc2
-rw-r--r--crawl-ref/source/acr.cc4
-rw-r--r--crawl-ref/source/chardump.cc2
-rw-r--r--crawl-ref/source/clua.cc123
-rw-r--r--crawl-ref/source/clua.h47
-rw-r--r--crawl-ref/source/dat/clua/dungeon.lua41
-rw-r--r--crawl-ref/source/dat/ebranch.des2
-rw-r--r--crawl-ref/source/makefile.obj1
-rw-r--r--crawl-ref/source/mapdef.cc386
-rw-r--r--crawl-ref/source/mapdef.h77
-rw-r--r--crawl-ref/source/maps.cc13
-rw-r--r--crawl-ref/source/mutation.cc4
-rw-r--r--crawl-ref/source/output.cc2
-rw-r--r--crawl-ref/source/util/levcomp.lpp89
-rw-r--r--crawl-ref/source/util/levcomp.ypp305
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()));
}
;