Source:NetHack 3.2.0/potion.c

From NetHackWiki
Revision as of 09:18, 4 March 2008 by Kernigh bot (talk | contribs) (NetHack 3.2.0/potion.c moved to Source:NetHack 3.2.0/potion.c: Robot: moved page)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Below is the full text to potion.c from the source code of NetHack 3.2.0. To link to a particular line, write [[NetHack 3.2.0/potion.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

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

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

1.    /*	SCCS Id: @(#)potion.c	3.2	96/03/06	*/
2.    /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3.    /* NetHack may be freely redistributed.  See license for details. */
4.    
5.    #include "hack.h"
6.    
7.    #ifdef OVLB
8.    boolean notonhead = FALSE;
9.    
10.   static NEARDATA int nothing, unkn;
11.   static NEARDATA const char beverages[] = { POTION_CLASS, 0 };
12.   
13.   static long FDECL(itimeout, (long));
14.   static long FDECL(itimeout_incr, (long,int));
15.   static void NDECL(ghost_from_bottle);
16.   static short FDECL(mixtype, (struct obj *,struct obj *));
17.   
18.   /* force `val' to be within valid range for intrinsic timeout value */
19.   static long
20.   itimeout(val)
21.   long val;
22.   {
23.       if (val >= TIMEOUT) val = TIMEOUT;
24.       else if (val < 1) val = 0;
25.   
26.       return val;
27.   }
28.   
29.   /* increment `old' by `incr' and force result to be valid intrinsic timeout */
30.   static long
31.   itimeout_incr(old, incr)
32.   long old;
33.   int incr;
34.   {
35.       return itimeout((old & TIMEOUT) + (long)incr);
36.   }
37.   
38.   /* set the timeout field of intrinsic `which' */
39.   void
40.   set_itimeout(which, val)
41.   long *which, val;
42.   {
43.       *which &= ~TIMEOUT;
44.       *which |= itimeout(val);
45.   }
46.   
47.   /* increment the timeout field of intrinsic `which' */
48.   void
49.   incr_itimeout(which, incr)
50.   long *which;
51.   int incr;
52.   {
53.       set_itimeout(which, itimeout_incr(*which, incr));
54.   }
55.   
56.   void
57.   make_confused(xtime,talk)
58.   long xtime;
59.   boolean talk;
60.   {
61.   	long old = HConfusion;
62.   
63.   	if (!xtime && old) {
64.   		if (talk)
65.   		    You_feel("less %s now.",
66.   			Hallucination ? "trippy" : "confused");
67.   	}
68.   	if ((xtime && !old) || (!xtime && old)) flags.botl = TRUE;
69.   
70.   	set_itimeout(&HConfusion, xtime);
71.   }
72.   
73.   void
74.   make_stunned(xtime,talk)
75.   long xtime;
76.   boolean talk;
77.   {
78.   	long old = HStun;
79.   
80.   	if (!xtime && old) {
81.   		if (talk)
82.   		    You_feel("%s now.",
83.   			Hallucination ? "less wobbly" : "a bit steadier");
84.   	}
85.   	if (xtime && !old) {
86.   		if (talk) You("stagger...");
87.   	}
88.   	if ((!xtime && old) || (xtime && !old)) flags.botl = TRUE;
89.   
90.   	set_itimeout(&HStun, xtime);
91.   }
92.   
93.   void
94.   make_sick(xtime, cause, talk, type)
95.   long xtime;
96.   const char *cause;	/* sickness cause */
97.   boolean talk;
98.   int type;
99.   {
100.  	long old = Sick;
101.  
102.  	if (xtime > 0L) {
103.  	    if (u.usym == S_FUNGUS) return;
104.  	    if (!old) {
105.  		/* newly sick */
106.  		You_feel("deathly sick.");
107.  	    } else {
108.  		/* already sick */
109.  		if (talk) You_feel("%s worse.",
110.  			      xtime <= Sick/2L ? "much" : "even");
111.  	    }
112.  	    set_itimeout(&Sick, xtime);
113.  	    u.usick_type |= type;
114.  	    flags.botl = TRUE;
115.  	} else if (old && (type & u.usick_type)) {
116.  	    /* was sick, now not */
117.  	    u.usick_type &= ~type;
118.  	    if (u.usick_type) { /* only partly cured */
119.  		if (talk) You_feel("somewhat better.");
120.  		set_itimeout(&Sick, Sick * 2); /* approximation */
121.  	    } else {
122.  		if (talk) pline("What a relief!");
123.  		Sick = 0L;		/* set_itimeout(&Sick, 0L) */
124.  	    }
125.  	    flags.botl = TRUE;
126.  	}
127.  
128.  	if (Sick) {
129.  	    exercise(A_CON, FALSE);
130.  	    if (cause) {
131.  		(void) strncpy(u.usick_cause, cause, sizeof(u.usick_cause));
132.  		u.usick_cause[sizeof(u.usick_cause)-1] = 0;
133.  		}
134.  	    else
135.  		u.usick_cause[0] = 0;
136.  	} else
137.  	    u.usick_cause[0] = 0;
138.  }
139.  
140.  void
141.  make_vomiting(xtime, talk)
142.  long xtime;
143.  boolean talk;
144.  {
145.  	long old = Vomiting;
146.  
147.  	if(!xtime && old)
148.  	    if(talk) You_feel("much less nauseous now.");
149.  
150.  	set_itimeout(&Vomiting, xtime);
151.  }
152.  
153.  
154.  void
155.  make_blinded(xtime, talk)
156.  long xtime;
157.  boolean talk;
158.  {
159.  	long old = Blinded;
160.  	boolean changed = FALSE;
161.  
162.  	if (u.usleep) talk = FALSE;
163.  
164.  	if (!xtime && old && !Blindfolded && haseyes(uasmon)) {
165.  	    if (talk) {
166.  		if (Hallucination)
167.  		    pline("Far out!  Everything is all cosmic again!");
168.  		else		   You("can see again.");
169.  	    }
170.  	    changed = TRUE;
171.  	}
172.  	if (xtime && !old && !Blindfolded && haseyes(uasmon)) {
173.  	    if (talk) {
174.  		if (Hallucination)
175.  			pline("Oh, bummer!  Everything is dark!  Help!");
176.  		else
177.  			pline("A cloud of darkness falls upon you.");
178.  	    }
179.  	    changed = TRUE;
180.  
181.  	    /* Before the hero goes blind, set the ball&chain variables. */
182.  	    if (Punished) set_bc(0);
183.  	}
184.  	set_itimeout(&Blinded, xtime);
185.  	if (changed) {
186.  	    flags.botl = 1;
187.  	    vision_full_recalc = 1;
188.  	    if (Telepat) see_monsters();
189.  	}
190.  }
191.  
192.  void
193.  make_hallucinated(xtime, talk, mask)
194.  long xtime;	/* nonzero if this is an attempt to turn on hallucination */
195.  boolean talk;
196.  long mask;	/* nonzero if resistance status should change by mask */
197.  {
198.  	boolean changed = 0;
199.  #ifdef LINT
200.  	const char *message = 0;
201.  #else
202.  	const char *message;
203.  #endif
204.  
205.  	if (!xtime)
206.  	    message = "Everything looks SO boring now.";
207.  	else
208.  	    message = "Oh wow!  Everything seems so cosmic!";
209.  
210.  	if (mask) {
211.  	    if (HHallucination) changed = TRUE;
212.  
213.  	    if (!xtime) HHalluc_resistance |= mask;
214.  	    else HHalluc_resistance &= ~mask;
215.  	} else {
216.  	    if (!HHalluc_resistance && (!!HHallucination != !!xtime))
217.  		changed = TRUE;
218.  	    set_itimeout(&HHallucination, xtime);
219.  	}
220.  
221.  	if (changed) {
222.  	    if (u.uswallow) {
223.  		swallowed(0);	/* redraw swallow display */
224.  	    } else {
225.  		/* The see_* routines should be called *before* the pline. */
226.  		see_monsters();
227.  		see_objects();
228.  	    }
229.  	    flags.botl = 1;
230.  	    if (!Blind && talk) pline(message);
231.  	}
232.  }
233.  
234.  static void
235.  ghost_from_bottle()
236.  {
237.  	struct monst *mtmp = makemon(&mons[PM_GHOST], u.ux, u.uy);
238.  
239.  	if (!mtmp) {
240.  		pline("This bottle turns out to be empty.");
241.  		return;
242.  	}
243.  	if (Blind) {
244.  		pline("As you open the bottle, %s emerges.", something);
245.  		return;
246.  	}
247.  	pline("As you open the bottle, an enormous %s emerges!",
248.  		Hallucination ? rndmonnam() : (const char *)"ghost");
249.  	if(flags.verbose)
250.  	    You("are frightened to death, and unable to move.");
251.  	nomul(-3);
252.  	nomovemsg = "You regain your composure.";
253.  }
254.  
255.  int
256.  dodrink() {
257.  	register struct obj *otmp;
258.  	const char *potion_descr;
259.  
260.  	if (Strangled) {
261.  		pline("If you can't breathe air, how can you drink liquid?");
262.  		return 0;
263.  	}
264.  	/* Is there a fountain to drink from here? */
265.  	if (IS_FOUNTAIN(levl[u.ux][u.uy].typ) && !Levitation) {
266.  		if(yn("Drink from the fountain?") == 'y') {
267.  			drinkfountain();
268.  			return 1;
269.  		}
270.  	}
271.  #ifdef SINKS
272.  	/* Or a kitchen sink? */
273.  	if (IS_SINK(levl[u.ux][u.uy].typ)) {
274.  		if (yn("Drink from the sink?") == 'y') {
275.  			drinksink();
276.  			return 1;
277.  		}
278.  	}
279.  #endif
280.  
281.  	/* Or are you surrounded by water? */
282.  	if (Underwater) {
283.  		if (yn("Drink the water around you?") == 'y') {
284.  		    pline("Do you know what lives in this water!");
285.  			return 1;
286.  		}
287.  	}
288.  
289.  	otmp = getobj(beverages, "drink");
290.  	if(!otmp) return(0);
291.  #ifndef NO_SIGNAL
292.  	otmp->in_use = TRUE;		/* you've opened the stopper */
293.  #endif
294.  #define POTION_OCCUPANT_CHANCE(n) (13 + 2*(n))	/* also in muse.c */
295.  
296.  	potion_descr = OBJ_DESCR(objects[otmp->otyp]);
297.  	if (potion_descr && !strcmp(potion_descr, "milky") &&
298.  		    flags.ghost_count < MAXMONNO &&
299.  		    !rn2(POTION_OCCUPANT_CHANCE(flags.ghost_count))) {
300.  		ghost_from_bottle();
301.  		useup(otmp);
302.  		return(1);
303.  	} else if (potion_descr && !strcmp(potion_descr, "smoky") &&
304.  		    flags.djinni_count < MAXMONNO &&
305.  		    !rn2(POTION_OCCUPANT_CHANCE(flags.djinni_count))) {
306.  		djinni_from_bottle(otmp);
307.  		useup(otmp);
308.  		return(1);
309.  	}
310.  	return dopotion(otmp);
311.  }
312.  
313.  int
314.  dopotion(otmp)
315.  register struct obj *otmp;
316.  {
317.  	int retval;
318.  
319.  	nothing = unkn = 0;
320.  	if((retval = peffects(otmp)) >= 0) return(retval);
321.  
322.  	if(nothing) {
323.  	    unkn++;
324.  	    You("have a %s feeling for a moment, then it passes.",
325.  		  Hallucination ? "normal" : "peculiar");
326.  	}
327.  	if(otmp->dknown && !objects[otmp->otyp].oc_name_known) {
328.  		if(!unkn) {
329.  			makeknown(otmp->otyp);
330.  			more_experienced(0,10);
331.  		} else if(!objects[otmp->otyp].oc_uname)
332.  			docall(otmp);
333.  	}
334.  	useup(otmp);
335.  	return(1);
336.  }
337.  
338.  int
339.  peffects(otmp)
340.  	register struct obj	*otmp;
341.  {
342.  	register int i, ii, lim;
343.  
344.  	switch(otmp->otyp){
345.  	case POT_RESTORE_ABILITY:
346.  	case SPE_RESTORE_ABILITY:
347.  		unkn++;
348.  		if(otmp->cursed) {
349.  		    pline("Ulch!  This makes you feel mediocre!");
350.  		    break;
351.  		} else {
352.  		    pline("Wow!  This makes you feel %s!",
353.  			  (otmp->blessed) ? "great" : "good");
354.  		    i = rn2(A_MAX);		/* start at a random point */
355.  		    for (ii = 0; ii < A_MAX; ii++) {
356.  			lim = AMAX(i);
357.  			if (i == A_STR && u.uhs >= 3) --lim;	/* WEAK */
358.  			if (ABASE(i) < lim) {
359.  			    ABASE(i) = lim;
360.  			    flags.botl = 1;
361.  			    /* only first found if not blessed */
362.  			    if (!otmp->blessed) break;
363.  			}
364.  			if(++i >= A_MAX) i = 0;
365.  		    }
366.  		}
367.  		break;
368.  	case POT_HALLUCINATION:
369.  		if (Hallucination || HHalluc_resistance) nothing++;
370.  		make_hallucinated(itimeout_incr(HHallucination,
371.  					   rn1(200, 600 - 300 * bcsign(otmp))),
372.  				  TRUE, 0L);
373.  		break;
374.  	case POT_WATER:
375.  		if(!otmp->blessed && !otmp->cursed) {
376.  			pline("This tastes like water.");
377.  			u.uhunger += rnd(10);
378.  			newuhs(FALSE);
379.  			break;
380.  		}
381.  		unkn++;
382.  		if(is_undead(uasmon) || is_demon(uasmon) ||
383.  				u.ualign.type == A_CHAOTIC) {
384.  		    if(otmp->blessed) {
385.  			pline("This burns like acid!");
386.  			exercise(A_CON, FALSE);
387.  			if (u.ulycn >= LOW_PM) {
388.  			    Your("affinity to %s disappears!",
389.  				 makeplural(mons[u.ulycn].mname));
390.  			    if (uasmon == &mons[u.ulycn] && !Polymorph_control)
391.  				rehumanize();
392.  			    u.ulycn = NON_PM;
393.  			}
394.  			losehp(d(2,6), "potion of holy water", KILLED_BY_AN);
395.  		    } else if(otmp->cursed) {
396.  			You_feel("quite proud of yourself.");
397.  			healup(d(2,6),0,0,0);
398.  			exercise(A_CON, TRUE);
399.  		    }
400.  		} else
401.  		    if(otmp->blessed) {
402.  			You_feel("full of awe.");
403.  			make_sick(0L, (char *) 0, TRUE, SICK_ALL);
404.  			exercise(A_WIS, TRUE);
405.  			exercise(A_CON, TRUE);
406.  			if (u.ulycn >= LOW_PM) {
407.  			    You_feel("purified.");
408.  			    if (uasmon == &mons[u.ulycn] && !Polymorph_control)
409.  				rehumanize();
410.  			    u.ulycn = NON_PM;
411.  			}
412.  			/* make_confused(0L,TRUE); */
413.  		    } else {
414.  			if(u.ualign.type == A_LAWFUL) {
415.  			    pline("This burns like acid!");
416.  			    losehp(d(2,6), "potion of unholy water",
417.  				KILLED_BY_AN);
418.  			} else
419.  			    You_feel("full of dread.");
420.  			exercise(A_CON, FALSE);
421.  		    }
422.  		break;
423.  	case POT_BOOZE:
424.  		unkn++;
425.  		pline("Ooph!  This tastes like %s%s!",
426.  		      otmp->odiluted ? "watered down " : "",
427.  		      Hallucination ? "dandelion wine" : "liquid fire");
428.  		if (!otmp->blessed)
429.  		    make_confused(itimeout_incr(HConfusion, d(3,8)), FALSE);
430.  		/* the whiskey makes us feel better */
431.  		if (u.uhp < u.uhpmax && !otmp->odiluted)
432.  			losehp(-1, "", 0); /* can't kill you */
433.  		u.uhunger += 10 * (2 + bcsign(otmp));
434.  		newuhs(FALSE);
435.  		exercise(A_WIS, FALSE);
436.  		if(otmp->cursed) {
437.  			You("pass out.");
438.  			multi = -rnd(15);
439.  			nomovemsg = "You awake with a headache.";
440.  		}
441.  		break;
442.  	case POT_ENLIGHTENMENT:
443.  		if(otmp->cursed) {
444.  			unkn++;
445.  			You("have an uneasy feeling...");
446.  			exercise(A_WIS, FALSE);
447.  		} else {
448.  			if (otmp->blessed) {
449.  				(void) adjattrib(A_INT, 1, FALSE);
450.  				(void) adjattrib(A_WIS, 1, FALSE);
451.  			}
452.  			You_feel("self-knowledgeable...");
453.  			display_nhwindow(WIN_MESSAGE, FALSE);
454.  			enlightenment(0);
455.  			pline_The("feeling subsides.");
456.  			exercise(A_WIS, TRUE);
457.  		}
458.  		break;
459.  	case POT_INVISIBILITY:
460.  	case SPE_INVISIBILITY:
461.  		if (Invisible) {		/* no current effect */
462.  		    nothing++;
463.  		} else if (Blind ||		/* current effect sensed */
464.  			(HInvis & I_BLOCKED)) {
465.  		    You_feel("rather airy."),  unkn++;
466.  		} else if (See_invisible) {	/* eyes override sensing */
467.  		    nothing++;
468.  		} else {			/* current effect seen */
469.  		    pline(Hallucination ?
470.  			 "Far out, man!  You can see right through yourself!" :
471.  			 "Gee!  All of a sudden, you can't see yourself.");
472.  		}
473.  		if (otmp->blessed) HInvis |= FROMOUTSIDE;
474.  		else incr_itimeout(&HInvis, rn1(15,31));
475.  		newsym(u.ux,u.uy);	/* update position */
476.  		if(otmp->cursed) {
477.  		    pline("For some reason, you feel your presence is known.");
478.  		    aggravate();
479.  		}
480.  		break;
481.  	case POT_SEE_INVISIBLE:
482.  		/* tastes like fruit juice in Rogue */
483.  	case POT_FRUIT_JUICE:
484.  		unkn++;
485.  		if (otmp->cursed)
486.  		    pline("Yecch!  This tastes %s.",
487.  			  Hallucination ? "overripe" : "rotten");
488.  		else pline(Hallucination ?
489.  		"This tastes like 10%% real %s%s juice all-natural beverage." :
490.  				"This tastes like %s%s juice.",
491.  			  otmp->odiluted ? "reconstituted " : "", pl_fruit);
492.  		if (otmp->otyp == POT_FRUIT_JUICE) {
493.  		    u.uhunger += (otmp->odiluted ? 5 : 10) * (2 + bcsign(otmp));
494.  		    newuhs(FALSE);
495.  		    break;
496.  		}
497.  		if (!otmp->cursed) {
498.  			/* Tell them they can see again immediately, which
499.  			 * will help them identify the potion...
500.  			 */
501.  			make_blinded(0L,TRUE);
502.  		}
503.  		if (otmp->blessed)
504.  			HSee_invisible |= FROMOUTSIDE;
505.  		else
506.  			incr_itimeout(&HSee_invisible, rn1(100,750));
507.  		set_mimic_blocking(); /* do special mimic handling */
508.  		see_monsters();	/* see invisible monsters */
509.  		newsym(u.ux,u.uy); /* see yourself! */
510.  		break;
511.  	case POT_PARALYSIS:
512.  		if (Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz))
513.  		    You("are motionlessly suspended.");
514.  		else
515.  		    Your("%s are frozen to the %s!",
516.  			 makeplural(body_part(FOOT)), surface(u.ux, u.uy));
517.  		nomul(-(rn1(10, 25 - 12*bcsign(otmp))));
518.  		exercise(A_DEX, FALSE);
519.  		break;
520.  	case POT_MONSTER_DETECTION:
521.  	case SPE_DETECT_MONSTERS:
522.  		if (monster_detect(otmp, 0))
523.  			return(1);		/* nothing detected */
524.  		exercise(A_WIS, TRUE);
525.  		break;
526.  	case POT_OBJECT_DETECTION:
527.  	case SPE_DETECT_TREASURE:
528.  		if (object_detect(otmp, 0))
529.  			return(1);		/* nothing detected */
530.  		exercise(A_WIS, TRUE);
531.  		break;
532.  	case POT_SICKNESS:
533.  		pline("Yecch!  This stuff tastes like poison.");
534.  		if (otmp->blessed) {
535.  		    pline("(But in fact it was mildly stale %s juice.)",
536.  			  pl_fruit);
537.  		    if (!Role_is('H'))
538.  			losehp(1, "mildly contaminated potion", KILLED_BY_AN);
539.  		} else {
540.  		    if(Poison_resistance)
541.  			pline(
542.  		    "(But in fact it was biologically contaminated %s juice.)",
543.  			      pl_fruit);
544.  		    if (Role_is('H'))
545.  			pline("Fortunately, you have been immunized.");
546.  		    else {
547.  			int typ = rn2(A_MAX);
548.  			poisontell(typ);
549.  			(void) adjattrib(typ,
550.  					Poison_resistance ? -1 : -rn1(4,3),
551.  					TRUE);
552.  			if(!Poison_resistance)
553.  				losehp(rnd(10)+5*!!(otmp->cursed),
554.  				       "contaminated potion", KILLED_BY_AN);
555.  			exercise(A_CON, FALSE);
556.  		    }
557.  		}
558.  		if(Hallucination) {
559.  			You("are shocked back to your senses!");
560.  			make_hallucinated(0L,FALSE,0L);
561.  		}
562.  		break;
563.  	case POT_CONFUSION:
564.  		if(!Confusion)
565.  		    if (Hallucination) {
566.  			pline("What a trippy feeling!");
567.  			unkn++;
568.  		    } else
569.  			pline("Huh, What?  Where am I?");
570.  		else	nothing++;
571.  		make_confused(itimeout_incr(HConfusion,
572.  					    rn1(7, 16 - 8 * bcsign(otmp))),
573.  			      FALSE);
574.  		break;
575.  	case POT_GAIN_ABILITY:
576.  		if(otmp->cursed) {
577.  		    pline("Ulch!  That potion tasted foul!");
578.  		    unkn++;
579.  		} else {      /* If blessed, increase all; if not, try up to */
580.  		    int itmp; /* 6 times to find one which can be increased. */
581.  		    i = -1;		/* increment to 0 */
582.  		    for (ii = A_MAX; ii > 0; ii--) {
583.  			i = (otmp->blessed ? i + 1 : rn2(A_MAX));
584.  			/* only give "your X is already as high as it can get"
585.  			   message on last attempt (except blessed potions) */
586.  			itmp = (otmp->blessed || ii == 1) ? 0 : -1;
587.  			if (adjattrib(i, 1, itmp) && !otmp->blessed)
588.  			    break;
589.  		    }
590.  		}
591.  		break;
592.  	case POT_SPEED:
593.  		if(Wounded_legs && !otmp->cursed) {
594.  			heal_legs();
595.  			unkn++;
596.  			break;
597.  		}		/* and fall through */
598.  	case SPE_HASTE_SELF:
599.  		if(!(Fast & ~INTRINSIC)) /* wwf@doe.carleton.ca */
600.  			You("are suddenly moving %sfaster.",
601.  				Fast ? "" : "much ");
602.  		else {
603.  			Your("%s get new energy.",
604.  				makeplural(body_part(LEG)));
605.  			unkn++;
606.  		}
607.  		exercise(A_DEX, TRUE);
608.  		incr_itimeout(&Fast, rn1(10, 100 + 60 * bcsign(otmp)));
609.  		break;
610.  	case POT_BLINDNESS:
611.  		if(Blind) nothing++;
612.  		make_blinded(itimeout_incr(Blinded,
613.  					   rn1(200, 250 - 125 * bcsign(otmp))),
614.  			     TRUE);
615.  		break;
616.  	case POT_GAIN_LEVEL:
617.  		if (otmp->cursed) {
618.  			unkn++;
619.  			/* they went up a level */
620.  			if((ledger_no(&u.uz) == 1 && u.uhave.amulet) ||
621.  				Can_rise_up(u.ux, u.uy, &u.uz)) {
622.  			    const char *riseup ="rise up, through the %s!";
623.  			    if(ledger_no(&u.uz) == 1) {
624.  			        You(riseup, ceiling(u.ux,u.uy));
625.  				goto_level(&earth_level, FALSE, FALSE, FALSE);
626.  			    } else {
627.  			        register int newlev = depth(&u.uz)-1;
628.  				d_level newlevel;
629.  
630.  				get_level(&newlevel, newlev);
631.  				if(on_level(&newlevel, &u.uz)) {
632.  				    pline("It tasted bad.");
633.  				    break;
634.  				} else You(riseup, ceiling(u.ux,u.uy));
635.  				goto_level(&newlevel, FALSE, FALSE, FALSE);
636.  			    }
637.  			}
638.  			else You("have an uneasy feeling.");
639.  			break;
640.  		}
641.  		pluslvl();
642.  		if (otmp->blessed)
643.  			/* blessed potions place you at a random spot in the
644.  			 * middle of the new level instead of the low point
645.  			 */
646.  			u.uexp = rndexp();
647.  		break;
648.  	case POT_HEALING:
649.  		You_feel("better.");
650.  		healup(d(6 + 2 * bcsign(otmp), 4),
651.  		       !otmp->cursed ? 1 : 0, !!otmp->blessed, !otmp->cursed);
652.  		exercise(A_CON, TRUE);
653.  		break;
654.  	case POT_EXTRA_HEALING:
655.  		You_feel("much better.");
656.  		healup(d(6 + 2 * bcsign(otmp), 8),
657.  		       otmp->blessed ? 5 : !otmp->cursed ? 2 : 0,
658.  		       !otmp->cursed, TRUE);
659.  		make_hallucinated(0L,TRUE,0L);
660.  		exercise(A_CON, TRUE);
661.  		exercise(A_STR, TRUE);
662.  		break;
663.  	case POT_LEVITATION:
664.  	case SPE_LEVITATION:
665.  		if (otmp->cursed) HLevitation &= ~I_SPECIAL;
666.  		if(!Levitation) {
667.  			/* kludge to ensure proper operation of float_up() */
668.  			HLevitation = 1;
669.  			float_up();
670.  			/* reverse kludge */
671.  			HLevitation = 0;
672.  			if (otmp->cursed && !Is_waterlevel(&u.uz)) {
673.  	if((u.ux != xupstair || u.uy != yupstair)
674.  	   && (u.ux != sstairs.sx || u.uy != sstairs.sy || !sstairs.up)
675.  	   && (!xupladder || u.ux != xupladder || u.uy != yupladder)
676.  	) {
677.  					You("hit your %s on the %s.",
678.  						body_part(HEAD),
679.  						ceiling(u.ux,u.uy));
680.  					losehp(uarmh ? 1 : rnd(10),
681.  						"colliding with the ceiling",
682.  						KILLED_BY);
683.  				} else (void) doup();
684.  			}
685.  		} else
686.  			nothing++;
687.  		if (otmp->blessed) {
688.  		    incr_itimeout(&HLevitation, rn1(50,250));
689.  		    HLevitation |= I_SPECIAL;
690.  		} else incr_itimeout(&HLevitation, rn1(140,10));
691.  		break;
692.  	case POT_GAIN_ENERGY:			/* M. Stephenson */
693.  		{	register int num;
694.  			if(otmp->cursed)
695.  			    You_feel("lackluster.");
696.  			else
697.  			    pline("Magical energies course through your body.");
698.  			num = rnd(5) + 5 * otmp->blessed + 1;
699.  			u.uenmax += (otmp->cursed) ? -num : num;
700.  			u.uen += (otmp->cursed) ? -num : num;
701.  			if(u.uenmax <= 0) u.uenmax = 0;
702.  			if(u.uen <= 0) u.uen = 0;
703.  			flags.botl = 1;
704.  			exercise(A_WIS, TRUE);
705.  		}
706.  		break;
707.  	case POT_OIL:				/* P. Winner */
708.  		{
709.  			boolean good_for_you = FALSE;
710.  
711.  			if (otmp->lamplit) {
712.  			    if (likes_fire(uasmon)) {
713.  				pline("Ahh, a refreshing drink.");
714.  				good_for_you = TRUE;
715.  			    } else {
716.  				You("burn your %s", body_part(FACE));
717.  				losehp(d(Fire_resistance ? 1 : 3, 4),
718.  				       "burning potion of oil", KILLED_BY_AN);
719.  			    }
720.  			} else if(otmp->cursed)
721.  			    pline("This tastes like castor oil.");
722.  			else
723.  			    pline("That was smooth!");
724.  			exercise(A_WIS, good_for_you);
725.  		}
726.  		break;
727.  	default:
728.  		impossible("What a funny potion! (%u)", otmp->otyp);
729.  		return(0);
730.  	}
731.  	return(-1);
732.  }
733.  
734.  void
735.  healup(nhp, nxtra, curesick, cureblind)
736.  	int nhp, nxtra;
737.  	register boolean curesick, cureblind;
738.  {
739.  	if (nhp) {
740.  		if (u.mtimedone) {
741.  			u.mh += nhp;
742.  			if (u.mh > u.mhmax) u.mh = (u.mhmax += nxtra);
743.  		} else {
744.  			u.uhp += nhp;
745.  			if(u.uhp > u.uhpmax) u.uhp = (u.uhpmax += nxtra);
746.  		}
747.  	}
748.  	if(cureblind)	make_blinded(0L,TRUE);
749.  	if(curesick)	make_sick(0L, (char *) 0, TRUE, SICK_ALL);
750.  	flags.botl = 1;
751.  	return;
752.  }
753.  
754.  void
755.  strange_feeling(obj,txt)
756.  register struct obj *obj;
757.  register const char *txt;
758.  {
759.  	if(flags.beginner)
760.  		You("have a %s feeling for a moment, then it passes.",
761.  		Hallucination ? "normal" : "strange");
762.  	else
763.  		pline(txt);
764.  
765.  	if(!obj)	/* e.g., crystal ball finds no traps */
766.  		return;
767.  
768.  	if(obj->dknown && !objects[obj->otyp].oc_name_known &&
769.  						!objects[obj->otyp].oc_uname)
770.  		docall(obj);
771.  	useup(obj);
772.  }
773.  
774.  const char *bottlenames[] = {
775.  	"bottle", "phial", "flagon", "carafe", "flask", "jar", "vial"
776.  };
777.  
778.  void
779.  potionhit(mon, obj)
780.  register struct monst *mon;
781.  register struct obj *obj;
782.  {
783.  	register const char *botlnam = bottlenames[rn2(SIZE(bottlenames))];
784.  	boolean isyou = (mon == &youmonst);
785.  	int distance;
786.  
787.  	if(isyou) {
788.  		distance = 0;
789.  		pline_The("%s crashes on your %s and breaks into shards.",
790.  			botlnam, body_part(HEAD));
791.  		losehp(rnd(2), "thrown potion", KILLED_BY_AN);
792.  	} else {
793.  		distance = distu(mon->mx,mon->my);
794.  		if (mon->msleep) mon->msleep = 0;
795.  		if (!cansee(mon->mx,mon->my)) pline("Crash!");
796.  		else {
797.  		    char *mnam = mon_nam(mon);
798.  		    char buf[BUFSZ];
799.  
800.  		    if(has_head(mon->data)) {
801.  			Sprintf(buf, "%s %s",
802.  				s_suffix(mnam),
803.  				(notonhead ? "body" : "head"));
804.  		    } else {
805.  			Strcpy(buf, mnam);
806.  		    }
807.  		    pline_The("%s crashes on %s and breaks into shards.",
808.  			   botlnam, buf);
809.  		}
810.  		if(rn2(5) && mon->mhp > 1)
811.  			mon->mhp--;
812.  	}
813.  
814.  	/* oil doesn't instantly evaporate */
815.  	if (obj->otyp != POT_OIL && cansee(mon->mx,mon->my))
816.  		pline("%s evaporates.", The(xname(obj)));
817.  
818.  	if (isyou) switch (obj->otyp) {
819.  	    case POT_OIL:
820.  		if (obj->lamplit)
821.  		    splatter_burning_oil(u.ux, u.uy);
822.  		break;
823.  	    }
824.  	else switch (obj->otyp) {
825.  
826.  	case POT_RESTORE_ABILITY:
827.  	case POT_GAIN_ABILITY:
828.  	case POT_HEALING:
829.  	case POT_EXTRA_HEALING:
830.  		if(mon->mhp < mon->mhpmax) {
831.  		    mon->mhp = mon->mhpmax;
832.  		    if (canseemon(mon))
833.  			pline("%s looks sound and hale again.", Monnam(mon));
834.  		}
835.  		break;
836.  	case POT_SICKNESS:
837.  		if((mon->mhpmax > 3) && !resist(mon, POTION_CLASS, 0, NOTELL))
838.  			mon->mhpmax /= 2;
839.  		if((mon->mhp > 2) && !resist(mon, POTION_CLASS, 0, NOTELL))
840.  			mon->mhp /= 2;
841.  		if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax;
842.  		if (canseemon(mon))
843.  		    pline("%s looks rather ill.", Monnam(mon));
844.  		break;
845.  	case POT_CONFUSION:
846.  	case POT_BOOZE:
847.  		if(!resist(mon, POTION_CLASS, 0, NOTELL))  mon->mconf = TRUE;
848.  		break;
849.  	case POT_INVISIBILITY:
850.  		mon_set_minvis(mon);
851.  		break;
852.  	case POT_PARALYSIS:
853.  		if (mon->mcanmove) {
854.  			mon->mcanmove = 0;
855.  			/* really should be rnd(5) for consistency with players
856.  			 * breathing potions, but...
857.  			 */
858.  			mon->mfrozen = rnd(25);
859.  		}
860.  		break;
861.  	case POT_SPEED:
862.  		if (mon->mspeed == MSLOW) mon->mspeed = 0;
863.  		else mon->mspeed = MFAST;
864.  		break;
865.  	case POT_BLINDNESS:
866.  		if(haseyes(mon->data)) {
867.  		    register int btmp = 64 + rn2(32) +
868.  			rn2(32) * !resist(mon, POTION_CLASS, 0, NOTELL);
869.  		    btmp += mon->mblinded;
870.  		    mon->mblinded = min(btmp,127);
871.  		    mon->mcansee = 0;
872.  		}
873.  		break;
874.  	case POT_WATER:
875.  		if (is_undead(mon->data) || is_demon(mon->data)) {
876.  			if (obj->blessed) {
877.  				pline("%s shrieks in pain!", Monnam(mon));
878.  				mon->mhp -= d(2,6);
879.  				if (mon->mhp <1) killed(mon);
880.  			} else if (obj->cursed) {
881.  				if (canseemon(mon))
882.  				    pline("%s looks healthier.", Monnam(mon));
883.  				mon->mhp += d(2,6);
884.  				if (mon->mhp > mon->mhpmax)
885.  					mon->mhp = mon->mhpmax;
886.  			}
887.  		} else if(mon->data == &mons[PM_GREMLIN]) {
888.  			struct monst *mtmp2 = clone_mon(mon);
889.  
890.  			if (mtmp2) {
891.  				mtmp2->mhpmax = (mon->mhpmax /= 2);
892.  				if (canseemon(mon))
893.  					pline("%s multiplies.", Monnam(mon));
894.  			}
895.  		}
896.  		break;
897.  	case POT_OIL:
898.  		if (obj->lamplit)
899.  			splatter_burning_oil(mon->mx, mon->my);
900.  		break;
901.  /*
902.  	case POT_GAIN_LEVEL:
903.  	case POT_LEVITATION:
904.  	case POT_FRUIT_JUICE:
905.  	case POT_MONSTER_DETECTION:
906.  	case POT_OBJECT_DETECTION:
907.  		break;
908.  */
909.  	}
910.  	/* Note: potionbreathe() does its own docall() */
911.  	if (distance==0 || ((distance < 3) && rn2(5)))
912.  		potionbreathe(obj);
913.  	else if (obj->dknown && !objects[obj->otyp].oc_name_known &&
914.  		   !objects[obj->otyp].oc_uname && cansee(mon->mx,mon->my))
915.  		docall(obj);
916.  	if(*u.ushops && obj->unpaid) {
917.  	        register struct monst *shkp =
918.  			shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE));
919.  
920.  		if(!shkp)
921.  		    obj->unpaid = 0;
922.  		else {
923.  		    (void)stolen_value(obj, u.ux, u.uy,
924.  				 (boolean)shkp->mpeaceful, FALSE);
925.  		    subfrombill(obj, shkp);
926.  		}
927.  	}
928.  	obfree(obj, (struct obj *)0);
929.  }
930.  
931.  void
932.  potionbreathe(obj)
933.  register struct obj *obj;
934.  {
935.  	register int i, ii, isdone, kn = 0;
936.  
937.  	switch(obj->otyp) {
938.  	case POT_RESTORE_ABILITY:
939.  	case POT_GAIN_ABILITY:
940.  		if(obj->cursed) {
941.  		    pline("Ulch!  That potion smells terrible!");
942.  		    break;
943.  		} else {
944.  		    i = rn2(A_MAX);		/* start at a random point */
945.  		    for(isdone = ii = 0; !isdone && ii < A_MAX; ii++) {
946.  			if(ABASE(i) < AMAX(i)) {
947.  			    ABASE(i)++;
948.  			    /* only first found if not blessed */
949.  			    isdone = !(obj->blessed);
950.  			    flags.botl = 1;
951.  			}
952.  			if(++i >= A_MAX) i = 0;
953.  		    }
954.  		}
955.  		break;
956.  	case POT_EXTRA_HEALING:
957.  		if (u.uhp < u.uhpmax) u.uhp++, flags.botl = 1;
958.  		/*FALL THROUGH*/
959.  	case POT_HEALING:
960.  		if (u.uhp < u.uhpmax) u.uhp++, flags.botl = 1;
961.  		exercise(A_CON, TRUE);
962.  		break;
963.  	case POT_SICKNESS:
964.  		if (!Role_is('H')) {
965.  			if(u.uhp <= 5) u.uhp = 1; else u.uhp -= 5;
966.  			flags.botl = 1;
967.  			exercise(A_CON, FALSE);
968.  		}
969.  		break;
970.  	case POT_HALLUCINATION:
971.  		You("have a momentary vision.");
972.  		break;
973.  	case POT_CONFUSION:
974.  	case POT_BOOZE:
975.  		if(!Confusion)
976.  			You_feel("somewhat dizzy.");
977.  		make_confused(itimeout_incr(HConfusion, rnd(5)), FALSE);
978.  		break;
979.  	case POT_INVISIBILITY:
980.  		if (!See_invisible && !Invis)
981.  			pline("For an instant you could see through yourself!");
982.  		break;
983.  	case POT_PARALYSIS:
984.  		kn++;
985.  		pline("%s seems to be holding you.", Something);
986.  		nomul(-rnd(5));
987.  		exercise(A_DEX, FALSE);
988.  		break;
989.  	case POT_SPEED:
990.  		if (!Fast) Your("knees seem more flexible now.");
991.  		incr_itimeout(&Fast, rnd(5));
992.  		exercise(A_DEX, TRUE);
993.  		break;
994.  	case POT_BLINDNESS:
995.  		if (!Blind && !u.usleep) {
996.  		    kn++;
997.  		    pline("It suddenly gets dark.");
998.  		}
999.  		make_blinded(itimeout_incr(Blinded, rnd(5)), FALSE);
1000. 		break;
1001. 	case POT_WATER:
1002. 		if(u.umonnum == PM_GREMLIN) {
1003. 		    struct monst *mtmp;
1004. 		    if ((mtmp = cloneu()) != 0) {
1005. 			mtmp->mhpmax = (u.mhmax /= 2);
1006. 			You("multiply.");
1007. 		    }
1008. 		}
1009. /*
1010. 	case POT_GAIN_LEVEL:
1011. 	case POT_LEVITATION:
1012. 	case POT_FRUIT_JUICE:
1013. 	case POT_MONSTER_DETECTION:
1014. 	case POT_OBJECT_DETECTION:
1015. 	case POT_OIL:
1016. */
1017. 		break;
1018. 	}
1019. 	/* note: no obfree() */
1020. 	if (obj->dknown)
1021. 	    if (kn)
1022. 		makeknown(obj->otyp);
1023. 	    else if (!objects[obj->otyp].oc_name_known &&
1024. 						!objects[obj->otyp].oc_uname)
1025. 		docall(obj);
1026. }
1027. 
1028. static short
1029. mixtype(o1, o2)
1030. register struct obj *o1, *o2;
1031. /* returns the potion type when o1 is dipped in o2 */
1032. {
1033. 	/* cut down on the number of cases below */
1034. 	if (o1->oclass == POTION_CLASS &&
1035. 	    (o2->otyp == POT_GAIN_LEVEL ||
1036. 	     o2->otyp == POT_GAIN_ENERGY ||
1037. 	     o2->otyp == POT_HEALING ||
1038. 	     o2->otyp == POT_EXTRA_HEALING ||
1039. 	     o2->otyp == POT_ENLIGHTENMENT ||
1040. 	     o2->otyp == POT_FRUIT_JUICE)) {
1041. 		struct obj *swp;
1042. 
1043. 		swp = o1; o1 = o2; o2 = swp;
1044. 	}
1045. 
1046. 	switch (o1->otyp) {
1047. 		case POT_HEALING:
1048. 			switch (o2->otyp) {
1049. 			    case POT_SPEED:
1050. 			    case POT_GAIN_LEVEL:
1051. 			    case POT_GAIN_ENERGY:
1052. 				return POT_EXTRA_HEALING;
1053. 			}
1054. 		case POT_EXTRA_HEALING:
1055. 			switch (o2->otyp) {
1056. 			    case POT_GAIN_LEVEL:
1057. 			    case POT_GAIN_ENERGY:
1058. 				return POT_GAIN_ABILITY;
1059. 			}
1060. 		case UNICORN_HORN:
1061. 			switch (o2->otyp) {
1062. 			    case POT_SICKNESS:
1063. 				return POT_FRUIT_JUICE;
1064. 			    case POT_HALLUCINATION:
1065. 			    case POT_BLINDNESS:
1066. 			    case POT_CONFUSION:
1067. 				return POT_WATER;
1068. 			}
1069. 			break;
1070. 		case AMETHYST:		/* "a-methyst" == "not intoxicated" */
1071. 			if (o2->otyp == POT_BOOZE)
1072. 			    return POT_FRUIT_JUICE;
1073. 			break;
1074. 		case POT_GAIN_LEVEL:
1075. 		case POT_GAIN_ENERGY:
1076. 			switch (o2->otyp) {
1077. 			    case POT_CONFUSION:
1078. 				return (rn2(3) ? POT_BOOZE : POT_ENLIGHTENMENT);
1079. 			    case POT_HEALING:
1080. 				return POT_EXTRA_HEALING;
1081. 			    case POT_EXTRA_HEALING:
1082. 				return POT_GAIN_ABILITY;
1083. 			    case POT_FRUIT_JUICE:
1084. 				return POT_SEE_INVISIBLE;
1085. 			    case POT_BOOZE:
1086. 				return POT_HALLUCINATION;
1087. 			}
1088. 			break;
1089. 		case POT_FRUIT_JUICE:
1090. 			switch (o2->otyp) {
1091. 			    case POT_SICKNESS:
1092. 				return POT_SICKNESS;
1093. 			    case POT_SPEED:
1094. 				return POT_BOOZE;
1095. 			    case POT_GAIN_LEVEL:
1096. 			    case POT_GAIN_ENERGY:
1097. 				return POT_SEE_INVISIBLE;
1098. 			}
1099. 			break;
1100. 		case POT_ENLIGHTENMENT:
1101. 			switch (o2->otyp) {
1102. 			    case POT_LEVITATION:
1103. 				if (rn2(3)) return POT_GAIN_LEVEL;
1104. 				break;
1105. 			    case POT_FRUIT_JUICE:
1106. 				return POT_BOOZE;
1107. 			    case POT_BOOZE:
1108. 				return POT_CONFUSION;
1109. 			}
1110. 			break;
1111. 	}
1112. 
1113. 	return 0;
1114. }
1115. 
1116. 
1117. boolean
1118. get_wet(obj)
1119. register struct obj *obj;
1120. /* returns TRUE if something happened (potion should be used up) */
1121. {
1122. 	if(snuff_lit(obj)) return(TRUE);
1123. 
1124. 	if (obj->greased) {
1125. 		grease_protect(obj,(char *)0,FALSE);
1126. 		return(FALSE);
1127. 	}
1128. 	switch (obj->oclass) {
1129. 	    case WEAPON_CLASS:
1130. 		if (!obj->oerodeproof && is_rustprone(obj) &&
1131. 		    (obj->oeroded < MAX_ERODE) && !rn2(10)) {
1132. 			Your("%s some%s.", aobjnam(obj, "rust"),
1133. 			     obj->oeroded ? " more" : "what");
1134. 			obj->oeroded++;
1135. 			return TRUE;
1136. 		} else break;
1137. 	    case POTION_CLASS:
1138. 		if (obj->otyp == POT_WATER) return FALSE;
1139. 		Your("%s%s.", aobjnam(obj,"dilute"),
1140. 			obj->odiluted ? " further" : "");
1141. 		if (obj->odiluted) {
1142. 			obj->odiluted = 0;
1143. #ifdef UNIXPC
1144. 			obj->blessed = FALSE;
1145. 			obj->cursed = FALSE;
1146. #else
1147. 			obj->blessed = obj->cursed = FALSE;
1148. #endif
1149. 			obj->otyp = POT_WATER;
1150. 		} else obj->odiluted++;
1151. 		return TRUE;
1152. 	    case SCROLL_CLASS:
1153. 		if (obj->otyp != SCR_BLANK_PAPER
1154. #ifdef MAIL
1155. 		    && obj->otyp != SCR_MAIL
1156. #endif
1157. 		    ) {
1158. 			if (!Blind) {
1159. 				boolean oq1 = obj->quan == 1L;
1160. 				pline_The("scroll%s fade%s.",
1161. 					oq1 ? "" : "s",
1162. 					oq1 ? "s" : "");
1163. 			}
1164. 			if(obj->unpaid) {
1165. 			    subfrombill(obj, shop_keeper(*u.ushops));
1166. 			    You("erase it, you pay for it.");
1167. 			    bill_dummy_object(obj);
1168. 			}
1169. 			obj->otyp = SCR_BLANK_PAPER;
1170. 			obj->spe = 0;
1171. 			return TRUE;
1172. 		} else break;
1173. 	    case SPBOOK_CLASS:
1174. 		if (obj->otyp != SPE_BLANK_PAPER) {
1175. 
1176. 			if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
1177. 	pline("%s suddenly heats up; steam rises and it remains dry.",
1178. 				The(xname(obj)));
1179. 			} else {
1180. 			    if (!Blind) {
1181. 				    boolean oq1 = obj->quan == 1L;
1182. 				    pline_The("spellbook%s fade%s.",
1183. 					oq1 ? "" : "s", oq1 ? "s" : "");
1184. 			    }
1185. 			    if(obj->unpaid) {
1186. 			        subfrombill(obj, shop_keeper(*u.ushops));
1187. 			        You("erase it, you pay for it.");
1188. 			        bill_dummy_object(obj);
1189. 			    }
1190. 			    obj->otyp = SPE_BLANK_PAPER;
1191. 			}
1192. 			return TRUE;
1193. 		}
1194. 	}
1195. 	Your("%s wet.", aobjnam(obj,"get"));
1196. 	return FALSE;
1197. }
1198. 
1199. int
1200. dodip()
1201. {
1202. 	register struct obj *potion, *obj;
1203. 	const char *tmp;
1204. 	uchar here;
1205. 	char allowall[2];
1206. 	short mixture;
1207. 	char qbuf[QBUFSZ];
1208. 
1209. 	allowall[0] = ALL_CLASSES; allowall[1] = '\0';
1210. 	if(!(obj = getobj(allowall, "dip")))
1211. 		return(0);
1212. 
1213. 	here = levl[u.ux][u.uy].typ;
1214. 	/* Is there a fountain to dip into here? */
1215. 	if (IS_FOUNTAIN(here)) {
1216. 		if(yn("Dip it into the fountain?") == 'y') {
1217. 			dipfountain(obj);
1218. 			return(1);
1219. 		}
1220. 	} else if (is_pool(u.ux,u.uy)) {
1221. 		tmp = (here == POOL) ? "pool" : "moat";
1222. 		Sprintf(qbuf, "Dip it into the %s?", tmp);
1223. 		if (yn(qbuf) == 'y') {
1224. 		    if (Levitation)
1225. 			floating_above(tmp);
1226. 		    else
1227. 			(void) get_wet(obj);
1228. 		    return 1;
1229. 		}
1230. 	}
1231. 
1232. 	if(!(potion = getobj(beverages, "dip into")))
1233. 		return(0);
1234. 	if (potion == obj && potion->quan == 1L) {
1235. 		pline("That is a potion bottle, not a Klein bottle!");
1236. 		return 0;
1237. 	}
1238. 	if(potion->otyp == POT_WATER) {
1239. 		if (potion->blessed) {
1240. 			if (obj->cursed) {
1241. 				if (!Blind)
1242. 				    Your("%s %s.",
1243. 					  aobjnam(obj, "softly glow"),
1244. 					  hcolor(amber));
1245. 				uncurse(obj);
1246. 				obj->bknown=1;
1247. 	poof:
1248. 				if(!(objects[potion->otyp].oc_name_known) &&
1249. 				   !(objects[potion->otyp].oc_uname))
1250. 					docall(potion);
1251. 				useup(potion);
1252. 				return(1);
1253. 			} else if(!obj->blessed) {
1254. 				if (!Blind) {
1255. 				    tmp = hcolor(light_blue);
1256. 				    Your("%s with a%s %s aura.",
1257. 					  aobjnam(obj, "softly glow"),
1258. 					  index(vowels, *tmp) ? "n" : "", tmp);
1259. 				}
1260. 				bless(obj);
1261. 				obj->bknown=1;
1262. 				goto poof;
1263. 			}
1264. 		} else if (potion->cursed) {
1265. 			if (obj->blessed) {
1266. 				if (!Blind)
1267. 				    Your("%s %s.", aobjnam(obj, "glow"),
1268. 				     hcolor((const char *)"brown"));
1269. 				unbless(obj);
1270. 				obj->bknown=1;
1271. 				goto poof;
1272. 			} else if(!obj->cursed) {
1273. 				if (!Blind) {
1274. 				    tmp = hcolor(Black);
1275. 				    Your("%s with a%s %s aura.",
1276. 					  aobjnam(obj, "glow"),
1277. 					  index(vowels, *tmp) ? "n" : "", tmp);
1278. 				}
1279. 				curse(obj);
1280. 				obj->bknown=1;
1281. 				goto poof;
1282. 			}
1283. 		} else
1284. 			if (get_wet(obj))
1285. 			    goto poof;
1286. 	}
1287. 	else if(obj->oclass == POTION_CLASS && obj->otyp != potion->otyp) {
1288. 		/* Mixing potions is dangerous... */
1289. 		pline_The("potions mix...");
1290. 		if (obj->cursed || !rn2(10)) {
1291. 			pline("BOOM!  They explode!");
1292. 			exercise(A_STR, FALSE);
1293. 			potionbreathe(obj);
1294. 			useup(obj);
1295. 			useup(potion);
1296. 			losehp(rnd(10), "alchemic blast", KILLED_BY_AN);
1297. 			return(1);
1298. 		}
1299. 
1300. 		obj->blessed = obj->cursed = obj->bknown = 0;
1301. 		if (Blind || Hallucination) obj->dknown = 0;
1302. 
1303. 		if ((mixture = mixtype(obj, potion)) != 0) {
1304. 			obj->otyp = mixture;
1305. 		} else {
1306. 		    switch (obj->odiluted ? 1 : rnd(8)) {
1307. 			case 1:
1308. 				obj->otyp = POT_WATER;
1309. 				break;
1310. 			case 2:
1311. 			case 3:
1312. 				obj->otyp = POT_SICKNESS;
1313. 				break;
1314. 			case 4:
1315. 				{
1316. 				  struct obj *otmp;
1317. 				  otmp = mkobj(POTION_CLASS,FALSE);
1318. 				  obj->otyp = otmp->otyp;
1319. 				  obfree(otmp, (struct obj *)0);
1320. 				}
1321. 				break;
1322. 			default:
1323. 				if (!Blind)
1324. 			  pline_The("mixture glows brightly and evaporates.");
1325. 				useup(obj);
1326. 				useup(potion);
1327. 				return(1);
1328. 		    }
1329. 		}
1330. 
1331. 
1332. 		obj->odiluted = (obj->otyp != POT_WATER);
1333. 
1334. 		if (obj->otyp == POT_WATER && !Hallucination) {
1335. 			pline_The("mixture bubbles%s.",
1336. 				Blind ? "" : ", then clears");
1337. 		} else if (!Blind) {
1338. 			pline_The("mixture looks %s.",
1339. 				hcolor(OBJ_DESCR(objects[obj->otyp])));
1340. 		}
1341. 
1342. 		useup(potion);
1343. 		return(1);
1344. 	}
1345. 
1346. 	if(obj->oclass == WEAPON_CLASS && obj->otyp <= SHURIKEN) {
1347. 	    if(potion->otyp == POT_SICKNESS && !obj->opoisoned) {
1348. 		char buf[BUFSZ];
1349. 		Strcpy(buf, The(xname(potion)));
1350. 		pline("%s form%s a coating on %s.",
1351. 			buf, potion->quan == 1L ? "s" : "", the(xname(obj)));
1352. 		obj->opoisoned = TRUE;
1353. 		goto poof;
1354. 	    } else if(obj->opoisoned &&
1355. 		      (potion->otyp == POT_HEALING ||
1356. 		       potion->otyp == POT_EXTRA_HEALING)) {
1357. 		pline("A coating wears off %s.", the(xname(obj)));
1358. 		obj->opoisoned = 0;
1359. 		goto poof;
1360. 	    }
1361. 	}
1362. 	if((obj->oclass == WEAPON_CLASS) && (potion->otyp == POT_OIL)) {
1363. 	    if (potion->lamplit) {	/* burning */
1364. 		if (obj->oerodeproof) {
1365. 		    Your("%s burns for a moment.", xname(obj));
1366. 		} else {
1367. 		    pline_The("burning oil %s your %s",
1368. 			    obj->oeroded == MAX_ERODE ? "destroys" : "damages",
1369. 			    xname(obj));
1370. 		    if (obj->oeroded == MAX_ERODE) {
1371. 			obj_extract_self(obj);
1372. 			obfree(obj, (struct obj *)0);
1373. 			obj = (struct obj *) 0;
1374. 		    } else
1375. 			obj->oeroded++;
1376. 		}
1377. 		exercise(A_WIS, FALSE);
1378. 	    } else if (!obj->oeroded) {
1379. 		Your("%s do%s not need oiling.", xname(obj),
1380. 		    (obj->quan > 1L) ? "" : "es");
1381. 		exercise(A_WIS, FALSE);
1382. 	    } else {
1383. 		if (potion->cursed) {
1384. 		    pline_The("oil spills and covers your %s.",
1385. 					makeplural(body_part(FINGER)));
1386. 		    exercise(A_WIS, FALSE);
1387. 		    incr_itimeout(&Glib, rnd(10));
1388. 		} else {
1389. 		    Your("%s %s less rusty.", xname(obj),
1390. 			(obj->quan > 1L) ? "are" : "is");
1391. 		    obj->oeroded--;
1392. 		    exercise(A_WIS, TRUE);
1393. 		}
1394. 	    }
1395. 	    makeknown(potion->otyp);
1396. 	    useup(potion);
1397. 	    return TRUE;
1398. 	}
1399. 
1400. 	/* Allow filling of MAGIC_LAMPs to prevent identification by player */
1401. 	if ((obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP) &&
1402. 	   (potion->otyp == POT_OIL)) {
1403. 
1404. 	    /* Turn off engine before fueling, turn off fuel too :-)  */
1405. 	    if (obj->lamplit || potion->lamplit) {
1406. 		useup(potion);
1407. 		explode(u.ux, u.uy, 11, d(6,6), 0);
1408. 		exercise(A_WIS, FALSE);
1409. 		return TRUE;
1410. 	    }
1411. 	    /* Adding oil to an empty magic lamp renders it into an oil lamp */
1412. 	    if ((obj->otyp == MAGIC_LAMP) && obj->spe == 0) {
1413. 		obj->otyp = OIL_LAMP;
1414. 		obj->age = 0;
1415. 	    }
1416. 	    if (obj->age > 1000L) {
1417. 		Your("%s is full.", xname(obj));
1418. 	    } else {
1419. 		You("fill your %s with oil.", xname(obj));
1420. 		check_unpaid(potion);	/* surcharge for using unpaid item */
1421. 		obj->age += 2*potion->age;	/* burns more efficiently */
1422. 		if (obj->age > 1500L) obj->age = 1500L;
1423. 		useup(potion);
1424. 		exercise(A_WIS, TRUE);
1425. 	    }
1426. 	    obj->spe = 1;
1427. 	    update_inventory();
1428. 	    return TRUE;
1429. 	}
1430. 
1431. 	if ((obj->otyp == UNICORN_HORN || obj->otyp == AMETHYST) &&
1432. 	    (mixture = mixtype(obj, potion)) != 0) {
1433. 		/* with multiple merged potions, we should split off one and
1434. 		   just clear it, but clearing them all together is easier */
1435. 		boolean more_than_one = potion->quan > 1L;
1436. 		potion->otyp = mixture;
1437. 		potion->blessed = 0;
1438. 		if (mixture == POT_WATER)
1439. 		    potion->cursed = potion->odiluted = 0;
1440. 		else
1441. 		    potion->cursed = obj->cursed;  /* odiluted left as-is */
1442. 		if (Blind)
1443. 			potion->dknown = FALSE;
1444. 		else {
1445. 			if (mixture == POT_WATER &&
1446. #ifdef DCC30_BUG
1447. 			    (potion->dknown = !Hallucination,
1448. 			     potion->dknown != 0))
1449. #else
1450. 			    (potion->dknown = !Hallucination) != 0)
1451. #endif
1452. 				pline_The("potion%s clear%s.",
1453. 					more_than_one ? "s" : "",
1454. 					more_than_one ? "" : "s");
1455. 			else
1456. 				pline_The("potion%s turn%s %s.",
1457. 					more_than_one ? "s" : "",
1458. 					more_than_one ? "" : "s",
1459. 					hcolor(OBJ_DESCR(objects[mixture])));
1460. 		}
1461. 		return(1);
1462. 	}
1463. 
1464. 	pline("Interesting...");
1465. 	return(1);
1466. }
1467. 
1468. 
1469. void
1470. djinni_from_bottle(obj)
1471. register struct obj *obj;
1472. {
1473. 	struct monst *mtmp;
1474. 	int chance;
1475. 
1476. 	if(!(mtmp = makemon(&mons[PM_DJINNI], u.ux, u.uy))){
1477. 		pline("It turns out to be empty.");
1478. 		return;
1479. 	}
1480. 
1481. 	if (!Blind) {
1482. 		pline("In a cloud of smoke, %s emerges!", a_monnam(mtmp));
1483. 		pline("%s speaks.", Monnam(mtmp));
1484. 	} else {
1485. 		You("smell acrid fumes.");
1486. 		pline("%s speaks.", Something);
1487. 	}
1488. 
1489. 	chance = rn2(5);
1490. 	if (obj->blessed) chance = (chance == 4) ? rnd(4) : 0;
1491. 	else if (obj->cursed) chance = (chance == 0) ? rn2(4) : 4;
1492. 	/* 0,1,2,3,4:  b=80%,5,5,5,5; nc=20%,20,20,20,20; c=5%,5,5,5,80 */
1493. 
1494. 	switch (chance) {
1495. 	case 0 : verbalize("I am in your debt.  I will grant one wish!");
1496. 		makewish();
1497. 		mongone(mtmp);
1498. 		break;
1499. 	case 1 : verbalize("Thank you for freeing me!");
1500. 		(void) tamedog(mtmp, (struct obj *)0);
1501. 		break;
1502. 	case 2 : verbalize("You freed me!");
1503. 		mtmp->mpeaceful = TRUE;
1504. 		set_malign(mtmp);
1505. 		break;
1506. 	case 3 : verbalize("It is about time!");
1507. 		pline("%s vanishes.", Monnam(mtmp));
1508. 		mongone(mtmp);
1509. 		break;
1510. 	default: verbalize("You disturbed me, fool!");
1511. 		break;
1512. 	}
1513. }
1514. 
1515. #endif /* OVLB */
1516. 
1517. /*potion.c*/