-/* NetHack 3.6 zap.c $NHDT-Date: 1447987787 2015/11/20 02:49:47 $ $NHDT-Branch: master $:$NHDT-Revision: 1.236 $ */
+/* NetHack 3.6 zap.c $NHDT-Date: 1573688696 2019/11/13 23:44:56 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.316 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2013. */
/* NetHack may be freely redistributed. See license for details. */
/* JNetHack Copyright */
/* (c) Issei Numata, Naoki Hamada, Shigehiro Miyashita, 1994-2000 */
-/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2016 */
+/* For 3.4-, Copyright (c) SHIRAKATA Kentaro, 2002-2020 */
/* JNetHack may be freely redistributed. See license for details. */
#include "hack.h"
STATIC_DCL void FDECL(revive_egg, (struct obj *));
STATIC_DCL boolean FDECL(zap_steed, (struct obj *));
STATIC_DCL void FDECL(skiprange, (int, int *, int *));
-
STATIC_DCL int FDECL(zap_hit, (int, int));
STATIC_OVL void FDECL(disintegrate_mon, (struct monst *, int, const char *));
STATIC_DCL void FDECL(backfire, (struct obj *));
STATIC_DCL int FDECL(spell_hit_bonus, (int));
+STATIC_DCL void FDECL(destroy_one_item, (struct obj *, int, int));
+STATIC_DCL void FDECL(wishcmdassist, (int));
#define ZT_MAGIC_MISSILE (AD_MAGM - 1)
#define ZT_FIRE (AD_FIRE - 1)
*/
"\82Ü\82Î\82ä\82¢\8cõ\82Å\96Ú\82ª\8c©\82¦\82È\82\82È\82Á\82½\81I";
-const char *const flash_types[] =
- { /* also used in buzzmu(mcastu.c) */
-#if 0 /*JP*/
- "magic missile", /* Wands must be 0-9 */
- "bolt of fire", "bolt of cold", "sleep ray", "death ray",
- "bolt of lightning", "", "", "", "",
+const char *const flash_types[] = /* also used in buzzmu(mcastu.c) */
+ {
+#if 0 /*JP:T*/
+ "magic missile", /* Wands must be 0-9 */
+ "bolt of fire", "bolt of cold", "sleep ray", "death ray",
+ "bolt of lightning", "", "", "", "",
#else
"\96\82\96@\82Ì\96î", /* Wands must be 0-9 */
"\89Î\82Ì\91M\8cõ",
"",
#endif
-#if 0 /*JP*/
- "magic missile", /* Spell equivalents must be 10-19 */
- "fireball", "cone of cold", "sleep ray", "finger of death",
- "bolt of lightning", /* There is no spell, used for retribution */
- "", "", "", "",
+#if 0 /*JP:T*/
+ "magic missile", /* Spell equivalents must be 10-19 */
+ "fireball", "cone of cold", "sleep ray", "finger of death",
+ "bolt of lightning", /* there is no spell, used for retribution */
+ "", "", "", "",
#else
"\96\82\96@\82Ì\96î", /* Spell equivalents must be 10-19 */
"\89Î\82Ì\8bÊ",
"",
#endif
-#if 0 /*JP*/
- "blast of missiles", /* Dragon breath equivalents 20-29*/
- "blast of fire", "blast of frost", "blast of sleep gas",
- "blast of disintegration", "blast of lightning", "blast of poison gas",
- "blast of acid", "", ""
+#if 0 /*JP:T*/
+ "blast of missiles", /* Dragon breath equivalents 20-29*/
+ "blast of fire", "blast of frost", "blast of sleep gas",
+ "blast of disintegration", "blast of lightning",
+ "blast of poison gas", "blast of acid", "", ""
#else
"\96\82\96@\82Ì\96î\82Ì\91§", /* Dragon breath equivalents 20-29*/
"\89Î\82Ì\91§",
if (obj->dknown)
makeknown(obj->otyp);
}
+ update_inventory();
}
}
boolean wake = TRUE; /* Most 'zaps' should wake monster */
boolean reveal_invis = FALSE, learn_it = FALSE;
boolean dbldam = Role_if(PM_KNIGHT) && u.uhave.questart;
+ boolean skilled_spell, helpful_gesture = FALSE;
int dmg, otyp = otmp->otyp;
/*JP
const char *zap_type_text = "spell";
*/
const char *zap_type_text = "\96\82\96@";
struct obj *obj;
- boolean disguised_mimic =
- (mtmp->data->mlet == S_MIMIC && mtmp->m_ap_type != M_AP_NOTHING);
+ boolean disguised_mimic = (mtmp->data->mlet == S_MIMIC
+ && M_AP_TYPE(mtmp) != M_AP_NOTHING);
if (u.uswallow && mtmp == u.ustuck)
reveal_invis = FALSE;
+ notonhead = (mtmp->mx != bhitpos.x || mtmp->my != bhitpos.y);
+ skilled_spell = (otmp && otmp->oclass == SPBOOK_CLASS && otmp->blessed);
+
switch (otyp) {
case WAN_STRIKING:
/*JP
zap_type_text = "wand";
*/
zap_type_text = "\8fñ";
- /* fall through */
+ /*FALLTHRU*/
case SPE_FORCE_BOLT:
reveal_invis = TRUE;
+ if (disguised_mimic)
+ seemimic(mtmp);
if (resists_magm(mtmp)) { /* match effect on player */
shieldeff(mtmp->mx, mtmp->my);
/*JP
case WAN_SLOW_MONSTER:
case SPE_SLOW_MONSTER:
if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
+ if (disguised_mimic)
+ seemimic(mtmp);
mon_adjust_speed(mtmp, -1, otmp);
m_dowear(mtmp, FALSE); /* might want speed boots */
if (u.uswallow && (mtmp == u.ustuck) && is_whirly(mtmp->data)) {
break;
case WAN_SPEED_MONSTER:
if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
+ if (disguised_mimic)
+ seemimic(mtmp);
mon_adjust_speed(mtmp, 1, otmp);
m_dowear(mtmp, FALSE); /* might want speed boots */
}
+ if (mtmp->mtame)
+ helpful_gesture = TRUE;
break;
case WAN_UNDEAD_TURNING:
case SPE_TURN_UNDEAD:
dmg = spell_damage_bonus(dmg);
context.bypasses = TRUE; /* for make_corpse() */
if (!resist(mtmp, otmp->oclass, dmg, NOTELL)) {
- if (mtmp->mhp > 0)
+ if (!DEADMONSTER(mtmp))
monflee(mtmp, 0, FALSE, TRUE);
}
}
case WAN_POLYMORPH:
case SPE_POLYMORPH:
case POT_POLYMORPH:
- if (resists_magm(mtmp)) {
+ if (mtmp->data == &mons[PM_LONG_WORM] && has_mcorpsenm(mtmp)) {
+ /* if a long worm has mcorpsenm set, it was polymophed by
+ the current zap and shouldn't be affected if hit again */
+ ;
+ } else if (resists_magm(mtmp)) {
/* magic resistance protects from polymorph traps, so make
it guard against involuntary polymorph attacks too... */
shieldeff(mtmp->mx, mtmp->my);
} else if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
+ boolean polyspot = (otyp != POT_POLYMORPH),
+ give_msg = (!Hallucination
+ && (canseemon(mtmp)
+ || (u.uswallow && mtmp == u.ustuck)));
+
/* dropped inventory (due to death by system shock,
or loss of wielded weapon and/or worn armor due to
limitations of new shape) won't be hit by this zap */
- for (obj = mtmp->minvent; obj; obj = obj->nobj)
- bypass_obj(obj);
+ if (polyspot)
+ for (obj = mtmp->minvent; obj; obj = obj->nobj)
+ bypass_obj(obj);
+
/* natural shapechangers aren't affected by system shock
(unless protection from shapechangers is interfering
with their metabolism...) */
}
/* context.bypasses = TRUE; ## for make_corpse() */
/* no corpse after system shock */
- xkilled(mtmp, 3);
+ xkilled(mtmp, XKILL_GIVEMSG | XKILL_NOCORPSE);
} else if (newcham(mtmp, (struct permonst *) 0,
- (otyp != POT_POLYMORPH), FALSE)) {
- if (!Hallucination && canspotmon(mtmp))
+ polyspot, give_msg) != 0
+ /* if shapechange failed because there aren't
+ enough eligible candidates (most likely for
+ vampshifter), try reverting to original form */
+ || (mtmp->cham >= LOW_PM
+ && newcham(mtmp, &mons[mtmp->cham],
+ polyspot, give_msg) != 0)) {
+ if (give_msg && (canspotmon(mtmp)
+ || (u.uswallow && mtmp == u.ustuck)))
learn_it = TRUE;
}
+
+ /* do this even if polymorphed failed (otherwise using
+ flags.mon_polycontrol prompting to force mtmp to remain
+ 'long worm' would prompt again if zap hit another segment) */
+ if (!DEADMONSTER(mtmp) && mtmp->data == &mons[PM_LONG_WORM]) {
+ if (!has_mcorpsenm(mtmp))
+ newmcorpsenm(mtmp);
+ /* flag to indicate that mtmp became a long worm
+ on current zap, so further hits (on mtmp's new
+ tail) don't do further transforms */
+ MCORPSENM(mtmp) = PM_LONG_WORM;
+ /* flag to indicate that cleanup is needed; object
+ bypass cleanup also clears mon->mextra->mcorpsenm
+ for all long worms on the level */
+ context.bypasses = TRUE;
+ }
}
break;
case WAN_CANCELLATION:
case SPE_CANCELLATION:
+ if (disguised_mimic)
+ seemimic(mtmp);
(void) cancel_monst(mtmp, otmp, TRUE, TRUE, FALSE);
break;
case WAN_TELEPORTATION:
case SPE_TELEPORT_AWAY:
+ if (disguised_mimic)
+ seemimic(mtmp);
reveal_invis = !u_teleport_mon(mtmp, TRUE);
break;
case WAN_MAKE_INVISIBLE: {
int oldinvis = mtmp->minvis;
char nambuf[BUFSZ];
+ if (disguised_mimic)
+ seemimic(mtmp);
/* format monster's name before altering its visibility */
Strcpy(nambuf, Monnam(mtmp));
mon_set_minvis(mtmp);
pline("%s turns transparent!", nambuf);
*/
pline("%s\82Í\93§\96¾\82É\82È\82Á\82½\81I", nambuf);
+ reveal_invis = TRUE;
learn_it = TRUE;
}
break;
} else if ((obj = which_armor(mtmp, W_SADDLE)) != 0) {
char buf[BUFSZ];
-#if 0 /*JP*/
+#if 0 /*JP:T*/
Sprintf(buf, "%s %s", s_suffix(Monnam(mtmp)),
distant_name(obj, xname));
#else
- Sprintf(buf, "%s\82Ì%s", s_suffix(Monnam(mtmp)),
+ Sprintf(buf, "%s\82Ì%s", Monnam(mtmp),
distant_name(obj, xname));
#endif
if (cansee(mtmp->mx, mtmp->my)) {
if (!canspotmon(mtmp))
Strcpy(buf, An(distant_name(obj, xname)));
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s falls to the %s.", buf,
surface(mtmp->mx, mtmp->my));
#else
mtmp->mhp += d(6, otyp == SPE_EXTRA_HEALING ? 8 : 4);
if (mtmp->mhp > mtmp->mhpmax)
mtmp->mhp = mtmp->mhpmax;
- if (mtmp->mblinded) {
- mtmp->mblinded = 0;
- mtmp->mcansee = 1;
- }
+ /* plain healing must be blessed to cure blindness; extra
+ healing only needs to not be cursed, so spell always cures
+ [potions quaffed by monsters behave slightly differently;
+ we use the rules for the hero here...] */
+ if (skilled_spell || otyp == SPE_EXTRA_HEALING)
+ mcureblindness(mtmp, canseemon(mtmp));
if (canseemon(mtmp)) {
if (disguised_mimic) {
if (is_obj_mappear(mtmp,STRANGE_OBJECT)) {
} else
mimic_hit_msg(mtmp, otyp);
} else
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s looks%s better.", Monnam(mtmp),
otyp == SPE_EXTRA_HEALING ? " much" : "");
#else
wake = FALSE;
break;
case SPE_DRAIN_LIFE:
+ if (disguised_mimic)
+ seemimic(mtmp);
dmg = monhp_per_lvl(mtmp);
if (dbldam)
dmg *= 2;
if (otyp == SPE_DRAIN_LIFE)
dmg = spell_damage_bonus(dmg);
- if (resists_drli(mtmp))
+ if (resists_drli(mtmp)) {
shieldeff(mtmp->mx, mtmp->my);
- else if (!resist(mtmp, otmp->oclass, dmg, NOTELL) && mtmp->mhp > 0) {
+ } else if (!resist(mtmp, otmp->oclass, dmg, NOTELL)
+ && !DEADMONSTER(mtmp)) {
mtmp->mhp -= dmg;
mtmp->mhpmax -= dmg;
- if (mtmp->mhp <= 0 || mtmp->mhpmax <= 0 || mtmp->m_lev < 1)
- xkilled(mtmp, 1);
- else {
+ /* die if already level 0, regardless of hit points */
+ if (DEADMONSTER(mtmp) || mtmp->mhpmax <= 0 || mtmp->m_lev < 1) {
+ killed(mtmp);
+ } else {
mtmp->m_lev--;
if (canseemon(mtmp))
/*JP
break;
}
if (wake) {
- if (mtmp->mhp > 0) {
- wakeup(mtmp);
+ if (!DEADMONSTER(mtmp)) {
+ wakeup(mtmp, helpful_gesture ? FALSE : TRUE);
m_respond(mtmp);
if (mtmp->isshk && !*u.ushops)
hot_pursuit(mtmp);
- } else if (mtmp->m_ap_type)
+ } else if (M_AP_TYPE(mtmp))
seemimic(mtmp); /* might unblock if mimicing a boulder/door */
}
/* note: bhitpos won't be set if swallowed, but that's okay since
* might be an invisible worm hit on the tail.
*/
if (reveal_invis) {
- if (mtmp->mhp > 0 && cansee(bhitpos.x, bhitpos.y)
+ if (!DEADMONSTER(mtmp) && cansee(bhitpos.x, bhitpos.y)
&& !canspotmon(mtmp))
map_invisible(bhitpos.x, bhitpos.y);
}
otmp->cknown = 1;
}
}
- (void) display_minventory(mtmp, MINV_ALL | MINV_NOLET, (char *) 0);
+ (void) display_minventory(mtmp, MINV_ALL | MINV_NOLET | PICK_NONE,
+ (char *) 0);
} else {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s is not carrying anything%s.", noit_Monnam(mtmp),
(u.uswallow && mtmp == u.ustuck) ? " besides you" : "");
#else
/* used by revive() and animate_statue() */
struct monst *
-montraits(obj, cc)
+montraits(obj, cc, adjacentok)
struct obj *obj;
coord *cc;
+boolean adjacentok; /* False: at obj's spot only, True: nearby is allowed */
{
- struct monst *mtmp = (struct monst *) 0;
- struct monst *mtmp2 = (struct monst *) 0;
+ struct monst *mtmp, *mtmp2 = has_omonst(obj) ? get_mtraits(obj, TRUE) : 0;
- if (has_omonst(obj))
- mtmp2 = get_mtraits(obj, TRUE);
if (mtmp2) {
/* save_mtraits() validated mtmp2->mnum */
mtmp2->data = &mons[mtmp2->mnum];
if (mtmp2->mhpmax <= 0 && !is_rider(mtmp2->data))
return (struct monst *) 0;
mtmp = makemon(mtmp2->data, cc->x, cc->y,
- NO_MINVENT | MM_NOWAIT | MM_NOCOUNTBIRTH);
- if (!mtmp)
- return mtmp;
+ (NO_MINVENT | MM_NOWAIT | MM_NOCOUNTBIRTH
+ | (adjacentok ? MM_ADJACENTOK : 0)));
+ if (!mtmp) {
+ /* mtmp2 is a copy of obj's object->oextra->omonst extension
+ and is not on the map or on any monst lists */
+ dealloc_monst(mtmp2);
+ return (struct monst *) 0;
+ }
/* heal the monster */
if (mtmp->mhpmax > mtmp2->mhpmax && is_rider(mtmp2->data))
if (mtmp->m_id) {
mtmp2->m_id = mtmp->m_id;
/* might be bringing quest leader back to life */
- if (quest_status.leader_is_dead &&
+ if (quest_status.leader_is_dead
/* leader_is_dead implies leader_m_id is valid */
- mtmp2->m_id == quest_status.leader_m_id)
+ && mtmp2->m_id == quest_status.leader_m_id)
quest_status.leader_is_dead = FALSE;
}
mtmp2->mx = mtmp->mx;
mtmp2->mblinded = 0;
mtmp2->mstun = 0;
mtmp2->mconf = 0;
+ /* when traits are for a shopeekper, dummy monster 'mtmp' won't
+ have necessary eshk data for replmon() -> replshk() */
+ if (mtmp2->isshk) {
+ neweshk(mtmp);
+ *ESHK(mtmp) = *ESHK(mtmp2);
+ if (ESHK(mtmp2)->bill_p != 0
+ && ESHK(mtmp2)->bill_p != (struct bill_x *) -1000)
+ ESHK(mtmp)->bill_p = &(ESHK(mtmp)->bill[0]);
+ mtmp->isshk = 1;
+ }
replmon(mtmp, mtmp2);
newsym(mtmp2->mx, mtmp2->my); /* Might now be invisible */
/*
* Attempt to revive the given corpse, return the revived monster if
* successful. Note: this does NOT use up the corpse if it fails.
+ * If corpse->quan is more than 1, only one corpse will be affected
+ * and only one monster will be resurrected.
*/
struct monst *
revive(corpse, by_hero)
struct obj *container;
coord xy;
xchar x, y;
+ boolean one_of;
int montype, container_nesting = 0;
if (corpse->otyp != CORPSE) {
break; /* x,y are 0 */
}
}
- if (!x || !y ||
+ if (!x || !y
/* Rules for revival from containers:
- - the container cannot be locked
- - the container cannot be heavily nested (>2 is arbitrary)
- - the container cannot be a statue or bag of holding
- (except in very rare cases for the latter)
- */
- (container && (container->olocked || container_nesting > 2
- || container->otyp == STATUE
- || (container->otyp == BAG_OF_HOLDING && rn2(40)))))
+ * - the container cannot be locked
+ * - the container cannot be heavily nested (>2 is arbitrary)
+ * - the container cannot be a statue or bag of holding
+ * (except in very rare cases for the latter)
+ */
+ || (container && (container->olocked || container_nesting > 2
+ || container->otyp == STATUE
+ || (container->otyp == BAG_OF_HOLDING && rn2(40)))))
return (struct monst *) 0;
/* record the object's location now that we're sure where it is */
x = xy.x, y = xy.y;
}
- if (mons[montype].mlet == S_EEL && !IS_POOL(levl[x][y].typ)) {
- if (by_hero && cansee(x,y))
+ if ((mons[montype].mlet == S_EEL && !IS_POOL(levl[x][y].typ))
+ || (mons[montype].mlet == S_TROLL
+ && uwep && uwep->oartifact == ART_TROLLSBANE)) {
+ if (by_hero && cansee(x, y))
/*JP
pline("%s twitches feebly.",
*/
} else if (has_omonst(corpse)) {
/* use saved traits */
xy.x = x, xy.y = y;
- mtmp = montraits(corpse, &xy);
+ mtmp = montraits(corpse, &xy, FALSE);
if (mtmp && mtmp->mtame && !mtmp->isminion)
wary_dog(mtmp, TRUE);
} else {
mtmp->mundetected = 0;
newsym(mtmp->mx, mtmp->my);
}
- if (mtmp->m_ap_type)
+ if (M_AP_TYPE(mtmp))
seemimic(mtmp);
+ one_of = (corpse->quan > 1L);
+ if (one_of)
+ corpse = splitobj(corpse, 1L);
+
/* if this is caused by the hero there might be a shop charge */
if (by_hero) {
struct monst *shkp = 0;
x = corpse->ox, y = corpse->oy;
- if (costly_spot(x, y))
+ if (costly_spot(x, y)
+ && (carried(corpse) ? corpse->unpaid : !corpse->no_charge))
shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
- if (cansee(x, y))
+ if (cansee(x, y)) {
+ char buf[BUFSZ];
+
+#if 1 /*JP*//* \8e\80\91Ì\96¼\82Í\90æ\82É; Strcpy\82É\82È\82é */
+ Strcpy(buf, corpse_xname(corpse, (const char *) 0, CXN_NO_PFX));
+#endif
#if 0 /*JP*/
- pline(
- "%s glows iridescently.",
- upstart(corpse_xname(corpse, (const char *) 0, CXN_PFX_THE)));
-#else
- pline(
- "%s\82Í\93ø\90F\82É\8bP\82¢\82½\81D",
- upstart(corpse_xname(corpse, (const char *) 0, CXN_PFX_THE)));
+ Strcpy(buf, one_of ? "one of " : "");
+#else /* \8cê\8f\87\82Í\95Ï\82í\82Á\82Ä\82¢\82é */
+ if (one_of) {
+ Strcat(buf, "\82Ì\88ê\82Â");
+ }
+#endif
+#if 0 /*JP*//* \82±\82±\82Å\81u\82 \82È\82½\82Ì\81v\82Í\95s\8e©\91R */
+ /* shk_your: "the " or "your " or "<mon>'s " or "<Shk>'s ".
+ If the result is "Shk's " then it will be ambiguous:
+ is Shk the mon carrying it, or does Shk's shop own it?
+ Let's not worry about that... */
+ (void) shk_your(eos(buf), corpse);
#endif
- else if (shkp)
+ if (one_of)
+ corpse->quan++; /* force plural */
+#if 0 /*JP*//* \8aù\82É\90Ý\92è\8dÏ\82Ý */
+ Strcat(buf, corpse_xname(corpse, (const char *) 0, CXN_NO_PFX));
+#endif
+ if (one_of) /* could be simplified to ''corpse->quan = 1L;'' */
+ corpse->quan--;
+/*JP
+ pline("%s glows iridescently.", upstart(buf));
+*/
+ pline("%s\82Í\93ø\90F\82É\8bP\82¢\82½\81D", upstart(buf));
+ } else if (shkp) {
/* need some prior description of the corpse since
stolen_value() will refer to the object as "it" */
/*JP
pline("A corpse is resuscitated.");
*/
pline("\8e\80\91Ì\82ª\91h\90¶\82µ\82½\81D");
-
+ }
/* don't charge for shopkeeper's own corpse if we just revived him */
if (shkp && mtmp != shkp)
(void) stolen_value(corpse, x, y, (boolean) shkp->mpeaceful,
ghost = find_mid(m_id, FM_FMON);
if (ghost && ghost->data == &mons[PM_GHOST]) {
if (canseemon(ghost))
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s is suddenly drawn into its former body!",
#else
pline("%s\82Í\93Ë\91R\82à\82Æ\82Ì\91Ì\82É\88ø\82«\8d\9e\82Ü\82ê\82½\81I",
}
/* monster retains its name */
- if (has_oname(corpse))
+ if (has_oname(corpse) && !unique_corpstat(mtmp->data))
mtmp = christen_monst(mtmp, ONAME(corpse));
/* partially eaten corpse yields wounded monster */
if (corpse->oeaten)
struct monst *mtmp2;
char owner[BUFSZ], corpse[BUFSZ];
boolean youseeit;
- int once = 0, res = 0;
+ int res = 0;
youseeit = (mon == &youmonst) ? TRUE : canseemon(mon);
otmp2 = (mon == &youmonst) ? invent : mon->minvent;
+ owner[0] = corpse[0] = '\0'; /* lint suppression */
while ((otmp = otmp2) != 0) {
otmp2 = otmp->nobj;
if (otmp->otyp != CORPSE)
continue;
/* save the name; the object is liable to go away */
- if (youseeit)
+ if (youseeit) {
Strcpy(corpse,
corpse_xname(otmp, (const char *) 0, CXN_SINGULAR));
+ Shk_Your(owner, otmp); /* includes a trailing space */
+ }
- /* for a merged group, only one is revived; should this be fixed? */
+ /* for a stack, only one is revived */
if ((mtmp2 = revive(otmp, !context.mon_moving)) != 0) {
++res;
- if (youseeit) {
- if (!once++)
-/*JP
- Strcpy(owner, (mon == &youmonst) ? "Your"
-*/
- Strcpy(owner, (mon == &youmonst) ? "\82 \82È\82½"
- : s_suffix(Monnam(mon)));
+ if (youseeit)
/*JP
- pline("%s %s suddenly comes alive!", owner, corpse);
+ pline("%s%s suddenly comes alive!", owner, corpse);
*/
- pline("%s\82Ì%s\82Í\93Ë\91R\90¶\96½\82ð\91Ñ\82Ñ\82½\81I", owner, corpse);
- } else if (canseemon(mtmp2))
+ pline("%s%s\82Í\93Ë\91R\90¶\96½\82ð\91Ñ\82Ñ\82½\81I", owner, corpse);
+ else if (canseemon(mtmp2))
/*JP
pline("%s suddenly appears!", Amonnam(mtmp2));
*/
* possibly carried by you or a monster
*/
boolean
-drain_item(obj)
-register struct obj *obj;
+drain_item(obj, by_you)
+struct obj *obj;
+boolean by_you;
{
boolean u_ring;
return FALSE;
/* Charge for the cost of the object */
- costly_alteration(obj, COST_DRAIN);
+ if (by_you)
+ costly_alteration(obj, COST_DRAIN);
/* Drain the object and any implied effects */
obj->spe--;
if ((obj->owornmask & W_RING) && u_ring)
u.udaminc--;
break;
+ case RIN_PROTECTION:
+ if (u_ring)
+ context.botl = 1; /* bot() will recalc u.uac */
+ break;
case HELM_OF_BRILLIANCE:
if ((obj->owornmask & W_ARMH) && (obj == uarmh)) {
ABON(A_INT)--;
context.botl = 1;
}
break;
- case RIN_PROTECTION:
- context.botl = 1;
+ default:
break;
}
+ if (context.botl)
+ bot();
if (carried(obj))
update_inventory();
return TRUE;
default:
/* if all else fails... */
pm_index = PM_STRAW_GOLEM;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
material = "";
#else
material = "\95¨\91Ì";
polyuse(obj, okind, (int) mons[pm_index].cwt);
if (mtmp && cansee(mtmp->mx, mtmp->my)) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("Some %sobjects meld, and %s arises from the pile!", material,
a_monnam(mtmp));
#else
int id;
{
struct obj *otmp;
- xchar ox, oy;
+ xchar ox = 0, oy = 0;
+ long old_wornmask, new_wornmask = 0L;
boolean can_merge = (id == STRANGE_OBJECT);
int obj_location = obj->where;
/* now change it into something laid by the hero */
while (tryct--) {
- mnum = can_be_hatched(random_monster());
+ mnum = can_be_hatched(random_monster(rn2));
if (mnum != NON_PM && !dead_species(mnum, TRUE)) {
otmp->spe = 1; /* laid by hero */
set_corpsenm(otmp, mnum); /* also sets hatch timer */
otmp->cursed = obj->cursed;
otmp->blessed = obj->blessed;
- otmp->oeroded = obj->oeroded;
- otmp->oeroded2 = obj->oeroded2;
- if (!is_flammable(otmp) && !is_rustprone(otmp))
- otmp->oeroded = 0;
- if (!is_corrodeable(otmp) && !is_rottable(otmp))
- otmp->oeroded2 = 0;
- if (is_damageable(otmp))
- otmp->oerodeproof = obj->oerodeproof;
+
+ if (erosion_matters(otmp)) {
+ if (is_flammable(otmp) || is_rustprone(otmp))
+ otmp->oeroded = obj->oeroded;
+ if (is_corrodeable(otmp) || is_rottable(otmp))
+ otmp->oeroded2 = obj->oeroded2;
+ if (is_damageable(otmp))
+ otmp->oerodeproof = obj->oerodeproof;
+ }
/* Keep chest/box traps and poisoned ammo if we may */
if (obj->otrapped && Is_box(otmp))
/* update the weight */
otmp->owt = weight(otmp);
- /* handle polymorph of worn item: stone-to-flesh cast on self can
- affect multiple objects at once, but their new forms won't
- produce any side-effects; a single worn item dipped into potion
- of polymorph can produce side-effects but those won't yield out
- of sequence messages because current polymorph is finished */
- if (obj_location == OBJ_INVENT && obj->owornmask) {
- long old_wornmask = obj->owornmask & ~(W_ART | W_ARTI),
- new_wornmask = wearslot(otmp);
- boolean was_twohanded = bimanual(obj), was_twoweap = u.twoweap;
-
- remove_worn_item(obj, TRUE);
- /* if the new form can be worn in the same slot, make it so
- [possible extension: if it could be worn in some other
- slot which is currently unfilled, wear it there instead] */
- if ((old_wornmask & W_QUIVER) != 0L) {
- setuqwep(otmp);
- } else if ((old_wornmask & W_SWAPWEP) != 0L) {
- if (was_twohanded || !bimanual(otmp))
- setuswapwep(otmp);
- if (was_twoweap && uswapwep)
- u.twoweap = TRUE;
- } else if ((old_wornmask & W_WEP) != 0L) {
- if (was_twohanded || !bimanual(otmp) || !uarms)
- setuwep(otmp);
- if (was_twoweap && uwep && !bimanual(uwep))
- u.twoweap = TRUE;
- } else if ((old_wornmask & new_wornmask) != 0L) {
- new_wornmask &= old_wornmask;
- setworn(otmp, new_wornmask);
- set_wear(otmp); /* Armor_on() for side-effects */
- }
- }
-
- /* ** we are now done adjusting the object ** */
+ /*
+ * ** we are now done adjusting the object (except possibly wearing it) **
+ */
+ (void) get_obj_location(obj, &ox, &oy, BURIED_TOO | CONTAINED_TOO);
+ old_wornmask = obj->owornmask & ~(W_ART | W_ARTI);
/* swap otmp for obj */
replace_object(obj, otmp);
if (obj_location == OBJ_INVENT) {
freeinv_core(obj);
addinv_core1(otmp);
addinv_core2(otmp);
+ /*
+ * Handle polymorph of worn item. Stone-to-flesh cast on self can
+ * affect multiple objects at once, but their new forms won't
+ * produce any side-effects. A single worn item dipped into potion
+ * of polymorph can produce side-effects but those won't yield out
+ * of sequence messages because current polymorph is finished.
+ */
+ if (old_wornmask) {
+ boolean was_twohanded = bimanual(obj), was_twoweap = u.twoweap;
+
+ /* wearslot() returns a mask which might have multiple bits set;
+ narrow that down to the bit(s) currently in use */
+ new_wornmask = wearslot(otmp) & old_wornmask;
+ remove_worn_item(obj, TRUE);
+ /* if the new form can be worn in the same slot, make it so */
+ if ((new_wornmask & W_WEP) != 0L) {
+ if (was_twohanded || !bimanual(otmp) || !uarms)
+ setuwep(otmp);
+ if (was_twoweap && uwep && !bimanual(uwep))
+ u.twoweap = TRUE;
+ } else if ((new_wornmask & W_SWAPWEP) != 0L) {
+ if (was_twohanded || !bimanual(otmp))
+ setuswapwep(otmp);
+ if (was_twoweap && uswapwep)
+ u.twoweap = TRUE;
+ } else if ((new_wornmask & W_QUIVER) != 0L) {
+ setuqwep(otmp);
+ } else if (new_wornmask) {
+ setworn(otmp, new_wornmask);
+ /* set_wear() might result in otmp being destroyed if
+ worn amulet has been turned into an amulet of change */
+ set_wear(otmp);
+ otmp = wearmask_to_obj(new_wornmask); /* might be Null */
+ }
+ } /* old_wornmask */
} else if (obj_location == OBJ_FLOOR) {
- ox = otmp->ox, oy = otmp->oy; /* set by replace_object() */
if (obj->otyp == BOULDER && otmp->otyp != BOULDER
&& !does_block(ox, oy, &levl[ox][oy]))
unblock_point(ox, oy);
block_point(ox, oy);
}
- if ((!carried(otmp) || obj->unpaid)
- && get_obj_location(otmp, &ox, &oy, BURIED_TOO | CONTAINED_TOO)
- && costly_spot(ox, oy)) {
- register struct monst *shkp =
- shop_keeper(*in_rooms(ox, oy, SHOPBASE));
+ /* note: if otmp is gone, billing for it was handled by useup() */
+ if (((otmp && !carried(otmp)) || obj->unpaid) && costly_spot(ox, oy)) {
+ struct monst *shkp = shop_keeper(*in_rooms(ox, oy, SHOPBASE));
if ((!obj->no_charge
|| (Has_contents(obj)
&& inhishop(shkp)) {
if (shkp->mpeaceful) {
if (*u.ushops
- && *in_rooms(u.ux, u.uy, 0)
- == *in_rooms(shkp->mx, shkp->my, 0)
- && !costly_spot(u.ux, u.uy))
+ && (*in_rooms(u.ux, u.uy, 0)
+ == *in_rooms(shkp->mx, shkp->my, 0))
+ && !costly_spot(u.ux, u.uy)) {
make_angry_shk(shkp, ox, oy);
- else {
+ } else {
/*JP
pline("%s gets angry!", Monnam(shkp));
*/
{
int res = 1; /* affected object by default */
struct permonst *ptr;
- struct monst *mon;
+ struct monst *mon, *shkp;
struct obj *item;
xchar oox, ooy;
boolean smell = FALSE, golem_xform = FALSE;
break;
}
if (obj->otyp == STATUE) {
- /* animate_statue() forces all golems to become flesh golems
- */
+ /* animate_statue() forces all golems to become flesh golems */
mon = animate_statue(obj, oox, ooy, ANIMATE_SPELL, (int *) 0);
} else { /* (obj->otyp == FIGURINE) */
if (golem_xform)
ptr = &mons[PM_FLESH_GOLEM];
mon = makemon(ptr, oox, ooy, NO_MINVENT);
if (mon) {
- if (costly_spot(oox, ooy) && !obj->no_charge) {
- if (costly_spot(u.ux, u.uy))
- addtobill(obj, carried(obj), FALSE, FALSE);
- else
- stolen_value(obj, oox, ooy, TRUE, FALSE);
+ if (costly_spot(oox, ooy)
+ && (carried(obj) ? obj->unpaid : !obj->no_charge)) {
+ shkp = shop_keeper(*in_rooms(oox, ooy, SHOPBASE));
+ stolen_value(obj, oox, ooy,
+ (shkp && shkp->mpeaceful), FALSE);
}
if (obj->timed)
obj_stop_timers(obj);
else
delobj(obj);
if (cansee(mon->mx, mon->my))
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline_The("figurine %sanimates!",
golem_xform ? "turns to flesh and " : "");
#else
* from its inventory as a result of the change.
* If the items fall to the floor, they are not
* subject to direct subsequent polymorphing
- * themselves on that same zap. This makes it
- * consistent with items that remain in the
- * monster's inventory. They are not polymorphed
- * either.
+ * themselves on that same zap. This makes it
+ * consistent with items that remain in the monster's
+ * inventory. They are not polymorphed either.
* UNDEAD_TURNING - When an undead creature gets killed via
* undead turning, prevent its corpse from being
* immediately revived by the same effect.
* menu_drop(), askchain() - inventory traversal where multiple
* Drop can alter the invent chain while traversal
* is in progress (bhito isn't involved).
+ * destroy_item(), destroy_mitem() - inventory traversal where
+ * item destruction can trigger drop or destruction of
+ * other item(s) and alter the invent or mon->minvent
+ * chain, possibly recursively.
*
* The bypass bit on all objects is reset each turn, whenever
* context.bypasses is set.
(void) boxlock(obj, otmp);
if (obj_shudders(obj)) {
- boolean cover =
- ((obj == level.objects[u.ux][u.uy]) && u.uundetected
- && hides_under(youmonst.data));
+ boolean cover = ((obj == level.objects[u.ux][u.uy])
+ && u.uundetected
+ && hides_under(youmonst.data));
if (cansee(obj->ox, obj->oy))
learn_it = TRUE;
if (Is_container(obj) || obj->otyp == STATUE) {
obj->cknown = obj->lknown = 1;
if (!obj->cobj) {
- boolean catbox = SchroedingersBox(obj);
-
+/*JP
+ pline("%s empty.", Tobjnam(obj, "are"));
+*/
+ pline("%s\82Í\8bó\82Á\82Û\82¾\81D", xname(obj));
+ } else if (SchroedingersBox(obj)) {
/* we don't want to force alive vs dead
determination for Schroedinger's Cat here,
so just make probing be inconclusive for it */
- if (catbox)
- obj->cknown = 0;
-/*JP
- pline("%s empty.", Tobjnam(obj, catbox ? "seem" : "are"));
-*/
- pline("%s\82Í\8bó\82Á\82Û%s\82¾\81D", xname(obj), catbox ? "\82Ì\82æ\82¤" : "");
+#if 0 /*JP:T*/
+ You("aren't sure whether %s has %s or its corpse inside.",
+ the(xname(obj)),
+ /* unfortunately, we can't tell whether rndmonnam()
+ picks a form which can't leave a corpse */
+ an(Hallucination ? rndmonnam((char *) 0) : "cat"));
+#else
+ pline("%s\82É%s\82ª\93ü\82Á\82Ä\82¢\82é\82Ì\82©\82»\82Ì\8e\80\91Ì\82ª\93ü\82Á\82Ä\82¢\82é\82Ì\82©\82í\82©\82ç\82È\82¢\81D",
+ xname(obj),
+ /* unfortunately, we can't tell whether rndmonnam()
+ picks a form which can't leave a corpse */
+ Hallucination ? rndmonnam((char *) 0) : "\94L");
+#endif
+ obj->cknown = 0;
} else {
struct obj *o;
+
/* view contents (not recursively) */
for (o = obj->cobj; o; o = o->nobj)
o->dknown = 1; /* "seen", even if blind */
You_hear("\89½\82©\82ª\8dÓ\82¯\82é\89¹\82ð\95·\82¢\82½\81D");
}
} else {
+ int oox = obj->ox;
+ int ooy = obj->oy;
if (context.mon_moving
? !breaks(obj, obj->ox, obj->oy)
: !hero_breaks(obj, obj->ox, obj->oy, FALSE))
maybelearnit = FALSE; /* nothing broke */
+ else
+ newsym_force(oox,ooy);
res = 0;
}
if (maybelearnit)
#endif
break;
case SPE_DRAIN_LIFE:
- (void) drain_item(obj);
+ (void) drain_item(obj, TRUE);
break;
case WAN_TELEPORTATION:
case SPE_TELEPORT_AWAY:
if (obj->otyp == EGG) {
revive_egg(obj);
} else if (obj->otyp == CORPSE) {
+ struct monst *mtmp;
+ xchar ox, oy;
int corpsenm = corpse_revive_type(obj);
+ char *corpsname = cxname_singular(obj);
- res = !!revive(obj, TRUE);
- if (res && Role_if(PM_HEALER)) {
- if (Hallucination && !Deaf) {
-/*JP
- You_hear("the sound of a defibrillator.");
-*/
- You_hear("\8f\9c\8d×\93®\8aí\82Ì\89¹\82ð\95·\82¢\82½\81D");
- learn_it = TRUE;
- } else if (!Blind) {
-#if 0 /*JP*/
- You("observe %s %s change dramatically.",
- s_suffix(an(mons[corpsenm].mname)),
- nonliving(&mons[corpsenm]) ? "motility"
- : "health");
+ /* get corpse's location before revive() uses it up */
+ if (!get_obj_location(obj, &ox, &oy, 0))
+ ox = obj->ox, oy = obj->oy; /* won't happen */
+
+ mtmp = revive(obj, TRUE);
+ if (!mtmp) {
+ res = 0; /* no monster implies corpse was left intact */
+ } else {
+ if (cansee(ox, oy)) {
+ if (canspotmon(mtmp)) {
+#if 0 /*JP:T*/
+ pline("%s is resurrected!",
+ upstart(noname_monnam(mtmp, ARTICLE_THE)));
#else
- You("%s\82Ì%s\82ª\8c\80\93I\82É\95Ï\89»\82·\82é\82Ì\82ð\8c©\82½\81D",
- s_suffix(an(mons[corpsenm].mname)),
- nonliving(&mons[corpsenm]) ? "\89^\93®\90«"
- : "\8c\92\8dN");
+ pline("%s\82Í\90¶\82«\95Ô\82Á\82½\81I",
+ upstart(noname_monnam(mtmp, ARTICLE_THE)));
#endif
- learn_it = TRUE;
+ learn_it = TRUE;
+ } else {
+ /* saw corpse but don't see monster: maybe
+ mtmp is invisible, or has been placed at
+ a different spot than <ox,oy> */
+ if (!type_is_pname(&mons[corpsenm]))
+ corpsname = The(corpsname);
+/*JP
+ pline("%s disappears.", corpsname);
+*/
+ pline("%s\82Í\8fÁ\82¦\82½\81D", corpsname);
+ }
+ } else {
+ /* couldn't see corpse's location */
+ if (Role_if(PM_HEALER) && !Deaf
+ && !nonliving(&mons[corpsenm])) {
+ if (!type_is_pname(&mons[corpsenm]))
+ corpsname = an(corpsname);
+ if (!Hallucination)
+/*JP
+ You_hear("%s reviving.", corpsname);
+*/
+ You_hear("%s\82ª\90¶\82«\95Ô\82é\89¹\82ð\95·\82¢\82½\81D", corpsname);
+ else
+/*JP
+ You_hear("a defibrillator.");
+*/
+ You_hear("\8f\9c\8d×\93®\8aí\82Ì\89¹\82ð\95·\82¢\82½\81D");
+ learn_it = TRUE;
+ }
+ if (canspotmon(mtmp))
+ /* didn't see corpse but do see monster: it
+ has been placed somewhere other than <ox,oy>
+ or blind hero spots it with ESP */
+/*JP
+ pline("%s appears.", Monnam(mtmp));
+*/
+ pline("%s\82ª\8c»\82ê\82½\81D", Monnam(mtmp));
}
if (learn_it)
exercise(A_WIS, TRUE);
struct obj *otmp;
{
int dmg;
+
otmp->in_use = TRUE; /* in case losehp() is fatal */
/*JP
pline("%s suddenly explodes!", The(xname(otmp)));
if ((damage = zapyourself(obj, TRUE)) != 0) {
#if 0 /*JP*/
char buf[BUFSZ];
+
Sprintf(buf, "zapped %sself with a wand", uhim());
losehp(Maybe_Half_Phys(damage), buf, NO_KILLER_PREFIX);
#else
- losehp(Maybe_Half_Phys(damage), "\8e©\95ª\8e©\90g\82Ì\8fñ\82Ì\97Í\82ð\97\81\82Ñ\82Ä", KILLED_BY);
+ losehp(Maybe_Half_Phys(damage),
+ "\8e©\95ª\8e©\90g\82Ì\8fñ\82Ì\97Í\82ð\97\81\82Ñ\82Ä", KILLED_BY);
#endif
}
} else {
case WAN_CANCELLATION:
case SPE_CANCELLATION:
- (void) cancel_monst(&youmonst, obj, TRUE, FALSE, TRUE);
+ (void) cancel_monst(&youmonst, obj, TRUE, TRUE, TRUE);
break;
case SPE_DRAIN_LIFE:
learn_it = TRUE;
(void) unturn_dead(&youmonst);
if (is_undead(youmonst.data)) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
You_feel("frightened and %sstunned.",
Stunned ? "even more " : "");
#else
case SPE_EXTRA_HEALING:
learn_it = TRUE; /* (no effect for spells...) */
healup(d(6, obj->otyp == SPE_EXTRA_HEALING ? 8 : 4), 0, FALSE,
- (obj->otyp == SPE_EXTRA_HEALING));
+ (obj->blessed || obj->otyp == SPE_EXTRA_HEALING));
/*JP
You_feel("%sbetter.", obj->otyp == SPE_EXTRA_HEALING ? "much " : "");
*/
case WAN_LIGHT: /* (broken wand) */
/* assert( !ordinary ); */
damage = d(obj->spe, 25);
+ /*FALLTHRU*/
case EXPENSIVE_CAMERA:
if (!damage)
damage = 5;
learn_it = TRUE;
unpunish();
}
- if (u.utrap) { /* escape web or bear trap */
- (void) openholdingtrap(&youmonst, &learn_it);
- } else { /* trigger previously escaped trapdoor */
+ /* invent is hit iff hero doesn't escape from a trap */
+ if (!u.utrap || !openholdingtrap(&youmonst, &learn_it)) {
+ struct obj *otmp;
+ boolean boxing = FALSE;
+
+ /* unlock carried boxes */
+ for (otmp = invent; otmp; otmp = otmp->nobj)
+ if (Is_box(otmp)) {
+ (void) boxlock(otmp, obj);
+ boxing = TRUE;
+ }
+ if (boxing)
+ update_inventory(); /* in case any box->lknown has changed */
+
+ /* trigger previously escaped trapdoor */
(void) openfallingtrap(&youmonst, TRUE, &learn_it);
}
break;
case WAN_LOCKING:
case SPE_WIZARD_LOCK:
- if (!u.utrap) {
- (void) closeholdingtrap(&youmonst, &learn_it);
+ /* similar logic to opening; invent is hit iff no trap triggered */
+ if (u.utrap || !closeholdingtrap(&youmonst, &learn_it)) {
+ struct obj *otmp;
+ boolean boxing = FALSE;
+
+ /* lock carried boxes */
+ for (otmp = invent; otmp; otmp = otmp->nobj)
+ if (Is_box(otmp)) {
+ (void) boxlock(otmp, obj);
+ boxing = TRUE;
+ }
+ if (boxing)
+ update_inventory(); /* in case any box->lknown has changed */
}
break;
case WAN_DIGGING:
otmp->cknown = 1;
}
}
+ update_inventory();
learn_it = TRUE;
ustatusline();
break;
pline("\82¨\82í\81C\8cõ\82ª\92É\82¢%s", (dmg > 2 || u.mh <= 5) ? "\81I" : "\81D");
/* [composing killer/reason is superfluous here; if fatal, cause
of death will always be "killed while stuck in creature form"] */
+#if 0 /*JP*/
if (obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS)
ordinary = FALSE; /* say blasted rather than zapped */
+#endif
how = (obj->oclass != SPBOOK_CLASS)
? (const char *) ansimpleoname(obj)
/*JP
{
int steedhit = FALSE;
+ bhitpos.x = u.usteed->mx, bhitpos.y = u.usteed->my;
+ notonhead = FALSE;
switch (obj->otyp) {
/*
* Wands that are allowed to hit the steed
/* now handle special cases */
if (youdefend) {
- if (Upolyd) {
- if ((u.umonnum == PM_CLAY_GOLEM) && !Blind)
- pline(writing_vanishes, your);
-
- if (Unchanging)
+ if (Upolyd) { /* includes lycanthrope in creature form */
+ /*
+ * Return to normal form unless Unchanging.
+ * Hero in clay golem form dies if Unchanging.
+ * Does not cure lycanthropy or stop timed random polymorph.
+ */
+ if (u.umonnum == PM_CLAY_GOLEM) {
+ if (!Blind)
+ pline(writing_vanishes, your);
+ else /* note: "dark" rather than "heavy" is intentional... */
+#if 0 /*JP*/
+ You_feel("%s headed.", Hallucination ? "dark" : "light");
+#else /*\82¢\82¢\96ó\8cê\82ð\8ev\82¢\82Â\82©\82È\82¢\82Ì\82Å\8c¶\8ao\82Å\83\81\83b\83Z\81[\83W\82ð\95Ï\82¦\82È\82¢ */
+ You_feel("\8cy\82Í\82¸\82Ý\82¾\82Á\82½\8bC\82ª\82µ\82½\81D");
+#endif
+ u.mh = 0; /* fatal; death handled by rehumanize() */
+ }
+ if (Unchanging && u.mh > 0)
/*JP
Your("amulet grows hot for a moment, then cools.");
*/
rehumanize();
}
} else {
- mdef->mcan = TRUE;
-
- if (is_were(mdef->data) && mdef->data->mlet != S_HUMAN)
+ mdef->mcan = 1;
+ /* force shapeshifter into its base form */
+ if (M_AP_TYPE(mdef) != M_AP_NOTHING)
+ seemimic(mdef);
+ /* [not 'else if'; chameleon might have been hiding as a mimic] */
+ if (mdef->cham >= LOW_PM) {
+ /* note: newcham() uncancels shapechangers (resets m->mcan
+ to 0), but only for shapechangers whose m->cham is already
+ NON_PM and we just verified that it's LOW_PM or higher */
+ newcham(mdef, &mons[mdef->cham], FALSE, FALSE);
+ mdef->cham = NON_PM; /* cancelled shapeshifter can't shift */
+ }
+ if (is_were(mdef->data) && !is_human(mdef->data))
were_change(mdef);
if (mdef->data == &mons[PM_CLAY_GOLEM]) {
if (canseemon(mdef))
+#if 0 /*JP*/
pline(writing_vanishes, s_suffix(mon_nam(mdef)));
-
+#else
+ pline(writing_vanishes, mon_nam(mdef));
+#endif
+ /* !allow_cancel_kill is for Magicbane, where clay golem
+ will be killed somewhere back up the call/return chain... */
if (allow_cancel_kill) {
if (youattack)
killed(mdef);
if (is_db_wall(x, y) && find_drawbridge(&xx, &yy)) {
open_drawbridge(xx, yy);
disclose = TRUE;
- } else if (u.dz > 0 && (x == xdnstair && y == ydnstair) &&
+ } else if (u.dz > 0 && (x == xdnstair && y == ydnstair)
/* can't use the stairs down to quest level 2 until
leader "unlocks" them; give feedback if you try */
- on_level(&u.uz, &qstart_level) && !ok_to_quest()) {
+ && on_level(&u.uz, &qstart_level) && !ok_to_quest()) {
/*JP
pline_The("stairs seem to ripple momentarily.");
*/
&& !Is_qstart(&u.uz)) {
int dmg;
/* similar to zap_dig() */
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("A rock is dislodged from the %s and falls on your %s.",
ceiling(x, y), body_part(HEAD));
#else
/* locking transforms hole into trapdoor */
ttmp->ttyp = TRAPDOOR;
if (Blind || !ttmp->tseen) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("Some %s swirls beneath you.",
is_ice(x, y) ? "frost" : "dust");
#else
case SPE_STONE_TO_FLESH:
if (e->engr_type == ENGRAVE) {
/* only affects things in stone */
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline_The(Hallucination
? "floor runs like butter!"
: "edges on the floor get smoother.");
*/
pline("%s\82Í\89½\82©\82É\96½\92\86\82µ\82½\81D", str);
else
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s %s %s%s", The(str), vtense(str, "hit"),
mon_nam(mtmp), force);
#else
register const char *str;
register struct monst *mtmp;
{
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline(
"%s %s %s.", The(str), vtense(str, "miss"),
((cansee(bhitpos.x, bhitpos.y) || canspotmon(mtmp)) && flags.verbose)
{
int tr = (range / 4);
int tmp = range - ((tr > 0) ? rnd(tr) : 0);
+
*skipstart = tmp;
*skipend = tmp - ((tmp / 4) * rnd(3));
if (*skipend >= tmp)
struct monst *
bhit(ddx, ddy, range, weapon, fhitm, fhito, pobj)
register int ddx, ddy, range; /* direction and range */
-int weapon; /* see values in hack.h */
+enum bhit_call_types weapon; /* defined in hack.h */
int FDECL((*fhitm), (MONST_P, OBJ_P)), /* fns called when mon/obj hit */
FDECL((*fhito), (OBJ_P, OBJ_P));
struct obj **pobj; /* object tossed/used, set to NULL
* if object is destroyed */
{
- struct monst *mtmp;
+ struct monst *mtmp, *result = (struct monst *) 0;
struct obj *obj = *pobj;
uchar typ;
boolean shopdoor = FALSE, point_blank = TRUE;
boolean in_skip = FALSE, allow_skip = FALSE;
+ boolean tethered_weapon = FALSE;
int skiprange_start = 0, skiprange_end = 0, skipcount = 0;
if (weapon == KICKED_WEAPON) {
if (weapon == FLASHED_LIGHT) {
tmp_at(DISP_BEAM, cmap_to_glyph(S_flashbeam));
+ } else if (weapon == THROWN_TETHERED_WEAPON && obj) {
+ tethered_weapon = TRUE;
+ weapon = THROWN_WEAPON; /* simplify 'if's that follow below */
+ tmp_at(DISP_TETHER, obj_to_glyph(obj, rn2_on_display_rng));
} else if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM)
- tmp_at(DISP_FLASH, obj_to_glyph(obj));
+ tmp_at(DISP_FLASH, obj_to_glyph(obj, rn2_on_display_rng));
while (range-- > 0) {
int x, y;
}
if (is_pick(obj) && inside_shop(x, y)
- && (mtmp = shkcatch(obj, x, y))) {
+ && (mtmp = shkcatch(obj, x, y)) != 0) {
tmp_at(DISP_END, 0);
- return mtmp;
+ result = mtmp;
+ goto bhit_done;
}
typ = levl[bhitpos.x][bhitpos.y].typ;
- /* iron bars will block anything big enough */
- if ((weapon == THROWN_WEAPON || weapon == KICKED_WEAPON)
- && typ == IRONBARS && hits_bars(pobj, x - ddx, y - ddy,
- point_blank ? 0 : !rn2(5), 1)) {
- /* caveat: obj might now be null... */
- obj = *pobj;
- bhitpos.x -= ddx;
- bhitpos.y -= ddy;
- break;
+ /* iron bars will block anything big enough and break some things */
+ if (weapon == THROWN_WEAPON || weapon == KICKED_WEAPON) {
+ if (typ == IRONBARS
+ && hits_bars(pobj, x - ddx, y - ddy, bhitpos.x, bhitpos.y,
+ point_blank ? 0 : !rn2(5), 1)) {
+ /* caveat: obj might now be null... */
+ obj = *pobj;
+ bhitpos.x -= ddx;
+ bhitpos.y -= ddy;
+ break;
+ } else if (obj->lamplit && !Blind) {
+ show_transient_light(obj, bhitpos.x, bhitpos.y);
+ }
}
if (weapon == ZAPPED_WAND && find_drawbridge(&x, &y)) {
if (is_pool(bhitpos.x, bhitpos.y) && !mtmp) {
in_skip = TRUE;
if (!Blind)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s %s%s.", Yname2(obj), otense(obj, "skip"),
skipcount ? " again" : "");
#else
if (range > 3) /* another bounce? */
skiprange(range, &skiprange_start, &skiprange_end);
} else if (mtmp && M_IN_WATER(mtmp->data)) {
- if ((!Blind && canseemon(mtmp)) || sensemon(mtmp))
-#if 0 /*JP*/
+ if (!Blind && canspotmon(mtmp))
+#if 0 /*JP:T*/
pline("%s %s over %s.", Yname2(obj), otense(obj, "pass"),
mon_nam(mtmp));
#else
pline("%s\82Í%s\82ð\94ò\82Ñ\89z\82¦\82½\81D", Yname2(obj),
mon_nam(mtmp));
#endif
+ mtmp = (struct monst *) 0;
}
}
- if (mtmp && !(in_skip && M_IN_WATER(mtmp->data))) {
+ /* if mtmp is a shade and missile passes harmlessly through it,
+ give message and skip it in order to keep going */
+ if (mtmp && (weapon == THROWN_WEAPON || weapon == KICKED_WEAPON)
+ && shade_miss(&youmonst, mtmp, obj, TRUE, TRUE))
+ mtmp = (struct monst *) 0;
+
+ if (mtmp) {
notonhead = (bhitpos.x != mtmp->mx || bhitpos.y != mtmp->my);
if (weapon == FLASHED_LIGHT) {
/* FLASHED_LIGHT hitting invisible monster should
(void) flash_hits_mon(mtmp, obj);
} else {
tmp_at(DISP_END, 0);
- return mtmp; /* caller will call flash_hits_mon */
+ result = mtmp; /* caller will call flash_hits_mon */
+ goto bhit_done;
}
} else if (weapon == INVIS_BEAM) {
/* Like FLASHED_LIGHT, INVIS_BEAM should continue
prepared for multiple hits so just get first one
that's either visible or could see its invisible
self. [No tmp_at() cleanup is needed here.] */
- if (!mtmp->minvis || perceives(mtmp->data))
- return mtmp;
+ if (!mtmp->minvis || perceives(mtmp->data)) {
+ result = mtmp;
+ goto bhit_done;
+ }
} else if (weapon != ZAPPED_WAND) {
+
/* THROWN_WEAPON, KICKED_WEAPON */
- tmp_at(DISP_END, 0);
+ if (!tethered_weapon)
+ tmp_at(DISP_END, 0);
+
if (cansee(bhitpos.x, bhitpos.y) && !canspotmon(mtmp))
map_invisible(bhitpos.x, bhitpos.y);
- return mtmp;
+ result = mtmp;
+ goto bhit_done;
} else {
/* ZAPPED_WAND */
(*fhitm)(mtmp, obj);
|| ship_object(obj, bhitpos.x, bhitpos.y,
costly_spot(bhitpos.x, bhitpos.y)))) {
tmp_at(DISP_END, 0);
- return (struct monst *) 0;
+ goto bhit_done; /* result == (struct monst *) 0 */
}
}
if (weapon == ZAPPED_WAND && (IS_DOOR(typ) || typ == SDOOR)) {
if (levl[bhitpos.x][bhitpos.y].doormask == D_BROKEN
&& *in_rooms(bhitpos.x, bhitpos.y, SHOPBASE)) {
shopdoor = TRUE;
- add_damage(bhitpos.x, bhitpos.y, 400L);
+ add_damage(bhitpos.x, bhitpos.y, SHOP_DOOR_COST);
}
}
break;
&& obj->otyp == HEAVY_IRON_BALL) {
struct obj *bobj;
struct trap *t;
+
if ((bobj = sobj_at(BOULDER, x, y)) != 0) {
if (cansee(x, y))
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s hits %s.", The(distant_name(obj, xname)),
an(xname(bobj)));
#else
if (!test_move(x - ddx, y - ddy, ddx, ddy, TEST_MOVE)) {
/* nb: it didn't hit anything directly */
if (cansee(x, y))
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s jerks to an abrupt halt.",
The(distant_name(obj, xname))); /* lame */
#else
#endif
range = 0;
} else if (Sokoban && (t = t_at(x, y)) != 0
- && (t->ttyp == PIT || t->ttyp == SPIKED_PIT
- || t->ttyp == HOLE || t->ttyp == TRAPDOOR)) {
+ && (is_pit(t->ttyp) || is_hole(t->ttyp))) {
/* hero falls into the trap, so ball stops */
range = 0;
}
point_blank = FALSE; /* affects passing through iron bars */
}
- if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM)
+ if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM && !tethered_weapon)
tmp_at(DISP_END, 0);
if (shopdoor)
*/
pay_for_damage("\94j\89ó\82·\82é", FALSE);
- return (struct monst *) 0;
+ bhit_done:
+ if (weapon == THROWN_WEAPON || weapon == KICKED_WEAPON)
+ transient_light_cleanup();
+
+ return result;
}
/* process thrown boomerang, which travels a curving path...
if (bhitpos.x == u.ux && bhitpos.y == u.uy) { /* ct == 9 */
if (Fumbling || rn2(20) >= ACURR(A_DEX)) {
/* we hit ourselves */
- (void) thitu(10 + obj->spe, dmgval(obj, &youmonst), obj,
+ (void) thitu(10 + obj->spe, dmgval(obj, &youmonst), &obj,
/*JP
"boomerang");
*/
return (struct monst *) 0;
}
-/* used by buzz(); also used by munslime(muse.c); returns damage to mon */
+/* used by buzz(); also used by munslime(muse.c); returns damage applied
+ to mon; note: caller is responsible for killing mon if damage is fatal */
int
zhitm(mon, type, nd, ootmp)
register struct monst *mon;
case ZT_ACID:
if (Acid_resistance) {
/*JP
- pline_The("acid doesn't hurt.");
+ pline_The("%s doesn't hurt.", hliquid("acid"));
*/
- pline("\8e_\82Å\82Í\8f\9d\82Â\82©\82È\82©\82Á\82½\81D");
+ pline_The("%s\82Å\82Í\8f\9d\82Â\82©\82È\82©\82Á\82½\81D", hliquid("\8e_"));
dam = 0;
} else {
/*JP
- pline_The("acid burns!");
+ pline_The("%s burns!", hliquid("acid"));
*/
- pline("\8e_\82Å\8fÄ\82¯\82½\81I");
+ pline_The("%s\82Å\8fÄ\82¯\82½\81I", hliquid("\8e_"));
dam = d(nd, 6);
exercise(A_STR, FALSE);
}
if (type < 0)
monkilled(mon, (char *) 0, -AD_RBRE);
else
- xkilled(mon, 2);
+ xkilled(mon, XKILL_NOMSG | XKILL_NOCORPSE);
+}
+
+void
+buzz(type, nd, sx, sy, dx, dy)
+int type, nd;
+xchar sx, sy;
+int dx, dy;
+{
+ dobuzz(type, nd, sx, sy, dx, dy, TRUE);
}
/*
* called with dx = dy = 0 with vertical bolts
*/
void
-buzz(type, nd, sx, sy, dx, dy)
+dobuzz(type, nd, sx, sy, dx, dy, say)
register int type, nd;
register xchar sx, sy;
register int dx, dy;
+boolean say; /* Announce out of sight hit/miss events if true */
{
int range, abstype = abs(type) % 10;
- struct rm *lev;
register xchar lsx, lsy;
struct monst *mon;
coord save_bhitpos;
if (!u.ustuck)
u.uswallow = 0;
else
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s rips into %s%s", The(fltxt), mon_nam(u.ustuck),
exclam(tmp));
#else
/* Using disintegration from the inside only makes a hole... */
if (tmp == MAGIC_COOKIE)
u.ustuck->mhp = 0;
- if (u.ustuck->mhp < 1)
+ if (DEADMONSTER(u.ustuck))
killed(u.ustuck);
return;
}
sx += dx;
lsy = sy;
sy += dy;
- if (isok(sx, sy) && (lev = &levl[sx][sy])->typ) {
- mon = m_at(sx, sy);
- if (cansee(sx, sy)) {
- /* reveal/unreveal invisible monsters before tmp_at() */
- if (mon && !canspotmon(mon))
- map_invisible(sx, sy);
- else if (!mon && glyph_is_invisible(levl[sx][sy].glyph)) {
- unmap_object(sx, sy);
- newsym(sx, sy);
- }
- if (ZAP_POS(lev->typ) || (isok(lsx, lsy) && cansee(lsx, lsy)))
- tmp_at(sx, sy);
- delay_output(); /* wait a little */
- }
- } else
+ if (!isok(sx, sy) || levl[sx][sy].typ == STONE)
goto make_bounce;
+ mon = m_at(sx, sy);
+ if (cansee(sx, sy)) {
+ /* reveal/unreveal invisible monsters before tmp_at() */
+ if (mon && !canspotmon(mon))
+ map_invisible(sx, sy);
+ else if (!mon)
+ (void) unmap_invisible(sx, sy);
+ if (ZAP_POS(levl[sx][sy].typ)
+ || (isok(lsx, lsy) && cansee(lsx, lsy)))
+ tmp_at(sx, sy);
+ delay_output(); /* wait a little */
+ }
+
/* hit() and miss() need bhitpos to match the target */
bhitpos.x = sx, bhitpos.y = sy;
/* Fireballs only damage when they explode */
- if (type != ZT_SPELL(ZT_FIRE))
+ if (type != ZT_SPELL(ZT_FIRE)) {
range += zap_over_floor(sx, sy, type, &shopdamage, 0);
+ /* zap with fire -> melt ice -> drown monster, so monster
+ found and cached above might not be here any more */
+ mon = m_at(sx, sy);
+ }
if (mon) {
if (type == ZT_SPELL(ZT_FIRE))
break;
if (type >= 0)
mon->mstrategy &= ~STRAT_WAITMASK;
- buzzmonst:
+ buzzmonst:
+ notonhead = (mon->mx != bhitpos.x || mon->my != bhitpos.y);
if (zap_hit(find_mac(mon), spell_type)) {
if (mon_reflects(mon, (char *) 0)) {
if (cansee(mon->mx, mon->my)) {
hit(fltxt, mon, exclam(0));
shieldeff(mon->mx, mon->my);
-#if 0 /*JP*/
+#if 0 /*JP:T*/
(void) mon_reflects(mon,
"But it reflects from %s %s!");
#else
hit(fltxt, mon, ".");
*/
hit(fltxt, mon, "\81D");
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s absorbs the deadly %s!", Monnam(mon),
type == ZT_BREATH(ZT_DEATH) ? "blast"
: "ray");
if (tmp == MAGIC_COOKIE) { /* disintegration */
disintegrate_mon(mon, type, fltxt);
- } else if (mon->mhp < 1) {
- if (type < 0)
+ } else if (DEADMONSTER(mon)) {
+ if (type < 0) {
+ /* mon has just been killed by another monster */
monkilled(mon, fltxt, AD_RBRE);
- else
- killed(mon);
+ } else {
+ int xkflags = XKILL_GIVEMSG; /* killed(mon); */
+
+ /* killed by hero; we know 'type' isn't negative;
+ if it's fire, highly flammable monsters leave
+ no corpse; don't bother reporting that they
+ "burn completely" -- unnecessary verbosity */
+ if ((type % 10 == ZT_FIRE)
+ /* paper golem or straw golem */
+ && completelyburns(mon->data))
+ xkflags |= XKILL_NOCORPSE;
+ xkilled(mon, xkflags);
+ }
} else {
if (!otmp) {
/* normal non-fatal hit */
- hit(fltxt, mon, exclam(tmp));
+ if (say || canseemon(mon))
+ hit(fltxt, mon, exclam(tmp));
} else {
/* some armor was destroyed; no damage done */
if (canseemon(mon))
-/*JP
+#if 0 /*JP:T*/
pline("%s %s is disintegrated!",
-*/
- pline("%s\82Ì%s\82Í\82±\82È\82²\82È\82É\82È\82Á\82½\81I",
s_suffix(Monnam(mon)),
distant_name(otmp, xname));
+#else
+ pline("%s\82Ì%s\82Í\82±\82È\82²\82È\82É\82È\82Á\82½\81I",
+ Monnam(mon),
+ distant_name(otmp, xname));
+#endif
m_useup(mon, otmp);
}
if (mon_could_move && !mon->mcanmove) /* ZT_SLEEP */
}
range -= 2;
} else {
- miss(fltxt, mon);
+ if (say || canseemon(mon))
+ miss(fltxt, mon);
}
} else if (sx == u.ux && sy == u.uy && range >= 0) {
nomul(0);
pline("%s\82Í\82 \82È\82½\82É\96½\92\86\82µ\82½\81I", fltxt);
if (Reflecting) {
if (!Blind) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
(void) ureflects("But %s reflects from your %s!",
"it");
#else
nomul(0);
}
- if (!ZAP_POS(lev->typ) || (closed_door(sx, sy) && (range >= 0))) {
- int bounce;
+ if (!ZAP_POS(levl[sx][sy].typ)
+ || (closed_door(sx, sy) && range >= 0)) {
+ int bounce, bchance;
uchar rmn;
+ boolean fireball;
- make_bounce:
- if (type == ZT_SPELL(ZT_FIRE)) {
- sx = lsx;
- sy = lsy;
- break; /* fireballs explode before the wall */
- }
+ make_bounce:
+ bchance = (levl[sx][sy].typ == STONE) ? 10
+ : (In_mines(&u.uz) && IS_WALL(levl[sx][sy].typ)) ? 20
+ : 75;
bounce = 0;
- range--;
- if (range && isok(lsx, lsy) && cansee(lsx, lsy)) {
-#if 0 /*JP*/
- pline("%s %s!", The(fltxt),
- Is_airlevel(&u.uz)
- ? "vanishes into the aether"
- : "bounces");
-#else
- pline("%s\82Í%s\81I", The(fltxt),
- Is_airlevel(&u.uz)
- ? "\83G\81[\83e\83\8b\8bó\8aÔ\82É\8fÁ\82¦\82½"
- : "\94½\8eË\82µ\82½");
-#endif
- if (Is_airlevel(&u.uz)) goto get_out_buzz;
+ fireball = (type == ZT_SPELL(ZT_FIRE));
+ if ((--range > 0 && isok(lsx, lsy) && cansee(lsx, lsy))
+ || fireball) {
+ if (Is_airlevel(&u.uz)) { /* nothing to bounce off of */
+/*JP
+ pline_The("%s vanishes into the aether!", fltxt);
+*/
+ pline_The("%s\82Í\83G\81[\83e\83\8b\8bó\8aÔ\82É\8fÁ\82¦\82½\81I", fltxt);
+ if (fireball)
+ type = ZT_WAND(ZT_FIRE); /* skip pending fireball */
+ break;
+ } else if (fireball) {
+ sx = lsx;
+ sy = lsy;
+ break; /* fireballs explode before the obstacle */
+ } else
+/*JP
+ pline_The("%s bounces!", fltxt);
+*/
+ pline_The("%s\82Í\94½\8eË\82µ\82½\81I", fltxt);
}
- if (!dx || !dy || !rn2(20)) {
+ if (!dx || !dy || !rn2(bchance)) {
dx = -dx;
dy = -dy;
} else {
switch (bounce) {
case 0:
- dx = -dx; /* fall into... */
+ dx = -dx;
+ /*FALLTHRU*/
case 1:
dy = -dy;
break;
tmp_at(DISP_END, 0);
if (type == ZT_SPELL(ZT_FIRE))
explode(sx, sy, type, d(12, 6), 0, EXPL_FIERY);
- get_out_buzz:
if (shopdamage)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pay_for_damage(abstype == ZT_FIRE
? "burn away"
: abstype == ZT_COLD
? "shatter"
/* "damage" indicates wall rather than door */
: abstype == ZT_ACID
- ? "damage"
+ ? "damage"
: abstype == ZT_DEATH
? "disintegrate"
: "destroy",
{
struct rm *lev = &levl[x][y];
struct obj *otmp;
+ struct monst *mtmp;
if (!msg)
/*JP
msg = "The ice crackles and melts.";
*/
msg = "\95X\82Í\83s\83L\83s\83L\96Â\82è\81C\97n\82¯\82½\81D";
- if (lev->typ == DRAWBRIDGE_UP) {
+ if (lev->typ == DRAWBRIDGE_UP || lev->typ == DRAWBRIDGE_DOWN) {
lev->drawbridgemask &= ~DB_ICE; /* revert to DB_MOAT */
} else { /* lev->typ == ICE */
#ifdef STUPID
}
if (x == u.ux && y == u.uy)
spoteffects(TRUE); /* possibly drown, notice objects */
+ else if (is_pool(x, y) && (mtmp = m_at(x, y)) != 0)
+ (void) minliquid(mtmp);
}
#define MIN_ICE_TIME 50
{
xchar x, y;
long where = arg->a_long;
+ boolean save_mon_moving = context.mon_moving; /* will be False */
+ /* melt_ice -> minliquid -> mondead|xkilled shouldn't credit/blame hero */
+ context.mon_moving = TRUE; /* hero isn't causing this ice to melt */
y = (xchar) (where & 0xFFFF);
x = (xchar) ((where >> 16) & 0xFFFF);
/* melt_ice does newsym when appropriate */
melt_ice(x, y, "Some ice melts away.");
*/
melt_ice(x, y, "\95X\82ª\8f\82µ\97n\82¯\82½\81D");
+ context.mon_moving = save_mon_moving;
}
/* Burn floor scrolls, evaporate pools, etc... in a single square.
if (is_ice(x, y)) {
melt_ice(x, y, (char *) 0);
} else if (is_pool(x, y)) {
-/*JP
- const char *msgtxt = "You hear hissing gas.";
-*/
- const char *msgtxt = "\82µ\82ã\81[\82Á\82Æ\82¢\82¤\83K\83X\82Ì\89¹\82ð\95·\82¢\82½\81D";
+#if 0 /*JP*/
+ const char *msgtxt = (!Deaf)
+ ? "You hear hissing gas." /* Deaf-aware */
+ : (type >= 0)
+ ? "That seemed remarkably uneventful."
+ : (const char *) 0;
+#else
+ const char *msgtxt = (!Deaf)
+ ? "\82µ\82ã\81[\82Á\82Æ\82¢\82¤\83K\83X\82Ì\89¹\82ð\95·\82¢\82½\81D" /* Deaf-aware */
+ : (type >= 0)
+ ? "\82±\82ê\82Í\8bÁ\82\82Ù\82Ç\82È\82ñ\82Å\82à\82È\82³\82»\82¤\82¾\81D"
+ : (const char *) 0;
+#endif
if (lev->typ != POOL) { /* MOAT or DRAWBRIDGE_UP */
if (see_it)
msgtxt = "\82·\82±\82µ\90\85\82ª\8fö\94\82µ\82½\81D";
} else {
rangemod -= 3;
- lev->typ = ROOM;
+ lev->typ = ROOM, lev->flags = 0;
t = maketrap(x, y, PIT);
if (t)
t->tseen = 1;
*/
msgtxt = "\90\85\82ª\8fö\94\82µ\82½\81D";
}
- Norep("%s", msgtxt);
+ if (msgtxt)
+ Norep("%s", msgtxt);
if (lev->typ == ROOM)
newsym(x, y);
} else if (IS_FOUNTAIN(lev->typ)) {
case ZT_COLD:
if (is_pool(x, y) || is_lava(x, y)) {
- boolean lava = is_lava(x, y);
- boolean moat = is_moat(x, y);
+ boolean lava = is_lava(x, y),
+ moat = is_moat(x, y);
if (lev->typ == WATER) {
/* For now, don't let WATER freeze. */
if (see_it)
/*JP
- pline_The("water freezes for a moment.");
+ pline_The("%s freezes for a moment.", hliquid("water"));
*/
- pline("\90\85\82Í\88ê\8fu\93\80\82Á\82½\81D");
+ pline_The("%s\82Í\88ê\8fu\93\80\82Á\82½\81D", hliquid("\90\85"));
else
/*JP
You_hear("a soft crackling.");
You_hear("\83s\83L\81I\82Æ\82¢\82¤\89¹\82ð\95·\82¢\82½\81D");
rangemod -= 1000; /* stop */
} else {
+ char buf[BUFSZ];
+
+ Strcpy(buf, waterbody_name(x, y)); /* for MOAT */
rangemod -= 3;
if (lev->typ == DRAWBRIDGE_UP) {
lev->drawbridgemask &= ~DB_UNDER; /* clear lava */
lev->drawbridgemask |= (lava ? DB_FLOOR : DB_ICE);
} else {
- if (!lava)
- lev->icedpool =
- (lev->typ == POOL ? ICED_POOL : ICED_MOAT);
- lev->typ = (lava ? ROOM : ICE);
+ lev->icedpool = lava ? 0
+ : (lev->typ == POOL) ? ICED_POOL
+ : ICED_MOAT;
+ lev->typ = lava ? ROOM : ICE;
}
bury_objs(x, y);
if (see_it) {
if (lava)
/*JP
- Norep("The lava cools and solidifies.");
+ Norep("The %s cools and solidifies.", hliquid("lava"));
*/
- Norep("\97n\8aâ\82Í\97â\82¦\8cÅ\82Ü\82Á\82½\81D");
+ Norep("%s\82Í\97â\82¦\8cÅ\82Ü\82Á\82½\81D", hliquid("lava"));
else if (moat)
/*JP
- Norep("The %s is bridged with ice!",
+ Norep("The %s is bridged with ice!", buf);
*/
- Norep("%s\82É\95X\82Ì\8b´\82ª\82©\82¯\82ç\82ê\82½\81I",
- waterbody_name(x, y));
+ Norep("%s\82É\95X\82Ì\8b´\82ª\82©\82¯\82ç\82ê\82½\81I", buf);
else
/*JP
- Norep("The water freezes.");
+ Norep("The %s freezes.", hliquid("water"));
*/
- Norep("\90\85\82Í\93\80\82Á\82½\81D");
+ Norep("%s\82Í\93\80\82Á\82½\81D", hliquid("\95X"));
newsym(x, y);
} else if (!lava)
/*JP
vision_full_recalc = 1;
} else if (u.utrap && u.utraptype == TT_LAVA) {
if (Passes_walls) {
- u.utrap = 0;
/*JP
You("pass through the now-solid rock.");
*/
You("\82¢\82Ü\8cÅ\82\82È\82Á\82½\82Î\82©\82è\82Ì\90Î\82Ì\92\86\82ð\82·\82è\94²\82¯\82½\81D");
+ reset_utrap(TRUE);
} else {
- u.utrap = rn1(50, 20);
- u.utraptype = TT_INFLOOR;
+ set_utrap(rn1(50, 20), TT_INFLOOR);
/*JP
You("are firmly stuck in the cooling rock.");
*/
}
break; /* ZT_COLD */
+ case ZT_POISON_GAS:
+ (void) create_gas_cloud(x, y, 1, 8);
+ break;
+
case ZT_ACID:
if (lev->typ == IRONBARS) {
if ((lev->wall_info & W_NONDIGGABLE) != 0) {
Norep("%s\82ª\97n\82¯\82½\81D", defsyms[S_bars].explanation);
if (*in_rooms(x, y, SHOPBASE)) {
/* in case we ever have a shop bounded by bars */
- lev->typ = ROOM;
+ lev->typ = ROOM, lev->flags = 0;
if (see_it)
newsym(x, y);
- add_damage(x, y, (type >= 0) ? 300L : 0L);
+ add_damage(x, y, (type >= 0) ? SHOP_BARS_COST : 0L);
if (type >= 0)
*shopdamage = TRUE;
} else {
- lev->typ = DOOR;
- lev->doormask = D_NODOOR;
+ lev->typ = DOOR, lev->doormask = D_NODOOR;
if (see_it)
newsym(x, y);
}
/* set up zap text for possible door feedback; for exploding wand, we
want "the blast" rather than "your blast" even if hero caused it */
yourzap = (type >= 0 && !exploding_wand_typ);
-#if 0 /*JP*/
+#if 0 /*JP:T*/
zapverb = "blast"; /* breath attack or wand explosion */
#else
zapverb = "\8fÕ\8c\82"; /* breath attack or wand explosion */
#endif
if (!exploding_wand_typ) {
if (abs(type) < ZT_SPELL(0))
-#if 0 /*JP*/
+#if 0 /*JP:T*/
zapverb = "bolt"; /* wand zap */
#else
zapverb = "\8cõ\90ü"; /* wand zap */
(except on rogue level) */
newsym(x, y);
if (see_it)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s %s reveals a secret door.",
yourzap ? "Your" : "The", zapverb);
#else
hear_txt = "\83s\83L\83s\83L\82Æ\82¢\82¤\89¹\82ð\95·\82¢\82½\81D";
break;
default:
- def_case:
+ def_case:
if (exploding_wand_typ > 0) {
/* Magical explosion from misc exploding wand */
if (exploding_wand_typ == WAN_STRIKING) {
*/
pline_The("\94à\82Í\96³\8f\9d\82¾\81D");
else
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline_The("door absorbs %s %s!", yourzap ? "your" : "the",
zapverb);
#else
if (new_doormask >= 0) { /* door gets broken */
if (*in_rooms(x, y, SHOPBASE)) {
if (type >= 0) {
- add_damage(x, y, 400L);
+ add_damage(x, y, SHOP_DOOR_COST);
*shopdamage = TRUE;
} else /* caused by monster */
add_damage(x, y, 0L);
pline("%s\81D", !Blind ? "\82Û\82í\82Á\82Æ\89\8c\82ª\82 \82ª\82Á\82½" : "\89\8c\82Ì\83v\83\93\82Æ\82¢\82¤\93õ\82¢\82ª\82µ\82½");
}
if ((mon = m_at(x, y)) != 0) {
- /* Cannot use wakeup() which also angers the monster */
- mon->msleeping = 0;
- if (mon->m_ap_type)
- seemimic(mon);
+ wakeup(mon, FALSE);
if (type >= 0) {
- setmangry(mon);
+ setmangry(mon, TRUE);
if (mon->ispriest && *in_rooms(mon->mx, mon->my, TEMPLE))
ghod_hitsu(mon);
if (mon->isshk && !*u.ushops)
if (billable(&shkp, obj, objroom, FALSE)) {
/* shop message says "you owe <shk> <$> for it!" so we need
to precede that with a message explaining what "it" is */
+/*JP
You("fracture %s %s.", s_suffix(shkname(shkp)), xname(obj));
+*/
+ You("%s\82Ì%s\82ð\89ó\82µ\82½\81D", shkname(shkp), xname(obj));
breakobj(obj, x, y, TRUE, FALSE); /* charges for shop goods */
}
}
{ "\82Î\82ç\82Î\82ç\82É\89ó\82ê\82Ä\94\9a\94\82µ\82½", "\82Î\82ç\82Î\82ç\82É\89ó\82ê\82Ä\94\9a\94\82µ\82½", "\8fñ\82Ì\94\9a\94\82Å" },
};
-void
-destroy_item(osym, dmgtyp)
-register int osym, dmgtyp;
+/* guts of destroy_item(), which ought to be called maybe_destroy_items();
+ caller must decide whether obj is eligible */
+STATIC_OVL void
+destroy_one_item(obj, osym, dmgtyp)
+struct obj *obj;
+int osym, dmgtyp;
{
- register struct obj *obj, *obj2;
- int dmg, xresist, skip;
long i, cnt, quan;
- int dindx;
+ int dmg, xresist, skip, dindx;
const char *mult;
boolean physical_damage;
- for (obj = invent; obj; obj = obj2) {
- obj2 = obj->nobj;
- physical_damage = FALSE;
- if (obj->oclass != osym)
- continue; /* test only objs of type osym */
- if (obj->oartifact)
- continue; /* don't destroy artifacts */
- if (obj->in_use && obj->quan == 1L)
- continue; /* not available */
- xresist = skip = 0;
- /* lint suppression */
- dmg = dindx = 0;
- quan = 0L;
-
- switch (dmgtyp) {
- case AD_COLD:
- if (osym == POTION_CLASS && obj->otyp != POT_OIL) {
- quan = obj->quan;
- dindx = 0;
- dmg = rnd(4);
- } else
- skip++;
- break;
- case AD_FIRE:
- xresist = (Fire_resistance && obj->oclass != POTION_CLASS
- && obj->otyp != GLOB_OF_GREEN_SLIME);
+ physical_damage = FALSE;
+ xresist = skip = 0;
+ /* lint suppression */
+ dmg = dindx = 0;
+ quan = 0L;
- if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
- skip++;
- if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
- skip++;
- if (!Blind)
+ switch (dmgtyp) {
+ case AD_COLD:
+ if (osym == POTION_CLASS && obj->otyp != POT_OIL) {
+ quan = obj->quan;
+ dindx = 0;
+ dmg = rnd(4);
+ } else
+ skip++;
+ break;
+ case AD_FIRE:
+ xresist = (Fire_resistance && obj->oclass != POTION_CLASS
+ && obj->otyp != GLOB_OF_GREEN_SLIME);
+ if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
+ skip++;
+ if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
+ skip++;
+ if (!Blind)
#if 0 /*JP:T*/
- pline("%s glows a strange %s, but remains intact.",
- The(xname(obj)), hcolor("dark red"));
+ pline("%s glows a strange %s, but remains intact.",
+ The(xname(obj)), hcolor("dark red"));
#else
- pline("%s\82Í\8aï\96\82É%s\8bP\82¢\82½\82ª\89½\82à\95Ï\89»\82µ\82È\82©\82Á\82½\81D",
- xname(obj), jconj_adj(hcolor("\88Ã\8a\8c\90F\82Ì")));
+ pline("%s\82Í\8aï\96\82É%s\8bP\82¢\82½\82ª\89½\82à\95Ï\89»\82µ\82È\82©\82Á\82½\81D",
+ xname(obj), jconj_adj(hcolor("\88Ã\8a\8c\90F\82Ì")));
#endif
-
+ }
+ quan = obj->quan;
+ switch (osym) {
+ case POTION_CLASS:
+ dindx = (obj->otyp != POT_OIL) ? 1 : 2;
+ dmg = rnd(6);
+ break;
+ case SCROLL_CLASS:
+ dindx = 3;
+ dmg = 1;
+ break;
+ case SPBOOK_CLASS:
+ dindx = 4;
+ dmg = 1;
+ break;
+ case FOOD_CLASS:
+ if (obj->otyp == GLOB_OF_GREEN_SLIME) {
+ dindx = 1; /* boil and explode */
+ dmg = (obj->owt + 19) / 20;
+ } else {
+ skip++;
}
- quan = obj->quan;
- switch (osym) {
- case POTION_CLASS:
- dindx = (obj->otyp != POT_OIL) ? 1 : 2;
- dmg = rnd(6);
- break;
- case SCROLL_CLASS:
- dindx = 3;
- dmg = 1;
- break;
- case SPBOOK_CLASS:
- dindx = 4;
- dmg = 1;
- break;
- case FOOD_CLASS:
- if (obj->otyp == GLOB_OF_GREEN_SLIME) {
- dindx = obj->owt / 20;
- dmg = 1;
- } else {
- skip++;
- }
- break;
- default:
+ break;
+ default:
+ skip++;
+ break;
+ }
+ break;
+ case AD_ELEC:
+ xresist = (Shock_resistance && obj->oclass != RING_CLASS);
+ quan = obj->quan;
+ switch (osym) {
+ case RING_CLASS:
+ if (obj->otyp == RIN_SHOCK_RESISTANCE) {
skip++;
break;
}
+ dindx = 5;
+ dmg = 0;
break;
- case AD_ELEC:
- xresist = (Shock_resistance && obj->oclass != RING_CLASS);
- quan = obj->quan;
- switch (osym) {
- case RING_CLASS:
- if (obj->otyp == RIN_SHOCK_RESISTANCE) {
- skip++;
- break;
- }
- dindx = 5;
- dmg = 0;
- break;
- case WAND_CLASS:
- if (obj->otyp == WAN_LIGHTNING) {
- skip++;
- break;
- }
-#if 0
- if (obj == current_wand) { skip++; break; }
-#endif
- dindx = 6;
- dmg = rnd(10);
- break;
- default:
+ case WAND_CLASS:
+ if (obj->otyp == WAN_LIGHTNING) {
skip++;
break;
}
+#if 0
+ if (obj == current_wand) { skip++; break; }
+#endif
+ dindx = 6;
+ dmg = rnd(10);
break;
default:
skip++;
break;
}
- if (!skip) {
- if (obj->in_use)
- --quan; /* one will be used up elsewhere */
- for (i = cnt = 0L; i < quan; i++)
- if (!rn2(3))
- cnt++;
+ break;
+ default:
+ skip++;
+ break;
+ }
- if (!cnt)
- continue;
-#if 0 /*JP*/
- mult = (cnt == quan)
- ? (quan > 1) ? "All of your " : "Your"
- : (cnt == 1L) ? "One of your" : "Some of your";
-#else
- mult = (cnt == quan)
- ? ""
- : (cnt == 1L) ? "\82Ì\82Ð\82Æ\82Â" : "\82Ì\82¢\82\82Â\82©";
-#endif
-#if 0 /*JP*/
- pline("%s %s %s!", mult, xname(obj),
- destroy_strings[dindx][(cnt > 1L)]);
+ if (!skip) {
+ if (obj->in_use)
+ --quan; /* one will be used up elsewhere */
+ for (i = cnt = 0L; i < quan; i++)
+ if (!rn2(3))
+ cnt++;
+
+ if (!cnt)
+ return;
+#if 0 /*JP:T*/
+ mult = (cnt == 1L)
+ ? ((quan == 1L) ? "Your" /* 1 of 1 */
+ : "One of your") /* 1 of N */
+ : ((cnt < quan) ? "Some of your" /* n of N */
+ : (quan == 2L) ? "Both of your" /* 2 of 2 */
+ : "All of your"); /* N of N */
+ pline("%s %s %s!", mult, xname(obj),
+ destroy_strings[dindx][(cnt > 1L)]);
#else
- pline("\82 \82È\82½\82Ì%s%s\82Í%s\81I", xname(obj), mult,
- destroy_strings[dindx][(cnt > 1L)]);
+ mult = (cnt == 1L)
+ ? ((quan == 1L) ? "" /* 1 of 1 */
+ : "\82Ì\82Ð\82Æ\82Â") /* 1 of N */
+ : ((cnt < quan) ? "\82Ì\82¢\82\82Â\82©" /* n of N */
+ : "\82Ì\91S\82Ä"); /* N of N */
+ pline("\82 \82È\82½\82Ì%s%s\82Í%s\81I", xname(obj), mult,
+ destroy_strings[dindx][(cnt > 1L)]);
#endif
- if (osym == POTION_CLASS && dmgtyp != AD_COLD) {
- if (!breathless(youmonst.data) || haseyes(youmonst.data))
- potionbreathe(obj);
- }
- if (obj->owornmask) {
- if (obj->owornmask & W_RING) /* ring being worn */
- Ring_gone(obj);
- else
- setnotworn(obj);
- }
- if (obj == current_wand)
- current_wand = 0; /* destroyed */
- for (i = 0; i < cnt; i++)
- useup(obj);
- if (dmg) {
- if (xresist)
-/*JP
- You("aren't hurt!");
-*/
- You("\8f\9d\82Â\82©\82È\82¢\81I");
- else {
- const char *how = destroy_strings[dindx][2];
- boolean one = (cnt == 1L);
-
- if (physical_damage)
- dmg = Maybe_Half_Phys(dmg);
- losehp(dmg, one ? how : (const char *) makeplural(how),
- one ? KILLED_BY_AN : KILLED_BY);
- exercise(A_STR, FALSE);
- }
+ if (osym == POTION_CLASS && dmgtyp != AD_COLD) {
+ if (!breathless(youmonst.data) || haseyes(youmonst.data))
+ potionbreathe(obj);
+ }
+ if (obj->owornmask) {
+ if (obj->owornmask & W_RING) /* ring being worn */
+ Ring_gone(obj);
+ else
+ setnotworn(obj);
+ }
+ if (obj == current_wand)
+ current_wand = 0; /* destroyed */
+ for (i = 0; i < cnt; i++)
+ useup(obj);
+ if (dmg) {
+ if (xresist) {
+/*JP
+ You("aren't hurt!");
+*/
+ You("\8f\9d\82Â\82©\82È\82¢\81I");
+ } else {
+ const char *how = destroy_strings[dindx][2];
+ boolean one = (cnt == 1L);
+
+ if (dmgtyp == AD_FIRE && osym == FOOD_CLASS)
+/*JP
+ how = "exploding glob of slime";
+*/
+ how = "\83X\83\89\83C\83\80\82Ì\82Ë\82Î\82Ë\82Î\82Ì\94\9a\94\82Å";
+ if (physical_damage)
+ dmg = Maybe_Half_Phys(dmg);
+ losehp(dmg, one ? how : (const char *) makeplural(how),
+ one ? KILLED_BY_AN : KILLED_BY);
+ exercise(A_STR, FALSE);
}
}
}
+}
+
+/* target items of specified class for possible destruction */
+void
+destroy_item(osym, dmgtyp)
+int osym, dmgtyp;
+{
+ register struct obj *obj;
+ int i, deferral_indx = 0;
+ /* 1+52+1: try to handle a full inventory; it doesn't matter if
+ inventory actually has more, even if everything should be deferred */
+ unsigned short deferrals[1 + 52 + 1]; /* +1: gold, overflow */
+
+ (void) memset((genericptr_t) deferrals, 0, sizeof deferrals);
+ /*
+ * Sometimes destroying an item can change inventory aside from
+ * the item itself (cited case was a potion of unholy water; when
+ * boiled, potionbreathe() caused hero to transform into were-beast
+ * form and that resulted in dropping or destroying some worn armor).
+ *
+ * Unlike other uses of the object bybass mechanism, destroy_item()
+ * can be called multiple times for the same event. So we have to
+ * explicitly clear it before each use and hope no other section of
+ * code expects it to retain previous value.
+ *
+ * Destruction of a ring of levitation or form change which pushes
+ * off levitation boots could drop hero onto a fire trap that
+ * could destroy other items and we'll get called recursively. Or
+ * onto a trap which transports hero elsewhere, which won't disrupt
+ * traversal but could yield message sequencing issues. So we
+ * defer handling such things until after rest of inventory has
+ * been processed. If some other combination of items and events
+ * triggers a recursive call, rest of inventory after the triggering
+ * item will be skipped by the outer call since the inner one will
+ * have set the bypass bits of the whole list.
+ *
+ * [Unfortunately, death while poly'd into flyer and subsequent
+ * rehumanization could also drop hero onto a trap, and there's no
+ * straightforward way to defer that. Things could be improved by
+ * redoing this to use two passes, first to collect a list or array
+ * of o_id and quantity of what is targetted for destruction,
+ * second pass to handle the destruction.]
+ */
+ bypass_objlist(invent, FALSE); /* clear bypass bit for invent */
+
+ while ((obj = nxt_unbypassed_obj(invent)) != 0) {
+ if (obj->oclass != osym)
+ continue; /* test only objs of type osym */
+ if (obj->oartifact)
+ continue; /* don't destroy artifacts */
+ if (obj->in_use && obj->quan == 1L)
+ continue; /* not available */
+
+ /* if loss of this item might dump us onto a trap, hold off
+ until later because potential recursive destroy_item() will
+ result in setting bypass bits on whole chain--we would skip
+ the rest as already processed once control returns here */
+ if (deferral_indx < SIZE(deferrals)
+ && ((obj->owornmask != 0L
+ && (objects[obj->otyp].oc_oprop == LEVITATION
+ || objects[obj->otyp].oc_oprop == FLYING))
+ /* destroyed wands and potions of polymorph don't trigger
+ polymorph so don't need to be deferred */
+ || (obj->otyp == POT_WATER && u.ulycn >= LOW_PM
+ && (Upolyd ? obj->blessed : obj->cursed)))) {
+ deferrals[deferral_indx++] = obj->o_id;
+ continue;
+ }
+ /* obj is eligible; maybe destroy it */
+ destroy_one_item(obj, osym, dmgtyp);
+ }
+ /* if we saved some items for later (most likely just a worn ring
+ of levitation) and they're still in inventory, handle them now */
+ for (i = 0; i < deferral_indx; ++i) {
+ /* note: obj->nobj is only referenced when obj is skipped;
+ having obj be dropped or destroyed won't affect traversal */
+ for (obj = invent; obj; obj = obj->nobj)
+ if (obj->o_id == deferrals[i]) {
+ destroy_one_item(obj, osym, dmgtyp);
+ break;
+ }
+ }
return;
}
struct monst *mtmp;
int osym, dmgtyp;
{
- struct obj *obj, *obj2;
+ struct obj *obj;
int skip, tmp = 0;
long i, cnt, quan;
int dindx;
}
vis = canseemon(mtmp);
- for (obj = mtmp->minvent; obj; obj = obj2) {
- obj2 = obj->nobj;
+
+ /* see destroy_item(); object destruction could disrupt inventory list */
+ bypass_objlist(mtmp->minvent, FALSE); /* clear bypass bit for minvent */
+
+ while ((obj = nxt_unbypassed_obj(mtmp->minvent)) != 0) {
if (obj->oclass != osym)
continue; /* test only objs of type osym */
skip = 0;
if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
skip++;
if (vis)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s glows a strange %s, but remains intact.",
The(distant_name(obj, xname)), hcolor("dark red"));
#else
break;
case FOOD_CLASS:
if (obj->otyp == GLOB_OF_GREEN_SLIME) {
- dindx = obj->owt / 20;
- tmp++;
+ dindx = 1; /* boil and explode */
+ tmp += (obj->owt + 19) / 20;
} else {
skip++;
}
if (!cnt)
continue;
if (vis)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s%s %s!",
(cnt == obj->quan) ? "" : (cnt > 1L) ? "Some of "
: "One of ",
int resisted;
int alev, dlev;
+ /* fake players always pass resistance test against Conflict
+ (this doesn't guarantee that they're never affected by it) */
+ if (oclass == RING_CLASS && !damage && !tell && is_mplayer(mtmp->data))
+ return 1;
+
/* attack level */
switch (oclass) {
case WAND_CLASS:
if (damage) {
mtmp->mhp -= damage;
- if (mtmp->mhp < 1) {
+ if (DEADMONSTER(mtmp)) {
if (m_using)
monkilled(mtmp, "", AD_RBRE);
else
void
makewish()
{
- char buf[BUFSZ], promptbuf[BUFSZ];
+ char buf[BUFSZ] = DUMMY;
+ char promptbuf[BUFSZ];
struct obj *otmp, nothing;
int tries = 0;
You("may wish for an object.");
*/
You("\96]\82Ý\82Ì\82à\82Ì\82ð\8eè\82É\93ü\82ê\82ç\82ê\82é\81D");
-retry:
+ retry:
/*JP
Strcpy(promptbuf, "For what do you wish");
*/
buf[0] = '\0';
} else if (!strcmpi(buf, "help")) {
wishcmdassist(MAXWISHTRY - tries);
+ buf[0] = '\0'; /* for EDIT_GETLIN */
goto retry;
}
/*