1 /* $NetBSD: hack.worm.c,v 1.7 2009/06/07 18:30:39 dholland Exp $ */ 2 3 /* 4 * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica, 5 * Amsterdam 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are 10 * met: 11 * 12 * - Redistributions of source code must retain the above copyright notice, 13 * this list of conditions and the following disclaimer. 14 * 15 * - Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * - Neither the name of the Stichting Centrum voor Wiskunde en 20 * Informatica, nor the names of its contributors may be used to endorse or 21 * promote products derived from this software without specific prior 22 * written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 25 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 27 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 28 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 30 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 31 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 33 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37 /* 38 * Copyright (c) 1982 Jay Fenlason <hack@gnu.org> 39 * All rights reserved. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 3. The name of the author may not be used to endorse or promote products 50 * derived from this software without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 53 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 54 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 55 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 56 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 57 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 58 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 59 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 60 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 61 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62 */ 63 64 #include <sys/cdefs.h> 65 #ifndef lint 66 __RCSID("$NetBSD: hack.worm.c,v 1.7 2009/06/07 18:30:39 dholland Exp $"); 67 #endif /* not lint */ 68 69 #include <stdlib.h> 70 #include "hack.h" 71 #include "extern.h" 72 #ifndef NOWORM 73 #include "def.wseg.h" 74 75 struct wseg *wsegs[32]; /* linked list, tail first */ 76 struct wseg *wheads[32]; 77 long wgrowtime[32]; 78 79 int 80 getwn(struct monst *mtmp) 81 { 82 int tmp; 83 for (tmp = 1; tmp < 32; tmp++) 84 if (!wsegs[tmp]) { 85 mtmp->wormno = tmp; 86 return (1); 87 } 88 return (0); /* level infested with worms */ 89 } 90 91 /* called to initialize a worm unless cut in half */ 92 void 93 initworm(struct monst *mtmp) 94 { 95 struct wseg *wtmp; 96 int tmp = mtmp->wormno; 97 if (!tmp) 98 return; 99 wheads[tmp] = wsegs[tmp] = wtmp = newseg(); 100 wgrowtime[tmp] = 0; 101 wtmp->wx = mtmp->mx; 102 wtmp->wy = mtmp->my; 103 /* wtmp->wdispl = 0; */ 104 wtmp->nseg = 0; 105 } 106 107 void 108 worm_move(struct monst *mtmp) 109 { 110 struct wseg *wtmp, *whd = NULL; 111 int tmp = mtmp->wormno; 112 wtmp = newseg(); 113 wtmp->wx = mtmp->mx; 114 wtmp->wy = mtmp->my; 115 wtmp->nseg = 0; 116 /* wtmp->wdispl = 0; */ 117 (whd = wheads[tmp])->nseg = wtmp; 118 wheads[tmp] = wtmp; 119 if (cansee(whd->wx, whd->wy)) { 120 unpmon(mtmp); 121 atl(whd->wx, whd->wy, '~'); 122 whd->wdispl = 1; 123 } else 124 whd->wdispl = 0; 125 if (wgrowtime[tmp] <= moves) { 126 if (!wgrowtime[tmp]) 127 wgrowtime[tmp] = moves + rnd(5); 128 else 129 wgrowtime[tmp] += 2 + rnd(15); 130 mtmp->mhpmax += 3; 131 mtmp->mhp += 3; 132 return; 133 } 134 whd = wsegs[tmp]; 135 wsegs[tmp] = whd->nseg; 136 remseg(whd); 137 } 138 139 void 140 worm_nomove(struct monst *mtmp) 141 { 142 int tmp; 143 struct wseg *wtmp; 144 tmp = mtmp->wormno; 145 wtmp = wsegs[tmp]; 146 if (wtmp == wheads[tmp]) 147 return; 148 if (wtmp == 0 || wtmp->nseg == 0) 149 panic("worm_nomove?"); 150 wsegs[tmp] = wtmp->nseg; 151 remseg(wtmp); 152 mtmp->mhp -= 3; /* mhpmax not changed ! */ 153 } 154 155 void 156 wormdead(struct monst *mtmp) 157 { 158 int tmp = mtmp->wormno; 159 struct wseg *wtmp, *wtmp2; 160 if (!tmp) 161 return; 162 mtmp->wormno = 0; 163 for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2) { 164 wtmp2 = wtmp->nseg; 165 remseg(wtmp); 166 } 167 wsegs[tmp] = 0; 168 } 169 170 void 171 wormhit(struct monst *mtmp) 172 { 173 int tmp = mtmp->wormno; 174 struct wseg *wtmp; 175 if (!tmp) 176 return; /* worm without tail */ 177 for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp->nseg) 178 (void) hitu(mtmp, 1); 179 } 180 181 void 182 wormsee(unsigned tmp) 183 { 184 struct wseg *wtmp = wsegs[tmp]; 185 if (!wtmp) 186 panic("wormsee: wtmp==0"); 187 for (; wtmp->nseg; wtmp = wtmp->nseg) 188 if (!cansee(wtmp->wx, wtmp->wy) && wtmp->wdispl) { 189 newsym(wtmp->wx, wtmp->wy); 190 wtmp->wdispl = 0; 191 } 192 } 193 194 void 195 pwseg(struct wseg *wtmp) 196 { 197 if (!wtmp->wdispl) { 198 atl(wtmp->wx, wtmp->wy, '~'); 199 wtmp->wdispl = 1; 200 } 201 } 202 203 /* weptyp is uwep->otyp or 0 */ 204 void 205 cutworm(struct monst *mtmp, xchar x, xchar y, uchar weptyp) 206 { 207 struct wseg *wtmp, *wtmp2; 208 struct monst *mtmp2; 209 int tmp, tmp2; 210 if (mtmp->mx == x && mtmp->my == y) 211 return; /* hit headon */ 212 213 /* cutting goes best with axe or sword */ 214 tmp = rnd(20); 215 if (weptyp == LONG_SWORD || weptyp == TWO_HANDED_SWORD || 216 weptyp == AXE) 217 tmp += 5; 218 if (tmp < 12) 219 return; 220 221 /* if tail then worm just loses a tail segment */ 222 tmp = mtmp->wormno; 223 wtmp = wsegs[tmp]; 224 if (wtmp->wx == x && wtmp->wy == y) { 225 wsegs[tmp] = wtmp->nseg; 226 remseg(wtmp); 227 return; 228 } 229 /* cut the worm in two halves */ 230 mtmp2 = newmonst(0); 231 *mtmp2 = *mtmp; 232 mtmp2->mxlth = mtmp2->mnamelth = 0; 233 234 /* sometimes the tail end dies */ 235 if (rn2(3) || !getwn(mtmp2)) { 236 monfree(mtmp2); 237 tmp2 = 0; 238 } else { 239 tmp2 = mtmp2->wormno; 240 wsegs[tmp2] = wsegs[tmp]; 241 wgrowtime[tmp2] = 0; 242 } 243 do { 244 if (wtmp->nseg->wx == x && wtmp->nseg->wy == y) { 245 if (tmp2) 246 wheads[tmp2] = wtmp; 247 wsegs[tmp] = wtmp->nseg->nseg; 248 remseg(wtmp->nseg); 249 wtmp->nseg = 0; 250 if (tmp2) { 251 pline("You cut the worm in half."); 252 mtmp2->mhpmax = mtmp2->mhp = 253 d(mtmp2->data->mlevel, 8); 254 mtmp2->mx = wtmp->wx; 255 mtmp2->my = wtmp->wy; 256 mtmp2->nmon = fmon; 257 fmon = mtmp2; 258 pmon(mtmp2); 259 } else { 260 pline("You cut off part of the worm's tail."); 261 remseg(wtmp); 262 monfree(mtmp2); 263 } 264 mtmp->mhp /= 2; 265 return; 266 } 267 wtmp2 = wtmp->nseg; 268 if (!tmp2) 269 remseg(wtmp); 270 wtmp = wtmp2; 271 } while (wtmp->nseg); 272 panic("Cannot find worm segment"); 273 } 274 275 void 276 remseg(struct wseg *wtmp) 277 { 278 if (wtmp->wdispl) 279 newsym(wtmp->wx, wtmp->wy); 280 free((char *) wtmp); 281 } 282 #endif /* NOWORM */ 283