Source:NetHack 3.4.3/src/potion.c

From NetHackWiki
Revision as of 14:49, 4 March 2008 by Kernigh bot (talk | contribs) (Potion.c moved to Source:Potion.c: Robot: moved page)
Jump to navigation Jump to search

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.

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.

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