Wikihack
Advertisement

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

Top of file[]

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. */
The NetHack General Public License applies to screenshots, source code and other content from NetHack.
4.    
5.    #include "hack.h"
6.    
7.    #ifdef OVLB
8.    boolean notonhead = FALSE;
9.    
10.   static NEARDATA int nothing, unkn;
11.   static NEARDATA const char beverages[] = { POTION_CLASS, 0 };
12.   
13.   STATIC_DCL long FDECL(itimeout, (long));
14.   STATIC_DCL long FDECL(itimeout_incr, (long,int));
15.   STATIC_DCL void NDECL(ghost_from_bottle);
16.   STATIC_DCL short FDECL(mixtype, (struct obj *,struct obj *));
17.   

itimeout[]

18.   /* force `val' to be within valid range for intrinsic timeout value */
19.   STATIC_OVL long
20.   itimeout(val)
21.   long val;
22.   {
23.       if (val >= TIMEOUT) val = TIMEOUT;
24.       else if (val < 1) val = 0;
25.   
26.       return val;
27.   }
28.   

itimeout_incr[]

29.   /* increment `old' by `incr' and force result to be valid intrinsic timeout */
30.   STATIC_OVL long
31.   itimeout_incr(old, incr)
32.   long old;
33.   int incr;
34.   {
35.       return itimeout((old & TIMEOUT) + (long)incr);
36.   }
37.   

set_itimeout[]

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.   

incr_itimeout[]

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.   

make_confused[]

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.   

make_stunned[]

73.   void
74.   make_stunned(xtime,talk)
75.   long xtime;
76.   boolean talk;
77.   {
78.   	long old = HStun;
79.   
80.   	if (!xtime && old) {
81.   		if (talk)
82.   		    You_feel("%s now.",
83.   			Hallucination ? "less wobbly" : "a bit steadier");
84.   	}
85.   	if (xtime && !old) {
86.   		if (talk) {
87.   #ifdef STEED
88.   			if (u.usteed)
89.   				You("wobble in the saddle.");
90.   			else
91.   #endif
92.   			You("%s...", stagger(youmonst.data, "stagger"));
93.   		}
94.   	}
95.   	if ((!xtime && old) || (xtime && !old)) flags.botl = TRUE;
96.   
97.   	set_itimeout(&HStun, xtime);
98.   }
99.   

make_sick[]

100.  void
101.  make_sick(xtime, cause, talk, type)
102.  long xtime;
103.  const char *cause;	/* sickness cause */
104.  boolean talk;
105.  int type;
106.  {
107.  	long old = Sick;
108.  
109.  	if (xtime > 0L) {
110.  	    if (Sick_resistance) return;
111.  	    if (!old) {
112.  		/* newly sick */
113.  		You_feel("deathly sick.");
114.  	    } else {
115.  		/* already sick */
116.  		if (talk) You_feel("%s worse.",
117.  			      xtime <= Sick/2L ? "much" : "even");
118.  	    }
119.  	    set_itimeout(&Sick, xtime);
120.  	    u.usick_type |= type;
121.  	    flags.botl = TRUE;
122.  	} else if (old && (type & u.usick_type)) {
123.  	    /* was sick, now not */
124.  	    u.usick_type &= ~type;
125.  	    if (u.usick_type) { /* only partly cured */
126.  		if (talk) You_feel("somewhat better.");
127.  		set_itimeout(&Sick, Sick * 2); /* approximation */
128.  	    } else {
129.  		if (talk) pline("What a relief!");
130.  		Sick = 0L;		/* set_itimeout(&Sick, 0L) */
131.  	    }
132.  	    flags.botl = TRUE;
133.  	}
134.  
135.  	if (Sick) {
136.  	    exercise(A_CON, FALSE);
137.  	    if (cause) {
138.  		(void) strncpy(u.usick_cause, cause, sizeof(u.usick_cause));
139.  		u.usick_cause[sizeof(u.usick_cause)-1] = 0;
140.  		}
141.  	    else
142.  		u.usick_cause[0] = 0;
143.  	} else
144.  	    u.usick_cause[0] = 0;
145.  }
146.  

make_vomiting[]

147.  void
148.  make_vomiting(xtime, talk)
149.  long xtime;
150.  boolean talk;
151.  {
152.  	long old = Vomiting;
153.  
154.  	if(!xtime && old)
155.  	    if(talk) You_feel("much less nauseated now.");
156.  
157.  	set_itimeout(&Vomiting, xtime);
158.  }
159.  
160.  static const char vismsg[] = "vision seems to %s for a moment but is %s now.";
161.  static const char eyemsg[] = "%s momentarily %s.";
162.  
163.  void

make_blinded[]

164.  make_blinded(xtime, talk)
165.  long xtime;
166.  boolean talk;
167.  {
168.  	long old = Blinded;
169.  	boolean u_could_see, can_see_now;
170.  	int eyecnt;
171.  	char buf[BUFSZ];
172.  
173.  	/* we need to probe ahead in case the Eyes of the Overworld
174.  	   are or will be overriding blindness */
175.  	u_could_see = !Blind;
176.  	Blinded = xtime ? 1L : 0L;
177.  	can_see_now = !Blind;
178.  	Blinded = old;		/* restore */
179.  
180.  	if (u.usleep) talk = FALSE;
181.  
182.  	if (can_see_now && !u_could_see) {	/* regaining sight */
183.  	    if (talk) {
184.  		if (Hallucination)
185.  		    pline("Far out!  Everything is all cosmic again!");
186.  		else
187.  		    You("can see again.");
188.  	    }
189.  	} else if (old && !xtime) {
190.  	    /* clearing temporary blindness without toggling blindness */
191.  	    if (talk) {
192.  		if (!haseyes(youmonst.data)) {
193.  		    strange_feeling((struct obj *)0, (char *)0);
194.  		} else if (Blindfolded) {
195.  		    Strcpy(buf, body_part(EYE));
196.  		    eyecnt = eyecount(youmonst.data);
197.  		    Your(eyemsg, (eyecnt == 1) ? buf : makeplural(buf),
198.  			 (eyecnt == 1) ? "itches" : "itch");
199.  		} else {	/* Eyes of the Overworld */
200.  		    Your(vismsg, "brighten",
201.  			 Hallucination ? "sadder" : "normal");
202.  		}
203.  	    }
204.  	}
205.  
206.  	if (u_could_see && !can_see_now) {	/* losing sight */
207.  	    if (talk) {
208.  		if (Hallucination)
209.  		    pline("Oh, bummer!  Everything is dark!  Help!");
210.  		else
211.  		    pline("A cloud of darkness falls upon you.");
212.  	    }
213.  	    /* Before the hero goes blind, set the ball&chain variables. */
214.  	    if (Punished) set_bc(0);
215.  	} else if (!old && xtime) {
216.  	    /* setting temporary blindness without toggling blindness */
217.  	    if (talk) {
218.  		if (!haseyes(youmonst.data)) {
219.  		    strange_feeling((struct obj *)0, (char *)0);
220.  		} else if (Blindfolded) {
221.  		    Strcpy(buf, body_part(EYE));
222.  		    eyecnt = eyecount(youmonst.data);
223.  		    Your(eyemsg, (eyecnt == 1) ? buf : makeplural(buf),
224.  			 (eyecnt == 1) ? "twitches" : "twitch");
225.  		} else {	/* Eyes of the Overworld */
226.  		    Your(vismsg, "dim",
227.  			 Hallucination ? "happier" : "normal");
228.  		}
229.  	    }
230.  	}
231.  
232.  	set_itimeout(&Blinded, xtime);
233.  
234.  	if (u_could_see ^ can_see_now) {  /* one or the other but not both */
235.  	    flags.botl = 1;
236.  	    vision_full_recalc = 1;	/* blindness just got toggled */
237.  	    if (Blind_telepat || Infravision) see_monsters();
238.  	}
239.  }
240.  

make_hallucinated[]

241.  boolean
242.  make_hallucinated(xtime, talk, mask)
243.  long xtime;	/* nonzero if this is an attempt to turn on hallucination */
244.  boolean talk;
245.  long mask;	/* nonzero if resistance status should change by mask */
246.  {
247.  	long old = HHallucination;
248.  	boolean changed = 0;
249.  	const char *message, *verb;
250.  
251.  	message = (!xtime) ? "Everything %s SO boring now." :
252.  			     "Oh wow!  Everything %s so cosmic!";
253.  	verb = (!Blind) ? "looks" : "feels";
254.  
255.  	if (mask) {
256.  	    if (HHallucination) changed = TRUE;
257.  
258.  	    if (!xtime) EHalluc_resistance |= mask;
259.  	    else EHalluc_resistance &= ~mask;
260.  	} else {
261.  	    if (!EHalluc_resistance && (!!HHallucination != !!xtime))
262.  		changed = TRUE;
263.  	    set_itimeout(&HHallucination, xtime);
264.  
265.  	    /* clearing temporary hallucination without toggling vision */
266.  	    if (!changed && !HHallucination && old && talk) {
267.  		if (!haseyes(youmonst.data)) {
268.  		    strange_feeling((struct obj *)0, (char *)0);
269.  		} else if (Blind) {
270.  		    char buf[BUFSZ];
271.  		    int eyecnt = eyecount(youmonst.data);
272.  
273.  		    Strcpy(buf, body_part(EYE));
274.  		    Your(eyemsg, (eyecnt == 1) ? buf : makeplural(buf),
275.  			 (eyecnt == 1) ? "itches" : "itch");
276.  		} else {	/* Grayswandir */
277.  		    Your(vismsg, "flatten", "normal");
278.  		}
279.  	    }
280.  	}
281.  
282.  	if (changed) {
283.  	    if (u.uswallow) {
284.  		swallowed(0);	/* redraw swallow display */
285.  	    } else {
286.  		/* The see_* routines should be called *before* the pline. */
287.  		see_monsters();
288.  		see_objects();
289.  		see_traps();
290.  	    }
291.  
292.  	    /* for perm_inv and anything similar
293.  	    (eg. Qt windowport's equipped items display) */
294.  	    update_inventory();
295.  
296.  	    flags.botl = 1;
297.  	    if (talk) pline(message, verb);
298.  	}
299.  	return changed;
300.  }
301.  

ghost_from_bottle[]

