xref: /csrg-svn/games/hack/hack.potion.c (revision 41253)
1*41253Sbostic /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
2*41253Sbostic /* hack.potion.c - version 1.0.3 */
3*41253Sbostic 
4*41253Sbostic #include "hack.h"
5*41253Sbostic extern int float_down();
6*41253Sbostic extern char *nomovemsg;
7*41253Sbostic extern struct monst youmonst;
8*41253Sbostic extern struct monst *makemon();
9*41253Sbostic 
dodrink()10*41253Sbostic dodrink() {
11*41253Sbostic 	register struct obj *otmp,*objs;
12*41253Sbostic 	register struct monst *mtmp;
13*41253Sbostic 	register int unkn = 0, nothing = 0;
14*41253Sbostic 
15*41253Sbostic 	otmp = getobj("!", "drink");
16*41253Sbostic 	if(!otmp) return(0);
17*41253Sbostic 	if(!strcmp(objects[otmp->otyp].oc_descr, "smoky") && !rn2(13)) {
18*41253Sbostic 		ghost_from_bottle();
19*41253Sbostic 		goto use_it;
20*41253Sbostic 	}
21*41253Sbostic 	switch(otmp->otyp){
22*41253Sbostic 	case POT_RESTORE_STRENGTH:
23*41253Sbostic 		unkn++;
24*41253Sbostic 		pline("Wow!  This makes you feel great!");
25*41253Sbostic 		if(u.ustr < u.ustrmax) {
26*41253Sbostic 			u.ustr = u.ustrmax;
27*41253Sbostic 			flags.botl = 1;
28*41253Sbostic 		}
29*41253Sbostic 		break;
30*41253Sbostic 	case POT_BOOZE:
31*41253Sbostic 		unkn++;
32*41253Sbostic 		pline("Ooph!  This tastes like liquid fire!");
33*41253Sbostic 		Confusion += d(3,8);
34*41253Sbostic 		/* the whiskey makes us feel better */
35*41253Sbostic 		if(u.uhp < u.uhpmax) losehp(-1, "bottle of whiskey");
36*41253Sbostic 		if(!rn2(4)) {
37*41253Sbostic 			pline("You pass out.");
38*41253Sbostic 			multi = -rnd(15);
39*41253Sbostic 			nomovemsg = "You awake with a headache.";
40*41253Sbostic 		}
41*41253Sbostic 		break;
42*41253Sbostic 	case POT_INVISIBILITY:
43*41253Sbostic 		if(Invis || See_invisible)
44*41253Sbostic 		  nothing++;
45*41253Sbostic 		else {
46*41253Sbostic 		  if(!Blind)
47*41253Sbostic 		    pline("Gee!  All of a sudden, you can't see yourself.");
48*41253Sbostic 		  else
49*41253Sbostic 		    pline("You feel rather airy."), unkn++;
50*41253Sbostic 		  newsym(u.ux,u.uy);
51*41253Sbostic 		}
52*41253Sbostic 		Invis += rn1(15,31);
53*41253Sbostic 		break;
54*41253Sbostic 	case POT_FRUIT_JUICE:
55*41253Sbostic 		pline("This tastes like fruit juice.");
56*41253Sbostic 		lesshungry(20);
57*41253Sbostic 		break;
58*41253Sbostic 	case POT_HEALING:
59*41253Sbostic 		pline("You begin to feel better.");
60*41253Sbostic 		flags.botl = 1;
61*41253Sbostic 		u.uhp += rnd(10);
62*41253Sbostic 		if(u.uhp > u.uhpmax)
63*41253Sbostic 			u.uhp = ++u.uhpmax;
64*41253Sbostic 		if(Blind) Blind = 1;	/* see on next move */
65*41253Sbostic 		if(Sick) Sick = 0;
66*41253Sbostic 		break;
67*41253Sbostic 	case POT_PARALYSIS:
68*41253Sbostic 		if(Levitation)
69*41253Sbostic 			pline("You are motionlessly suspended.");
70*41253Sbostic 		else
71*41253Sbostic 			pline("Your feet are frozen to the floor!");
72*41253Sbostic 		nomul(-(rn1(10,25)));
73*41253Sbostic 		break;
74*41253Sbostic 	case POT_MONSTER_DETECTION:
75*41253Sbostic 		if(!fmon) {
76*41253Sbostic 			strange_feeling(otmp, "You feel threatened.");
77*41253Sbostic 			return(1);
78*41253Sbostic 		} else {
79*41253Sbostic 			cls();
80*41253Sbostic 			for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
81*41253Sbostic 				if(mtmp->mx > 0)
82*41253Sbostic 				at(mtmp->mx,mtmp->my,mtmp->data->mlet);
83*41253Sbostic 			prme();
84*41253Sbostic 			pline("You sense the presence of monsters.");
85*41253Sbostic 			more();
86*41253Sbostic 			docrt();
87*41253Sbostic 		}
88*41253Sbostic 		break;
89*41253Sbostic 	case POT_OBJECT_DETECTION:
90*41253Sbostic 		if(!fobj) {
91*41253Sbostic 			strange_feeling(otmp, "You feel a pull downward.");
92*41253Sbostic 			return(1);
93*41253Sbostic 		} else {
94*41253Sbostic 		    for(objs = fobj; objs; objs = objs->nobj)
95*41253Sbostic 			if(objs->ox != u.ux || objs->oy != u.uy)
96*41253Sbostic 				goto outobjmap;
97*41253Sbostic 		    pline("You sense the presence of objects close nearby.");
98*41253Sbostic 		    break;
99*41253Sbostic 		outobjmap:
100*41253Sbostic 			cls();
101*41253Sbostic 			for(objs = fobj; objs; objs = objs->nobj)
102*41253Sbostic 				at(objs->ox,objs->oy,objs->olet);
103*41253Sbostic 			prme();
104*41253Sbostic 			pline("You sense the presence of objects.");
105*41253Sbostic 			more();
106*41253Sbostic 			docrt();
107*41253Sbostic 		}
108*41253Sbostic 		break;
109*41253Sbostic 	case POT_SICKNESS:
110*41253Sbostic 		pline("Yech! This stuff tastes like poison.");
111*41253Sbostic 		if(Poison_resistance)
112*41253Sbostic     pline("(But in fact it was biologically contaminated orange juice.)");
113*41253Sbostic 		losestr(rn1(4,3));
114*41253Sbostic 		losehp(rnd(10), "contaminated potion");
115*41253Sbostic 		break;
116*41253Sbostic 	case POT_CONFUSION:
117*41253Sbostic 		if(!Confusion)
118*41253Sbostic 			pline("Huh, What?  Where am I?");
119*41253Sbostic 		else
120*41253Sbostic 			nothing++;
121*41253Sbostic 		Confusion += rn1(7,16);
122*41253Sbostic 		break;
123*41253Sbostic 	case POT_GAIN_STRENGTH:
124*41253Sbostic 		pline("Wow do you feel strong!");
125*41253Sbostic 		if(u.ustr >= 118) break;	/* > 118 is impossible */
126*41253Sbostic 		if(u.ustr > 17) u.ustr += rnd(118-u.ustr);
127*41253Sbostic 		else u.ustr++;
128*41253Sbostic 		if(u.ustr > u.ustrmax) u.ustrmax = u.ustr;
129*41253Sbostic 		flags.botl = 1;
130*41253Sbostic 		break;
131*41253Sbostic 	case POT_SPEED:
132*41253Sbostic 		if(Wounded_legs) {
133*41253Sbostic 			heal_legs();
134*41253Sbostic 			unkn++;
135*41253Sbostic 			break;
136*41253Sbostic 		}
137*41253Sbostic 		if(!(Fast & ~INTRINSIC))
138*41253Sbostic 			pline("You are suddenly moving much faster.");
139*41253Sbostic 		else
140*41253Sbostic 			pline("Your legs get new energy."), unkn++;
141*41253Sbostic 		Fast += rn1(10,100);
142*41253Sbostic 		break;
143*41253Sbostic 	case POT_BLINDNESS:
144*41253Sbostic 		if(!Blind)
145*41253Sbostic 			pline("A cloud of darkness falls upon you.");
146*41253Sbostic 		else
147*41253Sbostic 			nothing++;
148*41253Sbostic 		Blind += rn1(100,250);
149*41253Sbostic 		seeoff(0);
150*41253Sbostic 		break;
151*41253Sbostic 	case POT_GAIN_LEVEL:
152*41253Sbostic 		pluslvl();
153*41253Sbostic 		break;
154*41253Sbostic 	case POT_EXTRA_HEALING:
155*41253Sbostic 		pline("You feel much better.");
156*41253Sbostic 		flags.botl = 1;
157*41253Sbostic 		u.uhp += d(2,20)+1;
158*41253Sbostic 		if(u.uhp > u.uhpmax)
159*41253Sbostic 			u.uhp = (u.uhpmax += 2);
160*41253Sbostic 		if(Blind) Blind = 1;
161*41253Sbostic 		if(Sick) Sick = 0;
162*41253Sbostic 		break;
163*41253Sbostic 	case POT_LEVITATION:
164*41253Sbostic 		if(!Levitation)
165*41253Sbostic 			float_up();
166*41253Sbostic 		else
167*41253Sbostic 			nothing++;
168*41253Sbostic 		Levitation += rnd(100);
169*41253Sbostic 		u.uprops[PROP(RIN_LEVITATION)].p_tofn = float_down;
170*41253Sbostic 		break;
171*41253Sbostic 	default:
172*41253Sbostic 		impossible("What a funny potion! (%u)", otmp->otyp);
173*41253Sbostic 		return(0);
174*41253Sbostic 	}
175*41253Sbostic 	if(nothing) {
176*41253Sbostic 	    unkn++;
177*41253Sbostic 	    pline("You have a peculiar feeling for a moment, then it passes.");
178*41253Sbostic 	}
179*41253Sbostic 	if(otmp->dknown && !objects[otmp->otyp].oc_name_known) {
180*41253Sbostic 		if(!unkn) {
181*41253Sbostic 			objects[otmp->otyp].oc_name_known = 1;
182*41253Sbostic 			more_experienced(0,10);
183*41253Sbostic 		} else if(!objects[otmp->otyp].oc_uname)
184*41253Sbostic 			docall(otmp);
185*41253Sbostic 	}
186*41253Sbostic use_it:
187*41253Sbostic 	useup(otmp);
188*41253Sbostic 	return(1);
189*41253Sbostic }
190*41253Sbostic 
pluslvl()191*41253Sbostic pluslvl()
192*41253Sbostic {
193*41253Sbostic 	register num;
194*41253Sbostic 
195*41253Sbostic 	pline("You feel more experienced.");
196*41253Sbostic 	num = rnd(10);
197*41253Sbostic 	u.uhpmax += num;
198*41253Sbostic 	u.uhp += num;
199*41253Sbostic 	if(u.ulevel < 14) {
200*41253Sbostic 		extern long newuexp();
201*41253Sbostic 
202*41253Sbostic 		u.uexp = newuexp()+1;
203*41253Sbostic 		pline("Welcome to experience level %u.", ++u.ulevel);
204*41253Sbostic 	}
205*41253Sbostic 	flags.botl = 1;
206*41253Sbostic }
207*41253Sbostic 
strange_feeling(obj,txt)208*41253Sbostic strange_feeling(obj,txt)
209*41253Sbostic register struct obj *obj;
210*41253Sbostic register char *txt;
211*41253Sbostic {
212*41253Sbostic 	if(flags.beginner)
213*41253Sbostic 	    pline("You have a strange feeling for a moment, then it passes.");
214*41253Sbostic 	else
215*41253Sbostic 	    pline(txt);
216*41253Sbostic 	if(!objects[obj->otyp].oc_name_known && !objects[obj->otyp].oc_uname)
217*41253Sbostic 		docall(obj);
218*41253Sbostic 	useup(obj);
219*41253Sbostic }
220*41253Sbostic 
221*41253Sbostic char *bottlenames[] = {
222*41253Sbostic 	"bottle", "phial", "flagon", "carafe", "flask", "jar", "vial"
223*41253Sbostic };
224*41253Sbostic 
potionhit(mon,obj)225*41253Sbostic potionhit(mon, obj)
226*41253Sbostic register struct monst *mon;
227*41253Sbostic register struct obj *obj;
228*41253Sbostic {
229*41253Sbostic 	extern char *xname();
230*41253Sbostic 	register char *botlnam = bottlenames[rn2(SIZE(bottlenames))];
231*41253Sbostic 	boolean uclose, isyou = (mon == &youmonst);
232*41253Sbostic 
233*41253Sbostic 	if(isyou) {
234*41253Sbostic 		uclose = TRUE;
235*41253Sbostic 		pline("The %s crashes on your head and breaks into shivers.",
236*41253Sbostic 			botlnam);
237*41253Sbostic 		losehp(rnd(2), "thrown potion");
238*41253Sbostic 	} else {
239*41253Sbostic 		uclose = (dist(mon->mx,mon->my) < 3);
240*41253Sbostic 		/* perhaps 'E' and 'a' have no head? */
241*41253Sbostic 		pline("The %s crashes on %s's head and breaks into shivers.",
242*41253Sbostic 			botlnam, monnam(mon));
243*41253Sbostic 		if(rn2(5) && mon->mhp > 1)
244*41253Sbostic 			mon->mhp--;
245*41253Sbostic 	}
246*41253Sbostic 	pline("The %s evaporates.", xname(obj));
247*41253Sbostic 
248*41253Sbostic 	if(!isyou && !rn2(3)) switch(obj->otyp) {
249*41253Sbostic 
250*41253Sbostic 	case POT_RESTORE_STRENGTH:
251*41253Sbostic 	case POT_GAIN_STRENGTH:
252*41253Sbostic 	case POT_HEALING:
253*41253Sbostic 	case POT_EXTRA_HEALING:
254*41253Sbostic 		if(mon->mhp < mon->mhpmax) {
255*41253Sbostic 			mon->mhp = mon->mhpmax;
256*41253Sbostic 			pline("%s looks sound and hale again!", Monnam(mon));
257*41253Sbostic 		}
258*41253Sbostic 		break;
259*41253Sbostic 	case POT_SICKNESS:
260*41253Sbostic 		if(mon->mhpmax > 3)
261*41253Sbostic 			mon->mhpmax /= 2;
262*41253Sbostic 		if(mon->mhp > 2)
263*41253Sbostic 			mon->mhp /= 2;
264*41253Sbostic 		break;
265*41253Sbostic 	case POT_CONFUSION:
266*41253Sbostic 	case POT_BOOZE:
267*41253Sbostic 		mon->mconf = 1;
268*41253Sbostic 		break;
269*41253Sbostic 	case POT_INVISIBILITY:
270*41253Sbostic 		unpmon(mon);
271*41253Sbostic 		mon->minvis = 1;
272*41253Sbostic 		pmon(mon);
273*41253Sbostic 		break;
274*41253Sbostic 	case POT_PARALYSIS:
275*41253Sbostic 		mon->mfroz = 1;
276*41253Sbostic 		break;
277*41253Sbostic 	case POT_SPEED:
278*41253Sbostic 		mon->mspeed = MFAST;
279*41253Sbostic 		break;
280*41253Sbostic 	case POT_BLINDNESS:
281*41253Sbostic 		mon->mblinded |= 64 + rn2(64);
282*41253Sbostic 		break;
283*41253Sbostic /*
284*41253Sbostic 	case POT_GAIN_LEVEL:
285*41253Sbostic 	case POT_LEVITATION:
286*41253Sbostic 	case POT_FRUIT_JUICE:
287*41253Sbostic 	case POT_MONSTER_DETECTION:
288*41253Sbostic 	case POT_OBJECT_DETECTION:
289*41253Sbostic 		break;
290*41253Sbostic */
291*41253Sbostic 	}
292*41253Sbostic 	if(uclose && rn2(5))
293*41253Sbostic 		potionbreathe(obj);
294*41253Sbostic 	obfree(obj, Null(obj));
295*41253Sbostic }
296*41253Sbostic 
potionbreathe(obj)297*41253Sbostic potionbreathe(obj)
298*41253Sbostic register struct obj *obj;
299*41253Sbostic {
300*41253Sbostic 	switch(obj->otyp) {
301*41253Sbostic 	case POT_RESTORE_STRENGTH:
302*41253Sbostic 	case POT_GAIN_STRENGTH:
303*41253Sbostic 		if(u.ustr < u.ustrmax) u.ustr++, flags.botl = 1;
304*41253Sbostic 		break;
305*41253Sbostic 	case POT_HEALING:
306*41253Sbostic 	case POT_EXTRA_HEALING:
307*41253Sbostic 		if(u.uhp < u.uhpmax) u.uhp++, flags.botl = 1;
308*41253Sbostic 		break;
309*41253Sbostic 	case POT_SICKNESS:
310*41253Sbostic 		if(u.uhp <= 5) u.uhp = 1; else u.uhp -= 5;
311*41253Sbostic 		flags.botl = 1;
312*41253Sbostic 		break;
313*41253Sbostic 	case POT_CONFUSION:
314*41253Sbostic 	case POT_BOOZE:
315*41253Sbostic 		if(!Confusion)
316*41253Sbostic 			pline("You feel somewhat dizzy.");
317*41253Sbostic 		Confusion += rnd(5);
318*41253Sbostic 		break;
319*41253Sbostic 	case POT_INVISIBILITY:
320*41253Sbostic 		pline("For an instant you couldn't see your right hand.");
321*41253Sbostic 		break;
322*41253Sbostic 	case POT_PARALYSIS:
323*41253Sbostic 		pline("Something seems to be holding you.");
324*41253Sbostic 		nomul(-rnd(5));
325*41253Sbostic 		break;
326*41253Sbostic 	case POT_SPEED:
327*41253Sbostic 		Fast += rnd(5);
328*41253Sbostic 		pline("Your knees seem more flexible now.");
329*41253Sbostic 		break;
330*41253Sbostic 	case POT_BLINDNESS:
331*41253Sbostic 		if(!Blind) pline("It suddenly gets dark.");
332*41253Sbostic 		Blind += rnd(5);
333*41253Sbostic 		seeoff(0);
334*41253Sbostic 		break;
335*41253Sbostic /*
336*41253Sbostic 	case POT_GAIN_LEVEL:
337*41253Sbostic 	case POT_LEVITATION:
338*41253Sbostic 	case POT_FRUIT_JUICE:
339*41253Sbostic 	case POT_MONSTER_DETECTION:
340*41253Sbostic 	case POT_OBJECT_DETECTION:
341*41253Sbostic 		break;
342*41253Sbostic */
343*41253Sbostic 	}
344*41253Sbostic 	/* note: no obfree() */
345*41253Sbostic }
346*41253Sbostic 
347*41253Sbostic /*
348*41253Sbostic  * -- rudimentary -- to do this correctly requires much more work
349*41253Sbostic  * -- all sharp weapons get one or more qualities derived from the potions
350*41253Sbostic  * -- texts on scrolls may be (partially) wiped out; do they become blank?
351*41253Sbostic  * --   or does their effect change, like under Confusion?
352*41253Sbostic  * -- all objects may be made invisible by POT_INVISIBILITY
353*41253Sbostic  * -- If the flask is small, can one dip a large object? Does it magically
354*41253Sbostic  * --   become a jug? Etc.
355*41253Sbostic  */
dodip()356*41253Sbostic dodip(){
357*41253Sbostic 	register struct obj *potion, *obj;
358*41253Sbostic 
359*41253Sbostic 	if(!(obj = getobj("#", "dip")))
360*41253Sbostic 		return(0);
361*41253Sbostic 	if(!(potion = getobj("!", "dip into")))
362*41253Sbostic 		return(0);
363*41253Sbostic 	pline("Interesting...");
364*41253Sbostic 	if(obj->otyp == ARROW || obj->otyp == DART ||
365*41253Sbostic 	   obj->otyp == CROSSBOW_BOLT) {
366*41253Sbostic 		if(potion->otyp == POT_SICKNESS) {
367*41253Sbostic 			useup(potion);
368*41253Sbostic 			if(obj->spe < 7) obj->spe++;	/* %% */
369*41253Sbostic 		}
370*41253Sbostic 	}
371*41253Sbostic 	return(1);
372*41253Sbostic }
373*41253Sbostic 
ghost_from_bottle()374*41253Sbostic ghost_from_bottle(){
375*41253Sbostic 	extern struct permonst pm_ghost;
376*41253Sbostic 	register struct monst *mtmp;
377*41253Sbostic 
378*41253Sbostic 	if(!(mtmp = makemon(PM_GHOST,u.ux,u.uy))){
379*41253Sbostic 		pline("This bottle turns out to be empty.");
380*41253Sbostic 		return;
381*41253Sbostic 	}
382*41253Sbostic 	mnexto(mtmp);
383*41253Sbostic 	pline("As you open the bottle, an enormous ghost emerges!");
384*41253Sbostic 	pline("You are frightened to death, and unable to move.");
385*41253Sbostic 	nomul(-3);
386*41253Sbostic }
387