summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/mapdef.cc
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/source/mapdef.cc
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/source/mapdef.cc')
-rw-r--r--crawl-ref/source/mapdef.cc386
1 files changed, 375 insertions, 11 deletions
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