302.  STATIC_OVL void
303.  ghost_from_bottle()
304.  {
305.  	struct monst *mtmp = makemon(&mons[PM_GHOST], u.ux, u.uy, NO_MM_FLAGS);
306.  
307.  	if (!mtmp) {
308.  		pline("This bottle turns out to be empty.");
309.  		return;
310.  	}
311.  	if (Blind) {
312.  		pline("As you open the bottle, %s emerges.", something);
313.  		return;
314.  	}
315.  	pline("As you open the bottle, an enormous %s emerges!",
316.  		Hallucination ? rndmonnam() : (const char *)"ghost");
317.  	if(flags.verbose)
318.  	    You("are frightened to death, and unable to move.");
319.  	nomul(-3);
320.  	nomovemsg = "You regain your composure.";
321.  }
322.  

dodrink[]

323.  /* "Quaffing is like drinking, except you spill more."  -- Terry Pratchett
324.   */
325.  int
326.  dodrink()
327.  {
328.  	register struct obj *otmp;
329.  	const char *potion_descr;
330.  
331.  	if (Strangled) {
332.  		pline("If you can't breathe air, how can you drink liquid?");
333.  		return 0;
334.  	}
335.  	/* Is there a fountain to drink from here? */
336.  	if (IS_FOUNTAIN(levl[u.ux][u.uy].typ) && !Levitation) {
337.  		if(yn("Drink from the fountain?") == 'y') {
338.  			drinkfountain();
339.  			return 1;
340.  		}
341.  	}
342.  #ifdef SINKS
343.  	/* Or a kitchen sink? */
344.  	if (IS_SINK(levl[u.ux][u.uy].typ)) {
345.  		if (yn("Drink from the sink?") == 'y') {
346.  			drinksink();
347.  			return 1;
348.  		}
349.  	}
350.  #endif
351.  
352.  	/* Or are you surrounded by water? */
353.  	if (Underwater) {
354.  		if (yn("Drink the water around you?") == 'y') {
355.  		    pline("Do you know what lives in this water!");
356.  			return 1;
357.  		}
358.  	}
359.  
360.  	otmp = getobj(beverages, "drink");
361.  	if(!otmp) return(0);
362.  	otmp->in_use = TRUE;		/* you've opened the stopper */
363.  
364.  #define POTION_OCCUPANT_CHANCE(n) (13 + 2*(n))	/* also in muse.c */
365.  
366.  	potion_descr = OBJ_DESCR(objects[otmp->otyp]);
367.  	if (potion_descr) {
368.  	    if (!strcmp(potion_descr, "milky") &&
369.  		    flags.ghost_count < MAXMONNO &&
370.  		    !rn2(POTION_OCCUPANT_CHANCE(flags.ghost_count))) {
371.  		ghost_from_bottle();
372.  		useup(otmp);
373.  		return(1);
374.  	    } else if (!strcmp(potion_descr, "smoky") &&
375.  		    flags.djinni_count < MAXMONNO &&
376.  		    !rn2(POTION_OCCUPANT_CHANCE(flags.djinni_count))) {
377.  		djinni_from_bottle(otmp);
378.  		useup(otmp);
379.  		return(1);
380.  	    }
381.  	}
382.  	return dopotion(otmp);
383.  }
384.  

dopotion[]

385.  int
386.  dopotion(otmp)
387.  register struct obj *otmp;
388.  {
389.  	int retval;
390.  
391.  	otmp->in_use = TRUE;
392.  	nothing = unkn = 0;
393.  	if((retval = peffects(otmp)) >= 0) return(retval);
394.  
395.  	if(nothing) {
396.  	    unkn++;
397.  	    You("have a %s feeling for a moment, then it passes.",
398.  		  Hallucination ? "normal" : "peculiar");
399.  	}
400.  	if(otmp->dknown && !objects[otmp->otyp].oc_name_known) {
401.  		if(!unkn) {
402.  			makeknown(otmp->otyp);
403.  			more_experienced(0,10);
404.  		} else if(!objects[otmp->otyp].oc_uname)
405.  			docall(otmp);
406.  	}
407.  	useup(otmp);
408.  	return(1);
409.  }
410.  

peffects[]

