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