Attached Files:
|
0001-Clean-up-stairs-commands-and-checks.patch [^] (17,200 bytes) 2013-05-23 07:59 [Show Content] [Hide Content]From 7b3933b25a426d542ddea3982aa604f7c05e1caf Mon Sep 17 00:00:00 2001
From: Zannick <jokeserver@gmail.com>
Date: Wed, 22 May 2013 22:37:08 -0700
Subject: [PATCH] Clean up stairs commands and checks.
- Tree form is checked before the delay now. (#7074)
- Tree form no longer blocks forced level-changing such as banishment,
escaping the Abyss (the lugonu ability), falling down a shaft... (#7073).
- Being turned into a tree interrupts stair travel.
- Any tolls are checked before the player stops clinging or constricting.
- Merge _up_stairs and _down_stairs in main.cc into one function, with
some helper functions for checks and prompts.
- Moved some duplicate checks from up_stairs and down_stairs into a
helper function.
- Removed redundant or invalid checks.
---
crawl-ref/source/main.cc | 210 +++++++++++++++++------------------------
crawl-ref/source/stairs.cc | 118 +++++++++--------------
crawl-ref/source/transform.cc | 3 +-
3 files changed, 136 insertions(+), 195 deletions(-)
diff --git a/crawl-ref/source/main.cc b/crawl-ref/source/main.cc
index 0ac1ece..889b103 100644
--- a/crawl-ref/source/main.cc
+++ b/crawl-ref/source/main.cc
@@ -1373,17 +1373,75 @@ static void _input()
crawl_state.clear_god_acting();
}
-static bool _stairs_check_mesmerised()
+static bool _can_take_stairs(dungeon_feature_type ftype, bool down,
+ bool known_shaft)
{
+ // Immobile
+ if (you.form == TRAN_TREE)
+ {
+ canned_msg(MSG_CANNOT_MOVE);
+ return false;
+ }
+
+ // Mesmerized
if (you.beheld() && !you.confused())
{
const monster* beholder = you.get_any_beholder();
mprf("You cannot move away from %s!",
beholder->name(DESC_THE, true).c_str());
- return true;
+ return false;
}
- return false;
+ // Held
+ if (you.attribute[ATTR_HELD])
+ {
+ mprf("You can't use stairs while %s.", held_status());
+ return false;
+ }
+
+ // Up and down both work for shops and portals.
+ if (ftype == DNGN_ENTER_SHOP)
+ {
+ if (you.berserk())
+ canned_msg(MSG_TOO_BERSERK);
+ else
+ shop();
+ // Even though we may have "succeeded", return false so we don't keep
+ // trying to go downstairs.
+ return false;
+ }
+
+ // If it's not bidirectional, check that the player is headed
+ // in the right direction.
+ if (!feat_is_bidirectional_portal(ftype))
+ {
+ if (feat_stair_direction(ftype) != (down ? CMD_GO_DOWNSTAIRS
+ : CMD_GO_UPSTAIRS)
+ // probably shouldn't be passed known_shaft=true
+ // if going up, but just in case...
+ && (!down || !known_shaft))
+ {
+ if (ftype == DNGN_STONE_ARCH)
+ mpr("There is nothing on the other side of the stone arch.");
+ else if (ftype == DNGN_ABANDONED_SHOP)
+ mpr("This shop appears to be closed.");
+ else if (down)
+ mpr("You can't go down here!");
+ else
+ mpr("You can't go up here!");
+ return false;
+ }
+ }
+
+ // Overloaded, can't go up stairs.
+ if (!down && you.burden_state == BS_OVERLOADED
+ && !feat_is_escape_hatch(ftype) && !feat_is_gate(ftype))
+ {
+ mpr("You are carrying too much to climb upwards.");
+ return false;
+ }
+
+ return true;
}
static bool _marker_vetoes_stair()
@@ -1431,76 +1489,36 @@ static bool _prompt_unique_pan_rune(dungeon_feature_type ygrd)
return true;
}
-static void _go_downstairs();
-static void _go_upstairs()
+static bool _prompt_stairs(dungeon_feature_type ygrd, bool down)
{
- ASSERT(!crawl_state.game_is_arena() && !crawl_state.arena_suspended);
-
- const dungeon_feature_type ygrd = grd(you.pos());
-
- if (_stairs_check_mesmerised())
- return;
-
- if (you.attribute[ATTR_HELD])
- {
- mprf("You can't use stairs while %s.", held_status());
- return;
- }
-
- if (ygrd == DNGN_ENTER_SHOP)
- {
- if (you.berserk())
- canned_msg(MSG_TOO_BERSERK);
- else
- shop();
- return;
- }
- // Up and down both work for portals.
- else if (feat_is_bidirectional_portal(ygrd))
- ;
- else if (feat_stair_direction(ygrd) != CMD_GO_UPSTAIRS)
- {
- if (ygrd == DNGN_STONE_ARCH)
- mpr("There is nothing on the other side of the stone arch.");
- else if (ygrd == DNGN_ABANDONED_SHOP)
- mpr("This shop appears to be closed.");
- else
- mpr("You can't go up here!");
- return;
- }
-
- if (!you.attempt_escape()) // false means constricted and don't escape
- return;
-
+ // Certain portal types always carry warnings.
if (!_prompt_dangerous_portal(ygrd))
- return;
+ return false;
// Does the next level have a warning annotation?
+ // Also checks for entering a labyrinth with teleportitis.
if (!check_annotation_exclusion_warning())
- return;
+ return false;
+ // Toll portals, eg. troves, ziggurats. (Using vetoes like this is hacky.)
if (_marker_vetoes_stair())
- return;
-
- if (you.burden_state == BS_OVERLOADED && !feat_is_escape_hatch(ygrd)
- && !feat_is_gate(ygrd))
- {
- mpr("You are carrying too much to climb upwards.");
- return;
- }
+ return false;
+ // Exiting Ziggurats early.
if (ygrd == DNGN_EXIT_PORTAL_VAULT
&& player_in_branch(BRANCH_ZIGGURAT)
&& you.depth < brdepth[BRANCH_ZIGGURAT])
{
if (!yesno("Are you sure you want to leave this Ziggurat?"))
- return;
+ return false;
}
+ // Leaving Pan runes behind.
if (!_prompt_unique_pan_rune(ygrd))
- return;
+ return false;
- if (ygrd == DNGN_EXIT_DUNGEON && !player_has_orb())
+ // Escaping.
+ if (!down && ygrd == DNGN_EXIT_DUNGEON && !player_has_orb())
{
string prompt = make_stringf("Are you sure you want to leave the "
"Dungeon?%s",
@@ -1509,81 +1527,29 @@ static void _go_upstairs()
if (!yesno(prompt.c_str(), false, 'n'))
{
mpr("Alright, then stay!");
- return;
+ return false;
}
}
- you.clear_clinging();
- you.stop_constricting_all(true);
- you.stop_being_constricted();
-
- tag_followers(); // Only those beside us right now can follow.
- start_delay(DELAY_ASCENDING_STAIRS,
- 1 + (you.burden_state > BS_UNENCUMBERED));
+ return true;
}
-static void _go_downstairs()
+static void _take_stairs(bool down)
{
ASSERT(!crawl_state.game_is_arena() && !crawl_state.arena_suspended);
const dungeon_feature_type ygrd = grd(you.pos());
- const bool shaft = (get_trap_type(you.pos()) == TRAP_SHAFT
- && ygrd != DNGN_UNDISCOVERED_TRAP);
+ const bool shaft = (down && get_trap_type(you.pos()) == TRAP_SHAFT
+ && ygrd != DNGN_UNDISCOVERED_TRAP);
- if (_stairs_check_mesmerised())
+ if (!_can_take_stairs(ygrd, down, shaft))
return;
- // Up and down both work for shops.
- if (ygrd == DNGN_ENTER_SHOP)
- {
- if (you.berserk())
- canned_msg(MSG_TOO_BERSERK);
- else
- shop();
- return;
- }
- // Up and down both work for portals.
- else if (feat_is_bidirectional_portal(ygrd))
- ;
- else if (feat_stair_direction(ygrd) != CMD_GO_DOWNSTAIRS
- && !shaft)
- {
- if (ygrd == DNGN_STONE_ARCH)
- mpr("There is nothing on the other side of the stone arch.");
- else if (ygrd == DNGN_ABANDONED_SHOP)
- mpr("This shop appears to be closed.");
- else
- mpr("You can't go down here!");
- return;
- }
-
- if (you.attribute[ATTR_HELD])
- {
- mprf("You can't use stairs while %s.", held_status());
- return;
- }
-
if (!you.attempt_escape()) // false means constricted and don't escape
return;
- if (!_prompt_dangerous_portal(ygrd))
- return;
-
- // Does the next level have a warning annotation?
- // Also checks for entering a labyrinth with teleportitis.
- if (!check_annotation_exclusion_warning())
- return;
-
- if (ygrd == DNGN_EXIT_PORTAL_VAULT
- && player_in_branch(BRANCH_ZIGGURAT)
- && you.depth < brdepth[BRANCH_ZIGGURAT])
- {
- if (!yesno("Are you sure you want to leave this Ziggurat?"))
- return;
- }
-
- if (!_prompt_unique_pan_rune(ygrd))
+ if (!_prompt_stairs(ygrd, down))
return;
you.clear_clinging();
@@ -1594,11 +1560,8 @@ static void _go_downstairs()
start_delay(DELAY_DESCENDING_STAIRS, 0);
else
{
- if (_marker_vetoes_stair())
- return;
-
tag_followers(); // Only those beside us right now can follow.
- start_delay(DELAY_DESCENDING_STAIRS,
+ start_delay(down ? DELAY_DESCENDING_STAIRS : DELAY_ASCENDING_STAIRS,
1 + (you.burden_state > BS_UNENCUMBERED));
}
}
@@ -1910,9 +1873,12 @@ void process_command(command_type cmd)
#endif
case CMD_REST: _do_rest(); break;
- case CMD_GO_UPSTAIRS: _go_upstairs(); break;
- case CMD_GO_DOWNSTAIRS: _go_downstairs(); break;
- case CMD_OPEN_DOOR: _open_door(0, 0); break;
+ case CMD_GO_UPSTAIRS:
+ case CMD_GO_DOWNSTAIRS:
+ _take_stairs(cmd == CMD_GO_DOWNSTAIRS);
+ break;
+
+ case CMD_OPEN_DOOR: _open_door(0, 0); break;
case CMD_CLOSE_DOOR: _close_door(coord_def(0, 0)); break;
// Repeat commands.
diff --git a/crawl-ref/source/stairs.cc b/crawl-ref/source/stairs.cc
index b7f1262..377830e 100644
--- a/crawl-ref/source/stairs.cc
+++ b/crawl-ref/source/stairs.cc
@@ -311,42 +311,49 @@ static void _update_travel_cache(const level_id& old_level,
}
}
+// These checks are probably unnecessary.
+static bool _check_stairs(const dungeon_feature_type ftype, bool down = false)
+{
+ // If it's not bidirectional, check that the player is headed
+ // in the right direction.
+ if (!feat_is_bidirectional_portal(ftype))
+ {
+ if (feat_stair_direction(ftype) != (down ? CMD_GO_DOWNSTAIRS
+ : CMD_GO_UPSTAIRS))
+ {
+ if (ftype == DNGN_STONE_ARCH)
+ mpr("There is nothing on the other side of the stone arch.");
+ else if (ftype == DNGN_ABANDONED_SHOP)
+ mpr("This shop appears to be closed.");
+ else if (down)
+ mpr("You can't go down here!");
+ else
+ mpr("You can't go up here!");
+ return false;
+ }
+ }
+
+ return true;
+}
+
void up_stairs(dungeon_feature_type force_stair)
{
dungeon_feature_type stair_find = (force_stair ? force_stair
: grd(you.pos()));
const level_id old_level = level_id::current();
- if (you.form == TRAN_TREE)
- {
- canned_msg(MSG_CANNOT_MOVE);
- return;
- }
-
- // Up and down both work for shops.
- if (stair_find == DNGN_ENTER_SHOP)
- {
- shop();
- return;
- }
-
// Up and down both work for portals.
+ // Canonicalize the direction; hell exits into the vestibule are handled
+ // by up_stairs; everything else by down_stairs.
if (feat_is_bidirectional_portal(stair_find))
{
if (!(stair_find == DNGN_ENTER_HELL && player_in_hell()))
return down_stairs(force_stair);
}
- // Probably still need this check here (teleportation) -- bwr
- else if (feat_stair_direction(stair_find) != CMD_GO_UPSTAIRS)
- {
- if (stair_find == DNGN_STONE_ARCH)
- mpr("There is nothing on the other side of the stone arch.");
- else if (stair_find == DNGN_ABANDONED_SHOP)
- mpr("This shop appears to be closed.");
- else
- mpr("You can't go up here.");
+
+ // Only check the current position for a legal stair traverse.
+ if (!force_stair && !_check_stairs(stair_find))
return;
- }
if (_stair_moves_pre(stair_find))
return;
@@ -635,6 +642,7 @@ static void _maybe_destroy_trap(const coord_def &p)
trap->destroy(true);
}
+// TODO(Zannick): Fully merge with up_stairs into take_stairs.
void down_stairs(dungeon_feature_type force_stair)
{
const level_id old_level = level_id::current();
@@ -642,79 +650,45 @@ void down_stairs(dungeon_feature_type force_stair)
const dungeon_feature_type stair_find =
force_stair ? force_stair : old_feat;
- const bool shaft = (!force_stair
- && get_trap_type(you.pos()) == TRAP_SHAFT
- || force_stair == DNGN_TRAP_NATURAL);
+ // Taking a shaft manually
+ const bool known_shaft = (!force_stair
+ && get_trap_type(you.pos()) == TRAP_SHAFT
+ && stair_find != DNGN_UNDISCOVERED_TRAP);
+ // Latter case is falling down a shaft.
+ const bool shaft = known_shaft || (force_stair == DNGN_TRAP_NATURAL);
level_id shaft_dest;
- if (you.form == TRAN_TREE)
- {
- canned_msg(MSG_CANNOT_MOVE);
- return;
- }
-
- // Up and down both work for shops.
- if (stair_find == DNGN_ENTER_SHOP)
- {
- shop();
- return;
- }
-
// Up and down both work for portals.
+ // Canonicalize the direction; hell exits into the vestibule are handled
+ // by up_stairs; everything else by down_stairs.
if (feat_is_bidirectional_portal(stair_find))
{
if (stair_find == DNGN_ENTER_HELL && player_in_hell())
return up_stairs(force_stair);
}
- // Probably still need this check here (teleportation) -- bwr
- else if (feat_stair_direction(stair_find) != CMD_GO_DOWNSTAIRS && !shaft)
- {
- if (stair_find == DNGN_STONE_ARCH)
- mpr("There is nothing on the other side of the stone arch.");
- else if (stair_find == DNGN_ABANDONED_SHOP)
- mpr("This shop appears to be closed.");
- else
- mpr("You can't go down here!");
- return;
- }
-
- if (stair_find > DNGN_ENTER_LABYRINTH
- && stair_find <= DNGN_ESCAPE_HATCH_DOWN
- && player_in_branch(BRANCH_VESTIBULE_OF_HELL))
- {
- // Down stairs in vestibule are one-way!
- // This doesn't make any sense. Why would there be any down stairs
- // in the Vestibule? {due, 9/2010}
- mpr("A mysterious force prevents you from descending the staircase.");
- return;
- }
- if (stair_find == DNGN_STONE_ARCH)
- {
- mpr("There is nothing on the other side of the stone arch.");
+ // Only check the current position for a legal stair traverse.
+ // If it's a known shaft that we're taking, then we're already good.
+ if (!known_shaft && !_check_stairs(stair_find, true))
return;
- }
if (_stair_moves_pre(stair_find))
return;
if (shaft)
{
- const bool known_trap = (grd(you.pos()) != DNGN_UNDISCOVERED_TRAP
- && !force_stair);
-
if (!is_valid_shaft_level())
{
- if (known_trap)
+ if (known_shaft)
mpr("The shaft disappears in a puff of logic!");
_maybe_destroy_trap(you.pos());
return;
}
- shaft_dest = you.shaft_dest(known_trap);
+ shaft_dest = you.shaft_dest(known_shaft);
if (shaft_dest == level_id::current())
{
- if (known_trap)
+ if (known_shaft)
{
mpr("Strange, the shaft seems to lead back to this level.");
mpr("The strain on the space-time continuum destroys the "
@@ -724,7 +698,7 @@ void down_stairs(dungeon_feature_type force_stair)
return;
}
- if (!known_trap && shaft_dest.depth - you.depth > 1)
+ if (!known_shaft && shaft_dest.depth - you.depth > 1)
{
mark_milestone("shaft", "fell down a shaft to "
+ short_place_name(shaft_dest) + ".");
diff --git a/crawl-ref/source/transform.cc b/crawl-ref/source/transform.cc
index dbed059..f966a93 100644
--- a/crawl-ref/source/transform.cc
+++ b/crawl-ref/source/transform.cc
@@ -1107,7 +1107,8 @@ bool transform(int pow, transformation_type which_trans, bool force,
// This only has an effect if the transformation happens passively,
// for example if Xom decides to transform you while you're busy
// running around or butchering corpses.
- stop_delay();
+ // If you're turned into a tree, you stop taking stairs.
+ stop_delay(which_trans == TRAN_TREE);
if (crawl_state.which_god_acting() == GOD_XOM)
you.transform_uncancellable = true;
--
1.7.4.4
0002-Merge-up_stairs-and-down_stairs-into-take_stairs.patch [^] (38,946 bytes) 2015-01-27 04:54 [Show Content] [Hide Content]From 58322f74cec90cc2ade1c788d972e267d202e8d2 Mon Sep 17 00:00:00 2001
From: Zannick <jokeserver@gmail.com>
Date: Mon, 26 Jan 2015 19:34:04 -0800
Subject: [PATCH] Merge up_stairs and down_stairs into take_stairs.
A handful of inconsistencies between the two old functions are left in
(but obviously more noticeable) to avoid making this too much of a
change in actual behavior.
Actual behavior changed:
- End searing ray when moving up as well as down.
- The player can no longer trip down a shaft while confused.
- Don't mark a milestone that the player took an exit from Pan into
the Abyss when they got banished standing on the exit instead.
Other code changes:
- Condense _player_leaves_level_upstairs and _downstairs.
- Change _check_stairs to take a bool "going_up" instead of "down",
for consistency with _climb_message (and new helper functions).
- Create a helper function _fall_down_stairs that takes care of both cases.
- Create a helper function _require_runes which performs the fancy
runelock animations.
- Create a helper function _new_level_amuses_xom, except pull the abyss
blood spatter generation out of it. It now skips the newlevel check,
but Abyss should always be new levels anyway.
- Remove the "You fly upwards" override (which mostly means taking
hatches up while flying now produces the hatch message instead).
- Move the -cTele warning later in the function as part of merging.
- Move the helper function _maybe_destroy_trap above take_stairs.
- Remove a redundant variable "stairs_taken".
- Add a ton of comments.
- up_stairs and down_stairs are left in as convenience functions that
simply call take_stairs.
---
crawl-ref/source/stairs.cc | 917 +++++++++++++++++++++-----------------------
crawl-ref/source/stairs.h | 3 +
crawl-ref/source/terrain.cc | 2 +-
3 files changed, 437 insertions(+), 485 deletions(-)
diff --git a/crawl-ref/source/stairs.cc b/crawl-ref/source/stairs.cc
index b775d1a..b69e8b9 100644
--- a/crawl-ref/source/stairs.cc
+++ b/crawl-ref/source/stairs.cc
@@ -105,10 +105,11 @@ static void _player_change_level_reset()
you.prev_grd_targ.reset();
}
-static void _player_change_level_upstairs(dungeon_feature_type feat)
+static void _player_change_level(dungeon_feature_type feat, const string &dst)
{
- level_id lev = feat ? stair_destination(feat, "", true)
- : stair_destination(you.pos(), true);
+ level_id lev = stair_destination(feat, dst, true);
+ if (!lev.is_valid())
+ die("Unknown down stair: %s", dungeon_feature_name(feat));
you.depth = lev.depth;
you.where_are_you = lev.branch;
}
@@ -118,6 +119,13 @@ static bool _marker_vetoes_level_change()
return marker_vetoes_operation("veto_level_change");
}
+static void _maybe_destroy_trap(const coord_def &p)
+{
+ trap_def* trap = find_trap(p);
+ if (trap)
+ trap->destroy(true);
+}
+
static bool _stair_moves_pre(dungeon_feature_type stair)
{
if (crawl_state.prev_cmd == CMD_WIZARD)
@@ -305,23 +313,23 @@ static void _update_travel_cache(const level_id& old_level,
}
// These checks are probably unnecessary.
-static bool _check_stairs(const dungeon_feature_type ftype, bool down = false)
+static bool _check_stairs(const dungeon_feature_type ftype, bool going_up)
{
// If it's not bidirectional, check that the player is headed
// in the right direction.
if (!feat_is_bidirectional_portal(ftype))
{
- if (feat_stair_direction(ftype) != (down ? CMD_GO_DOWNSTAIRS
- : CMD_GO_UPSTAIRS))
+ if (feat_stair_direction(ftype) != (going_up ? CMD_GO_UPSTAIRS
+ : CMD_GO_DOWNSTAIRS))
{
if (ftype == DNGN_STONE_ARCH)
mpr("There is nothing on the other side of the stone arch.");
else if (ftype == DNGN_ABANDONED_SHOP)
mpr("This shop appears to be closed.");
- else if (down)
- mpr("You can't go down here!");
- else
+ else if (going_up)
mpr("You can't go up here!");
+ else
+ mpr("You can't go down here!");
return false;
}
}
@@ -329,57 +337,277 @@ static bool _check_stairs(const dungeon_feature_type ftype, bool down = false)
return true;
}
-void up_stairs(dungeon_feature_type force_stair, bool wizard)
+static bool _fall_down_stairs(const dungeon_feature_type ftype, bool going_up)
+{
+ if (!you.airborne()
+ && you.confused()
+ && !feat_is_escape_hatch(ftype)
+ && coinflip())
+ {
+ const char* fall_where = "down the stairs";
+ if (!feat_is_staircase(ftype))
+ fall_where = "through the gate";
+
+ mprf("In your confused state, you trip and fall %s%s.",
+ going_up ? "back " : "", fall_where);
+ if (!feat_is_staircase(ftype))
+ ouch(1, KILLED_BY_FALLING_THROUGH_GATE);
+ else
+ ouch(1, KILLED_BY_FALLING_DOWN_STAIRS);
+
+ // Note that this only does damage if going downstairs;
+ // it doesn't cancel the level transition.
+ if (going_up)
+ {
+ you.turn_is_over = true;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool _require_runes(dungeon_feature_type ftype)
+{
+ if (ftype != DNGN_ENTER_VAULTS
+ && ftype != DNGN_ENTER_ZOT
+ && ftype != DNGN_ENTER_ZIGGURAT) {
+ return false;
+ }
+
+ if ((ftype == DNGN_ENTER_VAULTS
+ && is_existing_level(level_id(BRANCH_VAULTS, 1)))
+ || (ftype == DNGN_ENTER_ZOT
+ && is_existing_level(level_id(BRANCH_ZOT, 1))))
+ {
+ return false;
+ }
+
+ #define ZIG_RUNES 2
+ const int min_runes = ((ftype == DNGN_ENTER_ZOT) ? NUMBER_OF_RUNES_NEEDED :
+ (ftype == DNGN_ENTER_VAULTS) ? 1 : ZIG_RUNES);
+
+ if (runes_in_pack() < min_runes)
+ {
+ if (min_runes == 1)
+ mpr("You need a rune to enter this place.");
+ else
+ mprf("You need at least %d runes to enter this place.", min_runes);
+ return true;
+ }
+
+ // Nothing even remotely flashy for Zig.
+ if (ftype != DNGN_ENTER_ZIGGURAT) {
+ vector<int> runes;
+ for (int i = 0; i < NUM_RUNE_TYPES; i++)
+ if (you.runes[i])
+ runes.push_back(i);
+
+ ASSERT(runes.size() >= 1);
+ shuffle_array(runes);
+
+ // Zot is extra flashy.
+ if (ftype == DNGN_ENTER_ZOT) {
+ ASSERT(runes.size() >= 3);
+
+ mprf("You insert the %s rune into the lock.", rune_type_name(runes[2]));
+#ifdef USE_TILE_LOCAL
+ tiles.add_overlay(you.pos(), tileidx_zap(rune_colour(runes[2])));
+ update_screen();
+#else
+ flash_view(UA_BRANCH_ENTRY, rune_colour(runes[2]));
+#endif
+ mpr("The lock glows eerily!");
+ more();
+
+ mprf("You insert the %s rune into the lock.", rune_type_name(runes[1]));
+ big_cloud(CLOUD_BLUE_SMOKE, &you, you.pos(), 20, 7 + random2(7));
+ viewwindow();
+ mpr("Heavy smoke blows from the lock!");
+ more();
+ }
+
+ mprf("You insert the %s rune into the lock.", rune_type_name(runes[0]));
+
+ if (silenced(you.pos()))
+ mpr("The gate opens wide!");
+ else
+ mpr("With a loud hiss the gate opens wide!");
+ more();
+ }
+
+ return false;
+}
+
+static void _new_level_amuses_xom(dungeon_feature_type feat,
+ dungeon_feature_type old_feat,
+ bool shaft, int shaft_depth, bool voluntary)
+{
+ switch (you.where_are_you)
+ {
+ default:
+ // Xom thinks it's funny if you enter a new level via shaft
+ // or escape hatch, for shafts it's funnier the deeper you fell.
+ if (shaft || feat_is_escape_hatch(feat))
+ xom_is_stimulated(shaft_depth * 50);
+ else if (!is_connected_branch(you.where_are_you))
+ xom_is_stimulated(25);
+ else
+ xom_is_stimulated(10);
+ break;
+
+ case BRANCH_ZIGGURAT:
+ // The best way to die currently.
+ xom_is_stimulated(50);
+ break;
+
+ case BRANCH_LABYRINTH:
+ // Finding the way out of a labyrinth interests Xom.
+ xom_is_stimulated(75);
+ break;
+
+ case BRANCH_PANDEMONIUM:
+ xom_is_stimulated(100);
+ break;
+
+ case BRANCH_ABYSS:
+ if (voluntary && old_feat == DNGN_ENTER_ABYSS)
+ xom_is_stimulated(100, XM_INTRIGUED);
+ else
+ xom_is_stimulated(200);
+ break;
+ }
+}
+
+void take_stairs(dungeon_feature_type force_stair, bool going_up,
+ bool force_known_shaft, bool wizard)
{
- dungeon_feature_type stair_find = (force_stair ? force_stair
- : orig_terrain(you.pos()));
const level_id old_level = level_id::current();
- // Up and down both work for portals.
- // Canonicalize the direction; hell exits into the vestibule are handled
- // by up_stairs; everything else by down_stairs.
- if (feat_is_bidirectional_portal(stair_find))
+ const dungeon_feature_type old_feat = orig_terrain(you.pos());
+ dungeon_feature_type stair_find = force_stair ? force_stair : old_feat;
+
+ // Taking a shaft manually
+ const bool known_shaft = (!force_stair
+ && get_trap_type(you.pos()) == TRAP_SHAFT
+ && stair_find != DNGN_UNDISCOVERED_TRAP)
+ || (force_stair == DNGN_TRAP_SHAFT
+ && force_known_shaft);
+ // Latter case is falling down a shaft.
+ const bool shaft = known_shaft || force_stair == DNGN_TRAP_SHAFT;
+ level_id shaft_dest;
+ if (shaft)
{
- if (!(stair_find == DNGN_ENTER_HELL && player_in_hell()))
- return down_stairs(force_stair);
+ if (!is_valid_shaft_level())
+ {
+ if (known_shaft)
+ mpr("The shaft disappears in a puff of logic!");
+ _maybe_destroy_trap(you.pos());
+ return;
+ }
+
+ shaft_dest = you.shaft_dest(known_shaft);
}
+ // How far down you fall via a shaft or hatch.
+ const int shaft_depth = (shaft ? shaft_dest.depth - you.depth : 1);
+
+ // Up and down both work for some portals.
+ // Canonicalize the direction: hell exits into the vestibule are considered
+ // going up; everything else is going down. This mostly affects which way you
+ // fall if confused.
+ if (feat_is_bidirectional_portal(stair_find))
+ going_up = (stair_find == DNGN_ENTER_HELL && player_in_hell());
// Only check the current position for a legal stair traverse.
- if (!force_stair && !_check_stairs(stair_find))
+ // Check that we're going the right way (if we're not falling through
+ // a shaft or being forced).
+ if (!shaft && !force_stair && !_check_stairs(stair_find, going_up))
return;
if (_stair_moves_pre(stair_find))
return;
- if (!you.airborne()
- && you.confused()
- && !feat_is_escape_hatch(stair_find)
- && coinflip())
+ // Falling down is checked before the transition if going upstairs, since
+ // it might prevent the transition itself.
+ if (going_up && _fall_down_stairs(stair_find, going_up))
+ return;
+
+ if (shaft)
{
- const char* fall_where = "down the stairs";
- if (!feat_is_staircase(stair_find))
- fall_where = "through the gate";
+ if (shaft_dest == level_id::current())
+ {
+ if (known_shaft)
+ {
+ mpr("Strange, the shaft seems to lead back to this level.");
+ mpr("The strain on the space-time continuum destroys the "
+ "shaft!");
+ }
+ _maybe_destroy_trap(you.pos());
+ return;
+ }
- mprf("In your confused state, you trip and fall back %s.", fall_where);
- if (!feat_is_staircase(stair_find))
- ouch(1, KILLED_BY_FALLING_THROUGH_GATE);
- else
- ouch(1, KILLED_BY_FALLING_DOWN_STAIRS);
- you.turn_is_over = true;
- return;
+ if (!known_shaft)
+ {
+ mark_milestone("shaft", "fell down a shaft to "
+ + shaft_dest.describe() + ".");
+ }
+
+ handle_items_on_shaft(you.pos(), false);
+
+ string howfar;
+ if (force_stair && shaft_depth > 1)
+ howfar = make_stringf(" for %d floors", shaft_depth);
+
+ mprf("You %s a shaft%s!", you.flight_mode() ? "are sucked into"
+ : "fall through",
+ howfar.c_str());
+
+ // Shafts are one-time-use.
+ mpr("The shaft crumbles and collapses.");
+ _maybe_destroy_trap(you.pos());
}
+ // Check the player's runes and maybe perform the entry sequence.
+ if (_require_runes(stair_find))
+ return;
+
// Bail if any markers veto the move.
if (_marker_vetoes_level_change())
return;
- // Magical level changes (don't exist yet in this direction)
- // need this.
+ // All checks are done, the player is on the move now.
+
+ // Magical level changes (which currently only exist "downwards") need this.
clear_trapping_net();
+ end_searing_ray();
+
+ // Markers might be deleted when removing portals.
+ const string dst = env.markers.property_at(you.pos(), MAT_ANY, "dst");
- // Checks are done, the character is committed to moving between levels.
+ // Fire level-leaving trigger.
leaving_level_now(stair_find);
+ // Not entirely accurate - the player could die before
+ // reaching the Abyss.
+ if (!force_stair && old_feat == DNGN_ENTER_ABYSS)
+ {
+ mark_milestone("abyss.enter", "entered the Abyss!");
+ take_note(Note(NOTE_MESSAGE, 0, 0, "Voluntarily entered the Abyss."), true);
+ }
+ else if (!force_stair && old_feat == DNGN_EXIT_THROUGH_ABYSS)
+ {
+ mark_milestone("abyss.enter", "escaped (hah) into the Abyss!");
+ take_note(Note(NOTE_MESSAGE, 0, 0, "Took an exit into the Abyss."), true);
+ }
+ else if (stair_find == DNGN_EXIT_ABYSS
+ && you.char_direction != GDT_GAME_START)
+ {
+ mark_milestone("abyss.exit", "escaped from the Abyss!");
+ you.attribute[ATTR_BANISHMENT_IMMUNITY] = you.elapsed_time + 100
+ + random2(100);
+ you.banished_by = "";
+ }
+
// Interlevel travel data.
const bool collect_travel_data = can_travel_interlevel();
if (collect_travel_data)
@@ -388,6 +616,8 @@ void up_stairs(dungeon_feature_type force_stair, bool wizard)
old_level_info.update();
}
+ const coord_def stair_pos = you.pos();
+
if (stair_find == DNGN_EXIT_DUNGEON)
{
you.depth = 0;
@@ -399,48 +629,159 @@ void up_stairs(dungeon_feature_type force_stair, bool wizard)
ouch(INSTANT_DEATH, KILLED_BY_LEAVING);
}
+ if (stair_find == DNGN_ENTER_LABYRINTH || stair_find == DNGN_ENTER_ZIGGURAT)
+ dungeon_terrain_changed(you.pos(), DNGN_STONE_ARCH);
+
+ if (stair_find == DNGN_ENTER_PANDEMONIUM
+ || stair_find == DNGN_ENTER_ABYSS
+ || feat_is_portal_entrance(stair_find))
+ {
+ you.level_stack.push_back(level_pos::current());
+ }
+
+ // Actually change the player's branch and depth, along with some cleanup.
_player_change_level_reset();
- _player_change_level_upstairs(force_stair);
+ if (shaft)
+ you.depth = shaft_dest.depth;
+ else
+ _player_change_level(stair_find, dst);
+ // Some branch specific messages.
if (old_level.branch == BRANCH_VESTIBULE
&& !player_in_branch(BRANCH_VESTIBULE))
{
mpr("Thank you for visiting Hell. Please come again soon.");
}
+ if (stair_find == DNGN_EXIT_ABYSS
+ || stair_find == DNGN_EXIT_PANDEMONIUM
+ || stair_find == DNGN_EXIT_THROUGH_ABYSS)
+ {
+ mpr("You pass through the gate.");
+ take_note(Note(NOTE_MESSAGE, 0, 0,
+ stair_find == DNGN_EXIT_ABYSS ? "Escaped the Abyss" :
+ stair_find == DNGN_EXIT_PANDEMONIUM ? "Escaped Pandemonium" :
+ stair_find == DNGN_EXIT_THROUGH_ABYSS ? "Escaped into the Abyss" :
+ "Buggered into bugdom"), true);
+
+ if (!you.wizard || !crawl_state.is_replaying_keys())
+ more();
+ }
+
// Fixup exits from the Hell branches.
if (player_in_branch(BRANCH_VESTIBULE) && is_hell_subbranch(old_level.branch))
stair_find = branches[old_level.branch].entry_stairs;
- const dungeon_feature_type stair_taken = stair_find;
+ // Special messages on returning from portal vaults, Abyss, Pan, etc.
+ if (!is_connected_branch(old_level.branch)
+ && player_in_connected_branch()
+ && old_level.branch != you.where_are_you)
+ {
+ mprf("Welcome %sto %s!",
+ you.char_direction == GDT_GAME_START ? "" : "back ",
+ branches[you.where_are_you].longname);
+ }
- if (you.flight_mode() && !feat_is_gate(stair_find))
- mpr("You fly upwards.");
- else
- _climb_message(stair_find, true, old_level.branch);
+ // Falling down the stairs or portal.
+ if (!going_up && !shaft
+ && force_stair != DNGN_ENTER_ABYSS
+ && force_stair != DNGN_ABYSSAL_STAIR
+ && force_stair != DNGN_EXIT_ABYSS)
+ {
+ _fall_down_stairs(stair_find, !going_up);
+ }
- _exit_stair_message(stair_find);
+ if (shaft)
+ stair_find = DNGN_TRAP_SHAFT;
- if (old_level.branch != you.where_are_you)
+ switch (you.where_are_you)
{
- mprf("Welcome back to %s!",
- branches[you.where_are_you].longname);
- if ((brdepth[old_level.branch] > 1
- || old_level.branch == BRANCH_VESTIBULE)
- && !you.branches_left[old_level.branch])
+ case BRANCH_ABYSS:
+ // There are no abyssal stairs that go up, so this whole case is only
+ // when going down.
+ if (old_level.branch == BRANCH_ABYSS)
{
- string old_branch_string = branches[old_level.branch].longname;
- if (old_branch_string.find("The ") == 0)
- old_branch_string[0] = tolower(old_branch_string[0]);
- mark_milestone("br.exit", "left " + old_branch_string + ".",
- old_level.describe());
- you.branches_left.set(old_level.branch);
+ mprf(MSGCH_BANISHMENT, "You plunge deeper into the Abyss.");
+ break;
}
- }
+ if (!force_stair)
+ mpr("You enter the Abyss!");
- const coord_def stair_pos = you.pos();
+ mpr("To return, you must find a gate leading back.");
+ if (you_worship(GOD_CHEIBRIADOS))
+ {
+ mprf(MSGCH_GOD, GOD_CHEIBRIADOS,
+ "You feel Cheibriados slowing down the madness of this place.");
+ }
- load_level(stair_taken, LOAD_ENTER_LEVEL, old_level);
+ // Re-entering the Abyss halves accumulated speed.
+ you.abyss_speed /= 2;
+ learned_something_new(HINT_ABYSS);
+ break;
+
+ case BRANCH_PANDEMONIUM:
+ if (old_level.branch == BRANCH_PANDEMONIUM)
+ mpr("You pass into a different region of Pandemonium.");
+ break;
+
+ default:
+ // This hits both cases.
+ if (!shaft)
+ _climb_message(stair_find, going_up, old_level.branch);
+ break;
+ }
+
+ // An extra message from using this particular stair (e.g. hatches).
+ if (!shaft)
+ _exit_stair_message(stair_find);
+
+ // Did we enter a new branch?
+ if (!player_in_branch(old_level.branch))
+ {
+ const branch_type branch = you.where_are_you;
+
+ if (going_up)
+ {
+ mprf("Welcome back to %s!", branches[branch].longname);
+
+ // Left a notable branch for the first time.
+ if ((brdepth[old_level.branch] > 1
+ || old_level.branch == BRANCH_VESTIBULE)
+ && !you.branches_left[old_level.branch])
+ {
+ string old_branch_string = branches[old_level.branch].longname;
+ if (old_branch_string.find("The ") == 0)
+ old_branch_string[0] = tolower(old_branch_string[0]);
+ mark_milestone("br.exit", "left " + old_branch_string + ".",
+ old_level.describe());
+ you.branches_left.set(old_level.branch);
+ }
+ }
+ else
+ {
+ // Entered a branch (including portals) through the front door.
+ if (stair_find == branches[branch].entry_stairs)
+ {
+ if (branches[branch].entry_message)
+ mpr(branches[branch].entry_message);
+ else
+ mprf("Welcome to %s!", branches[branch].longname);
+ }
+
+ // Entered a regular (non-portal) branch from above.
+ if (parent_branch(branch) == old_level.branch)
+ enter_branch(branch, old_level);
+ }
+ }
+
+ const bool newlevel = load_level(stair_find, LOAD_ENTER_LEVEL, old_level);
+
+ if (newlevel)
+ _new_level_amuses_xom(stair_find, old_feat, shaft, shaft_depth, !force_stair);
+
+ // This should maybe go in load_level?
+ if (you.where_are_you == BRANCH_ABYSS)
+ generate_random_blood_spatter_on_level();
you.turn_is_over = true;
@@ -448,20 +789,49 @@ void up_stairs(dungeon_feature_type force_stair, bool wizard)
new_level();
+ // Dunno why this is on going down only.
+ if (!going_up)
+ {
+ moveto_location_effects(old_feat);
+
+ // Clear list of beholding and constricting/constricted monsters.
+ you.clear_beholders();
+ you.clear_fearmongers();
+ you.stop_constricting_all();
+ you.stop_being_constricted();
+
+ trackers_init_new_level(true);
+ }
+
if (!wizard)
_update_travel_cache(old_level, stair_pos);
+ if (!allow_control_teleport(true))
+ mprf(MSGCH_WARN, "You sense a powerful magical force warping space.");
+
// Preventing obvious finding of stairs at your position.
env.map_seen.set(you.pos());
viewwindow();
- seen_monsters_react();
-
- if (!allow_control_teleport(true))
- mprf(MSGCH_WARN, "You sense a powerful magical force warping space.");
+ // There's probably a reason for this. I don't know it.
+ if (going_up)
+ seen_monsters_react();
+ else
+ maybe_update_stashes();
request_autopickup();
+
+ // Zotdef: returning from portals (e.g. bazaar) paralyses the player in
+ // place for 5 moves. Nasty, but punishes players for using portals as
+ // quick-healing stopovers.
+ if (!going_up && crawl_state.game_is_zotdef())
+ start_delay(DELAY_UNINTERRUPTIBLE, 5);
+}
+
+void up_stairs(dungeon_feature_type force_stair, bool wizard)
+{
+ take_stairs(force_stair, true, false, wizard);
}
// Find the other end of the stair or portal at location pos on the current
@@ -611,432 +981,11 @@ level_id stair_destination(dungeon_feature_type feat, const string &dst,
return level_id();
}
-static void _player_change_level_downstairs(dungeon_feature_type stair_find,
- const string &dst)
-{
- level_id lev = stair_destination(stair_find, dst, true);
- if (!lev.is_valid())
- die("Unknown down stair: %s", dungeon_feature_name(stair_find));
- you.depth = lev.depth;
- you.where_are_you = lev.branch;
-}
-
-static void _maybe_destroy_trap(const coord_def &p)
-{
- trap_def* trap = find_trap(p);
- if (trap)
- trap->destroy(true);
-}
-
// TODO(Zannick): Fully merge with up_stairs into take_stairs.
void down_stairs(dungeon_feature_type force_stair, bool force_known_shaft,
bool wizard)
{
- const level_id old_level = level_id::current();
- const dungeon_feature_type old_feat = orig_terrain(you.pos());
- const dungeon_feature_type stair_find =
- force_stair ? force_stair : old_feat;
-
- // Taking a shaft manually
- const bool known_shaft = (!force_stair
- && get_trap_type(you.pos()) == TRAP_SHAFT
- && stair_find != DNGN_UNDISCOVERED_TRAP)
- || (force_stair == DNGN_TRAP_SHAFT
- && force_known_shaft);
- // Latter case is falling down a shaft.
- const bool shaft = known_shaft || force_stair == DNGN_TRAP_SHAFT;
- level_id shaft_dest;
-
- // Up and down both work for portals.
- // Canonicalize the direction; hell exits into the vestibule are handled
- // by up_stairs; everything else by down_stairs.
- if (feat_is_bidirectional_portal(stair_find))
- {
- if (stair_find == DNGN_ENTER_HELL && player_in_hell())
- return up_stairs(force_stair);
- }
-
- // Only check the current position for a legal stair traverse.
- // If it's a shaft that we're taking, then we're already good.
- if (!shaft && !_check_stairs(stair_find, true))
- return;
-
- if (_stair_moves_pre(stair_find))
- return;
-
- if (shaft)
- {
- if (!is_valid_shaft_level())
- {
- if (known_shaft)
- mpr("The shaft disappears in a puff of logic!");
- _maybe_destroy_trap(you.pos());
- return;
- }
-
- shaft_dest = you.shaft_dest(known_shaft);
- }
- const int shaft_depth = (shaft ? shaft_dest.depth - you.depth : 1);
- if (shaft)
- {
- if (shaft_dest == level_id::current())
- {
- if (known_shaft)
- {
- mpr("Strange, the shaft seems to lead back to this level.");
- mpr("The strain on the space-time continuum destroys the "
- "shaft!");
- }
- _maybe_destroy_trap(you.pos());
- return;
- }
-
- if (!known_shaft)
- {
- mark_milestone("shaft", "fell down a shaft to "
- + shaft_dest.describe() + ".");
- }
-
- handle_items_on_shaft(you.pos(), false);
-
- string howfar;
- if (force_stair && shaft_depth > 1)
- howfar = make_stringf(" for %d floors", shaft_depth);
-
- mprf("You %s a shaft%s!", you.flight_mode() ? "are sucked into"
- : "fall through",
- howfar.c_str());
-
- // Shafts are one-time-use.
- mpr("The shaft crumbles and collapses.");
- _maybe_destroy_trap(you.pos());
- }
-
- if (stair_find == DNGN_ENTER_VAULTS
- && !is_existing_level(level_id(BRANCH_VAULTS, 1)))
- {
- if (!runes_in_pack())
- {
- mpr("You need a rune to enter this place.");
- return;
- }
-
- for (int i = 0; i < NUM_RUNE_TYPES; i++)
- if (you.runes[i])
- {
- mprf("You insert the %s rune into the lock.",
- rune_type_name(i));
- break;
- }
-
- if (silenced(you.pos()))
- mpr("The gate opens wide!");
- else
- mpr("With a loud hiss the gate opens wide!");
- more();
- }
-
- if (stair_find == DNGN_ENTER_ZOT
- && !is_existing_level(level_id(BRANCH_ZOT, 1)))
- {
- vector<int> runes;
- for (int i = 0; i < NUM_RUNE_TYPES; i++)
- if (you.runes[i])
- runes.push_back(i);
-
- if (runes.size() < NUMBER_OF_RUNES_NEEDED)
- {
- mprf("You need at least %d runes to enter this place.",
- NUMBER_OF_RUNES_NEEDED);
- return;
- }
-
- ASSERT(runes.size() >= 3);
-
- shuffle_array(runes);
- mprf("You insert the %s rune into the lock.", rune_type_name(runes[0]));
-#ifdef USE_TILE_LOCAL
- tiles.add_overlay(you.pos(), tileidx_zap(rune_colour(runes[0])));
- update_screen();
-#else
- flash_view(UA_BRANCH_ENTRY, rune_colour(runes[0]));
-#endif
- mpr("The lock glows eerily!");
- more();
-
- mprf("You insert the %s rune into the lock.", rune_type_name(runes[1]));
- big_cloud(CLOUD_BLUE_SMOKE, &you, you.pos(), 20, 7 + random2(7));
- viewwindow();
- mpr("Heavy smoke blows from the lock!");
- more();
-
- mprf("You insert the %s rune into the lock.", rune_type_name(runes[2]));
-
- if (silenced(you.pos()))
- mpr("The gate opens wide!");
- else
- mpr("With a loud hiss the gate opens wide!");
- more();
-
- }
-
- if (stair_find == DNGN_ENTER_ZIGGURAT)
- {
- #define ZIG_RUNES 2
- if (runes_in_pack() < ZIG_RUNES)
- {
- mprf("You need at least %d runes to enter this place.", ZIG_RUNES);
- return;
- }
- }
-
- // Bail if any markers veto the move.
- if (_marker_vetoes_level_change())
- return;
-
- // All checks are done, the player is on the move now.
-
- // Magical level changes (Portal, Banishment) need this.
- clear_trapping_net();
- end_searing_ray();
-
- // Markers might be deleted when removing portals.
- const string dst = env.markers.property_at(you.pos(), MAT_ANY, "dst");
-
- // Fire level-leaving trigger.
- leaving_level_now(stair_find);
-
- // Not entirely accurate - the player could die before
- // reaching the Abyss.
- if (!force_stair && old_feat == DNGN_ENTER_ABYSS)
- {
- mark_milestone("abyss.enter", "entered the Abyss!");
- take_note(Note(NOTE_MESSAGE, 0, 0, "Voluntarily entered the Abyss."), true);
- }
- else if (old_feat == DNGN_EXIT_THROUGH_ABYSS)
- {
- mark_milestone("abyss.enter", "escaped (hah) into the Abyss!");
- take_note(Note(NOTE_MESSAGE, 0, 0, "Took an exit into the Abyss."), true);
- }
- else if (stair_find == DNGN_EXIT_ABYSS
- && you.char_direction != GDT_GAME_START)
- {
- mark_milestone("abyss.exit", "escaped from the Abyss!");
- you.attribute[ATTR_BANISHMENT_IMMUNITY] = you.elapsed_time + 100
- + random2(100);
- you.banished_by = "";
- }
-
- // Interlevel travel data.
- const bool collect_travel_data = can_travel_interlevel();
- if (collect_travel_data)
- {
- LevelInfo &old_level_info = travel_cache.get_level_info(old_level);
- old_level_info.update();
- }
- const coord_def stair_pos = you.pos();
-
- if (stair_find == DNGN_ENTER_LABYRINTH || stair_find == DNGN_ENTER_ZIGGURAT)
- dungeon_terrain_changed(you.pos(), DNGN_STONE_ARCH);
-
- if (stair_find == DNGN_ENTER_PANDEMONIUM
- || stair_find == DNGN_ENTER_ABYSS
- || feat_is_portal_entrance(stair_find))
- {
- you.level_stack.push_back(level_pos::current());
- }
-
- _player_change_level_reset();
- if (shaft)
- you.depth = shaft_dest.depth;
- else
- _player_change_level_downstairs(stair_find, dst);
-
- if (stair_find == DNGN_EXIT_ABYSS
- || stair_find == DNGN_EXIT_PANDEMONIUM
- || stair_find == DNGN_EXIT_THROUGH_ABYSS)
- {
- mpr("You pass through the gate.");
- take_note(Note(NOTE_MESSAGE, 0, 0,
- stair_find == DNGN_EXIT_ABYSS ? "Escaped the Abyss" :
- stair_find == DNGN_EXIT_PANDEMONIUM ? "Escaped Pandemonium" :
- stair_find == DNGN_EXIT_THROUGH_ABYSS ? "Escaped into the Abyss" :
- "Buggered into bugdom"), true);
-
- if (!you.wizard || !crawl_state.is_replaying_keys())
- more();
- }
-
- if (!is_connected_branch(old_level.branch)
- && player_in_connected_branch()
- && old_level.branch != you.where_are_you)
- {
- mprf("Welcome %sto %s!",
- you.char_direction == GDT_GAME_START ? "" : "back ",
- branches[you.where_are_you].longname);
- }
-
- if (!you.airborne()
- && you.confused()
- && !feat_is_escape_hatch(stair_find)
- && force_stair != DNGN_ENTER_ABYSS
- && force_stair != DNGN_ABYSSAL_STAIR
- && force_stair != DNGN_EXIT_ABYSS
- && coinflip())
- {
- const char* fall_where = "down the stairs";
- if (!feat_is_staircase(stair_find))
- fall_where = "through the gate";
-
- mprf("In your confused state, you trip and fall %s.", fall_where);
- // Note that this only does damage; it doesn't cancel the level
- // transition.
- if (!feat_is_staircase(stair_find))
- ouch(1, KILLED_BY_FALLING_THROUGH_GATE);
- else
- ouch(1, KILLED_BY_FALLING_DOWN_STAIRS);
- }
-
- dungeon_feature_type stair_taken = stair_find;
-
- if (shaft)
- stair_taken = DNGN_TRAP_SHAFT;
-
- switch (you.where_are_you)
- {
- case BRANCH_ABYSS:
- if (old_level.branch == BRANCH_ABYSS)
- {
- mprf(MSGCH_BANISHMENT, "You plunge deeper into the Abyss.");
- break;
- }
- if (!force_stair)
- mpr("You enter the Abyss!");
-
- mpr("To return, you must find a gate leading back.");
- if (you_worship(GOD_CHEIBRIADOS))
- {
- mprf(MSGCH_GOD, GOD_CHEIBRIADOS,
- "You feel Cheibriados slowing down the madness of this place.");
- }
-
- // Re-entering the Abyss halves accumulated speed.
- you.abyss_speed /= 2;
- learned_something_new(HINT_ABYSS);
- break;
-
- case BRANCH_PANDEMONIUM:
- if (old_level.branch == BRANCH_PANDEMONIUM)
- mpr("You pass into a different region of Pandemonium.");
- break;
-
- default:
- if (!shaft)
- _climb_message(stair_find, false, old_level.branch);
- break;
- }
-
- if (!shaft)
- _exit_stair_message(stair_find);
-
- // Did we enter a new branch.
- if (!player_in_branch(old_level.branch))
- {
- const branch_type branch = you.where_are_you;
-
- // Entered a branch (including portals) through the front door.
- if (stair_taken == branches[branch].entry_stairs)
- {
- if (branches[branch].entry_message)
- mpr(branches[branch].entry_message);
- else
- mprf("Welcome to %s!", branches[branch].longname);
- }
-
- // Entered a regular (non-portal) branch from above.
- if (parent_branch(branch) == old_level.branch)
- enter_branch(branch, old_level);
- }
-
- const bool newlevel = load_level(stair_taken, LOAD_ENTER_LEVEL, old_level);
-
- if (newlevel)
- {
- switch (you.where_are_you)
- {
- default:
- // Xom thinks it's funny if you enter a new level via shaft
- // or escape hatch, for shafts it's funnier the deeper you fell.
- if (shaft || feat_is_escape_hatch(stair_find))
- xom_is_stimulated(shaft_depth * 50);
- else if (!is_connected_branch(you.where_are_you))
- xom_is_stimulated(25);
- else
- xom_is_stimulated(10);
- break;
-
- case BRANCH_ZIGGURAT:
- // The best way to die currently.
- xom_is_stimulated(50);
- break;
-
- case BRANCH_LABYRINTH:
- // Finding the way out of a labyrinth interests Xom,
- // but less so for Minotaurs. (though not now, as they cannot
- // map the labyrinth any more {due})
- xom_is_stimulated(75);
- break;
-
- case BRANCH_PANDEMONIUM:
- xom_is_stimulated(100);
- break;
-
- case BRANCH_ABYSS:
- generate_random_blood_spatter_on_level();
-
- if (!force_stair && old_feat == DNGN_ENTER_ABYSS)
- xom_is_stimulated(100, XM_INTRIGUED);
- else
- xom_is_stimulated(200);
- break;
- }
- }
-
- you.turn_is_over = true;
-
- save_game_state();
-
- new_level();
-
- moveto_location_effects(old_feat);
-
- // Clear list of beholding and constricting/constricted monsters.
- you.clear_beholders();
- you.clear_fearmongers();
- you.stop_constricting_all();
- you.stop_being_constricted();
-
- if (!allow_control_teleport(true))
- mprf(MSGCH_WARN, "You sense a powerful magical force warping space.");
-
- trackers_init_new_level(true);
- if (!wizard)
- _update_travel_cache(old_level, stair_pos);
-
- // Preventing obvious finding of stairs at your position.
- env.map_seen.set(you.pos());
-
- viewwindow();
-
- maybe_update_stashes();
-
- request_autopickup();
-
- // Zotdef: returning from portals (e.g. bazaar) paralyses the player in
- // place for 5 moves. Nasty, but punishes players for using portals as
- // quick-healing stopovers.
- if (crawl_state.game_is_zotdef())
- start_delay(DELAY_UNINTERRUPTIBLE, 5);
+ take_stairs(force_stair, false, force_known_shaft, wizard);
}
static bool _any_glowing_mold()
diff --git a/crawl-ref/source/stairs.h b/crawl-ref/source/stairs.h
index 151e41e..20c4535 100644
--- a/crawl-ref/source/stairs.h
+++ b/crawl-ref/source/stairs.h
@@ -10,6 +10,9 @@ bool check_annotation_exclusion_warning();
level_id stair_destination(dungeon_feature_type feat, const string &dst,
bool for_real = false);
level_id stair_destination(coord_def pos, bool for_real = false);
+void take_stairs(dungeon_feature_type force_stair = DNGN_UNSEEN,
+ bool going_up = false, bool force_known_shaft = false,
+ bool wizard = false);
void down_stairs(dungeon_feature_type force_stair = DNGN_UNSEEN,
bool force_known_shaft = false,
bool wizard = false);
diff --git a/crawl-ref/source/terrain.cc b/crawl-ref/source/terrain.cc
index c2328a8..0c9f505 100644
--- a/crawl-ref/source/terrain.cc
+++ b/crawl-ref/source/terrain.cc
@@ -527,7 +527,7 @@ bool feat_is_metal(dungeon_feature_type feat)
return feat == DNGN_METAL_WALL || feat == DNGN_GRATE;
}
-/** XXX: not sure what this means
+/** Is this feature ambivalent about whether we're going up or down?
*/
bool feat_is_bidirectional_portal(dungeon_feature_type feat)
{
--
1.9.1
|