411.  int
412.  peffects(otmp)
413.  	register struct obj	*otmp;
414.  {
415.  	register int i, ii, lim;
416.  
417.  	switch(otmp->otyp){
418.  	case POT_RESTORE_ABILITY:
419.  	case SPE_RESTORE_ABILITY:
420.  		unkn++;
421.  		if(otmp->cursed) {
422.  		    pline("Ulch!  This makes you feel mediocre!");
423.  		    break;
424.  		} else {
425.  		    pline("Wow!  This makes you feel %s!",
426.  			  (otmp->blessed) ?
427.  				(unfixable_trouble_count(FALSE) ? "better" : "great")
428.  			  : "good");
429.  		    i = rn2(A_MAX);		/* start at a random point */
430.  		    for (ii = 0; ii < A_MAX; ii++) {
431.  			lim = AMAX(i);
432.  			if (i == A_STR && u.uhs >= 3) --lim;	/* WEAK */
433.  			if (ABASE(i) < lim) {
434.  			    ABASE(i) = lim;
435.  			    flags.botl = 1;
436.  			    /* only first found if not blessed */
437.  			    if (!otmp->blessed) break;
438.  			}
439.  			if(++i >= A_MAX) i = 0;
440.  		    }
441.  		}
442.  		break;
443.  	case POT_HALLUCINATION:
444.  		if (Hallucination || Halluc_resistance) nothing++;
445.  		(void) make_hallucinated(itimeout_incr(HHallucination,
446.  					   rn1(200, 600 - 300 * bcsign(otmp))),
447.  				  TRUE, 0L);
448.  		break;
449.  	case POT_WATER:
450.  		if(!otmp->blessed && !otmp->cursed) {
451.  		    pline("This tastes like water.");
452.  		    u.uhunger += rnd(10);
453.  		    newuhs(FALSE);
454.  		    break;
455.  		}
456.  		unkn++;
457.  		if(is_undead(youmonst.data) || is_demon(youmonst.data) ||
458.  				u.ualign.type == A_CHAOTIC) {
459.  		    if(otmp->blessed) {
460.  			pline("This burns like acid!");
461.  			exercise(A_CON, FALSE);
462.  			if (u.ulycn >= LOW_PM) {
463.  			    Your("affinity to %s disappears!",
464.  				 makeplural(mons[u.ulycn].mname));
465.  			    if (youmonst.data == &mons[u.ulycn])
466.  				you_unwere(FALSE);
467.  			    u.ulycn = NON_PM;	/* cure lycanthropy */
468.  			}
469.  			losehp(d(2,6), "potion of holy water", KILLED_BY_AN);
470.  		    } else if(otmp->cursed) {
471.  			You_feel("quite proud of yourself.");
472.  			healup(d(2,6),0,0,0);
473.  			if (u.ulycn >= LOW_PM && !Upolyd) you_were();
474.  			exercise(A_CON, TRUE);
475.  		    }
476.  		} else {
477.  		    if(otmp->blessed) {
478.  			You_feel("full of awe.");
479.  			make_sick(0L, (char *) 0, TRUE, SICK_ALL);
480.  			exercise(A_WIS, TRUE);
481.  			exercise(A_CON, TRUE);
482.  			if (u.ulycn >= LOW_PM)
483.  			    you_unwere(TRUE);	/* "Purified" */
484.  			/* make_confused(0L,TRUE); */
485.  		    } else {
486.  			if(u.ualign.type == A_LAWFUL) {
487.  			    pline("This burns like acid!");
488.  			    losehp(d(2,6), "potion of unholy water",
489.  				KILLED_BY_AN);
490.  			} else
491.  			    You_feel("full of dread.");
492.  			if (u.ulycn >= LOW_PM && !Upolyd) you_were();
493.  			exercise(A_CON, FALSE);
494.  		    }
495.  		}
496.  		break;
497.  	case POT_BOOZE:
498.  		unkn++;
499.  		pline("Ooph!  This tastes like %s%s!",
500.  		      otmp->odiluted ? "watered down " : "",
501.  		      Hallucination ? "dandelion wine" : "liquid fire");
502.  		if (!otmp->blessed)
503.  		    make_confused(itimeout_incr(HConfusion, d(3,8)), FALSE);
504.  		/* the whiskey makes us feel better */
505.  		if (!otmp->odiluted) healup(1, 0, FALSE, FALSE);
506.  		u.uhunger += 10 * (2 + bcsign(otmp));
507.  		newuhs(FALSE);
508.  		exercise(A_WIS, FALSE);
509.  		if(otmp->cursed) {
510.  			You("pass out.");
511.  			multi = -rnd(15);
512.  			nomovemsg = "You awake with a headache.";
513.  		}
514.  		break;
515.  	case POT_ENLIGHTENMENT:
516.  		if(otmp->cursed) {
517.  			unkn++;
518.  			You("have an uneasy feeling...");
519.  			exercise(A_WIS, FALSE);
520.  		} else {
521.  			if (otmp->blessed) {
522.  				(void) adjattrib(A_INT, 1, FALSE);
523.  				(void) adjattrib(A_WIS, 1, FALSE);
524.  			}
525.  			You_feel("self-knowledgeable...");
526.  			display_nhwindow(WIN_MESSAGE, FALSE);
527.  			enlightenment(0);
528.  			pline_The("feeling subsides.");
529.  			exercise(A_WIS, TRUE);
530.  		}
531.  		break;
532.  	case SPE_INVISIBILITY:
533.  		/* spell cannot penetrate mummy wrapping */
534.  		if (BInvis && uarmc->otyp == MUMMY_WRAPPING) {
535.  			You_feel("rather itchy under your %s.", xname(uarmc));
536.  			break;
537.  		}
538.  		/* FALLTHRU */
539.  	case POT_INVISIBILITY:
540.  		if (Invis || Blind || BInvis) {
541.  		    nothing++;
542.  		} else {
543.  		    self_invis_message();
544.  		}
545.  		if (otmp->blessed) HInvis |= FROMOUTSIDE;
546.  		else incr_itimeout(&HInvis, rn1(15,31));
547.  		newsym(u.ux,u.uy);	/* update position */
548.  		if(otmp->cursed) {
549.  		    pline("For some reason, you feel your presence is known.");
550.  		    aggravate();
551.  		}
552.  		break;
553.  	case POT_SEE_INVISIBLE:
554.  		/* tastes like fruit juice in Rogue */
555.  	case POT_FRUIT_JUICE:
556.  	    {
557.  		int msg = Invisible && !Blind;
558.  
559.  		unkn++;
560.  		if (otmp->cursed)
561.  		    pline("Yecch!  This tastes %s.",
562.  			  Hallucination ? "overripe" : "rotten");
563.  		else
564.  		    pline(Hallucination ?
565.  		      "This tastes like 10%% real %s%s all-natural beverage." :
566.  				"This tastes like %s%s.",
567.  			  otmp->odiluted ? "reconstituted " : "",
568.  			  fruitname(TRUE));
569.  		if (otmp->otyp == POT_FRUIT_JUICE) {
570.  		    u.uhunger += (otmp->odiluted ? 5 : 10) * (2 + bcsign(otmp));
571.  		    newuhs(FALSE);
572.  		    break;
573.  		}
574.  		if (!otmp->cursed) {
575.  			/* Tell them they can see again immediately, which
576.  			 * will help them identify the potion...
577.  			 */
578.  			make_blinded(0L,TRUE);
579.  		}
580.  		if (otmp->blessed)
581.  			HSee_invisible |= FROMOUTSIDE;
582.  		else
583.  			incr_itimeout(&HSee_invisible, rn1(100,750));
584.  		set_mimic_blocking(); /* do special mimic handling */
585.  		see_monsters();	/* see invisible monsters */
586.  		newsym(u.ux,u.uy); /* see yourself! */
587.  		if (msg && !Blind) { /* Blind possible if polymorphed */
588.  		    You("can see through yourself, but you are visible!");
589.  		    unkn--;
590.  		}
591.  		break;
592.  	    }
593.  	case POT_PARALYSIS:
594.  		if (Free_action)
595.  		    You("stiffen momentarily.");
596.  		else {
597.  		    if (Levitation || Is_airlevel(&u.uz)||Is_waterlevel(&u.uz))
598.  			You("are motionlessly suspended.");
599.  #ifdef STEED
600.  		    else if (u.usteed)
601.  			You("are frozen in place!");
602.  #endif
603.  		    else
604.  			Your("%s are frozen to the %s!",
605.  			     makeplural(body_part(FOOT)), surface(u.ux, u.uy));
606.  		    nomul(-(rn1(10, 25 - 12*bcsign(otmp))));
607.  		    nomovemsg = You_can_move_again;
608.  		    exercise(A_DEX, FALSE);
609.  		}
610.  		break;
611.  	case POT_SLEEPING:
612.  		if(Sleep_resistance || Free_action)
613.  		    You("yawn.");
614.  		else {
615.  		    You("suddenly fall asleep!");
616.  		    fall_asleep(-rn1(10, 25 - 12*bcsign(otmp)), TRUE);
617.  		}
618.  		break;
619.  	case POT_MONSTER_DETECTION:
620.  	case SPE_DETECT_MONSTERS:
621.  		if (otmp->blessed) {
622.  		    int x, y;
623.  
624.  		    if (Detect_monsters) nothing++;
625.  		    unkn++;
626.  		    /* after a while, repeated uses become less effective */
627.  		    if (HDetect_monsters >= 300L)
628.  			i = 1;
629.  		    else
630.  			i = rn1(40,21);
631.  		    incr_itimeout(&HDetect_monsters, i);
632.  		    for (x = 1; x < COLNO; x++) {
633.  			for (y = 0; y < ROWNO; y++) {
634.  			    if (levl[x][y].glyph == GLYPH_INVISIBLE) {
635.  				unmap_object(x, y);
636.  				newsym(x,y);
637.  			    }
638.  			    if (MON_AT(x,y)) unkn = 0;
639.  			}
640.  		    }
641.  		    see_monsters();
642.  		    if (unkn) You_feel("lonely.");
643.  		    break;
644.  		}
645.  		if (monster_detect(otmp, 0))
646.  			return(1);		/* nothing detected */
647.  		exercise(A_WIS, TRUE);
648.  		break;
649.  	case POT_OBJECT_DETECTION:
650.  	case SPE_DETECT_TREASURE:
651.  		if (object_detect(otmp, 0))
652.  			return(1);		/* nothing detected */
653.  		exercise(A_WIS, TRUE);
654.  		break;
655.  	case POT_SICKNESS:
656.  		pline("Yecch!  This stuff tastes like poison.");
657.  		if (otmp->blessed) {
658.  		    pline("(But in fact it was mildly stale %s.)",
659.  			  fruitname(TRUE));
660.  		    if (!Role_if(PM_HEALER)) {
661.  			/* NB: blessed otmp->fromsink is not possible */
662.  			losehp(1, "mildly contaminated potion", KILLED_BY_AN);
663.  		    }
664.  		} else {
665.  		    if(Poison_resistance)
666.  			pline(
667.  			  "(But in fact it was biologically contaminated %s.)",
668.  			      fruitname(TRUE));
669.  		    if (Role_if(PM_HEALER))
670.  			pline("Fortunately, you have been immunized.");
671.  		    else {
672.  			int typ = rn2(A_MAX);
673.  
674.  			if (!Fixed_abil) {
675.  			    poisontell(typ);
676.  			    (void) adjattrib(typ,
677.  			    		Poison_resistance ? -1 : -rn1(4,3),
678.  			    		TRUE);
679.  			}
680.  			if(!Poison_resistance) {
681.  			    if (otmp->fromsink)
682.  				losehp(rnd(10)+5*!!(otmp->cursed),
683.  				       "contaminated tap water", KILLED_BY);
684.  			    else
685.  				losehp(rnd(10)+5*!!(otmp->cursed),
686.  				       "contaminated potion", KILLED_BY_AN);
687.  			}
688.  			exercise(A_CON, FALSE);
689.  		    }
690.  		}
691.  		if(Hallucination) {
692.  			You("are shocked back to your senses!");
693.  			(void) make_hallucinated(0L,FALSE,0L);
694.  		}
695.  		break;
696.  	case POT_CONFUSION:
697.  		if(!Confusion)
698.  		    if (Hallucination) {
699.  			pline("What a trippy feeling!");
700.  			unkn++;
701.  		    } else
702.  			pline("Huh, What?  Where am I?");
703.  		else	nothing++;
704.  		make_confused(itimeout_incr(HConfusion,
705.  					    rn1(7, 16 - 8 * bcsign(otmp))),
706.  			      FALSE);
707.  		break;
708.  	case POT_GAIN_ABILITY:
709.  		if(otmp->cursed) {
710.  		    pline("Ulch!  That potion tasted foul!");
711.  		    unkn++;
712.  		} else if (Fixed_abil) {
713.  		    nothing++;
714.  		} else {      /* If blessed, increase all; if not, try up to */
715.  		    int itmp; /* 6 times to find one which can be increased. */
716.  		    i = -1;		/* increment to 0 */
717.  		    for (ii = A_MAX; ii > 0; ii--) {
718.  			i = (otmp->blessed ? i + 1 : rn2(A_MAX));
719.  			/* only give "your X is already as high as it can get"
720.  			   message on last attempt (except blessed potions) */
721.  			itmp = (otmp->blessed || ii == 1) ? 0 : -1;
722.  			if (adjattrib(i, 1, itmp) && !otmp->blessed)
723.  			    break;
724.  		    }
725.  		}
726.  		break;
727.  	case POT_SPEED:
728.  		if(Wounded_legs && !otmp->cursed
729.  #ifdef STEED
730.  		   && !u.usteed	/* heal_legs() would heal steeds legs */
731.  #endif
732.  						) {
733.  			heal_legs();
734.  			unkn++;
735.  			break;
736.  		} /* and fall through */
737.  	case SPE_HASTE_SELF:
738.  		if(!Very_fast) /* wwf@doe.carleton.ca */
739.  			You("are suddenly moving %sfaster.",
740.  				Fast ? "" : "much ");
741.  		else {
742.  			Your("%s get new energy.",
743.  				makeplural(body_part(LEG)));
744.  			unkn++;
745.  		}
746.  		exercise(A_DEX, TRUE);
747.  		incr_itimeout(&HFast, rn1(10, 100 + 60 * bcsign(otmp)));
748.  		break;
749.  	case POT_BLINDNESS:
750.  		if(Blind) nothing++;
751.  		make_blinded(itimeout_incr(Blinded,
752.  					   rn1(200, 250 - 125 * bcsign(otmp))),
753.  			     (boolean)!Blind);
754.  		break;
755.  	case POT_GAIN_LEVEL:
756.  		if (otmp->cursed) {
757.  			unkn++;
758.  			/* they went up a level */
759.  			if((ledger_no(&u.uz) == 1 && u.uhave.amulet) ||
760.  				Can_rise_up(u.ux, u.uy, &u.uz)) {
761.  			    const char *riseup ="rise up, through the %s!";
762.  			    if(ledger_no(&u.uz) == 1) {
763.  			        You(riseup, ceiling(u.ux,u.uy));
764.  				goto_level(&earth_level, FALSE, FALSE, FALSE);
765.  			    } else {
766.  			        register int newlev = depth(&u.uz)-1;
767.  				d_level newlevel;
768.  
;769.  				get_level(&newlevel, newlev);
770.  				if(on_level(&newlevel, &u.uz)) {
771.  				    pline("It tasted bad.");
772.  				    break;
773.  				} else You(riseup, ceiling(u.ux,u.uy));
774.  				goto_level(&newlevel, FALSE, FALSE, FALSE);
775.  			    }
776.  			}
777.  			else You("have an uneasy feeling.");
778.  			break;
779.  		}
780.  		pluslvl(FALSE);
781.  		if (otmp->blessed)
782.  			/* blessed potions place you at a random spot in the
783.  			 * middle of the new level instead of the low point
784.  			 */
785.  			u.uexp = rndexp(TRUE);
786.  		break;
787.  	case POT_HEALING:
788.  		You_feel("better.");
789.  		healup(d(6 + 2 * bcsign(otmp), 4),
790.  		       !otmp->cursed ? 1 : 0, !!otmp->blessed, !otmp->cursed);
791.  		exercise(A_CON, TRUE);
792.  		break;
793.  	case POT_EXTRA_HEALING:
794.  		You_feel("much better.");
795.  		healup(d(6 + 2 * bcsign(otmp), 8),
796.  		       otmp->blessed ? 5 : !otmp->cursed ? 2 : 0,
797.  		       !otmp->cursed, TRUE);
798.  		(void) make_hallucinated(0L,TRUE,0L);
799.  		exercise(A_CON, TRUE);
800.  		exercise(A_STR, TRUE);
801.  		break;
802.  	case POT_FULL_HEALING:
803.  		You_feel("completely healed.");
804.  		healup(400, 4+4*bcsign(otmp), !otmp->cursed, TRUE);
805.  		/* Restore one lost level if blessed */
806.  		if (otmp->blessed && u.ulevel < u.ulevelmax) {
807.  		    /* when multiple levels have been lost, drinking
808.  		       multiple potions will only get half of them back */
809.  		    u.ulevelmax -= 1;
810.  		    pluslvl(FALSE);
811.  		}
812.  		(void) make_hallucinated(0L,TRUE,0L);
813.  		exercise(A_STR, TRUE);
814.  		exercise(A_CON, TRUE);
815.  		break;
816.  	case POT_LEVITATION:
817.  	case SPE_LEVITATION:
818.  		if (otmp->cursed) HLevitation &= ~I_SPECIAL;
819.  		if(!Levitation) {
820.  			/* kludge to ensure proper operation of float_up() */
821.  			HLevitation = 1;
822.  			float_up();
823.  			/* reverse kludge */
824.  			HLevitation = 0;
825.  			if (otmp->cursed && !Is_waterlevel(&u.uz)) {
826.  	if((u.ux != xupstair || u.uy != yupstair)
827.  	   && (u.ux != sstairs.sx || u.uy != sstairs.sy || !sstairs.up)
828.  	   && (!xupladder || u.ux != xupladder || u.uy != yupladder)
829.  	) {
830.  					You("hit your %s on the %s.",
831.  						body_part(HEAD),
832.  						ceiling(u.ux,u.uy));
833.  					losehp(uarmh ? 1 : rnd(10),
834.  						"colliding with the ceiling",
835.  						KILLED_BY);
836.  				} else (void) doup();
837.  			}
838.  		} else
839.  			nothing++;
840.  		if (otmp->blessed) {
841.  		    incr_itimeout(&HLevitation, rn1(50,250));
842.  		    HLevitation |= I_SPECIAL;
843.  		} else incr_itimeout(&HLevitation, rn1(140,10));
844.  		spoteffects(FALSE);	/* for sinks */
845.  		break;
846.  	case POT_GAIN_ENERGY:			/* M. Stephenson */
847.  		{	register int num;
848.  			if(otmp->cursed)
849.  			    You_feel("lackluster.");
850.  			else
851.  			    pline("Magical energies course through your body.");
852.  			num = rnd(5) + 5 * otmp->blessed + 1;
853.  			u.uenmax += (otmp->cursed) ? -num : num;
854.  			u.uen += (otmp->cursed) ? -num : num;
855.  			if(u.uenmax <= 0) u.uenmax = 0;
856.  			if(u.uen <= 0) u.uen = 0;
857.  			flags.botl = 1;
858.  			exercise(A_WIS, TRUE);
859.  		}
860.  		break;
861.  	case POT_OIL:				/* P. Winner */
862.  		{
863.  			boolean good_for_you = FALSE;
864.  
865.  			if (otmp->lamplit) {
866.  			    if (likes_fire(youmonst.data)) {
867.  				pline("Ahh, a refreshing drink.");
868.  				good_for_you = TRUE;
869.  			    } else {
870.  				You("burn your %s.", body_part(FACE));
871.  				losehp(d(Fire_resistance ? 1 : 3, 4),
872.  				       "burning potion of oil", KILLED_BY_AN);
873.  			    }
874.  			} else if(otmp->cursed)
875.  			    pline("This tastes like castor oil.");
876.  			else
877.  			    pline("That was smooth!");
878.  			exercise(A_WIS, good_for_you);
879.  		}
880.  		break;
881.  	case POT_ACID:
882.  		if (Acid_resistance)
883.  			/* Not necessarily a creature who _likes_ acid */
884.  			pline("This tastes %s.", Hallucination ? "tangy" : "sour");
885.  		else {
886.  			pline("This burns%s!", otmp->blessed ? " a little" :
887.  					otmp->cursed ? " a lot" : " like acid");
888.  			losehp(d(otmp->cursed ? 2 : 1, otmp->blessed ? 4 : 8),
889.  					"potion of acid", KILLED_BY_AN);
890.  			exercise(A_CON, FALSE);
891.  		}
892.  		if (Stoned) fix_petrification();
893.  		unkn++; /* holy/unholy water can burn like acid too */
894.  		break;
895.  	case POT_POLYMORPH:
896.  		You_feel("a little %s.", Hallucination ? "normal" : "strange");
897.  		if (!Unchanging) polyself(FALSE);
898.  		break;
899.  	default:
900.  		impossible("What a funny potion! (%u)", otmp->otyp);
901.  		return(0);
902.  	}
903.  	return(-1);
904.  }
905.  

