summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/docs/develop/level_design.txt43
-rw-r--r--crawl-ref/source/dat/entry.des16
-rw-r--r--crawl-ref/source/dat/mini.des10
-rw-r--r--crawl-ref/source/mapdef.cc134
-rw-r--r--crawl-ref/source/mapdef.h54
5 files changed, 182 insertions, 75 deletions
diff --git a/crawl-ref/docs/develop/level_design.txt b/crawl-ref/docs/develop/level_design.txt
index 2a8889c193..f0e9f73eae 100644
--- a/crawl-ref/docs/develop/level_design.txt
+++ b/crawl-ref/docs/develop/level_design.txt
@@ -753,11 +753,8 @@ FTILE: . = floor_grass:20 / floor_dirt / none
underneath it will be the tile that was specified.
If a feature that normally covers the floor (e.g. rock walls) is
- destroyed, this floor tile will be used in place of the normal floor.
- Thus, it can be useful even for non-floor features.
-
- For convenience, multiple glyphs can be specified together as a
- group, e.g. ".[{( = floor_orc".
+ destroyed, this floor tile will be used in place of the normal
+ floor. Thus, it can be useful even for non-floor features.
Like COLOUR, this should be used sparingly.
@@ -1009,6 +1006,9 @@ MARKER: A = feat:<feature_name> or lua:<marker_expr>
SHUFFLE: Oa/|c
MARKER: O = lua:<expr>
+Handling long lines
+-------------------
+
For most map headers, you can split long lines by ending the line that will be
continued on the next line with \ as:
@@ -1040,6 +1040,39 @@ ITEM: potion of\
Crawl will see "potion ofhealing", not "potion of healing".
+Assigning multiple glyphs at once
+---------------------------------
+
+Declarations that modify glyphs allow multiple glyphs to be assigned
+simultaneously as a convenience. For example, the following declaration will
+assign floor_orc as the tile to be used for all up stair cases and floor:
+
+ FTILE: .[{( = floor_orc
+
+This case is identical to the longer syntax:
+
+ FTILE: . = floor_orc
+ FTILE: [ = floor_orc
+ FTILE: { = floor_orc
+ FTILE: ( = floor_orc
+
+Using : instead of = while assigning glyphs will assign the same value to all
+glyphs. In the following example, the glyphs A, B, and C will either all
+contain gold or all contain nothing:
+
+ KITEM: ABC : gold / nothing
+
+Note: The number of items assigned in an NSUBST expression applies to the
+entire group of glyphs being assigned. For example:
+
+ # Among all A, B, and C glyphs, make one a floor and the rest walls.
+ NSUBST: ABC = 1:. / *:x
+
+ # Make one A glyph floor, one B glyph floor, and one C glyph floor.
+ # Make the rest of the A, B, and C glyphs walls.
+ NSUBST: A = 1:. / *:x
+ NSUBST: B = 1:. / *:x
+ NSUBST: C = 1:. / *:x
E. Conditionalising levels
=============================
diff --git a/crawl-ref/source/dat/entry.des b/crawl-ref/source/dat/entry.des
index 326afcdcce..f450e26af3 100644
--- a/crawl-ref/source/dat/entry.des
+++ b/crawl-ref/source/dat/entry.des
@@ -51,10 +51,7 @@ KFEAT: T = net trap
# ("Ack! Now I'm trapped too! Help!") so I coded it in. ^.^
NSUBST: M = 2=E / *=M E:2
KFEAT: E = teleport trap
-KFEAT: M = shallow_water
-KFEAT: N = shallow_water
-KFEAT: O = shallow_water
-KFEAT: Q = shallow_water
+KFEAT: MNOQ = shallow_water
SHUFFLE: M/N/O/P/Q
SUBST: P = MNO
#
@@ -3507,13 +3504,13 @@ MONS: w:30 nothing / ooze / w:2 jelly / giant cockroach / w:2 worm / \
# There is a very slight chance that a jelly or an intelligent monster
# (hobgoblin) might spawn inside near the door. This is okay; added an exit.
ORIENT: float
-FTILE: 1234+ABCDEabcde = floor_dirt
+FTILE: 1234+ABCDEabcdem = floor_dirt
SHUFFLE: abcde / fghij
# Don't let auto-explore open the door and unleash the caged monsters.
KPROP: + = force_exclude
SUBST: f=A, g=B, h=C, i=D, j=E
-SUBST: a=mx, b=mx, c=mx, d=mx, e=mx
-SUBST: A:mx, B:mx, C:mx, D:mx, E:mx
+SUBST: abcde = mx
+SUBST: ABCDE : mx
SUBST: ===++
SHUFFLE: xc, 123
KMASK: T = no_monster_gen
@@ -4898,8 +4895,7 @@ TAGS: entry no_rotate no_pool_fixup
ORIENT: northwest
MONS: plant
FTILE: .t1 = floor_lair
-KMASK: w = no_monster_gen
-KMASK: W = no_monster_gen
+KMASK: Ww = no_monster_gen
MAP
ttttttttttttttttttttttttttttttttttttttttttt
tttttttttttt1ttttttwwtttttttttttttttttttttt
@@ -4945,7 +4941,7 @@ SUBST: ' = .
inside = '.'
})
if crawl.coinflip() then
- map_smear({iterations=20, smear='x', onto='.W', boxy = true})
+ map_smear({iterations=20, smear='x', onto='.W', boxy=true})
end
}}
SUBST: W:xw
diff --git a/crawl-ref/source/dat/mini.des b/crawl-ref/source/dat/mini.des
index c033235a67..dd45054201 100644
--- a/crawl-ref/source/dat/mini.des
+++ b/crawl-ref/source/dat/mini.des
@@ -906,14 +906,8 @@ ENDMAP
#
NAME: minivault_13
SHUFFLE: AB, CD, EH/FG
-KFEAT: A = any trap
-KFEAT: C = any trap
-KFEAT: E = any trap
-KFEAT: H = any trap
-KITEM: A = gold / nothing
-KITEM: B = gold / nothing
-KITEM: C = gold / nothing
-KITEM: D = gold / nothing
+KFEAT: ACEH = any trap
+KITEM: ABCD = gold / nothing
SUBST: F = G:100 F:1
KMONS: F = orange crystal statue / silver statue / ice statue
MAP
diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc
index 960531bc8c..e05d021a99 100644
--- a/crawl-ref/source/mapdef.cc
+++ b/crawl-ref/source/mapdef.cc
@@ -423,11 +423,11 @@ std::string map_lines::add_feature_marker(const std::string &s)
{
std::string key, arg;
int sep = 0;
- std::string err = mapdef_split_key_item(s, &key, &sep, &arg);
+ std::string err = mapdef_split_key_item(s, &key, &sep, &arg, -1);
if (!err.empty())
return (err);
- map_marker_spec spec(key[0], arg);
+ map_marker_spec spec(key, arg);
spec.apply_transform(*this);
return ("");
@@ -436,7 +436,7 @@ std::string map_lines::add_feature_marker(const std::string &s)
std::string map_lines::add_lua_marker(const std::string &key,
const lua_datum &function)
{
- map_marker_spec spec(key[0], function);
+ map_marker_spec spec(key, function);
spec.apply_transform(*this);
return ("");
}
@@ -628,7 +628,7 @@ std::string map_lines::add_colour(const std::string &sub)
std::string key;
std::string substitute;
- std::string err = mapdef_split_key_item(sub, &key, &sep, &substitute);
+ std::string err = mapdef_split_key_item(sub, &key, &sep, &substitute, -1);
if (!err.empty())
return (err);
@@ -637,7 +637,7 @@ std::string map_lines::add_colour(const std::string &sub)
if (!err.empty())
return (err);
- colour_spec spec(key[0], sep == ':', colours);
+ colour_spec spec(key, sep == ':', colours);
overlay_colours(spec);
return ("");
@@ -664,7 +664,7 @@ std::string map_lines::add_fproperty(const std::string &sub)
std::string key;
std::string substitute;
- std::string err = mapdef_split_key_item(sub, &key, &sep, &substitute);
+ std::string err = mapdef_split_key_item(sub, &key, &sep, &substitute, -1);
if (!err.empty())
return (err);
@@ -673,7 +673,7 @@ std::string map_lines::add_fproperty(const std::string &sub)
if (!err.empty())
return (err);
- fprop_spec spec(key[0], sep == ':', fprops);
+ fprop_spec spec(key, sep == ':', fprops);
overlay_fprops(spec);
return ("");
@@ -690,7 +690,7 @@ std::string map_lines::add_subst(const std::string &sub)
std::string key;
std::string substitute;
- std::string err = mapdef_split_key_item(sub, &key, &sep, &substitute);
+ std::string err = mapdef_split_key_item(sub, &key, &sep, &substitute, -1);
if (!err.empty())
return (err);
@@ -699,7 +699,7 @@ std::string map_lines::add_subst(const std::string &sub)
if (!err.empty())
return (err);
- subst_spec spec(key[0], sep == ':', repl);
+ subst_spec spec(key, sep == ':', repl);
subst(spec);
return ("");
@@ -713,8 +713,8 @@ std::string map_lines::parse_nsubst_spec(const std::string &s,
std::string err = mapdef_split_key_item(s, &key, &sep, &arg, -1);
if (!err.empty())
return err;
- const int keyval = key == "*"? -1 : atoi(key.c_str());
- if (!keyval)
+ const int count = key == "*"? -1 : atoi(key.c_str());
+ if (!count)
return make_stringf("Illegal spec: %s", s.c_str());
glyph_replacements_t repl;
@@ -722,7 +722,7 @@ std::string map_lines::parse_nsubst_spec(const std::string &s,
if (!err.empty())
return (err);
- spec = subst_spec(keyval, sep == ':', repl);
+ spec = subst_spec(count, sep == ':', repl);
return ("");
}
@@ -733,7 +733,7 @@ std::string map_lines::add_nsubst(const std::string &s)
int sep;
std::string key, arg;
- std::string err = mapdef_split_key_item(s, &key, &sep, &arg);
+ std::string err = mapdef_split_key_item(s, &key, &sep, &arg, -1);
if (!err.empty())
return (err);
@@ -757,7 +757,7 @@ std::string map_lines::add_nsubst(const std::string &s)
substs.push_back(spec);
}
- nsubst_spec spec(key[0], substs);
+ nsubst_spec spec(key, substs);
nsubst(spec);
return ("");
@@ -903,12 +903,13 @@ void map_lines::clear()
void map_lines::subst(std::string &s, subst_spec &spec)
{
std::string::size_type pos = 0;
- while ((pos = s.find(spec.key(), pos)) != std::string::npos)
+ while ((pos = s.find_first_of(spec.key, pos)) != std::string::npos)
s[pos++] = spec.value();
}
void map_lines::subst(subst_spec &spec)
{
+ ASSERT(!spec.key.empty());
for (int y = 0, ysize = lines.size(); y < ysize; ++y)
subst(lines[y], spec);
}
@@ -921,7 +922,7 @@ void map_lines::overlay_colours(colour_spec &spec)
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)
+ while ((pos = lines[y].find_first_of(spec.key, pos)) != std::string::npos)
{
(*overlay)(pos, y).colour = spec.get_colour();
++pos;
@@ -937,7 +938,7 @@ void map_lines::overlay_fprops(fprop_spec &spec)
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)
+ while ((pos = lines[y].find_first_of(spec.key, pos)) != std::string::npos)
{
(*overlay)(pos, y).property |= spec.get_property();
++pos;
@@ -972,7 +973,7 @@ void map_lines::nsubst(nsubst_spec &spec)
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)
+ while ((pos = lines[y].find_first_of(spec.key, pos)) != std::string::npos)
positions.push_back(coord_def(pos++, y));
}
std::random_shuffle(positions.begin(), positions.end(), random2);
@@ -982,7 +983,7 @@ void map_lines::nsubst(nsubst_spec &spec)
for (int i = 0, vsize = spec.specs.size();
i < vsize && pcount < psize; ++i)
{
- const int nsubsts = spec.specs[i].key();
+ const int nsubsts = spec.specs[i].count;
pcount += apply_nsubst(positions, pcount, nsubsts, spec.specs[i]);
}
}
@@ -1212,6 +1213,21 @@ std::vector<coord_def> map_lines::find_glyph(int gly) const
return (points);
}
+std::vector<coord_def> map_lines::find_glyph(const std::string &glyphs) const
+{
+ std::vector<coord_def> points;
+ for (int y = height() - 1; y >= 0; --y)
+ {
+ for (int x = width() - 1; x >= 0; --x)
+ {
+ const coord_def c(x, y);
+ if (glyphs.find((*this)(c)) != std::string::npos)
+ points.push_back(c);
+ }
+ }
+ return (points);
+}
+
coord_def map_lines::find_first_glyph(int gly) const
{
for (int y = 0, h = height(); y < h; ++y)
@@ -2087,38 +2103,55 @@ keyed_mapspec *map_def::mapspec_for_key(int key)
std::string map_def::add_key_field(
const std::string &s,
- std::string (keyed_mapspec::*set_field)(const std::string &s, bool fixed))
+ std::string (keyed_mapspec::*set_field)(const std::string &s, bool fixed),
+ void (keyed_mapspec::*copy_field)(keyed_mapspec &spec))
{
int separator = 0;
std::string key, arg;
- std::string err = mapdef_split_key_item(s, &key, &separator, &arg);
+ std::string err = mapdef_split_key_item(s, &key, &separator, &arg, -1);
if (!err.empty())
return (err);
- keyed_mapspec &km = keyspecs[key[0]];
- km.key_glyph = key[0];
- return ((km.*set_field)(arg, separator == ':'));
+ keyed_mapspec &kmbase = keyspecs[key[0]];
+ kmbase.key_glyph = key[0];
+ err = ((kmbase.*set_field)(arg, separator == ':'));
+ if (!err.empty())
+ return (err);
+
+ size_t len = key.length();
+ for (size_t i = 1; i < len; i++)
+ {
+ keyed_mapspec &km = keyspecs[key[i]];
+ km.key_glyph = key[i];
+ ((km.*copy_field)(kmbase));
+ }
+
+ return (err);
}
std::string map_def::add_key_item(const std::string &s)
{
- return add_key_field(s, &keyed_mapspec::set_item);
+ return add_key_field(s, &keyed_mapspec::set_item,
+ &keyed_mapspec::copy_item);
}
std::string map_def::add_key_feat(const std::string &s)
{
- return add_key_field(s, &keyed_mapspec::set_feat);
+ return add_key_field(s, &keyed_mapspec::set_feat,
+ &keyed_mapspec::copy_feat);
}
std::string map_def::add_key_mons(const std::string &s)
{
- return add_key_field(s, &keyed_mapspec::set_mons);
+ return add_key_field(s, &keyed_mapspec::set_mons,
+ &keyed_mapspec::copy_mons);
}
std::string map_def::add_key_mask(const std::string &s)
{
- return add_key_field(s, &keyed_mapspec::set_mask);
+ return add_key_field(s, &keyed_mapspec::set_mask,
+ &keyed_mapspec::copy_mask);
}
///////////////////////////////////////////////////////////////////
@@ -2413,7 +2446,10 @@ std::string mons_list::add_mons(const std::string &s, bool fix)
return (error);
if (fix)
+ {
slotmons.fix_slot = true;
+ pick_monster(slotmons);
+ }
mons.push_back( slotmons );
@@ -2723,7 +2759,11 @@ std::string item_list::add_item(const std::string &spec, bool fix)
if (error.empty())
{
if (fix)
+ {
sp.fix_slot = true;
+ pick_item(sp);
+ }
+
items.push_back(sp);
}
@@ -3164,8 +3204,13 @@ item_list::item_spec_slot item_list::parse_item_spec(std::string spec)
/////////////////////////////////////////////////////////////////////////
// subst_spec
-subst_spec::subst_spec(int torepl, bool dofix, const glyph_replacements_t &g)
- : foo(torepl), fix(dofix), frozen_value(0), repl(g)
+subst_spec::subst_spec(std::string _k, bool _f, const glyph_replacements_t &g)
+ : key(_k), count(-1), fix(_f), frozen_value(0), repl(g)
+{
+}
+
+subst_spec::subst_spec(int _count, bool dofix, const glyph_replacements_t &g)
+ : key(""), count(_count), fix(dofix), frozen_value(0), repl(g)
{
}
@@ -3189,7 +3234,7 @@ int subst_spec::value()
//////////////////////////////////////////////////////////////////////////
// nsubst_spec
-nsubst_spec::nsubst_spec(int _key, const std::vector<subst_spec> &_specs)
+nsubst_spec::nsubst_spec(std::string _key, const std::vector<subst_spec> &_specs)
: key(_key), specs(_specs)
{
}
@@ -3329,9 +3374,19 @@ std::string keyed_mapspec::set_feat(const std::string &s, bool fix)
err.clear();
parse_features(s);
feat.fix_slot = fix;
+
+ // Fix this feature.
+ if (fix)
+ get_feat();
+
return (err);
}
+void keyed_mapspec::copy_feat(keyed_mapspec &spec)
+{
+ feat = spec.feat;
+}
+
void keyed_mapspec::parse_features(const std::string &s)
{
feat.feats.clear();
@@ -3433,6 +3488,7 @@ std::string keyed_mapspec::set_mons(const std::string &s, bool fix)
if (!error.empty())
return (error);
}
+
return ("");
}
@@ -3449,6 +3505,7 @@ std::string keyed_mapspec::set_item(const std::string &s, bool fix)
if (!err.empty())
return (err);
}
+
return (err);
}
@@ -3482,6 +3539,21 @@ std::string keyed_mapspec::set_mask(const std::string &s, bool garbage)
return (err);
}
+void keyed_mapspec::copy_mons(keyed_mapspec &spec)
+{
+ mons = spec.mons;
+}
+
+void keyed_mapspec::copy_item(keyed_mapspec &spec)
+{
+ item = spec.item;
+}
+
+void keyed_mapspec::copy_mask(keyed_mapspec &spec)
+{
+ map_mask = spec.map_mask;
+}
+
feature_spec keyed_mapspec::get_feat()
{
return feat.get_feat('.');
diff --git a/crawl-ref/source/mapdef.h b/crawl-ref/source/mapdef.h
index 41c5bc3c33..a02f89393e 100644
--- a/crawl-ref/source/mapdef.h
+++ b/crawl-ref/source/mapdef.h
@@ -105,19 +105,19 @@ class map_lines;
class subst_spec
{
public:
- subst_spec(int torepl, bool fix, const glyph_replacements_t &repls);
- subst_spec() : foo(0), fix(false), frozen_value(0), repl() { }
-
- int key() const
- {
- return (foo);
- }
+ subst_spec(std::string torepl, bool fix, const glyph_replacements_t &repls);
+ subst_spec(int count, bool fix, const glyph_replacements_t &repls);
+ subst_spec() : key(""), count(-1), fix(false), frozen_value(0), repl() { }
int value();
-private:
- int foo; // The thing to replace.
- bool fix; // If true, the first replacement fixes the value.
+public:
+ std::string key;
+ // If this is part of an nsubst spec, how many to replace.
+ // -1 corresponds to all (i.e. '*')
+ int count;
+
+ bool fix;
int frozen_value;
glyph_replacements_t repl;
@@ -126,9 +126,9 @@ private:
class nsubst_spec
{
public:
- nsubst_spec(int key, const std::vector<subst_spec> &specs);
+ nsubst_spec(std::string key, const std::vector<subst_spec> &specs);
public:
- int key;
+ std::string key;
std::vector<subst_spec> specs;
};
@@ -141,7 +141,7 @@ public:
class colour_spec
{
public:
- colour_spec(int _key, bool _fix, const map_colour_list &clist)
+ colour_spec(std::string _key, bool _fix, const map_colour_list &clist)
: key(_key), fix(_fix), fixed_colour(BLACK), colours(clist)
{
}
@@ -149,7 +149,7 @@ public:
int get_colour();
public:
- int key;
+ std::string key;
bool fix;
int fixed_colour;
map_colour_list colours;
@@ -164,7 +164,7 @@ public:
class fprop_spec
{
public:
- fprop_spec(int _key, bool _fix, const map_fprop_list &flist)
+ fprop_spec(std::string _key, bool _fix, const map_fprop_list &flist)
: key(_key), fix(_fix), fixed_prop(FPROP_NONE), fprops(flist)
{
}
@@ -172,7 +172,7 @@ public:
int get_property();
public:
- int key;
+ std::string key;
bool fix;
int fixed_prop;
map_fprop_list fprops;
@@ -180,7 +180,7 @@ public:
#ifdef USE_TILE
typedef std::pair<int, int> map_weighted_tile;
-class map_tile_list : public std::vector<map_weighted_colour>
+class map_tile_list : public std::vector<map_weighted_tile>
{
public:
bool parse(const std::string &s, int weight);
@@ -210,16 +210,16 @@ public:
class map_marker_spec
{
public:
- int key;
+ std::string key;
std::string marker;
// Special handling for Lua markers:
std::auto_ptr<lua_datum> lua_fn;
- map_marker_spec(int _key, const std::string &mark)
+ map_marker_spec(std::string _key, const std::string &mark)
: key(_key), marker(mark), lua_fn() { }
- map_marker_spec(int _key, const lua_datum &fn)
+ map_marker_spec(std::string _key, const lua_datum &fn)
: key(_key), marker(), lua_fn(new lua_datum(fn)) { }
std::string apply_transform(map_lines &map);
@@ -253,6 +253,7 @@ public:
std::string add_rocktile(const std::string &s);
#endif
+ std::vector<coord_def> find_glyph(const std::string &glyphs) const;
std::vector<coord_def> find_glyph(int glyph) const;
coord_def find_first_glyph(int glyph) const;
coord_def find_first_glyph(const std::string &glyphs) const;
@@ -576,11 +577,21 @@ public:
public:
keyed_mapspec();
+ // Parse the string and set the given entry. If fix is true,
+ // then whatever is selected for the first feature will be
+ // permanently fixed.
std::string set_feat(const std::string &s, bool fix);
std::string set_mons(const std::string &s, bool fix);
std::string set_item(const std::string &s, bool fix);
std::string set_mask(const std::string &s, bool garbage);
+ // Copy from the given mapspec. If that entry is fixed,
+ // it should be pre-selected prior to the copy.
+ void copy_feat(keyed_mapspec &spec);
+ void copy_mons(keyed_mapspec &spec);
+ void copy_item(keyed_mapspec &spec);
+ void copy_mask(keyed_mapspec &spec);
+
feature_spec get_feat();
mons_list &get_monsters();
item_list &get_items();
@@ -805,7 +816,8 @@ private:
std::string add_key_field(
const std::string &s,
std::string (keyed_mapspec::*set_field)(
- const std::string &s, bool fixed));
+ const std::string &s, bool fixed),
+ void (keyed_mapspec::*copy_field)(keyed_mapspec &spec));
};
const int CHANCE_ROLL = 10000;