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