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