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