Source:NetHack 3.1.0/potion.c

From NetHackWiki
Jump to navigation Jump to search

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

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

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

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

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