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