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