summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source
diff options
context:
space:
mode:
authorj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2009-07-14 22:41:26 +0000
committerj-p-e-g <j-p-e-g@c06c8d41-db1a-0410-9941-cceddc491573>2009-07-14 22:41:26 +0000
commit314d93a98176f4eea464be2349039a4fd57de764 (patch)
tree9bd62049a41086a4198c58daaa428462ea0d88e2 /crawl-ref/source
parent26f8d2de7b69e5cc901b293f76dd0ded073ad1b7 (diff)
downloadcrawl-ref-314d93a98176f4eea464be2349039a4fd57de764.tar.gz
crawl-ref-314d93a98176f4eea464be2349039a4fd57de764.zip
Fix closing/opening doors not prompting if there are several adjacent
doors. Also, confusion is now handled more consistently. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@10215 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source')
-rw-r--r--crawl-ref/source/acr.cc397
-rw-r--r--crawl-ref/source/player.cc5
2 files changed, 233 insertions, 169 deletions
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc
index 38423e73fa..22c0e65395 100644
--- a/crawl-ref/source/acr.cc
+++ b/crawl-ref/source/acr.cc
@@ -2928,19 +2928,85 @@ static int _check_adjacent(dungeon_feature_type feat, coord_def& delta)
return num;
}
-// Opens doors and handles some aspects of untrapping. If either move_x or
+// Handles some aspects of untrapping. Returns false if the target is a
+// closed door that will need to be opened.
+static bool _untrap_target(const coord_def move, bool check_confused)
+{
+ const coord_def target = you.pos() + move;
+ monsters* mon = monster_at(target);
+ if (mon && player_can_hit_monster(mon))
+ {
+ if (mons_is_caught(mon) && mons_friendly(mon)
+ && player_can_open_doors() && !you.confused())
+ {
+ const std::string prompt =
+ make_stringf("Do you want to try to take the net off %s?",
+ mon->name(DESC_NOCAP_THE).c_str());
+
+ if (yesno(prompt.c_str(), true, 'n'))
+ {
+ remove_net_from(mon);
+ return (true);
+ }
+ }
+
+ you.turn_is_over = true;
+ you_attack(mon->mindex(), true);
+
+ if (you.berserk_penalty != NO_BERSERK_PENALTY)
+ you.berserk_penalty = 0;
+
+ return (true);
+ }
+
+ if (find_trap(target) && grd(target) != DNGN_UNDISCOVERED_TRAP)
+ {
+ if (!you.confused())
+ {
+ if (!player_can_open_doors())
+ {
+ mpr("You can't disarm traps in your present form.");
+ return (true);
+ }
+ if (env.cgrid(target) != EMPTY_CLOUD)
+ {
+ mpr("You can't get to that trap right now.");
+ return (true);
+ }
+ }
+
+ // If you're confused, you may attempt it and stumble into the trap.
+ disarm_trap(target);
+ return (true);
+ }
+
+ const dungeon_feature_type feat = grd(target);
+ if (!grid_is_closed_door(feat) || you.confused())
+ {
+ switch (feat)
+ {
+ case DNGN_OPEN_DOOR:
+ _close_door(move); // for convenience
+ return (true);
+ default:
+ mpr("You swing at nothing.");
+ make_hungry(3, true);
+ you.turn_is_over = true;
+ return (true);
+ }
+ }
+
+ // Else it's a closed door and needs further handling.
+ return (false);
+}
+
+// Opens doors and . If either move_x or
// move_y are non-zero, the pair carries a specific direction for the door
// to be opened (eg if you type ctrl + dir).
static void _open_door(coord_def move, bool check_confused)
{
ASSERT(!crawl_state.arena && !crawl_state.arena_suspended);
- if (!player_can_open_doors())
- {
- mpr("You can't open doors in your present form.");
- return;
- }
-
if (you.attribute[ATTR_HELD])
{
free_self_from_net();
@@ -2948,184 +3014,174 @@ static void _open_door(coord_def move, bool check_confused)
return;
}
- // If there's only one door to open, don't ask.
- if ((!check_confused || !you.confused()) && move.origin())
+ // The player used Ctrl + dir or a variant thereof.
+ if (!move.origin())
{
- if (_check_adjacent(DNGN_CLOSED_DOOR, move) == 0
- && _check_adjacent(DNGN_DETECTED_SECRET_DOOR, move) == 0)
+ if (check_confused && you.confused() && !one_chance_in(3))
{
- mpr("There's nothing to open.");
- return;
+ do
+ {
+ move.x = random2(3) - 1;
+ move.y = random2(3) - 1;
+ }
+ while (move.origin());
}
+ if (_untrap_target(move, check_confused))
+ return;
}
- if (check_confused && you.confused() && !one_chance_in(3))
+ // If we get here, the player either hasn't picked a direction yet
+ // or the chosen direction actually contains a closed door.
+
+ if (!player_can_open_doors())
{
- move.x = random2(3) - 1;
- move.y = random2(3) - 1;
+ mpr("You can't open doors in your present form.");
+ return;
}
dist door_move;
- door_move.delta = move;
- coord_def doorpos;
- if (!move.origin())
+ // The player hasn't picked a direction yet.
+ if (move.origin())
{
- doorpos = you.pos() + move;
-
- monsters* mon = monster_at(doorpos);
+ const int num = _check_adjacent(DNGN_CLOSED_DOOR, move)
+ + _check_adjacent(DNGN_DETECTED_SECRET_DOOR, move);
- if (mon && player_can_hit_monster(mon))
+ if (num == 0)
{
- if (mons_is_caught(mon))
- {
- const std::string prompt =
- make_stringf("Do you want to try to take the net off %s?",
- mon->name(DESC_NOCAP_THE).c_str());
-
- if (yesno(prompt.c_str(), true, 'n'))
- {
- remove_net_from(mon);
- return;
- }
-
- }
-
- you.turn_is_over = true;
- you_attack(mon->mindex(), true);
-
- if (you.berserk_penalty != NO_BERSERK_PENALTY)
- you.berserk_penalty = 0;
-
+ mpr("There's nothing to open nearby.");
return;
}
- if (find_trap(doorpos) && grd(doorpos) != DNGN_UNDISCOVERED_TRAP)
+ // If there's only one door to open, don't ask.
+ if (num == 1)
+ door_move.delta = move;
+ else
{
- if (env.cgrid(doorpos) != EMPTY_CLOUD)
- {
- mpr("You can't get to that trap right now.");
- return;
- }
+ mpr("Which direction? ", MSGCH_PROMPT);
+ direction(door_move, DIR_DIR);
- disarm_trap(doorpos);
- return;
+ if (!door_move.isValid)
+ return;
}
}
else
- {
- mpr("Which direction? ", MSGCH_PROMPT);
- direction(door_move, DIR_DIR);
-
- if (!door_move.isValid)
- return;
+ door_move.delta = move;
- doorpos = you.pos() + door_move.delta;
-
- const dungeon_feature_type feat =
- in_bounds(doorpos) ? grd(doorpos) : DNGN_UNSEEN;
-
- if (!grid_is_closed_door(feat))
+ if (check_confused && you.confused() && !one_chance_in(3))
+ {
+ do
{
- switch (feat)
- {
- case DNGN_OPEN_DOOR:
- mpr("It's already open!"); break;
- default:
- mpr("There isn't anything that you can open there!");
- break;
- }
- // Don't lose a turn.
- return;
+ door_move.delta.x = random2(3) - 1;
+ door_move.delta.y = random2(3) - 1;
}
+ while (door_move.delta.origin());
}
+ ASSERT(door_move.isValid);
- if (grid_is_closed_door(grd(doorpos)))
- {
- std::set<coord_def> all_door;
- find_connected_range(doorpos, DNGN_CLOSED_DOOR,
- DNGN_SECRET_DOOR, all_door);
- const char *adj, *noun;
- get_door_description(all_door.size(), &adj, &noun);
-
- int skill = you.dex +
- (you.skills[SK_TRAPS_DOORS] + you.skills[SK_STEALTH]) / 2;
+ // We got a valid direction.
+ const coord_def doorpos = you.pos() + door_move.delta;
+ const dungeon_feature_type feat = (in_bounds(doorpos) ? grd(doorpos)
+ : DNGN_UNSEEN);
- if (you.duration[DUR_BERSERKER])
+ if (!grid_is_closed_door(feat))
+ {
+ if (you.confused())
{
- // XXX: Better flavour for larger doors?
- if (silenced(you.pos()))
- mprf("The %s%s flies open!", adj, noun);
- else
- {
- mprf(MSGCH_SOUND, "The %s%s flies open with a bang!",
- adj, noun);
- noisy(15, you.pos());
- }
+ mpr("You swing at nothing.");
+ make_hungry(3, true);
+ you.turn_is_over = true;
+ return;
}
- else if (one_chance_in(skill) && !silenced(you.pos()))
+ switch (feat)
{
- mprf(MSGCH_SOUND, "As you open the %s%s, it creaks loudly!",
- adj, noun);
- noisy(10, you.pos());
+ case DNGN_OPEN_DOOR:
+ mpr("It's already open!");
+ break;
+ default:
+ mpr("There isn't anything that you can open there!");
+ break;
}
+ // Don't lose a turn.
+ return;
+ }
+
+ // Finally, open the closed door!
+ std::set<coord_def> all_door;
+ find_connected_range(doorpos, DNGN_CLOSED_DOOR, DNGN_SECRET_DOOR, all_door);
+ const char *adj, *noun;
+ get_door_description(all_door.size(), &adj, &noun);
+
+ int skill = you.dex
+ + (you.skills[SK_TRAPS_DOORS] + you.skills[SK_STEALTH]) / 2;
+
+ if (you.duration[DUR_BERSERKER])
+ {
+ // XXX: Better flavour for larger doors?
+ if (silenced(you.pos()))
+ mprf("The %s%s flies open!", adj, noun);
else
{
- const char* verb =
- player_is_airborne() ? "reach down and open" : "open";
- mprf( "You %s the %s%s.", verb, adj, noun );
+ mprf(MSGCH_SOUND, "The %s%s flies open with a bang!", adj, noun);
+ noisy(15, you.pos());
}
+ }
+ else if (one_chance_in(skill) && !silenced(you.pos()))
+ {
+ mprf(MSGCH_SOUND, "As you open the %s%s, it creaks loudly!",
+ adj, noun);
+ noisy(10, you.pos());
+ }
+ else
+ {
+ const char* verb = (player_is_airborne() ? "reach down and open"
+ : "open");
+ mprf("You %s the %s%s.", verb, adj, noun);
+ }
- bool seen_secret = false;
- std::vector<coord_def> excludes;
- for (std::set<coord_def>::iterator i = all_door.begin();
- i != all_door.end(); ++i)
+ bool seen_secret = false;
+ std::vector<coord_def> excludes;
+ for (std::set<coord_def>::iterator i = all_door.begin();
+ i != all_door.end(); ++i)
+ {
+ const coord_def& dc = *i;
+ // Even if some of the door is out of LOS, we want the entire
+ // door to be updated. Hitting this case requires a really big
+ // door!
+ if (is_terrain_seen(dc))
{
- const coord_def& dc = *i;
- // Even if some of the door is out of LOS, we want the entire
- // door to be updated. Hitting this case requires a really big
- // door!
- if (is_terrain_seen(dc))
- {
- set_envmap_obj(dc, DNGN_OPEN_DOOR);
+ set_envmap_obj(dc, DNGN_OPEN_DOOR);
#ifdef USE_TILE
- env.tile_bk_bg(dc) = TILE_DNGN_OPEN_DOOR;
+ env.tile_bk_bg(dc) = TILE_DNGN_OPEN_DOOR;
#endif
- if (!seen_secret && grd(dc) == DNGN_SECRET_DOOR)
- {
- seen_secret = true;
- dungeon_feature_type secret
- = grid_secret_door_appearance(dc);
- mprf("That %s was a secret door!",
- feature_description(secret, NUM_TRAPS, false,
- DESC_PLAIN, false).c_str());
- }
+ if (!seen_secret && grd(dc) == DNGN_SECRET_DOOR)
+ {
+ seen_secret = true;
+ dungeon_feature_type secret
+ = grid_secret_door_appearance(dc);
+ mprf("That %s was a secret door!",
+ feature_description(secret, NUM_TRAPS, false,
+ DESC_PLAIN, false).c_str());
}
- grd(dc) = DNGN_OPEN_DOOR;
- if (is_excluded(dc))
- excludes.push_back(dc);
}
- if (!excludes.empty())
- {
- mark_all_excludes_non_updated();
- for (unsigned int i = 0; i < excludes.size(); ++i)
- update_exclusion_los(excludes[i]);
- }
- you.turn_is_over = true;
+ grd(dc) = DNGN_OPEN_DOOR;
+ if (is_excluded(dc))
+ excludes.push_back(dc);
}
- else if (grd(doorpos) == DNGN_OPEN_DOOR)
- _close_door(move); // for convenience
- else
+
+ if (!excludes.empty())
{
- mpr("You swing at nothing.");
- make_hungry(3, true);
- you.turn_is_over = true;
+ mark_all_excludes_non_updated();
+ for (unsigned int i = 0; i < excludes.size(); ++i)
+ update_exclusion_los(excludes[i]);
}
+
+ you.turn_is_over = true;
}
static void _close_door(coord_def move)
{
- if (player_in_bat_form())
+ if (!player_can_open_doors())
{
mpr("You can't close doors in your present form.");
return;
@@ -3138,39 +3194,41 @@ static void _close_door(coord_def move)
}
dist door_move;
- coord_def doorpos;
- // If there's only one door to close, don't ask.
- if (!you.confused() && move.origin())
+ // The player hasn't yet told us a direction.
+ if (move.origin())
{
+ // If there's only one door to close, don't ask.
int num = _check_adjacent(DNGN_OPEN_DOOR, move);
if (num == 0)
{
- mpr("There's nothing to close.");
+ mpr("There's nothing to close nearby.");
return;
}
- else if (num == 1 && move.origin())
+ else if (num == 1)
{
- mpr("You can't close doors on yourself!");
- return;
+ door_move.delta = move;
}
- }
+ else
+ {
+ mpr("Which direction? ", MSGCH_PROMPT);
+ direction(door_move, DIR_DIR);
- if (you.confused() && !one_chance_in(3))
- {
- move.x = random2(3) - 1;
- move.y = random2(3) - 1;
+ if (!door_move.isValid)
+ return;
+ }
}
+ else
+ door_move.delta = move;
- door_move.delta = move;
-
- if (move.origin())
+ if (you.confused() && !one_chance_in(3))
{
- mpr("Which direction? ", MSGCH_PROMPT);
- direction(door_move, DIR_DIR);
-
- if (!door_move.isValid)
- return;
+ do
+ {
+ door_move.delta.x = random2(3) - 1;
+ door_move.delta.y = random2(3) - 1;
+ }
+ while (door_move.delta.origin());
}
if (door_move.delta.origin())
@@ -3179,10 +3237,9 @@ static void _close_door(coord_def move)
return;
}
- doorpos = you.pos() + door_move.delta;
-
- const dungeon_feature_type feat =
- in_bounds(doorpos) ? grd(doorpos) : DNGN_UNSEEN;
+ const coord_def doorpos = you.pos() + door_move.delta;
+ const dungeon_feature_type feat = (in_bounds(doorpos) ? grd(doorpos)
+ : DNGN_UNSEEN);
if (feat == DNGN_OPEN_DOOR)
{
@@ -3222,8 +3279,8 @@ static void _close_door(coord_def move)
}
}
- int skill = you.dex +
- (you.skills[SK_TRAPS_DOORS] + you.skills[SK_STEALTH]) / 2;
+ int skill = you.dex
+ + (you.skills[SK_TRAPS_DOORS] + you.skills[SK_STEALTH]) / 2;
if (you.duration[DUR_BERSERKER])
{
@@ -3249,7 +3306,8 @@ static void _close_door(coord_def move)
{
const char* verb = player_is_airborne() ? "reach down and close"
: "close";
- mprf( "You %s the %s%s.", verb, adj, noun );
+
+ mprf("You %s the %s%s.", verb, adj, noun);
}
std::vector<coord_def> excludes;
@@ -3259,6 +3317,7 @@ static void _close_door(coord_def move)
const coord_def& dc = *i;
// Once opened, formerly secret doors become normal doors.
grd(dc) = DNGN_CLOSED_DOOR;
+
// Even if some of the door is out of LOS once it's closed (or even
// if some of it is out of LOS when it's open), we want the entire
// door to be updated.
@@ -3280,15 +3339,19 @@ static void _close_door(coord_def move)
}
you.turn_is_over = true;
}
+ else if (you.confused())
+ _open_door(door_move.delta);
else
{
switch (feat)
{
case DNGN_CLOSED_DOOR:
case DNGN_DETECTED_SECRET_DOOR:
- mpr("It's already closed!"); break;
+ mpr("It's already closed!");
+ break;
default:
- mpr("There isn't anything that you can close there!"); break;
+ mpr("There isn't anything that you can close there!");
+ break;
}
}
}
diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc
index 1d13865abd..a3af5c9ebb 100644
--- a/crawl-ref/source/player.cc
+++ b/crawl-ref/source/player.cc
@@ -435,8 +435,9 @@ bool player_in_bat_form()
bool player_can_open_doors()
{
- // Bats can't close/open doors.
- return !player_in_bat_form();
+ // Bats and pigs can't open/close doors.
+ return (you.attribute[ATTR_TRANSFORMATION] != TRAN_BAT
+ && you.attribute[ATTR_TRANSFORMATION] != TRAN_PIG);
}
bool player_under_penance(void)