healup[]

906.  void
907.  healup(nhp, nxtra, curesick, cureblind)
908.  	int nhp, nxtra;
909.  	register boolean curesick, cureblind;
910.  {
911.  	if (nhp) {
912.  		if (Upolyd) {
913.  			u.mh += nhp;
914.  			if (u.mh > u.mhmax) u.mh = (u.mhmax += nxtra);
915.  		} else {
916.  			u.uhp += nhp;
917.  			if(u.uhp > u.uhpmax) u.uhp = (u.uhpmax += nxtra);
918.  		}
919.  	}
920.  	if(cureblind)	make_blinded(0L,TRUE);
921.  	if(curesick)	make_sick(0L, (char *) 0, TRUE, SICK_ALL);
922.  	flags.botl = 1;
923.  	return;
924.  }
925.  

strange_feeling[]

926.  void
927.  strange_feeling(obj,txt)
928.  register struct obj *obj;
929.  register const char *txt;
930.  {
931.  	if (flags.beginner || !txt)
932.  		You("have a %s feeling for a moment, then it passes.",
933.  		Hallucination ? "normal" : "strange");
934.  	else
935.  		pline(txt);
936.  
937.  	if(!obj)	/* e.g., crystal ball finds no traps */
938.  		return;
939.  
940.  	if(obj->dknown && !objects[obj->otyp].oc_name_known &&
941.  						!objects[obj->otyp].oc_uname)
942.  		docall(obj);
943.  	useup(obj);
944.  }
945.  

bottlename[]

946.  const char *bottlenames[] = {
947.  	"bottle", "phial", "flagon", "carafe", "flask", "jar", "vial"
948.  };
949.  
950.  
951.  const char *
952.  bottlename()
953.  {
954.  	return bottlenames[rn2(SIZE(bottlenames))];
955.  }
956.  

potionhit[]

