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 :
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 :
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 :
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: }