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