Home | History | Annotate | Line # | Download | only in hack
hack.mhitu.c revision 1.6
      1 /*	$NetBSD: hack.mhitu.c,v 1.6 2003/04/02 18:36:37 jsm Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
      5  * Amsterdam
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions are
     10  * met:
     11  *
     12  * - Redistributions of source code must retain the above copyright notice,
     13  * this list of conditions and the following disclaimer.
     14  *
     15  * - Redistributions in binary form must reproduce the above copyright
     16  * notice, this list of conditions and the following disclaimer in the
     17  * documentation and/or other materials provided with the distribution.
     18  *
     19  * - Neither the name of the Stichting Centrum voor Wiskunde en
     20  * Informatica, nor the names of its contributors may be used to endorse or
     21  * promote products derived from this software without specific prior
     22  * written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
     25  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     26  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
     27  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
     28  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     29  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     30  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     31  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     32  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     33  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     34  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     35  */
     36 
     37 /*
     38  * Copyright (c) 1982 Jay Fenlason <hack (at) gnu.org>
     39  * All rights reserved.
     40  *
     41  * Redistribution and use in source and binary forms, with or without
     42  * modification, are permitted provided that the following conditions
     43  * are met:
     44  * 1. Redistributions of source code must retain the above copyright
     45  *    notice, this list of conditions and the following disclaimer.
     46  * 2. Redistributions in binary form must reproduce the above copyright
     47  *    notice, this list of conditions and the following disclaimer in the
     48  *    documentation and/or other materials provided with the distribution.
     49  * 3. The name of the author may not be used to endorse or promote products
     50  *    derived from this software without specific prior written permission.
     51  *
     52  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
     53  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
     54  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
     55  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     56  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     57  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     58  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     59  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     60  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     61  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     62  */
     63 
     64 #include <sys/cdefs.h>
     65 #ifndef lint
     66 __RCSID("$NetBSD: hack.mhitu.c,v 1.6 2003/04/02 18:36:37 jsm Exp $");
     67 #endif				/* not lint */
     68 
     69 #include "hack.h"
     70 #include "extern.h"
     71 
     72 /*
     73  * mhitu: monster hits you
     74  *	  returns 1 if monster dies (e.g. 'y', 'F'), 0 otherwise
     75  */
     76 int
     77 mhitu(mtmp)
     78 	struct monst   *mtmp;
     79 {
     80 	const struct permonst *mdat = mtmp->data;
     81 	int             tmp, ctmp;
     82 
     83 	nomul(0);
     84 
     85 	/* If swallowed, can only be affected by hissers and by u.ustuck */
     86 	if (u.uswallow) {
     87 		if (mtmp != u.ustuck) {
     88 			if (mdat->mlet == 'c' && !rn2(13)) {
     89 				pline("Outside, you hear %s's hissing!",
     90 				      monnam(mtmp));
     91 				pline("%s gets turned to stone!",
     92 				      Monnam(u.ustuck));
     93 				pline("And the same fate befalls you.");
     94 				done_in_by(mtmp);
     95 				/* "notreached": not return(1); */
     96 			}
     97 			return (0);
     98 		}
     99 		switch (mdat->mlet) {	/* now mtmp == u.ustuck */
    100 		case ',':
    101 			youswld(mtmp, (u.uac > 0) ? u.uac + 4 : 4,
    102 				5, "The trapper");
    103 			break;
    104 		case '\'':
    105 			youswld(mtmp, rnd(6), 7, "The lurker above");
    106 			break;
    107 		case 'P':
    108 			youswld(mtmp, d(2, 4), 12, "The purple worm");
    109 			break;
    110 		default:
    111 			/* This is not impossible! */
    112 			pline("The mysterious monster totally digests you.");
    113 			u.uhp = 0;
    114 		}
    115 		if (u.uhp < 1)
    116 			done_in_by(mtmp);
    117 		return (0);
    118 	}
    119 	if (mdat->mlet == 'c' && Stoned)
    120 		return (0);
    121 
    122 	/* make eels visible the moment they hit/miss us */
    123 	if (mdat->mlet == ';' && mtmp->minvis && cansee(mtmp->mx, mtmp->my)) {
    124 		mtmp->minvis = 0;
    125 		pmon(mtmp);
    126 	}
    127 	if (!strchr("1&DuxynNF", mdat->mlet))
    128 		tmp = hitu(mtmp, d(mdat->damn, mdat->damd));
    129 	else
    130 		tmp = 0;
    131 	if (strchr(UNDEAD, mdat->mlet) && midnight())
    132 		tmp += hitu(mtmp, d(mdat->damn, mdat->damd));
    133 
    134 	ctmp = tmp && !mtmp->mcan &&
    135 		(!uarm || objects[uarm->otyp].a_can < rnd(3) || !rn2(50));
    136 	switch (mdat->mlet) {
    137 	case '1':
    138 		if (wiz_hit(mtmp))
    139 			return (1);	/* he disappeared */
    140 		break;
    141 	case '&':
    142 		if (!mtmp->cham && !mtmp->mcan && !rn2(13)) {
    143 			(void) makemon(PM_DEMON, u.ux, u.uy);
    144 		} else {
    145 			(void) hitu(mtmp, d(2, 6));
    146 			(void) hitu(mtmp, d(2, 6));
    147 			(void) hitu(mtmp, rnd(3));
    148 			(void) hitu(mtmp, rnd(3));
    149 			(void) hitu(mtmp, rn1(4, 2));
    150 		}
    151 		break;
    152 	case ',':
    153 		if (tmp)
    154 			justswld(mtmp, "The trapper");
    155 		break;
    156 	case '\'':
    157 		if (tmp)
    158 			justswld(mtmp, "The lurker above");
    159 		break;
    160 	case ';':
    161 		if (ctmp) {
    162 			if (!u.ustuck && !rn2(10)) {
    163 				pline("%s swings itself around you!",
    164 				      Monnam(mtmp));
    165 				u.ustuck = mtmp;
    166 			} else if (u.ustuck == mtmp &&
    167 				   levl[mtmp->mx][mtmp->my].typ == POOL) {
    168 				pline("%s drowns you ...", Monnam(mtmp));
    169 				done("drowned");
    170 			}
    171 		}
    172 		break;
    173 	case 'A':
    174 		if (ctmp && rn2(2)) {
    175 			if (Poison_resistance)
    176 				pline("The sting doesn't seem to affect you.");
    177 			else {
    178 				pline("You feel weaker!");
    179 				losestr(1);
    180 			}
    181 		}
    182 		break;
    183 	case 'C':
    184 		(void) hitu(mtmp, rnd(6));
    185 		break;
    186 	case 'c':
    187 		if (!rn2(5)) {
    188 			pline("You hear %s's hissing!", monnam(mtmp));
    189 			if (ctmp || !rn2(20) || (flags.moonphase == NEW_MOON
    190 					       && !carrying(DEAD_LIZARD))) {
    191 				Stoned = 5;
    192 				/* pline("You get turned to stone!"); */
    193 				/* done_in_by(mtmp); */
    194 			}
    195 		}
    196 		break;
    197 	case 'D':
    198 		if (rn2(6) || mtmp->mcan) {
    199 			(void) hitu(mtmp, d(3, 10));
    200 			(void) hitu(mtmp, rnd(8));
    201 			(void) hitu(mtmp, rnd(8));
    202 			break;
    203 		}
    204 		kludge("%s breathes fire!", "The dragon");
    205 		buzz(-1, mtmp->mx, mtmp->my, u.ux - mtmp->mx, u.uy - mtmp->my);
    206 		break;
    207 	case 'd':
    208 		(void) hitu(mtmp, d(2, (flags.moonphase == FULL_MOON) ? 3 : 4));
    209 		break;
    210 	case 'e':
    211 		(void) hitu(mtmp, d(3, 6));
    212 		break;
    213 	case 'F':
    214 		if (mtmp->mcan)
    215 			break;
    216 		kludge("%s explodes!", "The freezing sphere");
    217 		if (Cold_resistance)
    218 			pline("You don't seem affected by it.");
    219 		else {
    220 			xchar           dn;
    221 			if (17 - (u.ulevel / 2) > rnd(20)) {
    222 				pline("You get blasted!");
    223 				dn = 6;
    224 			} else {
    225 				pline("You duck the blast...");
    226 				dn = 3;
    227 			}
    228 			losehp_m(d(dn, 6), mtmp);
    229 		}
    230 		mondead(mtmp);
    231 		return (1);
    232 	case 'g':
    233 		if (ctmp && multi >= 0 && !rn2(3)) {
    234 			kludge("You are frozen by %ss juices", "the cube'");
    235 			nomul(-rnd(10));
    236 		}
    237 		break;
    238 	case 'h':
    239 		if (ctmp && multi >= 0 && !rn2(5)) {
    240 			nomul(-rnd(10));
    241 			kludge("You are put to sleep by %ss bite!",
    242 			       "the homunculus'");
    243 		}
    244 		break;
    245 	case 'j':
    246 		tmp = hitu(mtmp, rnd(3));
    247 		tmp &= hitu(mtmp, rnd(3));
    248 		if (tmp) {
    249 			(void) hitu(mtmp, rnd(4));
    250 			(void) hitu(mtmp, rnd(4));
    251 		}
    252 		break;
    253 	case 'k':
    254 		if ((hitu(mtmp, rnd(4)) || !rn2(3)) && ctmp) {
    255 			poisoned("bee's sting", mdat->mname);
    256 		}
    257 		break;
    258 	case 'L':
    259 		if (tmp)
    260 			stealgold(mtmp);
    261 		break;
    262 	case 'N':
    263 		if (mtmp->mcan && !Blind) {
    264 			pline("%s tries to seduce you, but you seem not interested.",
    265 			      Amonnam(mtmp, "plain"));
    266 			if (rn2(3))
    267 				rloc(mtmp);
    268 		} else if (steal(mtmp)) {
    269 			rloc(mtmp);
    270 			mtmp->mflee = 1;
    271 		}
    272 		break;
    273 	case 'n':
    274 		if (!uwep && !uarm && !uarmh && !uarms && !uarmg) {
    275 			pline("%s hits! (I hope you don't mind)",
    276 			      Monnam(mtmp));
    277 			u.uhp += rnd(7);
    278 			if (!rn2(7))
    279 				u.uhpmax++;
    280 			if (u.uhp > u.uhpmax)
    281 				u.uhp = u.uhpmax;
    282 			flags.botl = 1;
    283 			if (!rn2(50))
    284 				rloc(mtmp);
    285 		} else {
    286 			(void) hitu(mtmp, d(2, 6));
    287 			(void) hitu(mtmp, d(2, 6));
    288 		}
    289 		break;
    290 	case 'o':
    291 		tmp = hitu(mtmp, rnd(6));
    292 		if (hitu(mtmp, rnd(6)) && tmp &&	/* hits with both paws */
    293 		    !u.ustuck && rn2(2)) {
    294 			u.ustuck = mtmp;
    295 			kludge("%s has grabbed you!", "The owlbear");
    296 			u.uhp -= d(2, 8);
    297 		} else if (u.ustuck == mtmp) {
    298 			u.uhp -= d(2, 8);
    299 			pline("You are being crushed.");
    300 		}
    301 		break;
    302 	case 'P':
    303 		if (ctmp && !rn2(4))
    304 			justswld(mtmp, "The purple worm");
    305 		else
    306 			(void) hitu(mtmp, d(2, 4));
    307 		break;
    308 	case 'Q':
    309 		(void) hitu(mtmp, rnd(2));
    310 		(void) hitu(mtmp, rnd(2));
    311 		break;
    312 	case 'R':
    313 		if (tmp && uarmh && !uarmh->rustfree &&
    314 		    (int) uarmh->spe >= -1) {
    315 			pline("Your helmet rusts!");
    316 			uarmh->spe--;
    317 		} else if (ctmp && uarm && !uarm->rustfree &&	/* Mike Newton */
    318 			   uarm->otyp < STUDDED_LEATHER_ARMOR &&
    319 			   (int) uarm->spe >= -1) {
    320 			pline("Your armor rusts!");
    321 			uarm->spe--;
    322 		}
    323 		break;
    324 	case 'S':
    325 		if (ctmp && !rn2(8)) {
    326 			poisoned("snake's bite", mdat->mname);
    327 		}
    328 		break;
    329 	case 's':
    330 		if (tmp && !rn2(8)) {
    331 			poisoned("scorpion's sting", mdat->mname);
    332 		}
    333 		(void) hitu(mtmp, rnd(8));
    334 		(void) hitu(mtmp, rnd(8));
    335 		break;
    336 	case 'T':
    337 		(void) hitu(mtmp, rnd(6));
    338 		(void) hitu(mtmp, rnd(6));
    339 		break;
    340 	case 't':
    341 		if (!rn2(5))
    342 			rloc(mtmp);
    343 		break;
    344 	case 'u':
    345 		mtmp->mflee = 1;
    346 		break;
    347 	case 'U':
    348 		(void) hitu(mtmp, d(3, 4));
    349 		(void) hitu(mtmp, d(3, 4));
    350 		break;
    351 	case 'v':
    352 		if (ctmp && !u.ustuck)
    353 			u.ustuck = mtmp;
    354 		break;
    355 	case 'V':
    356 		if (tmp)
    357 			u.uhp -= 4;
    358 		if (ctmp)
    359 			losexp();
    360 		break;
    361 	case 'W':
    362 		if (ctmp)
    363 			losexp();
    364 		break;
    365 #ifndef NOWORM
    366 	case 'w':
    367 		if (tmp)
    368 			wormhit(mtmp);
    369 #endif	/* NOWORM */
    370 		break;
    371 	case 'X':
    372 		(void) hitu(mtmp, rnd(5));
    373 		(void) hitu(mtmp, rnd(5));
    374 		(void) hitu(mtmp, rnd(5));
    375 		break;
    376 	case 'x':
    377 		{
    378 			long            side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE;
    379 			pline("%s pricks in your %s leg!",
    380 			      Monnam(mtmp), (side == RIGHT_SIDE) ? "right" : "left");
    381 			set_wounded_legs(side, rnd(50));
    382 			losehp_m(2, mtmp);
    383 			break;
    384 		}
    385 	case 'y':
    386 		if (mtmp->mcan)
    387 			break;
    388 		mondead(mtmp);
    389 		if (!Blind) {
    390 			pline("You are blinded by a blast of light!");
    391 			Blind = d(4, 12);
    392 			seeoff(0);
    393 		}
    394 		return (1);
    395 	case 'Y':
    396 		(void) hitu(mtmp, rnd(6));
    397 		break;
    398 	}
    399 	if (u.uhp < 1)
    400 		done_in_by(mtmp);
    401 	return (0);
    402 }
    403 
    404 int
    405 hitu(mtmp, dam)
    406 	struct monst   *mtmp;
    407 	int dam;
    408 {
    409 	int tmp, res;
    410 
    411 	nomul(0);
    412 	if (u.uswallow)
    413 		return (0);
    414 
    415 	if (mtmp->mhide && mtmp->mundetected) {
    416 		mtmp->mundetected = 0;
    417 		if (!Blind) {
    418 			struct obj     *obj;
    419 			if ((obj = o_at(mtmp->mx, mtmp->my)) != NULL)
    420 				pline("%s was hidden under %s!",
    421 				      Xmonnam(mtmp), doname(obj));
    422 		}
    423 	}
    424 	tmp = u.uac;
    425 	/* give people with Ac = -10 at least some vulnerability */
    426 	if (tmp < 0) {
    427 		dam += tmp;	/* decrease damage */
    428 		if (dam <= 0)
    429 			dam = 1;
    430 		tmp = -rn2(-tmp);
    431 	}
    432 	tmp += mtmp->data->mlevel;
    433 	if (multi < 0)
    434 		tmp += 4;
    435 	if ((Invis && mtmp->data->mlet != 'I') || !mtmp->mcansee)
    436 		tmp -= 2;
    437 	if (mtmp->mtrapped)
    438 		tmp -= 2;
    439 	if (tmp <= rnd(20)) {
    440 		if (Blind)
    441 			pline("It misses.");
    442 		else
    443 			pline("%s misses.", Monnam(mtmp));
    444 		res = 0;
    445 	} else {
    446 		if (Blind)
    447 			pline("It hits!");
    448 		else
    449 			pline("%s hits!", Monnam(mtmp));
    450 		losehp_m(dam, mtmp);
    451 		res = 1;
    452 	}
    453 	stop_occupation();
    454 	return (res);
    455 }
    456