diff options
-rw-r--r-- | crawl-ref/docs/develop/level_design.txt | 43 | ||||
-rw-r--r-- | crawl-ref/source/dat/entry.des | 16 | ||||
-rw-r--r-- | crawl-ref/source/dat/mini.des | 10 | ||||
-rw-r--r-- | crawl-ref/source/mapdef.cc | 134 | ||||
-rw-r--r-- | crawl-ref/source/mapdef.h | 54 |
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; |