Merge from vendor branch GCC:
[dragonfly.git] / games / hack / hack.worm.c
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 */