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