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
R25VQ2MUGGDTO5UZR2DPO5XUYSA3LB6RIEBGLJ6CD75T2GED2ZNAC
TFWVU5PMJESW2RVSJQUQJAQY5Q2KH4KC32X7CTXYWLCSLT5TGQDAC
KF5BNN42PTO35TBQD5CNMDXFAXHYCSQTBOOXZV7I3ML5VASUUT5AC
ADKWRQ4QN4WGEGH2X66IJX6AWEUKEY5YTD4NSFWZIXR24BNLPN6QC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
A43NYENITQ3BRLUMCFT3T5CM2NFXCIDRX7OCMEAXXGNTJIDDS6YQC
R22TTMI6WXWULC7ODKFF3QCB7MOTETQQ6IR4BUCUPOCQKQNCTT5AC
QLMCSREGK2UUAPXZSZQKLZOLM4BCB7PAVCSR3DLFQS3EW3IMWQSQC
H5BVKRORNXTCJKFXQPTFWDURKSUFW24CGSJXBGZCJUP4DHMSVDBQC
FSJKED4U2SOUP64DTHF2NEGAYY7EUMSIDKC2SATEXAXEVOCNL3CAC
PZ3XLK6F2H6OZU462GNYVHNICLQ6JOGNF5GYDBJBWXNNPAYIT6YQC
7VCVH6XKT4L4PSCBF6XRYV3WQQDVGDMA73RHPV6IOWMQ2S7B5XAQC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
SIDH2P7NBIG5KEOE27XHD3ZT2NQ2OJZFN6VZXWNWYFFY5YVXSSVQC
HB27XKFYVYIEQZGBCEZ6LKPUBMXLIPDAAS636GJ5TULIQ7KND5KQC
4UXFU3FZOCBSLDQ4S7MJKAE2H7VUHCNRDQMIY6NJ3PHYXWNGISDQC
P5TRGRH7XMQSPCZKM5IEEO34TY6WMLGHHX7BU6Y453JFRXLUR2VQC
CK7CT5TUFUL2AQY7FUHB5JI3FC2KSPWUWHXC6VEUJJ7G4OWUQFTAC
NVSFIV2ZKP44XHCSCXG6OZVGL67OIFINC34J2EMKTA4KULCERUEAC
3BUZB6SWAESYJGX564WE7IS2FFURCDOZT4D2I4PWSZXUVHEQDTQAC
B7MSPF6X2RLGWN4M6ZZF3WSOPKGYPTTD7LIJVST7DXN27DG6JHNAC
LVCBY444HPB4RRFMUAZPHVZ67IC3L6DB27AEMCW3DEXHLBF73TMQC
AMBBZGB4EP4MA2ILKQSAY4O2XQAIH673JHCDQ6N4MBGL2MAZGXNAC
JEWGBHOQGDSWMLT4FZTQWUKTBJJWY5CSRAQQUOWIZ7U4QBJ6ZLBQC
X5DCNPFXJAWWTCTVQGZN4PTTWUJIUE4JPTXH3WVWCO2DW67MXWYAC
7V4DCKFJCNBXFODMKJ6H3MCDUTSD4XVQ7D4D6XFCD4JNF4HCE4KAC
4FQAKUKUO6PCAZ3N4HUR5XL6E4VA5UQUZ3AEDGRBLVY7W2LMWI7QC
5XNQ3SSNBFXFNWA6DPM74W6FH65NX665P3DMH6YCWVFOPZTJSYCQC
QCIPZ52TOIKLA6O22P7USLEAYI4VAZRLGVXMAASSGEP37KN5PEVAC
TGJZXTUIAKCFZQJ54ZQEBGFBVZSJCAX6AWDRSH3TP7UJRLGUM5SAC
PPUOTH5Z7TV4OLVIFYAXNAXXH2WUMJNFDOZK2QN6B6WJYTFBMNOAC
WKGCRBVC45E5T6TKJ6BOLIJFRUF7IZBDHNUIBUXCCOIWKGJBEVCQC
7Q7PY2DHSCW7Y663XJUTBFZTHXCF6KPIMZV2A6XORBCMMHIJWVGQC
FG6S2SNKFZWJK7PYHASHXU32ORYBOLGFL5RWQVDJ47MFVS4VMQHQC
O6ZMFKDI3XO2SWPNEYHIPYFDWJR4TVDP5BAATK6LVCVETQID6E7AC
LMRRQE4ZXQYZPXVGBTDZP7LEIM6OGSSOOQ5FAOWXJCDCNCECX5VAC
KA5FM5FELFEKHCCICIQCKVKOLHOYXOCODGK4NFJWRSPJ4UXULC2AC
// 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
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 (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.");
if (env.cgrid(doorpos) != EMPTY_CLOUD)
{
mpr("You can't get to that trap right now.");
mpr("Which direction? ", MSGCH_PROMPT);
direction(door_move, DIR_DIR);
if (!door_move.isValid)
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 (!grid_is_closed_door(feat))
{
if (you.confused())
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.
mpr("You swing at nothing.");
make_hungry(3, true);
you.turn_is_over = true;
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);
// 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);
if (you.duration[DUR_BERSERKER])
{
// 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());
}
}
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());
}
if (you.duration[DUR_BERSERKER])
{
// XXX: Better flavour for larger doors?
if (silenced(you.pos()))
mprf("The %s%s flies open!", adj, noun);
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);
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());
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())
door_move.delta = move;
if (move.origin())
{
mpr("Which direction? ", MSGCH_PROMPT);
direction(door_move, DIR_DIR);
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);