957.  void
958.  potionhit(mon, obj, your_fault)
959.  register struct monst *mon;
960.  register struct obj *obj;
961.  boolean your_fault;
962.  {
963.  	register const char *botlnam = bottlename();
964.  	boolean isyou = (mon == &youmonst);
965.  	int distance;
966.  
967.  	if(isyou) {
968.  		distance = 0;
969.  		pline_The("%s crashes on your %s and breaks into shards.",
970.  			botlnam, body_part(HEAD));
971.  		losehp(rnd(2), "thrown potion", KILLED_BY_AN);
972.  	} else {
973.  		distance = distu(mon->mx,mon->my);
974.  		if (!cansee(mon->mx,mon->my)) pline("Crash!");
975.  		else {
976.  		    char *mnam = mon_nam(mon);
977.  		    char buf[BUFSZ];
978.  
979.  		    if(has_head(mon->data)) {
980.  			Sprintf(buf, "%s %s",
981.  				s_suffix(mnam),
982.  				(notonhead ? "body" : "head"));
983.  		    } else {
984.  			Strcpy(buf, mnam);
985.  		    }
986.  		    pline_The("%s crashes on %s and breaks into shards.",
987.  			   botlnam, buf);
988.  		}
989.  		if(rn2(5) && mon->mhp > 1)
990.  			mon->mhp--;
991.  	}
992.  
993.  	/* oil doesn't instantly evaporate */
994.  	if (obj->otyp != POT_OIL && cansee(mon->mx,mon->my))
995.  		pline("%s.", Tobjnam(obj, "evaporate"));
996.  
997.      if (isyou) {
998.  	switch (obj->otyp) {
999.  	case POT_OIL:
1000. 		if (obj->lamplit)
1001. 		    splatter_burning_oil(u.ux, u.uy);
1002. 		break;
1003. 	case POT_POLYMORPH:
1004. 		You_feel("a little %s.", Hallucination ? "normal" : "strange");
1005. 		if (!Unchanging && !Antimagic) polyself(FALSE);
1006. 		break;
1007. 	case POT_ACID:
1008. 		if (!Acid_resistance) {
1009. 		    pline("This burns%s!", obj->blessed ? " a little" :
1010. 				    obj->cursed ? " a lot" : "");
1011. 		    losehp(d(obj->cursed ? 2 : 1, obj->blessed ? 4 : 8),
1012. 				    "potion of acid", KILLED_BY_AN);
1013. 		}
1014. 		break;
1015. 	}
1016.     } else {
1017. 	boolean angermon = TRUE;
1018. 
1019. 	if (!your_fault) angermon = FALSE;
1020. 	switch (obj->otyp) {
1021. 	case POT_HEALING:
1022. 	case POT_EXTRA_HEALING:
1023. 	case POT_FULL_HEALING:
1024. 		if (mon->data == &mons[PM_PESTILENCE]) goto do_illness;
1025. 		/*FALLTHRU*/
1026. 	case POT_RESTORE_ABILITY:
1027. 	case POT_GAIN_ABILITY:
1028.  do_healing:
1029. 		angermon = FALSE;
1030. 		if(mon->mhp < mon->mhpmax) {
1031. 		    mon->mhp = mon->mhpmax;
1032. 		    if (canseemon(mon))
1033. 			pline("%s looks sound and hale again.", Monnam(mon));
1034. 		}
1035. 		break;
1036. 	case POT_SICKNESS:
1037. 		if (mon->data == &mons[PM_PESTILENCE]) goto do_healing;
1038. 		if (dmgtype(mon->data, AD_DISE) ||
1039. 			   dmgtype(mon->data, AD_PEST) || /* won't happen, see prior goto */
1040. 			   resists_poison(mon)) {
1041. 		    if (canseemon(mon))
1042. 			pline("%s looks unharmed.", Monnam(mon));
1043. 		    break;
1044. 		}
1045.  do_illness:
1046. 		if((mon->mhpmax > 3) && !resist(mon, POTION_CLASS, 0, NOTELL))
1047. 			mon->mhpmax /= 2;
1048. 		if((mon->mhp > 2) && !resist(mon, POTION_CLASS, 0, NOTELL))
1049. 			mon->mhp /= 2;
1050. 		if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax;
1051. 		if (canseemon(mon))
1052. 		    pline("%s looks rather ill.", Monnam(mon));
1053. 		break;
1054. 	case POT_CONFUSION:
1055. 	case POT_BOOZE:
1056. 		if(!resist(mon, POTION_CLASS, 0, NOTELL))  mon->mconf = TRUE;
1057. 		break;
1058. 	case POT_INVISIBILITY:
1059. 		angermon = FALSE;
1060. 		mon_set_minvis(mon);
1061. 		break;
1062. 	case POT_SLEEPING:
1063. 		/* wakeup() doesn't rouse victims of temporary sleep */
1064. 		if (sleep_monst(mon, rnd(12), POTION_CLASS)) {
1065. 		    pline("%s falls asleep.", Monnam(mon));
1066. 		    slept_monst(mon);
1067. 		}
1068. 		break;
1069. 	case POT_PARALYSIS:
1070. 		if (mon->mcanmove) {
1071. 			mon->mcanmove = 0;
1072. 			/* really should be rnd(5) for consistency with players
1073. 			 * breathing potions, but...
1074. 			 */
1075. 			mon->mfrozen = rnd(25);
1076. 		}
1077. 		break;
1078. 	case POT_SPEED:
1079. 		angermon = FALSE;
1080. 		mon_adjust_speed(mon, 1, obj);
1081. 		break;
1082. 	case POT_BLINDNESS:
1083. 		if(haseyes(mon->data)) {
1084. 		    register int btmp = 64 + rn2(32) +
1085. 			rn2(32) * !resist(mon, POTION_CLASS, 0, NOTELL);
1086. 		    btmp += mon->mblinded;
1087. 		    mon->mblinded = min(btmp,127);
1088. 		    mon->mcansee = 0;
1089. 		}
1090. 		break;
1091. 	case POT_WATER:
1092. 		if (is_undead(mon->data) || is_demon(mon->data) ||
1093. 			is_were(mon->data)) {
1094. 		    if (obj->blessed) {
1095. 			pline("%s %s in pain!", Monnam(mon),
1096. 			      is_silent(mon->data) ? "writhes" : "shrieks");
1097. 			mon->mhp -= d(2,6);
1098. 			/* should only be by you */
1099. 			if (mon->mhp < 1) killed(mon);
1100. 			else if (is_were(mon->data) && !is_human(mon->data))
1101. 			    new_were(mon);	/* revert to human */
1102. 		    } else if (obj->cursed) {
1103. 			angermon = FALSE;
1104. 			if (canseemon(mon))
1105. 			    pline("%s looks healthier.", Monnam(mon));
1106. 			mon->mhp += d(2,6);
1107. 			if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax;
1108. 			if (is_were(mon->data) && is_human(mon->data) &&
1109. 				!Protection_from_shape_changers)
1110. 			    new_were(mon);	/* transform into beast */
1111. 		    }
1112. 		} else if(mon->data == &mons[PM_GREMLIN]) {
1113. 		    angermon = FALSE;
1114. 		    (void)split_mon(mon, (struct monst *)0);
1115. 		} else if(mon->data == &mons[PM_IRON_GOLEM]) {
1116. 		    if (canseemon(mon))
1117. 			pline("%s rusts.", Monnam(mon));
1118. 		    mon->mhp -= d(1,6);
1119. 		    /* should only be by you */
1120. 		    if (mon->mhp < 1) killed(mon);
1121. 		}
1122. 		break;
1123. 	case POT_OIL:
1124. 		if (obj->lamplit)
1125. 			splatter_burning_oil(mon->mx, mon->my);
1126. 		break;
1127. 	case POT_ACID:
1128. 		if (!resists_acid(mon) && !resist(mon, POTION_CLASS, 0, NOTELL)) {
1129. 		    pline("%s %s in pain!", Monnam(mon),
1130. 			  is_silent(mon->data) ? "writhes" : "shrieks");
1131. 		    mon->mhp -= d(obj->cursed ? 2 : 1, obj->blessed ? 4 : 8);
1132. 		    if (mon->mhp < 1) {
1133. 			if (your_fault)
1134. 			    killed(mon);
1135. 			else
1136. 			    monkilled(mon, "", AD_ACID);
1137. 		    }
1138. 		}
1139. 		break;
1140. 	case POT_POLYMORPH:
1141. 		(void) bhitm(mon, obj);
1142. 		break;
1143. /*
1144. 	case POT_GAIN_LEVEL:
1145. 	case POT_LEVITATION:
1146. 	case POT_FRUIT_JUICE:
1147. 	case POT_MONSTER_DETECTION:
1148. 	case POT_OBJECT_DETECTION:
1149. 		break;
1150. */
1151. 	}
1152. 	if (angermon)
1153. 	    wakeup(mon);
1154. 	else
1155. 	    mon->msleeping = 0;
1156.     }
1157. 
1158. 	/* Note: potionbreathe() does its own docall() */
1159. 	if ((distance==0 || ((distance < 3) && rn2(5))) &&
1160. 	    (!breathless(youmonst.data) || haseyes(youmonst.data)))
1161. 		potionbreathe(obj);
1162. 	else if (obj->dknown && !objects[obj->otyp].oc_name_known &&
1163. 		   !objects[obj->otyp].oc_uname && cansee(mon->mx,mon->my))
1164. 		docall(obj);
1165. 	if(*u.ushops && obj->unpaid) {
1166. 	        register struct monst *shkp =
1167. 			shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE));
1168. 
1169. 		if(!shkp)
1170. 		    obj->unpaid = 0;
1171. 		else {
1172. 		    (void)stolen_value(obj, u.ux, u.uy,
1173. 				 (boolean)shkp->mpeaceful, FALSE);
1174. 		    subfrombill(obj, shkp);
1175. 		}
1176. 	}
1177. 	obfree(obj, (struct obj *)0);
1178. }
1179. 

potionbreathe[]

1180. /* vapors are inhaled or get in your eyes */
1181. void
1182. potionbreathe(obj)
1183. register struct obj *obj;
1184. {
1185. 	register int i, ii, isdone, kn = 0;
1186. 
1187. 	switch(obj->otyp) {
1188. 	case POT_RESTORE_ABILITY:
1189. 	case POT_GAIN_ABILITY:
1190. 		if(obj->cursed) {
1191. 		    if (!breathless(youmonst.data))
1192. 			pline("Ulch!  That potion smells terrible!");
1193. 		    else if (haseyes(youmonst.data)) {
1194. 			int numeyes = eyecount(youmonst.data);
1195. 			Your("%s sting%s!",
1196. 			     (numeyes == 1) ? body_part(EYE) : makeplural(body_part(EYE)),
1197. 			     (numeyes == 1) ? "s" : "");
1198. 		    }
1199. 		    break;
1200. 		} else {
1201. 		    i = rn2(A_MAX);		/* start at a random point */
1202. 		    for(isdone = ii = 0; !isdone && ii < A_MAX; ii++) {
1203. 			if(ABASE(i) < AMAX(i)) {
1204. 			    ABASE(i)++;
1205. 			    /* only first found if not blessed */
1206. 			    isdone = !(obj->blessed);
1207. 			    flags.botl = 1;
1208. 			}
1209. 			if(++i >= A_MAX) i = 0;
1210. 		    }
1211. 		}
1212. 		break;
1213. 	case POT_FULL_HEALING:
1214. 		if (Upolyd && u.mh < u.mhmax) u.mh++, flags.botl = 1;
1215. 		if (u.uhp < u.uhpmax) u.uhp++, flags.botl = 1;
1216. 		/*FALL THROUGH*/
1217. 	case POT_EXTRA_HEALING:
1218. 		if (Upolyd && u.mh < u.mhmax) u.mh++, flags.botl = 1;
1219. 		if (u.uhp < u.uhpmax) u.uhp++, flags.botl = 1;
1220. 		/*FALL THROUGH*/
1221. 	case POT_HEALING:
1222. 		if (Upolyd && u.mh < u.mhmax) u.mh++, flags.botl = 1;
1223. 		if (u.uhp < u.uhpmax) u.uhp++, flags.botl = 1;
1224. 		exercise(A_CON, TRUE);
1225. 		break;
1226. 	case POT_SICKNESS:
1227. 		if (!Role_if(PM_HEALER)) {
1228. 			if (Upolyd) {
1229. 			    if (u.mh <= 5) u.mh = 1; else u.mh -= 5;
1230. 			} else {
1231. 			    if (u.uhp <= 5) u.uhp = 1; else u.uhp -= 5;
1232. 			}
1233. 			flags.botl = 1;
1234. 			exercise(A_CON, FALSE);
1235. 		}
1236. 		break;
1237. 	case POT_HALLUCINATION:
1238. 		You("have a momentary vision.");
1239. 		break;
1240. 	case POT_CONFUSION:
1241. 	case POT_BOOZE:
1242. 		if(!Confusion)
1243. 			You_feel("somewhat dizzy.");
1244. 		make_confused(itimeout_incr(HConfusion, rnd(5)), FALSE);
1245. 		break;
1246. 	case POT_INVISIBILITY:
1247. 		if (!Blind && !Invis) {
1248. 		    kn++;
1249. 		    pline("For an instant you %s!",
1250. 			See_invisible ? "could see right through yourself"
1251. 			: "couldn't see yourself");
1252. 		}
1253. 		break;
1254. 	case POT_PARALYSIS:
1255. 		kn++;
1256. 		if (!Free_action) {
1257. 		    pline("%s seems to be holding you.", Something);
1258. 		    nomul(-rnd(5));
1259. 		    nomovemsg = You_can_move_again;
1260. 		    exercise(A_DEX, FALSE);
1261. 		} else You("stiffen momentarily.");
1262. 		break;
1263. 	case POT_SLEEPING:
1264. 		kn++;
1265. 		if (!Free_action && !Sleep_resistance) {
1266. 		    You_feel("rather tired.");
1267. 		    nomul(-rnd(5));
1268. 		    nomovemsg = You_can_move_again;
1269. 		    exercise(A_DEX, FALSE);
1270. 		} else You("yawn.");
1271. 		break;
1272. 	case POT_SPEED:
1273. 		if (!Fast) Your("knees seem more flexible now.");
1274. 		incr_itimeout(&HFast, rnd(5));
1275. 		exercise(A_DEX, TRUE);
1276. 		break;
1277. 	case POT_BLINDNESS:
1278. 		if (!Blind && !u.usleep) {
1279. 		    kn++;
1280. 		    pline("It suddenly gets dark.");
1281. 		}
1282. 		make_blinded(itimeout_incr(Blinded, rnd(5)), FALSE);
1283. 		if (!Blind && !u.usleep) Your(vision_clears);
1284. 		break;
1285. 	case POT_WATER:
1286. 		if(u.umonnum == PM_GREMLIN) {
1287. 		    (void)split_mon(&youmonst, (struct monst *)0);
1288. 		} else if (u.ulycn >= LOW_PM) {
1289. 		    /* vapor from [un]holy water will trigger
1290. 		       transformation but won't cure lycanthropy */
1291. 		    if (obj->blessed && youmonst.data == &mons[u.ulycn])
1292. 			you_unwere(FALSE);
1293. 		    else if (obj->cursed && !Upolyd)
1294. 			you_were();
1295. 		}
1296. 		break;
1297. 	case POT_ACID:
1298. 	case POT_POLYMORPH:
1299. 		exercise(A_CON, FALSE);
1300. 		break;
1301. /*
1302. 	case POT_GAIN_LEVEL:
1303. 	case POT_LEVITATION:
1304. 	case POT_FRUIT_JUICE:
1305. 	case POT_MONSTER_DETECTION:
1306. 	case POT_OBJECT_DETECTION:
1307. 	case POT_OIL:
1308. 		break;
1309. */
1310. 	}
1311. 	/* note: no obfree() */
1312. 	if (obj->dknown) {
1313. 	    if (kn)
1314. 		makeknown(obj->otyp);
1315. 	    else if (!objects[obj->otyp].oc_name_known &&
1316. 						!objects[obj->otyp].oc_uname)
1317. 		docall(obj);
1318. 	}
1319. }
1320. 

