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