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