mixtype[]

1321. STATIC_OVL short
1322. mixtype(o1, o2)
1323. register struct obj *o1, *o2;
1324. /* returns the potion type when o1 is dipped in o2 */
1325. {
1326. 	/* cut down on the number of cases below */
1327. 	if (o1->oclass == POTION_CLASS &&
1328. 	    (o2->otyp == POT_GAIN_LEVEL ||
1329. 	     o2->otyp == POT_GAIN_ENERGY ||
1330. 	     o2->otyp == POT_HEALING ||
1331. 	     o2->otyp == POT_EXTRA_HEALING ||
1332. 	     o2->otyp == POT_FULL_HEALING ||
1333. 	     o2->otyp == POT_ENLIGHTENMENT ||
1334. 	     o2->otyp == POT_FRUIT_JUICE)) {
1335. 		struct obj *swp;
1336. 
1337. 		swp = o1; o1 = o2; o2 = swp;
1338. 	}
1339. 
1340. 	switch (o1->otyp) {
1341. 		case POT_HEALING:
1342. 			switch (o2->otyp) {
1343. 			    case POT_SPEED:
1344. 			    case POT_GAIN_LEVEL:
1345. 			    case POT_GAIN_ENERGY:
1346. 				return POT_EXTRA_HEALING;
1347. 			}
1348. 		case POT_EXTRA_HEALING:
1349. 			switch (o2->otyp) {
1350. 			    case POT_GAIN_LEVEL:
1351. 			    case POT_GAIN_ENERGY:
1352. 				return POT_FULL_HEALING;
1353. 			}
1354. 		case POT_FULL_HEALING:
1355. 			switch (o2->otyp) {
1356. 			    case POT_GAIN_LEVEL:
1357. 			    case POT_GAIN_ENERGY:
1358. 				return POT_GAIN_ABILITY;
1359. 			}
1360. 		case UNICORN_HORN:
1361. 			switch (o2->otyp) {
1362. 			    case POT_SICKNESS:
1363. 				return POT_FRUIT_JUICE;
1364. 			    case POT_HALLUCINATION:
1365. 			    case POT_BLINDNESS:
1366. 			    case POT_CONFUSION:
1367. 				return POT_WATER;
1368. 			}
1369. 			break;
1370. 		case AMETHYST:		/* "a-methyst" == "not intoxicated" */
1371. 			if (o2->otyp == POT_BOOZE)
1372. 			    return POT_FRUIT_JUICE;
1373. 			break;
1374. 		case POT_GAIN_LEVEL:
1375. 		case POT_GAIN_ENERGY:
1376. 			switch (o2->otyp) {
1377. 			    case POT_CONFUSION:
1378. 				return (rn2(3) ? POT_BOOZE : POT_ENLIGHTENMENT);
1379. 			    case POT_HEALING:
1380. 				return POT_EXTRA_HEALING;
1381. 			    case POT_EXTRA_HEALING:
1382. 				return POT_FULL_HEALING;
1383. 			    case POT_FULL_HEALING:
1384. 				return POT_GAIN_ABILITY;
1385. 			    case POT_FRUIT_JUICE:
1386. 				return POT_SEE_INVISIBLE;
1387. 			    case POT_BOOZE:
1388. 				return POT_HALLUCINATION;
1389. 			}
1390. 			break;
1391. 		case POT_FRUIT_JUICE:
1392. 			switch (o2->otyp) {
1393. 			    case POT_SICKNESS:
1394. 				return POT_SICKNESS;
1395. 			    case POT_SPEED:
1396. 				return POT_BOOZE;
1397. 			    case POT_GAIN_LEVEL:
1398. 			    case POT_GAIN_ENERGY:
1399. 				return POT_SEE_INVISIBLE;
1400. 			}
1401. 			break;
1402. 		case POT_ENLIGHTENMENT:
1403. 			switch (o2->otyp) {
1404. 			    case POT_LEVITATION:
1405. 				if (rn2(3)) return POT_GAIN_LEVEL;
1406. 				break;
1407. 			    case POT_FRUIT_JUICE:
1408. 				return POT_BOOZE;
1409. 			    case POT_BOOZE:
1410. 				return POT_CONFUSION;
1411. 			}
1412. 			break;
1413. 	}
1414. 
1415. 	return 0;
1416. }
1417. 
1418. 

get_wet[]

1419. boolean
1420. get_wet(obj)
1421. register struct obj *obj;
1422. /* returns TRUE if something happened (potion should be used up) */
1423. {
1424. 	char Your_buf[BUFSZ];
1425. 
1426. 	if (snuff_lit(obj)) return(TRUE);
1427. 
1428. 	if (obj->greased) {
1429. 		grease_protect(obj,(char *)0,&youmonst);
1430. 		return(FALSE);
1431. 	}
1432. 	(void) Shk_Your(Your_buf, obj);
1433. 	/* (Rusting shop goods ought to be charged for.) */
1434. 	switch (obj->oclass) {
1435. 	    case POTION_CLASS:
1436. 		if (obj->otyp == POT_WATER) return FALSE;
1437. 		/* KMH -- Water into acid causes an explosion */
1438. 		if (obj->otyp == POT_ACID) {
1439. 			pline("It boils vigorously!");
1440. 			You("are caught in the explosion!");
1441. 			losehp(rnd(10), "elementary chemistry", KILLED_BY);
1442. 			makeknown(obj->otyp);
1443. 			update_inventory();
1444. 			return (TRUE);
1445. 		}
1446. 		pline("%s %s%s.", Your_buf, aobjnam(obj,"dilute"),
1447. 		      obj->odiluted ? " further" : "");
1448. 		if(obj->unpaid && costly_spot(u.ux, u.uy)) {
1449. 		    You("dilute it, you pay for it.");
1450. 		    bill_dummy_object(obj);
1451. 		}
1452. 		if (obj->odiluted) {
1453. 			obj->odiluted = 0;
1454. #ifdef UNIXPC
1455. 			obj->blessed = FALSE;
1456. 			obj->cursed = FALSE;
1457. #else
1458. 			obj->blessed = obj->cursed = FALSE;
1459. #endif
1460. 			obj->otyp = POT_WATER;
1461. 		} else obj->odiluted++;
1462. 		update_inventory();
1463. 		return TRUE;
1464. 	    case SCROLL_CLASS:
1465. 		if (obj->otyp != SCR_BLANK_PAPER
1466. #ifdef MAIL
1467. 		    && obj->otyp != SCR_MAIL
1468. #endif
1469. 		    ) {
1470. 			if (!Blind) {
1471. 				boolean oq1 = obj->quan == 1L;
1472. 				pline_The("scroll%s %s.",
1473. 					  oq1 ? "" : "s", otense(obj, "fade"));
1474. 			}
1475. 			if(obj->unpaid && costly_spot(u.ux, u.uy)) {
1476. 			    You("erase it, you pay for it.");
1477. 			    bill_dummy_object(obj);
1478. 			}
1479. 			obj->otyp = SCR_BLANK_PAPER;
1480. 			obj->spe = 0;
1481. 			update_inventory();
1482. 			return TRUE;
1483. 		} else break;
1484. 	    case SPBOOK_CLASS:
1485. 		if (obj->otyp != SPE_BLANK_PAPER) {
1486. 
1487. 			if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
1488. 	pline("%s suddenly heats up; steam rises and it remains dry.",
1489. 				The(xname(obj)));
1490. 			} else {
1491. 			    if (!Blind) {
1492. 				    boolean oq1 = obj->quan == 1L;
1493. 				    pline_The("spellbook%s %s.",
1494. 					oq1 ? "" : "s", otense(obj, "fade"));
1495. 			    }
1496. 			    if(obj->unpaid && costly_spot(u.ux, u.uy)) {
1497. 			        You("erase it, you pay for it.");
1498. 			        bill_dummy_object(obj);
1499. 			    }
1500. 			    obj->otyp = SPE_BLANK_PAPER;
1501. 			    update_inventory();
1502. 			}
1503. 			return TRUE;
1504. 		}
1505. 		break;
1506. 	    case WEAPON_CLASS:
1507. 	    /* Just "fall through" to generic rustprone check for now. */
1508. 	    /* fall through */
1509. 	    default:
1510. 		if (!obj->oerodeproof && is_rustprone(obj) &&
1511. 		    (obj->oeroded < MAX_ERODE) && !rn2(2)) {
1512. 			pline("%s %s some%s.",
1513. 			      Your_buf, aobjnam(obj, "rust"),
1514. 			      obj->oeroded ? " more" : "what");
1515. 			obj->oeroded++;
1516. 			update_inventory();
1517. 			return TRUE;
1518. 		} else break;
1519. 	}
1520. 	pline("%s %s wet.", Your_buf, aobjnam(obj,"get"));
1521. 	return FALSE;
1522. }
1523. 

dodip[]

