1 /* $NetBSD: hack.worm.c,v 1.6 2006/05/13 22:43:02 christos 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.6 2006/05/13 22:43:02 christos 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(mtmp) 81 struct monst *mtmp; 82 { 83 int tmp; 84 for (tmp = 1; tmp < 32; tmp++) 85 if (!wsegs[tmp]) { 86 mtmp->wormno = tmp; 87 return (1); 88 } 89 return (0); /* level infested with worms */ 90 } 91 92 /* called to initialize a worm unless cut in half */ 93 void 94 initworm(mtmp) 95 struct monst *mtmp; 96 { 97 struct wseg *wtmp; 98 int tmp = mtmp->wormno; 99 if (!tmp) 100 return; 101 wheads[tmp] = wsegs[tmp] = wtmp = newseg(); 102 wgrowtime[tmp] = 0; 103 wtmp->wx = mtmp->mx; 104 wtmp->wy = mtmp->my; 105 /* wtmp->wdispl = 0; */ 106 wtmp->nseg = 0; 107 } 108 109 void 110 worm_move(mtmp) 111 struct monst *mtmp; 112 { 113 struct wseg *wtmp, *whd = NULL; 114 int tmp = mtmp->wormno; 115 wtmp = newseg(); 116 wtmp->wx = mtmp->mx; 117 wtmp->wy = mtmp->my; 118 wtmp->nseg = 0; 119 /* wtmp->wdispl = 0; */ 120 (whd = wheads[tmp])->nseg = wtmp; 121 wheads[tmp] = wtmp; 122 if (cansee(whd->wx, whd->wy)) { 123 unpmon(mtmp); 124 atl(whd->wx, whd->wy, '~'); 125 whd->wdispl = 1; 126 } else 127 whd->wdispl = 0; 128 if (wgrowtime[tmp] <= moves) { 129 if (!wgrowtime[tmp]) 130 wgrowtime[tmp] = moves + rnd(5); 131 else 132 wgrowtime[tmp] += 2 + rnd(15); 133 mtmp->mhpmax += 3; 134 mtmp->mhp += 3; 135 return; 136 } 137 whd = wsegs[tmp]; 138 wsegs[tmp] = whd->nseg; 139 remseg(whd); 140 } 141 142 void 143 worm_nomove(mtmp) 144 struct monst *mtmp; 145 { 146 int tmp; 147 struct wseg *wtmp; 148 tmp = mtmp->wormno; 149 wtmp = wsegs[tmp]; 150 if (wtmp == wheads[tmp]) 151 return; 152 if (wtmp == 0 || wtmp->nseg == 0) 153 panic("worm_nomove?"); 154 wsegs[tmp] = wtmp->nseg; 155 remseg(wtmp); 156 mtmp->mhp -= 3; /* mhpmax not changed ! */ 157 } 158 159 void 160 wormdead(mtmp) 161 struct monst *mtmp; 162 { 163 int tmp = mtmp->wormno; 164 struct wseg *wtmp, *wtmp2; 165 if (!tmp) 166 return; 167 mtmp->wormno = 0; 168 for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp2) { 169 wtmp2 = wtmp->nseg; 170 remseg(wtmp); 171 } 172 wsegs[tmp] = 0; 173 } 174 175 void 176 wormhit(mtmp) 177 struct monst *mtmp; 178 { 179 int tmp = mtmp->wormno; 180 struct wseg *wtmp; 181 if (!tmp) 182 return; /* worm without tail */ 183 for (wtmp = wsegs[tmp]; wtmp; wtmp = wtmp->nseg) 184 (void) hitu(mtmp, 1); 185 } 186 187 void 188 wormsee(tmp) 189 unsigned tmp; 190 { 191 struct wseg *wtmp = wsegs[tmp]; 192 if (!wtmp) 193 panic("wormsee: wtmp==0"); 194 for (; wtmp->nseg; wtmp = wtmp->nseg) 195 if (!cansee(wtmp->wx, wtmp->wy) && wtmp->wdispl) { 196 newsym(wtmp->wx, wtmp->wy); 197 wtmp->wdispl = 0; 198 } 199 } 200 201 void 202 pwseg(wtmp) 203 struct wseg *wtmp; 204 { 205 if (!wtmp->wdispl) { 206 atl(wtmp->wx, wtmp->wy, '~'); 207 wtmp->wdispl = 1; 208 } 209 } 210 211 void 212 cutworm(mtmp, x, y, weptyp) 213 struct monst *mtmp; 214 xchar x, y; 215 uchar weptyp; /* uwep->otyp or 0 */ 216 { 217 struct wseg *wtmp, *wtmp2; 218 struct monst *mtmp2; 219 int tmp, tmp2; 220 if (mtmp->mx == x && mtmp->my == y) 221 return; /* hit headon */ 222 223 /* cutting goes best with axe or sword */ 224 tmp = rnd(20); 225 if (weptyp == LONG_SWORD || weptyp == TWO_HANDED_SWORD || 226 weptyp == AXE) 227 tmp += 5; 228 if (tmp < 12) 229 return; 230 231 /* if tail then worm just loses a tail segment */ 232 tmp = mtmp->wormno; 233 wtmp = wsegs[tmp]; 234 if (wtmp->wx == x && wtmp->wy == y) { 235 wsegs[tmp] = wtmp->nseg; 236 remseg(wtmp); 237 return; 238 } 239 /* cut the worm in two halves */ 240 mtmp2 = newmonst(0); 241 *mtmp2 = *mtmp; 242 mtmp2->mxlth = mtmp2->mnamelth = 0; 243 244 /* sometimes the tail end dies */ 245 if (rn2(3) || !getwn(mtmp2)) { 246 monfree(mtmp2); 247 tmp2 = 0; 248 } else { 249 tmp2 = mtmp2->wormno; 250 wsegs[tmp2] = wsegs[tmp]; 251 wgrowtime[tmp2] = 0; 252 } 253 do { 254 if (wtmp->nseg->wx == x && wtmp->nseg->wy == y) { 255 if (tmp2) 256 wheads[tmp2] = wtmp; 257 wsegs[tmp] = wtmp->nseg->nseg; 258 remseg(wtmp->nseg); 259 wtmp->nseg = 0; 260 if (tmp2) { 261 pline("You cut the worm in half."); 262 mtmp2->mhpmax = mtmp2->mhp = 263 d(mtmp2->data->mlevel, 8); 264 mtmp2->mx = wtmp->wx; 265 mtmp2->my = wtmp->wy; 266 mtmp2->nmon = fmon; 267 fmon = mtmp2; 268 pmon(mtmp2); 269 } else { 270 pline("You cut off part of the worm's tail."); 271 remseg(wtmp); 272 monfree(mtmp2); 273 } 274 mtmp->mhp /= 2; 275 return; 276 } 277 wtmp2 = wtmp->nseg; 278 if (!tmp2) 279 remseg(wtmp); 280 wtmp = wtmp2; 281 } while (wtmp->nseg); 282 panic("Cannot find worm segment"); 283 } 284 285 void 286 remseg(wtmp) 287 struct wseg *wtmp; 288 { 289 if (wtmp->wdispl) 290 newsym(wtmp->wx, wtmp->wy); 291 free((char *) wtmp); 292 } 293 #endif /* NOWORM */ 294