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