Sweep-fix comparing pointers with 0 (and assigning 0 to pointers).
[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
5 #include "hack.h"
6 #ifndef NOWORM
7
8 struct wseg *wsegs[32]; /* linked list, tail first */
9 struct wseg *wheads[32];
10 long wgrowtime[32];
11
12 static void remseg(struct wseg *);
13
14 bool
15 getwn(struct monst *mtmp)
16 {
17         int tmp;
18
19         for (tmp = 1; tmp < 32; tmp++)
20                 if (!wsegs[tmp]) {
21                         mtmp->wormno = tmp;
22                         return (1);
23                 }
24         return (0);             /* level infested with worms */
25 }
26
27 /* called to initialize a worm unless cut in half */
28 void
29 initworm(struct monst *mtmp)
30 {
31         struct wseg *wtmp;
32         int tmp = mtmp->wormno;
33
34         if (!tmp)
35                 return;
36         wheads[tmp] = wsegs[tmp] = wtmp = newseg();
37         wgrowtime[tmp] = 0;
38         wtmp->wx = mtmp->mx;
39         wtmp->wy = mtmp->my;
40         wtmp->nseg = 0;
41 }
42
43 void
44 worm_move(struct monst *mtmp)
45 {
46         struct wseg *wtmp, *whd;
47         int tmp = mtmp->wormno;
48
49         wtmp = newseg();
50         wtmp->wx = mtmp->mx;
51         wtmp->wy = mtmp->my;
52         wtmp->nseg = 0;
53         (whd = wheads[tmp])->nseg = wtmp;
54         wheads[tmp] = wtmp;
55         if (cansee(whd->wx, whd->wy)) {
56                 unpmon(mtmp);
57                 atl(whd->wx, whd->wy, '~');
58                 whd->wdispl = 1;
59         } else
60                 whd->wdispl = 0;
61         if (wgrowtime[tmp] <= moves) {
62                 if (!wgrowtime[tmp])
63                         wgrowtime[tmp] = moves + rnd(5);
64                 else
65                         wgrowtime[tmp] += 2 + rnd(15);
66                 mtmp->mhpmax += 3;
67                 mtmp->mhp += 3;
68                 return;
69         }
70         whd = wsegs[tmp];
71         wsegs[tmp] = whd->nseg;
72         remseg(whd);
73 }
74
75 void
76 worm_nomove(struct monst *mtmp)
77 {
78         int tmp;
79         struct wseg *wtmp;
80
81         tmp = mtmp->wormno;
82         wtmp = wsegs[tmp];
83         if (wtmp == wheads[tmp])
84                 return;
85         if (wtmp == NULL || wtmp->nseg == 0)
86                 panic("worm_nomove?");
87         wsegs[tmp] = wtmp->nseg;
88         remseg(wtmp);
89         mtmp->mhp -= 3;         /* mhpmax not changed ! */
90 }
91
92 void
93 wormdead(struct monst *mtmp)
94 {
95         int tmp = mtmp->wormno;
96         struct wseg *wtmp, *wtmp2;
97
98         if (!tmp)
99                 return;
100         mtmp->wormno = 0;
101         for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2) {
102                 wtmp2 = wtmp->nseg;
103                 remseg(wtmp);
104         }
105         wsegs[tmp] = NULL;
106 }
107
108 void
109 wormhit(struct monst *mtmp)
110 {
111         int tmp = mtmp->wormno;
112         struct wseg *wtmp;
113
114         if (!tmp)       /* worm without tail */
115                 return;
116         for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp->nseg)
117                 hitu(mtmp, 1);
118 }
119
120 void
121 wormsee(unsigned int tmp)
122 {
123         struct wseg *wtmp = wsegs[tmp];
124
125         if (!wtmp)
126                 panic("wormsee: wtmp==0");
127         for (; wtmp->nseg; wtmp = wtmp->nseg)
128                 if (!cansee(wtmp->wx, wtmp->wy) && wtmp->wdispl) {
129                         newsym(wtmp->wx, wtmp->wy);
130                         wtmp->wdispl = 0;
131                 }
132 }
133
134 void
135 pwseg(struct wseg *wtmp)
136 {
137         if (!wtmp->wdispl) {
138                 atl(wtmp->wx, wtmp->wy, '~');
139                 wtmp->wdispl = 1;
140         }
141 }
142
143 /* weptyp: uwep->otyp or 0 */
144 void
145 cutworm(struct monst *mtmp, xchar x, xchar y, uchar weptyp)
146 {
147         struct wseg *wtmp, *wtmp2;
148         struct monst *mtmp2;
149         int tmp, tmp2;
150
151         if (mtmp->mx == x && mtmp->my == y)     /* hit headon */
152                 return;
153
154         /* cutting goes best with axe or sword */
155         tmp = rnd(20);
156         if (weptyp == LONG_SWORD || weptyp == TWO_HANDED_SWORD ||
157             weptyp == AXE)
158                 tmp += 5;
159         if (tmp < 12)
160                 return;
161
162         /* if tail then worm just loses a tail segment */
163         tmp = mtmp->wormno;
164         wtmp = wsegs[tmp];
165         if (wtmp->wx == x && wtmp->wy == y) {
166                 wsegs[tmp] = wtmp->nseg;
167                 remseg(wtmp);
168                 return;
169         }
170
171         /* cut the worm in two halves */
172         mtmp2 = newmonst(0);
173         *mtmp2 = *mtmp;
174         mtmp2->mxlth = mtmp2->mnamelth = 0;
175
176         /* sometimes the tail end dies */
177         if (rn2(3) || !getwn(mtmp2)) {
178                 monfree(mtmp2);
179                 tmp2 = 0;
180         } else {
181                 tmp2 = mtmp2->wormno;
182                 wsegs[tmp2] = wsegs[tmp];
183                 wgrowtime[tmp2] = 0;
184         }
185         do {
186                 if (wtmp->nseg->wx == x && wtmp->nseg->wy == y) {
187                         if (tmp2)
188                                 wheads[tmp2] = wtmp;
189                         wsegs[tmp] = wtmp->nseg->nseg;
190                         remseg(wtmp->nseg);
191                         wtmp->nseg = 0;
192                         if (tmp2) {
193                                 pline("You cut the worm in half.");
194                                 mtmp2->mhpmax = mtmp2->mhp =
195                                     d(mtmp2->data->mlevel, 8);
196                                 mtmp2->mx = wtmp->wx;
197                                 mtmp2->my = wtmp->wy;
198                                 mtmp2->nmon = fmon;
199                                 fmon = mtmp2;
200                                 pmon(mtmp2);
201                         } else {
202                                 pline("You cut off part of the worm's tail.");
203                                 remseg(wtmp);
204                         }
205                         mtmp->mhp /= 2;
206                         return;
207                 }
208                 wtmp2 = wtmp->nseg;
209                 if (!tmp2)
210                         remseg(wtmp);
211                 wtmp = wtmp2;
212         } while (wtmp->nseg);
213         panic("Cannot find worm segment");
214 }
215
216 static void
217 remseg(struct wseg *wtmp)
218 {
219         if (wtmp->wdispl)
220                 newsym(wtmp->wx, wtmp->wy);
221         free(wtmp);
222 }
223 #endif /* NOWORM */