1 /**
2  * @defgroup mapdef Map Parsing
3  * @brief Parse .des files into map objects.
4  * @section DESCRIPTION
5  *
6  * mapdef.h:
7  * Header for map structures used by the level compiler.
8  *
9  * NOTE: When we refer to map, this could be a full map, filling an entire
10  * level or a minivault that occupies just a portion of the level.
11  */
12 
13 #pragma once
14 
15 #include <cstdio>
16 #include <memory>
17 #include <stdexcept>
18 #include <string>
19 #include <vector>
20 #include <unordered_set>
21 
22 #include "dlua.h"
23 #include "enum.h"
24 #include "fprop.h"
25 #include "god-type.h"
26 #include "makeitem.h"
27 #include "matrix.h"
28 #include "mon-attitude-type.h"
29 #include "mon-ench.h"
30 #include "mon-flags.h"
31 #include "tags.h"
32 #include "trap-type.h"
33 #include "travel-defs.h"
34 
35 #define NEVER_CORPSE_KEY "never_corpse"
36 
37 #define RANDBK_OWNER_KEY "randbook_owner"
38 #define RANDBK_TITLE_KEY "randbook_title"
39 #define RANDBK_DISC1_KEY "randbook_disc1"
40 #define RANDBK_DISC2_KEY "randbook_disc2"
41 #define RANDBK_SPELLS_KEY "randbook_spells"
42 #define RANDBK_SLVLS_KEY "randbook_slevels"
43 #define RANDBK_NSPELLS_KEY "randbook_num_spells"
44 
45 #ifdef DEBUG_TAG_PROFILING
46 void tag_profile_out();
47 #endif
48 
49 class mon_enchant;
50 extern const char *traversable_glyphs;
51 
52 // Invalid heightmap height.
53 static const int INVALID_HEIGHT = -31999;
54 
55 static const int BRANCH_END = 100;
56 
57 // Exception thrown when a map cannot be loaded from its .dsc file
58 // because the .dsc file has changed under it.
59 struct map_load_exception : public runtime_error
60 {
61     // g++ 4.7 doesn't have inherited constructors, sadly
map_load_exceptionmap_load_exception62     map_load_exception(const string &s) : runtime_error(s) { }
map_load_exceptionmap_load_exception63     map_load_exception(const char *s) : runtime_error(s) { }
64 };
65 
66 // [dshaligram] Maps can be mirrored; for every orientation, there must be
67 // a suitable mirror.
68 enum map_section_type                  // see maps.cc and dungeon.cc {dlb}
69 {
70     MAP_NONE  = -1,
71     MAP_NORTH = 1,                     //    1
72     MAP_SOUTH,
73     MAP_EAST,
74     MAP_WEST,
75     MAP_NORTHWEST,                     //    5
76     MAP_NORTHEAST,
77     MAP_SOUTHWEST,
78     MAP_SOUTHEAST,
79     MAP_ENCOMPASS,
80 
81     // A "floating" vault is placed somewhat like a minivault, away from
82     // the edges, although in other respects it behaves like a regular vault.
83     MAP_FLOAT,
84 
85     // Place at the centre of the map, and use a "central" layout.
86     MAP_CENTRE,
87 
88     MAP_NUM_SECTION_TYPES
89 };
90 
91 struct raw_range
92 {
93     branch_type branch;
94     int shallowest, deepest;
95     bool deny;
96 };
97 
98 struct level_range
99 {
100 public:
101     branch_type branch;
102     int shallowest, deepest;
103     bool deny;
104 
105 public:
106     level_range(const raw_range &range);
107     /// @throws bad_level_id if d < s and d != -1.
108     level_range(branch_type br = BRANCH_DUNGEON, int s = -1, int d = -1);
109 
110     /// @throws bad_level_id if d < s and d != -1.
111     void set(int s, int d = -1);
112     /// @throws bad_level_id if d < s, d < 0, or branch could not be parsed.
113     void set(const string &branch, int s, int d);
114 
115     void reset();
116     bool matches(const level_id &) const;
117     bool matches(int depth) const;
118 
119     void write(writer&) const;
120     void read(reader&);
121 
122     bool valid() const;
123 
124     /// @throws bad_level_id if lr does not specify a valid level range.
125     static level_range parse(string lr);
126 
127     string describe() const;
128     string str_depth_range() const;
129 
130     bool operator == (const level_range &lr) const;
131 
132     operator raw_range () const;
stringlevel_range133     operator string () const
134     {
135         return describe();
136     }
137 
138 private:
139     /// @throws bad_level_id if s does not specify a valid level range.
140     static void parse_partial(level_range &lr, const string &s);
141     /// @throws bad_level_id if s does not specify a valid level range.
142     static void parse_depth_range(const string &s, int *low, int *high);
143 };
144 
145 typedef pair<int,int> glyph_weighted_replacement_t;
146 typedef vector<glyph_weighted_replacement_t> glyph_replacements_t;
147 
148 class map_lines;
149 
150 class subst_spec
151 {
152 public:
153     subst_spec(string torepl, bool fix, const glyph_replacements_t &repls);
154     subst_spec(int count, bool fix, const glyph_replacements_t &repls);
subst_spec()155     subst_spec() : key(""), count(-1), fix(false), frozen_value(0), repl() { }
156 
157     int value();
158 
159 public:
160     string key;
161     // If this is part of an nsubst spec, how many to replace.
162     // -1 corresponds to all (i.e. '*')
163     int count;
164 
165     bool fix;
166     int frozen_value;
167 
168     glyph_replacements_t repl;
169 };
170 
171 class nsubst_spec
172 {
173 public:
174     nsubst_spec(string key, const vector<subst_spec> &specs);
175 public:
176     string key;
177     vector<subst_spec> specs;
178 };
179 
180 typedef pair<int, int> map_weighted_colour;
181 class map_colour_list : public vector<map_weighted_colour>
182 {
183 public:
184     bool parse(const string &s, int weight);
185 };
186 class colour_spec
187 {
188 public:
colour_spec(string _key,bool _fix,const map_colour_list & clist)189     colour_spec(string _key, bool _fix, const map_colour_list &clist)
190         : key(_key), fix(_fix), fixed_colour(BLACK), colours(clist)
191     {
192     }
193 
194     int get_colour();
195 
196 public:
197     string key;
198     bool fix;
199     int fixed_colour;
200     map_colour_list colours;
201 };
202 
203 typedef pair<feature_property_type, int> map_weighted_fprop;
204 class map_fprop_list : public vector<map_weighted_fprop>
205 {
206 public:
207     bool parse(const string &fp, int weight);
208 };
209 
210 typedef pair<int, int> map_weighted_fheight;
211 class map_featheight_list : public vector<map_weighted_fheight>
212 {
213 public:
214     bool parse(const string &fp, int weight);
215 };
216 
217 class fprop_spec
218 {
219 public:
fprop_spec(string _key,bool _fix,const map_fprop_list & flist)220     fprop_spec(string _key, bool _fix, const map_fprop_list &flist)
221         : key(_key), fix(_fix), fixed_prop(FPROP_NONE), fprops(flist)
222     {
223     }
224 
225     feature_property_type get_property();
226 
227 public:
228     string key;
229     bool fix;
230     feature_property_type fixed_prop;
231     map_fprop_list fprops;
232 };
233 
234 class fheight_spec
235 {
236 public:
fheight_spec(string _key,bool _fix,const map_featheight_list & _fheights)237     fheight_spec(string _key, bool _fix, const map_featheight_list &_fheights)
238         : key(_key), fix(_fix), fixed_height(INVALID_HEIGHT),
239           fheights(_fheights)
240     {
241     }
242     int get_height();
243 public:
244     string key;
245     bool fix;
246     int fixed_height;
247     map_featheight_list fheights;
248 };
249 
250 typedef pair<string, int> map_weighted_tile;
251 class map_tile_list : public vector<map_weighted_tile>
252 {
253 public:
254     bool parse(const string &s, int weight);
255 };
256 
257 class tile_spec
258 {
259 public:
tile_spec(const string & _key,bool _fix,bool _rand,bool _last,bool _floor,bool _feat,const map_tile_list & _tiles)260     tile_spec(const string &_key, bool _fix, bool _rand, bool _last, bool _floor, bool _feat, const map_tile_list &_tiles)
261         : key(_key), fix(_fix), chose_fixed(false), no_random(_rand), last_tile(_last), floor(_floor), feat(_feat),
262           fixed_tile(""), tiles(_tiles)
263     {
264     }
265 
266     string get_tile();
267 
268 public:
269     string key;
270     bool fix;
271     bool chose_fixed;
272     bool no_random;
273     bool last_tile;
274     bool floor;
275     bool feat;
276     string fixed_tile;
277     map_tile_list tiles;
278 };
279 
280 class map_marker_spec
281 {
282 public:
283     string key;
284     string marker;
285 
286     // Special handling for Lua markers:
287     unique_ptr<lua_datum> lua_fn;
288 
map_marker_spec(string _key,const string & mark)289     map_marker_spec(string _key, const string &mark)
290         : key(_key), marker(mark), lua_fn() { }
291 
map_marker_spec(string _key,const lua_datum & fn)292     map_marker_spec(string _key, const lua_datum &fn)
293         : key(_key), marker(), lua_fn(new lua_datum(fn)) { }
294 
295     string apply_transform(map_lines &map);
296 
297 private:
298     map_marker *create_marker();
299 };
300 
301 typedef pair<string, int> map_weighted_string;
302 class map_string_list : public vector<map_weighted_string>
303 {
304 public:
305     bool parse(const string &fp, int weight);
306 };
307 class string_spec
308 {
309 public:
string_spec(string _key,bool _fix,const map_string_list & slist)310     string_spec(string _key, bool _fix, const map_string_list &slist)
311         : key(_key), fix(_fix), fixed_str(""), strlist(slist)
312     {
313     }
314 
315     string get_property();
316 
317 public:
318     string key;
319     bool fix;
320     string fixed_str;
321     map_string_list strlist;
322 };
323 
324 typedef pair<coord_def, coord_def> map_corner_t;
325 class map_def;
326 class rectangle_iterator;
327 struct keyed_mapspec;
328 class map_lines
329 {
330 public:
331     class iterator
332     {
333     public:
334         iterator(map_lines &ml, const string &key);
335         operator bool () const;
336         coord_def operator ++ ();
337         coord_def operator ++ (int);
338         coord_def operator * () const;
339     private:
340         void advance();
341     private:
342         map_lines &maplines;
343         string key;
344         coord_def p;
345     };
346 
347 public:
348     map_lines();
349     map_lines(const map_lines &);
350     ~map_lines();
351 
352     map_lines &operator = (const map_lines &);
353 
354     bool in_map(const coord_def &pos) const;
355 
356     void add_line(const string &s);
357     string add_nsubst(const string &st);
358     string add_subst(const string &st);
359     string add_shuffle(const string &s);
360     string add_clear(const string &s);
361     string add_colour(const string &col);
362     string add_fproperty(const string &sub);
363     string add_fheight(const string &arg);
364     void clear_markers();
365 
366     void write_maplines(writer &) const;
367     void read_maplines(reader&);
368 
369     string add_floortile(const string &s);
370     string add_rocktile(const string &s);
371     string add_spec_tile(const string &s);
372 
373     vector<coord_def> find_glyph(const string &glyphs) const;
374     vector<coord_def> find_glyph(int glyph) const;
375     coord_def find_first_glyph(int glyph) const;
376     coord_def find_first_glyph(const string &glyphs) const;
377 
378     // Find rectangular bounds (inclusive) for uses of the glyph in the map.
379     // Returns false if glyph could not be found.
380     bool find_bounds(int glyph, coord_def &tl, coord_def &br) const;
381     // Same as above, but for any of the glyphs in glyph_str.
382     bool find_bounds(const char *glyph_str, coord_def &tl, coord_def &br) const;
383 
384     void set_orientation(const string &s);
385 
386     int width() const;
387     int height() const;
388     coord_def size() const;
389 
390     int glyph(int x, int y) const;
391     int glyph(const coord_def &) const;
392     bool is_solid(int gly) const;
393 
394     bool solid_borders(map_section_type border);
395 
396     // Make all lines the same length.
397     void normalise(char fillc = ' ');
398 
399     // Rotate 90 degrees either clockwise or anticlockwise
400     void rotate(bool clockwise);
401     void hmirror();
402     void vmirror();
403 
404     void clear();
405 
406     void add_marker(map_marker *marker);
407     string add_feature_marker(const string &desc);
408     string add_lua_marker(const string &key, const lua_datum &fn);
409 
410     void apply_markers(const coord_def &pos);
411     void apply_grid_overlay(const coord_def &pos, bool is_layout);
412     void apply_overlays(const coord_def &pos, bool is_layout);
413 
414     const vector<string> &get_lines() const;
415     vector<string> &get_lines();
416 
417     rectangle_iterator get_iter() const;
418     char operator () (const coord_def &c) const;
419     char& operator () (const coord_def &c);
420     char operator () (int x, int y) const;
421     char& operator () (int x, int y);
422 
423     const keyed_mapspec *mapspec_at(const coord_def &c) const;
424     keyed_mapspec *mapspec_at(const coord_def &c);
425 
426     string add_key_item(const string &s);
427     string add_key_mons(const string &s);
428     string add_key_feat(const string &s);
429     string add_key_mask(const string &s);
430 
431     bool in_bounds(const coord_def &c) const;
432 
433     // Extend map dimensions with glyph 'fill' to minimum width and height.
434     void extend(int min_width, int min_height, char fill);
435 
436     bool fill_zone(travel_distance_grid_t &tpd, const coord_def &start,
437                    const coord_def &tl, const coord_def &br, int zone,
438                    const char *wanted, const char *passable) const;
439 
440     int count_feature_in_box(const coord_def &tl, const coord_def &br,
441                              const char *feat) const;
442 
443     void fill_mask_matrix(const string &glyphs, const coord_def &tl,
444                           const coord_def &br, Matrix<bool> &flags);
445 
446     // Merge vault onto the tl/br subregion, where mask is true.
447     map_corner_t merge_subvault(const coord_def &tl, const coord_def &br,
448                                 const Matrix<bool> &mask, const map_def &vault);
449 private:
450     void init_from(const map_lines &map);
451     void vmirror_markers();
452     void hmirror_markers();
453     void rotate_markers(bool clock);
454     void vmirror_marker(map_marker *, int par);
455     void hmirror_marker(map_marker *, int par);
456     void rotate_marker(map_marker *, int par);
457     void translate_marker(void (map_lines::*xform)(map_marker *, int par),
458                           int par = 0);
459 
460     void resolve_shuffle(const string &shuffle);
461     void clear(const string &clear);
462     void subst(string &s, subst_spec &spec);
463     void subst(subst_spec &);
464     void nsubst(nsubst_spec &);
465     void bind_overlay();
466     void overlay_colours(colour_spec &);
467     void overlay_fprops(fprop_spec &);
468     void overlay_fheights(fheight_spec &);
469 
470     // Merge cell (vx, vy) from vault onto this map's (x, y) cell.
471     typedef FixedVector<int, 256> keyspec_map;
472     void merge_cell(int x, int y, const map_def &vault, int vx, int vy,
473                     int keyspec_idx);
474 
475     void overlay_tiles(tile_spec &);
476     void check_borders();
477     string shuffle(string s);
478     string block_shuffle(const string &s);
479     string check_shuffle(string &s);
480     string check_block_shuffle(const string &s);
481     string clean_shuffle(string s);
482     string check_clear(string &s);
483     string parse_nsubst_spec(const string &s, subst_spec &spec);
484     int apply_nsubst(vector<coord_def> &pos, int start, int nsub,
485                      subst_spec &spec);
486     string parse_glyph_replacements(string s, glyph_replacements_t &gly);
487 
488     string add_tile(const string &sub, bool is_floor, bool is_feat);
489 
490     string add_key_field(
491         const string &s,
492         string (keyed_mapspec::*set_field)(const string &s, bool fixed),
493         void (keyed_mapspec::*copy_field)(const keyed_mapspec &spec));
494 
495     const keyed_mapspec *mapspec_for_key(int key) const;
496     keyed_mapspec *mapspec_for_key(int key);
497 
498     friend class subst_spec;
499     friend class nsubst_spec;
500     friend class shuffle_spec;
501     friend class map_marker_spec;
502     friend class colour_spec;
503     friend class tile_spec;
504 
505 private:
506     vector<map_marker *> markers;
507     vector<string> lines;
508 
509     struct overlay_def
510     {
overlay_defoverlay_def511         overlay_def() :
512             colour(0), rocktile(""), floortile(""), tile(""),
513             no_random(false), last_tile(false), property(),
514             height(INVALID_HEIGHT), keyspec_idx(0)
515         {}
516         colour_t colour;
517         string rocktile;
518         string floortile;
519         string tile;
520         bool no_random;
521         bool last_tile;
522         terrain_property_t property;
523         int height;      // heightmap height
524         int keyspec_idx;
525     };
526     typedef Matrix<overlay_def> overlay_matrix;
527     unique_ptr<overlay_matrix> overlay;
528 
529     typedef map<int, keyed_mapspec> keyed_specs;
530     keyed_specs keyspecs;
531     int next_keyspec_idx;
532 
533     enum
534     {
535         SUBVAULT_GLYPH = 1,
536     };
537 
538     int map_width;
539     bool solid_north, solid_east, solid_south, solid_west;
540     bool solid_checked;
541 };
542 
543 enum item_spec_type
544 {
545     ISPEC_STAR    = -2,
546     ISPEC_SUPERB  = -3,
547     ISPEC_DAMAGED = -4,
548     ISPEC_BAD     = -5,
549     ISPEC_RANDART = -6,
550     ISPEC_MUNDANE = -7,
551     ISPEC_ACQUIREMENT = -9,
552     ISPEC_GIFT    = 350, // worse than the next one
553     ISPEC_GOOD_ITEM = 351,
554 };
555 
556 class mons_spec;
557 class item_spec
558 {
559 public:
560     int genweight;
561 
562     object_class_type base_type;
563     int sub_type;
564     int plus, plus2;
565     int ego;
566     int allow_uniques;
567     int level;
568     int item_special;
569     int qty;
570     int acquirement_source;
571     level_id place;
572 
573     // Specifically for storing information about randart spell books.
574     CrawlHashTable props;
575 
item_spec()576     item_spec() : genweight(10), base_type(OBJ_RANDOM), sub_type(OBJ_RANDOM),
577         plus(-1), plus2(-1), ego(0), allow_uniques(1), level(-1),
578         item_special(0), qty(0), acquirement_source(0), place(), props(),
579         _corpse_monster_spec(nullptr)
580     {
581     }
582 
583     item_spec(const item_spec &other);
584     item_spec &operator = (const item_spec &other);
585     ~item_spec();
586 
587     bool corpselike() const;
588     const mons_spec &corpse_monster_spec() const;
589     void set_corpse_monster_spec(const mons_spec &spec);
590 
591 private:
592     mons_spec *_corpse_monster_spec;
593 
594 private:
595     void release_corpse_monster_spec();
596 };
597 typedef vector<item_spec> item_spec_list;
598 
599 class item_list
600 {
601 public:
item_list()602     item_list() : items() { }
603 
604     void clear();
605 
606     item_spec get_item(int index);
607     item_spec random_item();
608     item_spec random_item_weighted();
size()609     size_t size() const { return items.size(); }
empty()610     bool empty() const { return items.empty(); }
611 
612     string add_item(const string &spec, bool fix = false);
613     string set_item(int index, const string &spec);
614 
615     // Set this list to be a copy of the item_spec_slot in list.
616     void set_from_slot(const item_list &list, int slot_index);
617 
618 private:
619     struct item_spec_slot
620     {
621         item_spec_list ilist;
622         bool fix_slot;
623 
item_spec_slotitem_spec_slot624         item_spec_slot() : ilist(), fix_slot(false)
625         {
626         }
627     };
628 
629 private:
630     item_spec item_by_specifier(const string &spec);
631     item_spec_slot parse_item_spec(string spec);
632     bool parse_single_spec(item_spec &result, string s);
633     int parse_acquirement_source(const string &source);
634     void parse_raw_name(string name, item_spec &spec);
635     void parse_random_by_class(string c, item_spec &spec);
636     item_spec pick_item(item_spec_slot &slot);
637     bool parse_corpse_spec(item_spec &result, string s);
638     bool monster_corpse_is_valid(monster_type *, const string &name,
639                                  bool skeleton);
640 
641 private:
642     vector<item_spec_slot> items;
643     string error;
644 };
645 
646 class mons_spec
647 {
648 public:
649     monster_type type;
650     level_id place;
651     monster_type monbase;     // Base monster for zombies and dracs.
652     mon_attitude_type attitude;
653     int quantity;             // Number of monsters (usually 1).
654     int genweight;
655     bool generate_awake;
656     bool patrolling;
657     bool band;
658     int colour; // either COLOUR_INHERIT for "default", COLOUR_UNDEF for any
659                 // colour upon creation, or an otherwise valid colour_t value.
660 
661     god_type god;
662     bool god_gift;
663 
664     int hd;
665     int hp;
666     int abjuration_duration;
667     int summon_type;
668 
669     item_list items;
670     string monname;
671     string non_actor_summoner;
672 
673     bool explicit_spells;
674     vector<monster_spells> spells;
675     monster_flags_t extra_monster_flags;
676     vector<mon_enchant> ench;
677 
678     monster_type initial_shifter;
679 
680     CrawlHashTable props;
681 
682     mons_spec(monster_type t = RANDOM_MONSTER,
683               monster_type base = MONS_NO_MONSTER)
type(t)684         : type(t), place(), monbase(base), attitude(ATT_HOSTILE),
685           quantity(1), genweight(10),
686           generate_awake(false), patrolling(false), band(false),
687           colour(COLOUR_INHERIT), god(GOD_NO_GOD), god_gift(false), hd(0),
688           hp(0), abjuration_duration(0), summon_type(0), items(), monname(""),
689           non_actor_summoner(""), explicit_spells(false), spells(),
690           extra_monster_flags(), initial_shifter(RANDOM_MONSTER), props()
691     {
692     }
693 };
694 
695 class mons_list
696 {
697 public:
698     mons_list();
699 
700     void clear();
701 
702     // Set this list to be a copy of the mons_spec_slot in list.
703     void set_from_slot(const mons_list &list, int slot_index);
704 
705     mons_spec get_monster(int index);
706     mons_spec get_monster(int slot_index, int list_index) const;
707 
708     // Returns an error string if the monster is unrecognised.
709     string add_mons(const string &s, bool fix_slot = false);
710     string set_mons(int slot, const string &s);
711 
empty()712     bool empty()               const { return mons.empty(); }
size()713     size_t size()              const { return mons.size(); }
slot_size(int slot)714     size_t slot_size(int slot) const { return mons[slot].mlist.size(); }
715 
716 private:
717     typedef vector<mons_spec> mons_spec_list;
718 
719     struct mons_spec_slot
720     {
721         mons_spec_list mlist;
722         bool fix_slot;
723 
724         mons_spec_slot(const mons_spec_list &list, bool fix = false)
mlistmons_spec_slot725             : mlist(list), fix_slot(fix)
726         {
727         }
728 
mons_spec_slotmons_spec_slot729         mons_spec_slot()
730             : mlist(), fix_slot(false)
731         {
732         }
733     };
734 
735 private:
736     mons_spec mons_by_name(string name) const;
737     mons_spec drac_monspec(string name) const;
738     mons_spec demonspawn_monspec(string name) const;
739     mons_spec soh_monspec(string name) const;
740     void get_zombie_type(string s, mons_spec &spec) const;
741     mons_spec get_hydra_spec(const string &name) const;
742     mons_spec get_slime_spec(const string &name) const;
743     mons_spec get_salt_spec(const string &name) const;
744     mons_spec get_zombified_monster(const string &name,
745                                     monster_type zomb) const;
746     mons_spec_slot parse_mons_spec(string spec);
747     void parse_mons_spells(mons_spec &slot, vector<string> &spells);
748     mon_enchant parse_ench(string &ench_str, bool perm);
749     mons_spec pick_monster(mons_spec_slot &slot);
750 
751 private:
752     vector< mons_spec_slot > mons;
753     string error;
754 };
755 
756 /**
757  * @class shop_spec
758  * @ingroup mapdef
759  * @brief Specify how to create a shop.
760  *
761  * This specification struct is used when converting a vault-specified shop from
762  * a string into something the builder can use to actually create and place a
763  * shop.
764 **/
765 struct shop_spec
766 {
767     shop_type sh_type;  /**< One of the shop_type enum values. */
768 
769     string name;        /**< If provided, this is apostrophised and used as the
770                           *  shop keeper's name, ie, Plog as a name becomes
771                           *  Plog's. */
772 
773     string type;        /**< If provided, this is used as the shop type name,
774                           *  ie, Hide, Antique, Wand, etc. */
775 
776     string suffix;      /**< If provided, this is used as the shop suffix,
777                           *  ie, Shop, Boutique, Parlour, etc. */
778 
779     int greed;          /**< If provided, this value is used for price
780                           *  calculation. The higher the greed, the more
781                           *  inflation applied to prices. */
782 
783     int num_items;      /**< Cap the number of items in a shop at this. */
784 
785     item_list items;    /**< If provided, and `use_all` is false, items will be
786                           *  selected at random from the list and used to
787                           *  populate the shop. If `use_all` is true, the items
788                           *  contained will be placed precisely and in order. If
789                           *  the number of items contained is less than
790                           *  specified, random items according to the shop's
791                           *  type will be used to fill in the rest of the stock.
792                           *  */
793 
794     bool use_all;       /**< True if all items in `items` should be used. */
795 
796     bool gozag;         /**< True if this shop was created by Gozag's Call
797                          *   Merchant ability (and therefore should have better
798                          *   stock).
799                          *   */
800 
801     shop_spec(shop_type sh, string n="", string t="",
802               string s="", int g=-1, int ni=-1, bool u=false, bool goz=false)
sh_typeshop_spec803         : sh_type(sh), name(n), type(t), suffix(s),
804           greed(g), num_items(ni), items(), use_all(u), gozag(goz) { }
805 };
806 
807 /**
808  * @class trap_spec
809  * @ingroup mapdef
810  * @brief Specify how to create a trap.
811  *
812  * This specification struct is used when converting a vault-specified trap
813  * string into something that the builder can use to place a trap.
814 **/
815 struct trap_spec
816 {
817     trap_type tr_type; /*> One of the trap_type enum values. */
trap_spectrap_spec818     trap_spec(trap_type tr)
819         : tr_type(static_cast<trap_type>(tr)) { }
820 };
821 
822 /**
823  * @class feature_spec
824  * @ingroup mapdef
825  * @brief Specify how to create a feature.
826  *
827  * This specification struct is used firstly when a feature is specified in
828  * vault code (any feature), and secondly, if that feature is either a trap or a
829  * shop, as a container for a unique_ptr to that shop_spec or trap_spec.
830 **/
831 struct feature_spec
832 {
833     int genweight;                 /**> The weight of this specific feature. */
834     int feat;                      /**> The specific feature being placed. */
835     unique_ptr<shop_spec> shop;    /**> A pointer to a shop_spec. */
836     unique_ptr<trap_spec> trap;    /**> A pointer to a trap_spec. */
837     int glyph;                     /**> What glyph to use instead. */
838     int mimic;                     /**> 1 chance in x to be a feature mimic. */
839     bool no_mimic;                 /**> Prevents random feature mimic here. */
840 
841     feature_spec();
842     feature_spec(int f, int wt = 10, int _mimic = 0, bool _no_mimic = false);
843     feature_spec(const feature_spec& other);
844     feature_spec& operator = (const feature_spec& other);
845     void init_with(const feature_spec& other);
846 };
847 
848 typedef vector<feature_spec> feature_spec_list;
849 struct feature_slot
850 {
851     feature_spec_list feats;
852     bool fix_slot;
853 
854     feature_slot();
855     feature_spec get_feat(int default_glyph);
856 };
857 
858 struct bad_map_flag : public runtime_error
859 {
bad_map_flagbad_map_flag860     explicit bad_map_flag(const string &flag) : runtime_error(flag) {}
bad_map_flagbad_map_flag861     explicit bad_map_flag(const char *flag) : runtime_error(flag) {}
862 };
863 
864 struct map_flags
865 {
866     unsigned long flags_set, flags_unset;
867 
868     map_flags();
869     void clear();
870     map_flags &operator |= (const map_flags &o);
871 
872     /// @throws bad_map_flag if one of the flags was invalid.
873     static map_flags parse(const string flag_list[], const string &s);
874 };
875 
876 struct keyed_mapspec
877 {
878 public:
879     int          key_glyph;
880 
881     feature_slot feat;
882     item_list    item;
883     mons_list    mons;
884     map_flags    map_mask;
885 
886 public:
887     keyed_mapspec();
888 
889     // Parse the string and set the given entry. If fix is true,
890     // then whatever is selected for the first feature will be
891     // permanently fixed.
892     string set_feat(const string &s, bool fix);
893     string set_mons(const string &s, bool fix);
894     string set_item(const string &s, bool fix);
895     string set_mask(const string &s, bool /*garbage*/);
896 
897     // Copy from the given mapspec. If that entry is fixed,
898     // it should be pre-selected prior to the copy.
899     void copy_feat(const keyed_mapspec &spec);
900     void copy_mons(const keyed_mapspec &spec);
901     void copy_item(const keyed_mapspec &spec);
902     void copy_mask(const keyed_mapspec &spec);
903     void copy_height(const keyed_mapspec &spec);
904 
905     feature_spec get_feat();
906     mons_list   &get_monsters();
907     item_list   &get_items();
908     map_flags   &get_mask();
909 
910     // Does this mapspec specify a feature, item, or monster?  If so, the
911     // glyph should be ignored.
912     bool replaces_glyph();
913 private:
914     string err;
915 
916 private:
917     void parse_features(const string &);
918     feature_spec_list parse_feature(const string &s);
919     feature_spec parse_shop(string s, int weight, int mimic, bool no_mimic);
920     feature_spec parse_trap(string s, int weight);
921 };
922 
923 class dlua_set_map
924 {
925 public:
926     dlua_set_map(map_def *map);
927     ~dlua_set_map();
928 private:
929     unique_ptr<lua_datum> old_map;
930 };
931 
932 dungeon_feature_type map_feature_at(map_def *map,
933                                     const coord_def &c,
934                                     int rawfeat);
935 
936 struct map_file_place
937 {
938     string filename;
939     int lineno;
940 
941     map_file_place(const string &s = "", int line = 0)
filenamemap_file_place942         : filename(s), lineno(line)
943     {
944     }
945 
clearmap_file_place946     void clear()
947     {
948         filename.clear();
949         lineno = 0;
950     }
951 };
952 
953 struct map_chance
954 {
955     int chance;
map_chancemap_chance956     map_chance() : chance(-1) { }
map_chancemap_chance957     map_chance(int _chance) : chance(_chance) { }
validmap_chance958     bool valid() const { return chance >= 0; }
959     string describe() const;
960     // Returns true if the vault makes the random CHANCE_ROLL.
961     bool roll() const;
962     void write(writer &) const;
963     void read(reader &);
964 };
965 
966 typedef vector<level_range> depth_ranges_v;
967 class depth_ranges
968 {
969 private:
970     depth_ranges_v depths;
971 public:
972     // @throws bad_level_id if one if the comma-separated ranges is invalid.
973     static depth_ranges parse_depth_ranges(const string &depth_ranges_string);
974     void read(reader &);
975     void write(writer &) const;
clear()976     void clear() { depths.clear(); }
empty()977     bool empty() const { return depths.empty(); }
978     bool is_usable_in(const level_id &lid) const;
add_depth(const level_range & range)979     void add_depth(const level_range &range) { depths.push_back(range); }
980     void add_depths(const depth_ranges &other_ranges);
981     string describe() const;
982 };
983 
984 template <typename X>
985 struct depth_range_X
986 {
987     depth_ranges depths;
988     X depth_thing;
depth_range_Xdepth_range_X989     depth_range_X() : depths(), depth_thing() { }
990     /// @throws bad_level_id if depth_range_string is invalid.
depth_range_Xdepth_range_X991     depth_range_X(const string &depth_range_string, const X &thing)
992         : depths(depth_ranges::parse_depth_ranges(depth_range_string)),
993           depth_thing(thing)
994     {
995     }
is_usable_indepth_range_X996     bool is_usable_in(const level_id &lid) const
997     {
998         return depths.is_usable_in(lid);
999     }
1000     template <typename reader_fn_type>
readdepth_range_X1001     static depth_range_X read(reader &inf, reader_fn_type reader_fn)
1002     {
1003         depth_range_X range_x;
1004         range_x.depths.read(inf);
1005         range_x.depth_thing = reader_fn(inf);
1006         return range_x;
1007     }
1008     template <typename writer_fn_type>
writedepth_range_X1009     void write(writer &outf, writer_fn_type writer_fn) const
1010     {
1011         depths.write(outf);
1012         writer_fn(outf, depth_thing);
1013     }
1014 };
1015 
1016 template <typename X>
1017 class depth_ranges_X
1018 {
1019 private:
1020     typedef vector<depth_range_X<X> > depth_range_X_v;
1021 
1022     X default_thing;
1023     depth_range_X_v depth_range_Xs;
1024 public:
depth_ranges_X()1025     depth_ranges_X() : default_thing(), depth_range_Xs() { }
depth_ranges_X(const X & _default_thing)1026     depth_ranges_X(const X &_default_thing)
1027         : default_thing(_default_thing), depth_range_Xs() { }
1028     void clear(const X &_default_X = X())
1029     {
1030         depth_range_Xs.clear();
1031         set_default(_default_X);
1032     }
set_default(const X & _default_X)1033     void set_default(const X &_default_X)
1034     {
1035         default_thing = _default_X;
1036     }
get_default()1037     X get_default() const { return default_thing; }
1038     /// @throws bad_level_id if depth_range_string is invalid.
add_range(const string & depth_range_string,const X & thing)1039     void add_range(const string &depth_range_string, const X &thing)
1040     {
1041         depth_range_Xs.push_back(depth_range_X<X>(depth_range_string, thing));
1042     }
depth_value(const level_id & lid)1043     X depth_value(const level_id &lid) const
1044     {
1045         typename depth_range_X_v::const_iterator i = depth_range_Xs.begin();
1046         for ( ; i != depth_range_Xs.end(); ++i)
1047             if (i->is_usable_in(lid))
1048                 return i->depth_thing;
1049         return default_thing;
1050     }
1051     template <typename reader_fn_type>
read(reader & inf,reader_fn_type reader_fn)1052     static depth_ranges_X read(reader &inf, reader_fn_type reader_fn)
1053     {
1054         depth_ranges_X ranges;
1055         ranges.clear(reader_fn(inf));
1056         const int count = unmarshallShort(inf);
1057         for (int i = 0; i < count; ++i)
1058         {
1059             ranges.depth_range_Xs.push_back(
1060                 depth_range_X<X>::read(inf, reader_fn));
1061         }
1062         return ranges;
1063     }
1064     template <typename writer_fn_type>
write(writer & outf,writer_fn_type writer_fn)1065     void write(writer &outf, writer_fn_type writer_fn) const
1066     {
1067         writer_fn(outf, default_thing);
1068         marshallShort(outf, depth_range_Xs.size());
1069         for (const auto &range : depth_range_Xs)
1070             range.write(outf, writer_fn);
1071     }
1072 };
1073 
1074 // Position of a subvault inside its parent.
1075 struct subvault_place
1076 {
1077     coord_def tl, br;
1078     unique_ptr<map_def> subvault;
1079 
1080     subvault_place();
1081     subvault_place(const coord_def &_tl, const coord_def &_br,
1082                    const map_def &_subvault);
1083     subvault_place(const subvault_place &place);
1084     subvault_place &operator = (const subvault_place &place);
1085 
1086     void set_subvault(const map_def &);
1087 };
1088 
1089 /////////////////////////////////////////////////////////////////////////////
1090 // map_def: map definitions for maps loaded from .des files.
1091 //
1092 // Please read this before changing map_def.
1093 //
1094 // When adding Lua-visible fields to map_def, note that there are two
1095 // kinds of fields:
1096 //
1097 // * Fields that determine placement of the map, or are unchanging,
1098 //   such as "place", "depths" (determine placement), or "name" (does
1099 //   not change between different evaluations of the map). Such fields
1100 //   must be reset to their default values in map_def::init() if they
1101 //   determine placement, or just initialised in the constructor if
1102 //   they will not change.
1103 //
1104 // * Fields that do not determine placement and may change between
1105 //   different uses of the map (such as "mons", "items", etc.). Such fields
1106 //   must be reset to their default values in map_def::reinit(), which is
1107 //   called before the map is used.
1108 //
1109 // If you do not do this, maps will not work correctly, and will break
1110 // in obscure, hard-to-find ways. The level-compiler will not (cannot)
1111 // warn you.
1112 //
1113 class map_def
1114 {
1115 public:
1116     string          name;
1117     // Description for the map that can be shown to players.
1118     string          description;
1119     // Order among related maps; used only for tutorial/sprint.
1120     int             order;
1121     depth_ranges    place;
1122 
1123     depth_ranges     depths;
1124     map_section_type orient;
1125 
1126     typedef depth_ranges_X<map_chance> range_chance_t;
1127     typedef depth_ranges_X<int> range_weight_t;
1128 
1129     range_chance_t   _chance;
1130     range_weight_t   _weight;
1131 
1132     map_lines       map;
1133     mons_list       mons;
1134     item_list       items;
1135 
1136     static bool valid_item_array_glyph(int gly);
1137     static int item_array_glyph_to_slot(int gly);
1138     static bool valid_monster_array_glyph(int gly);
1139     static bool valid_monster_glyph(int gly);
1140     static int monster_array_glyph_to_slot(int gly);
1141 
1142     vector<mons_spec> random_mons;
1143 
1144     dlua_chunk      prelude, mapchunk, main, validate, veto, epilogue;
1145 
1146     map_file_place  place_loaded_from;
1147 
1148     map_def         *original;
1149 
1150     colour_t        rock_colour, floor_colour;
1151     string          rock_tile, floor_tile;
1152 
1153     dungeon_feature_type border_fill_type;
1154 
1155     ::map<dungeon_feature_type, string> feat_renames;
1156     vector<subvault_place> subvault_places;
1157     string          file;
1158 
1159 private:
1160     unordered_set<string>     tags;
1161     // This map has been loaded from an index, and not fully realised.
1162     bool            index_only;
1163     mutable long    cache_offset;
1164     string          cache_name;
1165 
1166     typedef Matrix<bool> subvault_mask;
1167     subvault_mask *svmask;
1168 
1169     // True if this map is in the process of being validated.
1170     bool validating_map_flag;
1171 
1172     // values cached from tags -- adding to this is only recommended if you've
1173     // actually done the profiling...
1174     // These are the top three worst tags, which jointly amount to about 3-4%
1175     // of levelgen time if not cached.
1176     bool cache_minivault;
1177     bool cache_overwritable;
1178     bool cache_extra;
1179 
1180 public:
1181     map_def();
1182 
1183     string name_at(const coord_def &pos) const;
1184     string desc_or_name() const;
1185 
1186     string describe() const;
1187     void init();
1188     void reinit();
1189     void reload_epilogue();
1190 
1191     void load();
1192     void strip();
1193 
1194     int weight(const level_id &lid) const;
1195     map_chance chance(const level_id &lid) const;
1196 
1197     bool in_map(const coord_def &p) const;
1198     bool map_already_used() const;
1199 
size()1200     coord_def size() const { return coord_def(map.width(), map.height()); }
1201 
1202     vector<coord_def> find_glyph(int glyph) const;
1203     coord_def find_first_glyph(int glyph) const;
1204     coord_def find_first_glyph(const string &glyphs) const;
1205 
1206     void write_index(writer&) const;
1207     void write_full(writer&) const;
1208     void write_maplines(writer &) const;
1209 
1210     void read_index(reader&);
1211     void read_full(reader&);
1212     void read_maplines(reader&);
1213 
1214     void set_file(const string &s);
1215     string run_lua(bool skip_main);
1216     bool run_hook(const string &hook_name, bool die_on_lua_error = false);
1217     bool run_postplace_hook(bool die_on_lua_error = false);
1218     void copy_hooks_from(const map_def &other_map, const string &hook_name);
1219 
1220     // Returns true if the validation passed.
1221     bool test_lua_validate(bool croak = false);
1222 
1223     // Returns true if *not* vetoed, i.e., the map is good to go.
1224     bool test_lua_veto();
1225 
1226     // Executes post-generation lua code.
1227     bool run_lua_epilogue(bool croak = false);
1228 
1229     string validate_map_def(const depth_ranges &);
1230     string validate_temple_map();
1231     // Returns true if this map is in the middle of validation.
is_validating()1232     bool is_validating() const { return validating_map_flag; }
1233 
1234     void add_prelude_line(int line,  const string &s);
1235     void add_main_line(int line, const string &s);
1236 
1237     void hmirror();
1238     void vmirror();
1239     void rotate(bool clockwise);
1240     void normalise();
1241     string resolve();
1242     void fixup();
1243 
1244     bool is_usable_in(const level_id &lid) const;
1245 
1246     const keyed_mapspec *mapspec_at(const coord_def &c) const;
1247     keyed_mapspec *mapspec_at(const coord_def &c);
1248 
1249     bool has_depth() const;
1250     void add_depth(const level_range &depth);
1251     void add_depths(const depth_ranges &depth);
1252 
1253     bool can_dock(map_section_type) const;
1254     coord_def dock_pos(map_section_type) const;
1255     coord_def float_dock();
1256     coord_def float_place();
1257     coord_def float_aligned_place() const;
1258     coord_def float_random_place() const;
1259 
1260     vector<coord_def> anchor_points() const;
1261 
1262     bool is_minivault() const;
1263     bool is_overwritable_layout() const;
1264     bool is_extra_vault() const;
1265     bool has_tag(const string &tagwanted) const;
1266     bool has_tag_prefix(const string &tag) const;
1267     bool has_tag_suffix(const string &suffix) const;
1268 
1269     template <typename TagIterator>
has_all_tags(TagIterator begin,TagIterator end)1270     bool has_all_tags(TagIterator begin, TagIterator end) const
1271     {
1272         if (tags.empty() || begin == end) // legacy behaviour for empty case
1273             return false;
1274         for ( ; begin != end; ++begin)
1275             if (!has_tag(*begin))
1276                 return false;
1277         return true;
1278     }
1279     bool has_all_tags(const string &tagswanted) const;
1280 
1281     template <typename TagIterator>
has_any_tag(TagIterator begin,TagIterator end)1282     bool has_any_tag(TagIterator begin, TagIterator end) const
1283     {
1284         for ( ; begin != end; ++begin)
1285             if (has_tag(*begin))
1286                 return true;
1287         return false;
1288     }
1289 
1290     const vector<string> get_tags() const;
1291     const unordered_set<string> get_tags_unsorted() const;
1292     void add_tags(const string &tag);
1293     void set_tags(const string &tag);
1294     bool remove_tags(const string &tag);
1295     void clear_tags();
1296     string tags_string() const;
1297 
1298     vector<string> get_shuffle_strings() const;
1299     vector<string> get_subst_strings() const;
1300 
1301     int glyph_at(const coord_def &c) const;
1302 
1303     // Subvault functions.
1304     string subvault_from_tagstring(const string &s);
1305     bool is_subvault() const;
1306     void apply_subvault_mask();
1307     bool subvault_cell_valid(const coord_def &c) const;
1308     int subvault_width() const;
1309     int subvault_height() const;
1310     // Returns the number of cells in the subvault map that
1311     // will not get copied to parent vault at a given placement.
1312     int subvault_mismatch_count(const coord_def &place) const;
1313 
1314 public:
1315     struct map_feature_finder
1316     {
1317         map_def &map;
map_feature_findermap_feature_finder1318         map_feature_finder(map_def &map_) : map(map_) { }
1319         // This may actually modify the underlying map by fixing KFEAT:
1320         // feature slots, but that's fine by us.
operatormap_feature_finder1321         dungeon_feature_type operator () (const coord_def &c) const
1322         {
1323             return map_feature_at(&map, c, -1);
1324         }
1325     };
1326 
1327     struct map_bounds_check
1328     {
1329         map_def &map;
map_bounds_checkmap_bounds_check1330         map_bounds_check(map_def &map_) : map(map_) { }
operatormap_bounds_check1331         bool operator () (const coord_def &c) const
1332         {
1333             return c.x >= 0 && c.x < map.map.width()
1334                    && c.y >= 0 && c.y < map.map.height();
1335         }
1336     };
1337 
1338 private:
1339     bool test_lua_boolchunk(dlua_chunk &, bool def = false, bool croak = false);
1340     string rewrite_chunk_errors(const string &s) const;
1341     string apply_subvault(string_spec &);
1342     string validate_map_placeable();
1343     bool has_exit() const;
1344     void update_cached_tags();
1345 };
1346 
1347 const int CHANCE_ROLL = 10000;
1348 
1349 void clear_subvault_stack();
1350 
1351 void map_register_flag(const string &flag);
1352 
1353 string mapdef_split_key_item(const string &s, string *key, int *separator,
1354                              string *arg, int key_max_len = 1);
1355 
1356 const char *map_section_name(int msect);
1357 
1358 int store_tilename_get_index(const string& tilename);
1359 
1360 int str_to_ego(object_class_type item_type, string ego_str);
1361