Home | History | Annotate | Line # | Download | only in hack
hack.mhitu.c revision 1.5
      1 /*	$NetBSD: hack.mhitu.c,v 1.5 2001/03/25 20:44:01 jsm Exp $	*/
      2 
      3 /*
      4  * Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985.
      5  */
      6 
      7 #include <sys/cdefs.h>
      8 #ifndef lint
      9 __RCSID("$NetBSD: hack.mhitu.c,v 1.5 2001/03/25 20:44:01 jsm Exp $");
     10 #endif				/* not lint */
     11 
     12 #include "hack.h"
     13 #include "extern.h"
     14 
     15 /*
     16  * mhitu: monster hits you
     17  *	  returns 1 if monster dies (e.g. 'y', 'F'), 0 otherwise
     18  */
     19 int
     20 mhitu(mtmp)
     21 	struct monst   *mtmp;
     22 {
     23 	const struct permonst *mdat = mtmp->data;
     24 	int             tmp, ctmp;
     25 
     26 	nomul(0);
     27 
     28 	/* If swallowed, can only be affected by hissers and by u.ustuck */
     29 	if (u.uswallow) {
     30 		if (mtmp != u.ustuck) {
     31 			if (mdat->mlet == 'c' && !rn2(13)) {
     32 				pline("Outside, you hear %s's hissing!",
     33 				      monnam(mtmp));
     34 				pline("%s gets turned to stone!",
     35 				      Monnam(u.ustuck));
     36 				pline("And the same fate befalls you.");
     37 				done_in_by(mtmp);
     38 				/* "notreached": not return(1); */
     39 			}
     40 			return (0);
     41 		}
     42 		switch (mdat->mlet) {	/* now mtmp == u.ustuck */
     43 		case ',':
     44 			youswld(mtmp, (u.uac > 0) ? u.uac + 4 : 4,
     45 				5, "The trapper");
     46 			break;
     47 		case '\'':
     48 			youswld(mtmp, rnd(6), 7, "The lurker above");
     49 			break;
     50 		case 'P':
     51 			youswld(mtmp, d(2, 4), 12, "The purple worm");
     52 			break;
     53 		default:
     54 			/* This is not impossible! */
     55 			pline("The mysterious monster totally digests you.");
     56 			u.uhp = 0;
     57 		}
     58 		if (u.uhp < 1)
     59 			done_in_by(mtmp);
     60 		return (0);
     61 	}
     62 	if (mdat->mlet == 'c' && Stoned)
     63 		return (0);
     64 
     65 	/* make eels visible the moment they hit/miss us */
     66 	if (mdat->mlet == ';' && mtmp->minvis && cansee(mtmp->mx, mtmp->my)) {
     67 		mtmp->minvis = 0;
     68 		pmon(mtmp);
     69 	}
     70 	if (!strchr("1&DuxynNF", mdat->mlet))
     71 		tmp = hitu(mtmp, d(mdat->damn, mdat->damd));
     72 	else
     73 		tmp = 0;
     74 	if (strchr(UNDEAD, mdat->mlet) && midnight())
     75 		tmp += hitu(mtmp, d(mdat->damn, mdat->damd));
     76 
     77 	ctmp = tmp && !mtmp->mcan &&
     78 		(!uarm || objects[uarm->otyp].a_can < rnd(3) || !rn2(50));
     79 	switch (mdat->mlet) {
     80 	case '1':
     81 		if (wiz_hit(mtmp))
     82 			return (1);	/* he disappeared */
     83 		break;
     84 	case '&':
     85 		if (!mtmp->cham && !mtmp->mcan && !rn2(13)) {
     86 			(void) makemon(PM_DEMON, u.ux, u.uy);
     87 		} else {
     88 			(void) hitu(mtmp, d(2, 6));
     89 			(void) hitu(mtmp, d(2, 6));
     90 			(void) hitu(mtmp, rnd(3));
     91 			(void) hitu(mtmp, rnd(3));
     92 			(void) hitu(mtmp, rn1(4, 2));
     93 		}
     94 		break;
     95 	case ',':
     96 		if (tmp)
     97 			justswld(mtmp, "The trapper");
     98 		break;
     99 	case '\'':
    100 		if (tmp)
    101 			justswld(mtmp, "The lurker above");
    102 		break;
    103 	case ';':
    104 		if (ctmp) {
    105 			if (!u.ustuck && !rn2(10)) {
    106 				pline("%s swings itself around you!",
    107 				      Monnam(mtmp));
    108 				u.ustuck = mtmp;
    109 			} else if (u.ustuck == mtmp &&
    110 				   levl[mtmp->mx][mtmp->my].typ == POOL) {
    111 				pline("%s drowns you ...", Monnam(mtmp));
    112 				done("drowned");
    113 			}
    114 		}
    115 		break;
    116 	case 'A':
    117 		if (ctmp && rn2(2)) {
    118 			if (Poison_resistance)
    119 				pline("The sting doesn't seem to affect you.");
    120 			else {
    121 				pline("You feel weaker!");
    122 				losestr(1);
    123 			}
    124 		}
    125 		break;
    126 	case 'C':
    127 		(void) hitu(mtmp, rnd(6));
    128 		break;
    129 	case 'c':
    130 		if (!rn2(5)) {
    131 			pline("You hear %s's hissing!", monnam(mtmp));
    132 			if (ctmp || !rn2(20) || (flags.moonphase == NEW_MOON
    133 					       && !carrying(DEAD_LIZARD))) {
    134 				Stoned = 5;
    135 				/* pline("You get turned to stone!"); */
    136 				/* done_in_by(mtmp); */
    137 			}
    138 		}
    139 		break;
    140 	case 'D':
    141 		if (rn2(6) || mtmp->mcan) {
    142 			(void) hitu(mtmp, d(3, 10));
    143 			(void) hitu(mtmp, rnd(8));
    144 			(void) hitu(mtmp, rnd(8));
    145 			break;
    146 		}
    147 		kludge("%s breathes fire!", "The dragon");
    148 		buzz(-1, mtmp->mx, mtmp->my, u.ux - mtmp->mx, u.uy - mtmp->my);
    149 		break;
    150 	case 'd':
    151 		(void) hitu(mtmp, d(2, (flags.moonphase == FULL_MOON) ? 3 : 4));
    152 		break;
    153 	case 'e':
    154 		(void) hitu(mtmp, d(3, 6));
    155 		break;
    156 	case 'F':
    157 		if (mtmp->mcan)
    158 			break;
    159 		kludge("%s explodes!", "The freezing sphere");
    160 		if (Cold_resistance)
    161 			pline("You don't seem affected by it.");
    162 		else {
    163 			xchar           dn;
    164 			if (17 - (u.ulevel / 2) > rnd(20)) {
    165 				pline("You get blasted!");
    166 				dn = 6;
    167 			} else {
    168 				pline("You duck the blast...");
    169 				dn = 3;
    170 			}
    171 			losehp_m(d(dn, 6), mtmp);
    172 		}
    173 		mondead(mtmp);
    174 		return (1);
    175 	case 'g':
    176 		if (ctmp && multi >= 0 && !rn2(3)) {
    177 			kludge("You are frozen by %ss juices", "the cube'");
    178 			nomul(-rnd(10));
    179 		}
    180 		break;
    181 	case 'h':
    182 		if (ctmp && multi >= 0 && !rn2(5)) {
    183 			nomul(-rnd(10));
    184 			kludge("You are put to sleep by %ss bite!",
    185 			       "the homunculus'");
    186 		}
    187 		break;
    188 	case 'j':
    189 		tmp = hitu(mtmp, rnd(3));
    190 		tmp &= hitu(mtmp, rnd(3));
    191 		if (tmp) {
    192 			(void) hitu(mtmp, rnd(4));
    193 			(void) hitu(mtmp, rnd(4));
    194 		}
    195 		break;
    196 	case 'k':
    197 		if ((hitu(mtmp, rnd(4)) || !rn2(3)) && ctmp) {
    198 			poisoned("bee's sting", mdat->mname);
    199 		}
    200 		break;
    201 	case 'L':
    202 		if (tmp)
    203 			stealgold(mtmp);
    204 		break;
    205 	case 'N':
    206 		if (mtmp->mcan && !Blind) {
    207 			pline("%s tries to seduce you, but you seem not interested.",
    208 			      Amonnam(mtmp, "plain"));
    209 			if (rn2(3))
    210 				rloc(mtmp);
    211 		} else if (steal(mtmp)) {
    212 			rloc(mtmp);
    213 			mtmp->mflee = 1;
    214 		}
    215 		break;
    216 	case 'n':
    217 		if (!uwep && !uarm && !uarmh && !uarms && !uarmg) {
    218 			pline("%s hits! (I hope you don't mind)",
    219 			      Monnam(mtmp));
    220 			u.uhp += rnd(7);
    221 			if (!rn2(7))
    222 				u.uhpmax++;
    223 			if (u.uhp > u.uhpmax)
    224 				u.uhp = u.uhpmax;
    225 			flags.botl = 1;
    226 			if (!rn2(50))
    227 				rloc(mtmp);
    228 		} else {
    229 			(void) hitu(mtmp, d(2, 6));
    230 			(void) hitu(mtmp, d(2, 6));
    231 		}
    232 		break;
    233 	case 'o':
    234 		tmp = hitu(mtmp, rnd(6));
    235 		if (hitu(mtmp, rnd(6)) && tmp &&	/* hits with both paws */
    236 		    !u.ustuck && rn2(2)) {
    237 			u.ustuck = mtmp;
    238 			kludge("%s has grabbed you!", "The owlbear");
    239 			u.uhp -= d(2, 8);
    240 		} else if (u.ustuck == mtmp) {
    241 			u.uhp -= d(2, 8);
    242 			pline("You are being crushed.");
    243 		}
    244 		break;
    245 	case 'P':
    246 		if (ctmp && !rn2(4))
    247 			justswld(mtmp, "The purple worm");
    248 		else
    249 			(void) hitu(mtmp, d(2, 4));
    250 		break;
    251 	case 'Q':
    252 		(void) hitu(mtmp, rnd(2));
    253 		(void) hitu(mtmp, rnd(2));
    254 		break;
    255 	case 'R':
    256 		if (tmp && uarmh && !uarmh->rustfree &&
    257 		    (int) uarmh->spe >= -1) {
    258 			pline("Your helmet rusts!");
    259 			uarmh->spe--;
    260 		} else if (ctmp && uarm && !uarm->rustfree &&	/* Mike Newton */
    261 			   uarm->otyp < STUDDED_LEATHER_ARMOR &&
    262 			   (int) uarm->spe >= -1) {
    263 			pline("Your armor rusts!");
    264 			uarm->spe--;
    265 		}
    266 		break;
    267 	case 'S':
    268 		if (ctmp && !rn2(8)) {
    269 			poisoned("snake's bite", mdat->mname);
    270 		}
    271 		break;
    272 	case 's':
    273 		if (tmp && !rn2(8)) {
    274 			poisoned("scorpion's sting", mdat->mname);
    275 		}
    276 		(void) hitu(mtmp, rnd(8));
    277 		(void) hitu(mtmp, rnd(8));
    278 		break;
    279 	case 'T':
    280 		(void) hitu(mtmp, rnd(6));
    281 		(void) hitu(mtmp, rnd(6));
    282 		break;
    283 	case 't':
    284 		if (!rn2(5))
    285 			rloc(mtmp);
    286 		break;
    287 	case 'u':
    288 		mtmp->mflee = 1;
    289 		break;
    290 	case 'U':
    291 		(void) hitu(mtmp, d(3, 4));
    292 		(void) hitu(mtmp, d(3, 4));
    293 		break;
    294 	case 'v':
    295 		if (ctmp && !u.ustuck)
    296 			u.ustuck = mtmp;
    297 		break;
    298 	case 'V':
    299 		if (tmp)
    300 			u.uhp -= 4;
    301 		if (ctmp)
    302 			losexp();
    303 		break;
    304 	case 'W':
    305 		if (ctmp)
    306 			losexp();
    307 		break;
    308 #ifndef NOWORM
    309 	case 'w':
    310 		if (tmp)
    311 			wormhit(mtmp);
    312 #endif	/* NOWORM */
    313 		break;
    314 	case 'X':
    315 		(void) hitu(mtmp, rnd(5));
    316 		(void) hitu(mtmp, rnd(5));
    317 		(void) hitu(mtmp, rnd(5));
    318 		break;
    319 	case 'x':
    320 		{
    321 			long            side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE;
    322 			pline("%s pricks in your %s leg!",
    323 			      Monnam(mtmp), (side == RIGHT_SIDE) ? "right" : "left");
    324 			set_wounded_legs(side, rnd(50));
    325 			losehp_m(2, mtmp);
    326 			break;
    327 		}
    328 	case 'y':
    329 		if (mtmp->mcan)
    330 			break;
    331 		mondead(mtmp);
    332 		if (!Blind) {
    333 			pline("You are blinded by a blast of light!");
    334 			Blind = d(4, 12);
    335 			seeoff(0);
    336 		}
    337 		return (1);
    338 	case 'Y':
    339 		(void) hitu(mtmp, rnd(6));
    340 		break;
    341 	}
    342 	if (u.uhp < 1)
    343 		done_in_by(mtmp);
    344 	return (0);
    345 }
    346 
    347 int
    348 hitu(mtmp, dam)
    349 	struct monst   *mtmp;
    350 	int dam;
    351 {
    352 	int tmp, res;
    353 
    354 	nomul(0);
    355 	if (u.uswallow)
    356 		return (0);
    357 
    358 	if (mtmp->mhide && mtmp->mundetected) {
    359 		mtmp->mundetected = 0;
    360 		if (!Blind) {
    361 			struct obj     *obj;
    362 			if ((obj = o_at(mtmp->mx, mtmp->my)) != NULL)
    363 				pline("%s was hidden under %s!",
    364 				      Xmonnam(mtmp), doname(obj));
    365 		}
    366 	}
    367 	tmp = u.uac;
    368 	/* give people with Ac = -10 at least some vulnerability */
    369 	if (tmp < 0) {
    370 		dam += tmp;	/* decrease damage */
    371 		if (dam <= 0)
    372 			dam = 1;
    373 		tmp = -rn2(-tmp);
    374 	}
    375 	tmp += mtmp->data->mlevel;
    376 	if (multi < 0)
    377 		tmp += 4;
    378 	if ((Invis && mtmp->data->mlet != 'I') || !mtmp->mcansee)
    379 		tmp -= 2;
    380 	if (mtmp->mtrapped)
    381 		tmp -= 2;
    382 	if (tmp <= rnd(20)) {
    383 		if (Blind)
    384 			pline("It misses.");
    385 		else
    386 			pline("%s misses.", Monnam(mtmp));
    387 		res = 0;
    388 	} else {
    389 		if (Blind)
    390 			pline("It hits!");
    391 		else
    392 			pline("%s hits!", Monnam(mtmp));
    393 		losehp_m(dam, mtmp);
    394 		res = 1;
    395 	}
    396 	stop_occupation();
    397 	return (res);
    398 }
    399