summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-06-23 20:02:09 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-06-23 20:02:09 +0000
commitdd633d4ba9abc5e8384ec12974ea18c3bbaefe2d (patch)
tree9d3210276b7cb9b141571e3eb75503c81c3d39ef /crawl-ref/source
parent32ba97b96685241b1e30299f313c15d20d103998 (diff)
downloadcrawl-ref-dd633d4ba9abc5e8384ec12974ea18c3bbaefe2d.tar.gz
crawl-ref-dd633d4ba9abc5e8384ec12974ea18c3bbaefe2d.zip
Oops, missed luadgn.cc
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1630 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/luadgn.cc504
-rw-r--r--crawl-ref/source/luadgn.h48
2 files changed, 552 insertions, 0 deletions
diff --git a/crawl-ref/source/luadgn.cc b/crawl-ref/source/luadgn.cc
new file mode 100644
index 0000000000..1857cdf4d0
--- /dev/null
+++ b/crawl-ref/source/luadgn.cc
@@ -0,0 +1,504 @@
+/*
+ * File: luadgn.cc
+ * Summary: Dungeon-builder Lua interface.
+ *
+ * Modified for Crawl Reference by $Author: dshaligram $ on $Date: 2007-06-21T19:20:47.183838Z $
+ */
+
+#include "AppHdr.h"
+#include "clua.h"
+#include "luadgn.h"
+#include "mapdef.h"
+
+// Lua interpreter for the dungeon builder.
+CLua dlua(false);
+
+template <typename list, typename lpush>
+static int dlua_gentable(lua_State *ls, const list &strings, lpush push)
+{
+ lua_newtable(ls);
+ for (int i = 0, size = strings.size(); i < size; ++i)
+ {
+ push(ls, strings[i]);
+ lua_rawseti(ls, -2, i + 1);
+ }
+ return (1);
+}
+
+inline static void dlua_pushcxxstring(lua_State *ls, const std::string &s)
+{
+ lua_pushstring(ls, s.c_str());
+}
+
+static int dlua_stringtable(lua_State *ls, const std::vector<std::string> &s)
+{
+ return dlua_gentable(ls, s, dlua_pushcxxstring);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// dlua_chunk
+
+dlua_chunk::dlua_chunk()
+ : file(), chunk(), first(-1), last(-1), error()
+{
+ clear();
+}
+
+void dlua_chunk::clear()
+{
+ file.clear();
+ chunk.clear();
+ first = last = -1;
+ error.clear();
+}
+
+void dlua_chunk::set_file(const std::string &s)
+{
+ file = s;
+}
+
+void dlua_chunk::add(int line, const std::string &s)
+{
+ if (first == -1)
+ first = line;
+
+ if (line != last && last != -1)
+ chunk += "\n";
+
+ chunk += " ";
+ chunk += s;
+ last = line;
+}
+
+int dlua_chunk::check_op(CLua *interp, int err)
+{
+ error = interp->error;
+ return (err);
+}
+
+int dlua_chunk::load(CLua *interp)
+{
+ if (trimmed_string(chunk).empty())
+ return (-1000);
+ return check_op(interp,
+ interp->loadstring(chunk.c_str(), "dlua_chunk"));
+}
+
+int dlua_chunk::load_call(CLua *interp, const char *fn)
+{
+ int err = load(interp);
+ if (err == -1000)
+ return (0);
+ if (err)
+ return (err);
+
+ return check_op(interp, interp->callfn(fn, 1, 0));
+}
+
+std::string dlua_chunk::orig_error() const
+{
+ return (error);
+}
+
+bool dlua_chunk::empty() const
+{
+ return trimmed_string(chunk).empty();
+}
+
+///////////////////////////////////////////////////////////////////////////
+// Lua dungeon bindings (in the dgn table).
+
+static depth_ranges dgn_default_depths;
+
+#define MAP(ls, n, var) \
+ map_def *var = *(map_def **) luaL_checkudata(ls, n, MAP_METATABLE)
+
+void dgn_reset_default_depth()
+{
+ dgn_default_depths.clear();
+}
+
+std::string dgn_set_default_depth(const std::string &s)
+{
+ std::vector<std::string> frags = split_string(",", s);
+ for (int i = 0, size = frags.size(); i < size; ++i)
+ {
+ try
+ {
+ dgn_default_depths.push_back( level_range::parse(frags[i]) );
+ }
+ catch (const std::string &error)
+ {
+ return (error);
+ }
+ }
+ return ("");
+}
+
+static void dgn_add_depths(depth_ranges &drs, lua_State *ls, int s, int e)
+{
+ for (int i = s; i <= e; ++i)
+ {
+ const char *depth = luaL_checkstring(ls, i);
+ std::vector<std::string> frags = split_string(",", depth);
+ for (int j = 0, size = frags.size(); i < size; ++i)
+ {
+ try
+ {
+ dgn_default_depths.push_back( level_range::parse(frags[j]) );
+ }
+ catch (const std::string &error)
+ {
+ luaL_error(ls, error.c_str());
+ }
+ }
+ }
+}
+
+static std::string dgn_depth_list_string(const depth_ranges &drs)
+{
+ return (comma_separated_line(drs.begin(), drs.end(), ", ", ", "));
+}
+
+static int dgn_depth_proc(lua_State *ls, depth_ranges &dr, int s)
+{
+ if (lua_gettop(ls) < s)
+ {
+ PLUARET(string, dgn_depth_list_string(dr).c_str());
+ }
+
+ if (lua_isnil(ls, s))
+ {
+ dr.clear();
+ return (0);
+ }
+
+ dr.clear();
+ dgn_add_depths(dr, ls, s, lua_gettop(ls));
+ return (0);
+}
+
+static int dgn_default_depth(lua_State *ls)
+{
+ return dgn_depth_proc(ls, dgn_default_depths, 1);
+}
+
+static int dgn_depth(lua_State *ls)
+{
+ MAP(ls, 1, map);
+ return dgn_depth_proc(ls, map->depths, 2);
+}
+
+static int dgn_place(lua_State *ls)
+{
+ MAP(ls, 1, map);
+ if (lua_gettop(ls) > 1)
+ {
+ if (lua_isnil(ls, 2))
+ map->place.clear();
+ else
+ map->place = luaL_checkstring(ls, 2);
+ }
+ PLUARET(string, map->place.c_str());
+}
+
+static int dgn_tags(lua_State *ls)
+{
+ MAP(ls, 1, map);
+ if (lua_gettop(ls) > 1)
+ {
+ if (lua_isnil(ls, 2))
+ map->tags.clear();
+ else
+ {
+ const char *s = luaL_checkstring(ls, 2);
+ map->tags += " " + trimmed_string(s) + " ";
+ }
+ }
+ PLUARET(string, map->tags.c_str());
+}
+
+static int dgn_tags_remove(lua_State *ls)
+{
+ MAP(ls, 1, map);
+
+ const int top = lua_gettop(ls);
+ for (int i = 2; i <= top; ++i)
+ {
+ const std::string axee = luaL_checkstring(ls, i);
+ const std::string::size_type pos = map->tags.find(axee);
+ if (pos != std::string::npos)
+ map->tags =
+ map->tags.substr(0, pos)
+ + map->tags.substr(pos + axee.length());
+ }
+ PLUARET(string, map->tags.c_str());
+}
+
+static int dgn_weight(lua_State *ls)
+{
+ MAP(ls, 1, map);
+ if (!lua_isnil(ls, 2))
+ map->chance = luaL_checkint(ls, 2);
+ PLUARET(number, map->chance);
+}
+
+static int dgn_orient(lua_State *ls)
+{
+ MAP(ls, 1, map);
+ if (lua_gettop(ls) > 1)
+ {
+ if (lua_isnil(ls, 2))
+ map->orient = MAP_NONE;
+ else
+ {
+ const std::string orient = luaL_checkstring(ls, 2);
+ bool found = false;
+ // Note: Empty string is intentionally mapped to MAP_NONE!
+ for (int i = MAP_NONE; i < MAP_NUM_SECTION_TYPES; ++i)
+ {
+ if (orient == map_section_name(i))
+ {
+ map->orient = static_cast<map_section_type>(i);
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ luaL_error(ls, ("Bad orient: " + orient).c_str());
+ }
+ }
+ PLUARET(string, map_section_name(map->orient));
+}
+
+static int dgn_shuffle(lua_State *ls)
+{
+ MAP(ls, 1, map);
+ if (lua_gettop(ls) == 1)
+ return dlua_stringtable(ls, map->get_shuffle_strings());
+
+ 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());
+ }
+ }
+
+ 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_subst(lua_State *ls)
+{
+ MAP(ls, 1, map);
+ if (lua_gettop(ls) == 1)
+ return dlua_stringtable(ls, map->get_subst_strings());
+
+ for (int i = 2, size = lua_gettop(ls); i <= size; ++i)
+ {
+ if (lua_isnil(ls, i))
+ map->map.clear_substs();
+ else
+ {
+ std::string err = map->map.add_subst(luaL_checkstring(ls, i));
+ if (!err.empty())
+ luaL_error(ls, err.c_str());
+ }
+ }
+
+ return (0);
+}
+
+static int dgn_subst_remove(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));
+ return (0);
+}
+
+static int dgn_map(lua_State *ls)
+{
+ MAP(ls, 1, map);
+ if (lua_gettop(ls) == 1)
+ return dlua_stringtable(ls, map->map.get_lines());
+
+ if (lua_isnil(ls, 2))
+ {
+ map->map.clear();
+ return (0);
+ }
+
+ if (lua_isstring(ls, 2))
+ {
+ map->map.add_line(luaL_checkstring(ls, 2));
+ return (0);
+ }
+
+ std::vector<std::string> &lines = map->map.get_lines();
+ int which_line = luaL_checkint(ls, 2);
+ if (which_line < 0)
+ which_line += (int) lines.size();
+ if (lua_gettop(ls) == 2)
+ {
+ if (which_line < 0 || which_line >= (int) lines.size())
+ {
+ luaL_error(ls,
+ lines.empty()? "Map is empty"
+ : make_stringf("Line %d out of range (0-%u)",
+ which_line,
+ lines.size() - 1).c_str());
+ }
+ PLUARET(string, lines[which_line].c_str());
+ }
+
+ if (lua_isnil(ls, 3))
+ {
+ if (which_line >= 0 && which_line < (int) lines.size())
+ {
+ lines.erase(lines.begin() + which_line);
+ PLUARET(boolean, true);
+ }
+ return (0);
+ }
+
+ const std::string newline = luaL_checkstring(ls, 3);
+ if (which_line < 0)
+ luaL_error(ls,
+ make_stringf("Index %d out of range", which_line).c_str());
+
+ if (which_line < (int) lines.size())
+ {
+ lines[which_line] = newline;
+ return (0);
+ }
+
+ lines.reserve(which_line + 1);
+ lines.resize(which_line + 1, "");
+ lines[which_line] = newline;
+ return (0);
+}
+
+static int dgn_mons(lua_State *ls)
+{
+ MAP(ls, 1, map);
+ if (lua_gettop(ls) == 1)
+ return (0);
+
+ if (lua_isnil(ls, 2))
+ {
+ map->mons.clear();
+ return (0);
+ }
+
+ if (lua_isstring(ls, 2))
+ {
+ std::string err = map->mons.add_mons(luaL_checkstring(ls, 2));
+ if (!err.empty())
+ luaL_error(ls, err.c_str());
+ return (0);
+ }
+
+ const int index = luaL_checkint(ls, 2);
+ std::string err = map->mons.set_mons(index, luaL_checkstring(ls, 3));
+ if (!err.empty())
+ luaL_error(ls, err.c_str());
+ return (0);
+}
+
+static int dgn_item(lua_State *ls)
+{
+ MAP(ls, 1, map);
+ if (lua_gettop(ls) == 1)
+ return (0);
+
+ if (lua_isnil(ls, 2))
+ {
+ map->items.clear();
+ return (0);
+ }
+
+ if (lua_isstring(ls, 2))
+ {
+ std::string err = map->items.add_item(luaL_checkstring(ls, 2));
+ if (!err.empty())
+ luaL_error(ls, err.c_str());
+ return (0);
+ }
+
+ const int index = luaL_checkint(ls, 2);
+ std::string err = map->items.set_item(index, luaL_checkstring(ls, 3));
+ if (!err.empty())
+ luaL_error(ls, err.c_str());
+ return (0);
+}
+
+static int dgn_kfeat(lua_State *ls)
+{
+ MAP(ls, 1, map);
+ std::string err = map->add_key_feat(luaL_checkstring(ls, 2));
+ if (!err.empty())
+ luaL_error(ls, err.c_str());
+ return (0);
+}
+
+static int dgn_kmons(lua_State *ls)
+{
+ MAP(ls, 1, map);
+ std::string err = map->add_key_mons(luaL_checkstring(ls, 2));
+ if (!err.empty())
+ luaL_error(ls, err.c_str());
+ return (0);
+}
+
+static int dgn_kitem(lua_State *ls)
+{
+ MAP(ls, 1, map);
+ std::string err = map->add_key_item(luaL_checkstring(ls, 2));
+ if (!err.empty())
+ luaL_error(ls, err.c_str());
+ return (0);
+}
+
+static const struct luaL_reg dgn_lib[] =
+{
+ { "default_depth", dgn_default_depth },
+ { "depth", dgn_depth },
+ { "place", dgn_place },
+ { "tags", dgn_tags },
+ { "tags_remove", dgn_tags_remove },
+ { "chance", dgn_weight },
+ { "weight", dgn_weight },
+ { "orient", dgn_orient },
+ { "shuffle", dgn_shuffle },
+ { "shuffle_remove", dgn_shuffle_remove },
+ { "subst", dgn_subst },
+ { "subst_remove", dgn_subst_remove },
+ { "map", dgn_map },
+ { "mons", dgn_mons },
+ { "item", dgn_item },
+ { "kfeat", dgn_kfeat },
+ { "kitem", dgn_kitem },
+ { "kmons", dgn_kmons },
+ { NULL, NULL }
+};
+
+void init_dungeon_lua()
+{
+ dlua.execfile("clua/dungeon.lua");
+ luaL_newmetatable(dlua, MAP_METATABLE);
+ lua_pop(dlua, 1);
+ luaL_openlib(dlua, "dgn", dgn_lib, 0);
+}
diff --git a/crawl-ref/source/luadgn.h b/crawl-ref/source/luadgn.h
new file mode 100644
index 0000000000..ca778c4b19
--- /dev/null
+++ b/crawl-ref/source/luadgn.h
@@ -0,0 +1,48 @@
+/*
+ * File: luadgn.h
+ * Summary: Dungeon-builder Lua interface.
+ *
+ * Modified for Crawl Reference by $Author: dshaligram $ on $Date: 2007-06-21T19:20:47.183838Z $
+ */
+
+#ifndef LUADGN_H
+#define LUADGN_H
+
+#include "AppHdr.h"
+#include "clua.h"
+
+extern CLua dlua;
+
+class dlua_chunk
+{
+private:
+ std::string file;
+ std::string chunk;
+ int first, last; // First and last lines of the original source.
+
+private:
+ int check_op(CLua *, int);
+
+public:
+ std::string error;
+
+public:
+ dlua_chunk();
+ void clear();
+ void add(int line, const std::string &line);
+
+ int load(CLua *interp);
+ int load_call(CLua *interp, const char *function);
+ void set_file(const std::string &s);
+
+ const std::string &lua_string() const { return chunk; }
+ std::string orig_error() const;
+
+ bool empty() const;
+};
+
+void init_dungeon_lua();
+std::string dgn_set_default_depth(const std::string &s);
+void dgn_reset_default_depth();
+
+#endif