xref: /openbsd-src/games/hack/hack.worm.c (revision aed906e4b20d9afbda31247cdb6acf6f29da8819)
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