1524. int
1525. dodip()
1526. {
1527. 	register struct obj *potion, *obj;
1528. 	struct obj *singlepotion;
1529. 	const char *tmp;
1530. 	uchar here;
1531. 	char allowall[2];
1532. 	short mixture;
1533. 	char qbuf[QBUFSZ], Your_buf[BUFSZ];
1534. 
1535. 	allowall[0] = ALL_CLASSES; allowall[1] = '\0';
1536. 	if(!(obj = getobj(allowall, "dip")))
1537. 		return(0);
1538. 
1539. 	here = levl[u.ux][u.uy].typ;
1540. 	/* Is there a fountain to dip into here? */
1541. 	if (IS_FOUNTAIN(here)) {
1542. 		if(yn("Dip it into the fountain?") == 'y') {
1543. 			dipfountain(obj);
1544. 			return(1);
1545. 		}
1546. 	} else if (is_pool(u.ux,u.uy)) {
1547. 		tmp = waterbody_name(u.ux,u.uy);
1548. 		Sprintf(qbuf, "Dip it into the %s?", tmp);
1549. 		if (yn(qbuf) == 'y') {
1550. 		    if (Levitation) {
1551. 			floating_above(tmp);
1552. #ifdef STEED
1553. 		    } else if (u.usteed && !is_swimmer(u.usteed->data) &&
1554. 			    P_SKILL(P_RIDING) < P_BASIC) {
1555. 			rider_cant_reach(); /* not skilled enough to reach */
1556. #endif
1557. 		    } else {
1558. 			(void) get_wet(obj);
1559. 			if (obj->otyp == POT_ACID) useup(obj);
1560. 		    }
1561. 		    return 1;
1562. 		}
1563. 	}
1564. 
1565. 	if(!(potion = getobj(beverages, "dip into")))
1566. 		return(0);
1567. 	if (potion == obj && potion->quan == 1L) {
1568. 		pline("That is a potion bottle, not a Klein bottle!");
1569. 		return 0;
1570. 	}
1571. 	potion->in_use = TRUE;		/* assume it will be used up */
1572. 	if(potion->otyp == POT_WATER) {
1573. 		boolean useeit = !Blind;
1574. 		if (useeit) (void) Shk_Your(Your_buf, obj);
1575. 		if (potion->blessed) {
1576. 			if (obj->cursed) {
1577. 				if (useeit)
1578. 				    pline("%s %s %s.",
1579. 					  Your_buf,
1580. 					  aobjnam(obj, "softly glow"),
1581. 					  hcolor(NH_AMBER));
1582. 				uncurse(obj);
1583. 				obj->bknown=1;
1584. 	poof:
1585. 				if(!(objects[potion->otyp].oc_name_known) &&
1586. 				   !(objects[potion->otyp].oc_uname))
1587. 					docall(potion);
1588. 				useup(potion);
1589. 				return(1);
1590. 			} else if(!obj->blessed) {
1591. 				if (useeit) {
1592. 				    tmp = hcolor(NH_LIGHT_BLUE);
1593. 				    pline("%s %s with a%s %s aura.",
1594. 					  Your_buf,
1595. 					  aobjnam(obj, "softly glow"),
1596. 					  index(vowels, *tmp) ? "n" : "", tmp);
1597. 				}
1598. 				bless(obj);
1599. 				obj->bknown=1;
1600. 				goto poof;
1601. 			}
1602. 		} else if (potion->cursed) {
1603. 			if (obj->blessed) {
1604. 				if (useeit)
1605. 				    pline("%s %s %s.",
1606. 					  Your_buf,
1607. 					  aobjnam(obj, "glow"),
1608. 					  hcolor((const char *)"brown"));
1609. 				unbless(obj);
1610. 				obj->bknown=1;
1611. 				goto poof;
1612. 			} else if(!obj->cursed) {
1613. 				if (useeit) {
1614. 				    tmp = hcolor(NH_BLACK);
1615. 				    pline("%s %s with a%s %s aura.",
1616. 					  Your_buf,
1617. 					  aobjnam(obj, "glow"),
1618. 					  index(vowels, *tmp) ? "n" : "", tmp);
1619. 				}
1620. 				curse(obj);
1621. 				obj->bknown=1;
1622. 				goto poof;
1623. 			}
1624. 		} else
1625. 			if (get_wet(obj))
1626. 			    goto poof;
1627. 	} else if (obj->otyp == POT_POLYMORPH ||
1628. 		potion->otyp == POT_POLYMORPH) {
1629. 	    /* some objects can't be polymorphed */
1630. 	    if (obj->otyp == potion->otyp ||	/* both POT_POLY */
1631. 		    obj->otyp == WAN_POLYMORPH ||
1632. 		    obj->otyp == SPE_POLYMORPH ||
1633. 		    obj == uball || obj == uskin ||
1634. 		    obj_resists(obj->otyp == POT_POLYMORPH ?
1635. 				potion : obj, 5, 95)) {
1636. 		pline(nothing_happens);
1637. 	    } else {
1638. 	    	boolean was_wep = FALSE, was_swapwep = FALSE, was_quiver = FALSE;
1639. 		short save_otyp = obj->otyp;
1640. 		/* KMH, conduct */
1641. 		u.uconduct.polypiles++;
1642. 
1643. 		if (obj == uwep) was_wep = TRUE;
1644. 		else if (obj == uswapwep) was_swapwep = TRUE;
1645. 		else if (obj == uquiver) was_quiver = TRUE;
1646. 
1647. 		obj = poly_obj(obj, STRANGE_OBJECT);
1648. 
1649. 		if (was_wep) setuwep(obj);
1650. 		else if (was_swapwep) setuswapwep(obj);
1651. 		else if (was_quiver) setuqwep(obj);
1652. 
1653. 		if (obj->otyp != save_otyp) {
1654. 			makeknown(POT_POLYMORPH);
1655. 			useup(potion);
1656. 			prinv((char *)0, obj, 0L);
1657. 			return 1;
1658. 		} else {
1659. 			pline("Nothing seems to happen.");
1660. 			goto poof;
1661. 		}
1662. 	    }
1663. 	    potion->in_use = FALSE;	/* didn't go poof */
1664. 	    return(1);
1665. 	} else if(obj->oclass == POTION_CLASS && obj->otyp != potion->otyp) {
1666. 		/* Mixing potions is dangerous... */
1667. 		pline_The("potions mix...");
1668. 		/* KMH, balance patch -- acid is particularly unstable */
1669. 		if (obj->cursed || obj->otyp == POT_ACID || !rn2(10)) {
1670. 			pline("BOOM!  They explode!");
1671. 			exercise(A_STR, FALSE);
1672. 			if (!breathless(youmonst.data) || haseyes(youmonst.data))
1673. 				potionbreathe(obj);
1674. 			useup(obj);
1675. 			useup(potion);
1676. 			losehp(rnd(10), "alchemic blast", KILLED_BY_AN);
1677. 			return(1);
1678. 		}
1679. 
1680. 		obj->blessed = obj->cursed = obj->bknown = 0;
1681. 		if (Blind || Hallucination) obj->dknown = 0;
1682. 
1683. 		if ((mixture = mixtype(obj, potion)) != 0) {
1684. 			obj->otyp = mixture;
1685. 		} else {
1686. 		    switch (obj->odiluted ? 1 : rnd(8)) {
1687. 			case 1:
1688. 				obj->otyp = POT_WATER;
1689. 				break;
1690. 			case 2:
1691. 			case 3:
1692. 				obj->otyp = POT_SICKNESS;
1693. 				break;
1694. 			case 4:
1695. 				{
1696. 				  struct obj *otmp;
1697. 				  otmp = mkobj(POTION_CLASS,FALSE);
1698. 				  obj->otyp = otmp->otyp;
1699. 				  obfree(otmp, (struct obj *)0);
1700. 				}
1701. 				break;
1702. 			default:
1703. 				if (!Blind)
1704. 			  pline_The("mixture glows brightly and evaporates.");
1705. 				useup(obj);
1706. 				useup(potion);
1707. 				return(1);
1708. 		    }
1709. 		}
1710. 
1711. 		obj->odiluted = (obj->otyp != POT_WATER);
1712. 
1713. 		if (obj->otyp == POT_WATER && !Hallucination) {
1714. 			pline_The("mixture bubbles%s.",
1715. 				Blind ? "" : ", then clears");
1716. 		} else if (!Blind) {
1717. 			pline_The("mixture looks %s.",
1718. 				hcolor(OBJ_DESCR(objects[obj->otyp])));
1719. 		}
1720. 
1721. 		useup(potion);
1722. 		return(1);
1723. 	}
1724. 
1725. #ifdef INVISIBLE_OBJECTS
1726. 	if (potion->otyp == POT_INVISIBILITY && !obj->oinvis) {
1727. 		obj->oinvis = TRUE;
1728. 		if (!Blind) {
1729. 		    if (!See_invisible) pline("Where did %s go?",
1730. 		    		the(xname(obj)));
1731. 		    else You("notice a little haziness around %s.",
1732. 		    		the(xname(obj)));
1733. 		}
1734. 		goto poof;
1735. 	} else if (potion->otyp == POT_SEE_INVISIBLE && obj->oinvis) {
1736. 		obj->oinvis = FALSE;
1737. 		if (!Blind) {
1738. 		    if (!See_invisible) pline("So that's where %s went!",
1739. 		    		the(xname(obj)));
1740. 		    else pline_The("haziness around %s disappears.",
1741. 		    		the(xname(obj)));
1742. 		}
1743. 		goto poof;
1744. 	}
1745. #endif
1746. 
1747. 	if(is_poisonable(obj)) {
1748. 	    if(potion->otyp == POT_SICKNESS && !obj->opoisoned) {
1749. 		char buf[BUFSZ];
1750. 		if (potion->quan > 1L)
1751. 		    Sprintf(buf, "One of %s", the(xname(potion)));
1752. 		else
1753. 		    Strcpy(buf, The(xname(potion)));
1754. 		pline("%s forms a coating on %s.",
1755. 		      buf, the(xname(obj)));
1756. 		obj->opoisoned = TRUE;
1757. 		goto poof;
1758. 	    } else if(obj->opoisoned &&
1759. 		      (potion->otyp == POT_HEALING ||
1760. 		       potion->otyp == POT_EXTRA_HEALING ||
1761. 		       potion->otyp == POT_FULL_HEALING)) {
1762. 		pline("A coating wears off %s.", the(xname(obj)));
1763. 		obj->opoisoned = 0;
1764. 		goto poof;
1765. 	    }
1766. 	}
1767. 
1768. 	if (potion->otyp == POT_OIL) {
1769. 	    boolean wisx = FALSE;
1770. 	    if (potion->lamplit) {	/* burning */
1771. 		int omat = objects[obj->otyp].oc_material;
1772. 		/* the code here should be merged with fire_damage */
1773. 		if (catch_lit(obj)) {
1774. 		    /* catch_lit does all the work if true */
1775. 		} else if (obj->oerodeproof || obj_resists(obj, 5, 95) ||
1776. 			   !is_flammable(obj) || obj->oclass == FOOD_CLASS) {
1777. 		    pline("%s %s to burn for a moment.",
1778. 			  Yname2(obj), otense(obj, "seem"));
1779. 		} else {
1780. 		    if ((omat == PLASTIC || omat == PAPER) && !obj->oartifact)
1781. 			obj->oeroded = MAX_ERODE;
1782. 		    pline_The("burning oil %s %s.",
1783. 			    obj->oeroded == MAX_ERODE ? "destroys" : "damages",
1784. 			    yname(obj));
1785. 		    if (obj->oeroded == MAX_ERODE) {
1786. 			obj_extract_self(obj);
1787. 			obfree(obj, (struct obj *)0);
1788. 			obj = (struct obj *) 0;
1789. 		    } else {
1790. 			/* we know it's carried */
1791. 			if (obj->unpaid) {
1792. 			    /* create a dummy duplicate to put on bill */
1793. 			    verbalize("You burnt it, you bought it!");
1794. 			    bill_dummy_object(obj);
1795. 			}
1796. 			obj->oeroded++;
1797. 		    }
1798. 		}
1799. 	    } else if (potion->cursed) {
1800. 		pline_The("potion spills and covers your %s with oil.",
1801. 			  makeplural(body_part(FINGER)));
1802. 		incr_itimeout(&Glib, d(2,10));
1803. 	    } else if (obj->oclass != WEAPON_CLASS && !is_weptool(obj)) {
1804. 		/* the following cases apply only to weapons */
1805. 		goto more_dips;
1806. 	    /* Oil removes rust and corrosion, but doesn't unburn.
1807. 	     * Arrows, etc are classed as metallic due to arrowhead
1808. 	     * material, but dipping in oil shouldn't repair them.
1809. 	     */
1810. 	    } else if ((!is_rustprone(obj) && !is_corrodeable(obj)) ||
1811. 			is_ammo(obj) || (!obj->oeroded && !obj->oeroded2)) {
1812. 		/* uses up potion, doesn't set obj->greased */
1813. 		pline("%s %s with an oily sheen.",
1814. 		      Yname2(obj), otense(obj, "gleam"));
1815. 	    } else {
1816. 		pline("%s %s less %s.",
1817. 		      Yname2(obj), otense(obj, "are"),
1818. 		      (obj->oeroded && obj->oeroded2) ? "corroded and rusty" :
1819. 			obj->oeroded ? "rusty" : "corroded");
1820. 		if (obj->oeroded > 0) obj->oeroded--;
1821. 		if (obj->oeroded2 > 0) obj->oeroded2--;
1822. 		wisx = TRUE;
1823. 	    }
1824. 	    exercise(A_WIS, wisx);
1825. 	    makeknown(potion->otyp);
1826. 	    useup(potion);
1827. 	    return 1;
1828. 	}
1829.     more_dips:
1830. 
1831. 	/* Allow filling of MAGIC_LAMPs to prevent identification by player */
1832. 	if ((obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP) &&
1833. 	   (potion->otyp == POT_OIL)) {
1834. 	    /* Turn off engine before fueling, turn off fuel too :-)  */
1835. 	    if (obj->lamplit || potion->lamplit) {
1836. 		useup(potion);
1837. 		explode(u.ux, u.uy, 11, d(6,6), 0, EXPL_FIERY);
1838. 		exercise(A_WIS, FALSE);
1839. 		return 1;
1840. 	    }
1841. 	    /* Adding oil to an empty magic lamp renders it into an oil lamp */
1842. 	    if ((obj->otyp == MAGIC_LAMP) && obj->spe == 0) {
1843. 		obj->otyp = OIL_LAMP;
1844. 		obj->age = 0;
1845. 	    }
1846. 	    if (obj->age > 1000L) {
1847. 		pline("%s %s full.", Yname2(obj), otense(obj, "are"));
1848. 		potion->in_use = FALSE;	/* didn't go poof */
1849. 	    } else {
1850. 		You("fill %s with oil.", yname(obj));
1851. 		check_unpaid(potion);	/* Yendorian Fuel Tax */
1852. 		obj->age += 2*potion->age;	/* burns more efficiently */
1853. 		if (obj->age > 1500L) obj->age = 1500L;
1854. 		useup(potion);
1855. 		exercise(A_WIS, TRUE);
1856. 	    }
1857. 	    makeknown(POT_OIL);
1858. 	    obj->spe = 1;
1859. 	    update_inventory();
1860. 	    return 1;
1861. 	}
1862. 
1863. 	potion->in_use = FALSE;		/* didn't go poof */
1864. 	if ((obj->otyp == UNICORN_HORN || obj->otyp == AMETHYST) &&
1865. 	    (mixture = mixtype(obj, potion)) != 0) {
1866. 		char oldbuf[BUFSZ], newbuf[BUFSZ];
1867. 		short old_otyp = potion->otyp;
1868. 		boolean old_dknown = FALSE;
1869. 		boolean more_than_one = potion->quan > 1;
1870. 
1871. 		oldbuf[0] = '\0';
1872. 		if (potion->dknown) {
1873. 		    old_dknown = TRUE;
1874. 		    Sprintf(oldbuf, "%s ",
1875. 			    hcolor(OBJ_DESCR(objects[potion->otyp])));
1876. 		}
1877. 		/* with multiple merged potions, split off one and
1878. 		   just clear it */
1879. 		if (potion->quan > 1L) {
1880. 		    singlepotion = splitobj(potion, 1L);
1881. 		} else singlepotion = potion;
1882. 		
1883. 		if(singlepotion->unpaid && costly_spot(u.ux, u.uy)) {
1884. 		    You("use it, you pay for it.");
1885. 		    bill_dummy_object(singlepotion);
1886. 		}
1887. 		singlepotion->otyp = mixture;
1888. 		singlepotion->blessed = 0;
1889. 		if (mixture == POT_WATER)
1890. 		    singlepotion->cursed = singlepotion->odiluted = 0;
1891. 		else
1892. 		    singlepotion->cursed = obj->cursed;  /* odiluted left as-is */
1893. 		singlepotion->bknown = FALSE;
1894. 		if (Blind) {
1895. 		    singlepotion->dknown = FALSE;
1896. 		} else {
1897. 		    singlepotion->dknown = !Hallucination;
1898. 		    if (mixture == POT_WATER && singlepotion->dknown)
1899. 			Sprintf(newbuf, "clears");
1900. 		    else
1901. 			Sprintf(newbuf, "turns %s",
1902. 				hcolor(OBJ_DESCR(objects[mixture])));
1903. 		    pline_The("%spotion%s %s.", oldbuf,
1904. 			      more_than_one ? " that you dipped into" : "",
1905. 			      newbuf);
1906. 		    if(!objects[old_otyp].oc_uname &&
1907. 			!objects[old_otyp].oc_name_known && old_dknown) {
1908. 			struct obj fakeobj;
1909. 			fakeobj = zeroobj;
1910. 			fakeobj.dknown = 1;
1911. 			fakeobj.otyp = old_otyp;
1912. 			fakeobj.oclass = POTION_CLASS;
1913. 			docall(&fakeobj);
1914. 		    }
1915. 		}
1916. 		obj_extract_self(singlepotion);
1917. 		singlepotion = hold_another_object(singlepotion,
1918. 					"You juggle and drop %s!",
1919. 					doname(singlepotion), (const char *)0);
1920. 		update_inventory();
1921. 		return(1);
1922. 	}
1923. 
1924. 	pline("Interesting...");
1925. 	return(1);
1926. }
1927. 
1928. 

