FANDOM


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.
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*/

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.