Home | History | Annotate | Line # | Download | only in hack
hack.worm.c revision 1.4
      1 /*	$NetBSD: hack.worm.c,v 1.4 1997/10/19 16:59:30 christos 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.worm.c,v 1.4 1997/10/19 16:59:30 christos Exp $");
     10 #endif				/* not lint */
     11 
     12 #include <stdlib.h>
     13 #include "hack.h"
     14 #include "extern.h"
     15 #ifndef NOWORM
     16 #include "def.wseg.h"
     17 
     18 struct wseg    *wsegs[32];	/* linked list, tail first */
     19 struct wseg    *wheads[32];
     20 long            wgrowtime[32];
     21 
     22 int
     23 getwn(mtmp)
     24 	struct monst   *mtmp;
     25 {
     26 	int	tmp;
     27 	for (tmp = 1; tmp < 32; tmp++)
     28 		if (!wsegs[tmp]) {
     29 			mtmp->wormno = tmp;
     30 			return (1);
     31 		}
     32 	return (0);		/* level infested with worms */
     33 }
     34 
     35 /* called to initialize a worm unless cut in half */
     36 void
     37 initworm(mtmp)
     38 	struct monst   *mtmp;
     39 {
     40 	struct wseg    *wtmp;
     41 	int	tmp = mtmp->wormno;
     42 	if (!tmp)
     43 		return;
     44 	wheads[tmp] = wsegs[tmp] = wtmp = newseg();
     45 	wgrowtime[tmp] = 0;
     46 	wtmp->wx = mtmp->mx;
     47 	wtmp->wy = mtmp->my;
     48 	/* wtmp->wdispl = 0; */
     49 	wtmp->nseg = 0;
     50 }
     51 
     52 void
     53 worm_move(mtmp)
     54 	struct monst   *mtmp;
     55 {
     56 	struct wseg    *wtmp, *whd = NULL;
     57 	int		tmp = mtmp->wormno;
     58 	wtmp = newseg();
     59 	wtmp->wx = mtmp->mx;
     60 	wtmp->wy = mtmp->my;
     61 	wtmp->nseg = 0;
     62 	/* wtmp->wdispl = 0; */
     63 	(whd = wheads[tmp])->nseg = wtmp;
     64 	wheads[tmp] = wtmp;
     65 	if (cansee(whd->wx, whd->wy)) {
     66 		unpmon(mtmp);
     67 		atl(whd->wx, whd->wy, '~');
     68 		whd->wdispl = 1;
     69 	} else
     70 		whd->wdispl = 0;
     71 	if (wgrowtime[tmp] <= moves) {
     72 		if (!wgrowtime[tmp])
     73 			wgrowtime[tmp] = moves + rnd(5);
     74 		else
     75 			wgrowtime[tmp] += 2 + rnd(15);
     76 		mtmp->mhpmax += 3;
     77 		mtmp->mhp += 3;
     78 		return;
     79 	}
     80 	whd = wsegs[tmp];
     81 	wsegs[tmp] = whd->nseg;
     82 	remseg(whd);
     83 }
     84 
     85 void
     86 worm_nomove(mtmp)
     87 	struct monst   *mtmp;
     88 {
     89 	int		tmp;
     90 	struct wseg    *wtmp;
     91 	tmp = mtmp->wormno;
     92 	wtmp = wsegs[tmp];
     93 	if (wtmp == wheads[tmp])
     94 		return;
     95 	if (wtmp == 0 || wtmp->nseg == 0)
     96 		panic("worm_nomove?");
     97 	wsegs[tmp] = wtmp->nseg;
     98 	remseg(wtmp);
     99 	mtmp->mhp -= 3;		/* mhpmax not changed ! */
    100 }
    101 
    102 void
    103 wormdead(mtmp)
    104 	struct monst   *mtmp;
    105 {
    106 	int		tmp = mtmp->wormno;
    107 	struct wseg    *wtmp, *wtmp2;
    108 	if (!tmp)
    109 		return;
    110 	mtmp->wormno = 0;
    111 	for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2) {
    112 		wtmp2 = wtmp->nseg;
    113 		remseg(wtmp);
    114 	}
    115 	wsegs[tmp] = 0;
    116 }
    117 
    118 void
    119 wormhit(mtmp)
    120 	struct monst   *mtmp;
    121 {
    122 	int		tmp = mtmp->wormno;
    123 	struct wseg    *wtmp;
    124 	if (!tmp)
    125 		return;		/* worm without tail */
    126 	for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp->nseg)
    127 		(void) hitu(mtmp, 1);
    128 }
    129 
    130 void
    131 wormsee(tmp)
    132 	unsigned        tmp;
    133 {
    134 	struct wseg    *wtmp = wsegs[tmp];
    135 	if (!wtmp)
    136 		panic("wormsee: wtmp==0");
    137 	for (; wtmp->nseg; wtmp = wtmp->nseg)
    138 		if (!cansee(wtmp->wx, wtmp->wy) && wtmp->wdispl) {
    139 			newsym(wtmp->wx, wtmp->wy);
    140 			wtmp->wdispl = 0;
    141 		}
    142 }
    143 
    144 void
    145 pwseg(wtmp)
    146 	struct wseg    *wtmp;
    147 {
    148 	if (!wtmp->wdispl) {
    149 		atl(wtmp->wx, wtmp->wy, '~');
    150 		wtmp->wdispl = 1;
    151 	}
    152 }
    153 
    154 void
    155 cutworm(mtmp, x, y, weptyp)
    156 	struct monst   *mtmp;
    157 	xchar           x, y;
    158 	uchar           weptyp;	/* uwep->otyp or 0 */
    159 {
    160 	struct wseg    *wtmp, *wtmp2;
    161 	struct monst   *mtmp2;
    162 	int		tmp, tmp2;
    163 	if (mtmp->mx == x && mtmp->my == y)
    164 		return;		/* hit headon */
    165 
    166 	/* cutting goes best with axe or sword */
    167 	tmp = rnd(20);
    168 	if (weptyp == LONG_SWORD || weptyp == TWO_HANDED_SWORD ||
    169 	    weptyp == AXE)
    170 		tmp += 5;
    171 	if (tmp < 12)
    172 		return;
    173 
    174 	/* if tail then worm just loses a tail segment */
    175 	tmp = mtmp->wormno;
    176 	wtmp = wsegs[tmp];
    177 	if (wtmp->wx == x && wtmp->wy == y) {
    178 		wsegs[tmp] = wtmp->nseg;
    179 		remseg(wtmp);
    180 		return;
    181 	}
    182 	/* cut the worm in two halves */
    183 	mtmp2 = newmonst(0);
    184 	*mtmp2 = *mtmp;
    185 	mtmp2->mxlth = mtmp2->mnamelth = 0;
    186 
    187 	/* sometimes the tail end dies */
    188 	if (rn2(3) || !getwn(mtmp2)) {
    189 		monfree(mtmp2);
    190 		tmp2 = 0;
    191 	} else {
    192 		tmp2 = mtmp2->wormno;
    193 		wsegs[tmp2] = wsegs[tmp];
    194 		wgrowtime[tmp2] = 0;
    195 	}
    196 	do {
    197 		if (wtmp->nseg->wx == x && wtmp->nseg->wy == y) {
    198 			if (tmp2)
    199 				wheads[tmp2] = wtmp;
    200 			wsegs[tmp] = wtmp->nseg->nseg;
    201 			remseg(wtmp->nseg);
    202 			wtmp->nseg = 0;
    203 			if (tmp2) {
    204 				pline("You cut the worm in half.");
    205 				mtmp2->mhpmax = mtmp2->mhp =
    206 					d(mtmp2->data->mlevel, 8);
    207 				mtmp2->mx = wtmp->wx;
    208 				mtmp2->my = wtmp->wy;
    209 				mtmp2->nmon = fmon;
    210 				fmon = mtmp2;
    211 				pmon(mtmp2);
    212 			} else {
    213 				pline("You cut off part of the worm's tail.");
    214 				remseg(wtmp);
    215 			}
    216 			mtmp->mhp /= 2;
    217 			return;
    218 		}
    219 		wtmp2 = wtmp->nseg;
    220 		if (!tmp2)
    221 			remseg(wtmp);
    222 		wtmp = wtmp2;
    223 	} while (wtmp->nseg);
    224 	panic("Cannot find worm segment");
    225 }
    226 
    227 void
    228 remseg(wtmp)
    229 	struct wseg    *wtmp;
    230 {
    231 	if (wtmp->wdispl)
    232 		newsym(wtmp->wx, wtmp->wy);
    233 	free((char *) wtmp);
    234 }
    235 #endif	/* NOWORM */
    236