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