1 /**
2  * @file
3  * @brief Travel stuff
4 **/
5 #pragma once
6 
7 #include <cstdio>
8 #include <map>
9 #include <string>
10 #include <vector>
11 
12 #include "command-type.h"
13 #include "daction-type.h"
14 #include "exclude.h"
15 #include "travel-defs.h"
16 
17 class reader;
18 class writer;
19 
20 enum run_check_type
21 {
22     RCHECK_LEFT,
23     RCHECK_FRONT,
24     RCHECK_RIGHT,
25 };
26 
27 enum run_dir_type
28 {
29     RDIR_UP = 0,
30     RDIR_UP_RIGHT,
31     RDIR_RIGHT,
32     RDIR_DOWN_RIGHT,
33     RDIR_DOWN,
34     RDIR_DOWN_LEFT,
35     RDIR_LEFT,
36     RDIR_UP_LEFT,
37     RDIR_REST,
38 };
39 
40 enum run_mode_type
41 {
42     RMODE_INTERLEVEL     = -4, // Interlevel travel
43     RMODE_EXPLORE_GREEDY = -3, // Explore + grab items
44     RMODE_EXPLORE        = -2, // Exploring
45     RMODE_TRAVEL         = -1, // Classic or Plain Old travel
46     RMODE_NOT_RUNNING    = 0,  // must remain equal to 0
47     RMODE_CONTINUE,
48     RMODE_START,
49     RMODE_WAIT_DURATION = 100,
50     RMODE_REST_DURATION = 9999999, // just rest until fully healed
51     RMODE_CONNECTIVITY,        // Pathfinding connectivity check, not running.
52 };
53 
54 /* ***********************************************************************
55  * Initialises the travel subsystem.
56  */
57 void stop_running(bool clear_delays = true);
58 void travel_init_load_level();
59 void travel_init_new_level();
60 
61 uint8_t is_waypoint(const coord_def &p);
62 command_type direction_to_command(int x, int y);
63 bool is_resting();
64 void explore_pickup_event(int did_pickup, int tried_pickup);
65 bool feat_is_traversable_now(dungeon_feature_type feat, bool try_fallback = false);
66 bool feat_is_traversable(dungeon_feature_type feat, bool try_fallback = false);
67 bool is_known_branch_id(branch_type branch);
68 bool is_unknown_stair(const coord_def &p);
69 bool is_unknown_transporter(const coord_def &p);
70 
71 void fill_travel_point_distance(const coord_def& youpos,
72                      vector<coord_def>* coords = nullptr);
73 
74 bool is_stair_exclusion(const coord_def &p);
75 
76 /* ***********************************************************************
77  * Initiates explore - the character runs around the level to map it. Note
78  * that the caller has to ensure that the level is mappable before calling
79  * start_explore. start_explore may lock up the game on unmappable levels.
80  * If grab_items is true, greedy explore is triggered - in greedy mode, explore
81  * grabs items that are eligible for autopickup and visits (previously
82  * unvisited) shops.
83  */
84 void start_explore(bool grab_items = false);
85 void do_explore_cmd();
86 
87 struct level_pos;
88 class level_id;
89 
90 level_id find_up_level(level_id curr, bool up_branch = false);
91 level_id find_down_level(level_id curr);
92 
93 void start_translevel_travel(const level_pos &pos);
94 
95 void start_travel(const coord_def& p);
96 
97 command_type travel();
98 
99 void prevent_travel_to(const string &dungeon_feature_name);
100 
101 // Sort dungeon features as appropriate.
102 int level_distance(level_id first, level_id second);
103 level_id find_deepest_explored(level_id curr);
104 bool branch_entered(branch_type branch);
105 
106 bool can_travel_to(const level_id &lid);
107 bool can_travel_interlevel();
108 
109 enum translevel_prompt_flags
110 {
111     TPF_NO_FLAGS          = 0,
112 
113     TPF_ALLOW_WAYPOINTS   = 0x1,
114     TPF_ALLOW_UPDOWN      = 0x2,
115     TPF_REMEMBER_TARGET   = 0x4,
116     TPF_SHOW_ALL_BRANCHES = 0x8,
117     TPF_SHOW_PORTALS_ONLY = 0x10,
118 
119     TPF_DEFAULT_OPTIONS   = TPF_ALLOW_WAYPOINTS | TPF_ALLOW_UPDOWN
120                                                 | TPF_REMEMBER_TARGET,
121 };
122 
123 level_pos prompt_translevel_target(int prompt_flags, string& dest_name);
124 
125 // Magic numbers for point_distance:
126 
127 // This square is a trap
128 const int PD_TRAP = -42;
129 
130 // The user never wants to travel this square
131 const int PD_EXCLUDED = -20099;
132 
133 // This square is within LOS radius of an excluded square
134 const int PD_EXCLUDED_RADIUS = -20100;
135 
136 // This square has a damaging cloud
137 const int PD_CLOUD = -20101;
138 
139 /* ***********************************************************************
140  * Array of points on the map, each value being the distance the character
141  * would have to travel to get there. Negative distances imply that the point
142  * is a) a trap or hostile terrain or b) only reachable by crossing a trap or
143  * hostile terrain.
144  * ***********************************************************************
145  * referenced in: travel - view
146  * *********************************************************************** */
147 extern travel_distance_grid_t travel_point_distance;
148 
149 enum explore_stop_type
150 {
151     ES_NONE                      = 0x00000,
152 
153     // Explored into view of an item that is NOT eligible for autopickup.
154     ES_ITEM                      = 0x00001,
155 
156     // Picked up an item during greedy explore; will stop for anything
157     // that's not explicitly ignored and that is not gold.
158     ES_GREEDY_PICKUP             = 0x00002,
159 
160     // Stop when picking up gold with greedy explore.
161     ES_GREEDY_PICKUP_GOLD        = 0x00004,
162 
163     // Picked up an item during greedy explore, ignoring items that were
164     // thrown by the PC, and items that the player already has one of in
165     // inventory, or a bunch of other conditions (see
166     // _interesting_explore_pickup in items.cc)
167     ES_GREEDY_PICKUP_SMART       = 0x00008,
168 
169     // Greedy-picked up an item previously thrown by the PC.
170     ES_GREEDY_PICKUP_THROWN      = 0x00010,
171     ES_GREEDY_PICKUP_MASK        = (ES_GREEDY_PICKUP
172                                     | ES_GREEDY_PICKUP_GOLD
173                                     | ES_GREEDY_PICKUP_SMART
174                                     | ES_GREEDY_PICKUP_THROWN),
175 
176     // Explored into view of an item eligible for autopickup.
177     ES_GREEDY_ITEM               = 0x00020,
178 
179     // Stepped onto a stack of items that was previously unknown to
180     // the player (for instance, when stepping onto the heap of items
181     // of a freshly killed monster).
182     ES_GREEDY_VISITED_ITEM_STACK = 0x00040,
183 
184     // Explored into view of a stair, shop, altar, portal, glowing
185     // item, artefact, or branch entrance.
186     ES_STAIR                     = 0x00080,
187     ES_SHOP                      = 0x00100,
188     ES_ALTAR                     = 0x00200,
189     ES_PORTAL                    = 0x00400,
190     ES_GLOWING_ITEM              = 0x00800,
191     ES_ARTEFACT                  = 0x01000,
192     ES_RUNE                      = 0x02000,
193     ES_BRANCH                    = 0x04000,
194     ES_RUNED_DOOR                = 0x08000,
195     ES_TRANSPORTER               = 0x10000,
196 };
197 
198 ////////////////////////////////////////////////////////////////////////////
199 // Structs for interlevel travel.
200 
201 // Tracks items discovered by explore in this turn.
202 class LevelStashes;
203 class explore_discoveries
204 {
205 public:
206     explore_discoveries();
207 
208     void found_feature(const coord_def &pos, dungeon_feature_type grid);
209     void found_item(const coord_def &pos, const item_def &item);
210 
211     // Reports discoveries and stops exploration (if necessary).
212     bool stop_explore() const;
213 
214 private:
215     template <class Z> struct named_thing
216     {
217         string name;
218         Z thing;
219 
named_thingnamed_thing220         named_thing(const string &n, Z t) : name(n), thing(t) { }
stringnamed_thing221         operator string () const { return name; }
222 
223         bool operator == (const named_thing<Z> &other) const
224         {
225             return name == other.name;
226         }
227     };
228 
229     bool can_autopickup;
230     int es_flags;
231     const LevelStashes *current_level;
232     vector< named_thing<item_def> > items;
233     vector< named_thing<int> > stairs;
234     vector< named_thing<int> > portals;
235     vector< named_thing<int> > shops;
236     vector< named_thing<int> > altars;
237     vector< named_thing<int> > runed_doors;
238     vector< named_thing<int> > transporters;
239 
240     vector<string> marker_msgs;
241     vector<string> marked_feats;
242 
243 private:
244     template <class C> void say_any(const C &coll, const char *category) const;
245     template <class citer> bool has_duplicates(citer, citer) const;
246 
247     string cleaned_feature_description(const coord_def &) const;
248     void add_item(const item_def &item);
249     void add_stair(const named_thing<int> &stair);
250     vector<string> apply_quantities(const vector< named_thing<int> > &v) const;
251     bool merge_feature(vector< named_thing<int> > &v,
252                        const named_thing<int> &feat) const;
253 };
254 
255 struct stair_info
256 {
257 public:
258     enum stair_type
259     {
260         PHYSICAL,
261         PLACEHOLDER,
262         MAPPED,
263     };
264 
265 public:
266     coord_def position;     // Position of stair
267     dungeon_feature_type grid; // Grid feature of the stair.
268     level_pos destination;  // The level and the position on the level this
269                             // stair leads to. This may be a guess.
270     int       distance;     // The distance travelled to reach this stair.
271     bool      guessed_pos;  // true if we're not sure that 'destination' is
272                             // correct.
273     stair_type type;
274 
stair_infostair_info275     stair_info()
276         : position(-1, -1), grid(DNGN_FLOOR), destination(),
277           distance(-1), guessed_pos(true), type(PHYSICAL)
278     {
279     }
280 
clear_distancestair_info281     void clear_distance() { distance = -1; }
282 
283     void save(writer&) const;
284     void load(reader&);
285 
286     string describe() const;
287 
can_travelstair_info288     bool can_travel() const { return type != PLACEHOLDER; }
289 };
290 
291 struct transporter_info
292 {
293 public:
294     enum transporter_type
295     {
296         PHYSICAL,
297         MAPPED,
298     };
299 
300 public:
301     coord_def position;     // Position of transporter
302     coord_def destination;  // The position on the level this transporter leads
303                             // to.
304     transporter_type type;
305 
transporter_infotransporter_info306     transporter_info(const coord_def &p, const coord_def &d,
307                      transporter_type t)
308         : position(p), destination(d), type(t) {
309     }
310 
transporter_infotransporter_info311     transporter_info()
312         : position(-1, -1), destination(), type(PHYSICAL) {
313     }
314 
315     void save(writer&) const;
316     void load(reader&);
317 };
318 
319 // Information on a level that interlevel travel needs.
320 struct LevelInfo
321 {
LevelInfoLevelInfo322     LevelInfo() : stairs(), excludes(), stair_distances(), id()
323     {
324         daction_counters.init(0);
325     }
326 
327     void save(writer&) const;
328     void load(reader&, int minorVersion);
329 
get_stairsLevelInfo330     vector<stair_info> &get_stairs()
331     {
332         return stairs;
333     }
334 
get_transportersLevelInfo335     vector<transporter_info> &get_transporters()
336     {
337         return transporters;
338     }
339 
340     stair_info *get_stair(const coord_def &pos);
341     transporter_info *get_transporter(const coord_def &pos);
342     bool empty() const;
343     bool know_stair(const coord_def &pos) const;
344     bool know_transporter(const coord_def &pos) const;
345     int get_stair_index(const coord_def &pos) const;
346     int get_transporter_index(const coord_def &pos) const;
347 
348     void clear_distances();
349     void set_level_excludes();
350 
get_excludesLevelInfo351     const exclude_set &get_excludes() const
352     {
353         return excludes;
354     }
355 
356     // Returns the travel distance between two stairs. If either stair is nullptr,
357     // or does not exist in our list of stairs, returns 0.
358     int distance_between(const stair_info *s1, const stair_info *s2) const;
359 
360     void update_excludes();
361     void update();              // Update LevelInfo to be correct for the
362                                 // current level.
363 
364     // Updates/creates a StairInfo for the stair at stairpos in grid coordinates
365     void update_stair(const coord_def& stairpos, const level_pos &p,
366                       bool guess = false);
367     void update_transporter(const coord_def& transpos, const coord_def &dest);
368 
369     // Clears all stair info for stairs matching this grid type.
370     void clear_stairs(dungeon_feature_type grid);
371 
372     // Returns true if the given branch is known to be accessible from the
373     // current level.
374     bool is_known_branch(uint8_t branch) const;
375 
376     FixedVector<int, NUM_DACTION_COUNTERS> daction_counters;
377 
378 private:
379     // Gets a list of coordinates of all player-known stairs on the current
380     // level.
381     static void get_stairs(vector<coord_def> &stairs);
382     static void get_transporters(vector<coord_def> &transporters);
383 
384     void correct_stair_list(const vector<coord_def> &s);
385     void correct_transporter_list(const vector<coord_def> &s);
386     void update_stair_distances();
387     void sync_all_branch_stairs();
388     void sync_branch_stairs(const stair_info *si);
389     void set_distance_between_stairs(int a, int b, int dist);
390     void fixup();
391 
392 private:
393     vector<stair_info> stairs;
394     vector<transporter_info> transporters;
395 
396     // Squares that are not safe to travel to.
397     exclude_set excludes;
398 
399     vector<short> stair_distances;  // Dist between stairs
400     level_id id;
401 
402     friend class TravelCache;
403 
404 private:
405     void create_placeholder_stair(const coord_def &, const level_pos &);
406     void resize_stair_distances();
407 };
408 
409 const int TRAVEL_WAYPOINT_COUNT = 10;
410 // Tracks all levels that the player has seen.
411 class TravelCache
412 {
413 public:
414     void clear_distances();
415 
get_level_info(const level_id & lev)416     LevelInfo& get_level_info(const level_id &lev)
417     {
418         LevelInfo &li = levels[lev];
419         li.id = lev;
420         return li;
421     }
422 
find_level_info(const level_id & lev)423     LevelInfo *find_level_info(const level_id &lev)
424     {
425         map<level_id, LevelInfo>::iterator i = levels.find(lev);
426         return i != levels.end()? &i->second : nullptr;
427     }
428 
erase_level_info(const level_id & lev)429     void erase_level_info(const level_id& lev)
430     {
431         levels.erase(lev);
432     }
433 
434     bool know_stair(const coord_def &c);
435     bool know_transporter(const coord_def &c);
know_level(const level_id & lev)436     bool know_level(const level_id &lev) const
437     {
438         return levels.count(lev);
439     }
440     vector<level_id> known_levels() const;
441 
get_waypoint(int number)442     const level_pos &get_waypoint(int number) const
443     {
444         return waypoints[number];
445     }
446 
447     int get_waypoint_count() const;
448 
449     void set_level_excludes();
450 
451     void add_waypoint(int x = -1, int y = -1);
452     void set_waypoint(int waynum, int x, int y);
453     void delete_waypoint();
454     uint8_t is_waypoint(const level_pos &lp) const;
455     void list_waypoints() const;
456     void update_waypoints() const;
457 
458     void update_excludes();
459     void update();
460     void update_transporter(const coord_def &c);
461 
462     void save(writer&) const;
463     void load(reader&, int minorVersion);
464 
465     bool is_known_branch(uint8_t branch) const;
466 
467     void update_daction_counters(); // of the current level
468 
469     unsigned int query_daction_counter(daction_type c);
470     void clear_daction_counter(daction_type c);
471 
472 private:
473     void update_stone_stair(const coord_def &c);
474     void fixup_levels();
475 
476 private:
477     typedef map<level_id, LevelInfo> travel_levels_map;
478     travel_levels_map levels;
479     level_pos waypoints[TRAVEL_WAYPOINT_COUNT];
480 };
481 
482 // Handles travel and explore floodfill pathfinding. Does not do interlevel
483 // travel pathfinding directly (but is used internally by interlevel travel).
484 // * All coordinates are grid coords.
485 // * Do not reuse one travel_pathfind for different runmodes.
486 class travel_pathfind
487 {
488 public:
489     travel_pathfind();
490     virtual ~travel_pathfind();
491 
492     // Finds travel direction or explore target.
493     // If fallback_explore is set, will consider temporary obstructions like
494     // sealed doors as traversable
495     coord_def pathfind(run_mode_type rt, bool fallback_explore = false);
496 
497     // For flood-fills (explore), sets starting (seed) square.
498     void set_floodseed(const coord_def &seed, bool double_flood = false);
499 
500     // For regular travel, set starting point (usually the character's current
501     // position) and destination.
502     void set_src_dst(const coord_def &src, const coord_def &dst);
503 
504     // Set feature vector to use; if non-nullptr, also sets annotate_map to
505     // true.
506     void set_feature_vector(vector<coord_def> *features);
507 
508     // Extract features without pathfinding
509     void get_features();
510 
511     // The next square to go to to move towards the travel destination. Return
512     // value is undefined if pathfind was not called with RMODE_TRAVEL.
513     const coord_def travel_move() const;
514 
515     // Square to go to for (greedy) explore. Return value is undefined if
516     // pathfind was not called with RMODE_EXPLORE or RMODE_EXPLORE_GREEDY.
517     const coord_def explore_target() const;
518 
set_ignore_danger()519     inline void set_ignore_danger()
520     {
521         ignore_danger = true;
522     }
523 
524     // Determine if the level is fully explored, when called after pathfind().
525     int explore_status();
526 
527 protected:
528     bool is_greed_inducing_square(const coord_def &c) const;
529     bool path_examine_point(const coord_def &c);
530     virtual bool point_traverse_delay(const coord_def &c);
531     virtual bool path_flood(const coord_def &c, const coord_def &dc);
532     bool square_slows_movement(const coord_def &c);
533     void check_square_greed(const coord_def &c);
534     void good_square(const coord_def &c);
535 
536 protected:
537     static const int UNFOUND_DIST  = -30000;
538     static const int INFINITE_DIST =  INFINITE_DISTANCE;
539 
540 protected:
541     run_mode_type runmode;
542 
543     // Where pathfinding starts, and the destination. Note that dest is not
544     // relevant for explore!
545     coord_def start, dest;
546 
547     // This is the square adjacent to the starting position to move
548     // along the shortest path to the destination. Does *not* apply
549     // for explore!
550     coord_def next_travel_move;
551 
552     // True if flooding outwards from start square for explore.
553     bool floodout, double_flood;
554 
555     // Set true in the second part of a double floodfill to completely ignore
556     // hostile squares.
557     bool ignore_hostile;
558 
559     // Set to true for Tiles mode clicking, so you can move one step
560     // at a time through excluded areas and around stationary monsters.
561     bool ignore_danger;
562 
563     // If true, use magic numbers in point distance array which can be
564     // used to colour the level-map.
565     bool annotate_map;
566 
567     // Stashes on this level (needed for greedy explore and to populate the
568     // feature vector with stashes on the X level-map).
569     const LevelStashes *ls;
570 
571     // Are we greedy exploring?
572     bool need_for_greed;
573 
574     // Can we autopickup?
575     bool autopickup;
576 
577     // Targets for explore and greedy explore.
578     coord_def unexplored_place, greedy_place;
579 
580     // How far from player's location unexplored_place and greedy_place are.
581     int unexplored_dist, greedy_dist;
582 
583     const int *refdist;
584 
585     // For double-floods, the points to restart floodfill from at the end of
586     // the first flood.
587     vector<coord_def> reseed_points;
588 
589     vector<coord_def> *features;
590 
591     // List of unexplored and unreachable points.
592     set<coord_def> unreachables;
593 
594     travel_distance_col *point_distance;
595 
596     // How many points we'll consider next iteration.
597     int next_iter_points;
598 
599     // How far we've travelled from (start_x, start_y), in moves (a diagonal move
600     // is no longer than an orthogonal move).
601     int traveled_distance;
602 
603     // Which index of the circumference array are we currently looking at?
604     int circ_index;
605 
606     // Used by all instances of travel_pathfind. Happily, we do not need to be
607     // re-entrant or thread-safe.
608     static FixedVector<coord_def, GXM * GYM> circumference[2];
609 
610     // Attempt to path through temporary obstructions (like sealed doors)
611     // due to the possibility they are no longer obstructing us
612     bool try_fallback;
613 };
614 
615 extern TravelCache travel_cache;
616 
617 void do_interlevel_travel();
618 
619 // Travel from a mouse click. Take one step if not safe. Attack if adjacent.
620 // If force is true, then the player will attack empty squares/open doors.
621 #ifdef USE_TILE
622 bool click_travel_safe(const coord_def &gc);
623 int click_travel(const coord_def &gc, bool force);
624 #endif
625 
626 bool check_for_interesting_features();
627 void clear_level_target();
628 
629 void clear_travel_trail();
630 int travel_trail_index(const coord_def& gc);
631 
632 bool stairs_destination_is_excluded(const stair_info &si);
633