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