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