-/* NetHack 3.6 potion.c $NHDT-Date: 1446861768 2015/11/07 02:02:48 $ $NHDT-Branch: master $:$NHDT-Revision: 1.121 $ */
+/* NetHack 3.6 potion.c $NHDT-Date: 1573848199 2019/11/15 20:03:19 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.167 $ */
/* 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-2022 */
/* JNetHack may be freely redistributed. See license for details. */
#include "hack.h"
if (!xtime && old) {
if (talk)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
You_feel("%s now.",
Hallucination ? "less wobbly" : "a bit steadier");
#else
/*JP
You("%s...", stagger(youmonst.data, "stagger"));
*/
- You("%s\81D\81D\81D", stagger(youmonst.data, "\82\82ç\82\82ç\82µ\82½"));
+ You("\82\82ç\82\82ç\82µ\82½\81D\81D\81D");
}
}
if ((!xtime && old) || (xtime && !old))
set_itimeout(&HStun, xtime);
}
+/* Sick is overloaded with both fatal illness and food poisoning (via
+ u.usick_type bit mask), but delayed killer can only support one or
+ the other at a time. They should become separate intrinsics.... */
void
make_sick(xtime, cause, talk, type)
long xtime;
boolean talk;
int type;
{
+ struct kinfo *kptr;
long old = Sick;
-#if 0
+#if 0 /* tell player even if hero is unconscious */
if (Unaware)
talk = FALSE;
#endif
context.botl = TRUE;
}
+ kptr = find_delayed_killer(SICK);
if (Sick) {
exercise(A_CON, FALSE);
- delayed_killer(SICK, KILLED_BY_AN, cause);
+ /* setting delayed_killer used to be unconditional, but that's
+ not right when make_sick(0) is called to cure food poisoning
+ if hero was also fatally ill; this is only approximate */
+ if (xtime || !old || !kptr) {
+ int kpfx = ((cause && !strcmp(cause, "#wizintrinsic"))
+ ? KILLED_BY : KILLED_BY_AN);
+
+ delayed_killer(SICK, kpfx, cause);
+ }
} else
- dealloc_killer(find_delayed_killer(SICK));
+ dealloc_killer(kptr);
}
void
{
long old = Slimed;
-#if 0
+#if 0 /* tell player even if hero is unconscious */
if (Unaware)
msg = 0;
#endif
- if ((!xtime && old) || (xtime && !old)) {
+ set_itimeout(&Slimed, xtime);
+ if ((xtime != 0L) ^ (old != 0L)) {
+ context.botl = TRUE;
if (msg)
- pline1(msg);
- context.botl = 1;
+ pline("%s", msg);
}
- set_itimeout(&Slimed, xtime);
- if (!Slimed)
+ if (!Slimed) {
dealloc_killer(find_delayed_killer(SLIMED));
+ /* fake appearance is set late in turn-to-slime countdown */
+ if (U_AP_TYPE == M_AP_MONSTER
+ && youmonst.mappearance == PM_GREEN_SLIME) {
+ youmonst.m_ap_type = M_AP_NOTHING;
+ youmonst.mappearance = 0;
+ }
+ }
}
/* start or stop petrification */
{
long old = Stoned;
-#if 0
+#if 0 /* tell player even if hero is unconscious */
if (Unaware)
msg = 0;
#endif
- if ((!xtime && old) || (xtime && !old)) {
+ set_itimeout(&Stoned, xtime);
+ if ((xtime != 0L) ^ (old != 0L)) {
+ context.botl = TRUE;
if (msg)
- pline1(msg);
- /* context.botl = 1; --- Stoned is not a status line item */
+ pline("%s", msg);
}
- set_itimeout(&Stoned, xtime);
if (!Stoned)
dealloc_killer(find_delayed_killer(STONED));
else if (!old)
if (Unaware)
talk = FALSE;
+ set_itimeout(&Vomiting, xtime);
+ context.botl = TRUE;
if (!xtime && old)
if (talk)
/*JP
You_feel("much less nauseated now.");
*/
You("\93f\82«\8bC\82ª\82¨\82³\82Ü\82Á\82½\81D");
-
- set_itimeout(&Vomiting, xtime);
}
/*JP
{
long old = Blinded;
boolean u_could_see, can_see_now;
+#if 0 /*JP*/
const char *eyes;
+#endif
/* we need to probe ahead in case the Eyes of the Overworld
are or will be overriding blindness */
set_itimeout(&Blinded, xtime);
if (u_could_see ^ can_see_now) { /* one or the other but not both */
- context.botl = 1;
- vision_full_recalc = 1; /* blindness just got toggled */
- /* this vision recalculation used to be deferred until
- moveloop(), but that made it possible for vision
- irregularities to occur (cited case was force bolt
- hitting adjacent potion of blindness and then a
- secret door; hero was blinded by vapors but then
- got the message "a door appears in the wall") */
- vision_recalc(0);
- if (Blind_telepat || Infravision)
- see_monsters();
-
- /* avoid either of the sequences
- "Sting starts glowing", [become blind], "Sting stops quivering" or
- "Sting starts quivering", [regain sight], "Sting stops glowing"
- by giving "Sting is quivering" when becoming blind or
- "Sting is glowing" when regaining sight so that the eventual
- "stops" message matches */
- if (warn_obj_cnt && uwep && (EWarn_of_mon & W_WEP) != 0L)
- Sting_effects(-1);
- /* update dknown flag for inventory picked up while blind */
- if (can_see_now)
- learn_unseen_invent();
+ toggle_blindness();
}
}
+/* blindness has just started or just ended--caller enforces that;
+ called by Blindf_on(), Blindf_off(), and make_blinded() */
+void
+toggle_blindness()
+{
+ boolean Stinging = (uwep && (EWarn_of_mon & W_WEP) != 0L);
+
+ /* blindness has just been toggled */
+ context.botl = TRUE; /* status conditions need update */
+ vision_full_recalc = 1; /* vision has changed */
+ /* this vision recalculation used to be deferred until moveloop(),
+ but that made it possible for vision irregularities to occur
+ (cited case was force bolt hitting an adjacent potion of blindness
+ and then a secret door; hero was blinded by vapors but then got the
+ message "a door appears in the wall" because wall spot was IN_SIGHT) */
+ vision_recalc(0);
+ if (Blind_telepat || Infravision || Stinging)
+ see_monsters(); /* also counts EWarn_of_mon monsters */
+ /*
+ * Avoid either of the sequences
+ * "Sting starts glowing", [become blind], "Sting stops quivering" or
+ * "Sting starts quivering", [regain sight], "Sting stops glowing"
+ * by giving "Sting is quivering" when becoming blind or
+ * "Sting is glowing" when regaining sight so that the eventual
+ * "stops" message matches the most recent "Sting is ..." one.
+ */
+ if (Stinging)
+ Sting_effects(-1);
+ /* update dknown flag for inventory picked up while blind */
+ if (!Blind)
+ learn_unseen_invent();
+}
+
boolean
make_hallucinated(xtime, talk, mask)
long xtime; /* nonzero if this is an attempt to turn on hallucination */
if (Unaware)
talk = FALSE;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
message = (!xtime) ? "Everything %s SO boring now."
: "Oh wow! Everything %s so cosmic!";
#else
if (!haseyes(youmonst.data)) {
strange_feeling((struct obj *) 0, (char *) 0);
} else if (Blind) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
const char *eyes = body_part(EYE);
if (eyecount(youmonst.data) != 1)
(eg. Qt windowport's equipped items display) */
update_inventory();
- context.botl = 1;
+ context.botl = TRUE;
if (talk)
pline(message, verb);
}
boolean talk;
{
long old = HDeaf;
- boolean toggled = FALSE;
if (Unaware)
talk = FALSE;
- if (!xtime && old) {
- if (talk)
- You("can hear again.");
- toggled = TRUE;
- } else if (xtime && !old) {
+ set_itimeout(&HDeaf, xtime);
+ if ((xtime != 0L) ^ (old != 0L)) {
+ context.botl = TRUE;
if (talk)
- You("are unable to hear anything.");
- toggled = TRUE;
+/*JP
+ You(old ? "can hear again." : "are unable to hear anything.");
+*/
+ You(old ? "\82Ü\82½\95·\82±\82¦\82é\82æ\82¤\82É\82È\82Á\82½\81D" : "\89½\82à\95·\82±\82¦\82È\82\82È\82Á\82½\81D");
}
- /* deafness isn't presently shown on status line, but
- request a status update in case that changes someday */
- if (toggled)
- context.botl = TRUE;
+}
- set_itimeout(&HDeaf, xtime);
+/* set or clear "slippery fingers" */
+void
+make_glib(xtime)
+int xtime;
+{
+ set_itimeout(&Glib, xtime);
+ /* may change "(being worn)" to "(being worn; slippery)" or vice versa */
+ if (uarmg)
+ update_inventory();
+}
+
+void
+self_invis_message()
+{
+#if 0 /*JP:T*/
+ pline("%s %s.",
+ Hallucination ? "Far out, man! You"
+ : "Gee! All of a sudden, you",
+ See_invisible ? "can see right through yourself"
+ : "can't see yourself");
+#else
+ pline("%s\82 \82È\82½\82Í%s\81D",
+ Hallucination ? "\83\8f\81[\83I\81I" : "\82°\81I\93Ë\91R",
+ See_invisible ? "\8e©\95ª\8e©\90g\82ª\82¿\82á\82ñ\82Æ\8c©\82¦\82È\82\82È\82Á\82½"
+ : "\8e©\95ª\8e©\90g\82ª\8c©\82¦\82È\82\82È\82Á\82½");
+#endif
}
STATIC_OVL void
pline("\95r\82ð\8aJ\82¯\82é\82Æ\81C\89½\82©\82ª\8fo\82Ä\82«\82½\81D");
return;
}
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("As you open the bottle, an enormous %s emerges!",
Hallucination ? rndmonnam(NULL) : (const char *) "ghost");
#else
*/
You("\82Ü\82Á\82³\82¨\82É\82È\82Á\82Ä\8bÁ\82«\81C\93®\82¯\82È\82\82È\82Á\82½\81D");
nomul(-3);
+/*JP
multi_reason = "being frightened to death";
+*/
+ multi_reason = "\8e\80\82Ê\82Ù\82Ç\8bÁ\82¢\82½\8c\84\82É";
/*JP
nomovemsg = "You regain your composure.";
*/
if (nothing) {
unkn++;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
You("have a %s feeling for a moment, then it passes.",
Hallucination ? "normal" : "peculiar");
#else
break;
} else {
/* unlike unicorn horn, overrides Fixed_abil */
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("Wow! This makes you feel %s!",
(otmp->blessed)
? (unfixable_trouble_count(FALSE) ? "better" : "great")
i = rn2(A_MAX); /* start at a random point */
for (ii = 0; ii < A_MAX; ii++) {
lim = AMAX(i);
- if (i == A_STR && u.uhs >= 3)
- --lim; /* WEAK */
+ /* this used to adjust 'lim' for A_STR when u.uhs was
+ WEAK or worse, but that's handled via ATEMP(A_STR) now */
if (ABASE(i) < lim) {
ABASE(i) = lim;
context.botl = 1;
if (++i >= A_MAX)
i = 0;
}
+
+ /* when using the potion (not the spell) also restore lost levels,
+ to make the potion more worth keeping around for players with
+ the spell or with a unihorn; this is better than full healing
+ in that it can restore all of them, not just half, and a
+ blessed potion restores them all at once */
+ if (otmp->otyp == POT_RESTORE_ABILITY && u.ulevel < u.ulevelmax) {
+ do {
+ pluslvl(FALSE);
+ } while (u.ulevel < u.ulevelmax && otmp->blessed);
+ }
}
break;
case POT_HALLUCINATION:
if (Hallucination || Halluc_resistance)
nothing++;
- (void) make_hallucinated(
- itimeout_incr(HHallucination, rn1(200, 600 - 300 * bcsign(otmp))),
- TRUE, 0L);
+ (void) make_hallucinated(itimeout_incr(HHallucination,
+ rn1(200, 600 - 300 * bcsign(otmp))),
+ TRUE, 0L);
break;
case POT_WATER:
if (!otmp->blessed && !otmp->cursed) {
/*JP
- pline("This tastes like water.");
+ pline("This tastes like %s.", hliquid("water"));
*/
- pline("\90\85\82Ì\82æ\82¤\82È\96¡\82ª\82·\82é\81D");
+ pline("%s\82Ì\82æ\82¤\82È\96¡\82ª\82·\82é\81D", hliquid("\90\85"));
u.uhunger += rnd(10);
newuhs(FALSE);
break;
|| u.ualign.type == A_CHAOTIC) {
if (otmp->blessed) {
/*JP
- pline("This burns like acid!");
+ pline("This burns like %s!", hliquid("acid"));
*/
- pline("\8e_\82Ì\82æ\82¤\82É\90ã\82ª\82Ð\82è\82Ð\82è\82·\82é\81I");
+ pline("%s\82Ì\82æ\82¤\82É\90ã\82ª\82Ð\82è\82Ð\82è\82·\82é\81I", hliquid("\8e_"));
exercise(A_CON, FALSE);
if (u.ulycn >= LOW_PM) {
/*JP
makeplural(mons[u.ulycn].mname));
if (youmonst.data == &mons[u.ulycn])
you_unwere(FALSE);
- u.ulycn = NON_PM; /* cure lycanthropy */
+ set_ulycn(NON_PM); /* cure lycanthropy */
}
/*JP
losehp(Maybe_Half_Phys(d(2, 6)), "potion of holy water",
} else {
if (u.ualign.type == A_LAWFUL) {
/*JP
- pline("This burns like acid!");
+ pline("This burns like %s!", hliquid("acid"));
*/
- pline("\8e_\82Ì\82æ\82¤\82É\90ã\82ª\82Ð\82è\82Ð\82è\82·\82é\81I");
+ pline("%s\82Ì\82æ\82¤\82É\90ã\82ª\82Ð\82è\82Ð\82è\82·\82é\81I", hliquid("\8e_"));
/*JP
losehp(Maybe_Half_Phys(d(2, 6)), "potion of unholy water",
*/
break;
case POT_BOOZE:
unkn++;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("Ooph! This tastes like %s%s!",
otmp->odiluted ? "watered down " : "",
Hallucination ? "dandelion wine" : "liquid fire");
#else
pline("\82¤\82¥\82Á\82Õ\81I\82±\82ê\82Í%s%s\82Ì\82æ\82¤\82È\96¡\82ª\82·\82é\81I",
otmp->odiluted ? "\90\85\82Å\94\96\82ß\82½" : "",
- Hallucination ? "\83^\83\93\83|\83|\83\8f\83C\83\93" : "\94R\97¿\83I\83C\83\8b");
+ Hallucination ? "\82½\82ñ\82Û\82Û\82Ì\82¨\8eð" : "\94R\97¿\83I\83C\83\8b");
#endif
if (!otmp->blessed)
make_confused(itimeout_incr(HConfusion, d(3, 8)), FALSE);
unkn++;
if (otmp->cursed)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("Yecch! This tastes %s.",
Hallucination ? "overripe" : "rotten");
#else
Hallucination ? "\8fn\82µ\82·\82¬\82½" : "\95\85\82Á\82½");
#endif
else
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline(
Hallucination
? "This tastes like 10%% real %s%s all-natural beverage."
*/
You("\82»\82Ì\8fê\82Å\93®\82¯\82È\82\82È\82Á\82½\81I");
else
-#if 0 /*JP*/
+#if 0 /*JP:T*/
Your("%s are frozen to the %s!", makeplural(body_part(FOOT)),
surface(u.ux, u.uy));
#else
You("\93®\82¯\82È\82\82È\82Á\82½\81I");
#endif
nomul(-(rn1(10, 25 - 12 * bcsign(otmp))));
+/*JP
multi_reason = "frozen by a potion";
+*/
+ multi_reason = "\96ò\82Å\8dd\92¼\82µ\82Ä\82¢\82é\8e\9e\82É";
nomovemsg = You_can_move_again;
exercise(A_DEX, FALSE);
}
char contaminant[BUFSZ];
int typ = rn2(A_MAX);
-#if 0 /*JP*/
+#if 0 /*JP:T*/
Sprintf(contaminant, "%s%s",
(Poison_resistance) ? "mildly " : "",
(otmp->fromsink) ? "contaminated tap water"
}
break;
case POT_SPEED:
+ /* skip when mounted; heal_legs() would heal steed's legs */
if (Wounded_legs && !otmp->cursed && !u.usteed) {
- /* heal_legs() would heal steeds legs */
- heal_legs();
+ heal_legs(0);
unkn++;
break;
}
break;
case POT_LEVITATION:
case SPE_LEVITATION:
- if (otmp->cursed)
- HLevitation &= ~I_SPECIAL;
+ /*
+ * BLevitation will be set if levitation is blocked due to being
+ * inside rock (currently or formerly in phazing xorn form, perhaps)
+ * but it doesn't prevent setting or incrementing Levitation timeout
+ * (which will take effect after escaping from the rock if it hasn't
+ * expired by then).
+ */
if (!Levitation && !BLevitation) {
/* kludge to ensure proper operation of float_up() */
set_itimeout(&HLevitation, 1L);
float_up();
- /* reverse kludge */
- set_itimeout(&HLevitation, 0L);
- if (otmp->cursed) {
- if ((u.ux == xupstair && u.uy == yupstair)
- || (sstairs.up && u.ux == sstairs.sx
- && u.uy == sstairs.sy)
- || (xupladder && u.ux == xupladder
- && u.uy == yupladder)) {
- (void) doup();
- } else if (has_ceiling(&u.uz)) {
- int dmg = uarmh ? 1 : rnd(10);
+ /* This used to set timeout back to 0, then increment it below
+ for blessed and uncursed effects. But now we leave it so
+ that cursed effect yields "you float down" on next turn.
+ Blessed and uncursed get one extra turn duration. */
+ } else /* already levitating, or can't levitate */
+ nothing++;
-#if 0 /*JP*/
- You("hit your %s on the %s.", body_part(HEAD),
- ceiling(u.ux, u.uy));
+ if (otmp->cursed) {
+ /* 'already levitating' used to block the cursed effect(s)
+ aside from ~I_SPECIAL; it was not clear whether that was
+ intentional; either way, it no longer does (as of 3.6.1) */
+ HLevitation &= ~I_SPECIAL; /* can't descend upon demand */
+ if (BLevitation) {
+ ; /* rising via levitation is blocked */
+ } else if ((u.ux == xupstair && u.uy == yupstair)
+ || (sstairs.up && u.ux == sstairs.sx && u.uy == sstairs.sy)
+ || (xupladder && u.ux == xupladder && u.uy == yupladder)) {
+ (void) doup();
+ /* in case we're already Levitating, which would have
+ resulted in incrementing 'nothing' */
+ nothing = 0; /* not nothing after all */
+ } else if (has_ceiling(&u.uz)) {
+ int dmg = rnd(!uarmh ? 10 : !is_metallic(uarmh) ? 6 : 3);
+
+#if 0 /*JP:T*/
+ You("hit your %s on the %s.", body_part(HEAD),
+ ceiling(u.ux, u.uy));
#else
- You("%s\82ð%s\82É\82Ô\82Â\82¯\82½\81D", body_part(HEAD),
- ceiling(u.ux,u.uy));
+ You("%s\82ð%s\82É\82Ô\82Â\82¯\82½\81D", body_part(HEAD),
+ ceiling(u.ux,u.uy));
#endif
/*JP
- losehp(Maybe_Half_Phys(dmg), "colliding with the ceiling",
+ losehp(Maybe_Half_Phys(dmg), "colliding with the ceiling",
*/
- losehp(Maybe_Half_Phys(dmg), "\93V\88ä\82É\93ª\82ð\82Ô\82Â\82¯\82Ä",
- KILLED_BY);
- }
- } /*cursed*/
- } else
- nothing++;
- if (otmp->blessed) {
+ losehp(Maybe_Half_Phys(dmg), "\93V\88ä\82É\93ª\82ð\82Ô\82Â\82¯\82Ä",
+ KILLED_BY);
+ nothing = 0; /* not nothing after all */
+ }
+ } else if (otmp->blessed) {
+ /* at this point, timeout is already at least 1 */
incr_itimeout(&HLevitation, rn1(50, 250));
+ /* can descend at will (stop levitating via '>') provided timeout
+ is the only factor (ie, not also wearing Lev ring or boots) */
HLevitation |= I_SPECIAL;
- } else
+ } else /* timeout is already at least 1 */
incr_itimeout(&HLevitation, rn1(140, 10));
- if (Levitation)
- spoteffects(FALSE); /* for sinks */
+
+ if (Levitation && IS_SINK(levl[u.ux][u.uy].typ))
+ spoteffects(FALSE);
+ /* levitating blocks flying */
float_vs_flight();
break;
case POT_GAIN_ENERGY: { /* M. Stephenson */
} else {
int dmg;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("This burns%s!",
otmp->blessed ? " a little" : otmp->cursed ? " a lot"
: " like acid");
u.uhp = (u.uhpmax += nxtra);
}
}
- if (cureblind)
+ if (cureblind) {
+ /* 3.6.1: it's debatible whether healing magic should clean off
+ mundane 'dirt', but if it doesn't, blindness isn't cured */
+ u.ucreamed = 0;
make_blinded(0L, TRUE);
+ /* heal deafness too */
+ make_deaf(0L, TRUE);
+ }
if (curesick) {
make_vomiting(0L, TRUE);
make_sick(0L, (char *) 0, TRUE, SICK_ALL);
const char *txt;
{
if (flags.beginner || !txt)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
You("have a %s feeling for a moment, then it passes.",
Hallucination ? "normal" : "strange");
#else
useup(obj);
}
-#if 0 /*JP*/
+#if 0 /*JP:T*/
const char *bottlenames[] = { "bottle", "phial", "flagon", "carafe",
"flask", "jar", "vial" };
#else
} else if (potion->cursed) {
if (targobj->blessed) {
func = unbless;
+/*JP
glowcolor = "brown";
+*/
+ glowcolor = "\92\83\90F\82Ì";
costchange = COST_UNBLSS;
} else if (!targobj->cursed) {
func = curse;
is cleared instead of set if perception is distorted */
if (useeit) {
glowcolor = hcolor(glowcolor);
+ /*JP:3.6.0\8e\9e\93_\82Å\82Í\93®\8e\8c\82Í"glow"\82¾\82¯\82È\82Ì\82Å\8c\88\82ß\8c\82\82¿*/
if (altfmt)
+#if 0 /*JP:T*/
pline("%s with %s aura.", objphrase, an(glowcolor));
+#else
+ pline("%s\82Í%s\83I\81[\83\89\82É\82Â\82Â\82Ü\82ê\82½\81D", objphrase, glowcolor);
+#endif
else
+#if 0 /*JP:T*/
pline("%s %s.", objphrase, glowcolor);
+#else
+ pline("%s\82Í%s\8bP\82¢\82½\81D", objphrase, jconj_adj(glowcolor));
+#endif
iflags.last_msg = PLNMSG_OBJ_GLOWS;
targobj->bknown = !Hallucination;
+ } else {
+ /* didn't see what happened: forget the BUC state if that was
+ known unless the bless/curse state of the water is known;
+ without this, hero would know the new state even without
+ seeing the glow; priest[ess] will immediately relearn it */
+ if (!potion->bknown || !potion->dknown)
+ targobj->bknown = 0;
+ /* [should the bknown+dknown exception require that water
+ be discovered or at least named?] */
}
/* potions of water are the only shop goods whose price depends
on their curse/bless state */
return res;
}
+/* potion obj hits monster mon, which might be youmonst; obj always used up */
void
-potionhit(mon, obj, your_fault)
-register struct monst *mon;
-register struct obj *obj;
-boolean your_fault;
+potionhit(mon, obj, how)
+struct monst *mon;
+struct obj *obj;
+int how;
{
const char *botlnam = bottlename();
boolean isyou = (mon == &youmonst);
- int distance;
+ int distance, tx, ty;
struct obj *saddle = (struct obj *) 0;
- boolean hit_saddle = FALSE;
+ boolean hit_saddle = FALSE, your_fault = (how <= POTHIT_HERO_THROW);
if (isyou) {
+ tx = u.ux, ty = u.uy;
distance = 0;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline_The("%s crashes on your %s and breaks into shards.", botlnam,
body_part(HEAD));
#else
pline("%s\82ª\82 \82È\82½\82Ì%s\82Ì\8fã\82Å\89ó\82ê\94j\95Ð\82Æ\82È\82Á\82½\81D", botlnam,
- body_part(HEAD));
+ body_part(HEAD));
#endif
-/*JP
- losehp(Maybe_Half_Phys(rnd(2)), "thrown potion", KILLED_BY_AN);
-*/
+#if 0 /*JP*/
+ losehp(Maybe_Half_Phys(rnd(2)),
+ (how == POTHIT_OTHER_THROW) ? "propelled potion" /* scatter */
+ : "thrown potion",
+ KILLED_BY_AN);
+#else /*\82Ç\82¿\82ç\82à\81u\93\8a\82°\82ç\82ê\82½\81v\82Å\82æ\82¢*/
losehp(Maybe_Half_Phys(rnd(2)), "\93\8a\82°\82ç\82ê\82½\96ò\82Å", KILLED_BY_AN);
+#endif
} else {
+ tx = mon->mx, ty = mon->my;
/* sometimes it hits the saddle */
if (((mon->misc_worn_check & W_SADDLE)
&& (saddle = which_armor(mon, W_SADDLE)))
&& ((rnl(10) > 7 && obj->cursed)
|| (rnl(10) < 4 && obj->blessed) || !rn2(3)))))
hit_saddle = TRUE;
- distance = distu(mon->mx, mon->my);
- if (!cansee(mon->mx, mon->my))
+ distance = distu(tx, ty);
+ if (!cansee(tx, ty)) {
/*JP
pline("Crash!");
*/
pline("\83K\83V\83\83\83\93\81I");
- else {
+ } else {
char *mnam = mon_nam(mon);
char buf[BUFSZ];
if (hit_saddle && saddle) {
-/*JP
+#if 0 /*JP:T*/
Sprintf(buf, "%s saddle",
-*/
- Sprintf(buf, "%s\82Ì\88Æ",
s_suffix(x_monnam(mon, ARTICLE_THE, (char *) 0,
(SUPPRESS_IT | SUPPRESS_SADDLE),
FALSE)));
+#else
+ Sprintf(buf, "%s\82Ì\88Æ",
+ x_monnam(mon, ARTICLE_THE, (char *) 0,
+ (SUPPRESS_IT | SUPPRESS_SADDLE),
+ FALSE));
+#endif
} else if (has_head(mon->data)) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
Sprintf(buf, "%s %s", s_suffix(mnam),
(notonhead ? "body" : "head"));
#else
- Sprintf(buf, "%s\82Ì%s", s_suffix(mnam),
+ Sprintf(buf, "%s\82Ì%s", mnam,
(notonhead ? "\91Ì" : "\93ª"));
#endif
} else {
Strcpy(buf, mnam);
}
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline_The("%s crashes on %s and breaks into shards.", botlnam,
buf);
#else
}
/* oil doesn't instantly evaporate; Neither does a saddle hit */
- if (obj->otyp != POT_OIL && !hit_saddle && cansee(mon->mx, mon->my))
+ if (obj->otyp != POT_OIL && !hit_saddle && cansee(tx, ty))
/*JP
pline("%s.", Tobjnam(obj, "evaporate"));
*/
case POT_ACID:
if (!Acid_resistance) {
int dmg;
-#if 0 /*JP*/
+
+#if 0 /*JP:T*/
pline("This burns%s!",
obj->blessed ? " a little"
: obj->cursed ? " a lot" : "");
} else if (hit_saddle && saddle) {
char *mnam, buf[BUFSZ], saddle_glows[BUFSZ];
boolean affected = FALSE;
- boolean useeit = !Blind && canseemon(mon) && cansee(mon->mx, mon->my);
+ boolean useeit = !Blind && canseemon(mon) && cansee(tx, ty);
mnam = x_monnam(mon, ARTICLE_THE, (char *) 0,
(SUPPRESS_IT | SUPPRESS_SADDLE), FALSE);
switch (obj->otyp) {
case POT_WATER:
+/*JP
Sprintf(saddle_glows, "%s %s", buf, aobjnam(saddle, "glow"));
+*/
+ Sprintf(saddle_glows, "%s", buf);
affected = H2Opotion_dip(obj, saddle, useeit, saddle_glows);
break;
case POT_POLYMORPH:
break;
}
if (useeit && !affected)
+/*JP
pline("%s %s wet.", buf, aobjnam(saddle, "get"));
+*/
+ pline("%s\82Í\94G\82ê\82½\81D", buf);
} else {
- boolean angermon = TRUE;
+ boolean angermon = your_fault, cureblind = FALSE;
- if (!your_fault)
- angermon = FALSE;
switch (obj->otyp) {
- case POT_HEALING:
- case POT_EXTRA_HEALING:
case POT_FULL_HEALING:
+ cureblind = TRUE;
+ /*FALLTHRU*/
+ case POT_EXTRA_HEALING:
+ if (!obj->cursed)
+ cureblind = TRUE;
+ /*FALLTHRU*/
+ case POT_HEALING:
+ if (obj->blessed)
+ cureblind = TRUE;
if (mon->data == &mons[PM_PESTILENCE])
goto do_illness;
- /*FALLTHRU*/
+ /*FALLTHRU*/
case POT_RESTORE_ABILITY:
case POT_GAIN_ABILITY:
- do_healing:
+ do_healing:
angermon = FALSE;
if (mon->mhp < mon->mhpmax) {
mon->mhp = mon->mhpmax;
*/
pline("%s\82Í\8c³\8bC\82É\82È\82Á\82½\82æ\82¤\82É\8c©\82¦\82é\81D", Monnam(mon));
}
+ if (cureblind)
+ mcureblindness(mon, canseemon(mon));
break;
case POT_SICKNESS:
if (mon->data == &mons[PM_PESTILENCE])
/* most common case */
|| resists_poison(mon)) {
if (canseemon(mon))
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s looks unharmed.", Monnam(mon));
#else
pline("%s\82Í\82È\82ñ\82Æ\82à\82È\82¢\82æ\82¤\82¾\81D", Monnam(mon));
#endif
break;
}
- do_illness:
+ do_illness:
if ((mon->mhpmax > 3) && !resist(mon, POTION_CLASS, 0, NOTELL))
mon->mhpmax /= 2;
if ((mon->mhp > 2) && !resist(mon, POTION_CLASS, 0, NOTELL))
if (!resist(mon, POTION_CLASS, 0, NOTELL))
mon->mconf = TRUE;
break;
- case POT_INVISIBILITY:
+ case POT_INVISIBILITY: {
+ boolean sawit = canspotmon(mon);
+
angermon = FALSE;
mon_set_minvis(mon);
+ if (sawit && !canspotmon(mon) && cansee(mon->mx, mon->my))
+ map_invisible(mon->mx, mon->my);
break;
+ }
case POT_SLEEPING:
/* wakeup() doesn't rouse victims of temporary sleep */
if (sleep_monst(mon, rnd(12), POTION_CLASS)) {
break;
case POT_BLINDNESS:
if (haseyes(mon->data)) {
- register int btmp = 64 + rn2(32)
+ int btmp = 64 + rn2(32)
+ rn2(32) * !resist(mon, POTION_CLASS, 0, NOTELL);
btmp += mon->mblinded;
if (is_undead(mon->data) || is_demon(mon->data)
|| is_were(mon->data) || is_vampshifter(mon)) {
if (obj->blessed) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s %s in pain!", Monnam(mon),
is_silent(mon->data) ? "writhes" : "shrieks");
#else
is_silent(mon->data) ? "\82É\90g\82à\82¾\82¦\82µ\82½" : "\82Ì\8b©\82Ñ\90º\82ð\82 \82°\82½");
#endif
if (!is_silent(mon->data))
- wake_nearto(mon->mx, mon->my, mon->data->mlevel * 10);
+ wake_nearto(tx, ty, mon->data->mlevel * 10);
mon->mhp -= d(2, 6);
/* should only be by you */
- if (mon->mhp < 1)
+ if (DEADMONSTER(mon))
killed(mon);
else if (is_were(mon->data) && !is_human(mon->data))
new_were(mon); /* revert to human */
pline("%s\82Í\8eK\82Ñ\82½\81D", Monnam(mon));
mon->mhp -= d(1, 6);
/* should only be by you */
- if (mon->mhp < 1)
+ if (DEADMONSTER(mon))
killed(mon);
}
break;
case POT_OIL:
if (obj->lamplit)
- explode_oil(obj, mon->mx, mon->my);
+ explode_oil(obj, tx, ty);
break;
case POT_ACID:
if (!resists_acid(mon) && !resist(mon, POTION_CLASS, 0, NOTELL)) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("%s %s in pain!", Monnam(mon),
is_silent(mon->data) ? "writhes" : "shrieks");
#else
is_silent(mon->data) ? "\82É\90g\82à\82¾\82¦\82µ\82½" : "\82Ì\8b©\82Ñ\90º\82ð\82 \82°\82½");
#endif
if (!is_silent(mon->data))
- wake_nearto(mon->mx, mon->my, mon->data->mlevel * 10);
+ wake_nearto(tx, ty, mon->data->mlevel * 10);
mon->mhp -= d(obj->cursed ? 2 : 1, obj->blessed ? 4 : 8);
- if (mon->mhp < 1) {
+ if (DEADMONSTER(mon)) {
if (your_fault)
killed(mon);
else
break;
*/
}
- if (angermon)
- wakeup(mon);
- else
- mon->msleeping = 0;
+ /* target might have been killed */
+ if (!DEADMONSTER(mon)) {
+ if (angermon)
+ wakeup(mon, TRUE);
+ else
+ mon->msleeping = 0;
+ }
}
/* Note: potionbreathe() does its own docall() */
- if ((distance == 0 || ((distance < 3) && rn2(5)))
+ if ((distance == 0 || (distance < 3 && rn2(5)))
&& (!breathless(youmonst.data) || haseyes(youmonst.data)))
potionbreathe(obj);
else if (obj->dknown && !objects[obj->otyp].oc_name_known
- && !objects[obj->otyp].oc_uname && cansee(mon->mx, mon->my))
+ && !objects[obj->otyp].oc_uname && cansee(tx, ty))
docall(obj);
+
if (*u.ushops && obj->unpaid) {
struct monst *shkp = shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE));
- if (shkp)
+ /* neither of the first two cases should be able to happen;
+ only the hero should ever have an unpaid item, and only
+ when inside a tended shop */
+ if (!shkp) /* if shkp was killed, unpaid ought to cleared already */
+ obj->unpaid = 0;
+ else if (context.mon_moving) /* obj thrown by monster */
+ subfrombill(obj, shkp);
+ else /* obj thrown by hero */
(void) stolen_value(obj, u.ux, u.uy, (boolean) shkp->mpeaceful,
FALSE);
- else
- obj->unpaid = 0;
}
obfree(obj, (struct obj *) 0);
}
potionbreathe(obj)
register struct obj *obj;
{
- register int i, ii, isdone, kn = 0;
+ int i, ii, isdone, kn = 0;
+ boolean cureblind = FALSE;
+
+ /* potion of unholy water might be wielded; prevent
+ you_were() -> drop_weapon() from dropping it so that it
+ remains in inventory where our caller expects it to be */
+ obj->in_use = 1;
switch (obj->otyp) {
case POT_RESTORE_ABILITY:
*/
pline("\83E\83Q\83F\81I\96ò\82Í\82à\82Ì\82·\82²\82¢\93õ\82¢\82ª\82·\82é\81I");
else if (haseyes(youmonst.data)) {
-#if 0 /*JP*/
+#if 0 /*JP:T*/
const char *eyes = body_part(EYE);
if (eyecount(youmonst.data) != 1)
u.mh++, context.botl = 1;
if (u.uhp < u.uhpmax)
u.uhp++, context.botl = 1;
+ cureblind = TRUE;
/*FALLTHRU*/
case POT_EXTRA_HEALING:
if (Upolyd && u.mh < u.mhmax)
u.mh++, context.botl = 1;
if (u.uhp < u.uhpmax)
u.uhp++, context.botl = 1;
+ if (!obj->cursed)
+ cureblind = TRUE;
/*FALLTHRU*/
case POT_HEALING:
if (Upolyd && u.mh < u.mhmax)
u.mh++, context.botl = 1;
if (u.uhp < u.uhpmax)
u.uhp++, context.botl = 1;
+ if (obj->blessed)
+ cureblind = TRUE;
+ if (cureblind) {
+ make_blinded(0L, !u.ucreamed);
+ make_deaf(0L, TRUE);
+ }
exercise(A_CON, TRUE);
break;
case POT_SICKNESS:
case POT_INVISIBILITY:
if (!Blind && !Invis) {
kn++;
-#if 0 /*JP*/
+#if 0 /*JP:T*/
pline("For an instant you %s!",
See_invisible ? "could see right through yourself"
: "couldn't see yourself");
*/
pline("%s\82ª\82 \82È\82½\82ð\82Â\82©\82Ü\82¦\82Ä\82¢\82é\82æ\82¤\82È\8bC\82ª\82µ\82½\81D", Something);
nomul(-rnd(5));
+/*JP
multi_reason = "frozen by a potion";
+*/
+ multi_reason = "\96ò\82Å\8dd\92¼\82µ\82Ä\82¢\82é\8e\9e\82É";
nomovemsg = You_can_move_again;
exercise(A_DEX, FALSE);
} else
*/
You("\82·\82±\82µ\94æ\82ê\82½\81D");
nomul(-rnd(5));
+/*JP
multi_reason = "sleeping off a magical draught";
+*/
+ multi_reason = "\96\82\96@\93I\82É\96°\82Á\82Ä\82¢\82é\8aÔ\82É";
nomovemsg = You_can_move_again;
exercise(A_DEX, FALSE);
} else
break;
*/
}
- /* note: no obfree() */
+ /* note: no obfree() -- that's our caller's responsibility */
if (obj->dknown) {
if (kn)
makeknown(obj->otyp);
mixtype(o1, o2)
register struct obj *o1, *o2;
{
+ int o1typ = o1->otyp, o2typ = o2->otyp;
+
/* cut down on the number of cases below */
if (o1->oclass == POTION_CLASS
- && (o2->otyp == POT_GAIN_LEVEL || o2->otyp == POT_GAIN_ENERGY
- || o2->otyp == POT_HEALING || o2->otyp == POT_EXTRA_HEALING
- || o2->otyp == POT_FULL_HEALING || o2->otyp == POT_ENLIGHTENMENT
- || o2->otyp == POT_FRUIT_JUICE)) {
- struct obj *swp;
-
- swp = o1;
- o1 = o2;
- o2 = swp;
+ && (o2typ == POT_GAIN_LEVEL || o2typ == POT_GAIN_ENERGY
+ || o2typ == POT_HEALING || o2typ == POT_EXTRA_HEALING
+ || o2typ == POT_FULL_HEALING || o2typ == POT_ENLIGHTENMENT
+ || o2typ == POT_FRUIT_JUICE)) {
+ /* swap o1 and o2 */
+ o1typ = o2->otyp;
+ o2typ = o1->otyp;
}
- switch (o1->otyp) {
+ switch (o1typ) {
case POT_HEALING:
- switch (o2->otyp) {
- case POT_SPEED:
- case POT_GAIN_LEVEL:
- case POT_GAIN_ENERGY:
+ if (o2typ == POT_SPEED)
return POT_EXTRA_HEALING;
- }
+ /*FALLTHRU*/
case POT_EXTRA_HEALING:
- switch (o2->otyp) {
- case POT_GAIN_LEVEL:
- case POT_GAIN_ENERGY:
- return POT_FULL_HEALING;
- }
case POT_FULL_HEALING:
- switch (o2->otyp) {
- case POT_GAIN_LEVEL:
- case POT_GAIN_ENERGY:
- return POT_GAIN_ABILITY;
- }
+ if (o2typ == POT_GAIN_LEVEL || o2typ == POT_GAIN_ENERGY)
+ return (o1typ == POT_HEALING) ? POT_EXTRA_HEALING
+ : (o1typ == POT_EXTRA_HEALING) ? POT_FULL_HEALING
+ : POT_GAIN_ABILITY;
+ /*FALLTHRU*/
case UNICORN_HORN:
- switch (o2->otyp) {
+ switch (o2typ) {
case POT_SICKNESS:
return POT_FRUIT_JUICE;
case POT_HALLUCINATION:
}
break;
case AMETHYST: /* "a-methyst" == "not intoxicated" */
- if (o2->otyp == POT_BOOZE)
+ if (o2typ == POT_BOOZE)
return POT_FRUIT_JUICE;
break;
case POT_GAIN_LEVEL:
case POT_GAIN_ENERGY:
- switch (o2->otyp) {
+ switch (o2typ) {
case POT_CONFUSION:
return (rn2(3) ? POT_BOOZE : POT_ENLIGHTENMENT);
case POT_HEALING:
}
break;
case POT_FRUIT_JUICE:
- switch (o2->otyp) {
+ switch (o2typ) {
case POT_SICKNESS:
return POT_SICKNESS;
+ case POT_ENLIGHTENMENT:
case POT_SPEED:
return POT_BOOZE;
case POT_GAIN_LEVEL:
}
break;
case POT_ENLIGHTENMENT:
- switch (o2->otyp) {
+ switch (o2typ) {
case POT_LEVITATION:
if (rn2(3))
return POT_GAIN_LEVEL;
break;
}
- return 0;
+ return STRANGE_OBJECT;
}
/* #dip command */
int
dodip()
{
+/*JP
+ static const char Dip_[] = "Dip ";
+*/
+ static const char Dip_[] = "\90Z\82·";
register struct obj *potion, *obj;
struct obj *singlepotion;
uchar here;
char allowall[2];
short mixture;
- char qbuf[QBUFSZ], qtoo[QBUFSZ];
+ char qbuf[QBUFSZ], obuf[QBUFSZ];
+#if 0 /*JP*/
+ const char *shortestname; /* last resort obj name for prompt */
+#endif
allowall[0] = ALL_CLASSES;
allowall[1] = '\0';
if (!(obj = getobj(allowall, "dip")))
return 0;
+/*JP
if (inaccessible_equipment(obj, "dip", FALSE))
+*/
+ if (inaccessible_equipment(obj, "\82ð\90Z\82·", FALSE))
return 0;
#if 0 /*JP*/
- Sprintf(qbuf, "dip %s into", thesimpleoname(obj));
-#else
- Sprintf(qbuf, "%s\82ð\90Z\82µ\82Ü\82·\82©", thesimpleoname(obj));
+ shortestname = (is_plural(obj) || pair_of(obj)) ? "them" : "it";
#endif
+ /*
+ * Bypass safe_qbuf() since it doesn't handle varying suffix without
+ * an awful lot of support work. Format the object once, even though
+ * the fountain and pool prompts offer a lot more room for it.
+ * 3.6.0 used thesimpleoname() unconditionally, which posed no risk
+ * of buffer overflow but drew bug reports because it omits user-
+ * supplied type name.
+ * getobj: "What do you want to dip <the object> into? [xyz or ?*] "
+ */
+ Strcpy(obuf, short_oname(obj, doname, thesimpleoname,
+ /* 128 - (24 + 54 + 1) leaves 49 for <object> */
+ QBUFSZ - sizeof "What do you want to dip \
+ into? [abdeghjkmnpqstvwyzBCEFHIKLNOQRTUWXZ#-# or ?*] "));
+
here = levl[u.ux][u.uy].typ;
/* Is there a fountain to dip into here? */
if (IS_FOUNTAIN(here)) {
- /* "Dip <the object> into the fountain?" */
#if 0 /*JP*/
- Sprintf(qtoo, "%s the fountain?", qbuf);
+ Sprintf(qbuf, "%s%s into the fountain?", Dip_,
+ flags.verbose ? obuf : shortestname);
#else
- Sprintf(qtoo, "\90ò\82É%s\81H", qbuf);
+ Sprintf(qbuf, "\90ò\82É%s\81H", Dip_);
#endif
- if (yn(upstart(qtoo)) == 'y') {
+ /* "Dip <the object> into the fountain?" */
+ if (yn(qbuf) == 'y') {
dipfountain(obj);
return 1;
}
} else if (is_pool(u.ux, u.uy)) {
const char *pooltype = waterbody_name(u.ux, u.uy);
- /* "Dip <the object> into the {pool, moat, &c}?" */
#if 0 /*JP*/
- Sprintf(qtoo, "%s the %s?", qbuf, pooltype);
-#else
- Sprintf(qtoo, "%s\82É%s\81H", pooltype, qbuf);
+ Sprintf(qbuf, "%s%s into the %s?", Dip_,
+ flags.verbose ? obuf : shortestname, pooltype);
+#else /*JP:\89p\8cê\82Å\82Í\89½\82ð\90Z\82·\82©\82ð\8aÜ\82ß\82Ä\82¢\82é\82ª\93ú\96{\8cê\82Å\82Í\8f\88\97\9d\82Ì\93s\8d\87\82Å\82Æ\82è\82 \82¦\82¸\8fÈ\97ª*/
+ Sprintf(qbuf, "%s\82É%s\81H", pooltype, Dip_);
#endif
- if (yn(upstart(qtoo)) == 'y') {
+ /* "Dip <the object> into the {pool, moat, &c}?" */
+ if (yn(qbuf) == 'y') {
if (Levitation) {
floating_above(pooltype);
} else if (u.usteed && !is_swimmer(u.usteed->data)
}
}
- /* "What do you want to dip <the object> into?" */
- potion = getobj(beverages, qbuf); /* "dip into" */
+#if 0 /*JP*/
+ /* "What do you want to dip <the object> into? [xyz or ?*] " */
+ Sprintf(qbuf, "dip %s into", flags.verbose ? obuf : shortestname);
+#else
+ /* "What do you want to dip into? [xyz or ?*] " */
+ Sprintf(qbuf, "dip into");
+#endif
+ potion = getobj(beverages, qbuf);
if (!potion)
return 0;
if (potion == obj && potion->quan == 1L) {
potion->in_use = TRUE; /* assume it will be used up */
if (potion->otyp == POT_WATER) {
boolean useeit = !Blind || (obj == ublindf && Blindfolded_only);
+#if 0 /*JP*/
const char *obj_glows = Yobjnam2(obj, "glow");
+#else
+ const char *obj_glows = cxname(obj);
+#endif
if (H2Opotion_dip(potion, obj, useeit, obj_glows))
goto poof;
5, 95)) {
pline1(nothing_happens);
} else {
- boolean was_wep, was_swapwep, was_quiver;
short save_otyp = obj->otyp;
/* KMH, conduct */
u.uconduct.polypiles++;
- was_wep = (obj == uwep);
- was_swapwep = (obj == uswapwep);
- was_quiver = (obj == uquiver);
-
obj = poly_obj(obj, STRANGE_OBJECT);
- if (was_wep)
- setuwep(obj);
- else if (was_swapwep)
- setuswapwep(obj);
- else if (was_quiver)
- setuqwep(obj);
-
- if (obj->otyp != save_otyp) {
+ /*
+ * obj might be gone:
+ * poly_obj() -> set_wear() -> Amulet_on() -> useup()
+ * if obj->otyp is worn amulet and becomes AMULET_OF_CHANGE.
+ */
+ if (!obj) {
+ makeknown(POT_POLYMORPH);
+ return 1;
+ } else if (obj->otyp != save_otyp) {
makeknown(POT_POLYMORPH);
useup(potion);
prinv((char *) 0, obj, 0L);
potion->in_use = FALSE; /* didn't go poof */
return 1;
} else if (obj->oclass == POTION_CLASS && obj->otyp != potion->otyp) {
- long amt = obj->quan;
+ int amt = (int) obj->quan;
+ boolean magic;
+ mixture = mixtype(obj, potion);
+
+ magic = (mixture != STRANGE_OBJECT) ? objects[mixture].oc_magic
+ : (objects[obj->otyp].oc_magic || objects[potion->otyp].oc_magic);
#if 0 /*JP*/
- Strcpy(qbuf, "The");
+ Strcpy(qbuf, "The"); /* assume full stack */
#else
Strcpy(qbuf, "");
#endif
- if (amt > (objects[potion->otyp].oc_magic ? 2L : 9L)) {
+ if (amt > (magic ? 3 : 7)) {
/* trying to dip multiple potions will usually affect only a
- subset; pick an amount between 2 and min(N,9), inclusive */
- amt -= 1L;
- do {
- amt = (long) rnd((int) amt);
- } while (amt >= 9L);
- amt += 1L;
- if (amt < obj->quan) {
- obj = splitobj(obj, amt);
-#if 0 /*JP*/
+ subset; pick an amount between 3 and 8, inclusive, for magic
+ potion result, between 7 and N for non-magic */
+ if (magic)
+ amt = rnd(min(amt, 8) - (3 - 1)) + (3 - 1); /* 1..6 + 2 */
+ else
+ amt = rnd(amt - (7 - 1)) + (7 - 1); /* 1..(N-6) + 6 */
+
+ if ((long) amt < obj->quan) {
+ obj = splitobj(obj, (long) amt);
+/*JP
Sprintf(qbuf, "%ld of the", obj->quan);
-#else
+*/
Sprintf(qbuf, "%ld\96{\82Ì", obj->quan);
-#endif
}
}
/* [N of] the {obj(s)} mix(es) with [one of] {the potion}... */
thesimpleoname(potion),
(potion->quan > 1L) ? "\82Ì\88ê\82Â" : "");
#endif
+ /* get rid of 'dippee' before potential perm_invent updates */
+ useup(potion); /* now gone */
/* Mixing potions is dangerous...
KMH, balance patch -- acid is particularly unstable */
if (obj->cursed || obj->otyp == POT_ACID || !rn2(10)) {
to 'amt' because that's not implemented] */
obj->in_use = 1;
/*JP
- pline("BOOM! They explode!");
+ pline("%sThey explode!", !Deaf ? "BOOM! " : "");
*/
- pline("\83o\81[\83\93\81I\94\9a\94\82µ\82½\81I");
+ pline("%s\94\9a\94\82µ\82½\81I", !Deaf ? "\83o\81[\83\93\81I" : "");
wake_nearto(u.ux, u.uy, (BOLT_LIM + 1) * (BOLT_LIM + 1));
exercise(A_STR, FALSE);
if (!breathless(youmonst.data) || haseyes(youmonst.data))
potionbreathe(obj);
useupall(obj);
- useup(potion);
- losehp((int) (amt + rnd(9)), /* not physical damage */
+ losehp(amt + rnd(9), /* not physical damage */
/*JP
"alchemic blast", KILLED_BY_AN);
*/
if (Blind || Hallucination)
obj->dknown = 0;
- if ((mixture = mixtype(obj, potion)) != 0) {
+ if (mixture != STRANGE_OBJECT) {
obj->otyp = mixture;
} else {
+ struct obj *otmp;
+
switch (obj->odiluted ? 1 : rnd(8)) {
case 1:
obj->otyp = POT_WATER;
case 3:
obj->otyp = POT_SICKNESS;
break;
- case 4: {
- struct obj *otmp = mkobj(POTION_CLASS, FALSE);
-
+ case 4:
+ otmp = mkobj(POTION_CLASS, FALSE);
obj->otyp = otmp->otyp;
obfree(otmp, (struct obj *) 0);
break;
- }
default:
useupall(obj);
- useup(potion);
- if (!Blind)
-/*JP
- pline_The("mixture glows brightly and evaporates.");
-*/
- pline("\8d¬\82º\82é\82Æ\96ò\82Í\96¾\82é\82\8bP\82«\81C\8fö\94\82µ\82½\81D");
+#if 0 /*JP:T*/
+ pline_The("mixture %sevaporates.",
+ !Blind ? "glows brightly and " : "");
+#else
+ pline_The("\8d¬\82º\82é\82Æ\96ò\82Í%s\8fö\94\82µ\82½\81D",
+ !Blind ? "\96¾\82é\82\8bP\82«\81C" : "");
+#endif
return 1;
}
}
hcolor(OBJ_DESCR(objects[obj->otyp])));
}
- useup(potion);
/* this is required when 'obj' was split off from a bigger stack,
so that 'obj' will now be assigned its own inventory slot;
it has a side-effect of merging 'obj' into another compatible
been made in order to get the merge result for both cases;
as a consequence, mixing while Fumbling drops the mixture */
freeinv(obj);
+#if 0 /*JP:T*/
(void) hold_another_object(obj, "You drop %s!", doname(obj),
(const char *) 0);
+#else
+ (void) hold_another_object(obj, "%s\82ð\97\8e\82µ\82½\81I", doname(obj),
+ (const char *) 0);
+#endif
return 1;
}
if (potion->otyp == POT_ACID && obj->otyp == CORPSE
- && obj->corpsenm == PM_LICHEN && !Blind) {
+ && obj->corpsenm == PM_LICHEN) {
+#if 0 /*JP:T*/
pline("%s %s %s around the edges.", The(cxname(obj)),
- otense(obj, "turn"),
- potion->odiluted ? hcolor(NH_ORANGE) : hcolor(NH_RED));
+ otense(obj, "turn"), Blind ? "wrinkled"
+ : potion->odiluted ? hcolor(NH_ORANGE)
+ : hcolor(NH_RED));
+#else
+ pline("%s\82Í\82Ó\82¿\82ª%s\82È\82Á\82½\81D", The(cxname(obj)),
+ Blind ? "\82µ\82í\82µ\82í\82É"
+ : potion->odiluted ? hcolor_adv(NH_ORANGE)
+ : hcolor_adv(NH_RED));
+#endif
potion->in_use = FALSE; /* didn't go poof */
+ if (potion->dknown
+ && !objects[potion->otyp].oc_name_known
+ && !objects[potion->otyp].oc_uname)
+ docall(potion);
return 1;
}
if (potion->otyp == POT_WATER && obj->otyp == TOWEL) {
+/*JP
pline_The("towel soaks it up!");
+*/
+ pline_The("\83^\83I\83\8b\82Í\90\85\82ð\8bz\82¢\8d\9e\82ñ\82¾\81I");
/* wetting towel already done via water_damage() in H2Opotion_dip */
goto poof;
}
pline_The("potion spills and covers your %s with oil.",
*/
pline("\96û\82Í\94ò\82Ñ\8eU\82è\82 \82È\82½\82Ì%s\82É\82©\82©\82Á\82½\81D",
- makeplural(body_part(FINGER)));
- incr_itimeout(&Glib, d(2, 10));
+ fingers_or_gloves(TRUE));
+ make_glib((int) (Glib & TIMEOUT) + d(2, 10));
} else if (obj->oclass != WEAPON_CLASS && !is_weptool(obj)) {
/* the following cases apply only to weapons */
goto more_dips;
} else if ((!is_rustprone(obj) && !is_corrodeable(obj))
|| is_ammo(obj) || (!obj->oeroded && !obj->oeroded2)) {
/* uses up potion, doesn't set obj->greased */
-#if 0 /*JP*/
- pline("%s %s with an oily sheen.", Yname2(obj),
- otense(obj, "gleam"));
+ if (!Blind)
+#if 0 /*JP:T*/
+ pline("%s %s with an oily sheen.", Yname2(obj),
+ otense(obj, "gleam"));
#else
pline("%s\82Í\96û\82Ì\8cõ\91ò\82Å\82«\82ç\82è\82Æ\8cõ\82Á\82½\81D", Yname2(obj));
#endif
+ else /*if (!uarmg)*/
+/*JP
+ pline("%s %s oily.", Yname2(obj), otense(obj, "feel"));
+*/
+ pline("%s\82Í\96û\82Á\82Û\82¢\81D", Yname2(obj));
} else {
-#if 0 /*JP*/
- pline("%s %s less %s.", Yname2(obj), otense(obj, "are"),
+#if 0 /*JP:T*/
+ pline("%s %s less %s.", Yname2(obj),
+ otense(obj, !Blind ? "are" : "feel"),
(obj->oeroded && obj->oeroded2)
? "corroded and rusty"
: obj->oeroded ? "rusty" : "corroded");
#else
- pline("%s\82Ì%s\82ª\8eæ\82ê\82½\81D", Yname2(obj),
+ pline("%s\82Ì%s\82ª\8eæ\82ê\82½%s\81D", Yname2(obj),
(obj->oeroded && obj->oeroded2)
? "\95\85\90H\82Æ\8eK"
- : obj->oeroded ? "\8eK" : "\95\85\90H");
+ : obj->oeroded ? "\8eK" : "\95\85\90H",
+ !Blind ? "" : "\82æ\82¤\82¾");
#endif
if (obj->oeroded > 0)
obj->oeroded--;
wisx = TRUE;
}
exercise(A_WIS, wisx);
- makeknown(potion->otyp);
+ if (potion->dknown)
+ makeknown(potion->otyp);
useup(potion);
return 1;
}
-more_dips:
+ more_dips:
/* Allow filling of MAGIC_LAMPs to prevent identification by player */
if ((obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP)
*/
You("%s\82É\96û\82ð\93ü\82ê\82½\81D", yname(obj));
check_unpaid(potion); /* Yendorian Fuel Tax */
- obj->age += 2 * potion->age; /* burns more efficiently */
+ /* burns more efficiently in a lamp than in a bottle;
+ diluted potion provides less benefit but we don't attempt
+ to track that the lamp now also has some non-oil in it */
+ obj->age += (!potion->odiluted ? 4L : 3L) * potion->age / 2L;
if (obj->age > 1500L)
obj->age = 1500L;
useup(potion);
exercise(A_WIS, TRUE);
}
- makeknown(POT_OIL);
+ if (potion->dknown)
+ makeknown(POT_OIL);
obj->spe = 1;
update_inventory();
return 1;
potion->in_use = FALSE; /* didn't go poof */
if ((obj->otyp == UNICORN_HORN || obj->otyp == AMETHYST)
- && (mixture = mixtype(obj, potion)) != 0) {
+ && (mixture = mixtype(obj, potion)) != STRANGE_OBJECT) {
char oldbuf[BUFSZ], newbuf[BUFSZ];
short old_otyp = potion->otyp;
boolean old_dknown = FALSE;
singlepotion->dknown = FALSE;
} else {
singlepotion->dknown = !Hallucination;
-#if 0 /*JP*/
+ *newbuf = '\0';
if (mixture == POT_WATER && singlepotion->dknown)
+/*JP
Sprintf(newbuf, "clears");
- else
+*/
+ Sprintf(newbuf, "\93§\96¾");
+ else if (!Blind)
+#if 0 /*JP*/
Sprintf(newbuf, "turns %s",
hcolor(OBJ_DESCR(objects[mixture])));
- pline_The("%spotion%s %s.", oldbuf,
- more_than_one ? " that you dipped into" : "", newbuf);
#else
- if (mixture == POT_WATER && singlepotion->dknown)
- Sprintf(newbuf, "\93§\96¾");
- else
Sprintf(newbuf, "%s\96ò",
hcolor(OBJ_DESCR(objects[mixture])));
- pline_The("%s%s\96ò\82Í%s\82É\82È\82Á\82½\81D.", more_than_one ? "\90Z\82µ\82½" : "",
- oldbuf, newbuf);
#endif
- if (!objects[old_otyp].oc_uname
- && !objects[old_otyp].oc_name_known && old_dknown) {
+ if (*newbuf)
+#if 0 /*JP:T*/
+ pline_The("%spotion%s %s.", oldbuf,
+ more_than_one ? " that you dipped into" : "",
+ newbuf);
+#else
+ pline_The("%s%s\96ò\82Í%s\82É\82È\82Á\82½\81D.",
+ more_than_one ? "\90Z\82µ\82½" : "",
+ oldbuf, newbuf);
+#endif
+ else
+/*JP
+ pline("Something happens.");
+*/
+ pline("\89½\82©\82ª\8bN\82«\82½\81D");
+
+ if (old_dknown
+ && !objects[old_otyp].oc_name_known
+ && !objects[old_otyp].oc_uname) {
struct obj fakeobj;
+
fakeobj = zeroobj;
fakeobj.dknown = 1;
fakeobj.otyp = old_otyp;
}
}
obj_extract_self(singlepotion);
- singlepotion =
+ singlepotion = hold_another_object(singlepotion,
/*JP
- hold_another_object(singlepotion, "You juggle and drop %s!",
+ "You juggle and drop %s!",
*/
- hold_another_object(singlepotion, "\82¨\8eè\8bÊ\82µ\82Ä%s\82ð\97\8e\82Æ\82µ\82Ä\82µ\82Ü\82Á\82½\81I",
- doname(singlepotion), (const char *) 0);
+ "\82¨\8eè\8bÊ\82µ\82Ä%s\82ð\97\8e\82Æ\82µ\82Ä\82µ\82Ü\82Á\82½\81I",
+ doname(singlepotion),
+ (const char *) 0);
+ nhUse(singlepotion);
update_inventory();
return 1;
}
pline("\96Ê\94\92\82¢\81D\81D\81D");
return 1;
-poof:
- if (!objects[potion->otyp].oc_name_known
+ poof:
+ if (potion->dknown
+ && !objects[potion->otyp].oc_name_known
&& !objects[potion->otyp].oc_uname)
docall(potion);
useup(potion);
reason[0] = '\0';
if (mtmp)
-#if 0 /*JP*/
+#if 0 /*JP:T*/
Sprintf(reason, " from %s heat",
(mtmp == &youmonst) ? the_your[1]
: (const char *) s_suffix(mon_nam(mtmp)));
#else
Sprintf(reason, "%s\82Ì\94M\82Å",
(mtmp == &youmonst) ? the_your[1]
- : (const char *) s_suffix(mon_nam(mtmp)));
+ : (const char *) mon_nam(mtmp));
#endif
if (mon == &youmonst) {