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