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