periodic(8): Sync with FreeBSD current
[dragonfly.git] / games / hack / hack.worm.c
blob3a8d3603902f27bc7bb149c8617dcf306be76616
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 $ */
5 #include "hack.h"
6 #ifndef NOWORM
8 struct wseg *wsegs[32]; /* linked list, tail first */
9 struct wseg *wheads[32];
10 long wgrowtime[32];
12 static void remseg(struct wseg *);
14 bool
15 getwn(struct monst *mtmp)
17 int tmp;
19 for (tmp = 1; tmp < 32; tmp++)
20 if (!wsegs[tmp]) {
21 mtmp->wormno = tmp;
22 return (1);
24 return (0); /* level infested with worms */
27 /* called to initialize a worm unless cut in half */
28 void
29 initworm(struct monst *mtmp)
31 struct wseg *wtmp;
32 int tmp = mtmp->wormno;
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;
43 void
44 worm_move(struct monst *mtmp)
46 struct wseg *wtmp, *whd;
47 int tmp = mtmp->wormno;
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;
70 whd = wsegs[tmp];
71 wsegs[tmp] = whd->nseg;
72 remseg(whd);
75 void
76 worm_nomove(struct monst *mtmp)
78 int tmp;
79 struct wseg *wtmp;
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 ! */
92 void
93 wormdead(struct monst *mtmp)
95 int tmp = mtmp->wormno;
96 struct wseg *wtmp, *wtmp2;
98 if (!tmp)
99 return;
100 mtmp->wormno = 0;
101 for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2) {
102 wtmp2 = wtmp->nseg;
103 remseg(wtmp);
105 wsegs[tmp] = NULL;
108 void
109 wormhit(struct monst *mtmp)
111 int tmp = mtmp->wormno;
112 struct wseg *wtmp;
114 if (!tmp) /* worm without tail */
115 return;
116 for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp->nseg)
117 hitu(mtmp, 1);
120 void
121 wormsee(unsigned int tmp)
123 struct wseg *wtmp = wsegs[tmp];
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;
134 void
135 pwseg(struct wseg *wtmp)
137 if (!wtmp->wdispl) {
138 atl(wtmp->wx, wtmp->wy, '~');
139 wtmp->wdispl = 1;
143 /* weptyp: uwep->otyp or 0 */
144 void
145 cutworm(struct monst *mtmp, xchar x, xchar y, uchar weptyp)
147 struct wseg *wtmp, *wtmp2;
148 struct monst *mtmp2;
149 int tmp, tmp2;
151 if (mtmp->mx == x && mtmp->my == y) /* hit headon */
152 return;
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;
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;
171 /* cut the worm in two halves */
172 mtmp2 = newmonst(0);
173 *mtmp2 = *mtmp;
174 mtmp2->mxlth = mtmp2->mnamelth = 0;
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;
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);
205 mtmp->mhp /= 2;
206 return;
208 wtmp2 = wtmp->nseg;
209 if (!tmp2)
210 remseg(wtmp);
211 wtmp = wtmp2;
212 } while (wtmp->nseg);
213 panic("Cannot find worm segment");
216 static void
217 remseg(struct wseg *wtmp)
219 if (wtmp->wdispl)
220 newsym(wtmp->wx, wtmp->wy);
221 free(wtmp);
223 #endif /* NOWORM */