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