diff options
author | dshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573> | 2007-05-09 19:52:59 +0000 |
---|---|---|
committer | dshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573> | 2007-05-09 19:52:59 +0000 |
commit | d69688f0d70ebd684181678a77ca10f800258cfe (patch) | |
tree | 19b8b9fdd4c8194ea65d0729cdf44adf31ee7e60 /crawl-ref | |
parent | b31a9edb3090aa8dac6dc1fc70c5e241c3019642 (diff) | |
download | crawl-ref-d69688f0d70ebd684181678a77ca10f800258cfe.tar.gz crawl-ref-d69688f0d70ebd684181678a77ca10f800258cfe.zip |
Added Lemuel's mines minivaults.
Extended map DEPTH: attribute to support branch specifiers and negated depth
specifiers.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@1442 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref')
-rw-r--r-- | crawl-ref/source/branch.cc | 10 | ||||
-rw-r--r-- | crawl-ref/source/branch.h | 2 | ||||
-rw-r--r-- | crawl-ref/source/dat/vaults.des | 151 | ||||
-rw-r--r-- | crawl-ref/source/dungeon.cc | 48 | ||||
-rw-r--r-- | crawl-ref/source/hiscores.cc | 12 | ||||
-rw-r--r-- | crawl-ref/source/makefile.unix | 2 | ||||
-rw-r--r-- | crawl-ref/source/mapdef.cc | 116 | ||||
-rw-r--r-- | crawl-ref/source/mapdef.h | 37 | ||||
-rw-r--r-- | crawl-ref/source/maps.cc | 14 | ||||
-rw-r--r-- | crawl-ref/source/maps.h | 2 | ||||
-rw-r--r-- | crawl-ref/source/misc.cc | 4 | ||||
-rw-r--r-- | crawl-ref/source/misc.h | 8 | ||||
-rw-r--r-- | crawl-ref/source/util/levcomp.cc | 5 | ||||
-rw-r--r-- | crawl-ref/source/util/levcomp.h | 2 | ||||
-rw-r--r-- | crawl-ref/source/util/levcomp.lpp | 4 | ||||
-rw-r--r-- | crawl-ref/source/util/levcomp.ypp | 91 |
16 files changed, 410 insertions, 98 deletions
diff --git a/crawl-ref/source/branch.cc b/crawl-ref/source/branch.cc index 298431f866..3f81d87d32 100644 --- a/crawl-ref/source/branch.cc +++ b/crawl-ref/source/branch.cc @@ -12,6 +12,16 @@ Branch& your_branch() return branches[static_cast<int>(you.where_are_you)]; } +branch_type str_to_branch(const std::string &branch, branch_type err) +{ + for (int i = 0; i < NUM_BRANCHES; ++i) + { + if (branches[i].abbrevname && branches[i].abbrevname == branch) + return (static_cast<branch_type>(i)); + } + return (err); +} + Branch branches[] = { { BRANCH_MAIN_DUNGEON, BRANCH_MAIN_DUNGEON, 27, -1, diff --git a/crawl-ref/source/branch.h b/crawl-ref/source/branch.h index d1e3ca7c7c..009bb89bca 100644 --- a/crawl-ref/source/branch.h +++ b/crawl-ref/source/branch.h @@ -39,5 +39,7 @@ struct Branch extern Branch branches[]; Branch& your_branch(); +branch_type str_to_branch(const std::string &branch, + branch_type err = NUM_BRANCHES); #endif diff --git a/crawl-ref/source/dat/vaults.des b/crawl-ref/source/dat/vaults.des index 506770c6db..c53d0bb780 100644 --- a/crawl-ref/source/dat/vaults.des +++ b/crawl-ref/source/dat/vaults.des @@ -1282,7 +1282,7 @@ ENDMAP # attribute makes the map a normal vault, and mayhem can result. # Default depth for minivaults. -default-depth: 8-27 +default-depth: 8-27, !Orc, !Lair ############################################################################## # Minivault balancer @@ -1299,23 +1299,25 @@ ENDMAP # Greed's colour NAME: david_greed -DEPTH: 10-26 +DEPTH: 10-26, !Orc, !Lair ITEM: nothing / any good_item MONS: silver statue / orange crystal statue / ice statue SHUFFLE: d| MAP -xxxxxxxxx -xbbbbbbbx -xb1...1bx -xb.....bx -xb.....bx -xbb.|.bbx -xxb.d.bxx -xxb...bxx -xxb...bxx -xxb.*.bxx -xxb...bxx -xxx@I@xxx +........... +.xxxxxxxxx. +.xbbbbbbbx. +.xb1...1bx. +.xb.....bx. +.xb.....bx. +.xbb.|.bbx. +.xxb.d.bxx. +.xxb...bxx. +.xxb...bxx. +.xxb.*.bxx. +.xxb...bxx. +.xxx@I@xxx. +........... ENDMAP ############################################################################## @@ -2202,3 +2204,124 @@ MAP .xxxxxxxx=x. ............ ENDMAP + +############################################################################ +# Minivaults specific to particular branches +############################################################################ +# Orcish mines minivaults: + +default-depth: Orc:* + +################################## +# Dummy Orc minivault balancer. +# +NAME: mines_dummy +TAGS: dummy +CHANCE: 100 +MAP +x +ENDMAP + +################################### +# minvault intended for Orc Mines +# pond with fungi +NAME: mines1_lemuel +MONS: fungus, wandering mushroom +SUBST: 1 = . 1 2:4 +SUBST: ? : w.. +SUBST: ! : ww. +MAP +..1...?..... +....1???1... +..1...??ww1. +....1wwwwww. +.11wwwwwwww. +..www!!wwww. +..ww!!www1.. +..1ww!ww11.. +1..1w!!w1... +....!!1..... +.1...1!.1... +...........1 +ENDMAP + +################################### +# minvault intended for Orc Mines +# hidden treasure chamber +NAME: mines2_lemuel +SUBST: ? = x. +MAP +.......... +..?x=x?... +.?xx-xx?.. +?xx$$$xx?. +?xx$$$xx?. +.?xxxxx?.. +...???.... +ENDMAP + +################################### +# minvault intended for Orc Mines +# treasure chamber with oklob pant +NAME: mines3_lemuel +SUBST: ? = +=. +SUBST: ! = x. +SUBST: $ = $:30 * +MONS: oklob plant +MAP +.....!.!...... +....!x?x!..... +....!x.xx!.... +...!xx..xx!... +...!xxx..xx!.. +....!xxx.1x!.. +....!xxxx.x!.. +...!xxxxx.xx!. +..!xx$$x..xxx. +.!!xx$$?.xxxx. +.!xxx$$xxxx!.. +..!xxxxxxx!... +.............. +ENDMAP + +################################### +# minvault intended for Orc Mines +# mage tower -- either orc with assistants, or ogre with guards +NAME: mines4_lemuel +SUBST: ? = += +SUBST: d = $d +SUBST: I = IG +SHUFFLE: 112/334 +MONS: orc sorcerer,orc/orc wizard,ogre-mage,ogre/nothing +ITEM: any book +MAP +............... +...xxxx?xxxx... +..xx2.....2xx.. +.xx.2xxxxx2.xx. +.x..xxd1dxx..x. +.x.Ix$$G$$xI.x. +.x..xx222xx..x. +.xx.2xx?xx2.xx. +..xx..2.2..xx.. +...xxxxxxxxx... +............... +ENDMAP + +################################### +# minvault intended for Orc Mines +# warg stables, with goblin stableboy +NAME: mines5_lemuel +SUBST: ?: wx +MONS: warg/wolf,goblin +MAP +........... +.x???????x. +.xwwwwwwwx. +.xwwwwwwwx. +.x1.1.1.1x. +.x.1.1.1.x. +.x1.2...1x. +.xxxx+xxxx. +........... +ENDMAP diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 46fb3b6c79..c2b3c8aebd 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -177,6 +177,7 @@ static dgn_region_list no_monster_zones; static dgn_region_list no_item_zones; static dgn_region_list no_pool_fixup_zones; static dgn_region_list no_door_fixup_zones; +static int minivault_chance = 3; static std::vector<vault_placement> level_vaults; @@ -341,6 +342,7 @@ static void reset_level() no_item_zones.clear(); no_pool_fixup_zones.clear(); no_door_fixup_zones.clear(); + minivault_chance = 3; // blank level with DNGN_ROCK_WALL make_box(0, 0, GXM - 1, GYM - 1, DNGN_ROCK_WALL, DNGN_ROCK_WALL); @@ -1177,8 +1179,18 @@ static void place_special_minivaults(int level_number, int level_type) if (level_type != LEVEL_DUNGEON) return; - int chance = level_number == 0? 50 : 100; std::set<int> used; + if (minivault_chance && one_chance_in(minivault_chance)) + { + const int vault = random_map_for_depth(level_id::current(), true); + if (vault != -1) + { + build_minivaults(level_number, vault); + used.insert(vault); + } + } + + int chance = level_number == 0? 50 : 100; while (chance && random2(100) < chance) { const int vault = random_map_for_dlevel(level_number, true); @@ -1216,7 +1228,7 @@ static builder_rc_type builder_normal(int level_number, char level_type, if (vault == -1 && player_in_branch( BRANCH_MAIN_DUNGEON ) && one_chance_in(9)) - vault = random_map_for_depth(level_number); + vault = random_map_for_depth(level_id::current()); if (vault != -1) { @@ -1257,14 +1269,7 @@ static builder_rc_type builder_normal(int level_number, char level_type, if (level_number > 2 && level_number < 23 && one_chance_in(3)) { plan_main(level_number, 0); - - if (one_chance_in(3)) - { - int mvault = random_map_for_depth(level_number, true); - if (mvault != -1) - build_minivaults(level_number, mvault); - } - + minivault_chance = 3; return BUILD_SKIP; } @@ -1276,17 +1281,7 @@ static builder_rc_type builder_normal(int level_number, char level_type, { // sometimes roguey_levels generate a special room roguey_level(level_number, sr); - - if (player_in_branch( BRANCH_MAIN_DUNGEON ) - && one_chance_in(4)) - { - int mvault = random_map_for_depth(level_number, true); - if (mvault != -1) - { - build_minivaults(level_number, mvault); - return BUILD_SKIP; - } - } + minivault_chance = 4; } else { @@ -1413,17 +1408,6 @@ static void builder_extras( int level_number, int level_type ) if (level_number >= 11 && level_number <= 23 && one_chance_in(15)) place_specific_stair(DNGN_ENTER_LABYRINTH); - if (player_in_branch( BRANCH_MAIN_DUNGEON ) - && one_chance_in(3)) - { - int mvault = random_map_for_depth(level_number, true); - if (mvault != -1) - { - build_minivaults(level_number, mvault); - return; - } - } - if (level_number > 6 && one_chance_in(10)) { many_pools( level_number < 11 || coinflip() ? diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc index 50e697b100..30f1928da9 100644 --- a/crawl-ref/source/hiscores.cc +++ b/crawl-ref/source/hiscores.cc @@ -631,16 +631,6 @@ static const char *short_branch_name(int branch) return (""); } -static branch_type str_to_branch(const std::string &branch) -{ - for (int i = 0; i < NUM_BRANCHES; ++i) - { - if (branches[i].abbrevname && branches[i].abbrevname == branch) - return (static_cast<branch_type>(i)); - } - return (BRANCH_MAIN_DUNGEON); -} - static const char *level_type_names[] = { "D", "Lab", "Abyss", "Pan" @@ -691,7 +681,7 @@ void scorefile_entry::init_with_fields() death_type = str_to_kill_method(fields->str_field("ktyp")); death_source_name = fields->str_field("killer"); auxkilldata = fields->str_field("kaux"); - branch = str_to_branch(fields->str_field("br")); + branch = str_to_branch(fields->str_field("br"), BRANCH_MAIN_DUNGEON); dlvl = fields->int_field("lvl"); level_type = str_to_level_area_type(fields->str_field("ltyp")); diff --git a/crawl-ref/source/makefile.unix b/crawl-ref/source/makefile.unix index b0e2c1c27a..f67953792c 100644 --- a/crawl-ref/source/makefile.unix +++ b/crawl-ref/source/makefile.unix @@ -161,7 +161,7 @@ prebuildyacc: $(UTIL)levcomp.tab.cc $(UTIL)levcomp.tab.h $(UTIL)levcomp.lex.cc $(UTIL)levcomp.tab.cc: $(UTIL)levcomp.ypp cd $(UTIL) && $(YACC) -d -b levcomp levcomp.ypp \ - && mv $(YTABC) levcomp.tab.cc + && mv $(YTABC) levcomp.tab.cc || false $(UTIL)levcomp.lex.cc: $(UTIL)levcomp.lpp cd $(UTIL) && $(LEX) -olevcomp.lex.cc levcomp.lpp diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc index 3cf3ad9b41..2420d3ba9e 100644 --- a/crawl-ref/source/mapdef.cc +++ b/crawl-ref/source/mapdef.cc @@ -3,6 +3,7 @@ #include <cctype> #include "AppHdr.h" +#include "branch.h" #include "describe.h" #include "direct.h" #include "invent.h" @@ -122,17 +123,75 @@ static std::string split_key_item(const std::string &s, // level_range // -level_range::level_range(int s, int d) - : shallowest(), deepest() +level_range::level_range(branch_type br, int s, int d) + : branch(br), shallowest(), deepest(), deny(false) { set(s, d); } +level_range::level_range(const raw_range &r) + : branch(r.branch), shallowest(r.shallowest), deepest(r.deepest), + deny(r.deny) +{ +} + +std::string level_range::str_depth_range() const +{ + if (shallowest == -1) + return (":??"); + + if (shallowest == 1 && deepest >= branches[branch].depth) + return (""); + + if (shallowest == deepest) + return make_stringf(":%d", shallowest); + + return make_stringf(":%d-%d", shallowest, deepest); +} + +std::string level_range::describe() const +{ + return make_stringf("%s%s%s", + deny? "!" : "", + branch == NUM_BRANCHES? "Any" : + branches[branch].abbrevname, + str_depth_range().c_str()); +} + +level_range::operator raw_range () const +{ + raw_range r; + r.branch = branch; + r.shallowest = shallowest; + r.deepest = deepest; + r.deny = deny; + return (r); +} + +void level_range::set(const std::string &br, int s, int d) + throw (std::string) +{ + if (br == "any" || br == "Any") + branch = NUM_BRANCHES; + else + { + if ((branch = str_to_branch(br)) == NUM_BRANCHES) + throw make_stringf("Unknown branch: '%s'", br.c_str()); + } + + shallowest = s; + deepest = d; + + if (deepest < shallowest) + throw make_stringf("Level-range %s:%d-%d is malformed", + br.c_str(), s, d); +} + void level_range::set(int s, int d) { shallowest = s; deepest = d; - if (deepest == -1) + if (deepest == -1 || deepest < shallowest) deepest = shallowest; } @@ -141,7 +200,16 @@ void level_range::reset() deepest = shallowest = -1; } -bool level_range::contains(int x) const +bool level_range::matches(const level_id &lid) const +{ + if (branch == NUM_BRANCHES) + return (matches(absdungeon_depth(lid.branch, lid.depth))); + else + return (branch == lid.branch + && lid.depth >= shallowest && lid.depth <= deepest); +} + +bool level_range::matches(int x) const { // [ds] The level ranges used by the game are zero-based, adjust for that. ++x; @@ -559,7 +627,7 @@ void map_def::init() place.clear(); items.clear(); keyspecs.clear(); - depth.reset(); + depths.clear(); orient = MAP_NONE; // Base chance; this is not a percentage. @@ -573,6 +641,38 @@ void map_def::init() mons.clear(); } +bool map_def::is_usable_in(const level_id &lid) const +{ + bool any_matched = false; + for (int i = 0, size = depths.size(); i < size; ++i) + { + const level_range &lr = depths[i]; + if (lr.matches(lid)) + { + if (lr.deny) + return (false); + any_matched = true; + } + } + return (any_matched); +} + +void map_def::add_depth(const level_range &range) +{ + depths.push_back(range); +} + +void map_def::add_depths(depth_ranges::const_iterator s, + depth_ranges::const_iterator e) +{ + depths.insert(depths.end(), s, e); +} + +bool map_def::has_depth() const +{ + return (!depths.empty()); +} + bool map_def::is_minivault() const { return (orient == MAP_NONE); @@ -796,6 +896,12 @@ bool map_def::has_tag(const std::string &tagwanted) const && tags.find(" " + tagwanted + " ") != std::string::npos; } +bool map_def::has_tag_prefix(const std::string &prefix) const +{ + return !tags.empty() && !prefix.empty() + && tags.find(" " + prefix) != std::string::npos; +} + keyed_mapspec *map_def::mapspec_for_key(int key) { keyed_specs::iterator i = keyspecs.find(key); diff --git a/crawl-ref/source/mapdef.h b/crawl-ref/source/mapdef.h index ffb5cef40e..3d5866af96 100644 --- a/crawl-ref/source/mapdef.h +++ b/crawl-ref/source/mapdef.h @@ -24,20 +24,38 @@ enum map_flags MAPF_ROTATE = 0x40 // may be rotated }; -class level_range +struct raw_range +{ + branch_type branch; + int shallowest, deepest; + bool deny; +}; + +struct level_range { public: + branch_type branch; int shallowest, deepest; + bool deny; public: - level_range(int s = -1, int d = -1); + level_range(const raw_range &range); + level_range(branch_type br = BRANCH_MAIN_DUNGEON, int s = -1, int d = -1); void set(int s, int d = -1); + void set(const std::string &branch, int s, int d) throw (std::string); + void reset(); - bool contains(int depth) const; + bool matches(const level_id &) const; + bool matches(int depth) const; bool valid() const; int span() const; + + std::string describe() const; + std::string str_depth_range() const; + + operator raw_range () const; }; typedef std::pair<int,int> glyph_weighted_replacement_t; @@ -328,6 +346,8 @@ private: typedef std::map<int, keyed_mapspec> keyed_specs; +typedef std::vector<level_range> depth_ranges; + // Not providing a constructor to make life easy for C-style initialisation. class map_def { @@ -335,7 +355,8 @@ public: std::string name; std::string tags; std::string place; - level_range depth; + + depth_ranges depths; map_section_type orient; int chance; long flags; @@ -355,7 +376,14 @@ public: void resolve(); void fixup(); + bool is_usable_in(const level_id &lid) const; + keyed_mapspec *mapspec_for_key(int key); + + bool has_depth() const; + void add_depth(const level_range &depth); + void add_depths(depth_ranges::const_iterator s, + depth_ranges::const_iterator e); std::string add_key_item(const std::string &s); std::string add_key_mons(const std::string &s); @@ -369,6 +397,7 @@ public: bool is_minivault() const; bool has_tag(const std::string &tag) const; + bool has_tag_prefix(const std::string &tag) const; private: std::string add_key_field( diff --git a/crawl-ref/source/maps.cc b/crawl-ref/source/maps.cc index 98ecb5c25f..bc9c9acf27 100644 --- a/crawl-ref/source/maps.cc +++ b/crawl-ref/source/maps.cc @@ -283,19 +283,19 @@ int random_map_for_place(const std::string &place, bool want_minivault) return (mapindex); } -int random_map_for_depth(int depth, bool want_minivault) +int random_map_for_depth(const level_id &place, bool want_minivault) { int mapindex = -1; int rollsize = 0; for (unsigned i = 0, size = vdefs.size(); i < size; ++i) - if (vdefs[i].depth.contains(depth) + if (vdefs[i].is_minivault() == want_minivault + && vdefs[i].is_usable_in(place) // Tagged levels cannot be selected by depth. This is // the only thing preventing Pandemonium demon vaults from // showing up in the main dungeon. && !vdefs[i].has_tag("entry") - && !vdefs[i].has_tag("pan") - && vdefs[i].is_minivault() == want_minivault) + && !vdefs[i].has_tag("pan")) { rollsize += vdefs[i].chance; @@ -305,7 +305,7 @@ int random_map_for_depth(int depth, bool want_minivault) if (mapindex != -1 && vdefs[mapindex].has_tag("dummy")) mapindex = -1; - + return (mapindex); } @@ -319,8 +319,8 @@ int random_map_for_tag(const std::string &tag, for (unsigned i = 0, size = vdefs.size(); i < size; ++i) { if (vdefs[i].has_tag(tag) && vdefs[i].is_minivault() == want_minivault - && (!check_depth || !vdefs[i].depth.valid() - || vdefs[i].depth.contains(you.your_level))) + && (!check_depth || !vdefs[i].has_depth() + || vdefs[i].is_usable_in(level_id::current()))) { rollsize += vdefs[i].chance; diff --git a/crawl-ref/source/maps.h b/crawl-ref/source/maps.h index 82738abd5c..6b3ab76089 100644 --- a/crawl-ref/source/maps.h +++ b/crawl-ref/source/maps.h @@ -41,7 +41,7 @@ int vault_main(map_type vgrid, const map_def *map_by_index(int index); int random_map_for_place(const std::string &place, bool mini = false); -int random_map_for_depth(int depth, bool want_minivault = false); +int random_map_for_depth(const level_id &lid, bool want_minivault = false); int random_map_for_tag(const std::string &tag, bool want_minivault, bool check_depth = false); void add_parsed_map(const map_def &md); diff --git a/crawl-ref/source/misc.cc b/crawl-ref/source/misc.cc index a7a7887402..d8baa06295 100644 --- a/crawl-ref/source/misc.cc +++ b/crawl-ref/source/misc.cc @@ -2042,7 +2042,7 @@ std::string prep_branch_level_name() return prep_branch_level_name( get_packed_place() ); } -int absdungeon_depth(unsigned char branch, int subdepth) +int absdungeon_depth(branch_type branch, int subdepth) { if (branch >= BRANCH_VESTIBULE_OF_HELL && branch <= BRANCH_THE_PIT) return subdepth + 27; @@ -2058,7 +2058,7 @@ int absdungeon_depth(unsigned char branch, int subdepth) return subdepth; } -int subdungeon_depth(unsigned char branch, int depth) +int subdungeon_depth(branch_type branch, int depth) { return depth - absdungeon_depth(branch, 0); } diff --git a/crawl-ref/source/misc.h b/crawl-ref/source/misc.h index 59d1e5a2b8..6c82049174 100644 --- a/crawl-ref/source/misc.h +++ b/crawl-ref/source/misc.h @@ -182,14 +182,14 @@ std::string prep_branch_level_name(); // Get displayable depth in the current branch, given the absolute // depth. -int subdungeon_depth(unsigned char branch, int depth); +int subdungeon_depth(branch_type branch, int depth); + +// Get absolute depth given the displayable depth in the branch. +int absdungeon_depth(branch_type branch, int subdepth); // Get displayable depth in the current branch. int player_branch_depth(); -// Get absolute depth given the displayable depth in the branch. -int absdungeon_depth(unsigned char branch, int subdepth); - bool single_level_branch(branch_type branch); ////////////////////////////////////////////////////////////////////// diff --git a/crawl-ref/source/util/levcomp.cc b/crawl-ref/source/util/levcomp.cc index 5e0bb4cb64..af92a23bb6 100644 --- a/crawl-ref/source/util/levcomp.cc +++ b/crawl-ref/source/util/levcomp.cc @@ -1,10 +1,11 @@ #include "AppHdr.h" #include "levcomp.h" +#include <vector> std::string lc_desfile; map_def lc_map; level_range lc_range; -level_range lc_default_depth; +depth_ranges lc_default_depths; extern int yylineno; @@ -12,7 +13,7 @@ void reset_map_parser() { lc_map.init(); lc_range.reset(); - lc_default_depth.reset(); + lc_default_depths.clear(); yylineno = 1; } diff --git a/crawl-ref/source/util/levcomp.h b/crawl-ref/source/util/levcomp.h index 99f0495f90..c3bf3a73ea 100644 --- a/crawl-ref/source/util/levcomp.h +++ b/crawl-ref/source/util/levcomp.h @@ -6,7 +6,7 @@ extern map_def lc_map; extern level_range lc_range; -extern level_range lc_default_depth; +extern depth_ranges lc_default_depths; extern std::string lc_desfile; void reset_map_parser(); diff --git a/crawl-ref/source/util/levcomp.lpp b/crawl-ref/source/util/levcomp.lpp index 64d790017c..157d53b5bc 100644 --- a/crawl-ref/source/util/levcomp.lpp +++ b/crawl-ref/source/util/levcomp.lpp @@ -188,6 +188,10 @@ float return FLOAT; \" return QUOTE; +: return COLON; +\* return STAR; +! return NOT; + [a-zA-Z_][a-zA-Z_0-9]+ { settext(); return IDENTIFIER; diff --git a/crawl-ref/source/util/levcomp.ypp b/crawl-ref/source/util/levcomp.ypp index f917ad37e6..d62800845e 100644 --- a/crawl-ref/source/util/levcomp.ypp +++ b/crawl-ref/source/util/levcomp.ypp @@ -3,6 +3,7 @@ #include "AppHdr.h" #include "libutil.h" #include "levcomp.h" +#include "mapdef.h" #include "stuff.h" #include <map> @@ -34,12 +35,26 @@ void yyerror(const char *e) end(1); } +level_range set_range(const char *s, int start, int end) +{ + try + { + lc_range.set(s, start, end); + } + catch (const std::string &err) + { + yyerror(err.c_str()); + } + return (lc_range); +} + %} %union { int i; const char *text; + raw_range range; } %token <i> BRANCHDEF BRANCH DESC DEFAULT @@ -58,10 +73,11 @@ void yyerror(const char *e) %token <i> NO_HMIRROR NO_VMIRROR NO_ROTATE %token <i> PANDEMONIC -%token <i> DASH COMMA QUOTE OPAREN CPAREN +%token <i> DASH COMMA QUOTE OPAREN CPAREN COLON STAR NOT %token <i> INTEGER %type <i> orient_name flagname +%type <range> lev_range ext_range %token <text> STRING MAP_LINE MONSTER_NAME ITEM_INFO %token <text> IDENTIFIER @@ -72,20 +88,19 @@ file : definitions { } ; definitions : /* empty */ {} - | definition definitions {} + | definitions definition {} ; definition : def {} | level {} ; -def : defdepth +def : defdepth {} ; -defdepth : DEFAULT_DEPTH depth_range - { - lc_default_depth = lc_range; - } +defdepth : DEFAULT_DEPTH + { lc_default_depths.clear(); } + default_depth_ranges ; level : name metalines map_def metalines @@ -123,6 +138,10 @@ level : name metalines map_def metalines if (lc_map.map.height() == 0) yyerror("Must define map."); + if (!lc_map.has_depth() && !lc_default_depths.empty()) + lc_map.add_depths(lc_default_depths.begin(), + lc_default_depths.end()); + add_parsed_map( lc_map ); } ; @@ -130,7 +149,6 @@ level : name metalines map_def metalines name : NAME STRING { lc_map.init(); - lc_map.depth = lc_default_depth; lc_map.name = $2; map_load_info_t::const_iterator i = @@ -203,7 +221,7 @@ shuffle : SHUFFLE shuffle_specifiers {} ; shuffle_specifiers : shuffle_spec - | shuffle_spec COMMA shuffle_specifiers + | shuffle_specifiers COMMA shuffle_spec ; shuffle_spec : ITEM_INFO @@ -300,20 +318,65 @@ place : PLACE STRING ; depth : DEPTH {} - | DEPTH depth_range + | DEPTH extended_depth_ranges {} + ; + +default_depth_ranges : + ext_range + { + lc_default_depths.push_back($1); + } + + | default_depth_ranges COMMA ext_range + { + lc_default_depths.push_back($3); + } + ; + +extended_depth_ranges : + ext_range { - lc_map.depth = lc_range; + lc_map.add_depth($1); + } + + | extended_depth_ranges COMMA ext_range + { + lc_map.add_depth($3); } ; -depth_range : INTEGER DASH INTEGER +ext_range : lev_range { $$ = $1; } + | NOT lev_range { $$ = $2; $$.deny = true; } + ; + +lev_range : IDENTIFIER + { + $$ = set_range($1, 1, 100); + } + + | IDENTIFIER COLON STAR + { + $$ = set_range($1, 1, 100); + } + + | IDENTIFIER COLON INTEGER DASH INTEGER + { + $$ = set_range($1, $3, $5); + } + + | IDENTIFIER COLON INTEGER + { + $$ = set_range($1, $3, $3); + } + + | INTEGER DASH INTEGER { - lc_range.set($1, $3); + $$ = set_range("Any", $1, $3); } | INTEGER { - lc_range.set($1); + $$ = set_range("Any", $1, $1); } ; |