potion.c (8834B)
1 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ 2 /* 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 }