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