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