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