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