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