Home | History | Annotate | Line # | Download | only in hack
      1 /*	$NetBSD: hack.worm.c,v 1.9 2011/08/06 20:29:37 dholland 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.worm.c,v 1.9 2011/08/06 20:29:37 dholland Exp $");
     67 #endif				/* not lint */
     68 
     69 #include <stdlib.h>
     70 #include "hack.h"
     71 #include "extern.h"
     72 #ifndef NOWORM
     73 #include "def.wseg.h"
     74 
     75 struct wseg    *wsegs[32];	/* linked list, tail first */
     76 struct wseg    *wheads[32];
     77 long            wgrowtime[32];
     78 
     79 static void remseg(struct wseg *);
     80 
     81 int
     82 getwn(struct monst *mtmp)
     83 {
     84 	int	tmp;
     85 	for (tmp = 1; tmp < 32; tmp++)
     86 		if (!wsegs[tmp]) {
     87 			mtmp->wormno = tmp;
     88 			return (1);
     89 		}
     90 	return (0);		/* level infested with worms */
     91 }
     92 
     93 /* called to initialize a worm unless cut in half */
     94 void
     95 initworm(struct monst *mtmp)
     96 {
     97 	struct wseg    *wtmp;
     98 	int	tmp = mtmp->wormno;
     99 	if (!tmp)
    100 		return;
    101 	wheads[tmp] = wsegs[tmp] = wtmp = newseg();
    102 	wgrowtime[tmp] = 0;
    103 	wtmp->wx = mtmp->mx;
    104 	wtmp->wy = mtmp->my;
    105 	/* wtmp->wdispl = 0; */
    106 	wtmp->nseg = 0;
    107 }
    108 
    109 void
    110 worm_move(struct monst *mtmp)
    111 {
    112 	struct wseg    *wtmp, *whd = NULL;
    113 	int		tmp = mtmp->wormno;
    114 	wtmp = newseg();
    115 	wtmp->wx = mtmp->mx;
    116 	wtmp->wy = mtmp->my;
    117 	wtmp->nseg = 0;
    118 	/* wtmp->wdispl = 0; */
    119 	(whd = wheads[tmp])->nseg = wtmp;
    120 	wheads[tmp] = wtmp;
    121 	if (cansee(whd->wx, whd->wy)) {
    122 		unpmon(mtmp);
    123 		atl(whd->wx, whd->wy, '~');
    124 		whd->wdispl = 1;
    125 	} else
    126 		whd->wdispl = 0;
    127 	if (wgrowtime[tmp] <= moves) {
    128 		if (!wgrowtime[tmp])
    129 			wgrowtime[tmp] = moves + rnd(5);
    130 		else
    131 			wgrowtime[tmp] += 2 + rnd(15);
    132 		mtmp->mhpmax += 3;
    133 		mtmp->mhp += 3;
    134 		return;
    135 	}
    136 	whd = wsegs[tmp];
    137 	wsegs[tmp] = whd->nseg;
    138 	remseg(whd);
    139 }
    140 
    141 void
    142 worm_nomove(struct monst *mtmp)
    143 {
    144 	int		tmp;
    145 	struct wseg    *wtmp;
    146 	tmp = mtmp->wormno;
    147 	wtmp = wsegs[tmp];
    148 	if (wtmp == wheads[tmp])
    149 		return;
    150 	if (wtmp == 0 || wtmp->nseg == 0)
    151 		panic("worm_nomove?");
    152 	wsegs[tmp] = wtmp->nseg;
    153 	remseg(wtmp);
    154 	mtmp->mhp -= 3;		/* mhpmax not changed ! */
    155 }
    156 
    157 void
    158 wormdead(struct monst *mtmp)
    159 {
    160 	int		tmp = mtmp->wormno;
    161 	struct wseg    *wtmp, *wtmp2;
    162 	if (!tmp)
    163 		return;
    164 	mtmp->wormno = 0;
    165 	for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2) {
    166 		wtmp2 = wtmp->nseg;
    167 		remseg(wtmp);
    168 	}
    169 	wsegs[tmp] = 0;
    170 }
    171 
    172 void
    173 wormhit(struct monst *mtmp)
    174 {
    175 	int		tmp = mtmp->wormno;
    176 	struct wseg    *wtmp;
    177 	if (!tmp)
    178 		return;		/* worm without tail */
    179 	for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp->nseg)
    180 		(void) hitu(mtmp, 1);
    181 }
    182 
    183 void
    184 wormsee(unsigned tmp)
    185 {
    186 	struct wseg    *wtmp = wsegs[tmp];
    187 	if (!wtmp)
    188 		panic("wormsee: wtmp==0");
    189 	for (; wtmp->nseg; wtmp = wtmp->nseg)
    190 		if (!cansee(wtmp->wx, wtmp->wy) && wtmp->wdispl) {
    191 			newsym(wtmp->wx, wtmp->wy);
    192 			wtmp->wdispl = 0;
    193 		}
    194 }
    195 
    196 void
    197 pwseg(struct wseg *wtmp)
    198 {
    199 	if (!wtmp->wdispl) {
    200 		atl(wtmp->wx, wtmp->wy, '~');
    201 		wtmp->wdispl = 1;
    202 	}
    203 }
    204 
    205 /* weptyp is uwep->otyp or 0 */
    206 void
    207 cutworm(struct monst *mtmp, xchar x, xchar y, uchar weptyp)
    208 {
    209 	struct wseg    *wtmp, *wtmp2;
    210 	struct monst   *mtmp2;
    211 	int		tmp, tmp2;
    212 	if (mtmp->mx == x && mtmp->my == y)
    213 		return;		/* hit headon */
    214 
    215 	/* cutting goes best with axe or sword */
    216 	tmp = rnd(20);
    217 	if (weptyp == LONG_SWORD || weptyp == TWO_HANDED_SWORD ||
    218 	    weptyp == AXE)
    219 		tmp += 5;
    220 	if (tmp < 12)
    221 		return;
    222 
    223 	/* if tail then worm just loses a tail segment */
    224 	tmp = mtmp->wormno;
    225 	wtmp = wsegs[tmp];
    226 	if (wtmp->wx == x && wtmp->wy == y) {
    227 		wsegs[tmp] = wtmp->nseg;
    228 		remseg(wtmp);
    229 		return;
    230 	}
    231 	/* cut the worm in two halves */
    232 	mtmp2 = newmonst(0);
    233 	*mtmp2 = *mtmp;
    234 	mtmp2->mxlth = mtmp2->mnamelth = 0;
    235 
    236 	/* sometimes the tail end dies */
    237 	if (rn2(3) || !getwn(mtmp2)) {
    238 		monfree(mtmp2);
    239 		tmp2 = 0;
    240 	} else {
    241 		tmp2 = mtmp2->wormno;
    242 		wsegs[tmp2] = wsegs[tmp];
    243 		wgrowtime[tmp2] = 0;
    244 	}
    245 	do {
    246 		if (wtmp->nseg->wx == x && wtmp->nseg->wy == y) {
    247 			if (tmp2)
    248 				wheads[tmp2] = wtmp;
    249 			wsegs[tmp] = wtmp->nseg->nseg;
    250 			remseg(wtmp->nseg);
    251 			wtmp->nseg = 0;
    252 			if (tmp2) {
    253 				pline("You cut the worm in half.");
    254 				mtmp2->mhpmax = mtmp2->mhp =
    255 					d(mtmp2->data->mlevel, 8);
    256 				mtmp2->mx = wtmp->wx;
    257 				mtmp2->my = wtmp->wy;
    258 				mtmp2->nmon = fmon;
    259 				fmon = mtmp2;
    260 				pmon(mtmp2);
    261 			} else {
    262 				pline("You cut off part of the worm's tail.");
    263 				remseg(wtmp);
    264 				monfree(mtmp2);
    265 			}
    266 			mtmp->mhp /= 2;
    267 			return;
    268 		}
    269 		wtmp2 = wtmp->nseg;
    270 		if (!tmp2)
    271 			remseg(wtmp);
    272 		wtmp = wtmp2;
    273 	} while (wtmp->nseg);
    274 	panic("Cannot find worm segment");
    275 }
    276 
    277 static void
    278 remseg(struct wseg *wtmp)
    279 {
    280 	if (wtmp->wdispl)
    281 		newsym(wtmp->wx, wtmp->wy);
    282 	free(wtmp);
    283 }
    284 #endif	/* NOWORM */
    285