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 */ 224