1 /* SCCS Id: @(#)potion.c 3.4 2002/10/02 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
8 boolean notonhead = FALSE;
10 static NEARDATA int nothing, unkn;
11 static NEARDATA const char beverages[] = { POTION_CLASS, 0 };
13 STATIC_DCL long FDECL(itimeout, (long));
14 STATIC_DCL long FDECL(itimeout_incr, (long,int));
15 STATIC_DCL void NDECL(ghost_from_bottle);
16 STATIC_DCL short FDECL(mixtype, (struct obj *,struct obj *));
18 /* force `val' to be within valid range for intrinsic timeout value */
23 if (val >= TIMEOUT) val = TIMEOUT;
24 else if (val < 1) val = 0;
29 /* increment `old' by `incr' and force result to be valid intrinsic timeout */
31 itimeout_incr(old, incr)
35 return itimeout((old & TIMEOUT) + (long)incr);
38 /* set the timeout field of intrinsic `which' */
40 set_itimeout(which, val)
44 *which |= itimeout(val);
47 /* increment the timeout field of intrinsic `which' */
49 incr_itimeout(which, incr)
53 set_itimeout(which, itimeout_incr(*which, incr));
57 make_confused(xtime,talk)
61 long old = HConfusion;
65 You_feel("less %s now.",
66 Hallucination ? "trippy" : "confused");
68 if ((xtime && !old) || (!xtime && old)) flags.botl = TRUE;
70 set_itimeout(&HConfusion, xtime);
74 make_stunned(xtime,talk)
83 Hallucination ? "less wobbly" : "a bit steadier");
89 You("wobble in the saddle.");
92 You("%s...", stagger(youmonst.data, "stagger"));
95 if ((!xtime && old) || (xtime && !old)) flags.botl = TRUE;
97 set_itimeout(&HStun, xtime);
101 make_sick(xtime, cause, talk, type)
103 const char *cause; /* sickness cause */
110 if (Sick_resistance) return;
113 You_feel("deathly sick.");
116 if (talk) You_feel("%s worse.",
117 xtime <= Sick/2L ? "much" : "even");
119 set_itimeout(&Sick, xtime);
120 u.usick_type |= type;
122 } else if (old && (type & u.usick_type)) {
123 /* was sick, now not */
124 u.usick_type &= ~type;
125 if (u.usick_type) { /* only partly cured */
126 if (talk) You_feel("somewhat better.");
127 set_itimeout(&Sick, Sick * 2); /* approximation */
129 if (talk) pline("What a relief!");
130 Sick = 0L; /* set_itimeout(&Sick, 0L) */
136 exercise(A_CON, FALSE);
138 (void) strncpy(u.usick_cause, cause, sizeof(u.usick_cause));
139 u.usick_cause[sizeof(u.usick_cause)-1] = 0;
142 u.usick_cause[0] = 0;
144 u.usick_cause[0] = 0;
148 make_vomiting(xtime, talk)
155 if(talk) You_feel("much less nauseated now.");
157 set_itimeout(&Vomiting, xtime);
160 static const char vismsg[] = "vision seems to %s for a moment but is %s now.";
161 static const char eyemsg[] = "%s momentarily %s.";
164 make_blinded(xtime, talk)
169 boolean u_could_see, can_see_now;
173 /* we need to probe ahead in case the Eyes of the Overworld
174 are or will be overriding blindness */
175 u_could_see = !Blind;
176 Blinded = xtime ? 1L : 0L;
177 can_see_now = !Blind;
178 Blinded = old; /* restore */
180 if (u.usleep) talk = FALSE;
182 if (can_see_now && !u_could_see) { /* regaining sight */
185 pline("Far out! Everything is all cosmic again!");
187 You("can see again.");
189 } else if (old && !xtime) {
190 /* clearing temporary blindness without toggling blindness */
192 if (!haseyes(youmonst.data)) {
193 strange_feeling((struct obj *)0, (char *)0);
194 } else if (Blindfolded) {
195 Strcpy(buf, body_part(EYE));
196 eyecnt = eyecount(youmonst.data);
197 Your(eyemsg, (eyecnt == 1) ? buf : makeplural(buf),
198 (eyecnt == 1) ? "itches" : "itch");
199 } else { /* Eyes of the Overworld */
200 Your(vismsg, "brighten",
201 Hallucination ? "sadder" : "normal");
206 if (u_could_see && !can_see_now) { /* losing sight */
209 pline("Oh, bummer! Everything is dark! Help!");
211 pline("A cloud of darkness falls upon you.");
213 /* Before the hero goes blind, set the ball&chain variables. */
214 if (Punished) set_bc(0);
215 } else if (!old && xtime) {
216 /* setting temporary blindness without toggling blindness */
218 if (!haseyes(youmonst.data)) {
219 strange_feeling((struct obj *)0, (char *)0);
220 } else if (Blindfolded) {
221 Strcpy(buf, body_part(EYE));
222 eyecnt = eyecount(youmonst.data);
223 Your(eyemsg, (eyecnt == 1) ? buf : makeplural(buf),
224 (eyecnt == 1) ? "twitches" : "twitch");
225 } else { /* Eyes of the Overworld */
227 Hallucination ? "happier" : "normal");
232 set_itimeout(&Blinded, xtime);
234 if (u_could_see ^ can_see_now) { /* one or the other but not both */
236 vision_full_recalc = 1; /* blindness just got toggled */
237 if (Blind_telepat || Infravision) see_monsters();
242 make_hallucinated(xtime, talk, mask)
243 long xtime; /* nonzero if this is an attempt to turn on hallucination */
245 long mask; /* nonzero if resistance status should change by mask */
247 long old = HHallucination;
249 const char *message, *verb;
251 message = (!xtime) ? "Everything %s SO boring now." :
252 "Oh wow! Everything %s so cosmic!";
253 verb = (!Blind) ? "looks" : "feels";
256 if (HHallucination) changed = TRUE;
258 if (!xtime) EHalluc_resistance |= mask;
259 else EHalluc_resistance &= ~mask;
261 if (!EHalluc_resistance && (!!HHallucination != !!xtime))
263 set_itimeout(&HHallucination, xtime);
265 /* clearing temporary hallucination without toggling vision */
266 if (!changed && !HHallucination && old && talk) {
267 if (!haseyes(youmonst.data)) {
268 strange_feeling((struct obj *)0, (char *)0);
271 int eyecnt = eyecount(youmonst.data);
273 Strcpy(buf, body_part(EYE));
274 Your(eyemsg, (eyecnt == 1) ? buf : makeplural(buf),
275 (eyecnt == 1) ? "itches" : "itch");
276 } else { /* Grayswandir */
277 Your(vismsg, "flatten", "normal");
284 swallowed(0); /* redraw swallow display */
286 /* The see_* routines should be called *before* the pline. */
292 /* for perm_inv and anything similar
293 (eg. Qt windowport's equipped items display) */
297 if (talk) pline(message, verb);
305 struct monst *mtmp = makemon(&mons[PM_GHOST], u.ux, u.uy, NO_MM_FLAGS);
308 pline("This bottle turns out to be empty.");
312 pline("As you open the bottle, %s emerges.", something);
315 pline("As you open the bottle, an enormous %s emerges!",
316 Hallucination ? rndmonnam() : (const char *)"ghost");
318 You("are frightened to death, and unable to move.");
320 nomovemsg = "You regain your composure.";
323 /* "Quaffing is like drinking, except you spill more." -- Terry Pratchett
328 register struct obj *otmp;
329 const char *potion_descr;
332 pline("If you can't breathe air, how can you drink liquid?");
335 /* Is there a fountain to drink from here? */
336 if (IS_FOUNTAIN(levl[u.ux][u.uy].typ) && !Levitation) {
337 if(yn("Drink from the fountain?") == 'y') {
343 /* Or a kitchen sink? */
344 if (IS_SINK(levl[u.ux][u.uy].typ)) {
345 if (yn("Drink from the sink?") == 'y') {
352 /* Or are you surrounded by water? */
354 if (yn("Drink the water around you?") == 'y') {
355 pline("Do you know what lives in this water!");
360 otmp = getobj(beverages, "drink");
362 otmp->in_use = TRUE; /* you've opened the stopper */
364 #define POTION_OCCUPANT_CHANCE(n) (13 + 2*(n)) /* also in muse.c */
366 potion_descr = OBJ_DESCR(objects[otmp->otyp]);
368 if (!strcmp(potion_descr, "milky") &&
369 flags.ghost_count < MAXMONNO &&
370 !rn2(POTION_OCCUPANT_CHANCE(flags.ghost_count))) {
374 } else if (!strcmp(potion_descr, "smoky") &&
375 flags.djinni_count < MAXMONNO &&
376 !rn2(POTION_OCCUPANT_CHANCE(flags.djinni_count))) {
377 djinni_from_bottle(otmp);
382 return dopotion(otmp);
387 register struct obj *otmp;
393 if((retval = peffects(otmp)) >= 0) return(retval);
397 You("have a %s feeling for a moment, then it passes.",
398 Hallucination ? "normal" : "peculiar");
400 if(otmp->dknown && !objects[otmp->otyp].oc_name_known) {
402 makeknown(otmp->otyp);
403 more_experienced(0,10);
404 } else if(!objects[otmp->otyp].oc_uname)
413 register struct obj *otmp;
415 register int i, ii, lim;
418 case POT_RESTORE_ABILITY:
419 case SPE_RESTORE_ABILITY:
422 pline("Ulch! This makes you feel mediocre!");
425 pline("Wow! This makes you feel %s!",
427 (unfixable_trouble_count(FALSE) ? "better" : "great")
429 i = rn2(A_MAX); /* start at a random point */
430 for (ii = 0; ii < A_MAX; ii++) {
432 if (i == A_STR && u.uhs >= 3) --lim; /* WEAK */
433 if (ABASE(i) < lim) {
436 /* only first found if not blessed */
437 if (!otmp->blessed) break;
439 if(++i >= A_MAX) i = 0;
443 case POT_HALLUCINATION:
444 if (Hallucination || Halluc_resistance) nothing++;
445 (void) make_hallucinated(itimeout_incr(HHallucination,
446 rn1(200, 600 - 300 * bcsign(otmp))),
450 if(!otmp->blessed && !otmp->cursed) {
451 pline("This tastes like water.");
452 u.uhunger += rnd(10);
457 if(is_undead(youmonst.data) || is_demon(youmonst.data) ||
458 u.ualign.type == A_CHAOTIC) {
460 pline("This burns like acid!");
461 exercise(A_CON, FALSE);
462 if (u.ulycn >= LOW_PM) {
463 Your("affinity to %s disappears!",
464 makeplural(mons[u.ulycn].mname));
465 if (youmonst.data == &mons[u.ulycn])
467 u.ulycn = NON_PM; /* cure lycanthropy */
469 losehp(d(2,6), "potion of holy water", KILLED_BY_AN);
470 } else if(otmp->cursed) {
471 You_feel("quite proud of yourself.");
472 healup(d(2,6),0,0,0);
473 if (u.ulycn >= LOW_PM && !Upolyd) you_were();
474 exercise(A_CON, TRUE);
478 You_feel("full of awe.");
479 make_sick(0L, (char *) 0, TRUE, SICK_ALL);
480 exercise(A_WIS, TRUE);
481 exercise(A_CON, TRUE);
482 if (u.ulycn >= LOW_PM)
483 you_unwere(TRUE); /* "Purified" */
484 /* make_confused(0L,TRUE); */
486 if(u.ualign.type == A_LAWFUL) {
487 pline("This burns like acid!");
488 losehp(d(2,6), "potion of unholy water",
491 You_feel("full of dread.");
492 if (u.ulycn >= LOW_PM && !Upolyd) you_were();
493 exercise(A_CON, FALSE);
499 pline("Ooph! This tastes like %s%s!",
500 otmp->odiluted ? "watered down " : "",
501 Hallucination ? "dandelion wine" : "liquid fire");
503 make_confused(itimeout_incr(HConfusion, d(3,8)), FALSE);
504 /* the whiskey makes us feel better */
505 if (!otmp->odiluted) healup(1, 0, FALSE, FALSE);
506 u.uhunger += 10 * (2 + bcsign(otmp));
508 exercise(A_WIS, FALSE);
512 nomovemsg = "You awake with a headache.";
515 case POT_ENLIGHTENMENT:
518 You("have an uneasy feeling...");
519 exercise(A_WIS, FALSE);
522 (void) adjattrib(A_INT, 1, FALSE);
523 (void) adjattrib(A_WIS, 1, FALSE);
525 You_feel("self-knowledgeable...");
526 display_nhwindow(WIN_MESSAGE, FALSE);
528 pline_The("feeling subsides.");
529 exercise(A_WIS, TRUE);
532 case SPE_INVISIBILITY:
533 /* spell cannot penetrate mummy wrapping */
534 if (BInvis && uarmc->otyp == MUMMY_WRAPPING) {
535 You_feel("rather itchy under your %s.", xname(uarmc));
539 case POT_INVISIBILITY:
540 if (Invis || Blind || BInvis) {
543 self_invis_message();
545 if (otmp->blessed) HInvis |= FROMOUTSIDE;
546 else incr_itimeout(&HInvis, rn1(15,31));
547 newsym(u.ux,u.uy); /* update position */
549 pline("For some reason, you feel your presence is known.");
553 case POT_SEE_INVISIBLE:
554 /* tastes like fruit juice in Rogue */
555 case POT_FRUIT_JUICE:
557 int msg = Invisible && !Blind;
561 pline("Yecch! This tastes %s.",
562 Hallucination ? "overripe" : "rotten");
564 pline(Hallucination ?
565 "This tastes like 10%% real %s%s all-natural beverage." :
566 "This tastes like %s%s.",
567 otmp->odiluted ? "reconstituted " : "",
569 if (otmp->otyp == POT_FRUIT_JUICE) {
570 u.uhunger += (otmp->odiluted ? 5 : 10) * (2 + bcsign(otmp));
575 /* Tell them they can see again immediately, which
576 * will help them identify the potion...
578 make_blinded(0L,TRUE);
581 HSee_invisible |= FROMOUTSIDE;
583 incr_itimeout(&HSee_invisible, rn1(100,750));
584 set_mimic_blocking(); /* do special mimic handling */
585 see_monsters(); /* see invisible monsters */
586 newsym(u.ux,u.uy); /* see yourself! */
587 if (msg && !Blind) { /* Blind possible if polymorphed */
588 You("can see through yourself, but you are visible!");
595 You("stiffen momentarily.");
597 if (Levitation || Is_airlevel(&u.uz)||Is_waterlevel(&u.uz))
598 You("are motionlessly suspended.");
601 You("are frozen in place!");
604 Your("%s are frozen to the %s!",
605 makeplural(body_part(FOOT)), surface(u.ux, u.uy));
606 nomul(-(rn1(10, 25 - 12*bcsign(otmp))));
607 nomovemsg = You_can_move_again;
608 exercise(A_DEX, FALSE);
612 if(Sleep_resistance || Free_action)
615 You("suddenly fall asleep!");
616 fall_asleep(-rn1(10, 25 - 12*bcsign(otmp)), TRUE);
619 case POT_MONSTER_DETECTION:
620 case SPE_DETECT_MONSTERS:
624 if (Detect_monsters) nothing++;
626 /* after a while, repeated uses become less effective */
627 if (HDetect_monsters >= 300L)
631 incr_itimeout(&HDetect_monsters, i);
632 for (x = 1; x < COLNO; x++) {
633 for (y = 0; y < ROWNO; y++) {
634 if (levl[x][y].glyph == GLYPH_INVISIBLE) {
638 if (MON_AT(x,y)) unkn = 0;
642 if (unkn) You_feel("lonely.");
645 if (monster_detect(otmp, 0))
646 return(1); /* nothing detected */
647 exercise(A_WIS, TRUE);
649 case POT_OBJECT_DETECTION:
650 case SPE_DETECT_TREASURE:
651 if (object_detect(otmp, 0))
652 return(1); /* nothing detected */
653 exercise(A_WIS, TRUE);
656 pline("Yecch! This stuff tastes like poison.");
658 pline("(But in fact it was mildly stale %s.)",
660 if (!Role_if(PM_HEALER)) {
661 /* NB: blessed otmp->fromsink is not possible */
662 losehp(1, "mildly contaminated potion", KILLED_BY_AN);
665 if(Poison_resistance)
667 "(But in fact it was biologically contaminated %s.)",
669 if (Role_if(PM_HEALER))
670 pline("Fortunately, you have been immunized.");
672 int typ = rn2(A_MAX);
676 (void) adjattrib(typ,
677 Poison_resistance ? -1 : -rn1(4,3),
680 if(!Poison_resistance) {
682 losehp(rnd(10)+5*!!(otmp->cursed),
683 "contaminated tap water", KILLED_BY);
685 losehp(rnd(10)+5*!!(otmp->cursed),
686 "contaminated potion", KILLED_BY_AN);
688 exercise(A_CON, FALSE);
692 You("are shocked back to your senses!");
693 (void) make_hallucinated(0L,FALSE,0L);
699 pline("What a trippy feeling!");
702 pline("Huh, What? Where am I?");
704 make_confused(itimeout_incr(HConfusion,
705 rn1(7, 16 - 8 * bcsign(otmp))),
708 case POT_GAIN_ABILITY:
710 pline("Ulch! That potion tasted foul!");
712 } else if (Fixed_abil) {
714 } else { /* If blessed, increase all; if not, try up to */
715 int itmp; /* 6 times to find one which can be increased. */
716 i = -1; /* increment to 0 */
717 for (ii = A_MAX; ii > 0; ii--) {
718 i = (otmp->blessed ? i + 1 : rn2(A_MAX));
719 /* only give "your X is already as high as it can get"
720 message on last attempt (except blessed potions) */
721 itmp = (otmp->blessed || ii == 1) ? 0 : -1;
722 if (adjattrib(i, 1, itmp) && !otmp->blessed)
728 if(Wounded_legs && !otmp->cursed
730 && !u.usteed /* heal_legs() would heal steeds legs */
736 } /* and fall through */
738 if(!Very_fast) /* wwf@doe.carleton.ca */
739 You("are suddenly moving %sfaster.",
740 Fast ? "" : "much ");
742 Your("%s get new energy.",
743 makeplural(body_part(LEG)));
746 exercise(A_DEX, TRUE);
747 incr_itimeout(&HFast, rn1(10, 100 + 60 * bcsign(otmp)));
751 make_blinded(itimeout_incr(Blinded,
752 rn1(200, 250 - 125 * bcsign(otmp))),
758 /* they went up a level */
759 if((ledger_no(&u.uz) == 1 && u.uhave.amulet) ||
760 Can_rise_up(u.ux, u.uy, &u.uz)) {
761 const char *riseup ="rise up, through the %s!";
762 if(ledger_no(&u.uz) == 1) {
763 You(riseup, ceiling(u.ux,u.uy));
764 goto_level(&earth_level, FALSE, FALSE, FALSE);
766 register int newlev = depth(&u.uz)-1;
769 get_level(&newlevel, newlev);
770 if(on_level(&newlevel, &u.uz)) {
771 pline("It tasted bad.");
773 } else You(riseup, ceiling(u.ux,u.uy));
774 goto_level(&newlevel, FALSE, FALSE, FALSE);
777 else You("have an uneasy feeling.");
782 /* blessed potions place you at a random spot in the
783 * middle of the new level instead of the low point
785 u.uexp = rndexp(TRUE);
789 healup(d(6 + 2 * bcsign(otmp), 4),
790 !otmp->cursed ? 1 : 0, !!otmp->blessed, !otmp->cursed);
791 exercise(A_CON, TRUE);
793 case POT_EXTRA_HEALING:
794 You_feel("much better.");
795 healup(d(6 + 2 * bcsign(otmp), 8),
796 otmp->blessed ? 5 : !otmp->cursed ? 2 : 0,
797 !otmp->cursed, TRUE);
798 (void) make_hallucinated(0L,TRUE,0L);
799 exercise(A_CON, TRUE);
800 exercise(A_STR, TRUE);
802 case POT_FULL_HEALING:
803 You_feel("completely healed.");
804 healup(400, 4+4*bcsign(otmp), !otmp->cursed, TRUE);
805 /* Restore one lost level if blessed */
806 if (otmp->blessed && u.ulevel < u.ulevelmax) {
807 /* when multiple levels have been lost, drinking
808 multiple potions will only get half of them back */
812 (void) make_hallucinated(0L,TRUE,0L);
813 exercise(A_STR, TRUE);
814 exercise(A_CON, TRUE);
818 if (otmp->cursed) HLevitation &= ~I_SPECIAL;
820 /* kludge to ensure proper operation of float_up() */
825 if (otmp->cursed && !Is_waterlevel(&u.uz)) {
826 if((u.ux != xupstair || u.uy != yupstair)
827 && (u.ux != sstairs.sx || u.uy != sstairs.sy || !sstairs.up)
828 && (!xupladder || u.ux != xupladder || u.uy != yupladder)
830 You("hit your %s on the %s.",
833 losehp(uarmh ? 1 : rnd(10),
834 "colliding with the ceiling",
836 } else (void) doup();
841 incr_itimeout(&HLevitation, rn1(50,250));
842 HLevitation |= I_SPECIAL;
843 } else incr_itimeout(&HLevitation, rn1(140,10));
844 spoteffects(FALSE); /* for sinks */
846 case POT_GAIN_ENERGY: /* M. Stephenson */
849 You_feel("lackluster.");
851 pline("Magical energies course through your body.");
852 num = rnd(5) + 5 * otmp->blessed + 1;
853 u.uenmax += (otmp->cursed) ? -num : num;
854 u.uen += (otmp->cursed) ? -num : num;
855 if(u.uenmax <= 0) u.uenmax = 0;
856 if(u.uen <= 0) u.uen = 0;
858 exercise(A_WIS, TRUE);
861 case POT_OIL: /* P. Winner */
863 boolean good_for_you = FALSE;
866 if (likes_fire(youmonst.data)) {
867 pline("Ahh, a refreshing drink.");
870 You("burn your %s.", body_part(FACE));
871 losehp(d(Fire_resistance ? 1 : 3, 4),
872 "burning potion of oil", KILLED_BY_AN);
874 } else if(otmp->cursed)
875 pline("This tastes like castor oil.");
877 pline("That was smooth!");
878 exercise(A_WIS, good_for_you);
883 /* Not necessarily a creature who _likes_ acid */
884 pline("This tastes %s.", Hallucination ? "tangy" : "sour");
886 pline("This burns%s!", otmp->blessed ? " a little" :
887 otmp->cursed ? " a lot" : " like acid");
888 losehp(d(otmp->cursed ? 2 : 1, otmp->blessed ? 4 : 8),
889 "potion of acid", KILLED_BY_AN);
890 exercise(A_CON, FALSE);
892 if (Stoned) fix_petrification();
893 unkn++; /* holy/unholy water can burn like acid too */
896 You_feel("a little %s.", Hallucination ? "normal" : "strange");
897 if (!Unchanging) polyself(FALSE);
900 impossible("What a funny potion! (%u)", otmp->otyp);
907 healup(nhp, nxtra, curesick, cureblind)
909 register boolean curesick, cureblind;
914 if (u.mh > u.mhmax) u.mh = (u.mhmax += nxtra);
917 if(u.uhp > u.uhpmax) u.uhp = (u.uhpmax += nxtra);
920 if(cureblind) make_blinded(0L,TRUE);
921 if(curesick) make_sick(0L, (char *) 0, TRUE, SICK_ALL);
927 strange_feeling(obj,txt)
928 register struct obj *obj;
929 register const char *txt;
931 if (flags.beginner || !txt)
932 You("have a %s feeling for a moment, then it passes.",
933 Hallucination ? "normal" : "strange");
937 if(!obj) /* e.g., crystal ball finds no traps */
940 if(obj->dknown && !objects[obj->otyp].oc_name_known &&
941 !objects[obj->otyp].oc_uname)
946 const char *bottlenames[] = {
947 "bottle", "phial", "flagon", "carafe", "flask", "jar", "vial"
954 return bottlenames[rn2(SIZE(bottlenames))];
958 potionhit(mon, obj, your_fault)
959 register struct monst *mon;
960 register struct obj *obj;
963 register const char *botlnam = bottlename();
964 boolean isyou = (mon == &youmonst);
969 pline_The("%s crashes on your %s and breaks into shards.",
970 botlnam, body_part(HEAD));
971 losehp(rnd(2), "thrown potion", KILLED_BY_AN);
973 distance = distu(mon->mx,mon->my);
974 if (!cansee(mon->mx,mon->my)) pline("Crash!");
976 char *mnam = mon_nam(mon);
979 if(has_head(mon->data)) {
980 Sprintf(buf, "%s %s",
982 (notonhead ? "body" : "head"));
986 pline_The("%s crashes on %s and breaks into shards.",
989 if(rn2(5) && mon->mhp > 1)
993 /* oil doesn't instantly evaporate */
994 if (obj->otyp != POT_OIL && cansee(mon->mx,mon->my))
995 pline("%s.", Tobjnam(obj, "evaporate"));
1001 splatter_burning_oil(u.ux, u.uy);
1004 You_feel("a little %s.", Hallucination ? "normal" : "strange");
1005 if (!Unchanging && !Antimagic) polyself(FALSE);
1008 if (!Acid_resistance) {
1009 pline("This burns%s!", obj->blessed ? " a little" :
1010 obj->cursed ? " a lot" : "");
1011 losehp(d(obj->cursed ? 2 : 1, obj->blessed ? 4 : 8),
1012 "potion of acid", KILLED_BY_AN);
1017 boolean angermon = TRUE;
1019 if (!your_fault) angermon = FALSE;
1020 switch (obj->otyp) {
1022 case POT_EXTRA_HEALING:
1023 case POT_FULL_HEALING:
1024 if (mon->data == &mons[PM_PESTILENCE]) goto do_illness;
1026 case POT_RESTORE_ABILITY:
1027 case POT_GAIN_ABILITY:
1030 if(mon->mhp < mon->mhpmax) {
1031 mon->mhp = mon->mhpmax;
1033 pline("%s looks sound and hale again.", Monnam(mon));
1037 if (mon->data == &mons[PM_PESTILENCE]) goto do_healing;
1038 if (dmgtype(mon->data, AD_DISE) ||
1039 dmgtype(mon->data, AD_PEST) || /* won't happen, see prior goto */
1040 resists_poison(mon)) {
1042 pline("%s looks unharmed.", Monnam(mon));
1046 if((mon->mhpmax > 3) && !resist(mon, POTION_CLASS, 0, NOTELL))
1048 if((mon->mhp > 2) && !resist(mon, POTION_CLASS, 0, NOTELL))
1050 if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax;
1052 pline("%s looks rather ill.", Monnam(mon));
1056 if(!resist(mon, POTION_CLASS, 0, NOTELL)) mon->mconf = TRUE;
1058 case POT_INVISIBILITY:
1060 mon_set_minvis(mon);
1063 /* wakeup() doesn't rouse victims of temporary sleep */
1064 if (sleep_monst(mon, rnd(12), POTION_CLASS)) {
1065 pline("%s falls asleep.", Monnam(mon));
1070 if (mon->mcanmove) {
1072 /* really should be rnd(5) for consistency with players
1073 * breathing potions, but...
1075 mon->mfrozen = rnd(25);
1080 mon_adjust_speed(mon, 1, obj);
1083 if(haseyes(mon->data)) {
1084 register int btmp = 64 + rn2(32) +
1085 rn2(32) * !resist(mon, POTION_CLASS, 0, NOTELL);
1086 btmp += mon->mblinded;
1087 mon->mblinded = min(btmp,127);
1092 if (is_undead(mon->data) || is_demon(mon->data) ||
1093 is_were(mon->data)) {
1095 pline("%s %s in pain!", Monnam(mon),
1096 is_silent(mon->data) ? "writhes" : "shrieks");
1098 /* should only be by you */
1099 if (mon->mhp < 1) killed(mon);
1100 else if (is_were(mon->data) && !is_human(mon->data))
1101 new_were(mon); /* revert to human */
1102 } else if (obj->cursed) {
1105 pline("%s looks healthier.", Monnam(mon));
1107 if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax;
1108 if (is_were(mon->data) && is_human(mon->data) &&
1109 !Protection_from_shape_changers)
1110 new_were(mon); /* transform into beast */
1112 } else if(mon->data == &mons[PM_GREMLIN]) {
1114 (void)split_mon(mon, (struct monst *)0);
1115 } else if(mon->data == &mons[PM_IRON_GOLEM]) {
1117 pline("%s rusts.", Monnam(mon));
1119 /* should only be by you */
1120 if (mon->mhp < 1) killed(mon);
1125 splatter_burning_oil(mon->mx, mon->my);
1128 if (!resists_acid(mon) && !resist(mon, POTION_CLASS, 0, NOTELL)) {
1129 pline("%s %s in pain!", Monnam(mon),
1130 is_silent(mon->data) ? "writhes" : "shrieks");
1131 mon->mhp -= d(obj->cursed ? 2 : 1, obj->blessed ? 4 : 8);
1136 monkilled(mon, "", AD_ACID);
1141 (void) bhitm(mon, obj);
1144 case POT_GAIN_LEVEL:
1145 case POT_LEVITATION:
1146 case POT_FRUIT_JUICE:
1147 case POT_MONSTER_DETECTION:
1148 case POT_OBJECT_DETECTION:
1158 /* Note: potionbreathe() does its own docall() */
1159 if ((distance==0 || ((distance < 3) && rn2(5))) &&
1160 (!breathless(youmonst.data) || haseyes(youmonst.data)))
1162 else if (obj->dknown && !objects[obj->otyp].oc_name_known &&
1163 !objects[obj->otyp].oc_uname && cansee(mon->mx,mon->my))
1165 if(*u.ushops && obj->unpaid) {
1166 register struct monst *shkp =
1167 shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE));
1172 (void)stolen_value(obj, u.ux, u.uy,
1173 (boolean)shkp->mpeaceful, FALSE);
1174 subfrombill(obj, shkp);
1177 obfree(obj, (struct obj *)0);
1180 /* vapors are inhaled or get in your eyes */
1183 register struct obj *obj;
1185 register int i, ii, isdone, kn = 0;
1188 case POT_RESTORE_ABILITY:
1189 case POT_GAIN_ABILITY:
1191 if (!breathless(youmonst.data))
1192 pline("Ulch! That potion smells terrible!");
1193 else if (haseyes(youmonst.data)) {
1194 int numeyes = eyecount(youmonst.data);
1196 (numeyes == 1) ? body_part(EYE) : makeplural(body_part(EYE)),
1197 (numeyes == 1) ? "s" : "");
1201 i = rn2(A_MAX); /* start at a random point */
1202 for(isdone = ii = 0; !isdone && ii < A_MAX; ii++) {
1203 if(ABASE(i) < AMAX(i)) {
1205 /* only first found if not blessed */
1206 isdone = !(obj->blessed);
1209 if(++i >= A_MAX) i = 0;
1213 case POT_FULL_HEALING:
1214 if (Upolyd && u.mh < u.mhmax) u.mh++, flags.botl = 1;
1215 if (u.uhp < u.uhpmax) u.uhp++, flags.botl = 1;
1217 case POT_EXTRA_HEALING:
1218 if (Upolyd && u.mh < u.mhmax) u.mh++, flags.botl = 1;
1219 if (u.uhp < u.uhpmax) u.uhp++, flags.botl = 1;
1222 if (Upolyd && u.mh < u.mhmax) u.mh++, flags.botl = 1;
1223 if (u.uhp < u.uhpmax) u.uhp++, flags.botl = 1;
1224 exercise(A_CON, TRUE);
1227 if (!Role_if(PM_HEALER)) {
1229 if (u.mh <= 5) u.mh = 1; else u.mh -= 5;
1231 if (u.uhp <= 5) u.uhp = 1; else u.uhp -= 5;
1234 exercise(A_CON, FALSE);
1237 case POT_HALLUCINATION:
1238 You("have a momentary vision.");
1243 You_feel("somewhat dizzy.");
1244 make_confused(itimeout_incr(HConfusion, rnd(5)), FALSE);
1246 case POT_INVISIBILITY:
1247 if (!Blind && !Invis) {
1249 pline("For an instant you %s!",
1250 See_invisible ? "could see right through yourself"
1251 : "couldn't see yourself");
1257 pline("%s seems to be holding you.", Something);
1259 nomovemsg = You_can_move_again;
1260 exercise(A_DEX, FALSE);
1261 } else You("stiffen momentarily.");
1265 if (!Free_action && !Sleep_resistance) {
1266 You_feel("rather tired.");
1268 nomovemsg = You_can_move_again;
1269 exercise(A_DEX, FALSE);
1270 } else You("yawn.");
1273 if (!Fast) Your("knees seem more flexible now.");
1274 incr_itimeout(&HFast, rnd(5));
1275 exercise(A_DEX, TRUE);
1278 if (!Blind && !u.usleep) {
1280 pline("It suddenly gets dark.");
1282 make_blinded(itimeout_incr(Blinded, rnd(5)), FALSE);
1283 if (!Blind && !u.usleep) Your(vision_clears);
1286 if(u.umonnum == PM_GREMLIN) {
1287 (void)split_mon(&youmonst, (struct monst *)0);
1288 } else if (u.ulycn >= LOW_PM) {
1289 /* vapor from [un]holy water will trigger
1290 transformation but won't cure lycanthropy */
1291 if (obj->blessed && youmonst.data == &mons[u.ulycn])
1293 else if (obj->cursed && !Upolyd)
1299 exercise(A_CON, FALSE);
1302 case POT_GAIN_LEVEL:
1303 case POT_LEVITATION:
1304 case POT_FRUIT_JUICE:
1305 case POT_MONSTER_DETECTION:
1306 case POT_OBJECT_DETECTION:
1311 /* note: no obfree() */
1314 makeknown(obj->otyp);
1315 else if (!objects[obj->otyp].oc_name_known &&
1316 !objects[obj->otyp].oc_uname)
1323 register struct obj *o1, *o2;
1324 /* returns the potion type when o1 is dipped in o2 */
1326 /* cut down on the number of cases below */
1327 if (o1->oclass == POTION_CLASS &&
1328 (o2->otyp == POT_GAIN_LEVEL ||
1329 o2->otyp == POT_GAIN_ENERGY ||
1330 o2->otyp == POT_HEALING ||
1331 o2->otyp == POT_EXTRA_HEALING ||
1332 o2->otyp == POT_FULL_HEALING ||
1333 o2->otyp == POT_ENLIGHTENMENT ||
1334 o2->otyp == POT_FRUIT_JUICE)) {
1337 swp = o1; o1 = o2; o2 = swp;
1344 case POT_GAIN_LEVEL:
1345 case POT_GAIN_ENERGY:
1346 return POT_EXTRA_HEALING;
1348 case POT_EXTRA_HEALING:
1350 case POT_GAIN_LEVEL:
1351 case POT_GAIN_ENERGY:
1352 return POT_FULL_HEALING;
1354 case POT_FULL_HEALING:
1356 case POT_GAIN_LEVEL:
1357 case POT_GAIN_ENERGY:
1358 return POT_GAIN_ABILITY;
1363 return POT_FRUIT_JUICE;
1364 case POT_HALLUCINATION:
1370 case AMETHYST: /* "a-methyst" == "not intoxicated" */
1371 if (o2->otyp == POT_BOOZE)
1372 return POT_FRUIT_JUICE;
1374 case POT_GAIN_LEVEL:
1375 case POT_GAIN_ENERGY:
1378 return (rn2(3) ? POT_BOOZE : POT_ENLIGHTENMENT);
1380 return POT_EXTRA_HEALING;
1381 case POT_EXTRA_HEALING:
1382 return POT_FULL_HEALING;
1383 case POT_FULL_HEALING:
1384 return POT_GAIN_ABILITY;
1385 case POT_FRUIT_JUICE:
1386 return POT_SEE_INVISIBLE;
1388 return POT_HALLUCINATION;
1391 case POT_FRUIT_JUICE:
1394 return POT_SICKNESS;
1397 case POT_GAIN_LEVEL:
1398 case POT_GAIN_ENERGY:
1399 return POT_SEE_INVISIBLE;
1402 case POT_ENLIGHTENMENT:
1404 case POT_LEVITATION:
1405 if (rn2(3)) return POT_GAIN_LEVEL;
1407 case POT_FRUIT_JUICE:
1410 return POT_CONFUSION;
1421 register struct obj *obj;
1422 /* returns TRUE if something happened (potion should be used up) */
1424 char Your_buf[BUFSZ];
1426 if (snuff_lit(obj)) return(TRUE);
1429 grease_protect(obj,(char *)0,&youmonst);
1432 (void) Shk_Your(Your_buf, obj);
1433 /* (Rusting shop goods ought to be charged for.) */
1434 switch (obj->oclass) {
1436 if (obj->otyp == POT_WATER) return FALSE;
1437 /* KMH -- Water into acid causes an explosion */
1438 if (obj->otyp == POT_ACID) {
1439 pline("It boils vigorously!");
1440 You("are caught in the explosion!");
1441 losehp(rnd(10), "elementary chemistry", KILLED_BY);
1442 makeknown(obj->otyp);
1446 pline("%s %s%s.", Your_buf, aobjnam(obj,"dilute"),
1447 obj->odiluted ? " further" : "");
1448 if(obj->unpaid && costly_spot(u.ux, u.uy)) {
1449 You("dilute it, you pay for it.");
1450 bill_dummy_object(obj);
1452 if (obj->odiluted) {
1455 obj->blessed = FALSE;
1456 obj->cursed = FALSE;
1458 obj->blessed = obj->cursed = FALSE;
1460 obj->otyp = POT_WATER;
1461 } else obj->odiluted++;
1465 if (obj->otyp != SCR_BLANK_PAPER
1467 && obj->otyp != SCR_MAIL
1471 boolean oq1 = obj->quan == 1L;
1472 pline_The("scroll%s %s.",
1473 oq1 ? "" : "s", otense(obj, "fade"));
1475 if(obj->unpaid && costly_spot(u.ux, u.uy)) {
1476 You("erase it, you pay for it.");
1477 bill_dummy_object(obj);
1479 obj->otyp = SCR_BLANK_PAPER;
1485 if (obj->otyp != SPE_BLANK_PAPER) {
1487 if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
1488 pline("%s suddenly heats up; steam rises and it remains dry.",
1492 boolean oq1 = obj->quan == 1L;
1493 pline_The("spellbook%s %s.",
1494 oq1 ? "" : "s", otense(obj, "fade"));
1496 if(obj->unpaid && costly_spot(u.ux, u.uy)) {
1497 You("erase it, you pay for it.");
1498 bill_dummy_object(obj);
1500 obj->otyp = SPE_BLANK_PAPER;
1507 /* Just "fall through" to generic rustprone check for now. */
1510 if (!obj->oerodeproof && is_rustprone(obj) &&
1511 (obj->oeroded < MAX_ERODE) && !rn2(2)) {
1512 pline("%s %s some%s.",
1513 Your_buf, aobjnam(obj, "rust"),
1514 obj->oeroded ? " more" : "what");
1520 pline("%s %s wet.", Your_buf, aobjnam(obj,"get"));
1527 register struct obj *potion, *obj;
1528 struct obj *singlepotion;
1533 char qbuf[QBUFSZ], Your_buf[BUFSZ];
1535 allowall[0] = ALL_CLASSES; allowall[1] = '\0';
1536 if(!(obj = getobj(allowall, "dip")))
1539 here = levl[u.ux][u.uy].typ;
1540 /* Is there a fountain to dip into here? */
1541 if (IS_FOUNTAIN(here)) {
1542 if(yn("Dip it into the fountain?") == 'y') {
1546 } else if (is_pool(u.ux,u.uy)) {
1547 tmp = waterbody_name(u.ux,u.uy);
1548 Sprintf(qbuf, "Dip it into the %s?", tmp);
1549 if (yn(qbuf) == 'y') {
1551 floating_above(tmp);
1553 } else if (u.usteed && !is_swimmer(u.usteed->data) &&
1554 P_SKILL(P_RIDING) < P_BASIC) {
1555 rider_cant_reach(); /* not skilled enough to reach */
1558 (void) get_wet(obj);
1559 if (obj->otyp == POT_ACID) useup(obj);
1565 if(!(potion = getobj(beverages, "dip into")))
1567 if (potion == obj && potion->quan == 1L) {
1568 pline("That is a potion bottle, not a Klein bottle!");
1571 potion->in_use = TRUE; /* assume it will be used up */
1572 if(potion->otyp == POT_WATER) {
1573 boolean useeit = !Blind;
1574 if (useeit) (void) Shk_Your(Your_buf, obj);
1575 if (potion->blessed) {
1580 aobjnam(obj, "softly glow"),
1585 if(!(objects[potion->otyp].oc_name_known) &&
1586 !(objects[potion->otyp].oc_uname))
1590 } else if(!obj->blessed) {
1592 tmp = hcolor(NH_LIGHT_BLUE);
1593 pline("%s %s with a%s %s aura.",
1595 aobjnam(obj, "softly glow"),
1596 index(vowels, *tmp) ? "n" : "", tmp);
1602 } else if (potion->cursed) {
1607 aobjnam(obj, "glow"),
1608 hcolor((const char *)"brown"));
1612 } else if(!obj->cursed) {
1614 tmp = hcolor(NH_BLACK);
1615 pline("%s %s with a%s %s aura.",
1617 aobjnam(obj, "glow"),
1618 index(vowels, *tmp) ? "n" : "", tmp);
1627 } else if (obj->otyp == POT_POLYMORPH ||
1628 potion->otyp == POT_POLYMORPH) {
1629 /* some objects can't be polymorphed */
1630 if (obj->otyp == potion->otyp || /* both POT_POLY */
1631 obj->otyp == WAN_POLYMORPH ||
1632 obj->otyp == SPE_POLYMORPH ||
1633 obj == uball || obj == uskin ||
1634 obj_resists(obj->otyp == POT_POLYMORPH ?
1635 potion : obj, 5, 95)) {
1636 pline(nothing_happens);
1638 boolean was_wep = FALSE, was_swapwep = FALSE, was_quiver = FALSE;
1639 short save_otyp = obj->otyp;
1641 u.uconduct.polypiles++;
1643 if (obj == uwep) was_wep = TRUE;
1644 else if (obj == uswapwep) was_swapwep = TRUE;
1645 else if (obj == uquiver) was_quiver = TRUE;
1647 obj = poly_obj(obj, STRANGE_OBJECT);
1649 if (was_wep) setuwep(obj);
1650 else if (was_swapwep) setuswapwep(obj);
1651 else if (was_quiver) setuqwep(obj);
1653 if (obj->otyp != save_otyp) {
1654 makeknown(POT_POLYMORPH);
1656 prinv((char *)0, obj, 0L);
1659 pline("Nothing seems to happen.");
1663 potion->in_use = FALSE; /* didn't go poof */
1665 } else if(obj->oclass == POTION_CLASS && obj->otyp != potion->otyp) {
1666 /* Mixing potions is dangerous... */
1667 pline_The("potions mix...");
1668 /* KMH, balance patch -- acid is particularly unstable */
1669 if (obj->cursed || obj->otyp == POT_ACID || !rn2(10)) {
1670 pline("BOOM! They explode!");
1671 exercise(A_STR, FALSE);
1672 if (!breathless(youmonst.data) || haseyes(youmonst.data))
1676 losehp(rnd(10), "alchemic blast", KILLED_BY_AN);
1680 obj->blessed = obj->cursed = obj->bknown = 0;
1681 if (Blind || Hallucination) obj->dknown = 0;
1683 if ((mixture = mixtype(obj, potion)) != 0) {
1684 obj->otyp = mixture;
1686 switch (obj->odiluted ? 1 : rnd(8)) {
1688 obj->otyp = POT_WATER;
1692 obj->otyp = POT_SICKNESS;
1697 otmp = mkobj(POTION_CLASS,FALSE);
1698 obj->otyp = otmp->otyp;
1699 obfree(otmp, (struct obj *)0);
1704 pline_The("mixture glows brightly and evaporates.");
1711 obj->odiluted = (obj->otyp != POT_WATER);
1713 if (obj->otyp == POT_WATER && !Hallucination) {
1714 pline_The("mixture bubbles%s.",
1715 Blind ? "" : ", then clears");
1716 } else if (!Blind) {
1717 pline_The("mixture looks %s.",
1718 hcolor(OBJ_DESCR(objects[obj->otyp])));
1725 #ifdef INVISIBLE_OBJECTS
1726 if (potion->otyp == POT_INVISIBILITY && !obj->oinvis) {
1729 if (!See_invisible) pline("Where did %s go?",
1731 else You("notice a little haziness around %s.",
1735 } else if (potion->otyp == POT_SEE_INVISIBLE && obj->oinvis) {
1736 obj->oinvis = FALSE;
1738 if (!See_invisible) pline("So that's where %s went!",
1740 else pline_The("haziness around %s disappears.",
1747 if(is_poisonable(obj)) {
1748 if(potion->otyp == POT_SICKNESS && !obj->opoisoned) {
1750 if (potion->quan > 1L)
1751 Sprintf(buf, "One of %s", the(xname(potion)));
1753 Strcpy(buf, The(xname(potion)));
1754 pline("%s forms a coating on %s.",
1755 buf, the(xname(obj)));
1756 obj->opoisoned = TRUE;
1758 } else if(obj->opoisoned &&
1759 (potion->otyp == POT_HEALING ||
1760 potion->otyp == POT_EXTRA_HEALING ||
1761 potion->otyp == POT_FULL_HEALING)) {
1762 pline("A coating wears off %s.", the(xname(obj)));
1768 if (potion->otyp == POT_OIL) {
1769 boolean wisx = FALSE;
1770 if (potion->lamplit) { /* burning */
1771 int omat = objects[obj->otyp].oc_material;
1772 /* the code here should be merged with fire_damage */
1773 if (catch_lit(obj)) {
1774 /* catch_lit does all the work if true */
1775 } else if (obj->oerodeproof || obj_resists(obj, 5, 95) ||
1776 !is_flammable(obj) || obj->oclass == FOOD_CLASS) {
1777 pline("%s %s to burn for a moment.",
1778 Yname2(obj), otense(obj, "seem"));
1780 if ((omat == PLASTIC || omat == PAPER) && !obj->oartifact)
1781 obj->oeroded = MAX_ERODE;
1782 pline_The("burning oil %s %s.",
1783 obj->oeroded == MAX_ERODE ? "destroys" : "damages",
1785 if (obj->oeroded == MAX_ERODE) {
1786 obj_extract_self(obj);
1787 obfree(obj, (struct obj *)0);
1788 obj = (struct obj *) 0;
1790 /* we know it's carried */
1792 /* create a dummy duplicate to put on bill */
1793 verbalize("You burnt it, you bought it!");
1794 bill_dummy_object(obj);
1799 } else if (potion->cursed) {
1800 pline_The("potion spills and covers your %s with oil.",
1801 makeplural(body_part(FINGER)));
1802 incr_itimeout(&Glib, d(2,10));
1803 } else if (obj->oclass != WEAPON_CLASS && !is_weptool(obj)) {
1804 /* the following cases apply only to weapons */
1806 /* Oil removes rust and corrosion, but doesn't unburn.
1807 * Arrows, etc are classed as metallic due to arrowhead
1808 * material, but dipping in oil shouldn't repair them.
1810 } else if ((!is_rustprone(obj) && !is_corrodeable(obj)) ||
1811 is_ammo(obj) || (!obj->oeroded && !obj->oeroded2)) {
1812 /* uses up potion, doesn't set obj->greased */
1813 pline("%s %s with an oily sheen.",
1814 Yname2(obj), otense(obj, "gleam"));
1816 pline("%s %s less %s.",
1817 Yname2(obj), otense(obj, "are"),
1818 (obj->oeroded && obj->oeroded2) ? "corroded and rusty" :
1819 obj->oeroded ? "rusty" : "corroded");
1820 if (obj->oeroded > 0) obj->oeroded--;
1821 if (obj->oeroded2 > 0) obj->oeroded2--;
1824 exercise(A_WIS, wisx);
1825 makeknown(potion->otyp);
1831 /* Allow filling of MAGIC_LAMPs to prevent identification by player */
1832 if ((obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP) &&
1833 (potion->otyp == POT_OIL)) {
1834 /* Turn off engine before fueling, turn off fuel too :-) */
1835 if (obj->lamplit || potion->lamplit) {
1837 explode(u.ux, u.uy, 11, d(6,6), 0, EXPL_FIERY);
1838 exercise(A_WIS, FALSE);
1841 /* Adding oil to an empty magic lamp renders it into an oil lamp */
1842 if ((obj->otyp == MAGIC_LAMP) && obj->spe == 0) {
1843 obj->otyp = OIL_LAMP;
1846 if (obj->age > 1000L) {
1847 pline("%s %s full.", Yname2(obj), otense(obj, "are"));
1848 potion->in_use = FALSE; /* didn't go poof */
1850 You("fill %s with oil.", yname(obj));
1851 check_unpaid(potion); /* Yendorian Fuel Tax */
1852 obj->age += 2*potion->age; /* burns more efficiently */
1853 if (obj->age > 1500L) obj->age = 1500L;
1855 exercise(A_WIS, TRUE);
1863 potion->in_use = FALSE; /* didn't go poof */
1864 if ((obj->otyp == UNICORN_HORN || obj->otyp == AMETHYST) &&
1865 (mixture = mixtype(obj, potion)) != 0) {
1866 char oldbuf[BUFSZ], newbuf[BUFSZ];
1867 short old_otyp = potion->otyp;
1868 boolean old_dknown = FALSE;
1869 boolean more_than_one = potion->quan > 1;
1872 if (potion->dknown) {
1874 Sprintf(oldbuf, "%s ",
1875 hcolor(OBJ_DESCR(objects[potion->otyp])));
1877 /* with multiple merged potions, split off one and
1879 if (potion->quan > 1L) {
1880 singlepotion = splitobj(potion, 1L);
1881 } else singlepotion = potion;
1883 if(singlepotion->unpaid && costly_spot(u.ux, u.uy)) {
1884 You("use it, you pay for it.");
1885 bill_dummy_object(singlepotion);
1887 singlepotion->otyp = mixture;
1888 singlepotion->blessed = 0;
1889 if (mixture == POT_WATER)
1890 singlepotion->cursed = singlepotion->odiluted = 0;
1892 singlepotion->cursed = obj->cursed; /* odiluted left as-is */
1893 singlepotion->bknown = FALSE;
1895 singlepotion->dknown = FALSE;
1897 singlepotion->dknown = !Hallucination;
1898 if (mixture == POT_WATER && singlepotion->dknown)
1899 Sprintf(newbuf, "clears");
1901 Sprintf(newbuf, "turns %s",
1902 hcolor(OBJ_DESCR(objects[mixture])));
1903 pline_The("%spotion%s %s.", oldbuf,
1904 more_than_one ? " that you dipped into" : "",
1906 if(!objects[old_otyp].oc_uname &&
1907 !objects[old_otyp].oc_name_known && old_dknown) {
1911 fakeobj.otyp = old_otyp;
1912 fakeobj.oclass = POTION_CLASS;
1916 obj_extract_self(singlepotion);
1917 singlepotion = hold_another_object(singlepotion,
1918 "You juggle and drop %s!",
1919 doname(singlepotion), (const char *)0);
1924 pline("Interesting...");
1930 djinni_from_bottle(obj)
1931 register struct obj *obj;
1936 if(!(mtmp = makemon(&mons[PM_DJINNI], u.ux, u.uy, NO_MM_FLAGS))){
1937 pline("It turns out to be empty.");
1942 pline("In a cloud of smoke, %s emerges!", a_monnam(mtmp));
1943 pline("%s speaks.", Monnam(mtmp));
1945 You("smell acrid fumes.");
1946 pline("%s speaks.", Something);
1950 if (obj->blessed) chance = (chance == 4) ? rnd(4) : 0;
1951 else if (obj->cursed) chance = (chance == 0) ? rn2(4) : 4;
1952 /* 0,1,2,3,4: b=80%,5,5,5,5; nc=20%,20,20,20,20; c=5%,5,5,5,80 */
1955 case 0 : verbalize("I am in your debt. I will grant one wish!");
1959 case 1 : verbalize("Thank you for freeing me!");
1960 (void) tamedog(mtmp, (struct obj *)0);
1962 case 2 : verbalize("You freed me!");
1963 mtmp->mpeaceful = TRUE;
1966 case 3 : verbalize("It is about time!");
1967 pline("%s vanishes.", Monnam(mtmp));
1970 default: verbalize("You disturbed me, fool!");
1975 /* clone a gremlin or mold (2nd arg non-null implies heat as the trigger);
1976 hit points are cut in half (odd HP stays with original) */
1978 split_mon(mon, mtmp)
1979 struct monst *mon, /* monster being split */
1980 *mtmp; /* optional attacker whose heat triggered it */
1982 struct monst *mtmp2;
1986 if (mtmp) Sprintf(reason, " from %s heat",
1987 (mtmp == &youmonst) ? (const char *)"your" :
1988 (const char *)s_suffix(mon_nam(mtmp)));
1990 if (mon == &youmonst) {
1993 mtmp2->mhpmax = u.mhmax / 2;
1994 u.mhmax -= mtmp2->mhpmax;
1996 You("multiply%s!", reason);
1999 mtmp2 = clone_mon(mon, 0, 0);
2001 mtmp2->mhpmax = mon->mhpmax / 2;
2002 mon->mhpmax -= mtmp2->mhpmax;
2003 if (canspotmon(mon))
2004 pline("%s multiplies%s!", Monnam(mon), reason);