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