From 5f0573841648581363fc0ce9a33a778c40370b6f Mon Sep 17 00:00:00 2001 From: dshaligram Date: Mon, 4 Aug 2008 10:01:49 +0000 Subject: Trunk-0.4 r6764: Warn the player if interlevel travel is going to take them to a level outside the range [src,dest] (rax, doy). ^G => Esc in yesno prompts. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/branches/stone_soup-0.4@6765 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/stuff.cc | 5 +-- crawl-ref/source/travel.cc | 83 ++++++++++++++++++++++++++++++++++++++++++++++ crawl-ref/source/travel.h | 8 +++++ 3 files changed, 94 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc index 3406decaa9..67f50b723f 100644 --- a/crawl-ref/source/stuff.cc +++ b/crawl-ref/source/stuff.cc @@ -1008,7 +1008,8 @@ bool yesno( const char *str, bool safe, int safeanswer, bool clear_after, tmp = map->find(tmp)->second; if (safeanswer - && (tmp == ' ' || tmp == 27 || tmp == '\r' || tmp == '\n')) + && (tmp == ' ' || tmp == ESCAPE || tmp == CONTROL('G') + || tmp == '\r' || tmp == '\n')) { tmp = safeanswer; } @@ -1103,7 +1104,7 @@ int yesnoquit( const char* str, bool safe, int safeanswer, bool allow_all, int tmp = getchm(KC_CONFIRM); - if (tmp == CK_ESCAPE || tmp == 'q' || tmp == 'Q') + if (tmp == CK_ESCAPE || tmp == CONTROL('G') || tmp == 'q' || tmp == 'Q') return -1; if ((tmp == ' ' || tmp == '\r' || tmp == '\n') && safeanswer) diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc index da2685d2e0..058cbf7d22 100644 --- a/crawl-ref/source/travel.cc +++ b/crawl-ref/source/travel.cc @@ -93,6 +93,10 @@ static level_id last_stair; // Where travel wants to get to. static travel_target level_target; +// How many stairs there are between the source and destination of +// interlevel travel, as estimated by level_distance. +static int _Src_Dest_Level_Delta = -1; + // Remember the last place explore stopped because autopickup failed. static coord_def explore_stopped_pos; @@ -123,6 +127,56 @@ const signed char FORBIDDEN = -1; // Map of terrain types that are traversable. static signed char traversable_terrain[256]; +/* + * Warn if interlevel travel is going to take you outside levels in + * the range [src,dest]. + */ +class deviant_route_warning +{ +private: + travel_target target; + bool warned; + +public: + deviant_route_warning(): target(), warned(false) + { + } + + void new_dest(const travel_target &dest); + bool warn_continue_travel(const travel_target &des, + const level_id &deviant); +}; + +void deviant_route_warning::new_dest(const travel_target &dest) +{ + if (target != dest) + { + warned = false; + target = dest; + } +} + +// Returns true if the player wants to continue travelling after the warning. +bool deviant_route_warning::warn_continue_travel( + const travel_target &dest, const level_id &deviant) +{ + // We've already prompted, don't ask again, on the player's head be it. + if (target == dest && warned) + return (true); + + target = dest; + const std::string prompt = + make_stringf("Have to go through %s. Continue?", + deviant.describe().c_str()); + // If the user says "Yes, shut up and take me there", we won't ask + // again for that destination. If the user says "No", we will + // prompt again. + cursor_control con(true); + return ((warned = yesno(prompt.c_str(), true, 'n', true, false))); +} + +static deviant_route_warning _Route_Warning; + static command_type _trans_negotiate_stairs(); static bool _find_transtravel_square(const level_pos &pos, bool verbose = true); @@ -2442,6 +2496,12 @@ void start_translevel_travel(bool prompt_for_destination) you.running = RMODE_INTERLEVEL; you.running.x = you.running.y = 0; last_stair.depth = -1; + + _Route_Warning.new_dest(level_target); + + _Src_Dest_Level_Delta = level_distance(level_id::current(), + level_target.p.id); + _start_running(); } } @@ -2760,6 +2820,29 @@ static bool _find_transtravel_square(const level_pos &target, bool verbose) if (best_stair.x != -1 && best_stair.y != -1) { + // Is this stair going offlevel? + if ((level_target.p.id != current || level_target.p.pos != best_stair) + && _Src_Dest_Level_Delta != -1) + { + // If so, is the original level closer to the target level than + // the destination of the stair? + LevelInfo &li = travel_cache.get_level_info(current); + const stair_info *dest_stair = li.get_stair(best_stair); + + if (dest_stair && dest_stair->destination.id.is_valid()) + { + const int ndist = + level_distance(dest_stair->destination.id, + level_target.p.id); + + if (_Src_Dest_Level_Delta < ndist + && !_Route_Warning.warn_continue_travel( + level_target, + dest_stair->destination.id)) + return (false); + } + } + you.running.x = best_stair.x; you.running.y = best_stair.y; return (true); diff --git a/crawl-ref/source/travel.h b/crawl-ref/source/travel.h index 752c285044..cd34eda39d 100644 --- a/crawl-ref/source/travel.h +++ b/crawl-ref/source/travel.h @@ -345,6 +345,14 @@ struct travel_target p.clear(); entrance_only = false; } + bool operator == (const travel_target &other) const + { + return p == other.p && entrance_only == other.entrance_only; + } + bool operator != (const travel_target &other) const + { + return !operator == (other); + } }; // Tracks items discovered by explore in this turn. -- cgit v1.2.3-54-g00ecf