summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/mapdef.cc
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-07-01 16:07:21 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2007-07-01 16:07:21 +0000
commitfc78d02aee0c39be4fb45b3b640a17f2af18cd45 (patch)
tree8826cfb101f01e3a0d2abe855e8dff8ef2ffc87c /crawl-ref/source/mapdef.cc
parent0645520057d5b630626c5e6ce7bf3099c9500ea1 (diff)
downloadcrawl-ref-fc78d02aee0c39be4fb45b3b640a17f2af18cd45.tar.gz
crawl-ref-fc78d02aee0c39be4fb45b3b640a17f2af18cd45.zip
Added NSUBST.
Should not highlight unvisited stairs in the Vestibule, since travel cache doesn't track visited-ness of Vestibule stairs. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1706 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/mapdef.cc')
-rw-r--r--crawl-ref/source/mapdef.cc165
1 files changed, 150 insertions, 15 deletions
diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc
index a4238facf4..0f8b161c2b 100644
--- a/crawl-ref/source/mapdef.cc
+++ b/crawl-ref/source/mapdef.cc
@@ -41,6 +41,19 @@ const char *map_section_name(int msect)
return map_section_names[msect];
}
+template <typename V>
+void scramble(V &v)
+{
+ V temp(v);
+ v.clear();
+ while (!temp.empty())
+ {
+ int i = random2(temp.size());
+ v.push_back(temp[i]);
+ temp.erase(temp.begin() + i);
+ }
+}
+
// Returns true if s contains tag 'tag', and strips out tag from s.
bool strip_tag(std::string &s, const std::string &tag)
{
@@ -96,9 +109,10 @@ static int find_weight(std::string &s)
}
static std::string split_key_item(const std::string &s,
- int *key,
+ std::string *key,
int *separator,
- std::string *arg)
+ std::string *arg,
+ int key_max_len = 1)
{
std::string::size_type
norm = s.find("=", 1),
@@ -108,19 +122,18 @@ static std::string split_key_item(const std::string &s,
if (sep == std::string::npos)
return ("malformed declaration - must use = or :");
- std::string what_to_subst = trimmed_string(s.substr(0, sep));
+ *key = trimmed_string(s.substr(0, sep));
std::string substitute = trimmed_string(s.substr(sep + 1));
- if (what_to_subst.length() != 1)
+ if (key->empty() || (int) key->length() > key_max_len)
return make_stringf(
"selector '%s' must be exactly one character in '%s'",
- what_to_subst.c_str(), s.c_str());
+ key->c_str(), s.c_str());
if (substitute.empty())
return make_stringf("no substitute defined in '%s'",
s.c_str());
- *key = what_to_subst[0];
*arg = substitute;
*separator = s[sep];
@@ -410,8 +423,8 @@ void map_lines::add_marker(map_marker *marker)
std::string map_lines::add_feature_marker(const std::string &s)
{
- std::string arg;
- int key = 0, sep = 0;
+ std::string key, arg;
+ int sep = 0;
std::string err = split_key_item(s, &key, &sep, &arg);
if (!err.empty())
return (err);
@@ -420,7 +433,7 @@ std::string map_lines::add_feature_marker(const std::string &s)
if (feat == DNGN_UNSEEN)
return make_stringf("unknown feature: %s", arg.c_str());
- transforms.push_back(new map_feat_marker_spec(key, feat));
+ transforms.push_back(new map_feat_marker_spec(key[0], feat));
return ("");
}
@@ -521,7 +534,7 @@ std::string map_lines::add_subst(const std::string &sub)
return ("");
int sep = 0;
- int key = 0;
+ std::string key;
std::string substitute;
std::string err = split_key_item(sub, &key, &sep, &substitute);
@@ -533,8 +546,64 @@ std::string map_lines::add_subst(const std::string &sub)
if (!err.empty())
return (err);
- transforms.push_back( new subst_spec( key, sep == ':', repl ) );
+ transforms.push_back( new subst_spec( key[0], sep == ':', repl ) );
+
+ return ("");
+}
+
+std::string map_lines::parse_nsubst_spec(const std::string &s,
+ subst_spec &spec)
+{
+ std::string key, arg;
+ int sep;
+ std::string err = split_key_item(s, &key, &sep, &arg);
+ if (!err.empty())
+ return err;
+ const int keyval = key == "*"? -1 : atoi(key.c_str());
+ if (!keyval)
+ return make_stringf("Illegal spec: %s", s.c_str());
+
+ glyph_replacements_t repl;
+ err = parse_glyph_replacements(arg, repl);
+ if (!err.empty())
+ return (err);
+
+ spec = subst_spec(keyval, sep == ':', repl);
+ return ("");
+}
+
+std::string map_lines::add_nsubst(const std::string &s)
+{
+ std::vector<subst_spec> substs;
+
+ int sep;
+ std::string key, arg;
+
+ std::string err = split_key_item(s, &key, &sep, &arg);
+ if (!err.empty())
+ return (err);
+
+ std::vector<std::string> segs = split_string("/", arg);
+ for (int i = 0, size = segs.size(); i < size; ++i)
+ {
+ std::string &ns = segs[i];
+ if (ns.find('=') == std::string::npos
+ && ns.find(':') == std::string::npos)
+ {
+ if (i < size - 1)
+ ns = "1=" + ns;
+ else
+ ns = "*=" + ns;
+ }
+ subst_spec spec;
+ err = parse_nsubst_spec(ns, spec);
+ if (!err.empty())
+ return (make_stringf("Bad NSUBST spec: %s (%s)",
+ s.c_str(), err.c_str()));
+ substs.push_back(spec);
+ }
+ transforms.push_back( new nsubst_spec(key[0], substs) );
return ("");
}
@@ -617,6 +686,11 @@ void map_lines::clear_shuffles()
clear_transforms(map_transformer::TT_SHUFFLE);
}
+void map_lines::clear_nsubsts()
+{
+ clear_transforms(map_transformer::TT_NSUBST);
+}
+
void map_lines::clear_substs()
{
clear_transforms(map_transformer::TT_SUBST);
@@ -709,6 +783,44 @@ void map_lines::subst(subst_spec &spec)
subst(lines[y], spec);
}
+void map_lines::nsubst(nsubst_spec &spec)
+{
+ std::vector<coord_def> positions;
+ for (int y = 0, ysize = lines.size(); y < ysize; ++y)
+ {
+ std::string::size_type pos = 0;
+ while ((pos = lines[y].find(spec.key, pos)) != std::string::npos)
+ positions.push_back(coord_def(pos++, y));
+ }
+ scramble(positions);
+
+ int pcount = 0;
+ const int psize = positions.size();
+ for (int i = 0, size = spec.specs.size(); i < size && pcount < psize; ++i)
+ {
+ const int nsubsts = spec.specs[i].key();
+ pcount += apply_nsubst(positions, pcount, nsubsts, spec.specs[i]);
+ }
+}
+
+int map_lines::apply_nsubst(std::vector<coord_def> &pos,
+ int start, int nsub,
+ subst_spec &spec)
+{
+ if (nsub == -1)
+ nsub = pos.size();
+ const int end = std::min(start + nsub, (int) pos.size());
+ int substituted = 0;
+ for (int i = start; i < end; ++i)
+ {
+ const int val = spec.value();
+ const coord_def &c = pos[i];
+ lines[c.y][c.x] = val;
+ ++substituted;
+ }
+ return (substituted);
+}
+
std::string map_lines::block_shuffle(const std::string &s)
{
std::vector<std::string> segs = split_string("/", s);
@@ -1525,16 +1637,15 @@ std::string map_def::add_key_field(
const std::string &s,
std::string (keyed_mapspec::*set_field)(const std::string &s, bool fixed))
{
- int key = 0;
int separator = 0;
- std::string arg;
+ std::string key, arg;
std::string err = split_key_item(s, &key, &separator, &arg);
if (!err.empty())
return (err);
- keyed_mapspec &km = keyspecs[key];
- km.key_glyph = key;
+ keyed_mapspec &km = keyspecs[key[0]];
+ km.key_glyph = key[0];
return ((km.*set_field)(arg, separator == ':'));
}
@@ -2159,6 +2270,30 @@ bool subst_spec::operator == (const subst_spec &other) const
}
//////////////////////////////////////////////////////////////////////////
+// nsubst_spec
+
+nsubst_spec::nsubst_spec(int _key, const std::vector<subst_spec> &_specs)
+ : key(_key), specs(_specs)
+{
+}
+
+std::string nsubst_spec::apply_transform(map_lines &map)
+{
+ map.nsubst(*this);
+ return ("");
+}
+
+map_transformer *nsubst_spec::clone() const
+{
+ return new nsubst_spec(key, specs);
+}
+
+std::string nsubst_spec::describe() const
+{
+ return ("");
+}
+
+//////////////////////////////////////////////////////////////////////////
// shuffle_spec
std::string shuffle_spec::apply_transform(map_lines &map)