djinni_from_bottle[]

1929. void
1930. djinni_from_bottle(obj)
1931. register struct obj *obj;
1932. {
1933. 	struct monst *mtmp;
1934. 	int chance;
1935. 
1936. 	if(!(mtmp = makemon(&mons[PM_DJINNI], u.ux, u.uy, NO_MM_FLAGS))){
1937. 		pline("It turns out to be empty.");
1938. 		return;
1939. 	}
1940. 
1941. 	if (!Blind) {
1942. 		pline("In a cloud of smoke, %s emerges!", a_monnam(mtmp));
1943. 		pline("%s speaks.", Monnam(mtmp));
1944. 	} else {
1945. 		You("smell acrid fumes.");
1946. 		pline("%s speaks.", Something);
1947. 	}
1948. 
1949. 	chance = rn2(5);
1950. 	if (obj->blessed) chance = (chance == 4) ? rnd(4) : 0;
1951. 	else if (obj->cursed) chance = (chance == 0) ? rn2(4) : 4;
1952. 	/* 0,1,2,3,4:  b=80%,5,5,5,5; nc=20%,20,20,20,20; c=5%,5,5,5,80 */
1953. 
1954. 	switch (chance) {
1955. 	case 0 : verbalize("I am in your debt.  I will grant one wish!");
1956. 		makewish();
1957. 		mongone(mtmp);
1958. 		break;
1959. 	case 1 : verbalize("Thank you for freeing me!");
1960. 		(void) tamedog(mtmp, (struct obj *)0);
1961. 		break;
1962. 	case 2 : verbalize("You freed me!");
1963. 		mtmp->mpeaceful = TRUE;
1964. 		set_malign(mtmp);
1965. 		break;
1966. 	case 3 : verbalize("It is about time!");
1967. 		pline("%s vanishes.", Monnam(mtmp));
1968. 		mongone(mtmp);
1969. 		break;
1970. 	default: verbalize("You disturbed me, fool!");
1971. 		break;
1972. 	}
1973. }
1974. 

split_mon[]

1975. /* clone a gremlin or mold (2nd arg non-null implies heat as the trigger);
1976.    hit points are cut in half (odd HP stays with original) */
1977. struct monst *
1978. split_mon(mon, mtmp)
1979. struct monst *mon,	/* monster being split */
1980. 	     *mtmp;	/* optional attacker whose heat triggered it */
1981. {
1982. 	struct monst *mtmp2;
1983. 	char reason[BUFSZ];
1984. 
1985. 	reason[0] = '\0';
1986. 	if (mtmp) Sprintf(reason, " from %s heat",
1987. 			  (mtmp == &youmonst) ? (const char *)"your" :
1988. 			      (const char *)s_suffix(mon_nam(mtmp)));
1989. 
1990. 	if (mon == &youmonst) {
1991. 	    mtmp2 = cloneu();
1992. 	    if (mtmp2) {
1993. 		mtmp2->mhpmax = u.mhmax / 2;
1994. 		u.mhmax -= mtmp2->mhpmax;
1995. 		flags.botl = 1;
1996. 		You("multiply%s!", reason);
1997. 	    }
1998. 	} else {
1999. 	    mtmp2 = clone_mon(mon, 0, 0);
2000. 	    if (mtmp2) {
2001. 		mtmp2->mhpmax = mon->mhpmax / 2;
2002. 		mon->mhpmax -= mtmp2->mhpmax;
2003. 		if (canspotmon(mon))
2004. 		    pline("%s multiplies%s!", Monnam(mon), reason);
2005. 	    }
2006. 	}
2007. 	return mtmp2;
2008. }
2009. 
2010. #endif /* OVLB */
2011. 
2012. /*potion.c*/
Advertisement