OSDN Git Service

04abd41a2db56373a0ed87c7fb9e93ab465b53cf
[nethackexpress/trunk.git] / src / potion.c
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. */
4
5 #include "hack.h"
6
7 #ifdef OVLB
8 boolean notonhead = FALSE;
9
10 static NEARDATA int nothing, unkn;
11 static NEARDATA const char beverages[] = { POTION_CLASS, 0 };
12
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 *));
17
18 /* force `val' to be within valid range for intrinsic timeout value */
19 STATIC_OVL long
20 itimeout(val)
21 long val;
22 {
23     if (val >= TIMEOUT) val = TIMEOUT;
24     else if (val < 1) val = 0;
25
26     return val;
27 }
28
29 /* increment `old' by `incr' and force result to be valid intrinsic timeout */
30 STATIC_OVL long
31 itimeout_incr(old, incr)
32 long old;
33 int incr;
34 {
35     return itimeout((old & TIMEOUT) + (long)incr);
36 }
37
38 /* set the timeout field of intrinsic `which' */
39 void
40 set_itimeout(which, val)
41 long *which, val;
42 {
43     *which &= ~TIMEOUT;
44     *which |= itimeout(val);
45 }
46
47 /* increment the timeout field of intrinsic `which' */
48 void
49 incr_itimeout(which, incr)
50 long *which;
51 int incr;
52 {
53     set_itimeout(which, itimeout_incr(*which, incr));
54 }
55
56 void
57 make_confused(xtime,talk)
58 long xtime;
59 boolean talk;
60 {
61         long old = HConfusion;
62
63         if (!xtime && old) {
64                 if (talk)
65                     You_feel("less %s now.",
66                         Hallucination ? "trippy" : "confused");
67         }
68         if ((xtime && !old) || (!xtime && old)) flags.botl = TRUE;
69
70         set_itimeout(&HConfusion, xtime);
71 }
72
73 void
74 make_stunned(xtime,talk)
75 long xtime;
76 boolean talk;
77 {
78         long old = HStun;
79
80         if (!xtime && old) {
81                 if (talk)
82                     You_feel("%s now.",
83                         Hallucination ? "less wobbly" : "a bit steadier");
84         }
85         if (xtime && !old) {
86                 if (talk) {
87 #ifdef STEED
88                         if (u.usteed)
89                                 You("wobble in the saddle.");
90                         else
91 #endif
92                         You("%s...", stagger(youmonst.data, "stagger"));
93                 }
94         }
95         if ((!xtime && old) || (xtime && !old)) flags.botl = TRUE;
96
97         set_itimeout(&HStun, xtime);
98 }
99
100 void
101 make_sick(xtime, cause, talk, type)
102 long xtime;
103 const char *cause;      /* sickness cause */
104 boolean talk;
105 int type;
106 {
107         long old = Sick;
108
109         if (xtime > 0L) {
110             if (Sick_resistance) return;
111             if (!old) {
112                 /* newly sick */
113                 You_feel("deathly sick.");
114             } else {
115                 /* already sick */
116                 if (talk) You_feel("%s worse.",
117                               xtime <= Sick/2L ? "much" : "even");
118             }
119             set_itimeout(&Sick, xtime);
120             u.usick_type |= type;
121             flags.botl = TRUE;
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 */
128             } else {
129                 if (talk) pline("What a relief!");
130                 Sick = 0L;              /* set_itimeout(&Sick, 0L) */
131             }
132             flags.botl = TRUE;
133         }
134
135         if (Sick) {
136             exercise(A_CON, FALSE);
137             if (cause) {
138                 (void) strncpy(u.usick_cause, cause, sizeof(u.usick_cause));
139                 u.usick_cause[sizeof(u.usick_cause)-1] = 0;
140                 }
141             else
142                 u.usick_cause[0] = 0;
143         } else
144             u.usick_cause[0] = 0;
145 }
146
147 void
148 make_vomiting(xtime, talk)
149 long xtime;
150 boolean talk;
151 {
152         long old = Vomiting;
153
154         if(!xtime && old)
155             if(talk) You_feel("much less nauseated now.");
156
157         set_itimeout(&Vomiting, xtime);
158 }
159
160 static const char vismsg[] = "vision seems to %s for a moment but is %s now.";
161 static const char eyemsg[] = "%s momentarily %s.";
162
163 void
164 make_blinded(xtime, talk)
165 long xtime;
166 boolean talk;
167 {
168         long old = Blinded;
169         boolean u_could_see, can_see_now;
170         int eyecnt;
171         char buf[BUFSZ];
172
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 */
179
180         if (u.usleep) talk = FALSE;
181
182         if (can_see_now && !u_could_see) {      /* regaining sight */
183             if (talk) {
184                 if (Hallucination)
185                     pline("Far out!  Everything is all cosmic again!");
186                 else
187                     You("can see again.");
188             }
189         } else if (old && !xtime) {
190             /* clearing temporary blindness without toggling blindness */
191             if (talk) {
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");
202                 }
203             }
204         }
205
206         if (u_could_see && !can_see_now) {      /* losing sight */
207             if (talk) {
208                 if (Hallucination)
209                     pline("Oh, bummer!  Everything is dark!  Help!");
210                 else
211                     pline("A cloud of darkness falls upon you.");
212             }
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 */
217             if (talk) {
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 */
226                     Your(vismsg, "dim",
227                          Hallucination ? "happier" : "normal");
228                 }
229             }
230         }
231
232         set_itimeout(&Blinded, xtime);
233
234         if (u_could_see ^ can_see_now) {  /* one or the other but not both */
235             flags.botl = 1;
236             vision_full_recalc = 1;     /* blindness just got toggled */
237             if (Blind_telepat || Infravision) see_monsters();
238         }
239 }
240
241 boolean
242 make_hallucinated(xtime, talk, mask)
243 long xtime;     /* nonzero if this is an attempt to turn on hallucination */
244 boolean talk;
245 long mask;      /* nonzero if resistance status should change by mask */
246 {
247         long old = HHallucination;
248         boolean changed = 0;
249         const char *message, *verb;
250
251         message = (!xtime) ? "Everything %s SO boring now." :
252                              "Oh wow!  Everything %s so cosmic!";
253         verb = (!Blind) ? "looks" : "feels";
254
255         if (mask) {
256             if (HHallucination) changed = TRUE;
257
258             if (!xtime) EHalluc_resistance |= mask;
259             else EHalluc_resistance &= ~mask;
260         } else {
261             if (!EHalluc_resistance && (!!HHallucination != !!xtime))
262                 changed = TRUE;
263             set_itimeout(&HHallucination, xtime);
264
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);
269                 } else if (Blind) {
270                     char buf[BUFSZ];
271                     int eyecnt = eyecount(youmonst.data);
272
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");
278                 }
279             }
280         }
281
282         if (changed) {
283             if (u.uswallow) {
284                 swallowed(0);   /* redraw swallow display */
285             } else {
286                 /* The see_* routines should be called *before* the pline. */
287                 see_monsters();
288                 see_objects();
289                 see_traps();
290             }
291
292             /* for perm_inv and anything similar
293             (eg. Qt windowport's equipped items display) */
294             update_inventory();
295
296             flags.botl = 1;
297             if (talk) pline(message, verb);
298         }
299         return changed;
300 }
301
302 STATIC_OVL void
303 ghost_from_bottle()
304 {
305         struct monst *mtmp = makemon(&mons[PM_GHOST], u.ux, u.uy, NO_MM_FLAGS);
306
307         if (!mtmp) {
308                 pline("This bottle turns out to be empty.");
309                 return;
310         }
311         if (Blind) {
312                 pline("As you open the bottle, %s emerges.", something);
313                 return;
314         }
315         pline("As you open the bottle, an enormous %s emerges!",
316                 Hallucination ? rndmonnam() : (const char *)"ghost");
317         if(flags.verbose)
318             You("are frightened to death, and unable to move.");
319         nomul(-3);
320         nomovemsg = "You regain your composure.";
321 }
322
323 /* "Quaffing is like drinking, except you spill more."  -- Terry Pratchett
324  */
325 int
326 dodrink()
327 {
328         register struct obj *otmp;
329         const char *potion_descr;
330
331         if (Strangled) {
332                 pline("If you can't breathe air, how can you drink liquid?");
333                 return 0;
334         }
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') {
338                         drinkfountain();
339                         return 1;
340                 }
341         }
342 #ifdef SINKS
343         /* Or a kitchen sink? */
344         if (IS_SINK(levl[u.ux][u.uy].typ)) {
345                 if (yn("Drink from the sink?") == 'y') {
346                         drinksink();
347                         return 1;
348                 }
349         }
350 #endif
351
352         /* Or are you surrounded by water? */
353         if (Underwater) {
354                 if (yn("Drink the water around you?") == 'y') {
355                     pline("Do you know what lives in this water!");
356                         return 1;
357                 }
358         }
359
360         otmp = getobj(beverages, "drink");
361         if(!otmp) return(0);
362         otmp->in_use = TRUE;            /* you've opened the stopper */
363
364 #define POTION_OCCUPANT_CHANCE(n) (13 + 2*(n))  /* also in muse.c */
365
366         potion_descr = OBJ_DESCR(objects[otmp->otyp]);
367         if (potion_descr) {
368             if (!strcmp(potion_descr, "milky") &&
369                     flags.ghost_count < MAXMONNO &&
370                     !rn2(POTION_OCCUPANT_CHANCE(flags.ghost_count))) {
371                 ghost_from_bottle();
372                 useup(otmp);
373                 return(1);
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);
378                 useup(otmp);
379                 return(1);
380             }
381         }
382         return dopotion(otmp);
383 }
384
385 int
386 dopotion(otmp)
387 register struct obj *otmp;
388 {
389         int retval;
390
391         otmp->in_use = TRUE;
392         nothing = unkn = 0;
393         if((retval = peffects(otmp)) >= 0) return(retval);
394
395         if(nothing) {
396             unkn++;
397             You("have a %s feeling for a moment, then it passes.",
398                   Hallucination ? "normal" : "peculiar");
399         }
400         if(otmp->dknown && !objects[otmp->otyp].oc_name_known) {
401                 if(!unkn) {
402                         makeknown(otmp->otyp);
403                         more_experienced(0,10);
404                 } else if(!objects[otmp->otyp].oc_uname)
405                         docall(otmp);
406         }
407         useup(otmp);
408         return(1);
409 }
410
411 int
412 peffects(otmp)
413         register struct obj     *otmp;
414 {
415         register int i, ii, lim;
416
417         switch(otmp->otyp){
418         case POT_RESTORE_ABILITY:
419         case SPE_RESTORE_ABILITY:
420                 unkn++;
421                 if(otmp->cursed) {
422                     pline("Ulch!  This makes you feel mediocre!");
423                     break;
424                 } else {
425                     pline("Wow!  This makes you feel %s!",
426                           (otmp->blessed) ?
427                                 (unfixable_trouble_count(FALSE) ? "better" : "great")
428                           : "good");
429                     i = rn2(A_MAX);             /* start at a random point */
430                     for (ii = 0; ii < A_MAX; ii++) {
431                         lim = AMAX(i);
432                         if (i == A_STR && u.uhs >= 3) --lim;    /* WEAK */
433                         if (ABASE(i) < lim) {
434                             ABASE(i) = lim;
435                             flags.botl = 1;
436                             /* only first found if not blessed */
437                             if (!otmp->blessed) break;
438                         }
439                         if(++i >= A_MAX) i = 0;
440                     }
441                 }
442                 break;
443         case POT_HALLUCINATION:
444                 if (Hallucination || Halluc_resistance) nothing++;
445                 (void) make_hallucinated(itimeout_incr(HHallucination,
446                                            rn1(200, 600 - 300 * bcsign(otmp))),
447                                   TRUE, 0L);
448                 break;
449         case POT_WATER:
450                 if(!otmp->blessed && !otmp->cursed) {
451                     pline("This tastes like water.");
452                     u.uhunger += rnd(10);
453                     newuhs(FALSE);
454                     break;
455                 }
456                 unkn++;
457                 if(is_undead(youmonst.data) || is_demon(youmonst.data) ||
458                                 u.ualign.type == A_CHAOTIC) {
459                     if(otmp->blessed) {
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])
466                                 you_unwere(FALSE);
467                             u.ulycn = NON_PM;   /* cure lycanthropy */
468                         }
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);
475                     }
476                 } else {
477                     if(otmp->blessed) {
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); */
485                     } else {
486                         if(u.ualign.type == A_LAWFUL) {
487                             pline("This burns like acid!");
488                             losehp(d(2,6), "potion of unholy water",
489                                 KILLED_BY_AN);
490                         } else
491                             You_feel("full of dread.");
492                         if (u.ulycn >= LOW_PM && !Upolyd) you_were();
493                         exercise(A_CON, FALSE);
494                     }
495                 }
496                 break;
497         case POT_BOOZE:
498                 unkn++;
499                 pline("Ooph!  This tastes like %s%s!",
500                       otmp->odiluted ? "watered down " : "",
501                       Hallucination ? "dandelion wine" : "liquid fire");
502                 if (!otmp->blessed)
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));
507                 newuhs(FALSE);
508                 exercise(A_WIS, FALSE);
509                 if(otmp->cursed) {
510                         You("pass out.");
511                         multi = -rnd(15);
512                         nomovemsg = "You awake with a headache.";
513                 }
514                 break;
515         case POT_ENLIGHTENMENT:
516                 if(otmp->cursed) {
517                         unkn++;
518                         You("have an uneasy feeling...");
519                         exercise(A_WIS, FALSE);
520                 } else {
521                         if (otmp->blessed) {
522                                 (void) adjattrib(A_INT, 1, FALSE);
523                                 (void) adjattrib(A_WIS, 1, FALSE);
524                         }
525                         You_feel("self-knowledgeable...");
526                         display_nhwindow(WIN_MESSAGE, FALSE);
527                         enlightenment(0);
528                         pline_The("feeling subsides.");
529                         exercise(A_WIS, TRUE);
530                 }
531                 break;
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));
536                         break;
537                 }
538                 /* FALLTHRU */
539         case POT_INVISIBILITY:
540                 if (Invis || Blind || BInvis) {
541                     nothing++;
542                 } else {
543                     self_invis_message();
544                 }
545                 if (otmp->blessed) HInvis |= FROMOUTSIDE;
546                 else incr_itimeout(&HInvis, rn1(15,31));
547                 newsym(u.ux,u.uy);      /* update position */
548                 if(otmp->cursed) {
549                     pline("For some reason, you feel your presence is known.");
550                     aggravate();
551                 }
552                 break;
553         case POT_SEE_INVISIBLE:
554                 /* tastes like fruit juice in Rogue */
555         case POT_FRUIT_JUICE:
556             {
557                 int msg = Invisible && !Blind;
558
559                 unkn++;
560                 if (otmp->cursed)
561                     pline("Yecch!  This tastes %s.",
562                           Hallucination ? "overripe" : "rotten");
563                 else
564                     pline(Hallucination ?
565                       "This tastes like 10%% real %s%s all-natural beverage." :
566                                 "This tastes like %s%s.",
567                           otmp->odiluted ? "reconstituted " : "",
568                           fruitname(TRUE));
569                 if (otmp->otyp == POT_FRUIT_JUICE) {
570                     u.uhunger += (otmp->odiluted ? 5 : 10) * (2 + bcsign(otmp));
571                     newuhs(FALSE);
572                     break;
573                 }
574                 if (!otmp->cursed) {
575                         /* Tell them they can see again immediately, which
576                          * will help them identify the potion...
577                          */
578                         make_blinded(0L,TRUE);
579                 }
580                 if (otmp->blessed)
581                         HSee_invisible |= FROMOUTSIDE;
582                 else
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!");
589                     unkn--;
590                 }
591                 break;
592             }
593         case POT_PARALYSIS:
594                 if (Free_action)
595                     You("stiffen momentarily.");
596                 else {
597                     if (Levitation || Is_airlevel(&u.uz)||Is_waterlevel(&u.uz))
598                         You("are motionlessly suspended.");
599 #ifdef STEED
600                     else if (u.usteed)
601                         You("are frozen in place!");
602 #endif
603                     else
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);
609                 }
610                 break;
611         case POT_SLEEPING:
612                 if(Sleep_resistance || Free_action)
613                     You("yawn.");
614                 else {
615                     You("suddenly fall asleep!");
616                     fall_asleep(-rn1(10, 25 - 12*bcsign(otmp)), TRUE);
617                 }
618                 break;
619         case POT_MONSTER_DETECTION:
620         case SPE_DETECT_MONSTERS:
621                 if (otmp->blessed) {
622                     int x, y;
623
624                     if (Detect_monsters) nothing++;
625                     unkn++;
626                     /* after a while, repeated uses become less effective */
627                     if (HDetect_monsters >= 300L)
628                         i = 1;
629                     else
630                         i = rn1(40,21);
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) {
635                                 unmap_object(x, y);
636                                 newsym(x,y);
637                             }
638                             if (MON_AT(x,y)) unkn = 0;
639                         }
640                     }
641                     see_monsters();
642                     if (unkn) You_feel("lonely.");
643                     break;
644                 }
645                 if (monster_detect(otmp, 0))
646                         return(1);              /* nothing detected */
647                 exercise(A_WIS, TRUE);
648                 break;
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);
654                 break;
655         case POT_SICKNESS:
656                 pline("Yecch!  This stuff tastes like poison.");
657                 if (otmp->blessed) {
658                     pline("(But in fact it was mildly stale %s.)",
659                           fruitname(TRUE));
660                     if (!Role_if(PM_HEALER)) {
661                         /* NB: blessed otmp->fromsink is not possible */
662                         losehp(1, "mildly contaminated potion", KILLED_BY_AN);
663                     }
664                 } else {
665                     if(Poison_resistance)
666                         pline(
667                           "(But in fact it was biologically contaminated %s.)",
668                               fruitname(TRUE));
669                     if (Role_if(PM_HEALER))
670                         pline("Fortunately, you have been immunized.");
671                     else {
672                         int typ = rn2(A_MAX);
673
674                         if (!Fixed_abil) {
675                             poisontell(typ);
676                             (void) adjattrib(typ,
677                                         Poison_resistance ? -1 : -rn1(4,3),
678                                         TRUE);
679                         }
680                         if(!Poison_resistance) {
681                             if (otmp->fromsink)
682                                 losehp(rnd(10)+5*!!(otmp->cursed),
683                                        "contaminated tap water", KILLED_BY);
684                             else
685                                 losehp(rnd(10)+5*!!(otmp->cursed),
686                                        "contaminated potion", KILLED_BY_AN);
687                         }
688                         exercise(A_CON, FALSE);
689                     }
690                 }
691                 if(Hallucination) {
692                         You("are shocked back to your senses!");
693                         (void) make_hallucinated(0L,FALSE,0L);
694                 }
695                 break;
696         case POT_CONFUSION:
697                 if(!Confusion)
698                     if (Hallucination) {
699                         pline("What a trippy feeling!");
700                         unkn++;
701                     } else
702                         pline("Huh, What?  Where am I?");
703                 else    nothing++;
704                 make_confused(itimeout_incr(HConfusion,
705                                             rn1(7, 16 - 8 * bcsign(otmp))),
706                               FALSE);
707                 break;
708         case POT_GAIN_ABILITY:
709                 if(otmp->cursed) {
710                     pline("Ulch!  That potion tasted foul!");
711                     unkn++;
712                 } else if (Fixed_abil) {
713                     nothing++;
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)
723                             break;
724                     }
725                 }
726                 break;
727         case POT_SPEED:
728                 if(Wounded_legs && !otmp->cursed
729 #ifdef STEED
730                    && !u.usteed /* heal_legs() would heal steeds legs */
731 #endif
732                                                 ) {
733                         heal_legs();
734                         unkn++;
735                         break;
736                 } /* and fall through */
737         case SPE_HASTE_SELF:
738                 if(!Very_fast) /* wwf@doe.carleton.ca */
739                         You("are suddenly moving %sfaster.",
740                                 Fast ? "" : "much ");
741                 else {
742                         Your("%s get new energy.",
743                                 makeplural(body_part(LEG)));
744                         unkn++;
745                 }
746                 exercise(A_DEX, TRUE);
747                 incr_itimeout(&HFast, rn1(10, 100 + 60 * bcsign(otmp)));
748                 break;
749         case POT_BLINDNESS:
750                 if(Blind) nothing++;
751                 make_blinded(itimeout_incr(Blinded,
752                                            rn1(200, 250 - 125 * bcsign(otmp))),
753                              (boolean)!Blind);
754                 break;
755         case POT_GAIN_LEVEL:
756                 if (otmp->cursed) {
757                         unkn++;
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);
765                             } else {
766                                 register int newlev = depth(&u.uz)-1;
767                                 d_level newlevel;
768
769                                 get_level(&newlevel, newlev);
770                                 if(on_level(&newlevel, &u.uz)) {
771                                     pline("It tasted bad.");
772                                     break;
773                                 } else You(riseup, ceiling(u.ux,u.uy));
774                                 goto_level(&newlevel, FALSE, FALSE, FALSE);
775                             }
776                         }
777                         else You("have an uneasy feeling.");
778                         break;
779                 }
780                 pluslvl(FALSE);
781                 if (otmp->blessed)
782                         /* blessed potions place you at a random spot in the
783                          * middle of the new level instead of the low point
784                          */
785                         u.uexp = rndexp(TRUE);
786                 break;
787         case POT_HEALING:
788                 You_feel("better.");
789                 healup(d(6 + 2 * bcsign(otmp), 4),
790                        !otmp->cursed ? 1 : 0, !!otmp->blessed, !otmp->cursed);
791                 exercise(A_CON, TRUE);
792                 break;
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);
801                 break;
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 */
809                     u.ulevelmax -= 1;
810                     pluslvl(FALSE);
811                 }
812                 (void) make_hallucinated(0L,TRUE,0L);
813                 exercise(A_STR, TRUE);
814                 exercise(A_CON, TRUE);
815                 break;
816         case POT_LEVITATION:
817         case SPE_LEVITATION:
818                 if (otmp->cursed) HLevitation &= ~I_SPECIAL;
819                 if(!Levitation) {
820                         /* kludge to ensure proper operation of float_up() */
821                         HLevitation = 1;
822                         float_up();
823                         /* reverse kludge */
824                         HLevitation = 0;
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)
829         ) {
830                                         You("hit your %s on the %s.",
831                                                 body_part(HEAD),
832                                                 ceiling(u.ux,u.uy));
833                                         losehp(uarmh ? 1 : rnd(10),
834                                                 "colliding with the ceiling",
835                                                 KILLED_BY);
836                                 } else (void) doup();
837                         }
838                 } else
839                         nothing++;
840                 if (otmp->blessed) {
841                     incr_itimeout(&HLevitation, rn1(50,250));
842                     HLevitation |= I_SPECIAL;
843                 } else incr_itimeout(&HLevitation, rn1(140,10));
844                 spoteffects(FALSE);     /* for sinks */
845                 break;
846         case POT_GAIN_ENERGY:                   /* M. Stephenson */
847                 {       register int num;
848                         if(otmp->cursed)
849                             You_feel("lackluster.");
850                         else
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;
857                         flags.botl = 1;
858                         exercise(A_WIS, TRUE);
859                 }
860                 break;
861         case POT_OIL:                           /* P. Winner */
862                 {
863                         boolean good_for_you = FALSE;
864
865                         if (otmp->lamplit) {
866                             if (likes_fire(youmonst.data)) {
867                                 pline("Ahh, a refreshing drink.");
868                                 good_for_you = TRUE;
869                             } else {
870                                 You("burn your %s.", body_part(FACE));
871                                 losehp(d(Fire_resistance ? 1 : 3, 4),
872                                        "burning potion of oil", KILLED_BY_AN);
873                             }
874                         } else if(otmp->cursed)
875                             pline("This tastes like castor oil.");
876                         else
877                             pline("That was smooth!");
878                         exercise(A_WIS, good_for_you);
879                 }
880                 break;
881         case POT_ACID:
882                 if (Acid_resistance)
883                         /* Not necessarily a creature who _likes_ acid */
884                         pline("This tastes %s.", Hallucination ? "tangy" : "sour");
885                 else {
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);
891                 }
892                 if (Stoned) fix_petrification();
893                 unkn++; /* holy/unholy water can burn like acid too */
894                 break;
895         case POT_POLYMORPH:
896                 You_feel("a little %s.", Hallucination ? "normal" : "strange");
897                 if (!Unchanging) polyself(FALSE);
898                 break;
899         default:
900                 impossible("What a funny potion! (%u)", otmp->otyp);
901                 return(0);
902         }
903         return(-1);
904 }
905
906 void
907 healup(nhp, nxtra, curesick, cureblind)
908         int nhp, nxtra;
909         register boolean curesick, cureblind;
910 {
911         if (nhp) {
912                 if (Upolyd) {
913                         u.mh += nhp;
914                         if (u.mh > u.mhmax) u.mh = (u.mhmax += nxtra);
915                 } else {
916                         u.uhp += nhp;
917                         if(u.uhp > u.uhpmax) u.uhp = (u.uhpmax += nxtra);
918                 }
919         }
920         if(cureblind)   make_blinded(0L,TRUE);
921         if(curesick)    make_sick(0L, (char *) 0, TRUE, SICK_ALL);
922         flags.botl = 1;
923         return;
924 }
925
926 void
927 strange_feeling(obj,txt)
928 register struct obj *obj;
929 register const char *txt;
930 {
931         if (flags.beginner || !txt)
932                 You("have a %s feeling for a moment, then it passes.",
933                 Hallucination ? "normal" : "strange");
934         else
935                 pline(txt);
936
937         if(!obj)        /* e.g., crystal ball finds no traps */
938                 return;
939
940         if(obj->dknown && !objects[obj->otyp].oc_name_known &&
941                                                 !objects[obj->otyp].oc_uname)
942                 docall(obj);
943         useup(obj);
944 }
945
946 const char *bottlenames[] = {
947         "bottle", "phial", "flagon", "carafe", "flask", "jar", "vial"
948 };
949
950
951 const char *
952 bottlename()
953 {
954         return bottlenames[rn2(SIZE(bottlenames))];
955 }
956
957 void
958 potionhit(mon, obj, your_fault)
959 register struct monst *mon;
960 register struct obj *obj;
961 boolean your_fault;
962 {
963         register const char *botlnam = bottlename();
964         boolean isyou = (mon == &youmonst);
965         int distance;
966
967         if(isyou) {
968                 distance = 0;
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);
972         } else {
973                 distance = distu(mon->mx,mon->my);
974                 if (!cansee(mon->mx,mon->my)) pline("Crash!");
975                 else {
976                     char *mnam = mon_nam(mon);
977                     char buf[BUFSZ];
978
979                     if(has_head(mon->data)) {
980                         Sprintf(buf, "%s %s",
981                                 s_suffix(mnam),
982                                 (notonhead ? "body" : "head"));
983                     } else {
984                         Strcpy(buf, mnam);
985                     }
986                     pline_The("%s crashes on %s and breaks into shards.",
987                            botlnam, buf);
988                 }
989                 if(rn2(5) && mon->mhp > 1)
990                         mon->mhp--;
991         }
992
993         /* oil doesn't instantly evaporate */
994         if (obj->otyp != POT_OIL && cansee(mon->mx,mon->my))
995                 pline("%s.", Tobjnam(obj, "evaporate"));
996
997     if (isyou) {
998         switch (obj->otyp) {
999         case POT_OIL:
1000                 if (obj->lamplit)
1001                     splatter_burning_oil(u.ux, u.uy);
1002                 break;
1003         case POT_POLYMORPH:
1004                 You_feel("a little %s.", Hallucination ? "normal" : "strange");
1005                 if (!Unchanging && !Antimagic) polyself(FALSE);
1006                 break;
1007         case POT_ACID:
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);
1013                 }
1014                 break;
1015         }
1016     } else {
1017         boolean angermon = TRUE;
1018
1019         if (!your_fault) angermon = FALSE;
1020         switch (obj->otyp) {
1021         case POT_HEALING:
1022         case POT_EXTRA_HEALING:
1023         case POT_FULL_HEALING:
1024                 if (mon->data == &mons[PM_PESTILENCE]) goto do_illness;
1025                 /*FALLTHRU*/
1026         case POT_RESTORE_ABILITY:
1027         case POT_GAIN_ABILITY:
1028  do_healing:
1029                 angermon = FALSE;
1030                 if(mon->mhp < mon->mhpmax) {
1031                     mon->mhp = mon->mhpmax;
1032                     if (canseemon(mon))
1033                         pline("%s looks sound and hale again.", Monnam(mon));
1034                 }
1035                 break;
1036         case POT_SICKNESS:
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)) {
1041                     if (canseemon(mon))
1042                         pline("%s looks unharmed.", Monnam(mon));
1043                     break;
1044                 }
1045  do_illness:
1046                 if((mon->mhpmax > 3) && !resist(mon, POTION_CLASS, 0, NOTELL))
1047                         mon->mhpmax /= 2;
1048                 if((mon->mhp > 2) && !resist(mon, POTION_CLASS, 0, NOTELL))
1049                         mon->mhp /= 2;
1050                 if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax;
1051                 if (canseemon(mon))
1052                     pline("%s looks rather ill.", Monnam(mon));
1053                 break;
1054         case POT_CONFUSION:
1055         case POT_BOOZE:
1056                 if(!resist(mon, POTION_CLASS, 0, NOTELL))  mon->mconf = TRUE;
1057                 break;
1058         case POT_INVISIBILITY:
1059                 angermon = FALSE;
1060                 mon_set_minvis(mon);
1061                 break;
1062         case POT_SLEEPING:
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));
1066                     slept_monst(mon);
1067                 }
1068                 break;
1069         case POT_PARALYSIS:
1070                 if (mon->mcanmove) {
1071                         mon->mcanmove = 0;
1072                         /* really should be rnd(5) for consistency with players
1073                          * breathing potions, but...
1074                          */
1075                         mon->mfrozen = rnd(25);
1076                 }
1077                 break;
1078         case POT_SPEED:
1079                 angermon = FALSE;
1080                 mon_adjust_speed(mon, 1, obj);
1081                 break;
1082         case POT_BLINDNESS:
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);
1088                     mon->mcansee = 0;
1089                 }
1090                 break;
1091         case POT_WATER:
1092                 if (is_undead(mon->data) || is_demon(mon->data) ||
1093                         is_were(mon->data)) {
1094                     if (obj->blessed) {
1095                         pline("%s %s in pain!", Monnam(mon),
1096                               is_silent(mon->data) ? "writhes" : "shrieks");
1097                         mon->mhp -= d(2,6);
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) {
1103                         angermon = FALSE;
1104                         if (canseemon(mon))
1105                             pline("%s looks healthier.", Monnam(mon));
1106                         mon->mhp += d(2,6);
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 */
1111                     }
1112                 } else if(mon->data == &mons[PM_GREMLIN]) {
1113                     angermon = FALSE;
1114                     (void)split_mon(mon, (struct monst *)0);
1115                 } else if(mon->data == &mons[PM_IRON_GOLEM]) {
1116                     if (canseemon(mon))
1117                         pline("%s rusts.", Monnam(mon));
1118                     mon->mhp -= d(1,6);
1119                     /* should only be by you */
1120                     if (mon->mhp < 1) killed(mon);
1121                 }
1122                 break;
1123         case POT_OIL:
1124                 if (obj->lamplit)
1125                         splatter_burning_oil(mon->mx, mon->my);
1126                 break;
1127         case POT_ACID:
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);
1132                     if (mon->mhp < 1) {
1133                         if (your_fault)
1134                             killed(mon);
1135                         else
1136                             monkilled(mon, "", AD_ACID);
1137                     }
1138                 }
1139                 break;
1140         case POT_POLYMORPH:
1141                 (void) bhitm(mon, obj);
1142                 break;
1143 /*
1144         case POT_GAIN_LEVEL:
1145         case POT_LEVITATION:
1146         case POT_FRUIT_JUICE:
1147         case POT_MONSTER_DETECTION:
1148         case POT_OBJECT_DETECTION:
1149                 break;
1150 */
1151         }
1152         if (angermon)
1153             wakeup(mon);
1154         else
1155             mon->msleeping = 0;
1156     }
1157
1158         /* Note: potionbreathe() does its own docall() */
1159         if ((distance==0 || ((distance < 3) && rn2(5))) &&
1160             (!breathless(youmonst.data) || haseyes(youmonst.data)))
1161                 potionbreathe(obj);
1162         else if (obj->dknown && !objects[obj->otyp].oc_name_known &&
1163                    !objects[obj->otyp].oc_uname && cansee(mon->mx,mon->my))
1164                 docall(obj);
1165         if(*u.ushops && obj->unpaid) {
1166                 register struct monst *shkp =
1167                         shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE));
1168
1169                 if(!shkp)
1170                     obj->unpaid = 0;
1171                 else {
1172                     (void)stolen_value(obj, u.ux, u.uy,
1173                                  (boolean)shkp->mpeaceful, FALSE);
1174                     subfrombill(obj, shkp);
1175                 }
1176         }
1177         obfree(obj, (struct obj *)0);
1178 }
1179
1180 /* vapors are inhaled or get in your eyes */
1181 void
1182 potionbreathe(obj)
1183 register struct obj *obj;
1184 {
1185         register int i, ii, isdone, kn = 0;
1186
1187         switch(obj->otyp) {
1188         case POT_RESTORE_ABILITY:
1189         case POT_GAIN_ABILITY:
1190                 if(obj->cursed) {
1191                     if (!breathless(youmonst.data))
1192                         pline("Ulch!  That potion smells terrible!");
1193                     else if (haseyes(youmonst.data)) {
1194                         int numeyes = eyecount(youmonst.data);
1195                         Your("%s sting%s!",
1196                              (numeyes == 1) ? body_part(EYE) : makeplural(body_part(EYE)),
1197                              (numeyes == 1) ? "s" : "");
1198                     }
1199                     break;
1200                 } else {
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)) {
1204                             ABASE(i)++;
1205                             /* only first found if not blessed */
1206                             isdone = !(obj->blessed);
1207                             flags.botl = 1;
1208                         }
1209                         if(++i >= A_MAX) i = 0;
1210                     }
1211                 }
1212                 break;
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;
1216                 /*FALL THROUGH*/
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;
1220                 /*FALL THROUGH*/
1221         case POT_HEALING:
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);
1225                 break;
1226         case POT_SICKNESS:
1227                 if (!Role_if(PM_HEALER)) {
1228                         if (Upolyd) {
1229                             if (u.mh <= 5) u.mh = 1; else u.mh -= 5;
1230                         } else {
1231                             if (u.uhp <= 5) u.uhp = 1; else u.uhp -= 5;
1232                         }
1233                         flags.botl = 1;
1234                         exercise(A_CON, FALSE);
1235                 }
1236                 break;
1237         case POT_HALLUCINATION:
1238                 You("have a momentary vision.");
1239                 break;
1240         case POT_CONFUSION:
1241         case POT_BOOZE:
1242                 if(!Confusion)
1243                         You_feel("somewhat dizzy.");
1244                 make_confused(itimeout_incr(HConfusion, rnd(5)), FALSE);
1245                 break;
1246         case POT_INVISIBILITY:
1247                 if (!Blind && !Invis) {
1248                     kn++;
1249                     pline("For an instant you %s!",
1250                         See_invisible ? "could see right through yourself"
1251                         : "couldn't see yourself");
1252                 }
1253                 break;
1254         case POT_PARALYSIS:
1255                 kn++;
1256                 if (!Free_action) {
1257                     pline("%s seems to be holding you.", Something);
1258                     nomul(-rnd(5));
1259                     nomovemsg = You_can_move_again;
1260                     exercise(A_DEX, FALSE);
1261                 } else You("stiffen momentarily.");
1262                 break;
1263         case POT_SLEEPING:
1264                 kn++;
1265                 if (!Free_action && !Sleep_resistance) {
1266                     You_feel("rather tired.");
1267                     nomul(-rnd(5));
1268                     nomovemsg = You_can_move_again;
1269                     exercise(A_DEX, FALSE);
1270                 } else You("yawn.");
1271                 break;
1272         case POT_SPEED:
1273                 if (!Fast) Your("knees seem more flexible now.");
1274                 incr_itimeout(&HFast, rnd(5));
1275                 exercise(A_DEX, TRUE);
1276                 break;
1277         case POT_BLINDNESS:
1278                 if (!Blind && !u.usleep) {
1279                     kn++;
1280                     pline("It suddenly gets dark.");
1281                 }
1282                 make_blinded(itimeout_incr(Blinded, rnd(5)), FALSE);
1283                 if (!Blind && !u.usleep) Your(vision_clears);
1284                 break;
1285         case POT_WATER:
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])
1292                         you_unwere(FALSE);
1293                     else if (obj->cursed && !Upolyd)
1294                         you_were();
1295                 }
1296                 break;
1297         case POT_ACID:
1298         case POT_POLYMORPH:
1299                 exercise(A_CON, FALSE);
1300                 break;
1301 /*
1302         case POT_GAIN_LEVEL:
1303         case POT_LEVITATION:
1304         case POT_FRUIT_JUICE:
1305         case POT_MONSTER_DETECTION:
1306         case POT_OBJECT_DETECTION:
1307         case POT_OIL:
1308                 break;
1309 */
1310         }
1311         /* note: no obfree() */
1312         if (obj->dknown) {
1313             if (kn)
1314                 makeknown(obj->otyp);
1315             else if (!objects[obj->otyp].oc_name_known &&
1316                                                 !objects[obj->otyp].oc_uname)
1317                 docall(obj);
1318         }
1319 }
1320
1321 STATIC_OVL short
1322 mixtype(o1, o2)
1323 register struct obj *o1, *o2;
1324 /* returns the potion type when o1 is dipped in o2 */
1325 {
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)) {
1335                 struct obj *swp;
1336
1337                 swp = o1; o1 = o2; o2 = swp;
1338         }
1339
1340         switch (o1->otyp) {
1341                 case POT_HEALING:
1342                         switch (o2->otyp) {
1343                             case POT_SPEED:
1344                             case POT_GAIN_LEVEL:
1345                             case POT_GAIN_ENERGY:
1346                                 return POT_EXTRA_HEALING;
1347                         }
1348                 case POT_EXTRA_HEALING:
1349                         switch (o2->otyp) {
1350                             case POT_GAIN_LEVEL:
1351                             case POT_GAIN_ENERGY:
1352                                 return POT_FULL_HEALING;
1353                         }
1354                 case POT_FULL_HEALING:
1355                         switch (o2->otyp) {
1356                             case POT_GAIN_LEVEL:
1357                             case POT_GAIN_ENERGY:
1358                                 return POT_GAIN_ABILITY;
1359                         }
1360                 case UNICORN_HORN:
1361                         switch (o2->otyp) {
1362                             case POT_SICKNESS:
1363                                 return POT_FRUIT_JUICE;
1364                             case POT_HALLUCINATION:
1365                             case POT_BLINDNESS:
1366                             case POT_CONFUSION:
1367                                 return POT_WATER;
1368                         }
1369                         break;
1370                 case AMETHYST:          /* "a-methyst" == "not intoxicated" */
1371                         if (o2->otyp == POT_BOOZE)
1372                             return POT_FRUIT_JUICE;
1373                         break;
1374                 case POT_GAIN_LEVEL:
1375                 case POT_GAIN_ENERGY:
1376                         switch (o2->otyp) {
1377                             case POT_CONFUSION:
1378                                 return (rn2(3) ? POT_BOOZE : POT_ENLIGHTENMENT);
1379                             case POT_HEALING:
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;
1387                             case POT_BOOZE:
1388                                 return POT_HALLUCINATION;
1389                         }
1390                         break;
1391                 case POT_FRUIT_JUICE:
1392                         switch (o2->otyp) {
1393                             case POT_SICKNESS:
1394                                 return POT_SICKNESS;
1395                             case POT_SPEED:
1396                                 return POT_BOOZE;
1397                             case POT_GAIN_LEVEL:
1398                             case POT_GAIN_ENERGY:
1399                                 return POT_SEE_INVISIBLE;
1400                         }
1401                         break;
1402                 case POT_ENLIGHTENMENT:
1403                         switch (o2->otyp) {
1404                             case POT_LEVITATION:
1405                                 if (rn2(3)) return POT_GAIN_LEVEL;
1406                                 break;
1407                             case POT_FRUIT_JUICE:
1408                                 return POT_BOOZE;
1409                             case POT_BOOZE:
1410                                 return POT_CONFUSION;
1411                         }
1412                         break;
1413         }
1414
1415         return 0;
1416 }
1417
1418
1419 boolean
1420 get_wet(obj)
1421 register struct obj *obj;
1422 /* returns TRUE if something happened (potion should be used up) */
1423 {
1424         char Your_buf[BUFSZ];
1425
1426         if (snuff_lit(obj)) return(TRUE);
1427
1428         if (obj->greased) {
1429                 grease_protect(obj,(char *)0,&youmonst);
1430                 return(FALSE);
1431         }
1432         (void) Shk_Your(Your_buf, obj);
1433         /* (Rusting shop goods ought to be charged for.) */
1434         switch (obj->oclass) {
1435             case POTION_CLASS:
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);
1443                         update_inventory();
1444                         return (TRUE);
1445                 }
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);
1451                 }
1452                 if (obj->odiluted) {
1453                         obj->odiluted = 0;
1454 #ifdef UNIXPC
1455                         obj->blessed = FALSE;
1456                         obj->cursed = FALSE;
1457 #else
1458                         obj->blessed = obj->cursed = FALSE;
1459 #endif
1460                         obj->otyp = POT_WATER;
1461                 } else obj->odiluted++;
1462                 update_inventory();
1463                 return TRUE;
1464             case SCROLL_CLASS:
1465                 if (obj->otyp != SCR_BLANK_PAPER
1466 #ifdef MAIL
1467                     && obj->otyp != SCR_MAIL
1468 #endif
1469                     ) {
1470                         if (!Blind) {
1471                                 boolean oq1 = obj->quan == 1L;
1472                                 pline_The("scroll%s %s.",
1473                                           oq1 ? "" : "s", otense(obj, "fade"));
1474                         }
1475                         if(obj->unpaid && costly_spot(u.ux, u.uy)) {
1476                             You("erase it, you pay for it.");
1477                             bill_dummy_object(obj);
1478                         }
1479                         obj->otyp = SCR_BLANK_PAPER;
1480                         obj->spe = 0;
1481                         update_inventory();
1482                         return TRUE;
1483                 } else break;
1484             case SPBOOK_CLASS:
1485                 if (obj->otyp != SPE_BLANK_PAPER) {
1486
1487                         if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
1488         pline("%s suddenly heats up; steam rises and it remains dry.",
1489                                 The(xname(obj)));
1490                         } else {
1491                             if (!Blind) {
1492                                     boolean oq1 = obj->quan == 1L;
1493                                     pline_The("spellbook%s %s.",
1494                                         oq1 ? "" : "s", otense(obj, "fade"));
1495                             }
1496                             if(obj->unpaid && costly_spot(u.ux, u.uy)) {
1497                                 You("erase it, you pay for it.");
1498                                 bill_dummy_object(obj);
1499                             }
1500                             obj->otyp = SPE_BLANK_PAPER;
1501                             update_inventory();
1502                         }
1503                         return TRUE;
1504                 }
1505                 break;
1506             case WEAPON_CLASS:
1507             /* Just "fall through" to generic rustprone check for now. */
1508             /* fall through */
1509             default:
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");
1515                         obj->oeroded++;
1516                         update_inventory();
1517                         return TRUE;
1518                 } else break;
1519         }
1520         pline("%s %s wet.", Your_buf, aobjnam(obj,"get"));
1521         return FALSE;
1522 }
1523
1524 int
1525 dodip()
1526 {
1527         register struct obj *potion, *obj;
1528         struct obj *singlepotion;
1529         const char *tmp;
1530         uchar here;
1531         char allowall[2];
1532         short mixture;
1533         char qbuf[QBUFSZ], Your_buf[BUFSZ];
1534
1535         allowall[0] = ALL_CLASSES; allowall[1] = '\0';
1536         if(!(obj = getobj(allowall, "dip")))
1537                 return(0);
1538
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') {
1543                         dipfountain(obj);
1544                         return(1);
1545                 }
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') {
1550                     if (Levitation) {
1551                         floating_above(tmp);
1552 #ifdef STEED
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 */
1556 #endif
1557                     } else {
1558                         (void) get_wet(obj);
1559                         if (obj->otyp == POT_ACID) useup(obj);
1560                     }
1561                     return 1;
1562                 }
1563         }
1564
1565         if(!(potion = getobj(beverages, "dip into")))
1566                 return(0);
1567         if (potion == obj && potion->quan == 1L) {
1568                 pline("That is a potion bottle, not a Klein bottle!");
1569                 return 0;
1570         }
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) {
1576                         if (obj->cursed) {
1577                                 if (useeit)
1578                                     pline("%s %s %s.",
1579                                           Your_buf,
1580                                           aobjnam(obj, "softly glow"),
1581                                           hcolor(NH_AMBER));
1582                                 uncurse(obj);
1583                                 obj->bknown=1;
1584         poof:
1585                                 if(!(objects[potion->otyp].oc_name_known) &&
1586                                    !(objects[potion->otyp].oc_uname))
1587                                         docall(potion);
1588                                 useup(potion);
1589                                 return(1);
1590                         } else if(!obj->blessed) {
1591                                 if (useeit) {
1592                                     tmp = hcolor(NH_LIGHT_BLUE);
1593                                     pline("%s %s with a%s %s aura.",
1594                                           Your_buf,
1595                                           aobjnam(obj, "softly glow"),
1596                                           index(vowels, *tmp) ? "n" : "", tmp);
1597                                 }
1598                                 bless(obj);
1599                                 obj->bknown=1;
1600                                 goto poof;
1601                         }
1602                 } else if (potion->cursed) {
1603                         if (obj->blessed) {
1604                                 if (useeit)
1605                                     pline("%s %s %s.",
1606                                           Your_buf,
1607                                           aobjnam(obj, "glow"),
1608                                           hcolor((const char *)"brown"));
1609                                 unbless(obj);
1610                                 obj->bknown=1;
1611                                 goto poof;
1612                         } else if(!obj->cursed) {
1613                                 if (useeit) {
1614                                     tmp = hcolor(NH_BLACK);
1615                                     pline("%s %s with a%s %s aura.",
1616                                           Your_buf,
1617                                           aobjnam(obj, "glow"),
1618                                           index(vowels, *tmp) ? "n" : "", tmp);
1619                                 }
1620                                 curse(obj);
1621                                 obj->bknown=1;
1622                                 goto poof;
1623                         }
1624                 } else
1625                         if (get_wet(obj))
1626                             goto poof;
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);
1637             } else {
1638                 boolean was_wep = FALSE, was_swapwep = FALSE, was_quiver = FALSE;
1639                 short save_otyp = obj->otyp;
1640                 /* KMH, conduct */
1641                 u.uconduct.polypiles++;
1642
1643                 if (obj == uwep) was_wep = TRUE;
1644                 else if (obj == uswapwep) was_swapwep = TRUE;
1645                 else if (obj == uquiver) was_quiver = TRUE;
1646
1647                 obj = poly_obj(obj, STRANGE_OBJECT);
1648
1649                 if (was_wep) setuwep(obj);
1650                 else if (was_swapwep) setuswapwep(obj);
1651                 else if (was_quiver) setuqwep(obj);
1652
1653                 if (obj->otyp != save_otyp) {
1654                         makeknown(POT_POLYMORPH);
1655                         useup(potion);
1656                         prinv((char *)0, obj, 0L);
1657                         return 1;
1658                 } else {
1659                         pline("Nothing seems to happen.");
1660                         goto poof;
1661                 }
1662             }
1663             potion->in_use = FALSE;     /* didn't go poof */
1664             return(1);
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))
1673                                 potionbreathe(obj);
1674                         useup(obj);
1675                         useup(potion);
1676                         losehp(rnd(10), "alchemic blast", KILLED_BY_AN);
1677                         return(1);
1678                 }
1679
1680                 obj->blessed = obj->cursed = obj->bknown = 0;
1681                 if (Blind || Hallucination) obj->dknown = 0;
1682
1683                 if ((mixture = mixtype(obj, potion)) != 0) {
1684                         obj->otyp = mixture;
1685                 } else {
1686                     switch (obj->odiluted ? 1 : rnd(8)) {
1687                         case 1:
1688                                 obj->otyp = POT_WATER;
1689                                 break;
1690                         case 2:
1691                         case 3:
1692                                 obj->otyp = POT_SICKNESS;
1693                                 break;
1694                         case 4:
1695                                 {
1696                                   struct obj *otmp;
1697                                   otmp = mkobj(POTION_CLASS,FALSE);
1698                                   obj->otyp = otmp->otyp;
1699                                   obfree(otmp, (struct obj *)0);
1700                                 }
1701                                 break;
1702                         default:
1703                                 if (!Blind)
1704                           pline_The("mixture glows brightly and evaporates.");
1705                                 useup(obj);
1706                                 useup(potion);
1707                                 return(1);
1708                     }
1709                 }
1710
1711                 obj->odiluted = (obj->otyp != POT_WATER);
1712
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])));
1719                 }
1720
1721                 useup(potion);
1722                 return(1);
1723         }
1724
1725 #ifdef INVISIBLE_OBJECTS
1726         if (potion->otyp == POT_INVISIBILITY && !obj->oinvis) {
1727                 obj->oinvis = TRUE;
1728                 if (!Blind) {
1729                     if (!See_invisible) pline("Where did %s go?",
1730                                 the(xname(obj)));
1731                     else You("notice a little haziness around %s.",
1732                                 the(xname(obj)));
1733                 }
1734                 goto poof;
1735         } else if (potion->otyp == POT_SEE_INVISIBLE && obj->oinvis) {
1736                 obj->oinvis = FALSE;
1737                 if (!Blind) {
1738                     if (!See_invisible) pline("So that's where %s went!",
1739                                 the(xname(obj)));
1740                     else pline_The("haziness around %s disappears.",
1741                                 the(xname(obj)));
1742                 }
1743                 goto poof;
1744         }
1745 #endif
1746
1747         if(is_poisonable(obj)) {
1748             if(potion->otyp == POT_SICKNESS && !obj->opoisoned) {
1749                 char buf[BUFSZ];
1750                 if (potion->quan > 1L)
1751                     Sprintf(buf, "One of %s", the(xname(potion)));
1752                 else
1753                     Strcpy(buf, The(xname(potion)));
1754                 pline("%s forms a coating on %s.",
1755                       buf, the(xname(obj)));
1756                 obj->opoisoned = TRUE;
1757                 goto poof;
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)));
1763                 obj->opoisoned = 0;
1764                 goto poof;
1765             }
1766         }
1767
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"));
1779                 } else {
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",
1784                             yname(obj));
1785                     if (obj->oeroded == MAX_ERODE) {
1786                         obj_extract_self(obj);
1787                         obfree(obj, (struct obj *)0);
1788                         obj = (struct obj *) 0;
1789                     } else {
1790                         /* we know it's carried */
1791                         if (obj->unpaid) {
1792                             /* create a dummy duplicate to put on bill */
1793                             verbalize("You burnt it, you bought it!");
1794                             bill_dummy_object(obj);
1795                         }
1796                         obj->oeroded++;
1797                     }
1798                 }
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 */
1805                 goto more_dips;
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.
1809              */
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"));
1815             } else {
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--;
1822                 wisx = TRUE;
1823             }
1824             exercise(A_WIS, wisx);
1825             makeknown(potion->otyp);
1826             useup(potion);
1827             return 1;
1828         }
1829     more_dips:
1830
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) {
1836                 useup(potion);
1837                 explode(u.ux, u.uy, 11, d(6,6), 0, EXPL_FIERY);
1838                 exercise(A_WIS, FALSE);
1839                 return 1;
1840             }
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;
1844                 obj->age = 0;
1845             }
1846             if (obj->age > 1000L) {
1847                 pline("%s %s full.", Yname2(obj), otense(obj, "are"));
1848                 potion->in_use = FALSE; /* didn't go poof */
1849             } else {
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;
1854                 useup(potion);
1855                 exercise(A_WIS, TRUE);
1856             }
1857             makeknown(POT_OIL);
1858             obj->spe = 1;
1859             update_inventory();
1860             return 1;
1861         }
1862
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;
1870
1871                 oldbuf[0] = '\0';
1872                 if (potion->dknown) {
1873                     old_dknown = TRUE;
1874                     Sprintf(oldbuf, "%s ",
1875                             hcolor(OBJ_DESCR(objects[potion->otyp])));
1876                 }
1877                 /* with multiple merged potions, split off one and
1878                    just clear it */
1879                 if (potion->quan > 1L) {
1880                     singlepotion = splitobj(potion, 1L);
1881                 } else singlepotion = potion;
1882                 
1883                 if(singlepotion->unpaid && costly_spot(u.ux, u.uy)) {
1884                     You("use it, you pay for it.");
1885                     bill_dummy_object(singlepotion);
1886                 }
1887                 singlepotion->otyp = mixture;
1888                 singlepotion->blessed = 0;
1889                 if (mixture == POT_WATER)
1890                     singlepotion->cursed = singlepotion->odiluted = 0;
1891                 else
1892                     singlepotion->cursed = obj->cursed;  /* odiluted left as-is */
1893                 singlepotion->bknown = FALSE;
1894                 if (Blind) {
1895                     singlepotion->dknown = FALSE;
1896                 } else {
1897                     singlepotion->dknown = !Hallucination;
1898                     if (mixture == POT_WATER && singlepotion->dknown)
1899                         Sprintf(newbuf, "clears");
1900                     else
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" : "",
1905                               newbuf);
1906                     if(!objects[old_otyp].oc_uname &&
1907                         !objects[old_otyp].oc_name_known && old_dknown) {
1908                         struct obj fakeobj;
1909                         fakeobj = zeroobj;
1910                         fakeobj.dknown = 1;
1911                         fakeobj.otyp = old_otyp;
1912                         fakeobj.oclass = POTION_CLASS;
1913                         docall(&fakeobj);
1914                     }
1915                 }
1916                 obj_extract_self(singlepotion);
1917                 singlepotion = hold_another_object(singlepotion,
1918                                         "You juggle and drop %s!",
1919                                         doname(singlepotion), (const char *)0);
1920                 update_inventory();
1921                 return(1);
1922         }
1923
1924         pline("Interesting...");
1925         return(1);
1926 }
1927
1928
1929 void
1930 djinni_from_bottle(obj)
1931 register struct obj *obj;
1932 {
1933         struct monst *mtmp;
1934         int chance;
1935
1936         if(!(mtmp = makemon(&mons[PM_DJINNI], u.ux, u.uy, NO_MM_FLAGS))){
1937                 pline("It turns out to be empty.");
1938                 return;
1939         }
1940
1941         if (!Blind) {
1942                 pline("In a cloud of smoke, %s emerges!", a_monnam(mtmp));
1943                 pline("%s speaks.", Monnam(mtmp));
1944         } else {
1945                 You("smell acrid fumes.");
1946                 pline("%s speaks.", Something);
1947         }
1948
1949         chance = rn2(5);
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 */
1953
1954         switch (chance) {
1955         case 0 : verbalize("I am in your debt.  I will grant one wish!");
1956                 makewish();
1957                 mongone(mtmp);
1958                 break;
1959         case 1 : verbalize("Thank you for freeing me!");
1960                 (void) tamedog(mtmp, (struct obj *)0);
1961                 break;
1962         case 2 : verbalize("You freed me!");
1963                 mtmp->mpeaceful = TRUE;
1964                 set_malign(mtmp);
1965                 break;
1966         case 3 : verbalize("It is about time!");
1967                 pline("%s vanishes.", Monnam(mtmp));
1968                 mongone(mtmp);
1969                 break;
1970         default: verbalize("You disturbed me, fool!");
1971                 break;
1972         }
1973 }
1974
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) */
1977 struct monst *
1978 split_mon(mon, mtmp)
1979 struct monst *mon,      /* monster being split */
1980              *mtmp;     /* optional attacker whose heat triggered it */
1981 {
1982         struct monst *mtmp2;
1983         char reason[BUFSZ];
1984
1985         reason[0] = '\0';
1986         if (mtmp) Sprintf(reason, " from %s heat",
1987                           (mtmp == &youmonst) ? (const char *)"your" :
1988                               (const char *)s_suffix(mon_nam(mtmp)));
1989
1990         if (mon == &youmonst) {
1991             mtmp2 = cloneu();
1992             if (mtmp2) {
1993                 mtmp2->mhpmax = u.mhmax / 2;
1994                 u.mhmax -= mtmp2->mhpmax;
1995                 flags.botl = 1;
1996                 You("multiply%s!", reason);
1997             }
1998         } else {
1999             mtmp2 = clone_mon(mon, 0, 0);
2000             if (mtmp2) {
2001                 mtmp2->mhpmax = mon->mhpmax / 2;
2002                 mon->mhpmax -= mtmp2->mhpmax;
2003                 if (canspotmon(mon))
2004                     pline("%s multiplies%s!", Monnam(mon), reason);
2005             }
2006         }
2007         return mtmp2;
2008 }
2009
2010 #endif /* OVLB */
2011
2012 /*potion.c*/