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