Source:SLASH'EM 0.0.7E7F2/potion.c

From NetHackWiki
Jump to navigation Jump to search

Below is the full text to potion.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/potion.c#line123]], for example.

The latest source code for vanilla NetHack is at Source code.


The NetHack General Public License applies to screenshots, source code and other content from NetHack.

This content was modified from the original NetHack source code distribution (by splitting up NetHack content between wiki pages, and possibly further editing). See the page history for a list of who changed it, and on what dates.

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.    
8.    /* KMH, intrinsics patch
9.     * There are many changes here to support >32-bit properties.
10.    * Also, blessed potions are once again permitted to convey
11.    * permanent intrinsics.
12.    */
13.   
14.   
15.   #ifdef OVLB
16.   boolean notonhead = FALSE;
17.   
18.   static NEARDATA int nothing, unkn;
19.   static NEARDATA const char beverages[] = { POTION_CLASS, 0 };
20.   
21.   STATIC_DCL long FDECL(itimeout, (long));
22.   STATIC_DCL long FDECL(itimeout_incr, (long,int));
23.   STATIC_DCL void NDECL(ghost_from_bottle);
24.   STATIC_DCL short FDECL(mixtype, (struct obj *,struct obj *));
25.   
26.   STATIC_DCL void FDECL(healup_mon, (struct monst *, int,int,BOOLEAN_P,BOOLEAN_P));
27.   	/* For healing monsters - analogous to healup for players */
28.   
29.   
30.   /* force `val' to be within valid range for intrinsic timeout value */
31.   STATIC_OVL long
32.   itimeout(val)
33.   long val;
34.   {
35.       if (val >= TIMEOUT) val = TIMEOUT;
36.       else if (val < 1) val = 0;
37.   
38.       return val;
39.   }
40.   
41.   /* increment `old' by `incr' and force result to be valid intrinsic timeout */
42.   STATIC_OVL long
43.   itimeout_incr(old, incr)
44.   long old;
45.   int incr;
46.   {
47.       return itimeout((old & TIMEOUT) + (long)incr);
48.   }
49.   
50.   /* set the timeout field of intrinsic `which' */
51.   void
52.   set_itimeout(which, val)
53.   long *which, val;
54.   {
55.       *which &= ~TIMEOUT;
56.       *which |= itimeout(val);
57.   }
58.   
59.   /* increment the timeout field of intrinsic `which' */
60.   void
61.   incr_itimeout(which, incr)
62.   long *which;
63.   int incr;
64.   {
65.       set_itimeout(which, itimeout_incr(*which, incr));
66.   }
67.   
68.   void
69.   make_confused(xtime,talk)
70.   long xtime;
71.   boolean talk;
72.   {
73.   	long old = HConfusion;
74.   
75.   	if (!xtime && old) {
76.   		if (talk)
77.   		    You_feel("less %s now.",
78.   			Hallucination ? "trippy" : "confused");
79.   	}
80.   	if ((xtime && !old) || (!xtime && old)) flags.botl = TRUE;
81.   
82.   	set_itimeout(&HConfusion, xtime);
83.   }
84.   
85.   void
86.   make_stunned(xtime,talk)
87.   long xtime;
88.   boolean talk;
89.   {
90.   	long old = HStun;
91.   
92.   	if (!xtime && old) {
93.   		if (talk)
94.   		    You_feel("%s now.",
95.   			Hallucination ? "less wobbly" : "a bit steadier");
96.   	}
97.   	if (xtime && !old) {
98.   		if (talk) {
99.   #ifdef STEED
100.  			if (u.usteed)
101.  				You("wobble in the saddle.");
102.  			else
103.  #endif
104.  			You("%s...", stagger(youmonst.data, "stagger"));
105.  		}
106.  	}
107.  	if ((!xtime && old) || (xtime && !old)) flags.botl = TRUE;
108.  
109.  	set_itimeout(&HStun, xtime);
110.  }
111.  
112.  void
113.  make_sick(xtime, cause, talk, type)
114.  long xtime;
115.  const char *cause;	/* sickness cause */
116.  boolean talk;
117.  int type;
118.  {
119.  	long old = Sick;
120.  
121.  	if (xtime > 0L) {
122.  	    if (Sick_resistance) return;
123.  	    if (!old) {
124.  		/* newly sick */
125.  		You_feel("deathly sick.");
126.  	    } else {
127.  		/* already sick */
128.  		if (talk) You_feel("%s worse.",
129.  			      xtime <= Sick/2L ? "much" : "even");
130.  	    }
131.  	    set_itimeout(&Sick, xtime);
132.  	    u.usick_type |= type;
133.  	    flags.botl = TRUE;
134.  	} else if (old && (type & u.usick_type)) {
135.  	    /* was sick, now not */
136.  	    u.usick_type &= ~type;
137.  	    if (u.usick_type) { /* only partly cured */
138.  		if (talk) You_feel("somewhat better.");
139.  		set_itimeout(&Sick, Sick * 2); /* approximation */
140.  	    } else {
141.  		if (talk) pline("What a relief!");
142.  		Sick = 0L;		/* set_itimeout(&Sick, 0L) */
143.  	    }
144.  	    flags.botl = TRUE;
145.  	}
146.  
147.  	if (Sick) {
148.  	    exercise(A_CON, FALSE);
149.  	    if (cause) {
150.  		(void) strncpy(u.usick_cause, cause, sizeof(u.usick_cause));
151.  		u.usick_cause[sizeof(u.usick_cause)-1] = 0;
152.  		}
153.  	    else
154.  		u.usick_cause[0] = 0;
155.  	} else
156.  	    u.usick_cause[0] = 0;
157.  }
158.  
159.  void
160.  make_vomiting(xtime, talk)
161.  long xtime;
162.  boolean talk;
163.  {
164.  	long old = Vomiting;
165.  
166.  	if(!xtime && old)
167.  	    if(talk) You_feel("much less nauseated now.");
168.  
169.  	set_itimeout(&Vomiting, xtime);
170.  }
171.  
172.  static const char vismsg[] = "vision seems to %s for a moment but is %s now.";
173.  static const char eyemsg[] = "%s momentarily %s.";
174.  
175.  void
176.  make_blinded(xtime, talk)
177.  long xtime;
178.  boolean talk;
179.  {
180.  	long old = Blinded;
181.  	boolean u_could_see, can_see_now;
182.  	int eyecnt;
183.  	char buf[BUFSZ];
184.  
185.  	/* we need to probe ahead in case the Eyes of the Overworld
186.  	   are or will be overriding blindness */
187.  	u_could_see = !Blind;
188.  	Blinded = xtime ? 1L : 0L;
189.  	can_see_now = !Blind;
190.  	Blinded = old;		/* restore */
191.  
192.  	if (u.usleep) talk = FALSE;
193.  
194.  	if (can_see_now && !u_could_see) {	/* regaining sight */
195.  	    if (talk) {
196.  		if (Hallucination)
197.  		    pline("Far out!  Everything is all cosmic again!");
198.  		else
199.  		    You("can see again.");
200.  	    }
201.  	} else if (old && !xtime) {
202.  	    /* clearing temporary blindness without toggling blindness */
203.  	    if (talk) {
204.  		if (!haseyes(youmonst.data)) {
205.  		    strange_feeling((struct obj *)0, (char *)0);
206.  		} else if (Blindfolded) {
207.  		    Strcpy(buf, body_part(EYE));
208.  		    eyecnt = eyecount(youmonst.data);
209.  		    Your(eyemsg, (eyecnt == 1) ? buf : makeplural(buf),
210.  			 (eyecnt == 1) ? "itches" : "itch");
211.  		} else {	/* Eyes of the Overworld */
212.  		    Your(vismsg, "brighten",
213.  			 Hallucination ? "sadder" : "normal");
214.  		}
215.  	    }
216.  	}
217.  
218.  	if (u_could_see && !can_see_now) {	/* losing sight */
219.  	    if (talk) {
220.  		if (Hallucination)
221.  		    pline("Oh, bummer!  Everything is dark!  Help!");
222.  		else
223.  		    pline("A cloud of darkness falls upon you.");
224.  	    }
225.  	    /* Before the hero goes blind, set the ball&chain variables. */
226.  	    if (Punished) set_bc(0);
227.  	} else if (!old && xtime) {
228.  	    /* setting temporary blindness without toggling blindness */
229.  	    if (talk) {
230.  		if (!haseyes(youmonst.data)) {
231.  		    strange_feeling((struct obj *)0, (char *)0);
232.  		} else if (Blindfolded) {
233.  		    Strcpy(buf, body_part(EYE));
234.  		    eyecnt = eyecount(youmonst.data);
235.  		    Your(eyemsg, (eyecnt == 1) ? buf : makeplural(buf),
236.  			 (eyecnt == 1) ? "twitches" : "twitch");
237.  		} else {	/* Eyes of the Overworld */
238.  		    Your(vismsg, "dim",
239.  			 Hallucination ? "happier" : "normal");
240.  		}
241.  	    }
242.  	}
243.  
244.  	set_itimeout(&Blinded, xtime);
245.  
246.  	if (u_could_see ^ can_see_now) {  /* one or the other but not both */
247.  	    flags.botl = 1;
248.  	    vision_full_recalc = 1;	/* blindness just got toggled */
249.  	    if (Blind_telepat || Infravision) see_monsters();
250.  	}
251.  }
252.  
253.  boolean
254.  make_hallucinated(xtime, talk, mask)
255.  long xtime;	/* nonzero if this is an attempt to turn on hallucination */
256.  boolean talk;
257.  long mask;	/* nonzero if resistance status should change by mask */
258.  {
259.  	long old = HHallucination;
260.  	boolean changed = 0;
261.  	const char *message, *verb;
262.  
263.  	message = (!xtime) ? "Everything %s SO boring now." :
264.  			     "Oh wow!  Everything %s so cosmic!";
265.  	verb = (!Blind) ? "looks" : "feels";
266.  
267.  	if (mask) {
268.  	    if (HHallucination) changed = TRUE;
269.  
270.  	    if (!xtime) EHalluc_resistance |= mask;
271.  	    else EHalluc_resistance &= ~mask;
272.  	} else {
273.  	    if (!EHalluc_resistance && (!!HHallucination != !!xtime))
274.  		changed = TRUE;
275.  	    set_itimeout(&HHallucination, xtime);
276.  
277.  	    /* clearing temporary hallucination without toggling vision */
278.  	    if (!changed && !HHallucination && old && talk) {
279.  		if (!haseyes(youmonst.data)) {
280.  		    strange_feeling((struct obj *)0, (char *)0);
281.  		} else if (Blind) {
282.  		    char buf[BUFSZ];
283.  		    int eyecnt = eyecount(youmonst.data);
284.  
285.  		    Strcpy(buf, body_part(EYE));
286.  		    Your(eyemsg, (eyecnt == 1) ? buf : makeplural(buf),
287.  			 (eyecnt == 1) ? "itches" : "itch");
288.  		} else {	/* Grayswandir */
289.  		    Your(vismsg, "flatten", "normal");
290.  		}
291.  	    }
292.  	}
293.  
294.  	if (changed) {
295.  	    if (u.uswallow) {
296.  		swallowed(0);	/* redraw swallow display */
297.  	    } else {
298.  		/* The see_* routines should be called *before* the pline. */
299.  		see_monsters();
300.  		see_objects();
301.  		see_traps();
302.  	    }
303.  
304.  	    /* for perm_inv and anything similar
305.  	    (eg. Qt windowport's equipped items display) */
306.  	    update_inventory();
307.  
308.  	    flags.botl = 1;
309.  	    if (talk) pline(message, verb);
310.  	}
311.  	return changed;
312.  }
313.  
314.  STATIC_OVL void
315.  ghost_from_bottle()
316.  {
317.  	struct monst *mtmp = makemon(&mons[PM_GHOST], u.ux, u.uy, NO_MM_FLAGS);
318.  
319.  	if (!mtmp) {
320.  		pline("This bottle turns out to be empty.");
321.  		return;
322.  	}
323.  	if (Blind) {
324.  		pline("As you open the bottle, %s emerges.", something);
325.  		return;
326.  	}
327.  	pline("As you open the bottle, an enormous %s emerges!",
328.  		Hallucination ? rndmonnam() : (const char *)"ghost");
329.  	if(flags.verbose)
330.  	    You("are frightened to death, and unable to move.");
331.  	nomul(-3);
332.  	nomovemsg = "You regain your composure.";
333.  }
334.  
335.  /* "Quaffing is like drinking, except you spill more."  -- Terry Pratchett
336.   */
337.  int
338.  dodrink()
339.  {
340.  	register struct obj *otmp;
341.  	const char *potion_descr;
342.  	char quaffables[SIZE(beverages) + 2];
343.  	char *qp = quaffables;
344.  
345.  	if (Strangled) {
346.  		pline("If you can't breathe air, how can you drink liquid?");
347.  		return 0;
348.  	}
349.  
350.  	*qp++ = ALLOW_FLOOROBJ;
351.  	if (!u.uswallow && (IS_FOUNTAIN(levl[u.ux][u.uy].typ) ||
352.  #ifdef SINKS
353.  			    IS_SINK(levl[u.ux][u.uy].typ) ||
354.  			    IS_TOILET(levl[u.ux][u.uy].typ) ||
355.  #endif
356.  			    Underwater || IS_POOL(levl[u.ux][u.uy].typ)))
357.  	    *qp++ = ALLOW_THISPLACE;
358.  	Strcpy(qp, beverages);
359.  
360.  	otmp = getobj(quaffables, "drink");
361.  	if (otmp == &thisplace) {
362.  	    if (IS_FOUNTAIN(levl[u.ux][u.uy].typ)) {
363.  		drinkfountain();
364.  		return 1;
365.  	    }
366.  #ifdef SINKS
367.  	    else if (IS_SINK(levl[u.ux][u.uy].typ)) {
368.  		drinksink();
369.  		return 1;
370.  	    }
371.  	    else if (IS_TOILET(levl[u.ux][u.uy].typ)) {
372.  		drinktoilet();
373.  		return 1;
374.  	    }
375.  #endif
376.  	    pline("Do you know what lives in this water!");
377.  	    return 1;
378.  	}
379.  	if(!otmp) return(0);
380.  	otmp->in_use = TRUE;		/* you've opened the stopper */
381.  
382.  #define POTION_OCCUPANT_CHANCE(n) (13 + 2*(n))	/* also in muse.c */
383.  
384.  	potion_descr = OBJ_DESCR(objects[otmp->otyp]);
385.  	if (potion_descr) {
386.  	    if (!strcmp(potion_descr, "milky") &&
387.  		    flags.ghost_count < MAXMONNO &&
388.  		    !rn2(POTION_OCCUPANT_CHANCE(flags.ghost_count))) {
389.  		ghost_from_bottle();
390.  		if (carried(otmp)) useup(otmp);
391.  		else useupf(otmp, 1L);
392.  		return(1);
393.  	    } else if (!strcmp(potion_descr, "smoky") &&
394.  		    (flags.djinni_count < MAXMONNO) &&
395.  		    !rn2(POTION_OCCUPANT_CHANCE(flags.djinni_count))) {
396.  		djinni_from_bottle(otmp);
397.  		if (carried(otmp)) useup(otmp);
398.  		else useupf(otmp, 1L);
399.  		return(1);
400.  	    }
401.  	}
402.  	return dopotion(otmp);
403.  }
404.  
405.  int
406.  dopotion(otmp)
407.  register struct obj *otmp;
408.  {
409.  	int retval;
410.  
411.  	otmp->in_use = TRUE;
412.  	nothing = unkn = 0;
413.  
414.  
415.  	if((retval = peffects(otmp)) >= 0) return(retval);
416.  
417.  	if(nothing) {
418.  	    unkn++;
419.  	    You("have a %s feeling for a moment, then it passes.",
420.  		  Hallucination ? "normal" : "peculiar");
421.  	}
422.  	if(otmp->dknown && !objects[otmp->otyp].oc_name_known) {
423.  		if(!unkn) {
424.  			makeknown(otmp->otyp);
425.  			more_experienced(0,10);
426.  		} else if(!objects[otmp->otyp].oc_uname)
427.  			docall(otmp);
428.  	}
429.  	if (carried(otmp)) useup(otmp);
430.  	else if (mcarried(otmp)) m_useup(otmp->ocarry, otmp);
431.  	else if (otmp->where == OBJ_FLOOR) useupf(otmp, 1L);
432.  	else dealloc_obj(otmp);		/* Dummy potion */
433.  	return(1);
434.  }
435.  
436.  /* return -1 if potion is used up,  0 if error,  1 not used */
437.  int
438.  peffects(otmp)
439.  	register struct obj	*otmp;
440.  {
441.  	register int i, ii, lim;
442.  
443.  
444.  	/* KMH, balance patch -- this is too cruel for novices */
445.  #if 0
446.  	/* sometimes your constitution can be a little _too_ high! */
447.  	if ((Role_if(PM_BARBARIAN) || ACURR(A_CON) > 15) && !rn2(5)) {
448.  		pline("Strange ...");
449.  		nothing++;
450.  		return(-1);
451.  	}
452.  #endif
453.  
454.  	switch(otmp->otyp){
455.  	case POT_RESTORE_ABILITY:
456.  	case SPE_RESTORE_ABILITY:
457.  		unkn++;
458.  		if(otmp->cursed) {
459.  		    pline("Ulch!  This makes you feel mediocre!");
460.  		    break;
461.  		} else {
462.  		    pline("Wow!  This makes you feel %s!",
463.  			  (otmp->blessed) ?
464.  				(unfixable_trouble_count(FALSE) ? "better" : "great")
465.  			  : "good");
466.  		    i = rn2(A_MAX);		/* start at a random point */
467.  		    for (ii = 0; ii < A_MAX; ii++) {
468.  			lim = AMAX(i);
469.  			if (i == A_STR && u.uhs >= 3) --lim;	/* WEAK */
470.  			if (ABASE(i) < lim) {
471.  			    ABASE(i) = lim;
472.  			    flags.botl = 1;
473.  			    /* only first found if not blessed */
474.  			    if (!otmp->blessed) break;
475.  			}
476.  			if(++i >= A_MAX) i = 0;
477.  		    }
478.  		}
479.  		break;
480.  	case POT_HALLUCINATION:
481.  		if (Hallucination || Halluc_resistance) nothing++;
482.  		(void) make_hallucinated(itimeout_incr(HHallucination,
483.  					   rn1(200, 600 - 300 * bcsign(otmp))),
484.  				  TRUE, 0L);
485.  		break;
486.  	case POT_AMNESIA:
487.  		pline(Hallucination? "This tastes like champagne!" :
488.  			"This liquid bubbles and fizzes as you drink it.");
489.  		forget((!otmp->blessed? ALL_SPELLS : 0) | ALL_MAP);
490.  		if (Hallucination)
491.  		    pline("Hakuna matata!");
492.  		else
493.  		    You_feel("your memories dissolve.");
494.  
495.  		/* Blessed amnesia makes you forget lycanthropy, sickness */
496.  		if (otmp->blessed) {
497.  		    if (u.ulycn >= LOW_PM && !Race_if(PM_HUMAN_WEREWOLF)) {
498.  			You("forget your affinity to %s!",
499.  					makeplural(mons[u.ulycn].mname));
500.  			if (youmonst.data == &mons[u.ulycn])
501.  			    you_unwere(FALSE);
502.  			u.ulycn = NON_PM;	/* cure lycanthropy */
503.  		    }
504.  		    make_sick(0L, (char *) 0, TRUE, SICK_ALL);
505.  
506.  		    /* You feel refreshed */
507.  		    u.uhunger += 50 + rnd(50);
508.  		    newuhs(FALSE);
509.  		} else
510.  		    exercise(A_WIS, FALSE);
511.  		break;
512.  	case POT_WATER:
513.  		if(!otmp->blessed && !otmp->cursed) {
514.  		    pline("This tastes like water.");
515.  		    u.uhunger += rnd(10);
516.  		    newuhs(FALSE);
517.  		    break;
518.  		}
519.  		unkn++;
520.  		if(is_undead(youmonst.data) || is_demon(youmonst.data) ||
521.  				u.ualign.type == A_CHAOTIC) {
522.  		    if(otmp->blessed) {
523.  			pline("This burns like acid!");
524.  			exercise(A_CON, FALSE);
525.  			if (u.ulycn >= LOW_PM && !Race_if(PM_HUMAN_WEREWOLF)) {
526.  			    Your("affinity to %s disappears!",
527.  				 makeplural(mons[u.ulycn].mname));
528.  			    if (youmonst.data == &mons[u.ulycn])
529.  				you_unwere(FALSE);
530.  			    u.ulycn = NON_PM;	/* cure lycanthropy */
531.  			}
532.  			losehp(d(6,6), "potion of holy water", KILLED_BY_AN);
533.  		    } else if(otmp->cursed) {
534.  			You_feel("quite proud of yourself.");
535.  			healup(d(6,6),0,0,0);
536.  			if (u.ulycn >= LOW_PM && !Upolyd) you_were();
537.  			exercise(A_CON, TRUE);
538.  		    }
539.  		} else {
540.  		    if(otmp->blessed) {
541.  			You_feel("full of awe.");
542.  			if(u.ualign.type == A_LAWFUL) healup(d(6,6),0,0,0);                        
543.  			make_sick(0L, (char *) 0, TRUE, SICK_ALL);
544.  			exercise(A_WIS, TRUE);
545.  			exercise(A_CON, TRUE);
546.  			if (u.ulycn >= LOW_PM && !Race_if(PM_HUMAN_WEREWOLF)) {
547.  			    you_unwere(TRUE);	/* "Purified" */
548.  			}
549.  			/* make_confused(0L,TRUE); */
550.  		    } else {
551.  			if(u.ualign.type == A_LAWFUL) {
552.  			    pline("This burns like acid!");
553.  			    losehp(d(6,6), "potion of unholy water",
554.  				KILLED_BY_AN);
555.  			} else
556.  			    You_feel("full of dread.");
557.  			if (u.ulycn >= LOW_PM && !Upolyd) you_were();
558.  			exercise(A_CON, FALSE);
559.  		    }
560.  		}
561.  		break;
562.  	case POT_BOOZE:
563.  		unkn++;
564.  		pline("Ooph!  This tastes like %s%s!",
565.  		      otmp->odiluted ? "watered down " : "",
566.  		      Hallucination ? "dandelion wine" : "liquid fire");
567.  		if (!otmp->blessed)
568.  		    make_confused(itimeout_incr(HConfusion, d(3,8)), FALSE);
569.  		/* the whiskey makes us feel better */
570.  		if (!otmp->odiluted) healup(1, 0, FALSE, FALSE);
571.  		u.uhunger += 10 * (2 + bcsign(otmp));
572.  		newuhs(FALSE);
573.  		exercise(A_WIS, FALSE);
574.  		if(otmp->cursed) {
575.  			You("pass out.");
576.  			multi = -rnd(15);
577.  			nomovemsg = "You awake with a headache.";
578.  		}
579.  		break;
580.  	case POT_ENLIGHTENMENT:
581.  		if(otmp->cursed) {
582.  			unkn++;
583.  			You("have an uneasy feeling...");
584.  			exercise(A_WIS, FALSE);
585.  		} else {
586.  			if (otmp->blessed) {
587.  				(void) adjattrib(A_INT, 1, FALSE);
588.  				(void) adjattrib(A_WIS, 1, FALSE);
589.  			}
590.  			You_feel("self-knowledgeable...");
591.  			display_nhwindow(WIN_MESSAGE, FALSE);
592.  			enlightenment(0);
593.  			pline_The("feeling subsides.");
594.  			exercise(A_WIS, TRUE);
595.  		}
596.  		break;
597.  	case SPE_INVISIBILITY:
598.  		/* spell cannot penetrate mummy wrapping */
599.  		if (BInvis && uarmc->otyp == MUMMY_WRAPPING) {
600.  			You_feel("rather itchy under your %s.", xname(uarmc));
601.  			break;
602.  		}
603.  		/* FALLTHRU */
604.  	case POT_INVISIBILITY:
605.  		if (Invis || Blind || BInvis) {
606.  		    nothing++;
607.  		} else {
608.  		    self_invis_message();
609.  		}
610.  		if (otmp->blessed) HInvis |= FROMOUTSIDE;
611.  		else incr_itimeout(&HInvis, rn1(15,31));
612.  		newsym(u.ux,u.uy);	/* update position */
613.  		if(otmp->cursed) {
614.  		    pline("For some reason, you feel your presence is known.");
615.  		    aggravate();
616.  		}
617.  		break;
618.  	case POT_SEE_INVISIBLE:
619.  		/* tastes like fruit juice in Rogue */
620.  	case POT_FRUIT_JUICE:
621.  	    {
622.  		int msg = Invisible && !Blind;
623.  
624.  		unkn++;
625.  		if (otmp->cursed)
626.  		    pline("Yecch!  This tastes %s.",
627.  			  Hallucination ? "overripe" : "rotten");
628.  		else
629.  		    pline(Hallucination ?
630.  		      "This tastes like 10%% real %s%s all-natural beverage." :
631.  				"This tastes like %s%s.",
632.  			  otmp->odiluted ? "reconstituted " : "",
633.  			  fruitname(TRUE));
634.  		if (otmp->otyp == POT_FRUIT_JUICE) {
635.  		    u.uhunger += (otmp->odiluted ? 5 : 10) * (2 + bcsign(otmp));
636.  		    newuhs(FALSE);
637.  		    break;
638.  		}
639.  		if (!otmp->cursed) {
640.  			/* Tell them they can see again immediately, which
641.  			 * will help them identify the potion...
642.  			 */
643.  			make_blinded(0L,TRUE);
644.  		}
645.  		if (otmp->blessed)
646.  			HSee_invisible |= FROMOUTSIDE;
647.  		else
648.  			incr_itimeout(&HSee_invisible, rn1(100,750));
649.  		set_mimic_blocking(); /* do special mimic handling */
650.  		see_monsters();	/* see invisible monsters */
651.  		newsym(u.ux,u.uy); /* see yourself! */
652.  		if (msg && !Blind) { /* Blind possible if polymorphed */
653.  		    You("can see through yourself, but you are visible!");
654.  		    unkn--;
655.  		}
656.  		break;
657.  	    }
658.  	case POT_PARALYSIS:
659.  		if (Free_action)
660.  		    You("stiffen momentarily.");
661.  		else {
662.  		    if (Levitation || Is_airlevel(&u.uz)||Is_waterlevel(&u.uz))
663.  			You("are motionlessly suspended.");
664.  #ifdef STEED
665.  		    else if (u.usteed)
666.  			You("are frozen in place!");
667.  #endif
668.  		    else
669.  			Your("%s are frozen to the %s!",
670.  			     makeplural(body_part(FOOT)), surface(u.ux, u.uy));
671.  		    nomul(-(rn1(10, 25 - 12*bcsign(otmp))));
672.  		    nomovemsg = You_can_move_again;
673.  		    exercise(A_DEX, FALSE);
674.  		}
675.  		break;
676.  	case POT_SLEEPING:
677.  		if(Sleep_resistance || Free_action)
678.  		    You("yawn.");
679.  		else {
680.  		    You("suddenly fall asleep!");
681.  		    fall_asleep(-rn1(10, 25 - 12*bcsign(otmp)), TRUE);
682.  		}
683.  		break;
684.  	case POT_MONSTER_DETECTION:
685.  	case SPE_DETECT_MONSTERS:
686.  		if (otmp->blessed) {
687.  		    int x, y;
688.  
689.  		    if (Detect_monsters) nothing++;
690.  		    unkn++;
691.  		    /* after a while, repeated uses become less effective */
692.  		    if (HDetect_monsters >= 300L)
693.  			i = 1;
694.  		    else
695.  			i = rn1(40,21);
696.  		    incr_itimeout(&HDetect_monsters, i);
697.  		    for (x = 1; x < COLNO; x++) {
698.  			for (y = 0; y < ROWNO; y++) {
699.  			    if (memory_is_invisible(x, y)) {
700.  				unmap_object(x, y);
701.  				newsym(x,y);
702.  			    }
703.  			    if (MON_AT(x,y)) unkn = 0;
704.  			}
705.  		    }
706.  		    see_monsters();
707.  		    if (unkn) You_feel("lonely.");
708.  		    break;
709.  		}
710.  		if (monster_detect(otmp, 0))
711.  			return(1);		/* nothing detected */
712.  		exercise(A_WIS, TRUE);
713.  		break;
714.  	case POT_OBJECT_DETECTION:
715.  	case SPE_DETECT_TREASURE:
716.  		if (object_detect(otmp, 0))
717.  			return(1);		/* nothing detected */
718.  		exercise(A_WIS, TRUE);
719.  		break;
720.  	case POT_SICKNESS:
721.  		pline("Yecch!  This stuff tastes like poison.");
722.  		if (otmp->blessed) {
723.  		    pline("(But in fact it was mildly stale %s.)",
724.  			  fruitname(TRUE));
725.  		    if (!Role_if(PM_HEALER)) {
726.  			/* NB: blessed otmp->fromsink is not possible */
727.  			losehp(1, "mildly contaminated potion", KILLED_BY_AN);
728.  		    }
729.  		} else {
730.  		    if(Poison_resistance)
731.  			pline(
732.  			  "(But in fact it was biologically contaminated %s.)",
733.  			      fruitname(TRUE));
734.  		    if (Role_if(PM_HEALER))
735.  			pline("Fortunately, you have been immunized.");
736.  		    else {
737.  			int typ = rn2(A_MAX);
738.  
739.  			if (!Fixed_abil) {
740.  			    poisontell(typ);
741.  			    (void) adjattrib(typ,
742.  			    		Poison_resistance ? -1 : -rn1(4,3),
743.  			    		TRUE);
744.  			}
745.  			if(!Poison_resistance) {
746.  			    if (otmp->fromsink)
747.  				losehp(rnd(10)+5*!!(otmp->cursed),
748.  				       "contaminated tap water", KILLED_BY);
749.  			    else
750.  				losehp(rnd(10)+5*!!(otmp->cursed),
751.  				       "contaminated potion", KILLED_BY_AN);
752.  			}
753.  			exercise(A_CON, FALSE);
754.  		    }
755.  		}
756.  		if(Hallucination) {
757.  			You("are shocked back to your senses!");
758.  			(void) make_hallucinated(0L,FALSE,0L);
759.  		}
760.  		break;
761.  	case POT_CONFUSION:
762.  		if(!Confusion) {
763.  		    if (Hallucination) {
764.  			pline("What a trippy feeling!");
765.  			unkn++;
766.  		    } else
767.  			pline("Huh, What?  Where am I?");
768.  		} else	nothing++;
769.  		make_confused(itimeout_incr(HConfusion,
770.  					    rn1(7, 16 - 8 * bcsign(otmp))),
771.  			      FALSE);
772.  		break;
773.  	case POT_CLAIRVOYANCE:
774.  		/* KMH -- handle cursed, blessed, blocked */
775.  		if (otmp->cursed)
776.  			nothing++;
777.  		else if (!BClairvoyant) {
778.  			if (Hallucination) pline("Dude! See-through walls!");
779.  			do_vicinity_map();
780.  		}
781.  		if (otmp->blessed)
782.  			incr_itimeout(&HClairvoyant, rn1(50, 100));
783.  		break;
784.  	case POT_ESP:
785.  	{
786.  		const char *mod;
787.  
788.  		/* KMH -- handle cursed, blessed */
789.  		if (otmp->cursed) {
790.  			if (HTelepat) mod = "less ";
791.  			else {
792.  			    unkn++;
793.  			    mod = NULL;
794.  			}
795.  			HTelepat = 0;
796.  		} else if (otmp->blessed) {
797.  			mod = "fully ";
798.  			incr_itimeout(&HTelepat, rn1(100, 200));
799.  			HTelepat |= FROMOUTSIDE;
800.  		} else {
801.  			mod = "more ";
802.  			incr_itimeout(&HTelepat, rn1(50, 100));
803.  		}
804.  		if (mod)
805.  			You_feel(Hallucination ?
806.  				"%sin touch with the cosmos." :
807.  				"%smentally acute.", mod);
808.  		see_monsters();
809.  		break;
810.  	}
811.  	/* KMH, balance patch -- removed
812.  	case POT_FIRE_RESISTANCE:
813.  	       if(!(HFire_resistance & FROMOUTSIDE)) {
814.  		if (Hallucination)
815.  		   pline("You feel, like, totally cool!");
816.  		   else You("feel cooler.");
817.  		   HFire_resistance += rn1(100,50);
818.  		   unkn++;
819.  		   HFire_resistance |= FROMOUTSIDE;
820.  		}
821.  		break;*/
822.  	case POT_INVULNERABILITY:
823.  		incr_itimeout(&Invulnerable, rn1(4, 8 + 4 * bcsign(otmp)));
824.  		You_feel(Hallucination ?
825.  				"like a super-duper hero!" : "invulnerable!");
826.  		break;
827.  	case POT_GAIN_ABILITY:
828.  		if(otmp->cursed) {
829.  		    pline("Ulch!  That potion tasted foul!");
830.  		    unkn++;
831.  		} else if (Fixed_abil) {
832.  		    nothing++;
833.  		} else {      /* If blessed, increase all; if not, try up to */
834.  		    int itmp; /* 6 times to find one which can be increased. */
835.  		    i = -1;		/* increment to 0 */
836.  		    for (ii = A_MAX; ii > 0; ii--) {
837.  			i = (otmp->blessed ? i + 1 : rn2(A_MAX));
838.  			/* only give "your X is already as high as it can get"
839.  			   message on last attempt (except blessed potions) */
840.  			itmp = (otmp->blessed || ii == 1) ? 0 : -1;
841.  			if (adjattrib(i, 1, itmp) && !otmp->blessed)
842.  			    break;
843.  		    }
844.  		}
845.  		break;
846.  	case POT_SPEED:
847.  		if(Wounded_legs && !otmp->cursed
848.  #ifdef STEED
849.  		   && !u.usteed	/* heal_legs() would heal steeds legs */
850.  #endif
851.  						) {
852.  			heal_legs();
853.  			unkn++;
854.  			break;
855.  		} /* and fall through */
856.  	case SPE_HASTE_SELF:
857.  		if (!Very_fast)
858.  			You("are suddenly moving %sfaster.",
859.  				Fast ? "" : "much ");
860.  		else {
861.  			Your("%s get new energy.",
862.  				makeplural(body_part(LEG)));
863.  			unkn++;
864.  		}
865.  		exercise(A_DEX, TRUE);
866.  		incr_itimeout(&HFast, rn1(10, 100 + 60 * bcsign(otmp)));
867.  		break;
868.  	case POT_BLINDNESS:
869.  		if(Blind) nothing++;
870.  		make_blinded(itimeout_incr(Blinded,
871.  					   rn1(200, 250 - 125 * bcsign(otmp))),
872.  			     (boolean)!Blind);
873.  		break;
874.  
875.  	case POT_GAIN_LEVEL:
876.  		if (otmp->cursed) {
877.  			unkn++;
878.  			/* they went up a level */
879.  			if((ledger_no(&u.uz) == 1 && u.uhave.amulet) ||
880.  				Can_rise_up(u.ux, u.uy, &u.uz)) {
881.  			    const char *riseup ="rise up, through the %s!";
882.  			    /* [ALI] Special handling for quaffing potions
883.  			     * off the floor (otmp won't be valid after
884.  			     * we change levels otherwise).
885.  			     */
886.  			    if (otmp->where == OBJ_FLOOR) {
887.  				if (otmp->quan > 1)
888.  					(void) splitobj(otmp, 1);
889.  				/* Make sure you're charged if in shop */
890.  				otmp->quan++;
891.  				useupf(otmp, 1);
892.  				obj_extract_self(otmp);
893.  			    }
894.  			    if(ledger_no(&u.uz) == 1) {
895.  			        You(riseup, ceiling(u.ux,u.uy));
896.  				goto_level(&earth_level, FALSE, FALSE, FALSE);
897.  			    } else {
898.  			        register int newlev = depth(&u.uz)-1;
899.  				d_level newlevel;
900.  
901.  				get_level(&newlevel, newlev);
902.  				if(on_level(&newlevel, &u.uz)) {
903.  				    pline("It tasted bad.");
904.  				    break;
905.  				} else You(riseup, ceiling(u.ux,u.uy));
906.  				goto_level(&newlevel, FALSE, FALSE, FALSE);
907.  			    }
908.  			}
909.  			else You("have an uneasy feeling.");
910.  			break;
911.  		}
912.  		pluslvl(FALSE);
913.  		if (otmp->blessed)
914.  			/* blessed potions place you at a random spot in the
915.  			 * middle of the new level instead of the low point
916.  			 */
917.  			u.uexp = rndexp(TRUE);
918.  		break;
919.  	case POT_HEALING:
920.  		You_feel("better.");
921.  		healup(d(5,6) + 5 * bcsign(otmp),
922.  		       !otmp->cursed ? 1 : 0, 1+1*!!otmp->blessed, !otmp->cursed);
923.  		exercise(A_CON, TRUE);
924.  		break;
925.  	case POT_EXTRA_HEALING:
926.  		You_feel("much better.");
927.  		healup(d(6,8) + 5 * bcsign(otmp),
928.  		       otmp->blessed ? 5 : !otmp->cursed ? 2 : 0,
929.  		       !otmp->cursed, TRUE);
930.  		(void) make_hallucinated(0L,TRUE,0L);
931.  		exercise(A_CON, TRUE);
932.  		exercise(A_STR, TRUE);
933.  		break;
934.  	case POT_FULL_HEALING:
935.  		You_feel("completely healed.");
936.  		healup(400, 4+4*bcsign(otmp), !otmp->cursed, TRUE);
937.  		/* Restore one lost level if blessed */
938.  		if (otmp->blessed && u.ulevel < u.ulevelmax) {
939.  		    /* when multiple levels have been lost, drinking
940.  		       multiple potions will only get half of them back */
941.  		    u.ulevelmax -= 1;
942.  		    pluslvl(FALSE);
943.  		}
944.  		(void) make_hallucinated(0L,TRUE,0L);
945.  		exercise(A_STR, TRUE);
946.  		exercise(A_CON, TRUE);
947.  		break;
948.  	case POT_LEVITATION:
949.  	case SPE_LEVITATION:
950.  		if (otmp->cursed) HLevitation &= ~I_SPECIAL;
951.  		if(!Levitation) {
952.  			/* kludge to ensure proper operation of float_up() */
953.  			HLevitation = 1;
954.  			float_up();
955.  			/* reverse kludge */
956.  			HLevitation = 0;
957.  			if (otmp->cursed && !Is_waterlevel(&u.uz)) {
958.  	if((u.ux != xupstair || u.uy != yupstair)
959.  	   && (u.ux != sstairs.sx || u.uy != sstairs.sy || !sstairs.up)
960.  	   && (!xupladder || u.ux != xupladder || u.uy != yupladder)
961.  	) {
962.  					You("hit your %s on the %s.",
963.  						body_part(HEAD),
964.  						ceiling(u.ux,u.uy));
965.  					losehp(uarmh ? 1 : rnd(10),
966.  						"colliding with the ceiling",
967.  						KILLED_BY);
968.  				} else (void) doup();
969.  			}
970.  		} else
971.  			nothing++;
972.  		if (otmp->blessed) {
973.  		    incr_itimeout(&HLevitation, rn1(50,250));
974.  		    HLevitation |= I_SPECIAL;
975.  		} else incr_itimeout(&HLevitation, rn1(140,10));
976.  		spoteffects(FALSE);	/* for sinks */
977.  		break;
978.  	case POT_GAIN_ENERGY:			/* M. Stephenson */
979.  		{       register int num , num2;
980.  			if(otmp->cursed)
981.  			    You_feel("lackluster.");
982.  			else
983.  			    pline("Magical energies course through your body.");
984.  			num = rnd(25) + 5 * otmp->blessed + 10;                        
985.  			num2 = rnd(2) + 2 * otmp->blessed + 1;
986.  			u.uenmax += (otmp->cursed) ? -num2 : num2;
987.  			u.uen += (otmp->cursed) ? -num : num;
988.  			if(u.uenmax <= 0) u.uenmax = 0;
989.  			if(u.uen <= 0) u.uen = 0;
990.  			if(u.uen > u.uenmax) {
991.  				u.uenmax += ((u.uen - u.uenmax) / 2);
992.  				u.uen = u.uenmax;
993.  			}
994.  			flags.botl = 1;
995.  			exercise(A_WIS, TRUE);
996.  		}
997.  		break;
998.  	case POT_OIL:				/* P. Winner */
999.  		{
1000. 			boolean good_for_you = FALSE;
1001. 
1002. 			if (otmp->lamplit) {
1003. 			    if (likes_fire(youmonst.data)) {
1004. 				pline("Ahh, a refreshing drink.");
1005. 				good_for_you = TRUE;
1006. 			    } else {
1007. 				You("burn your %s.", body_part(FACE));
1008. 				losehp(d(Fire_resistance ? 1 : 3, 4),
1009. 				       "burning potion of oil", KILLED_BY_AN);
1010. 			    }
1011. 			} else if(otmp->cursed)
1012. 			    pline("This tastes like castor oil.");
1013. 			else
1014. 			    pline("That was smooth!");
1015. 			exercise(A_WIS, good_for_you);
1016. 		}
1017. 		break;
1018. 	case POT_ACID:
1019. 		if (Acid_resistance)
1020. 			/* Not necessarily a creature who _likes_ acid */
1021. 			pline("This tastes %s.", Hallucination ? "tangy" : "sour");
1022. 		else {
1023. 			pline("This burns%s!", otmp->blessed ? " a little" :
1024. 					otmp->cursed ? " a lot" : " like acid");
1025. 			losehp(d(otmp->cursed ? 2 : 1, otmp->blessed ? 4 : 8),
1026. 					"potion of acid", KILLED_BY_AN);
1027. 			exercise(A_CON, FALSE);
1028. 		}
1029. 		if (Stoned) fix_petrification();
1030. 		unkn++; /* holy/unholy water can burn like acid too */
1031. 		break;
1032. 	case POT_POLYMORPH:
1033. 		You_feel("a little %s.", Hallucination ? "normal" : "strange");
1034. 		if (!Unchanging) polyself(FALSE);
1035. 		break;
1036. 	case POT_BLOOD:
1037. 	case POT_VAMPIRE_BLOOD:
1038. 		unkn++;
1039. 		u.uconduct.unvegan++;
1040. 		if (maybe_polyd(is_vampire(youmonst.data), Race_if(PM_VAMPIRE))) {
1041. 		    violated_vegetarian();
1042. 		    if (otmp->cursed)
1043. 			pline("Yecch!  This %s.", Hallucination ?
1044. 			"liquid could do with a good stir" : "blood has congealed");
1045. 		    else pline(Hallucination ?
1046. 		      "The %s liquid stirs memories of home." :
1047. 		      "The %s blood tastes delicious.",
1048. 			  otmp->odiluted ? "watery" : "thick");
1049. 		    if (!otmp->cursed)
1050. 			lesshungry((otmp->odiluted ? 1 : 2) *
1051. 			  (otmp->otyp == POT_VAMPIRE_BLOOD ? 400 :
1052. 			  otmp->blessed ? 15 : 10));
1053. 		    if (otmp->otyp == POT_VAMPIRE_BLOOD && otmp->blessed) {
1054. 			int num = newhp();
1055. 			if (Upolyd) {
1056. 			    u.mhmax += num;
1057. 			    u.mh += num;
1058. 			} else {
1059. 			    u.uhpmax += num;
1060. 			    u.uhp += num;
1061. 			}
1062. 		    }
1063. 		} else if (otmp->otyp == POT_VAMPIRE_BLOOD) {
1064. 		    /* [CWC] fix conducts for potions of (vampire) blood -
1065. 		       doesn't use violated_vegetarian() to prevent
1066. 		       duplicated "you feel guilty" messages */
1067. 		    u.uconduct.unvegetarian++;
1068. 		    if (u.ualign.type == A_LAWFUL || Role_if(PM_MONK)) {
1069. 			You_feel("%sguilty about drinking such a vile liquid.",
1070. 				Role_if(PM_MONK) ? "especially " : "");
1071. 			u.ugangr++;
1072. 			adjalign(-15);
1073. 		    } else if (u.ualign.type == A_NEUTRAL)
1074. 			adjalign(-3);
1075. 		    exercise(A_CON, FALSE);
1076. 		    if (!Unchanging && polymon(PM_VAMPIRE))
1077. 			u.mtimedone = 0;	/* "Permament" change */
1078. 		} else {
1079. 		    violated_vegetarian();
1080. 		    pline("Ugh.  That was vile.");
1081. 		    make_vomiting(Vomiting+d(10,8), TRUE);
1082. 		}
1083. 		break;
1084. 	default:
1085. 		impossible("What a funny potion! (%u)", otmp->otyp);
1086. 		return(0);
1087. 	}
1088. 	return(-1);
1089. }
1090. 
1091. void
1092. healup(nhp, nxtra, curesick, cureblind)
1093. 	int nhp, nxtra;
1094. 	register boolean curesick, cureblind;
1095. {
1096. 	if (nhp) {
1097. 		if (Upolyd) {
1098. 			u.mh += nhp;
1099. 			if(u.mh > u.mhmax) u.mh = (u.mhmax += nxtra);
1100. 		} else {
1101. 			u.uhp += nhp;
1102. 			if(u.uhp > u.uhpmax) u.uhp = (u.uhpmax += nxtra);
1103. 		}
1104. 	}
1105. 	if(cureblind)	make_blinded(0L,TRUE);
1106. 	if(curesick)	make_sick(0L, (char *) 0, TRUE, SICK_ALL);
1107. 	flags.botl = 1;
1108. 	return;
1109. }
1110. 
1111. void
1112. healup_mon(mtmp, nhp, nxtra, curesick, cureblind)
1113. 	struct monst *mtmp;
1114. 	int nhp, nxtra;
1115. 	register boolean curesick, cureblind;
1116. {
1117. 	if (nhp) {
1118. 		mtmp->mhp += nhp;
1119. 		if (mtmp->mhp > mtmp->mhpmax) mtmp->mhp = (mtmp->mhpmax += nxtra);
1120. 	}
1121. #if 0
1122. 	if(cureblind) ; /* NOT DONE YET */
1123. 	if(curesick)  ; /* NOT DONE YET */
1124. #endif 
1125. 	return;
1126. }
1127. 
1128. void
1129. strange_feeling(obj,txt)
1130. register struct obj *obj;
1131. register const char *txt;
1132. {
1133. 	if (flags.beginner || !txt)
1134. 		You("have a %s feeling for a moment, then it passes.",
1135. 		Hallucination ? "normal" : "strange");
1136. 	else
1137. 		pline(txt);
1138. 
1139. 	if(!obj)	/* e.g., crystal ball finds no traps */
1140. 		return;
1141. 
1142. 	if(obj->dknown && !objects[obj->otyp].oc_name_known &&
1143. 						!objects[obj->otyp].oc_uname)
1144. 		docall(obj);
1145. 	if (carried(obj)) useup(obj);
1146. 	else useupf(obj, 1L);
1147. }
1148. 
1149. const char *bottlenames[] = {
1150. 	"bottle", "phial", "flagon", "carafe", "flask", "jar", "vial"
1151. };
1152. 
1153. const char *
1154. bottlename()
1155. {
1156. 	return bottlenames[rn2(SIZE(bottlenames))];
1157. }
1158. 
1159. /* WAC -- monsters can throw potions around too! */
1160. void
1161. potionhit(mon, obj, your_fault)
1162. register struct monst *mon; /* Monster that got hit */
1163. register struct obj *obj;
1164. boolean your_fault;
1165. {
1166. 	register const char *botlnam = bottlename();
1167. 	boolean isyou = (mon == &youmonst);
1168. 	int distance;
1169. 
1170. 	if(isyou) {
1171. 		distance = 0;
1172. 		pline_The("%s crashes on your %s and breaks into shards.",
1173. 			botlnam, body_part(HEAD));
1174. 		losehp(rnd(2), "thrown potion", KILLED_BY_AN);
1175. 	} else {
1176. 		distance = distu(mon->mx,mon->my);
1177. 		if (!cansee(mon->mx,mon->my)) pline("Crash!");
1178. 		else {
1179. 		    char *mnam = mon_nam(mon);
1180. 		    char buf[BUFSZ];
1181. 
1182. 		    if(has_head(mon->data)) {
1183. 			Sprintf(buf, "%s %s",
1184. 				s_suffix(mnam),
1185. 				(notonhead ? "body" : "head"));
1186. 		    } else {
1187. 			Strcpy(buf, mnam);
1188. 		    }
1189. 		    pline_The("%s crashes on %s and breaks into shards.",
1190. 			   botlnam, buf);
1191. 		}
1192. 		if(rn2(5) && mon->mhp > 1)
1193. 			mon->mhp--;
1194. 	}
1195. 
1196. 	/* oil doesn't instantly evaporate */
1197. 	if (obj->otyp != POT_OIL && cansee(mon->mx,mon->my))
1198. 		pline("%s.", Tobjnam(obj, "evaporate"));
1199. 
1200.     if (isyou) {
1201. 	switch (obj->otyp) {
1202. 	case POT_OIL:
1203. 		if (obj->lamplit)
1204. 		    splatter_burning_oil(u.ux, u.uy);
1205. 		break;
1206. 	case POT_POLYMORPH:
1207. 		You_feel("a little %s.", Hallucination ? "normal" : "strange");
1208. 		if (!Unchanging && !Antimagic) polyself(FALSE);
1209. 		break;
1210. 	case POT_ACID:
1211. 		if (!Acid_resistance) {
1212. 		    pline("This burns%s!", obj->blessed ? " a little" :
1213. 				    obj->cursed ? " a lot" : "");
1214. 		    losehp(d(obj->cursed ? 2 : 1, obj->blessed ? 4 : 8),
1215. 				    "potion of acid", KILLED_BY_AN);
1216. 		}
1217. 		break;
1218. 	case POT_AMNESIA:
1219. 		/* Uh-oh! */
1220. 		if (uarmh && is_helmet(uarmh) && 
1221. 			rn2(10 - (uarmh->cursed? 8 : 0)))
1222. 		    get_wet(uarmh, TRUE);
1223. 		break;
1224. 	}
1225.     } else {
1226. 	boolean angermon = TRUE;
1227. 
1228. 	if (!your_fault) angermon = FALSE;
1229. 	switch (obj->otyp) {
1230. 	case POT_HEALING:
1231.  do_healing:
1232. 		if (mon->data == &mons[PM_PESTILENCE]) goto do_illness;
1233. 		angermon = FALSE;
1234. 		if (canseemon(mon))
1235. 			pline("%s looks better.", Monnam(mon));
1236. 		healup_mon(mon, d(5,6) + 5 * bcsign(obj),
1237. 			!obj->cursed ? 1 : 0, 1+1*!!obj->blessed, !obj->cursed);
1238. 		break;
1239. 	case POT_EXTRA_HEALING:
1240. 		if (mon->data == &mons[PM_PESTILENCE]) goto do_illness;
1241. 		angermon = FALSE;
1242. 		if (canseemon(mon))
1243. 			pline("%s looks much better.", Monnam(mon));
1244. 		healup_mon(mon, d(6,8) + 5 * bcsign(obj),
1245. 			obj->blessed ? 5 : !obj->cursed ? 2 : 0,
1246. 			!obj->cursed, TRUE);
1247. 		break;
1248. 	case POT_FULL_HEALING:
1249. 		if (mon->data == &mons[PM_PESTILENCE]) goto do_illness;
1250. 		/*FALLTHRU*/
1251. 	case POT_RESTORE_ABILITY:
1252. 	case POT_GAIN_ABILITY:
1253. 		angermon = FALSE;
1254. 		    if (canseemon(mon))
1255. 			pline("%s looks sound and hale again.", Monnam(mon));
1256. 		healup_mon(mon, 400, 5+5*!!(obj->blessed), !(obj->cursed), 1);
1257. 		break;
1258. 	case POT_SICKNESS:
1259. 		if (mon->data == &mons[PM_PESTILENCE]) goto do_healing;
1260. 		if (dmgtype(mon->data, AD_DISE) ||
1261. 			   dmgtype(mon->data, AD_PEST) || /* won't happen, see prior goto */
1262. 			   resists_poison(mon)) {
1263. 		    if (canseemon(mon))
1264. 			pline("%s looks unharmed.", Monnam(mon));
1265. 		    break;
1266. 		}
1267.  do_illness:
1268. 		if((mon->mhpmax > 3) && !resist(mon, POTION_CLASS, 0, NOTELL))
1269. 			mon->mhpmax /= 2;
1270. 		if((mon->mhp > 2) && !resist(mon, POTION_CLASS, 0, NOTELL))
1271. 			mon->mhp /= 2;
1272. 		if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax;
1273. 		if (canseemon(mon))
1274. 		    pline("%s looks rather ill.", Monnam(mon));
1275. 		break;
1276. 	case POT_CONFUSION:
1277. 	case POT_BOOZE:
1278. 		if(!resist(mon, POTION_CLASS, 0, NOTELL))  mon->mconf = TRUE;
1279. 		break;
1280. #if 0 /* NH 3.3.0 version */
1281. 	case POT_POLYMORPH:
1282. 		(void) bhitm(mon, obj);
1283. 		break;
1284. #endif
1285. 	case POT_POLYMORPH:
1286. 	    /* [Tom] polymorph potion thrown 
1287. 	     * [max] added poor victim a chance to resist 
1288. 	     * magic resistance protects from polymorph traps, so make
1289. 	     * it guard against involuntary polymorph attacks too... 
1290. 	     */
1291. 	    if (resists_magm(mon)) {
1292.                 shieldeff(mon->mx, mon->my);
1293. 	    } else if (!resist (mon, POTION_CLASS, 0, NOTELL)) {
1294.                 mon_poly(mon, your_fault, "%s changes!");
1295.                 if (!Hallucination && canspotmon (mon))
1296.                                 makeknown (POT_POLYMORPH);
1297. 	    }
1298.   		break;
1299. 	case POT_INVISIBILITY:
1300. 		angermon = FALSE;
1301. 		mon_set_minvis(mon);
1302. 		break;
1303. 	case POT_SLEEPING:
1304. 		/* wakeup() doesn't rouse victims of temporary sleep */
1305. 		if (sleep_monst(mon, rnd(12), POTION_CLASS)) {
1306. 		    pline("%s falls asleep.", Monnam(mon));
1307. 		    slept_monst(mon);
1308. 		}
1309. 		break;
1310. 	case POT_PARALYSIS:
1311. 		if (mon->mcanmove) {
1312. 			mon->mcanmove = 0;
1313. 			/* really should be rnd(5) for consistency with players
1314. 			 * breathing potions, but...
1315. 			 */
1316. 			mon->mfrozen = rnd(25);
1317. 		}
1318. 		break;
1319. 	case POT_SPEED:
1320. 		angermon = FALSE;
1321. 		mon_adjust_speed(mon, 1, obj);
1322. 		break;
1323. 	case POT_BLINDNESS:
1324. 		if(haseyes(mon->data)) {
1325. 		    register int btmp = 64 + rn2(32) +
1326. 			rn2(32) * !resist(mon, POTION_CLASS, 0, NOTELL);
1327. 		    btmp += mon->mblinded;
1328. 		    mon->mblinded = min(btmp,127);
1329. 		    mon->mcansee = 0;
1330. 		}
1331. 		break;
1332. 	case POT_WATER:
1333. 		if (is_undead(mon->data) || is_demon(mon->data) ||
1334. 			is_were(mon->data)) {
1335. 		    if (obj->blessed) {
1336. 			pline("%s %s in pain!", Monnam(mon),
1337. 			      is_silent(mon->data) ? "writhes" : "shrieks");
1338. 			mon->mhp -= d(2,6);
1339. 			if (mon->mhp < 1) {
1340. 			    if (your_fault)
1341. 				killed(mon);
1342. 			    else
1343. 				monkilled(mon, "", AD_ACID);
1344. 			}
1345. 			else if (is_were(mon->data) && !is_human(mon->data))
1346. 			    new_were(mon);	/* revert to human */
1347. 		    } else if (obj->cursed) {
1348. 			angermon = FALSE;
1349. 			if (canseemon(mon))
1350. 			    pline("%s looks healthier.", Monnam(mon));
1351. 			mon->mhp += d(2,6);
1352. 			if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax;
1353. 			if (is_were(mon->data) && is_human(mon->data) &&
1354. 				!Protection_from_shape_changers)
1355. 			    new_were(mon);	/* transform into beast */
1356. 		    }
1357. 		} else if(mon->data == &mons[PM_GREMLIN]) {
1358. 		    angermon = FALSE;
1359. 		    (void)split_mon(mon, (struct monst *)0);
1360. 		} else if(mon->data == &mons[PM_FLAMING_SPHERE] ||
1361. 			mon->data == &mons[PM_IRON_GOLEM]) {
1362. 		    if (canseemon(mon))
1363. 			pline("%s %s.", Monnam(mon),
1364. 				mon->data == &mons[PM_IRON_GOLEM] ?
1365. 				"rusts" : "flickers");
1366. 		    mon->mhp -= d(1,6);
1367. 		    if (mon->mhp < 1) {
1368. 			if (your_fault)
1369. 			    killed(mon);
1370. 			else
1371. 			    monkilled(mon, "", AD_ACID);
1372. 		    }
1373. 		}
1374. 		break;
1375. 	case POT_AMNESIA:
1376. 		switch (monsndx(mon->data)) {
1377. 		case PM_GREMLIN:
1378. 		    /* Gremlins multiply... */
1379. 		    mon->mtame = FALSE;	
1380. 		    (void)split_mon(mon, (struct monst *)0);
1381. 		    break;
1382. 		case PM_FLAMING_SPHERE:
1383. 		case PM_IRON_GOLEM:
1384. 		    if (canseemon(mon)) pline("%s %s.", Monnam(mon),
1385. 			    monsndx(mon->data) == PM_IRON_GOLEM ?
1386. 			    "rusts" : "flickers");
1387. 		    mon->mhp -= d(1,6);
1388. 		    if (mon->mhp < 1)
1389. 			if (your_fault)
1390. 			    killed(mon);
1391. 			else
1392. 			    monkilled(mon, "", AD_ACID);
1393. 		    else
1394. 			mon->mtame = FALSE;	
1395. 		    break;
1396. 		case PM_WIZARD_OF_YENDOR:
1397. 		    if (your_fault) {
1398. 			if (canseemon(mon)) 
1399. 			    pline("%s laughs at you!", Monnam(mon));
1400. 			forget(1);
1401. 		    }
1402. 		    break;
1403. 		case PM_MEDUSA:
1404. 		    if (canseemon(mon))
1405. 			pline("%s looks like %s's having a bad hair day!", 
1406. 					Monnam(mon), mhe(mon));
1407. 		    break;
1408. 		case PM_CROESUS:
1409. 		    if (canseemon(mon))
1410. 		        pline("%s says: 'My gold! I must count my gold!'", 
1411. 					Monnam(mon));
1412. 		    break;
1413. 		case PM_DEATH:
1414.  		    if (canseemon(mon))
1415. 		        pline("%s pauses, then looks at you thoughtfully!", 
1416. 					Monnam(mon));
1417. 		    break;
1418. 		case PM_FAMINE:
1419. 		    if (canseemon(mon))
1420. 		        pline("%s looks unusually hungry!", Monnam(mon));
1421. 		    break;
1422. 		case PM_PESTILENCE:
1423. 		    if (canseemon(mon))
1424. 		        pline("%s looks unusually well!", Monnam(mon));
1425. 		    break;
1426. 		default:
1427. 		    if (mon->data->msound == MS_NEMESIS && canseemon(mon)
1428. 				    && your_fault)
1429. 			pline("%s curses your ancestors!", Monnam(mon));
1430. 		    else if (mon->isshk) {
1431. 			angermon = FALSE;
1432. 			if (canseemon(mon))
1433. 			    pline("%s looks at you curiously!", 
1434. 					    Monnam(mon));
1435. 			make_happy_shk(mon, FALSE);
1436. 		    } else if (!is_covetous(mon->data) && !rn2(4) &&
1437. 				    !resist(mon, POTION_CLASS, 0, 0)) {
1438. 			angermon = FALSE;
1439. 			if (canseemon(mon)) {
1440. 			    if (mon->msleeping) {
1441. 				wakeup(mon);
1442. 				pline("%s wakes up looking bewildered!", 
1443. 						Monnam(mon));
1444. 			    } else
1445. 				pline("%s looks bewildered!", Monnam(mon));
1446. 			    mon->mpeaceful = TRUE;
1447. 			    mon->mtame = FALSE;	
1448. 			}
1449. 		    }
1450. 		    break;
1451. 		}
1452. 		break;
1453. 	case POT_OIL:
1454. 		if (obj->lamplit)
1455. 			splatter_burning_oil(mon->mx, mon->my);
1456. 		break;
1457. /*
1458. 	case POT_GAIN_LEVEL:
1459. 	case POT_LEVITATION:
1460. 	case POT_FRUIT_JUICE:
1461. 	case POT_MONSTER_DETECTION:
1462. 	case POT_OBJECT_DETECTION:
1463. 		break;
1464. */
1465. 	/* KMH, balance patch -- added */
1466. 	case POT_ACID:
1467. 		if (!resists_acid(mon) && !resist(mon, POTION_CLASS, 0, NOTELL)) {
1468. 		    pline("%s %s in pain!", Monnam(mon),
1469. 			  is_silent(mon->data) ? "writhes" : "shrieks");
1470. 		    mon->mhp -= d(obj->cursed ? 2 : 1, obj->blessed ? 4 : 8);
1471. 		    if (mon->mhp < 1) {
1472. 			if (your_fault)
1473. 			    killed(mon);
1474. 			else
1475. 			    monkilled(mon, "", AD_ACID);
1476. 		    }
1477. 		}
1478. 		break;
1479. 	}
1480. 	if (angermon)
1481. 	    wakeup(mon);
1482. 	else
1483. 	    mon->msleeping = 0;
1484.     }
1485. 
1486. 	/* Note: potionbreathe() does its own docall() */
1487. 	if ((distance==0 || ((distance < 3) && rn2(5))) &&
1488. 	    (!breathless(youmonst.data) || haseyes(youmonst.data)))
1489. 		potionbreathe(obj);
1490. 	else if (obj->dknown && !objects[obj->otyp].oc_name_known &&
1491. 		   !objects[obj->otyp].oc_uname && cansee(mon->mx,mon->my))
1492. 		docall(obj);
1493. 	if(*u.ushops && obj->unpaid) {
1494. 	        register struct monst *shkp =
1495. 			shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE));
1496. 
1497. 		if(!shkp)
1498. 		    obj->unpaid = 0;
1499. 		else {
1500. 		    (void)stolen_value(obj, u.ux, u.uy,
1501. 				 (boolean)shkp->mpeaceful, FALSE, TRUE);
1502. 		    subfrombill(obj, shkp);
1503. 		}
1504. 	}
1505. 	obfree(obj, (struct obj *)0);
1506. }
1507. 
1508. /* vapors are inhaled or get in your eyes */
1509. void
1510. potionbreathe(obj)
1511. register struct obj *obj;
1512. {
1513. 	register int i, ii, isdone, kn = 0;
1514. 
1515. 	switch(obj->otyp) {
1516. 	case POT_RESTORE_ABILITY:
1517. 	case POT_GAIN_ABILITY:
1518. 		if(obj->cursed) {
1519. 		    if (!breathless(youmonst.data))
1520. 			pline("Ulch!  That potion smells terrible!");
1521. 		    else if (haseyes(youmonst.data)) {
1522. 			int numeyes = eyecount(youmonst.data);
1523. 			Your("%s sting%s!",
1524. 			     (numeyes == 1) ? body_part(EYE) : makeplural(body_part(EYE)),
1525. 			     (numeyes == 1) ? "s" : "");
1526. 		    }
1527. 		    break;
1528. 		} else {
1529. 		    i = rn2(A_MAX);		/* start at a random point */
1530. 		    for(isdone = ii = 0; !isdone && ii < A_MAX; ii++) {
1531. 			if(ABASE(i) < AMAX(i)) {
1532. 			    ABASE(i)++;
1533. 			    /* only first found if not blessed */
1534. 			    isdone = !(obj->blessed);
1535. 			    flags.botl = 1;
1536. 			}
1537. 			if(++i >= A_MAX) i = 0;
1538. 		    }
1539. 		}
1540. 		break;
1541. 	case POT_FULL_HEALING:
1542. 		if (Upolyd && u.mh < u.mhmax) u.mh++, flags.botl = 1;
1543. 		if (u.uhp < u.uhpmax) u.uhp++, flags.botl = 1;
1544. 		/*FALL THROUGH*/
1545. 	case POT_EXTRA_HEALING:
1546. 		if (Upolyd && u.mh < u.mhmax) u.mh++, flags.botl = 1;
1547. 		if (u.uhp < u.uhpmax) u.uhp++, flags.botl = 1;
1548. 		/*FALL THROUGH*/
1549. 	case POT_HEALING:
1550. 		if (Upolyd && u.mh < u.mhmax) u.mh++, flags.botl = 1;
1551. 		if (u.uhp < u.uhpmax) u.uhp++, flags.botl = 1;
1552. 		exercise(A_CON, TRUE);
1553. 		break;
1554. 	case POT_SICKNESS:
1555. 		if (!Role_if(PM_HEALER)) {
1556. 			if (Upolyd) {
1557. 			    if (u.mh <= 5) u.mh = 1; else u.mh -= 5;
1558. 			} else {
1559. 			    if (u.uhp <= 5) u.uhp = 1; else u.uhp -= 5;
1560. 			}
1561. 			flags.botl = 1;
1562. 			exercise(A_CON, FALSE);
1563. 		}
1564. 		break;
1565. 	case POT_HALLUCINATION:
1566. 		You("have a momentary vision.");
1567. 		break;
1568. 	case POT_CONFUSION:
1569. 	case POT_BOOZE:
1570. 		if(!Confusion)
1571. 			You_feel("somewhat dizzy.");
1572. 		make_confused(itimeout_incr(HConfusion, rnd(5)), FALSE);
1573. 		break;
1574. 	case POT_INVISIBILITY:
1575. 		if (!Blind && !Invis) {
1576. 		    kn++;
1577. 		    pline("For an instant you %s!",
1578. 			See_invisible ? "could see right through yourself"
1579. 			: "couldn't see yourself");
1580. 		}
1581. 		break;
1582. 	case POT_PARALYSIS:
1583. 		kn++;
1584. 		if (!Free_action) {
1585. 		    pline("%s seems to be holding you.", Something);
1586. 		    nomul(-rnd(5));
1587. 		    nomovemsg = You_can_move_again;
1588. 		    exercise(A_DEX, FALSE);
1589. 		} else You("stiffen momentarily.");
1590. 		break;
1591. 	case POT_SLEEPING:
1592. 		kn++;
1593. 		if (!Free_action && !Sleep_resistance) {
1594. 		    You_feel("rather tired.");
1595. 		    nomul(-rnd(5));
1596. 		    nomovemsg = You_can_move_again;
1597. 		    exercise(A_DEX, FALSE);
1598. 		} else You("yawn.");
1599. 		break;
1600. 	case POT_SPEED:
1601. 		if (!Fast) Your("knees seem more flexible now.");
1602. 		incr_itimeout(&HFast, rnd(5));
1603. 		exercise(A_DEX, TRUE);
1604. 		break;
1605. 	case POT_BLINDNESS:
1606. 		if (!Blind && !u.usleep) {
1607. 		    kn++;
1608. 		    pline("It suddenly gets dark.");
1609. 		}
1610. 		make_blinded(itimeout_incr(Blinded, rnd(5)), FALSE);
1611. 		if (!Blind && !u.usleep) Your(vision_clears);
1612. 		break;
1613. 	case POT_WATER:
1614. 		if(u.umonnum == PM_GREMLIN) {
1615. 		    (void)split_mon(&youmonst, (struct monst *)0);
1616. 		} else if (u.ulycn >= LOW_PM) {
1617. 		    /* vapor from [un]holy water will trigger
1618. 		       transformation but won't cure lycanthropy */
1619. 		    if (obj->blessed && youmonst.data == &mons[u.ulycn])
1620. 			you_unwere(FALSE);
1621. 		    else if (obj->cursed && !Upolyd)
1622. 			you_were();
1623. 		}
1624. 		break;
1625. 	case POT_AMNESIA:
1626. 		if(u.umonnum == PM_GREMLIN)
1627. 		    (void)split_mon(&youmonst, (struct monst *)0);
1628. 		else if(u.umonnum == PM_FLAMING_SPHERE) {
1629. 		    You("flicker!");
1630. 		    losehp(d(1,6),"potion of amnesia", KILLED_BY_AN);
1631. 		} else if(u.umonnum == PM_IRON_GOLEM) {
1632. 		    You("rust!");
1633. 		    losehp(d(1,6),"potion of amnesia", KILLED_BY_AN);
1634. 		}
1635. 		You_feel("dizzy!");
1636. 		forget(1 + rn2(5));
1637. 		break;
1638. 	case POT_ACID:
1639. 	case POT_POLYMORPH:
1640. 		exercise(A_CON, FALSE);
1641. 		break;
1642. 	case POT_BLOOD:
1643. 	case POT_VAMPIRE_BLOOD:
1644. 		if (maybe_polyd(is_vampire(youmonst.data), Race_if(PM_VAMPIRE))) {
1645. 		    exercise(A_WIS, FALSE);
1646. 		    You_feel("a %ssense of loss.",
1647. 		      obj->otyp == POT_VAMPIRE_BLOOD ? "terrible " : "");
1648. 		} else
1649. 		    exercise(A_CON, FALSE);
1650. 		break;
1651. /*
1652. 	case POT_GAIN_LEVEL:
1653. 	case POT_LEVITATION:
1654. 	case POT_FRUIT_JUICE:
1655. 	case POT_MONSTER_DETECTION:
1656. 	case POT_OBJECT_DETECTION:
1657. 	case POT_OIL:
1658. 		break;
1659. */
1660. 	}
1661. 	/* note: no obfree() */
1662. 	if (obj->dknown) {
1663. 	    if (kn)
1664. 		makeknown(obj->otyp);
1665. 	    else if (!objects[obj->otyp].oc_name_known &&
1666. 						!objects[obj->otyp].oc_uname)
1667. 		docall(obj);
1668. 	}
1669. }
1670. 
1671. STATIC_OVL short
1672. mixtype(o1, o2)
1673. register struct obj *o1, *o2;
1674. /* returns the potion type when o1 is dipped in o2 */
1675. {
1676. 	/* cut down on the number of cases below */
1677. 	if (o1->oclass == POTION_CLASS &&
1678. 	    (o2->otyp == POT_GAIN_LEVEL ||
1679. 	     o2->otyp == POT_GAIN_ENERGY ||
1680. 	     o2->otyp == POT_HEALING ||
1681. 	     o2->otyp == POT_EXTRA_HEALING ||
1682. 	     o2->otyp == POT_FULL_HEALING ||
1683. 	     o2->otyp == POT_ENLIGHTENMENT ||
1684. 	     o2->otyp == POT_FRUIT_JUICE)) {
1685. 		struct obj *swp;
1686. 
1687. 		swp = o1; o1 = o2; o2 = swp;
1688. 	}
1689. 
1690. 	switch (o1->otyp) {
1691. 		case POT_HEALING:
1692. 			switch (o2->otyp) {
1693. 			    case POT_SPEED:
1694. 			    case POT_GAIN_LEVEL:
1695. 			    case POT_GAIN_ENERGY:
1696. 				return POT_EXTRA_HEALING;
1697. 			}
1698. 			break;
1699. 		case POT_EXTRA_HEALING:
1700. 			switch (o2->otyp) {
1701. 			    case POT_GAIN_LEVEL:
1702. 			    case POT_GAIN_ENERGY:
1703. 				return POT_FULL_HEALING;
1704. 			}
1705. 			break;
1706. 		case POT_FULL_HEALING:
1707. 			switch (o2->otyp) {
1708. 			    case POT_GAIN_LEVEL:
1709. 			    case POT_GAIN_ENERGY:
1710. 				return POT_GAIN_ABILITY;
1711. 			}
1712. 			break;
1713. 		case UNICORN_HORN:
1714. 			switch (o2->otyp) {
1715. 			    case POT_SICKNESS:
1716. 				return POT_FRUIT_JUICE;
1717. 			    case POT_HALLUCINATION:
1718. 			    case POT_BLINDNESS:
1719. 			    case POT_CONFUSION:
1720. 			    case POT_BLOOD:
1721. 			    case POT_VAMPIRE_BLOOD:
1722. 				return POT_WATER;
1723. 			}
1724. 			break;
1725. 		case AMETHYST:		/* "a-methyst" == "not intoxicated" */
1726. 			if (o2->otyp == POT_BOOZE)
1727. 			    return POT_FRUIT_JUICE;
1728. 			break;
1729. 		case POT_GAIN_LEVEL:
1730. 		case POT_GAIN_ENERGY:
1731. 			switch (o2->otyp) {
1732. 			    case POT_CONFUSION:
1733. 				return (rn2(3) ? POT_BOOZE : POT_ENLIGHTENMENT);
1734. 			    case POT_HEALING:
1735. 				return POT_EXTRA_HEALING;
1736. 			    case POT_EXTRA_HEALING:
1737. 				return POT_FULL_HEALING;
1738. 			    case POT_FULL_HEALING:
1739. 				return POT_GAIN_ABILITY;
1740. 			    case POT_FRUIT_JUICE:
1741. 				return POT_SEE_INVISIBLE;
1742. 			    case POT_BOOZE:
1743. 				return POT_HALLUCINATION;
1744. 			}
1745. 			break;
1746. 		case POT_FRUIT_JUICE:
1747. 			switch (o2->otyp) {
1748. 			    case POT_SICKNESS:
1749. 				return POT_SICKNESS;
1750. 			    case POT_BLOOD:
1751. 				return POT_BLOOD;
1752. 			    case POT_VAMPIRE_BLOOD:
1753. 				return POT_VAMPIRE_BLOOD;
1754. 			    case POT_SPEED:
1755. 				return POT_BOOZE;
1756. 			    case POT_GAIN_LEVEL:
1757. 			    case POT_GAIN_ENERGY:
1758. 				return POT_SEE_INVISIBLE;
1759. 			}
1760. 			break;
1761. 		case POT_ENLIGHTENMENT:
1762. 			switch (o2->otyp) {
1763. 			    case POT_LEVITATION:
1764. 				if (rn2(3)) return POT_GAIN_LEVEL;
1765. 				break;
1766. 			    case POT_FRUIT_JUICE:
1767. 				return POT_BOOZE;
1768. 			    case POT_BOOZE:
1769. 				return POT_CONFUSION;
1770. 			}
1771. 			break;
1772. 	}
1773. 	/* MRKR: Extra alchemical effects. */
1774. 
1775. 	if (o2->otyp == POT_ACID && o1->oclass == GEM_CLASS) {
1776. 	  const char *potion_descr;
1777. 
1778. 	  /* Note: you can't create smoky, milky or clear potions */
1779. 
1780. 	  switch (o1->otyp) {
1781. 
1782. 	    /* white */
1783. 
1784. 	  case DILITHIUM_CRYSTAL:
1785. 	    /* explodes - special treatment in dodip */
1786. 	    /* here we just want to return something non-zero */
1787. 	    return POT_WATER;
1788. 	    break;
1789. 	  case DIAMOND:
1790. 	    /* won't dissolve */
1791. 	    potion_descr = NULL;
1792. 	    break;
1793. 	  case OPAL:
1794. 	    potion_descr = "cloudy";
1795. 	    break;
1796. 
1797. 	    /* red */
1798. 
1799. 	  case RUBY:
1800. 	    potion_descr = "ruby";
1801. 	    break;
1802. 	  case GARNET:
1803. 	    potion_descr = "pink";
1804. 	    break;
1805. 	  case JASPER:
1806. 	    potion_descr = "purple-red";
1807. 	    break;
1808. 
1809. 	    /* orange */
1810. 
1811. 	  case JACINTH:
1812. 	    potion_descr = "orange";
1813. 	    break;
1814. 	  case AGATE:
1815. 	    potion_descr = "swirly";
1816. 	    break;
1817. 
1818. 	    /* yellow */
1819. 
1820. 	  case CITRINE:
1821. 	    potion_descr = "yellow";
1822. 	    break;
1823. 	  case CHRYSOBERYL:
1824. 	    potion_descr = "golden";
1825. 	    break;
1826. 
1827. 	    /* yellowish brown */
1828. 
1829. 	  case AMBER:
1830. 	    potion_descr = "brown";
1831. 	    break;
1832. 	  case TOPAZ:
1833. 	    potion_descr = "murky";
1834. 	    break;
1835. 
1836. 	    /* green */
1837. 
1838. 	  case EMERALD:
1839. 	    potion_descr = "emerald";
1840. 	    break;
1841. 	  case TURQUOISE:
1842. 	    potion_descr = "sky blue";
1843. 	    break;
1844. 	  case AQUAMARINE:
1845. 	    potion_descr = "cyan";
1846. 	    break;
1847. 	  case JADE:
1848. 	    potion_descr = "dark green";
1849. 	    break;
1850. 
1851. 	    /* blue */
1852. 
1853. 	  case SAPPHIRE:
1854. 	    potion_descr = "brilliant blue";
1855. 	    break;
1856. 
1857. 	    /* violet */
1858. 
1859. 	  case AMETHYST:
1860. 	    potion_descr = "magenta";
1861. 	    break;
1862. 	  case FLUORITE:
1863. 	    potion_descr = "white";
1864. 	    break;
1865. 
1866. 	    /* black */
1867. 
1868. 	  case BLACK_OPAL:
1869. 	    potion_descr = "black";
1870. 	    break;
1871. 	  case JET:
1872. 	    potion_descr = "dark";
1873. 	    break;
1874. 	  case OBSIDIAN:
1875. 	    potion_descr = "effervescent";
1876. 	    break;
1877. 	  default: potion_descr = NULL;
1878. 	  }
1879. 
1880. 	  if (potion_descr) {
1881. 	    int typ;
1882. 
1883. 	    /* find a potion that matches the description */
1884. 
1885. 	    for (typ = bases[POTION_CLASS];
1886. 		 objects[typ].oc_class == POTION_CLASS;
1887. 		 typ++) {
1888. 
1889. 	      if (strcmp(potion_descr, OBJ_DESCR(objects[typ])) == 0) {
1890. 		return typ;
1891. 	      }
1892. 	    }
1893. 	  }
1894. 	}
1895. 
1896. 	return 0;
1897. }
1898. 
1899. /* Bills an object that's about to be downgraded, assuming that's not already
1900.  * been done */
1901. STATIC_OVL
1902. void
1903. pre_downgrade_obj(obj, used)
1904. register struct obj *obj;
1905. boolean *used;
1906. {
1907.     boolean dummy = FALSE;
1908. 
1909.     if (!used) used = &dummy;
1910.     if (!*used) Your("%s for a moment.", aobjnam(obj, "sparkle"));
1911.     if(obj->unpaid && costly_spot(u.ux, u.uy) && !*used) {
1912. 	You("damage it, you pay for it.");
1913. 	bill_dummy_object(obj);
1914.     }
1915.     *used = TRUE;
1916. }
1917. 
1918. /* Implements the downgrading effect of potions of amnesia and Lethe water */
1919. STATIC_OVL
1920. void
1921. downgrade_obj(obj, nomagic, used)
1922. register struct obj *obj;
1923. int nomagic;	/* The non-magical object to downgrade to */
1924. boolean *used;
1925. {
1926.     pre_downgrade_obj(obj, used);
1927.     obj->otyp = nomagic;
1928.     obj->spe = 0;
1929.     obj->owt = weight(obj);
1930.     flags.botl = TRUE;
1931. }
1932. 
1933. boolean
1934. get_wet(obj, amnesia)
1935. register struct obj *obj;
1936. boolean amnesia;
1937. /* returns TRUE if something happened (potion should be used up) */
1938. {
1939. 	char Your_buf[BUFSZ];
1940. 	boolean used = FALSE;
1941. 
1942. 	if (snuff_lit(obj)) return(TRUE);
1943. 
1944. 	if (obj->greased) {
1945. 		grease_protect(obj,(char *)0,&youmonst);
1946. 		return(FALSE);
1947. 	}
1948. 	(void) Shk_Your(Your_buf, obj);
1949. 	/* (Rusting shop goods ought to be charged for.) */
1950. 	switch (obj->oclass) {
1951. 	    case POTION_CLASS:
1952. 		if (obj->otyp == POT_WATER) {
1953. 		    if (amnesia) {
1954. 			Your("%s to sparkle.", aobjnam(obj,"start"));
1955. 			obj->odiluted 	= 0;
1956. 			obj->otyp 	= POT_AMNESIA;
1957. 			used 		= TRUE;
1958. 			break;
1959. 		    }
1960. 		    return FALSE;
1961. 		}
1962. 
1963. 		/* Diluting a !ofAmnesia just gives water... */
1964. 		if (obj->otyp == POT_AMNESIA) {
1965. 			Your("%s flat.", aobjnam(obj, "become"));
1966. 			obj->odiluted = 0;
1967. 			obj->otyp = POT_WATER;
1968. 			used = TRUE;
1969. 			break;
1970. 		}
1971. 
1972. 		/* KMH -- Water into acid causes an explosion */
1973. 		if (obj->otyp == POT_ACID) {
1974. 			pline("It boils vigorously!");
1975. 			You("are caught in the explosion!");
1976. 			losehp(Acid_resistance ? rnd(5) : rnd(10),
1977. 			       "elementary chemistry", KILLED_BY);
1978. 			if (amnesia) {
1979. 			    You_feel("a momentary lapse of reason!");
1980. 			    forget(2 + rn2(3));
1981. 			}
1982. 			makeknown(obj->otyp);
1983. 			used = TRUE;
1984. 			break;
1985. 		}
1986. 		if (amnesia)
1987. 		    pline("%s %s completely.", Your_buf, aobjnam(obj,"dilute"));
1988. 		else
1989. 		    pline("%s %s%s.", Your_buf, aobjnam(obj,"dilute"),
1990. 		      		obj->odiluted ? " further" : "");
1991. 		if(obj->unpaid && costly_spot(u.ux, u.uy)) {
1992. 		    You("dilute it, you pay for it.");
1993. 		    bill_dummy_object(obj);
1994. 		}
1995. 		if (obj->odiluted || amnesia) {
1996. 			obj->odiluted = 0;
1997. #ifdef UNIXPC
1998. 			obj->blessed = FALSE;
1999. 			obj->cursed = FALSE;
2000. #else
2001. 			obj->blessed = obj->cursed = FALSE;
2002. #endif
2003. 			obj->otyp = POT_WATER;
2004. 		} else obj->odiluted++;
2005. 		used = TRUE;
2006. 		break;
2007. 	    case SCROLL_CLASS:
2008. 		if (obj->otyp != SCR_BLANK_PAPER
2009. #ifdef MAIL
2010. 		    && obj->otyp != SCR_MAIL
2011. #endif
2012. 		    ) {
2013. 			if (!Blind) {
2014. 				boolean oq1 = obj->quan == 1L;
2015. 				pline_The("scroll%s %s.",
2016. 					  oq1 ? "" : "s", otense(obj, "fade"));
2017. 			}
2018. 			if(obj->unpaid && costly_spot(u.ux, u.uy)) {
2019. 			    You("erase it, you pay for it.");
2020. 			    bill_dummy_object(obj);
2021. 			}
2022. 			obj->otyp = SCR_BLANK_PAPER;
2023. 			obj->spe = 0;
2024. 			used = TRUE;
2025. 		} 
2026. 		break;
2027. 	    case SPBOOK_CLASS:
2028. 		if (obj->otyp != SPE_BLANK_PAPER) {
2029. 			if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
2030. 	pline("%s suddenly heats up; steam rises and it remains dry.",
2031. 				The(xname(obj)));
2032. 			} else {
2033. 			    if (!Blind) {
2034. 				    boolean oq1 = obj->quan == 1L;
2035. 				    pline_The("spellbook%s %s.",
2036. 					oq1 ? "" : "s", otense(obj, "fade"));
2037. 			    }
2038. 			    if(obj->unpaid) {
2039. 				subfrombill(obj, shop_keeper(*u.ushops));
2040. 			        You("erase it, you pay for it.");
2041. 			        bill_dummy_object(obj);
2042. 			    }
2043. 			    obj->otyp = SPE_BLANK_PAPER;
2044. 			}
2045. 			used = TRUE;
2046. 		}
2047. 		break;
2048. 	    case GEM_CLASS:
2049. 		if (amnesia && (obj->otyp == LUCKSTONE ||
2050. 			obj->otyp == LOADSTONE || obj->otyp == HEALTHSTONE ||
2051. 			obj->otyp == TOUCHSTONE))
2052. 		    downgrade_obj(obj, FLINT, &used);
2053. 		break;
2054. 	    case TOOL_CLASS:
2055. 		/* Artifacts aren't downgraded by amnesia */
2056. 		if (amnesia && !obj->oartifact) {
2057. 		    switch (obj->otyp) {
2058. 			case MAGIC_LAMP:
2059. 			    /* Magic lamps forget their djinn... */
2060. 			    downgrade_obj(obj, OIL_LAMP, &used);
2061. 			    break;
2062. 			case MAGIC_CANDLE:
2063. 			    downgrade_obj(obj, 
2064. 					    rn2(2)? WAX_CANDLE : TALLOW_CANDLE,
2065. 					    &used);
2066. 			    break;
2067. 			case DRUM_OF_EARTHQUAKE:
2068. 			    downgrade_obj(obj, LEATHER_DRUM, &used);
2069. 			    break;
2070. 			case MAGIC_WHISTLE:
2071. 			    /* Magic whistles lose their powers... */
2072. 			    downgrade_obj(obj, TIN_WHISTLE, &used);
2073. 			    break;
2074. 			case MAGIC_FLUTE:
2075. 			    /* Magic flutes sound normal again... */
2076. 			    downgrade_obj(obj, WOODEN_FLUTE, &used);
2077. 			    break;
2078. 			case MAGIC_HARP:
2079. 			    /* Magic harps sound normal again... */
2080. 			    downgrade_obj(obj, WOODEN_HARP, &used);
2081. 			    break;
2082. 			case FIRE_HORN:
2083. 			case FROST_HORN:
2084. 			case HORN_OF_PLENTY:
2085. 			    downgrade_obj(obj, TOOLED_HORN, &used);
2086. 			    break;
2087. 			case MAGIC_MARKER:
2088. 			    /* Magic markers run... */
2089. 			    if (obj->spe > 0) {
2090. 				pre_downgrade_obj(obj, &used);
2091. 				if ((obj->spe -= (3 + rn2(10))) < 0) 
2092. 				    obj->spe = 0;
2093. 			    }
2094. 			    break;
2095. 		    }
2096. 		}
2097. 
2098. 		/* The only other tools that can be affected are pick axes and 
2099. 		 * unicorn horns... */
2100. 		if (!is_weptool(obj)) break;
2101. 		/* Drop through for disenchantment and rusting... */
2102. 		/* fall through */
2103. 	    case ARMOR_CLASS:
2104. 	    case WEAPON_CLASS:
2105. 	    case WAND_CLASS:
2106. 	    case RING_CLASS:
2107. 	    /* Just "fall through" to generic rustprone check for now. */
2108. 	    /* fall through */
2109. 	    default:
2110. 		switch(artifact_wet(obj, FALSE)) {
2111. 		    case -1: break;
2112. 		    default:
2113. 			return TRUE;
2114. 		}
2115. 		/* !ofAmnesia acts as a disenchanter... */
2116. 		if (amnesia && obj->spe > 0) {
2117. 		    pre_downgrade_obj(obj, &used);
2118. 		    drain_item(obj);
2119. 		}
2120. 		if (!obj->oerodeproof && is_rustprone(obj) &&
2121. 		    (obj->oeroded < MAX_ERODE) && !rn2(2)) {
2122. 			pline("%s %s some%s.",
2123. 			      Your_buf, aobjnam(obj, "rust"),
2124. 			      obj->oeroded ? " more" : "what");
2125. 			obj->oeroded++;
2126. 			if(obj->unpaid && costly_spot(u.ux, u.uy) && !used) {
2127. 			    You("damage it, you pay for it.");
2128. 			    bill_dummy_object(obj);
2129. 			}
2130. 			used = TRUE;
2131. 		} 
2132. 		break;
2133. 	}
2134. 	/* !ofAmnesia might strip away fooproofing... */
2135. 	if (amnesia && obj->oerodeproof && !rn2(13)) {
2136. 	    pre_downgrade_obj(obj, &used);
2137. 	    obj->oerodeproof = FALSE;
2138. 	}
2139. 
2140. 	/* !ofAmnesia also strips blessed/cursed status... */
2141. 
2142. 	if (amnesia && (obj->cursed || obj->blessed)) {
2143. 	    /* Blessed objects are valuable, cursed objects aren't, unless
2144. 	     * they're water.
2145. 	     */
2146. 	    if (obj->blessed || obj->otyp == POT_WATER)
2147. 		pre_downgrade_obj(obj, &used);
2148. 	    else if (!used) {
2149. 		Your("%s for a moment.", aobjnam(obj, "sparkle"));
2150. 		used = TRUE;
2151. 	    }
2152. 	    uncurse(obj);
2153. 	    unbless(obj);
2154. 	}
2155. 
2156. 	if (used) 
2157. 	    update_inventory();
2158. 	else 
2159. 	    pline("%s %s wet.", Your_buf, aobjnam(obj,"get"));
2160. 
2161. 	return used;
2162. }
2163. 
2164. 
2165. /* KMH, balance patch -- idea by Dylan O'Donnell <dylanw@demon.net>
2166.  * The poor hacker's polypile.  This includes weapons, armor, and tools.
2167.  * To maintain balance, magical categories (amulets, scrolls, spellbooks,
2168.  * potions, rings, and wands) should NOT be supported.
2169.  * Polearms are not currently implemented.
2170.  */
2171. int
2172. upgrade_obj(obj)
2173. register struct obj *obj;
2174. /* returns 1 if something happened (potion should be used up) 
2175.  * returns 0 if nothing happened
2176.  * returns -1 if object exploded (potion should be used up) 
2177.  */
2178. {
2179. 	int chg, otyp = obj->otyp, otyp2;
2180. 	xchar ox, oy;
2181. 	long owornmask;
2182. 	struct obj *otmp;
2183. 	boolean explodes;
2184. 
2185. 	/* Check to see if object is valid */
2186. 	if (!obj)
2187. 		return 0;
2188. 	(void)snuff_lit(obj);
2189. 	if (obj->oartifact)
2190. 		/* WAC -- Could have some funky fx */
2191. 		return 0;
2192. 
2193. 	switch (obj->otyp)
2194. 	{
2195. 		/* weapons */
2196. 		case ORCISH_DAGGER:
2197. 			obj->otyp = DAGGER;
2198. 			break;
2199. 		case GREAT_DAGGER:
2200. 		case DAGGER:
2201. 			if (!rn2(2)) obj->otyp = ELVEN_DAGGER;
2202. 			else obj->otyp = DARK_ELVEN_DAGGER;
2203. 			break;
2204. 		case ELVEN_DAGGER:
2205. 		case DARK_ELVEN_DAGGER:
2206. 			obj->otyp = GREAT_DAGGER;
2207. 			break;
2208. 		case KNIFE:
2209. 			obj->otyp = STILETTO;
2210. 			break;
2211. 		case STILETTO:
2212. 			obj->otyp = KNIFE;
2213. 			break;
2214. 		case AXE:
2215. 			obj->otyp = BATTLE_AXE;
2216. 			break;
2217. 		case BATTLE_AXE:
2218. 			obj->otyp = AXE;
2219. 			break;
2220. 		case PICK_AXE:
2221. 			obj->otyp = DWARVISH_MATTOCK;
2222. 			break;
2223. 		case DWARVISH_MATTOCK:
2224. 			obj->otyp = PICK_AXE;
2225. 			break;
2226. 		case ORCISH_SHORT_SWORD:
2227. 			obj->otyp = SHORT_SWORD;
2228. 			break;
2229. 		case ELVEN_SHORT_SWORD:
2230. 		case DARK_ELVEN_SHORT_SWORD:
2231. 		case SHORT_SWORD:
2232. 			obj->otyp = DWARVISH_SHORT_SWORD;
2233. 			break;
2234. 		case DWARVISH_SHORT_SWORD:
2235. 			if (!rn2(2)) obj->otyp = ELVEN_SHORT_SWORD;
2236. 			else obj->otyp = DARK_ELVEN_SHORT_SWORD;
2237. 			break;
2238. 		case BROADSWORD:
2239. 			obj->otyp = ELVEN_BROADSWORD;
2240. 			break;
2241. 		case ELVEN_BROADSWORD:
2242. 			obj->otyp = BROADSWORD;
2243. 			break;
2244. 		case CLUB:
2245. 			obj->otyp = AKLYS;
2246. 			break;
2247. 		case AKLYS:
2248. 			obj->otyp = CLUB;
2249. 			break;
2250. 		case WAR_HAMMER:
2251. 			obj->otyp = HEAVY_HAMMER;
2252. 			break;
2253. 		case HEAVY_HAMMER:
2254. 			obj->otyp = WAR_HAMMER;
2255. 			break;
2256. 		case ELVEN_BOW:
2257. 		case DARK_ELVEN_BOW:
2258. 		case YUMI:
2259. 		case ORCISH_BOW:
2260. 			obj->otyp = BOW;
2261. 			break;
2262. 		case BOW:
2263. 			switch (rn2(3)) {
2264. 				case 0: obj->otyp = ELVEN_BOW; break;
2265. 				case 1: obj->otyp = DARK_ELVEN_BOW; break;
2266. 				case 2: obj->otyp = YUMI; break;
2267. 			}
2268. 			break;
2269. 		case ELVEN_ARROW:
2270. 		case DARK_ELVEN_ARROW:
2271. 		case YA:
2272. 		case ORCISH_ARROW:
2273. 			obj->otyp = ARROW;
2274. 			break;
2275. 		case ARROW:
2276. 			switch (rn2(3)) {
2277. 				case 0: obj->otyp = ELVEN_ARROW; break;
2278. 				case 1: obj->otyp = DARK_ELVEN_ARROW; break;
2279. 				case 2: obj->otyp = YA; break;
2280. 			}
2281. 			break;
2282. 		/* armour */
2283. 		case ELVEN_MITHRIL_COAT:
2284. 			obj->otyp = DARK_ELVEN_MITHRIL_COAT;
2285. 			break;
2286. 		case DARK_ELVEN_MITHRIL_COAT:
2287. 			obj->otyp = ELVEN_MITHRIL_COAT;
2288. 			break;
2289. 		case ORCISH_CHAIN_MAIL:
2290. 			obj->otyp = CHAIN_MAIL;
2291. 			break;
2292. 		case CHAIN_MAIL:
2293. 			obj->otyp = ORCISH_CHAIN_MAIL;
2294. 			break;
2295. 		case STUDDED_LEATHER_ARMOR:
2296. 		case LEATHER_JACKET:
2297. 			obj->otyp = LEATHER_ARMOR;
2298. 			break;
2299. 		case LEATHER_ARMOR:
2300. 			obj->otyp = STUDDED_LEATHER_ARMOR;
2301. 			break;
2302. 		/* robes */
2303. 		case ROBE:
2304. 			if (!rn2(2)) obj->otyp = ROBE_OF_PROTECTION;
2305. 			else obj->otyp = ROBE_OF_POWER;
2306. 			break;
2307. 		case ROBE_OF_PROTECTION:
2308. 		case ROBE_OF_POWER:
2309. 			obj->otyp = ROBE;
2310. 			break;
2311. 		/* cloaks */
2312. 		case CLOAK_OF_PROTECTION:
2313. 		case CLOAK_OF_INVISIBILITY:
2314. 		case CLOAK_OF_MAGIC_RESISTANCE:
2315. 		case CLOAK_OF_DISPLACEMENT:
2316. 		case DWARVISH_CLOAK:
2317. 		case ORCISH_CLOAK:
2318. 			if (!rn2(2)) obj->otyp = OILSKIN_CLOAK;
2319. 			else obj->otyp = ELVEN_CLOAK;
2320. 			break;
2321. 		case OILSKIN_CLOAK:
2322. 		case ELVEN_CLOAK:
2323. 			switch (rn2(4)) {
2324. 				case 0: obj->otyp = CLOAK_OF_PROTECTION; break;
2325. 				case 1: obj->otyp = CLOAK_OF_INVISIBILITY; break;
2326. 				case 2: obj->otyp = CLOAK_OF_MAGIC_RESISTANCE; break;
2327. 				case 3: obj->otyp = CLOAK_OF_DISPLACEMENT; break;
2328. 			}
2329. 			break;
2330. 		/* helms */
2331. 		case FEDORA:
2332. 			obj->otyp = ELVEN_LEATHER_HELM;
2333. 			break;
2334. 		case ELVEN_LEATHER_HELM:
2335. 			obj->otyp = FEDORA;
2336. 			break;
2337. 		case DENTED_POT:
2338. 			obj->otyp = ORCISH_HELM;
2339. 			break;
2340. 		case ORCISH_HELM:
2341. 		case HELM_OF_BRILLIANCE:
2342. 		case HELM_OF_TELEPATHY:
2343. 			obj->otyp = DWARVISH_IRON_HELM;
2344. 			break;
2345. 		case DWARVISH_IRON_HELM:
2346. 			if (!rn2(2)) obj->otyp = HELM_OF_BRILLIANCE;
2347. 			else obj->otyp = HELM_OF_TELEPATHY;
2348. 			break;
2349. 		case CORNUTHAUM:
2350. 			obj->otyp = DUNCE_CAP;
2351. 			break;
2352. 		case DUNCE_CAP:
2353. 			obj->otyp = CORNUTHAUM;
2354. 			break;
2355. 		/* gloves */
2356. 		case LEATHER_GLOVES:
2357. 			if (!rn2(2)) obj->otyp = GAUNTLETS_OF_SWIMMING;
2358. 			else obj->otyp = GAUNTLETS_OF_DEXTERITY;
2359. 			break;
2360. 		case GAUNTLETS_OF_SWIMMING:
2361. 		case GAUNTLETS_OF_DEXTERITY:
2362. 			obj->otyp = LEATHER_GLOVES;
2363. 			break;
2364. 		/* shields */
2365. 		case ELVEN_SHIELD:
2366. 			if (!rn2(2)) obj->otyp = URUK_HAI_SHIELD;
2367. 			else obj->otyp = ORCISH_SHIELD;
2368. 			break;
2369. 		case URUK_HAI_SHIELD:
2370. 		case ORCISH_SHIELD:
2371. 			obj->otyp = ELVEN_SHIELD;
2372. 			break;
2373. 		case DWARVISH_ROUNDSHIELD:
2374. 			obj->otyp = LARGE_SHIELD;
2375. 			break;
2376. 		case LARGE_SHIELD:
2377. 			obj->otyp = DWARVISH_ROUNDSHIELD;
2378. 			break;
2379. 		/* boots */
2380. 		case LOW_BOOTS:
2381. 			obj->otyp = HIGH_BOOTS;
2382. 			break;
2383. 		case HIGH_BOOTS:
2384. 			obj->otyp = LOW_BOOTS;
2385. 			break;
2386. 		/* NOTE:  Supposedly,  HIGH_BOOTS should upgrade to any of the
2387. 			other magic leather boots (except for fumble).  IRON_SHOES
2388. 			should upgrade to the iron magic boots,  unless
2389. 			the iron magic boots are fumble */
2390. 		/* rings,  amulets */
2391. 		case LARGE_BOX:
2392. 		case ICE_BOX:
2393. 			obj->otyp = CHEST;
2394. 			break;
2395. 		case CHEST:
2396. 			obj->otyp = ICE_BOX;
2397. 			break;
2398. 		case SACK:
2399. 			obj->otyp = rn2(5) ? OILSKIN_SACK : BAG_OF_HOLDING;
2400. 			break;
2401. 		case OILSKIN_SACK:
2402. 			obj->otyp = BAG_OF_HOLDING;
2403. 			break;
2404. 		case BAG_OF_HOLDING:
2405. 			obj->otyp = OILSKIN_SACK;
2406. 			break;
2407. #ifdef TOURIST
2408. 		case TOWEL:
2409. 			obj->otyp = BLINDFOLD;
2410. 			break;
2411. 		case BLINDFOLD:
2412. 			obj->otyp = TOWEL;
2413. 			break;
2414. 		case CREDIT_CARD:
2415. #endif
2416. 		case LOCK_PICK:
2417. 			obj->otyp = SKELETON_KEY;
2418. 			break;
2419. 		case SKELETON_KEY:
2420. 			obj->otyp = LOCK_PICK;
2421. 			break;
2422. 		case TALLOW_CANDLE:
2423. 			obj->otyp = WAX_CANDLE;
2424. 			break;
2425. 		case WAX_CANDLE:
2426. 			obj->otyp = TALLOW_CANDLE;
2427. 			break;
2428. 		case OIL_LAMP:
2429. 			obj->otyp = BRASS_LANTERN;
2430. 			break;
2431. 		case BRASS_LANTERN:
2432. 			obj->otyp = OIL_LAMP;
2433. 			break;
2434. 		case TIN_WHISTLE:
2435. 			obj->otyp = MAGIC_WHISTLE;
2436. 			break;
2437. 		case MAGIC_WHISTLE:
2438. 			obj->otyp = TIN_WHISTLE;
2439. 			break;
2440. 		case WOODEN_FLUTE:
2441. 			obj->otyp = MAGIC_FLUTE;
2442. 			obj->spe = rn1(5,10);
2443. 			break;
2444. 		case MAGIC_FLUTE:
2445. 			obj->otyp = WOODEN_FLUTE;
2446. 			break;
2447. 		case TOOLED_HORN:
2448. 			obj->otyp = rn1(HORN_OF_PLENTY - TOOLED_HORN, FROST_HORN);
2449. 			obj->spe = rn1(5,10);
2450. 			obj->known = 0;
2451. 			break;
2452. 		case HORN_OF_PLENTY:
2453. 		case FIRE_HORN:
2454. 		case FROST_HORN:
2455. 			obj->otyp = TOOLED_HORN;
2456. 			break;
2457. 		case WOODEN_HARP:
2458. 			obj->otyp = MAGIC_HARP;
2459. 			obj->spe = rn1(5,10);
2460. 			obj->known = 0;
2461. 			break;
2462. 		case MAGIC_HARP:
2463. 			obj->otyp = WOODEN_HARP;
2464. 			break;
2465. #ifdef STEED
2466. 		case LEASH:
2467. 			obj->otyp = SADDLE;
2468. 			break;
2469. 		case SADDLE:
2470. 			obj->otyp = LEASH;
2471. 			break;
2472. #endif
2473. 		case TIN_OPENER:
2474. 			obj->otyp = TINNING_KIT;
2475. 			obj->spe = rn1(30,70);
2476. 			obj->known = 0;
2477. 			break;
2478. 		case TINNING_KIT:
2479. 			obj->otyp = TIN_OPENER;
2480. 			break;
2481. 		case CRYSTAL_BALL:
2482. 			/* "ball-point pen" */
2483. 			obj->otyp = MAGIC_MARKER;
2484. 			/* Keep the charges (crystal ball usually less than marker) */
2485. 			break;
2486. 		case MAGIC_MARKER:
2487. 			obj->otyp = CRYSTAL_BALL;
2488. 			chg = rn1(10,3);
2489. 			if (obj->spe > chg)
2490. 				obj->spe = chg;
2491. 			obj->known = 0;
2492. 			break;
2493. 		case K_RATION:
2494. 		case C_RATION:
2495. 		case LEMBAS_WAFER:
2496. 			if (!rn2(2)) obj->otyp = CRAM_RATION;
2497. 			else obj->otyp = FOOD_RATION;
2498. 			break;
2499. 		case FOOD_RATION:
2500. 		case CRAM_RATION:
2501. 			obj->otyp = LEMBAS_WAFER;
2502. 			break;
2503. 		case LOADSTONE:
2504. 			obj->otyp = FLINT;
2505. 			break;
2506. 		case FLINT:
2507. 			if (!rn2(2)) obj->otyp = LUCKSTONE;
2508. 			else obj->otyp = HEALTHSTONE;
2509. 			break;
2510. 		default:
2511. 			/* This object is not upgradable */
2512. 			return 0;
2513. 	}
2514. 
2515. 	if ((!carried(obj) || obj->unpaid) &&
2516. #ifdef UNPOLYPILE
2517. 		!is_hazy(obj) &&
2518. #endif
2519. 		get_obj_location(obj, &ox, &oy, BURIED_TOO|CONTAINED_TOO) &&
2520. 		costly_spot(ox, oy)) {
2521. 	    char objroom = *in_rooms(ox, oy, SHOPBASE);
2522. 	    register struct monst *shkp = shop_keeper(objroom);
2523. 
2524. 	    if ((!obj->no_charge ||
2525. 		 (Has_contents(obj) &&
2526. 		    (contained_cost(obj, shkp, 0L, FALSE, FALSE) != 0L)))
2527. 	       && inhishop(shkp)) {
2528. 		if(shkp->mpeaceful) {
2529. 		    if(*u.ushops && *in_rooms(u.ux, u.uy, 0) ==
2530. 			    *in_rooms(shkp->mx, shkp->my, 0) &&
2531. 			    !costly_spot(u.ux, u.uy))
2532. 			make_angry_shk(shkp, ox, oy);
2533. 		    else {
2534. 			pline("%s gets angry!", Monnam(shkp));
2535. 			hot_pursuit(shkp);
2536. 		    }
2537. 		} else Norep("%s is furious!", Monnam(shkp));
2538. 		otyp2 = obj->otyp;
2539. 		obj->otyp = otyp;
2540. 		/*
2541. 		 * [ALI] When unpaid containers are upgraded, the
2542. 		 * old container is billed as a dummy object, but
2543. 		 * it's contents are unaffected and will remain
2544. 		 * either unpaid or not as appropriate.
2545. 		 */
2546. 		otmp = obj->cobj;
2547. 		obj->cobj = NULL;
2548. 		if (costly_spot(u.ux, u.uy) && objroom == *u.ushops)
2549. 		    bill_dummy_object(obj);
2550. 		else
2551. 		    (void) stolen_value(obj, ox, oy, FALSE, FALSE, FALSE);
2552. 		obj->otyp = otyp2;
2553. 		obj->cobj = otmp;
2554. 	    }
2555. 	}
2556. 
2557. 	/* The object was transformed */
2558. 	obj->owt = weight(obj);
2559. 	obj->oclass = objects[obj->otyp].oc_class;
2560. 	if (!objects[obj->otyp].oc_uses_known)
2561. 	    obj->known = 1;
2562. 
2563. 	if (carried(obj)) {
2564. 	    if (obj == uskin) rehumanize();
2565. 	    /* Quietly remove worn item if no longer compatible --ALI */
2566. 	    owornmask = obj->owornmask;
2567. 	    if (owornmask & W_ARM && !is_suit(obj))
2568. 		owornmask &= ~W_ARM;
2569. 	    if (owornmask & W_ARMC && !is_cloak(obj))
2570. 		owornmask &= ~W_ARMC;
2571. 	    if (owornmask & W_ARMH && !is_helmet(obj))
2572. 		owornmask &= ~W_ARMH;
2573. 	    if (owornmask & W_ARMS && !is_shield(obj))
2574. 		owornmask &= ~W_ARMS;
2575. 	    if (owornmask & W_ARMG && !is_gloves(obj))
2576. 		owornmask &= ~W_ARMG;
2577. 	    if (owornmask & W_ARMF && !is_boots(obj))
2578. 		owornmask &= ~W_ARMF;
2579. #ifdef TOURIST
2580. 	    if (owornmask & W_ARMU && !is_shirt(obj))
2581. 		owornmask &= ~W_ARMU;
2582. #endif
2583. 	    if (owornmask & W_TOOL && obj->otyp != BLINDFOLD &&
2584. 	      obj->otyp != TOWEL && obj->otyp != LENSES)
2585. 		owornmask &= ~W_TOOL;
2586. 	    otyp2 = obj->otyp;
2587. 	    obj->otyp = otyp;
2588. 	    if (obj->otyp == LEASH && obj->leashmon) o_unleash(obj);
2589. 	    remove_worn_item(obj, TRUE);
2590. 	    obj->otyp = otyp2;
2591. 	    obj->owornmask = owornmask;
2592. 	    setworn(obj, obj->owornmask);
2593. 	    puton_worn_item(obj);
2594. 	}
2595. 
2596. 	if (obj->otyp == BAG_OF_HOLDING && Has_contents(obj)) {
2597. 	    explodes = FALSE;
2598. 
2599. 	    for (otmp = obj->cobj; otmp; otmp = otmp->nobj)
2600. 		if (mbag_explodes(otmp, 0)) { 
2601. 		    explodes = TRUE;
2602. 		    break;
2603. 		}
2604. 
2605.             if (explodes) {
2606. 		pline("As you upgrade your bag, you are blasted by a magical explosion!");
2607. 		delete_contents(obj);
2608. 		if (carried(obj))
2609. 		    useup(obj);
2610. 		else
2611. 		    useupf(obj, obj->quan);
2612. 		losehp(d(6,6), "magical explosion", KILLED_BY_AN);
2613. 		return -1;
2614. 	    }
2615. 	}
2616. 	return 1;
2617. }
2618. 
2619. int
2620. dodip()
2621. {
2622. 	struct obj *potion, *obj, *singlepotion;
2623. 	const char *tmp;
2624. 	uchar here;
2625. 	char allowall[2], qbuf[QBUFSZ], Your_buf[BUFSZ];
2626. 	short mixture;
2627. 	int res;
2628. 
2629. 	allowall[0] = ALL_CLASSES; allowall[1] = '\0';
2630. 	if(!(obj = getobj(allowall, "dip")))
2631. 		return(0);
2632. 
2633. 	here = levl[u.ux][u.uy].typ;
2634. 	/* Is there a fountain to dip into here? */
2635. 	if (IS_FOUNTAIN(here)) {
2636. 		if(yn("Dip it into the fountain?") == 'y') {
2637. 			dipfountain(obj);
2638. 			return(1);
2639. 		}
2640. 	} else if (IS_TOILET(here)) {        
2641. 		if(yn("Dip it into the toilet?") == 'y') {
2642. 			diptoilet(obj);
2643. 			return(1);
2644. 		}
2645. 	} else if (is_pool(u.ux,u.uy)) {
2646. 		tmp = waterbody_name(u.ux,u.uy);
2647. 		Sprintf(qbuf, "Dip it into the %s?", tmp);
2648. 		if (yn(qbuf) == 'y') {
2649. 		    if (Levitation) {
2650. 			floating_above(tmp);
2651. #ifdef STEED
2652. 		    } else if (u.usteed && !is_swimmer(u.usteed->data) &&
2653. 			    P_SKILL(P_RIDING) < P_BASIC) {
2654. 			rider_cant_reach(); /* not skilled enough to reach */
2655. #endif
2656. 		    } else {
2657. 			(void) get_wet(obj, level.flags.lethe);
2658. 			if (obj->otyp == POT_ACID) useup(obj);
2659. 		    }
2660. 		    return 1;
2661. 		}
2662. 	}
2663. 
2664. 	if(!(potion = getobj(beverages, "dip into")))
2665. 		return(0);
2666. 	if (potion == obj && potion->quan == 1L) {
2667. 		pline("That is a potion bottle, not a Klein bottle!");
2668. 		return 0;
2669. 	}
2670. 
2671. 	if(potion->otyp != POT_WATER && obj->otyp == POT_WATER) {
2672. 	  /* swap roles, to ensure symmetry */
2673. 	  struct obj *otmp = potion;
2674. 	  potion = obj;
2675. 	  obj = otmp;
2676. 	} 
2677. 	potion->in_use = TRUE;          /* assume it will be used up */
2678. 	if(potion->otyp == POT_WATER) {
2679. 		boolean useeit = !Blind;
2680. 		if (useeit) (void) Shk_Your(Your_buf, obj);
2681. 		if (potion->blessed) {
2682. 			if (obj->cursed) {
2683. 				if (useeit)
2684. 				    pline("%s %s %s.",
2685. 					  Your_buf,
2686. 					  aobjnam(obj, "softly glow"),
2687. 					  hcolor(NH_AMBER));
2688. 				uncurse(obj);
2689. 				obj->bknown=1;
2690. 	poof:
2691. 				if(!(objects[potion->otyp].oc_name_known) &&
2692. 				   !(objects[potion->otyp].oc_uname))
2693. 					docall(potion);
2694. 				useup(potion);
2695. 				return(1);
2696. 			} else if(!obj->blessed) {
2697. 				if (useeit) {
2698. 				    tmp = hcolor(NH_LIGHT_BLUE);
2699. 				    pline("%s %s with a%s %s aura.",
2700. 					  Your_buf,
2701. 					  aobjnam(obj, "softly glow"),
2702. 					  index(vowels, *tmp) ? "n" : "", tmp);
2703. 				}
2704. 				bless(obj);
2705. 				obj->bknown=1;
2706. 				goto poof;
2707. 			}
2708. 		} else if (potion->cursed) {
2709. 			if (obj->blessed) {
2710. 				if (useeit)
2711. 				    pline("%s %s %s.",
2712. 					  Your_buf,
2713. 					  aobjnam(obj, "glow"),
2714. 					  hcolor((const char *)"brown"));
2715. 				unbless(obj);
2716. 				obj->bknown=1;
2717. 				goto poof;
2718. 			} else if(!obj->cursed) {
2719. 				if (useeit) {
2720. 				    tmp = hcolor(NH_BLACK);
2721. 				    pline("%s %s with a%s %s aura.",
2722. 					  Your_buf,
2723. 					  aobjnam(obj, "glow"),
2724. 					  index(vowels, *tmp) ? "n" : "", tmp);
2725. 				}
2726. 				curse(obj);
2727. 				obj->bknown=1;
2728. 				goto poof;
2729. 			}
2730. 		} else {
2731. 			switch(artifact_wet(obj,TRUE)) {
2732. 				/* Assume ZT_xxx is AD_xxx-1 */
2733. 				case -1: break;
2734. 				default:
2735. 					zap_over_floor(u.ux, u.uy,
2736. 					  (artifact_wet(obj,TRUE)-1), NULL);
2737. 					break;
2738. 			}
2739. 			if (get_wet(obj, FALSE))
2740. 			    goto poof;
2741. 		}
2742. 	} else if (potion->otyp == POT_AMNESIA) {
2743. 	    if (potion == obj) {
2744. 		obj->in_use = FALSE;
2745. 		potion = splitobj(obj, 1L);
2746. 		potion->in_use = TRUE;
2747. 	    }
2748. 	    if (get_wet(obj, TRUE)) goto poof;
2749. 	}
2750. 	/* WAC - Finn Theoderson - make polymorph and gain level msgs similar
2751. 	 * 	 Give out name of new object and allow user to name the potion
2752. 	 */
2753. 	/* KMH, balance patch -- idea by Dylan O'Donnell <dylanw@demon.net> */
2754. 	else if (potion->otyp == POT_GAIN_LEVEL) {
2755. 	    res = upgrade_obj(obj);
2756. 
2757. 	    if (res != 0) {
2758. 
2759. 		if (res == 1) { 
2760. 		     /* The object was upgraded */
2761. 		     pline("Hmm!  You don't recall dipping that into the potion.");
2762. 		     prinv((char *)0, obj, 0L);
2763. 		} /* else potion exploded */
2764. 		if (!objects[potion->otyp].oc_name_known &&
2765. 			!objects[potion->otyp].oc_uname)
2766. 		    docall(potion);
2767. 		useup(potion);
2768. 		update_inventory();
2769. 		exercise(A_WIS, TRUE);
2770. 		return(1);
2771. 	    }
2772. 	    /* no return here, go for Interesting... message */
2773. 	} else if (obj->otyp == POT_POLYMORPH ||
2774. 		potion->otyp == POT_POLYMORPH) {
2775. 	    /* some objects can't be polymorphed */
2776. 	    if (obj->otyp == potion->otyp ||	/* both POT_POLY */
2777. 		    obj->otyp == WAN_POLYMORPH ||
2778. 		    obj->otyp == SPE_POLYMORPH ||
2779. 		    obj == uball || obj == uskin ||
2780. 		    obj_resists(obj->otyp == POT_POLYMORPH ?
2781. 				potion : obj, 5, 95)) {
2782. 		pline(nothing_happens);
2783. 	    } else {
2784. 	    	boolean was_wep = FALSE, was_swapwep = FALSE, was_quiver = FALSE;
2785. 		short save_otyp = obj->otyp;
2786. 		/* KMH, conduct */
2787. 		u.uconduct.polypiles++;
2788. 
2789. 		if (obj == uwep) was_wep = TRUE;
2790. 		else if (obj == uswapwep) was_swapwep = TRUE;
2791. 		else if (obj == uquiver) was_quiver = TRUE;
2792. 
2793. 		obj = poly_obj(obj, STRANGE_OBJECT);
2794. 
2795. 		if (was_wep) setuwep(obj, TRUE);
2796. 		else if (was_swapwep) setuswapwep(obj, TRUE);
2797. 		else if (was_quiver) setuqwep(obj);
2798. 
2799. 		if (obj->otyp != save_otyp) {
2800. 			makeknown(POT_POLYMORPH);
2801. 			useup(potion);
2802. 			prinv((char *)0, obj, 0L);
2803. 			return 1;
2804. 		} else {
2805. 			pline("Nothing seems to happen.");
2806. 			goto poof;
2807. 		}
2808. 	    }
2809. 	    potion->in_use = FALSE;	/* didn't go poof */
2810. 	    return(1);
2811. #ifdef UNPOLYPILE
2812. 	} else if (potion->otyp == POT_RESTORE_ABILITY && is_hazy(obj)) {
2813. 		/* KMH -- Restore ability will stop unpolymorphing */
2814. 		stop_timer(UNPOLY_OBJ, (genericptr_t) obj);
2815. 		obj->oldtyp = STRANGE_OBJECT;
2816. 		if (!Blind)
2817. 			pline("%s seems less hazy.", Yname2(obj));
2818. 		useup(potion);
2819. 		return (1);
2820. #endif
2821. 	} else if(obj->oclass == POTION_CLASS && obj->otyp != potion->otyp) {
2822. 		/* Mixing potions is dangerous... */
2823. 		pline_The("potions mix...");
2824. 		/* KMH, balance patch -- acid is particularly unstable */
2825. 		if (obj->cursed || obj->otyp == POT_ACID ||
2826. 		    potion->cursed || potion->otyp == POT_ACID || !rn2(10)) {
2827. 			pline("BOOM!  They explode!");
2828. 			exercise(A_STR, FALSE);
2829. 			if (!breathless(youmonst.data) || haseyes(youmonst.data))
2830. 				potionbreathe(obj);
2831. 			useup(obj);
2832. 			useup(potion);
2833. 			/* MRKR: an alchemy smock ought to be */
2834. 			/* some protection against this: */
2835. 			losehp(Acid_resistance ? rnd(5) : rnd(10),
2836. 			       "alchemic blast", KILLED_BY_AN);
2837. 			return(1);
2838. 		}
2839. 
2840. 		obj->blessed = obj->cursed = obj->bknown = 0;
2841. 		if (Blind || Hallucination) obj->dknown = 0;
2842. 
2843. 		if ((mixture = mixtype(obj, potion)) != 0) {
2844. 			obj->otyp = mixture;
2845. 		} else {
2846. 		    switch (obj->odiluted ? 1 : rnd(8)) {
2847. 			case 1:
2848. 				obj->otyp = POT_WATER;
2849. 				break;
2850. 			case 2:
2851. 			case 3:
2852. 				obj->otyp = POT_SICKNESS;
2853. 				break;
2854. 			case 4:
2855. 				{
2856. 				  struct obj *otmp;
2857. 				  otmp = mkobj(POTION_CLASS,FALSE);
2858. 				  obj->otyp = otmp->otyp;
2859. 				  obfree(otmp, (struct obj *)0);
2860. 				}
2861. 				break;
2862. 			default:
2863. 				if (!Blind)
2864. 			  pline_The("mixture glows brightly and evaporates.");
2865. 				useup(obj);
2866. 				useup(potion);
2867. 				return(1);
2868. 		    }
2869. 		}
2870. 
2871. 		obj->odiluted = (obj->otyp != POT_WATER);
2872. 
2873. 		if (obj->otyp == POT_WATER && !Hallucination) {
2874. 			pline_The("mixture bubbles%s.",
2875. 				Blind ? "" : ", then clears");
2876. 		} else if (!Blind) {
2877. 			pline_The("mixture looks %s.",
2878. 				hcolor(OBJ_DESCR(objects[obj->otyp])));
2879. 		}
2880. 
2881. 		useup(potion);
2882. 		return(1);
2883. 	}
2884. #ifdef INVISIBLE_OBJECTS
2885. 	if (!always_visible(obj)) {
2886. 	    if (potion->otyp == POT_INVISIBILITY && !obj->oinvis) {
2887. 		obj->oinvis = TRUE;
2888. 		if (!Blind)
2889. 		    pline(!See_invisible ? "Where did %s go?" :
2890. 			  "Gee!  All of a sudden you can see right through %s.",
2891. 			  the(xname(obj)));
2892. 		goto poof;
2893. 	    } else if (potion->otyp == POT_SEE_INVISIBLE && obj->oinvis) {
2894. 		obj->oinvis = FALSE;
2895. 		if (!Blind) {
2896. 		    if (!See_invisible)
2897. 			pline("So that's where %s went!", the(xname(obj)));
2898. 		    else
2899. 			You("can no longer see through %s.",
2900. 				the(xname(obj)));
2901. 		}
2902. 		goto poof;
2903. 	    }
2904. 	}
2905. #endif
2906. 
2907. 	if(is_poisonable(obj)) {
2908. 	    if(potion->otyp == POT_SICKNESS && !obj->opoisoned) {
2909. 		char buf[BUFSZ];
2910. 		if (potion->quan > 1L)
2911. 		    Sprintf(buf, "One of %s", the(xname(potion)));
2912. 		else
2913. 		    Strcpy(buf, The(xname(potion)));
2914. 		pline("%s forms a coating on %s.",
2915. 		      buf, the(xname(obj)));
2916. 		obj->opoisoned = TRUE;
2917. 		goto poof;
2918. 	    } else if(obj->opoisoned &&
2919. 		      (potion->otyp == POT_HEALING ||
2920. 		       potion->otyp == POT_EXTRA_HEALING ||
2921. 		       potion->otyp == POT_FULL_HEALING)) {
2922. 		pline("A coating wears off %s.", the(xname(obj)));
2923. 		obj->opoisoned = 0;
2924. 		goto poof;
2925. 	    }
2926. 	}
2927. 
2928. 	if (potion->otyp == POT_OIL) {
2929. 	    boolean wisx = FALSE;
2930. 	    if (potion->lamplit) {	/* burning */
2931. 		int omat = objects[obj->otyp].oc_material;
2932. 		/* the code here should be merged with fire_damage */
2933. 		if (catch_lit(obj)) {
2934. 		    /* catch_lit does all the work if true */
2935. 		} else if (obj->oerodeproof || obj_resists(obj, 5, 95) ||
2936. 			   !is_flammable(obj) || obj->oclass == FOOD_CLASS) {
2937. 		    pline("%s %s to burn for a moment.",
2938. 			  Yname2(obj), otense(obj, "seem"));
2939. 		} else {
2940. 		    if ((omat == PLASTIC || omat == PAPER) && !obj->oartifact)
2941. 			obj->oeroded = MAX_ERODE;
2942. 		    pline_The("burning oil %s %s.",
2943. 			    obj->oeroded == MAX_ERODE ? "destroys" : "damages",
2944. 			    yname(obj));
2945. 		    if (obj->oeroded == MAX_ERODE) {
2946. 			obj_extract_self(obj);
2947. 			obfree(obj, (struct obj *)0);
2948. 			obj = (struct obj *) 0;
2949. 		    } else {
2950. 			/* we know it's carried */
2951. 			if (obj->unpaid) {
2952. 			    /* create a dummy duplicate to put on bill */
2953. 			    verbalize("You burnt it, you bought it!");
2954. 			    bill_dummy_object(obj);
2955. 			}
2956. 			obj->oeroded++;
2957. 		    }
2958. 		}
2959. 	    } else if (potion->cursed) {
2960. 		pline_The("potion spills and covers your %s with oil.",
2961. 			  makeplural(body_part(FINGER)));
2962. 		incr_itimeout(&Glib, d(2,10));
2963. 	    } else if (obj->oclass != WEAPON_CLASS && !is_weptool(obj)) {
2964. 		/* the following cases apply only to weapons */
2965. 		goto more_dips;
2966. 	    /* Oil removes rust and corrosion, but doesn't unburn.
2967. 	     * Arrows, etc are classed as metallic due to arrowhead
2968. 	     * material, but dipping in oil shouldn't repair them.
2969. 	     */
2970. 	    } else if ((!is_rustprone(obj) && !is_corrodeable(obj)) ||
2971. 			is_ammo(obj) || (!obj->oeroded && !obj->oeroded2)) {
2972. 		/* uses up potion, doesn't set obj->greased */
2973. 		pline("%s %s with an oily sheen.",
2974. 		      Yname2(obj), otense(obj, "gleam"));
2975. 	    } else {
2976. 		pline("%s %s less %s.",
2977. 		      Yname2(obj), otense(obj, "are"),
2978. 		      (obj->oeroded && obj->oeroded2) ? "corroded and rusty" :
2979. 			obj->oeroded ? "rusty" : "corroded");
2980. 		if (obj->oeroded > 0) obj->oeroded--;
2981. 		if (obj->oeroded2 > 0) obj->oeroded2--;
2982. 		wisx = TRUE;
2983. 	    }
2984. 	    exercise(A_WIS, wisx);
2985. 	    makeknown(potion->otyp);
2986. 	    useup(potion);
2987. 	    return 1;
2988. 	}
2989. 
2990. 	/* KMH, balance patch -- acid affects damage(proofing) */
2991. 	if (potion->otyp == POT_ACID && (obj->oclass == ARMOR_CLASS ||
2992. 		obj->oclass == WEAPON_CLASS || is_weptool(obj))) {
2993. 	    if (!potion->blessed && obj->oerodeproof) {
2994. 		pline("%s %s golden shield.",  Yname2(obj),
2995. 			(obj->quan > 1L) ? "lose their" : "loses its");
2996. 		obj->oerodeproof = 0;
2997. 		makeknown(potion->otyp);
2998. 	    } else {
2999. 		pline("%s looks a little dull.", Yname2(obj));
3000. 		if (!objects[potion->otyp].oc_name_known &&
3001. 			!objects[potion->otyp].oc_uname)
3002. 		    docall(potion);
3003. 	    }
3004. 	    exercise(A_WIS, FALSE);
3005.   	    useup(potion);
3006. 	    return 1;
3007. 	}
3008.     more_dips:
3009. 
3010. 	/* Allow filling of MAGIC_LAMPs to prevent identification by player */
3011. 	if ((obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP) &&
3012. 	   (potion->otyp == POT_OIL)) {
3013. 
3014. 	    /* Turn off engine before fueling, turn off fuel too :-)  */
3015. 	    if (obj->lamplit || potion->lamplit) {
3016. 		useup(potion);
3017. 		explode(u.ux, u.uy, ZT_SPELL(ZT_FIRE), d(6,6), 0, EXPL_FIERY);
3018. 		exercise(A_WIS, FALSE);
3019. 		return 1;
3020. 	    }
3021. 	    /* Adding oil to an empty magic lamp renders it into an oil lamp */
3022. 	    if ((obj->otyp == MAGIC_LAMP) && obj->spe == 0) {
3023. 		obj->otyp = OIL_LAMP;
3024. 		obj->age = 0;
3025. 	    }
3026. 	    if (obj->age > 1000L) {
3027.                 pline("%s %s full.", Yname2(obj), otense(obj, "are"));
3028. 		potion->in_use = FALSE; /* didn't go poof */
3029. 	    } else {
3030.                 You("fill your %s with oil.", yname(obj));
3031. 		check_unpaid(potion);	/* Yendorian Fuel Tax */
3032. 		obj->age += 2*potion->age;	/* burns more efficiently */
3033. 		if (obj->age > 1500L) obj->age = 1500L;
3034. 		useup(potion);
3035. 		exercise(A_WIS, TRUE);
3036. 	    }
3037. 	    makeknown(POT_OIL);
3038. 	    obj->spe = 1;
3039. 	    update_inventory();
3040. 	    return 1;
3041. 	}
3042. 
3043. 	potion->in_use = FALSE;         /* didn't go poof */
3044. 	if ((obj->otyp == UNICORN_HORN || obj->oclass == GEM_CLASS) &&
3045. 	    (mixture = mixtype(obj, potion)) != 0) {
3046. 		char oldbuf[BUFSZ], newbuf[BUFSZ];
3047. 		short old_otyp = potion->otyp;
3048. 		boolean old_dknown = FALSE;
3049. 		boolean more_than_one = potion->quan > 1;
3050. 
3051. 		oldbuf[0] = '\0';
3052. 		if (potion->dknown) {
3053. 		    old_dknown = TRUE;
3054. 		    Sprintf(oldbuf, "%s ",
3055. 			    hcolor(OBJ_DESCR(objects[potion->otyp])));
3056. 		}
3057. 		/* with multiple merged potions, split off one and
3058. 		   just clear it */
3059. 		if (potion->quan > 1L) {
3060. 		    singlepotion = splitobj(potion, 1L);
3061. 		} else singlepotion = potion;
3062. 		
3063. 		/* MRKR: Gems dissolve in acid to produce new potions */
3064. 
3065. 		if (obj->oclass == GEM_CLASS && potion->otyp == POT_ACID) {
3066. 		    struct obj *singlegem = (obj->quan > 1L ? 
3067. 					     splitobj(obj, 1L) : obj);
3068. 
3069. 		    singlegem->in_use = TRUE;
3070. 		    if (potion->otyp == POT_ACID && 
3071. 		      (obj->otyp == DILITHIUM_CRYSTAL || 
3072. 		       potion->cursed || !rn2(10))) {
3073. 			/* Just to keep them on their toes */
3074. 
3075. 			singlepotion->in_use = TRUE;
3076. 			if (Hallucination && obj->otyp == DILITHIUM_CRYSTAL) {
3077. 			    /* Thanks to Robin Johnson */
3078. 			    pline("Warning, Captain!  The warp core has been breached!");
3079. 			}
3080. 			pline("BOOM!  %s explodes!", The(xname(singlegem)));
3081. 			exercise(A_STR, FALSE);
3082. 			if (!breathless(youmonst.data) || haseyes(youmonst.data))
3083. 			    potionbreathe(singlepotion);
3084. 			useup(singlegem);
3085. 			useup(singlepotion);
3086. 			/* MRKR: an alchemy smock ought to be */
3087. 			/* some protection against this: */
3088. 			losehp(Acid_resistance ? rnd(5) : rnd(10), 
3089. 			       "alchemic blast", KILLED_BY_AN);
3090. 			return(1);	  
3091. 		    }
3092. 
3093. 		    pline("%s dissolves in %s.", The(xname(singlegem)), 
3094. 			  the(xname(singlepotion)));
3095. 		    makeknown(POT_ACID);
3096. 		    useup(singlegem);
3097. 		}
3098. 
3099. 		if(singlepotion->unpaid && costly_spot(u.ux, u.uy)) {
3100. 		    You("use it, you pay for it.");
3101. 		    bill_dummy_object(singlepotion);
3102. 		}
3103. 
3104. 		if (singlepotion->otyp == mixture) {		  
3105. 		    /* no change - merge it back in */
3106. 		    if (more_than_one && !merged(&potion, &singlepotion)) {
3107. 			/* should never happen */
3108. 			impossible("singlepotion won't merge with parent potion.");
3109. 		    }
3110. 		} else {		  
3111. 		singlepotion->otyp = mixture;
3112. 		singlepotion->blessed = 0;
3113. 		if (mixture == POT_WATER)
3114. 		    singlepotion->cursed = singlepotion->odiluted = 0;
3115. 		else
3116. 		    singlepotion->cursed = obj->cursed;  /* odiluted left as-is */
3117. 		singlepotion->bknown = FALSE;
3118. 		if (Blind) {
3119. 		    singlepotion->dknown = FALSE;
3120. 		} else {
3121. 		    singlepotion->dknown = !Hallucination;
3122. 		    if (mixture == POT_WATER && singlepotion->dknown)
3123. 			Sprintf(newbuf, "clears");
3124. 		    else
3125. 			Sprintf(newbuf, "turns %s",
3126. 				hcolor(OBJ_DESCR(objects[mixture])));
3127. 		    pline_The("%spotion%s %s.", oldbuf,
3128. 			      more_than_one ? " that you dipped into" : "",
3129. 			      newbuf);
3130. 		    if(!objects[old_otyp].oc_uname &&
3131. 			!objects[old_otyp].oc_name_known && old_dknown) {
3132. 			struct obj fakeobj;
3133. 			fakeobj = zeroobj;
3134. 			fakeobj.dknown = 1;
3135. 			fakeobj.otyp = old_otyp;
3136. 			fakeobj.oclass = POTION_CLASS;
3137. 			docall(&fakeobj);
3138. 		    }
3139. 		}
3140. 		obj_extract_self(singlepotion);
3141. 		singlepotion = hold_another_object(singlepotion,
3142. 					"You juggle and drop %s!",
3143. 					doname(singlepotion), (const char *)0);
3144. 		update_inventory();
3145. 		}
3146. 
3147. 		return(1);
3148. 	}
3149. 
3150. 	pline("Interesting...");
3151. 	return(1);
3152. }
3153. 
3154. 
3155. void
3156. djinni_from_bottle(obj)
3157. register struct obj *obj;
3158. {
3159. 	struct monst *mtmp;
3160. 	int genie_type;        
3161. 	int chance;
3162. 
3163. #if 0
3164. 	/* KMH -- See comments in monst.c */
3165. 	switch (rn2(4)) {
3166. 		default:
3167. 		case 0: genie_type = PM_DJINNI; break;
3168. 		case 1: genie_type = PM_EFREETI; break;
3169. 		case 2: genie_type = PM_MARID; break;
3170. 		case 3: genie_type = PM_DAO; break;
3171. 	}
3172. #else
3173. 	genie_type = PM_DJINNI;
3174. #endif
3175. 	if(!(mtmp = makemon(&mons[genie_type], u.ux, u.uy, NO_MM_FLAGS))){
3176. 		pline("It turns out to be empty.");
3177. 		return;
3178. 	}
3179. 
3180. 	if (!Blind) {
3181. 		pline("In a cloud of smoke, %s emerges!", a_monnam(mtmp));
3182. 		pline("%s speaks.", Monnam(mtmp));
3183. 	} else {
3184. 		You("smell acrid fumes.");
3185. 		pline("%s speaks.", Something);
3186. 	}
3187. 
3188. 	chance = rn2(5);
3189. 	if (obj->blessed) chance = (chance == 4) ? rnd(4) : 0;
3190. 	else if (obj->cursed) chance = (chance == 0) ? rn2(4) : 4;
3191. 	/* 0,1,2,3,4:  b=80%,5,5,5,5; nc=20%,20,20,20,20; c=5%,5,5,5,80 */
3192. 
3193. 	switch (chance) {
3194. 	case 0 : verbalize("I am in your debt.  I will grant one wish!");
3195. 		makewish();
3196. 		mongone(mtmp);
3197. 		break;
3198. 	case 1 : verbalize("Thank you for freeing me!");
3199. 		(void) tamedog(mtmp, (struct obj *)0);
3200. 		break;
3201. 	case 2 : verbalize("You freed me!");
3202. 		mtmp->mpeaceful = TRUE;
3203. 		set_malign(mtmp);
3204. 		break;
3205. 	case 3 : verbalize("It is about time!");
3206. 		pline("%s vanishes.", Monnam(mtmp));
3207. 		mongone(mtmp);
3208. 		break;
3209. 	default: verbalize("You disturbed me, fool!");
3210. 		break;
3211. 	}
3212. }
3213. 
3214. /* clone a gremlin or mold (2nd arg non-null implies heat as the trigger);
3215.    hit points are cut in half (odd HP stays with original) */
3216. struct monst *
3217. split_mon(mon, mtmp)
3218. struct monst *mon,	/* monster being split */
3219. 	     *mtmp;	/* optional attacker whose heat triggered it */
3220. {
3221. 	struct monst *mtmp2;
3222. 	char reason[BUFSZ];
3223. 
3224. 	reason[0] = '\0';
3225. 	if (mtmp) Sprintf(reason, " from %s heat",
3226. 			  (mtmp == &youmonst) ? (const char *)"your" :
3227. 			      (const char *)s_suffix(mon_nam(mtmp)));
3228. 
3229. 	if (mon == &youmonst) {
3230. 	    mtmp2 = cloneu();
3231. 	    if (mtmp2) {
3232. 		mtmp2->mhpmax = u.mhmax / 2;
3233. 		u.mhmax -= mtmp2->mhpmax;
3234. 		flags.botl = 1;
3235. 		You("multiply%s!", reason);
3236. 	    }
3237. 	} else {
3238. 	    mtmp2 = clone_mon(mon, 0, 0);
3239. 	    if (mtmp2) {
3240. 		mtmp2->mhpmax = mon->mhpmax / 2;
3241. 		mon->mhpmax -= mtmp2->mhpmax;
3242. 		if (canspotmon(mon))
3243. 		    pline("%s multiplies%s!", Monnam(mon), reason);
3244. 	    }
3245. 	}
3246. 	return mtmp2;
3247. }
3248. 
3249. #endif /* OVLB */
3250. 
3251. /*potion.c*/