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