1 1.10 rillig /* $NetBSD: hack.zap.c,v 1.10 2021/05/02 12:50:44 rillig Exp $ */ 2 1.4 christos 3 1.2 mycroft /* 4 1.6 jsm * Copyright (c) 1985, Stichting Centrum voor Wiskunde en Informatica, 5 1.6 jsm * Amsterdam 6 1.6 jsm * All rights reserved. 7 1.6 jsm * 8 1.6 jsm * Redistribution and use in source and binary forms, with or without 9 1.6 jsm * modification, are permitted provided that the following conditions are 10 1.6 jsm * met: 11 1.6 jsm * 12 1.6 jsm * - Redistributions of source code must retain the above copyright notice, 13 1.6 jsm * this list of conditions and the following disclaimer. 14 1.6 jsm * 15 1.6 jsm * - Redistributions in binary form must reproduce the above copyright 16 1.6 jsm * notice, this list of conditions and the following disclaimer in the 17 1.6 jsm * documentation and/or other materials provided with the distribution. 18 1.6 jsm * 19 1.6 jsm * - Neither the name of the Stichting Centrum voor Wiskunde en 20 1.6 jsm * Informatica, nor the names of its contributors may be used to endorse or 21 1.6 jsm * promote products derived from this software without specific prior 22 1.6 jsm * written permission. 23 1.6 jsm * 24 1.6 jsm * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 25 1.6 jsm * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 1.6 jsm * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 27 1.6 jsm * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 28 1.6 jsm * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 29 1.6 jsm * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 30 1.6 jsm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 31 1.6 jsm * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32 1.6 jsm * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 33 1.6 jsm * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34 1.6 jsm * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 1.6 jsm */ 36 1.6 jsm 37 1.6 jsm /* 38 1.6 jsm * Copyright (c) 1982 Jay Fenlason <hack (at) gnu.org> 39 1.6 jsm * All rights reserved. 40 1.6 jsm * 41 1.6 jsm * Redistribution and use in source and binary forms, with or without 42 1.6 jsm * modification, are permitted provided that the following conditions 43 1.6 jsm * are met: 44 1.6 jsm * 1. Redistributions of source code must retain the above copyright 45 1.6 jsm * notice, this list of conditions and the following disclaimer. 46 1.6 jsm * 2. Redistributions in binary form must reproduce the above copyright 47 1.6 jsm * notice, this list of conditions and the following disclaimer in the 48 1.6 jsm * documentation and/or other materials provided with the distribution. 49 1.6 jsm * 3. The name of the author may not be used to endorse or promote products 50 1.6 jsm * derived from this software without specific prior written permission. 51 1.6 jsm * 52 1.6 jsm * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 53 1.6 jsm * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 54 1.6 jsm * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 55 1.6 jsm * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 56 1.6 jsm * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 57 1.6 jsm * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 58 1.6 jsm * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 59 1.6 jsm * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 60 1.6 jsm * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 61 1.6 jsm * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 62 1.2 mycroft */ 63 1.2 mycroft 64 1.4 christos #include <sys/cdefs.h> 65 1.2 mycroft #ifndef lint 66 1.10 rillig __RCSID("$NetBSD: hack.zap.c,v 1.10 2021/05/02 12:50:44 rillig Exp $"); 67 1.4 christos #endif /* not lint */ 68 1.1 cgd 69 1.1 cgd #include "hack.h" 70 1.4 christos #include "extern.h" 71 1.1 cgd 72 1.9 dholland static const char *const fl[] = { 73 1.1 cgd "magic missile", 74 1.1 cgd "bolt of fire", 75 1.1 cgd "sleep ray", 76 1.1 cgd "bolt of cold", 77 1.1 cgd "death ray" 78 1.1 cgd }; 79 1.1 cgd 80 1.9 dholland static void bhitm(struct monst *, struct obj *); 81 1.9 dholland static int bhito(struct obj *, struct obj *); 82 1.9 dholland static char dirlet(int, int); 83 1.9 dholland static int zhit(struct monst *, int); 84 1.9 dholland static int revive(struct obj *); 85 1.9 dholland static void rloco(struct obj *); 86 1.9 dholland static void burn_scrolls(void); 87 1.9 dholland 88 1.1 cgd /* Routines for IMMEDIATE wands. */ 89 1.1 cgd /* bhitm: monster mtmp was hit by the effect of wand otmp */ 90 1.9 dholland static void 91 1.8 dholland bhitm(struct monst *mtmp, struct obj *otmp) 92 1.1 cgd { 93 1.1 cgd wakeup(mtmp); 94 1.4 christos switch (otmp->otyp) { 95 1.1 cgd case WAN_STRIKING: 96 1.4 christos if (u.uswallow || rnd(20) < 10 + mtmp->data->ac) { 97 1.4 christos int tmp = d(2, 12); 98 1.1 cgd hit("wand", mtmp, exclam(tmp)); 99 1.1 cgd mtmp->mhp -= tmp; 100 1.4 christos if (mtmp->mhp < 1) 101 1.4 christos killed(mtmp); 102 1.4 christos } else 103 1.4 christos miss("wand", mtmp); 104 1.1 cgd break; 105 1.1 cgd case WAN_SLOW_MONSTER: 106 1.1 cgd mtmp->mspeed = MSLOW; 107 1.1 cgd break; 108 1.1 cgd case WAN_SPEED_MONSTER: 109 1.1 cgd mtmp->mspeed = MFAST; 110 1.1 cgd break; 111 1.1 cgd case WAN_UNDEAD_TURNING: 112 1.4 christos if (strchr(UNDEAD, mtmp->data->mlet)) { 113 1.1 cgd mtmp->mhp -= rnd(8); 114 1.4 christos if (mtmp->mhp < 1) 115 1.4 christos killed(mtmp); 116 1.4 christos else 117 1.4 christos mtmp->mflee = 1; 118 1.1 cgd } 119 1.1 cgd break; 120 1.1 cgd case WAN_POLYMORPH: 121 1.4 christos if (newcham(mtmp, &mons[rn2(CMNUM)])) 122 1.1 cgd objects[otmp->otyp].oc_name_known = 1; 123 1.1 cgd break; 124 1.1 cgd case WAN_CANCELLATION: 125 1.1 cgd mtmp->mcan = 1; 126 1.1 cgd break; 127 1.1 cgd case WAN_TELEPORTATION: 128 1.1 cgd rloc(mtmp); 129 1.1 cgd break; 130 1.1 cgd case WAN_MAKE_INVISIBLE: 131 1.1 cgd mtmp->minvis = 1; 132 1.1 cgd break; 133 1.1 cgd #ifdef WAN_PROBING 134 1.1 cgd case WAN_PROBING: 135 1.1 cgd mstatusline(mtmp); 136 1.1 cgd break; 137 1.4 christos #endif /* WAN_PROBING */ 138 1.1 cgd default: 139 1.1 cgd impossible("What an interesting wand (%u)", otmp->otyp); 140 1.1 cgd } 141 1.1 cgd } 142 1.1 cgd 143 1.8 dholland /* 144 1.8 dholland * object obj was hit by the effect of wand otmp 145 1.8 dholland * returns TRUE if sth was done 146 1.8 dholland */ 147 1.9 dholland static int 148 1.8 dholland bhito(struct obj *obj, struct obj *otmp) 149 1.1 cgd { 150 1.4 christos int res = TRUE; 151 1.1 cgd 152 1.4 christos if (obj == uball || obj == uchain) 153 1.1 cgd res = FALSE; 154 1.1 cgd else 155 1.4 christos switch (otmp->otyp) { 156 1.4 christos case WAN_POLYMORPH: 157 1.4 christos /* 158 1.4 christos * preserve symbol and quantity, but turn rocks into 159 1.4 christos * gems 160 1.4 christos */ 161 1.4 christos mkobj_at((obj->otyp == ROCK || obj->otyp == ENORMOUS_ROCK) 162 1.4 christos ? GEM_SYM : obj->olet, 163 1.4 christos obj->ox, obj->oy)->quan = obj->quan; 164 1.4 christos delobj(obj); 165 1.4 christos break; 166 1.4 christos case WAN_STRIKING: 167 1.4 christos if (obj->otyp == ENORMOUS_ROCK) 168 1.4 christos fracture_rock(obj); 169 1.4 christos else 170 1.4 christos res = FALSE; 171 1.4 christos break; 172 1.4 christos case WAN_CANCELLATION: 173 1.4 christos if (obj->spe && obj->olet != AMULET_SYM) { 174 1.4 christos obj->known = 0; 175 1.4 christos obj->spe = 0; 176 1.4 christos } 177 1.4 christos break; 178 1.4 christos case WAN_TELEPORTATION: 179 1.4 christos rloco(obj); 180 1.4 christos break; 181 1.4 christos case WAN_MAKE_INVISIBLE: 182 1.4 christos obj->oinvis = 1; 183 1.4 christos break; 184 1.4 christos case WAN_UNDEAD_TURNING: 185 1.4 christos res = revive(obj); 186 1.4 christos break; 187 1.4 christos case WAN_SLOW_MONSTER: /* no effect on objects */ 188 1.4 christos case WAN_SPEED_MONSTER: 189 1.4 christos #ifdef WAN_PROBING 190 1.4 christos case WAN_PROBING: 191 1.4 christos #endif /* WAN_PROBING */ 192 1.1 cgd res = FALSE; 193 1.4 christos break; 194 1.4 christos default: 195 1.4 christos impossible("What an interesting wand (%u)", otmp->otyp); 196 1.1 cgd } 197 1.4 christos return (res); 198 1.1 cgd } 199 1.1 cgd 200 1.4 christos int 201 1.8 dholland dozap(void) 202 1.1 cgd { 203 1.4 christos struct obj *obj; 204 1.4 christos xchar zx, zy; 205 1.1 cgd 206 1.1 cgd obj = getobj("/", "zap"); 207 1.4 christos if (!obj) 208 1.4 christos return (0); 209 1.4 christos if (obj->spe < 0 || (obj->spe == 0 && rn2(121))) { 210 1.1 cgd pline("Nothing Happens."); 211 1.4 christos return (1); 212 1.1 cgd } 213 1.4 christos if (obj->spe == 0) 214 1.1 cgd pline("You wrest one more spell from the worn-out wand."); 215 1.4 christos if (!(objects[obj->otyp].bits & NODIR) && !getdir(1)) 216 1.4 christos return (1); /* make him pay for knowing !NODIR */ 217 1.1 cgd obj->spe--; 218 1.4 christos if (objects[obj->otyp].bits & IMMEDIATE) { 219 1.4 christos if (u.uswallow) 220 1.1 cgd bhitm(u.ustuck, obj); 221 1.4 christos else if (u.dz) { 222 1.4 christos if (u.dz > 0) { 223 1.4 christos struct obj *otmp = o_at(u.ux, u.uy); 224 1.4 christos if (otmp) 225 1.1 cgd (void) bhito(otmp, obj); 226 1.1 cgd } 227 1.1 cgd } else 228 1.4 christos (void) bhit(u.dx, u.dy, rn1(8, 6), 0, bhitm, bhito, obj); 229 1.1 cgd } else { 230 1.4 christos switch (obj->otyp) { 231 1.1 cgd case WAN_LIGHT: 232 1.1 cgd litroom(TRUE); 233 1.1 cgd break; 234 1.1 cgd case WAN_SECRET_DOOR_DETECTION: 235 1.4 christos if (!findit()) 236 1.4 christos return (1); 237 1.1 cgd break; 238 1.1 cgd case WAN_CREATE_MONSTER: 239 1.4 christos { 240 1.4 christos int cnt = 1; 241 1.4 christos if (!rn2(23)) 242 1.4 christos cnt += rn2(7) + 1; 243 1.4 christos while (cnt--) 244 1.4 christos (void) makemon((struct permonst *) 0, u.ux, u.uy); 245 1.1 cgd } 246 1.1 cgd break; 247 1.1 cgd case WAN_WISHING: 248 1.4 christos { 249 1.4 christos char buf[BUFSZ]; 250 1.4 christos struct obj *otmp; 251 1.4 christos if (u.uluck + rn2(5) < 0) { 252 1.4 christos pline("Unfortunately, nothing happens."); 253 1.4 christos break; 254 1.4 christos } 255 1.4 christos pline("You may wish for an object. What do you want? "); 256 1.4 christos getlin(buf); 257 1.4 christos if (buf[0] == '\033') 258 1.4 christos buf[0] = 0; 259 1.4 christos otmp = readobjnam(buf); 260 1.4 christos otmp = addinv(otmp); 261 1.4 christos prinv(otmp); 262 1.4 christos break; 263 1.1 cgd } 264 1.1 cgd case WAN_DIGGING: 265 1.4 christos /* 266 1.4 christos * Original effect (approximately): from CORR: dig 267 1.4 christos * until we pierce a wall from ROOM: piece wall and 268 1.4 christos * dig until we reach an ACCESSIBLE place. Currently: 269 1.4 christos * dig for digdepth positions; also down on request 270 1.4 christos * of Lennart Augustsson. 271 1.1 cgd */ 272 1.4 christos { 273 1.4 christos struct rm *room; 274 1.4 christos int digdepth; 275 1.4 christos if (u.uswallow) { 276 1.4 christos struct monst *mtmp = u.ustuck; 277 1.4 christos 278 1.4 christos pline("You pierce %s's stomach wall!", 279 1.4 christos monnam(mtmp)); 280 1.4 christos mtmp->mhp = 1; /* almost dead */ 281 1.4 christos unstuck(mtmp); 282 1.4 christos mnexto(mtmp); 283 1.4 christos break; 284 1.4 christos } 285 1.4 christos if (u.dz) { 286 1.4 christos if (u.dz < 0) { 287 1.4 christos pline("You loosen a rock from the ceiling."); 288 1.4 christos pline("It falls on your head!"); 289 1.4 christos losehp(1, "falling rock"); 290 1.4 christos mksobj_at(ROCK, u.ux, u.uy); 291 1.4 christos fobj->quan = 1; 292 1.4 christos stackobj(fobj); 293 1.4 christos if (Invisible) 294 1.4 christos newsym(u.ux, u.uy); 295 1.4 christos } else { 296 1.4 christos dighole(); 297 1.4 christos } 298 1.4 christos break; 299 1.4 christos } 300 1.4 christos zx = u.ux + u.dx; 301 1.4 christos zy = u.uy + u.dy; 302 1.4 christos digdepth = 8 + rn2(18); 303 1.4 christos Tmp_at(-1, '*'); /* open call */ 304 1.4 christos while (--digdepth >= 0) { 305 1.4 christos if (!isok(zx, zy)) 306 1.1 cgd break; 307 1.4 christos room = &levl[zx][zy]; 308 1.4 christos Tmp_at(zx, zy); 309 1.4 christos if (!xdnstair) { 310 1.4 christos if (zx < 3 || zx > COLNO - 3 || 311 1.4 christos zy < 3 || zy > ROWNO - 3) 312 1.4 christos break; 313 1.4 christos if (room->typ == HWALL || 314 1.4 christos room->typ == VWALL) { 315 1.4 christos room->typ = ROOM; 316 1.4 christos break; 317 1.4 christos } 318 1.4 christos } else if (room->typ == HWALL || room->typ == VWALL || 319 1.4 christos room->typ == SDOOR || room->typ == LDOOR) { 320 1.4 christos room->typ = DOOR; 321 1.4 christos digdepth -= 2; 322 1.4 christos } else if (room->typ == SCORR || !room->typ) { 323 1.4 christos room->typ = CORR; 324 1.4 christos digdepth--; 325 1.1 cgd } 326 1.4 christos mnewsym(zx, zy); 327 1.4 christos zx += u.dx; 328 1.4 christos zy += u.dy; 329 1.1 cgd } 330 1.4 christos mnewsym(zx, zy); /* not always necessary */ 331 1.4 christos Tmp_at(-1, -1); /* closing call */ 332 1.4 christos break; 333 1.1 cgd } 334 1.1 cgd default: 335 1.1 cgd buzz((int) obj->otyp - WAN_MAGIC_MISSILE, 336 1.4 christos u.ux, u.uy, u.dx, u.dy); 337 1.1 cgd break; 338 1.1 cgd } 339 1.4 christos if (!objects[obj->otyp].oc_name_known) { 340 1.1 cgd objects[obj->otyp].oc_name_known = 1; 341 1.4 christos more_experienced(0, 10); 342 1.1 cgd } 343 1.1 cgd } 344 1.4 christos return (1); 345 1.1 cgd } 346 1.1 cgd 347 1.5 jsm const char * 348 1.8 dholland exclam(int force) 349 1.1 cgd { 350 1.1 cgd /* force == 0 occurs e.g. with sleep ray */ 351 1.4 christos /* 352 1.4 christos * note that large force is usual with wands so that !! would require 353 1.4 christos * information about hand/weapon/wand 354 1.4 christos */ 355 1.4 christos return ((force < 0) ? "?" : (force <= 4) ? "." : "!"); 356 1.1 cgd } 357 1.1 cgd 358 1.4 christos void 359 1.8 dholland hit(const char *str, struct monst *mtmp, const char *force) 360 1.1 cgd { 361 1.8 dholland /* force is usually either "." or "!" */ 362 1.8 dholland 363 1.4 christos if (!cansee(mtmp->mx, mtmp->my)) 364 1.4 christos pline("The %s hits it.", str); 365 1.4 christos else 366 1.4 christos pline("The %s hits %s%s", str, monnam(mtmp), force); 367 1.1 cgd } 368 1.1 cgd 369 1.4 christos void 370 1.8 dholland miss(const char *str, struct monst *mtmp) 371 1.1 cgd { 372 1.4 christos if (!cansee(mtmp->mx, mtmp->my)) 373 1.4 christos pline("The %s misses it.", str); 374 1.4 christos else 375 1.4 christos pline("The %s misses %s.", str, monnam(mtmp)); 376 1.1 cgd } 377 1.1 cgd 378 1.4 christos /* 379 1.4 christos * bhit: called when a weapon is thrown (sym = obj->olet) or when an 380 1.4 christos * IMMEDIATE wand is zapped (sym = 0); the weapon falls down at end of range 381 1.4 christos * or when a monster is hit; the monster is returned, and bhitpos is set to 382 1.4 christos * the final position of the weapon thrown; the ray of a wand may affect 383 1.4 christos * several objects and monsters on its path - for each of these an argument 384 1.4 christos * function is called. 385 1.4 christos */ 386 1.1 cgd /* check !u.uswallow before calling bhit() */ 387 1.1 cgd 388 1.4 christos struct monst * 389 1.8 dholland bhit(int ddx, int ddy, int range, /* direction and range */ 390 1.8 dholland int sym, /* symbol displayed on path */ 391 1.8 dholland /* fns called when mon/obj hit */ 392 1.8 dholland void (*fhitm)(struct monst *, struct obj *), 393 1.8 dholland int (*fhito)(struct obj *, struct obj *), 394 1.8 dholland struct obj *obj) /* 2nd arg to fhitm/fhito */ 395 1.4 christos { 396 1.4 christos struct monst *mtmp; 397 1.4 christos struct obj *otmp; 398 1.4 christos int typ; 399 1.1 cgd 400 1.1 cgd bhitpos.x = u.ux; 401 1.1 cgd bhitpos.y = u.uy; 402 1.1 cgd 403 1.4 christos if (sym) 404 1.4 christos tmp_at(-1, sym);/* open call */ 405 1.4 christos while (range-- > 0) { 406 1.1 cgd bhitpos.x += ddx; 407 1.1 cgd bhitpos.y += ddy; 408 1.1 cgd typ = levl[bhitpos.x][bhitpos.y].typ; 409 1.4 christos if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != NULL) { 410 1.4 christos if (sym) { 411 1.1 cgd tmp_at(-1, -1); /* close call */ 412 1.4 christos return (mtmp); 413 1.1 cgd } 414 1.4 christos (*fhitm) (mtmp, obj); 415 1.1 cgd range -= 3; 416 1.1 cgd } 417 1.4 christos if (fhito && (otmp = o_at(bhitpos.x, bhitpos.y))) { 418 1.4 christos if ((*fhito) (otmp, obj)) 419 1.1 cgd range--; 420 1.1 cgd } 421 1.4 christos if (!ZAP_POS(typ)) { 422 1.1 cgd bhitpos.x -= ddx; 423 1.1 cgd bhitpos.y -= ddy; 424 1.1 cgd break; 425 1.1 cgd } 426 1.4 christos if (sym) 427 1.4 christos tmp_at(bhitpos.x, bhitpos.y); 428 1.1 cgd } 429 1.1 cgd 430 1.1 cgd /* leave last symbol unless in a pool */ 431 1.4 christos if (sym) 432 1.4 christos tmp_at(-1, (levl[bhitpos.x][bhitpos.y].typ == POOL) ? -1 : 0); 433 1.4 christos return (0); 434 1.1 cgd } 435 1.1 cgd 436 1.4 christos struct monst * 437 1.5 jsm boomhit(int dx, int dy) 438 1.4 christos { 439 1.4 christos int i, ct; 440 1.4 christos struct monst *mtmp; 441 1.4 christos char sym = ')'; 442 1.1 cgd 443 1.1 cgd bhitpos.x = u.ux; 444 1.1 cgd bhitpos.y = u.uy; 445 1.1 cgd 446 1.4 christos for (i = 0; i < 8; i++) 447 1.4 christos if (xdir[i] == dx && ydir[i] == dy) 448 1.4 christos break; 449 1.1 cgd tmp_at(-1, sym); /* open call */ 450 1.4 christos for (ct = 0; ct < 10; ct++) { 451 1.4 christos if (i == 8) 452 1.4 christos i = 0; 453 1.1 cgd sym = ')' + '(' - sym; 454 1.4 christos tmp_at(-2, sym);/* change let call */ 455 1.1 cgd dx = xdir[i]; 456 1.1 cgd dy = ydir[i]; 457 1.1 cgd bhitpos.x += dx; 458 1.1 cgd bhitpos.y += dy; 459 1.4 christos if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != NULL) { 460 1.4 christos tmp_at(-1, -1); 461 1.4 christos return (mtmp); 462 1.1 cgd } 463 1.4 christos if (!ZAP_POS(levl[bhitpos.x][bhitpos.y].typ)) { 464 1.1 cgd bhitpos.x -= dx; 465 1.1 cgd bhitpos.y -= dy; 466 1.1 cgd break; 467 1.1 cgd } 468 1.4 christos if (bhitpos.x == u.ux && bhitpos.y == u.uy) { /* ct == 9 */ 469 1.4 christos if (rn2(20) >= 10 + u.ulevel) { /* we hit ourselves */ 470 1.1 cgd (void) thitu(10, rnd(10), "boomerang"); 471 1.1 cgd break; 472 1.4 christos } else {/* we catch it */ 473 1.4 christos tmp_at(-1, -1); 474 1.1 cgd pline("Skillfully, you catch the boomerang."); 475 1.4 christos return (&youmonst); 476 1.1 cgd } 477 1.1 cgd } 478 1.1 cgd tmp_at(bhitpos.x, bhitpos.y); 479 1.4 christos if (ct % 5 != 0) 480 1.4 christos i++; 481 1.1 cgd } 482 1.4 christos tmp_at(-1, -1); /* do not leave last symbol */ 483 1.4 christos return (0); 484 1.1 cgd } 485 1.1 cgd 486 1.9 dholland static char 487 1.8 dholland dirlet(int dx, int dy) 488 1.4 christos { 489 1.1 cgd return 490 1.1 cgd (dx == dy) ? '\\' : (dx && dy) ? '/' : dx ? '-' : '|'; 491 1.1 cgd } 492 1.1 cgd 493 1.1 cgd /* type == -1: monster spitting fire at you */ 494 1.1 cgd /* type == -1,-2,-3: bolts sent out by wizard */ 495 1.1 cgd /* called with dx = dy = 0 with vertical bolts */ 496 1.4 christos void 497 1.8 dholland buzz(int type, xchar sx, xchar sy, int dx, int dy) 498 1.4 christos { 499 1.4 christos int abstype = abs(type); 500 1.5 jsm const char *fltxt = (type == -1) ? "blaze of fire" : fl[abstype]; 501 1.4 christos struct rm *lev; 502 1.4 christos xchar range; 503 1.4 christos struct monst *mon; 504 1.1 cgd 505 1.4 christos if (u.uswallow) { 506 1.4 christos int tmp; 507 1.1 cgd 508 1.4 christos if (type < 0) 509 1.4 christos return; 510 1.1 cgd tmp = zhit(u.ustuck, type); 511 1.1 cgd pline("The %s rips into %s%s", 512 1.4 christos fltxt, monnam(u.ustuck), exclam(tmp)); 513 1.1 cgd return; 514 1.1 cgd } 515 1.4 christos if (type < 0) 516 1.4 christos pru(); 517 1.4 christos range = rn1(7, 7); 518 1.4 christos Tmp_at(-1, dirlet(dx, dy)); /* open call */ 519 1.4 christos while (range-- > 0) { 520 1.1 cgd sx += dx; 521 1.1 cgd sy += dy; 522 1.4 christos if ((lev = &levl[sx][sy])->typ) 523 1.4 christos Tmp_at(sx, sy); 524 1.1 cgd else { 525 1.4 christos int bounce = 0; 526 1.4 christos if (cansee(sx - dx, sy - dy)) 527 1.1 cgd pline("The %s bounces!", fltxt); 528 1.4 christos if (ZAP_POS(levl[sx][sy - dy].typ)) 529 1.1 cgd bounce = 1; 530 1.4 christos if (ZAP_POS(levl[sx - dx][sy].typ)) { 531 1.4 christos if (!bounce || rn2(2)) 532 1.4 christos bounce = 2; 533 1.1 cgd } 534 1.4 christos switch (bounce) { 535 1.1 cgd case 0: 536 1.1 cgd dx = -dx; 537 1.1 cgd dy = -dy; 538 1.1 cgd continue; 539 1.1 cgd case 1: 540 1.1 cgd dy = -dy; 541 1.1 cgd sx -= dx; 542 1.1 cgd break; 543 1.1 cgd case 2: 544 1.1 cgd dx = -dx; 545 1.1 cgd sy -= dy; 546 1.1 cgd break; 547 1.1 cgd } 548 1.4 christos Tmp_at(-2, dirlet(dx, dy)); 549 1.1 cgd continue; 550 1.1 cgd } 551 1.4 christos if (lev->typ == POOL && abstype == 1 /* fire */ ) { 552 1.1 cgd range -= 3; 553 1.1 cgd lev->typ = ROOM; 554 1.4 christos if (cansee(sx, sy)) { 555 1.4 christos mnewsym(sx, sy); 556 1.1 cgd pline("The water evaporates."); 557 1.1 cgd } else 558 1.1 cgd pline("You hear a hissing sound."); 559 1.1 cgd } 560 1.4 christos if ((mon = m_at(sx, sy)) && 561 1.4 christos (type != -1 || mon->data->mlet != 'D')) { 562 1.1 cgd wakeup(mon); 563 1.4 christos if (rnd(20) < 18 + mon->data->ac) { 564 1.4 christos int tmp = zhit(mon, abstype); 565 1.4 christos if (mon->mhp < 1) { 566 1.4 christos if (type < 0) { 567 1.4 christos if (cansee(mon->mx, mon->my)) 568 1.4 christos pline("%s is killed by the %s!", 569 1.4 christos Monnam(mon), fltxt); 570 1.4 christos mondied(mon); 571 1.1 cgd } else 572 1.4 christos killed(mon); 573 1.1 cgd } else 574 1.1 cgd hit(fltxt, mon, exclam(tmp)); 575 1.1 cgd range -= 2; 576 1.1 cgd } else 577 1.4 christos miss(fltxt, mon); 578 1.4 christos } else if (sx == u.ux && sy == u.uy) { 579 1.1 cgd nomul(0); 580 1.4 christos if (rnd(20) < 18 + u.uac) { 581 1.4 christos int dam = 0; 582 1.1 cgd range -= 2; 583 1.4 christos pline("The %s hits you!", fltxt); 584 1.4 christos switch (abstype) { 585 1.1 cgd case 0: 586 1.4 christos dam = d(2, 6); 587 1.1 cgd break; 588 1.1 cgd case 1: 589 1.4 christos if (Fire_resistance) 590 1.1 cgd pline("You don't feel hot!"); 591 1.4 christos else 592 1.4 christos dam = d(6, 6); 593 1.4 christos if (!rn2(3)) 594 1.1 cgd burn_scrolls(); 595 1.1 cgd break; 596 1.1 cgd case 2: 597 1.4 christos nomul(-rnd(25)); /* sleep ray */ 598 1.1 cgd break; 599 1.1 cgd case 3: 600 1.4 christos if (Cold_resistance) 601 1.1 cgd pline("You don't feel cold!"); 602 1.4 christos else 603 1.4 christos dam = d(6, 6); 604 1.1 cgd break; 605 1.1 cgd case 4: 606 1.1 cgd u.uhp = -1; 607 1.1 cgd } 608 1.4 christos losehp(dam, fltxt); 609 1.4 christos } else 610 1.4 christos pline("The %s whizzes by you!", fltxt); 611 1.1 cgd stop_occupation(); 612 1.1 cgd } 613 1.4 christos if (!ZAP_POS(lev->typ)) { 614 1.4 christos int bounce = 0, rmn; 615 1.4 christos if (cansee(sx, sy)) 616 1.4 christos pline("The %s bounces!", fltxt); 617 1.1 cgd range--; 618 1.4 christos if (!dx || !dy || !rn2(20)) { 619 1.1 cgd dx = -dx; 620 1.1 cgd dy = -dy; 621 1.1 cgd } else { 622 1.4 christos if (ZAP_POS(rmn = levl[sx][sy - dy].typ) && 623 1.4 christos (IS_ROOM(rmn) || ZAP_POS(levl[sx + dx][sy - dy].typ))) 624 1.4 christos bounce = 1; 625 1.4 christos if (ZAP_POS(rmn = levl[sx - dx][sy].typ) && 626 1.4 christos (IS_ROOM(rmn) || ZAP_POS(levl[sx - dx][sy + dy].typ))) 627 1.4 christos if (!bounce || rn2(2)) 628 1.4 christos bounce = 2; 629 1.1 cgd 630 1.4 christos switch (bounce) { 631 1.4 christos case 0: 632 1.4 christos dy = -dy; 633 1.4 christos dx = -dx; 634 1.4 christos break; 635 1.4 christos case 1: 636 1.4 christos dy = -dy; 637 1.4 christos break; 638 1.4 christos case 2: 639 1.4 christos dx = -dx; 640 1.4 christos break; 641 1.4 christos } 642 1.4 christos Tmp_at(-2, dirlet(dx, dy)); 643 1.1 cgd } 644 1.1 cgd } 645 1.1 cgd } 646 1.4 christos Tmp_at(-1, -1); 647 1.1 cgd } 648 1.1 cgd 649 1.9 dholland static int 650 1.8 dholland zhit(struct monst *mon, int type) /* returns damage to mon */ 651 1.1 cgd { 652 1.4 christos int tmp = 0; 653 1.1 cgd 654 1.4 christos switch (type) { 655 1.4 christos case 0: /* magic missile */ 656 1.4 christos tmp = d(2, 6); 657 1.1 cgd break; 658 1.1 cgd case -1: /* Dragon blazing fire */ 659 1.4 christos case 1: /* fire */ 660 1.4 christos if (strchr("Dg", mon->data->mlet)) 661 1.4 christos break; 662 1.4 christos tmp = d(6, 6); 663 1.4 christos if (strchr("YF", mon->data->mlet)) 664 1.4 christos tmp += 7; 665 1.1 cgd break; 666 1.4 christos case 2: /* sleep */ 667 1.1 cgd mon->mfroz = 1; 668 1.1 cgd break; 669 1.4 christos case 3: /* cold */ 670 1.4 christos if (strchr("YFgf", mon->data->mlet)) 671 1.4 christos break; 672 1.4 christos tmp = d(6, 6); 673 1.4 christos if (mon->data->mlet == 'D') 674 1.4 christos tmp += 7; 675 1.4 christos break; 676 1.4 christos case 4: /* death */ 677 1.4 christos if (strchr(UNDEAD, mon->data->mlet)) 678 1.4 christos break; 679 1.4 christos tmp = mon->mhp + 1; 680 1.1 cgd break; 681 1.1 cgd } 682 1.1 cgd mon->mhp -= tmp; 683 1.4 christos return (tmp); 684 1.1 cgd } 685 1.1 cgd 686 1.1 cgd #define CORPSE_I_TO_C(otyp) (char) ((otyp >= DEAD_ACID_BLOB)\ 687 1.1 cgd ? 'a' + (otyp - DEAD_ACID_BLOB)\ 688 1.1 cgd : '@' + (otyp - DEAD_HUMAN)) 689 1.9 dholland static int 690 1.8 dholland revive(struct obj *obj) 691 1.1 cgd { 692 1.4 christos struct monst *mtmp = NULL; 693 1.1 cgd 694 1.4 christos if (obj->olet == FOOD_SYM && obj->otyp > CORPSE) { 695 1.1 cgd /* do not (yet) revive shopkeepers */ 696 1.4 christos /* 697 1.4 christos * Note: this might conceivably produce two monsters at the 698 1.4 christos * same position - strange, but harmless 699 1.4 christos */ 700 1.4 christos mtmp = mkmon_at(CORPSE_I_TO_C(obj->otyp), obj->ox, obj->oy); 701 1.1 cgd delobj(obj); 702 1.1 cgd } 703 1.4 christos return (!!mtmp); /* TRUE if some monster created */ 704 1.1 cgd } 705 1.1 cgd 706 1.9 dholland static void 707 1.8 dholland rloco(struct obj *obj) 708 1.1 cgd { 709 1.4 christos int tx, ty, otx, oty; 710 1.1 cgd 711 1.1 cgd otx = obj->ox; 712 1.1 cgd oty = obj->oy; 713 1.1 cgd do { 714 1.4 christos tx = rn1(COLNO - 3, 2); 715 1.1 cgd ty = rn2(ROWNO); 716 1.4 christos } while (!goodpos(tx, ty)); 717 1.1 cgd obj->ox = tx; 718 1.1 cgd obj->oy = ty; 719 1.4 christos if (cansee(otx, oty)) 720 1.4 christos newsym(otx, oty); 721 1.1 cgd } 722 1.1 cgd 723 1.8 dholland /* fractured by pick-axe or wand of striking */ 724 1.8 dholland /* no texts here! */ 725 1.4 christos void 726 1.10 rillig fracture_rock(struct obj *obj) 727 1.1 cgd { 728 1.1 cgd /* unpobj(obj); */ 729 1.1 cgd obj->otyp = ROCK; 730 1.1 cgd obj->quan = 7 + rn2(60); 731 1.1 cgd obj->owt = weight(obj); 732 1.1 cgd obj->olet = WEAPON_SYM; 733 1.4 christos if (cansee(obj->ox, obj->oy)) 734 1.4 christos prl(obj->ox, obj->oy); 735 1.1 cgd } 736 1.1 cgd 737 1.9 dholland static void 738 1.8 dholland burn_scrolls(void) 739 1.1 cgd { 740 1.4 christos struct obj *obj, *obj2; 741 1.4 christos int cnt = 0; 742 1.1 cgd 743 1.4 christos for (obj = invent; obj; obj = obj2) { 744 1.1 cgd obj2 = obj->nobj; 745 1.4 christos if (obj->olet == SCROLL_SYM) { 746 1.1 cgd cnt++; 747 1.1 cgd useup(obj); 748 1.1 cgd } 749 1.1 cgd } 750 1.4 christos if (cnt > 1) { 751 1.1 cgd pline("Your scrolls catch fire!"); 752 1.1 cgd losehp(cnt, "burning scrolls"); 753 1.4 christos } else if (cnt) { 754 1.1 cgd pline("Your scroll catches fire!"); 755 1.1 cgd losehp(1, "burning scroll"); 756 1.1 cgd } 757 1.1 cgd } 758