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