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