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