1*aed906e4Smestre /* $OpenBSD: hack.worm.c,v 1.8 2016/01/09 18:33:15 mestre Exp $ */
2d0b779f3Sniklas
3df930be7Sderaadt /*
4d25013f2Scamield * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica,
5d25013f2Scamield * Amsterdam
6d25013f2Scamield * All rights reserved.
7d25013f2Scamield *
8d25013f2Scamield * Redistribution and use in source and binary forms, with or without
9d25013f2Scamield * modification, are permitted provided that the following conditions are
10d25013f2Scamield * met:
11d25013f2Scamield *
12d25013f2Scamield * - Redistributions of source code must retain the above copyright notice,
13d25013f2Scamield * this list of conditions and the following disclaimer.
14d25013f2Scamield *
15d25013f2Scamield * - Redistributions in binary form must reproduce the above copyright
16d25013f2Scamield * notice, this list of conditions and the following disclaimer in the
17d25013f2Scamield * documentation and/or other materials provided with the distribution.
18d25013f2Scamield *
19d25013f2Scamield * - Neither the name of the Stichting Centrum voor Wiskunde en
20d25013f2Scamield * Informatica, nor the names of its contributors may be used to endorse or
21d25013f2Scamield * promote products derived from this software without specific prior
22d25013f2Scamield * written permission.
23d25013f2Scamield *
24d25013f2Scamield * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25d25013f2Scamield * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26d25013f2Scamield * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27d25013f2Scamield * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28d25013f2Scamield * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29d25013f2Scamield * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30d25013f2Scamield * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31d25013f2Scamield * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32d25013f2Scamield * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33d25013f2Scamield * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34d25013f2Scamield * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35d25013f2Scamield */
36d25013f2Scamield
37d25013f2Scamield /*
38d25013f2Scamield * Copyright (c) 1982 Jay Fenlason <hack@gnu.org>
39d25013f2Scamield * All rights reserved.
40d25013f2Scamield *
41d25013f2Scamield * Redistribution and use in source and binary forms, with or without
42d25013f2Scamield * modification, are permitted provided that the following conditions
43d25013f2Scamield * are met:
44d25013f2Scamield * 1. Redistributions of source code must retain the above copyright
45d25013f2Scamield * notice, this list of conditions and the following disclaimer.
46d25013f2Scamield * 2. Redistributions in binary form must reproduce the above copyright
47d25013f2Scamield * notice, this list of conditions and the following disclaimer in the
48d25013f2Scamield * documentation and/or other materials provided with the distribution.
49d25013f2Scamield * 3. The name of the author may not be used to endorse or promote products
50d25013f2Scamield * derived from this software without specific prior written permission.
51d25013f2Scamield *
52d25013f2Scamield * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
53d25013f2Scamield * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
54d25013f2Scamield * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
55d25013f2Scamield * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
56d25013f2Scamield * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
57d25013f2Scamield * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
58d25013f2Scamield * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59d25013f2Scamield * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
60d25013f2Scamield * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
61d25013f2Scamield * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62df930be7Sderaadt */
63df930be7Sderaadt
644a5fbbc4Spjanzen #include <stdlib.h>
65*aed906e4Smestre
66df930be7Sderaadt #include "hack.h"
67*aed906e4Smestre
68df930be7Sderaadt #ifndef NOWORM
69df930be7Sderaadt struct wseg *wsegs[32]; /* linked list, tail first */
70df930be7Sderaadt struct wseg *wheads[32];
71df930be7Sderaadt long wgrowtime[32];
72df930be7Sderaadt
734a5fbbc4Spjanzen static void remseg(struct wseg *);
744a5fbbc4Spjanzen
754a5fbbc4Spjanzen int
getwn(struct monst * mtmp)764a5fbbc4Spjanzen getwn(struct monst *mtmp)
774a5fbbc4Spjanzen {
784a5fbbc4Spjanzen int tmp;
794a5fbbc4Spjanzen
80df930be7Sderaadt for(tmp=1; tmp<32; tmp++) if(!wsegs[tmp]) {
81df930be7Sderaadt mtmp->wormno = tmp;
82df930be7Sderaadt return(1);
83df930be7Sderaadt }
84df930be7Sderaadt return(0); /* level infested with worms */
85df930be7Sderaadt }
86df930be7Sderaadt
87df930be7Sderaadt /* called to initialize a worm unless cut in half */
884a5fbbc4Spjanzen void
initworm(struct monst * mtmp)894a5fbbc4Spjanzen initworm(struct monst *mtmp)
904a5fbbc4Spjanzen {
914a5fbbc4Spjanzen struct wseg *wtmp;
924a5fbbc4Spjanzen int tmp = mtmp->wormno;
934a5fbbc4Spjanzen
94df930be7Sderaadt if(!tmp) return;
95df930be7Sderaadt wheads[tmp] = wsegs[tmp] = wtmp = newseg();
96df930be7Sderaadt wgrowtime[tmp] = 0;
97df930be7Sderaadt wtmp->wx = mtmp->mx;
98df930be7Sderaadt wtmp->wy = mtmp->my;
99df930be7Sderaadt /* wtmp->wdispl = 0; */
100df930be7Sderaadt wtmp->nseg = 0;
101df930be7Sderaadt }
102df930be7Sderaadt
1034a5fbbc4Spjanzen void
worm_move(struct monst * mtmp)1044a5fbbc4Spjanzen worm_move(struct monst *mtmp)
1054a5fbbc4Spjanzen {
1064a5fbbc4Spjanzen struct wseg *wtmp, *whd;
1074a5fbbc4Spjanzen int tmp = mtmp->wormno;
1084a5fbbc4Spjanzen
109df930be7Sderaadt wtmp = newseg();
110df930be7Sderaadt wtmp->wx = mtmp->mx;
111df930be7Sderaadt wtmp->wy = mtmp->my;
112df930be7Sderaadt wtmp->nseg = 0;
113df930be7Sderaadt /* wtmp->wdispl = 0; */
114df930be7Sderaadt (whd = wheads[tmp])->nseg = wtmp;
115df930be7Sderaadt wheads[tmp] = wtmp;
116df930be7Sderaadt if(cansee(whd->wx,whd->wy)){
117df930be7Sderaadt unpmon(mtmp);
118df930be7Sderaadt atl(whd->wx, whd->wy, '~');
119df930be7Sderaadt whd->wdispl = 1;
120df930be7Sderaadt } else whd->wdispl = 0;
121df930be7Sderaadt if(wgrowtime[tmp] <= moves) {
122df930be7Sderaadt if(!wgrowtime[tmp]) wgrowtime[tmp] = moves + rnd(5);
123df930be7Sderaadt else wgrowtime[tmp] += 2+rnd(15);
124df930be7Sderaadt mtmp->mhpmax += 3;
125df930be7Sderaadt mtmp->mhp += 3;
126df930be7Sderaadt return;
127df930be7Sderaadt }
128df930be7Sderaadt whd = wsegs[tmp];
129df930be7Sderaadt wsegs[tmp] = whd->nseg;
130df930be7Sderaadt remseg(whd);
131df930be7Sderaadt }
132df930be7Sderaadt
1334a5fbbc4Spjanzen void
worm_nomove(struct monst * mtmp)1344a5fbbc4Spjanzen worm_nomove(struct monst *mtmp)
1354a5fbbc4Spjanzen {
1364a5fbbc4Spjanzen int tmp;
1374a5fbbc4Spjanzen struct wseg *wtmp;
1384a5fbbc4Spjanzen
139df930be7Sderaadt tmp = mtmp->wormno;
140df930be7Sderaadt wtmp = wsegs[tmp];
141df930be7Sderaadt if(wtmp == wheads[tmp]) return;
142df930be7Sderaadt if(wtmp == 0 || wtmp->nseg == 0) panic("worm_nomove?");
143df930be7Sderaadt wsegs[tmp] = wtmp->nseg;
144df930be7Sderaadt remseg(wtmp);
145df930be7Sderaadt mtmp->mhp -= 3; /* mhpmax not changed ! */
146df930be7Sderaadt }
147df930be7Sderaadt
1484a5fbbc4Spjanzen void
wormdead(struct monst * mtmp)1494a5fbbc4Spjanzen wormdead(struct monst *mtmp)
1504a5fbbc4Spjanzen {
1514a5fbbc4Spjanzen int tmp = mtmp->wormno;
1524a5fbbc4Spjanzen struct wseg *wtmp, *wtmp2;
1534a5fbbc4Spjanzen
154df930be7Sderaadt if(!tmp) return;
155df930be7Sderaadt mtmp->wormno = 0;
156df930be7Sderaadt for(wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2){
157df930be7Sderaadt wtmp2 = wtmp->nseg;
158df930be7Sderaadt remseg(wtmp);
159df930be7Sderaadt }
160df930be7Sderaadt wsegs[tmp] = 0;
161df930be7Sderaadt }
162df930be7Sderaadt
1634a5fbbc4Spjanzen void
wormhit(struct monst * mtmp)1644a5fbbc4Spjanzen wormhit(struct monst *mtmp)
1654a5fbbc4Spjanzen {
1664a5fbbc4Spjanzen int tmp = mtmp->wormno;
1674a5fbbc4Spjanzen struct wseg *wtmp;
1684a5fbbc4Spjanzen
169df930be7Sderaadt if(!tmp) return; /* worm without tail */
170df930be7Sderaadt for(wtmp = wsegs[tmp]; wtmp; wtmp = wtmp->nseg)
171df930be7Sderaadt (void) hitu(mtmp,1);
172df930be7Sderaadt }
173df930be7Sderaadt
1744a5fbbc4Spjanzen void
wormsee(unsigned tmp)1754a5fbbc4Spjanzen wormsee(unsigned tmp)
1764a5fbbc4Spjanzen {
1774a5fbbc4Spjanzen struct wseg *wtmp = wsegs[tmp];
1784a5fbbc4Spjanzen
179df930be7Sderaadt if(!wtmp) panic("wormsee: wtmp==0");
180df930be7Sderaadt for(; wtmp->nseg; wtmp = wtmp->nseg)
181df930be7Sderaadt if(!cansee(wtmp->wx,wtmp->wy) && wtmp->wdispl){
182df930be7Sderaadt newsym(wtmp->wx, wtmp->wy);
183df930be7Sderaadt wtmp->wdispl = 0;
184df930be7Sderaadt }
185df930be7Sderaadt }
186df930be7Sderaadt
1874a5fbbc4Spjanzen void
pwseg(struct wseg * wtmp)1884a5fbbc4Spjanzen pwseg(struct wseg *wtmp)
1894a5fbbc4Spjanzen {
190df930be7Sderaadt if(!wtmp->wdispl){
191df930be7Sderaadt atl(wtmp->wx, wtmp->wy, '~');
192df930be7Sderaadt wtmp->wdispl = 1;
193df930be7Sderaadt }
194df930be7Sderaadt }
195df930be7Sderaadt
1964a5fbbc4Spjanzen /* uchar weptyp; uwep->otyp or 0 */
1974a5fbbc4Spjanzen void
cutworm(struct monst * mtmp,xchar x,xchar y,uchar weptyp)1984a5fbbc4Spjanzen cutworm(struct monst *mtmp, xchar x, xchar y, uchar weptyp)
199df930be7Sderaadt {
2004a5fbbc4Spjanzen struct wseg *wtmp, *wtmp2;
2014a5fbbc4Spjanzen struct monst *mtmp2;
2024a5fbbc4Spjanzen int tmp,tmp2;
203df930be7Sderaadt if(mtmp->mx == x && mtmp->my == y) return; /* hit headon */
204df930be7Sderaadt
205df930be7Sderaadt /* cutting goes best with axe or sword */
206df930be7Sderaadt tmp = rnd(20);
207df930be7Sderaadt if(weptyp == LONG_SWORD || weptyp == TWO_HANDED_SWORD ||
208df930be7Sderaadt weptyp == AXE) tmp += 5;
209df930be7Sderaadt if(tmp < 12) return;
210df930be7Sderaadt
211df930be7Sderaadt /* if tail then worm just loses a tail segment */
212df930be7Sderaadt tmp = mtmp->wormno;
213df930be7Sderaadt wtmp = wsegs[tmp];
214df930be7Sderaadt if(wtmp->wx == x && wtmp->wy == y){
215df930be7Sderaadt wsegs[tmp] = wtmp->nseg;
216df930be7Sderaadt remseg(wtmp);
217df930be7Sderaadt return;
218df930be7Sderaadt }
219df930be7Sderaadt
220df930be7Sderaadt /* cut the worm in two halves */
221df930be7Sderaadt mtmp2 = newmonst(0);
222df930be7Sderaadt *mtmp2 = *mtmp;
223df930be7Sderaadt mtmp2->mxlth = mtmp2->mnamelth = 0;
224df930be7Sderaadt
225df930be7Sderaadt /* sometimes the tail end dies */
226df930be7Sderaadt if(rn2(3) || !getwn(mtmp2)){
227df930be7Sderaadt monfree(mtmp2);
228df930be7Sderaadt tmp2 = 0;
229df930be7Sderaadt } else {
230df930be7Sderaadt tmp2 = mtmp2->wormno;
231df930be7Sderaadt wsegs[tmp2] = wsegs[tmp];
232df930be7Sderaadt wgrowtime[tmp2] = 0;
233df930be7Sderaadt }
234df930be7Sderaadt do {
235df930be7Sderaadt if(wtmp->nseg->wx == x && wtmp->nseg->wy == y){
236df930be7Sderaadt if(tmp2) wheads[tmp2] = wtmp;
237df930be7Sderaadt wsegs[tmp] = wtmp->nseg->nseg;
238df930be7Sderaadt remseg(wtmp->nseg);
239df930be7Sderaadt wtmp->nseg = 0;
240df930be7Sderaadt if(tmp2){
241df930be7Sderaadt pline("You cut the worm in half.");
242df930be7Sderaadt mtmp2->mhpmax = mtmp2->mhp =
243df930be7Sderaadt d(mtmp2->data->mlevel, 8);
244df930be7Sderaadt mtmp2->mx = wtmp->wx;
245df930be7Sderaadt mtmp2->my = wtmp->wy;
246df930be7Sderaadt mtmp2->nmon = fmon;
247df930be7Sderaadt fmon = mtmp2;
248df930be7Sderaadt pmon(mtmp2);
249df930be7Sderaadt } else {
250df930be7Sderaadt pline("You cut off part of the worm's tail.");
251df930be7Sderaadt remseg(wtmp);
252df930be7Sderaadt }
253df930be7Sderaadt mtmp->mhp /= 2;
254df930be7Sderaadt return;
255df930be7Sderaadt }
256df930be7Sderaadt wtmp2 = wtmp->nseg;
257df930be7Sderaadt if(!tmp2) remseg(wtmp);
258df930be7Sderaadt wtmp = wtmp2;
259df930be7Sderaadt } while(wtmp->nseg);
260df930be7Sderaadt panic("Cannot find worm segment");
261df930be7Sderaadt }
262df930be7Sderaadt
2634a5fbbc4Spjanzen static void
remseg(struct wseg * wtmp)2644a5fbbc4Spjanzen remseg(struct wseg *wtmp)
2654a5fbbc4Spjanzen {
266df930be7Sderaadt if(wtmp->wdispl)
267df930be7Sderaadt newsym(wtmp->wx, wtmp->wy);
268ebf3d589Sguenther free(wtmp);
269df930be7Sderaadt }
27054da88e4Spjanzen #endif /* NOWORM */
271