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