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