1 /*	SCCS Id: @(#)zap.c	3.4	2003/08/24	*/
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4 
5 #include "hack.h"
6 
7 /* Disintegration rays have special treatment; corpses are never left.
8  * But the routine which calculates the damage is separate from the routine
9  * which kills the monster.  The damage routine returns this cookie to
10  * indicate that the monster should be disintegrated.
11  */
12 #define MAGIC_COOKIE 1000
13 
14 #ifdef OVLB
15 static NEARDATA boolean obj_zapped;
16 static NEARDATA int poly_zapped;
17 #endif
18 
19 extern boolean notonhead;	/* for long worms */
20 
21 /* kludge to use mondied instead of killed */
22 extern boolean m_using;
23 
24 STATIC_DCL void FDECL(costly_cancel, (struct obj *));
25 STATIC_DCL void FDECL(polyuse, (struct obj*, int, int));
26 STATIC_DCL void FDECL(create_polymon, (struct obj *, int));
27 STATIC_DCL boolean FDECL(zap_updown, (struct obj *));
28 STATIC_DCL int FDECL(zhitm, (struct monst *,int,int,struct obj **));
29 STATIC_DCL void FDECL(zhitu, (int,int,const char *,XCHAR_P,XCHAR_P));
30 STATIC_DCL void FDECL(revive_egg, (struct obj *));
31 #ifdef STEED
32 STATIC_DCL boolean FDECL(zap_steed, (struct obj *));
33 #endif
34 
35 #ifdef OVLB
36 STATIC_DCL int FDECL(zap_hit, (int,int));
37 #endif
38 #ifdef OVL0
39 STATIC_DCL void FDECL(backfire, (struct obj *));
40 STATIC_DCL int FDECL(spell_hit_bonus, (int));
41 #endif
42 
43 #define ZT_MAGIC_MISSILE	(AD_MAGM-1)
44 #define ZT_FIRE			(AD_FIRE-1)
45 #define ZT_COLD			(AD_COLD-1)
46 #define ZT_SLEEP		(AD_SLEE-1)
47 #define ZT_DEATH		(AD_DISN-1)	/* or disintegration */
48 #define ZT_LIGHTNING		(AD_ELEC-1)
49 #define ZT_POISON_GAS		(AD_DRST-1)
50 #define ZT_ACID			(AD_ACID-1)
51 /* 8 and 9 are currently unassigned */
52 
53 #define ZT_WAND(x)		(x)
54 #define ZT_SPELL(x)		(10+(x))
55 #define ZT_BREATH(x)		(20+(x))
56 
57 #define is_hero_spell(type)	((type) >= 10 && (type) < 20)
58 
59 #ifndef OVLB
60 STATIC_VAR const char are_blinded_by_the_flash[];
61 extern const char * const flash_types[];
62 #else
63 STATIC_VAR const char are_blinded_by_the_flash[] = "are blinded by the flash!";
64 
65 const char * const flash_types[] = {	/* also used in buzzmu(mcastu.c) */
66 	"magic missile",	/* Wands must be 0-9 */
67 	"bolt of fire",
68 	"bolt of cold",
69 	"sleep ray",
70 	"death ray",
71 	"bolt of lightning",
72 	"",
73 	"",
74 	"",
75 	"",
76 
77 	"magic missile",	/* Spell equivalents must be 10-19 */
78 	"fireball",
79 	"cone of cold",
80 	"sleep ray",
81 	"finger of death",
82 	"bolt of lightning",	/* There is no spell, used for retribution */
83 	"",
84 	"",
85 	"",
86 	"",
87 
88 	"blast of missiles",	/* Dragon breath equivalents 20-29*/
89 	"blast of fire",
90 	"blast of frost",
91 	"blast of sleep gas",
92 	"blast of disintegration",
93 	"blast of lightning",
94 	"blast of poison gas",
95 	"blast of acid",
96 	"",
97 	""
98 };
99 
100 /* Routines for IMMEDIATE wands and spells. */
101 /* bhitm: monster mtmp was hit by the effect of wand or spell otmp */
102 int
bhitm(mtmp,otmp)103 bhitm(mtmp, otmp)
104 struct monst *mtmp;
105 struct obj *otmp;
106 {
107 	boolean wake = TRUE;	/* Most 'zaps' should wake monster */
108 	boolean reveal_invis = FALSE;
109 	boolean dbldam = Role_if(PM_KNIGHT) && u.uhave.questart;
110 	int dmg, otyp = otmp->otyp;
111 	const char *zap_type_text = "spell";
112 	struct obj *obj;
113 	boolean disguised_mimic = (mtmp->data->mlet == S_MIMIC &&
114 				   mtmp->m_ap_type != M_AP_NOTHING);
115 
116 	if (u.uswallow && mtmp == u.ustuck)
117 	    reveal_invis = FALSE;
118 
119 	switch(otyp) {
120 	case WAN_STRIKING:
121 		zap_type_text = "wand";
122 		/* fall through */
123 	case SPE_FORCE_BOLT:
124 		reveal_invis = TRUE;
125 		if (resists_magm(mtmp)) {	/* match effect on player */
126 			shieldeff(mtmp->mx, mtmp->my);
127 			break;	/* skip makeknown */
128 		} else if (u.uswallow || rnd(20) < 10 + find_mac(mtmp)) {
129 			dmg = d(2,12);
130 			if(dbldam) dmg *= 2;
131 			if (otyp == SPE_FORCE_BOLT)
132 			    dmg += spell_damage_bonus();
133 			hit(zap_type_text, mtmp, exclam(dmg));
134 			(void) resist(mtmp, otmp->oclass, dmg, TELL);
135 		} else miss(zap_type_text, mtmp);
136 		makeknown(otyp);
137 		break;
138 	case WAN_SLOW_MONSTER:
139 	case SPE_SLOW_MONSTER:
140 		if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
141 			mon_adjust_speed(mtmp, -1, otmp);
142 			m_dowear(mtmp, FALSE); /* might want speed boots */
143 			if (u.uswallow && (mtmp == u.ustuck) &&
144 			    is_whirly(mtmp->data)) {
145 				You("disrupt %s!", mon_nam(mtmp));
146 				pline("A huge hole opens up...");
147 				expels(mtmp, mtmp->data, TRUE);
148 			}
149 		}
150 		break;
151 	case WAN_SPEED_MONSTER:
152 		if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
153 			mon_adjust_speed(mtmp, 1, otmp);
154 			m_dowear(mtmp, FALSE); /* might want speed boots */
155 		}
156 		break;
157 	case WAN_UNDEAD_TURNING:
158 	case SPE_TURN_UNDEAD:
159 		wake = FALSE;
160 		if (unturn_dead(mtmp)) wake = TRUE;
161 		if (is_undead(mtmp->data)) {
162 			reveal_invis = TRUE;
163 			wake = TRUE;
164 			dmg = rnd(8);
165 			if(dbldam) dmg *= 2;
166 			if (otyp == SPE_TURN_UNDEAD)
167 				dmg += spell_damage_bonus();
168 			flags.bypasses = TRUE;	/* for make_corpse() */
169 			if (!resist(mtmp, otmp->oclass, dmg, NOTELL)) {
170 			    if (mtmp->mhp > 0) monflee(mtmp, 0, FALSE, TRUE);
171 			}
172 		}
173 		break;
174 	case WAN_POLYMORPH:
175 	case SPE_POLYMORPH:
176 	case POT_POLYMORPH:
177 		if (resists_magm(mtmp)) {
178 		    /* magic resistance protects from polymorph traps, so make
179 		       it guard against involuntary polymorph attacks too... */
180 		    shieldeff(mtmp->mx, mtmp->my);
181 		} else if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
182 		    /* natural shapechangers aren't affected by system shock
183 		       (unless protection from shapechangers is interfering
184 		       with their metabolism...) */
185 		    if (mtmp->cham == CHAM_ORDINARY && !rn2(25)) {
186 			if (canseemon(mtmp)) {
187 			    pline("%s shudders!", Monnam(mtmp));
188 			    makeknown(otyp);
189 			}
190 			/* dropped inventory shouldn't be hit by this zap */
191 			for (obj = mtmp->minvent; obj; obj = obj->nobj)
192 			    bypass_obj(obj);
193 			/* flags.bypasses = TRUE; ## for make_corpse() */
194 			/* no corpse after system shock */
195 			xkilled(mtmp, 3);
196 		    } else if (newcham(mtmp, (struct permonst *)0,
197 				       (otyp != POT_POLYMORPH), FALSE)) {
198 			if (!Hallucination && canspotmon(mtmp))
199 			    makeknown(otyp);
200 		    }
201 		}
202 		break;
203 	case WAN_CANCELLATION:
204 	case SPE_CANCELLATION:
205 		(void) cancel_monst(mtmp, otmp, TRUE, TRUE, FALSE);
206 		break;
207 	case WAN_TELEPORTATION:
208 	case SPE_TELEPORT_AWAY:
209 		reveal_invis = !u_teleport_mon(mtmp, TRUE);
210 		break;
211 	case WAN_MAKE_INVISIBLE:
212 	    {
213 		int oldinvis = mtmp->minvis;
214 		char nambuf[BUFSZ];
215 
216 		/* format monster's name before altering its visibility */
217 		Strcpy(nambuf, Monnam(mtmp));
218 		mon_set_minvis(mtmp);
219 		if (!oldinvis && knowninvisible(mtmp)) {
220 		    pline("%s turns transparent!", nambuf);
221 		    makeknown(otyp);
222 		}
223 		break;
224 	    }
225 	case WAN_NOTHING:
226 	case WAN_LOCKING:
227 	case SPE_WIZARD_LOCK:
228 		wake = FALSE;
229 		break;
230 	case WAN_PROBING:
231 		wake = FALSE;
232 		reveal_invis = TRUE;
233 		probe_monster(mtmp);
234 		makeknown(otyp);
235 		break;
236 	case WAN_OPENING:
237 	case SPE_KNOCK:
238 		wake = FALSE;	/* don't want immediate counterattack */
239 		if (u.uswallow && mtmp == u.ustuck) {
240 			if (is_animal(mtmp->data)) {
241 				if (Blind) You_feel("a sudden rush of air!");
242 				else pline("%s opens its mouth!", Monnam(mtmp));
243 			}
244 			expels(mtmp, mtmp->data, TRUE);
245 #ifdef STEED
246 		} else if (!!(obj = which_armor(mtmp, W_SADDLE))) {
247 			mtmp->misc_worn_check &= ~obj->owornmask;
248 			update_mon_intrinsics(mtmp, obj, FALSE, FALSE);
249 			obj->owornmask = 0L;
250 			obj_extract_self(obj);
251 			place_object(obj, mtmp->mx, mtmp->my);
252 			/* call stackobj() if we ever drop anything that can merge */
253 			newsym(mtmp->mx, mtmp->my);
254 #endif
255 		}
256 		break;
257 	case SPE_HEALING:
258 	case SPE_EXTRA_HEALING:
259 		reveal_invis = TRUE;
260 	    if (mtmp->data != &mons[PM_PESTILENCE]) {
261 		wake = FALSE;		/* wakeup() makes the target angry */
262 		mtmp->mhp += d(6, otyp == SPE_EXTRA_HEALING ? 8 : 4);
263 		if (mtmp->mhp > mtmp->mhpmax)
264 		    mtmp->mhp = mtmp->mhpmax;
265 		if (mtmp->mblinded) {
266 		    mtmp->mblinded = 0;
267 		    mtmp->mcansee = 1;
268 		}
269 		if (canseemon(mtmp)) {
270 		    if (disguised_mimic) {
271 			if (mtmp->m_ap_type == M_AP_OBJECT &&
272 			    mtmp->mappearance == STRANGE_OBJECT) {
273 			    /* it can do better now */
274 			    set_mimic_sym(mtmp);
275 			    newsym(mtmp->mx, mtmp->my);
276 			} else
277 			    mimic_hit_msg(mtmp, otyp);
278 		    } else pline("%s looks%s better.", Monnam(mtmp),
279 				 otyp == SPE_EXTRA_HEALING ? " much" : "" );
280 		}
281 		if (mtmp->mtame || mtmp->mpeaceful) {
282 		    adjalign(Role_if(PM_HEALER) ? 1 : sgn(u.ualign.type));
283 		}
284 	    } else {	/* Pestilence */
285 		/* Pestilence will always resist; damage is half of 3d{4,8} */
286 		(void) resist(mtmp, otmp->oclass,
287 			      d(3, otyp == SPE_EXTRA_HEALING ? 8 : 4), TELL);
288 	    }
289 		break;
290 	case WAN_LIGHT:	/* (broken wand) */
291 		if (flash_hits_mon(mtmp, otmp)) {
292 		    makeknown(WAN_LIGHT);
293 		    reveal_invis = TRUE;
294 		}
295 		break;
296 	case WAN_SLEEP:	/* (broken wand) */
297 		/* [wakeup() doesn't rouse victims of temporary sleep,
298 		    so it's okay to leave `wake' set to TRUE here] */
299 		reveal_invis = TRUE;
300 		if (sleep_monst(mtmp, d(1 + otmp->spe, 12), WAND_CLASS))
301 		    slept_monst(mtmp);
302 		if (!Blind) makeknown(WAN_SLEEP);
303 		break;
304 	case SPE_STONE_TO_FLESH:
305 		if (monsndx(mtmp->data) == PM_STONE_GOLEM) {
306 		    char *name = Monnam(mtmp);
307 		    /* turn into flesh golem */
308 		    if (newcham(mtmp, &mons[PM_FLESH_GOLEM], FALSE, FALSE)) {
309 			if (canseemon(mtmp))
310 			    pline("%s turns to flesh!", name);
311 		    } else {
312 			if (canseemon(mtmp))
313 			    pline("%s looks rather fleshy for a moment.",
314 				  name);
315 		    }
316 		} else
317 		    wake = FALSE;
318 		break;
319 	case SPE_DRAIN_LIFE:
320 		dmg = rnd(8);
321 		if(dbldam) dmg *= 2;
322 		if (otyp == SPE_DRAIN_LIFE)
323 			dmg += spell_damage_bonus();
324 		if (resists_drli(mtmp))
325 		    shieldeff(mtmp->mx, mtmp->my);
326 		else if (!resist(mtmp, otmp->oclass, dmg, NOTELL) &&
327 				mtmp->mhp > 0) {
328 		    mtmp->mhp -= dmg;
329 		    mtmp->mhpmax -= dmg;
330 		    if (mtmp->mhp <= 0 || mtmp->mhpmax <= 0 || mtmp->m_lev < 1)
331 			xkilled(mtmp, 1);
332 		    else {
333 			mtmp->m_lev--;
334 			if (canseemon(mtmp))
335 			    pline("%s suddenly seems weaker!", Monnam(mtmp));
336 		    }
337 		}
338 		break;
339 	default:
340 		impossible("What an interesting effect (%d)", otyp);
341 		break;
342 	}
343 	if(wake) {
344 	    if(mtmp->mhp > 0) {
345 		wakeup(mtmp);
346 		m_respond(mtmp);
347 		if(mtmp->isshk && !*u.ushops) hot_pursuit(mtmp);
348 	    } else if(mtmp->m_ap_type)
349 		seemimic(mtmp); /* might unblock if mimicing a boulder/door */
350 	}
351 	/* note: bhitpos won't be set if swallowed, but that's okay since
352 	 * reveal_invis will be false.  We can't use mtmp->mx, my since it
353 	 * might be an invisible worm hit on the tail.
354 	 */
355 	if (reveal_invis) {
356 	    if (mtmp->mhp > 0 && cansee(bhitpos.x, bhitpos.y) &&
357 							!canspotmon(mtmp))
358 		map_invisible(bhitpos.x, bhitpos.y);
359 	}
360 	return 0;
361 }
362 
363 void
probe_monster(mtmp)364 probe_monster(mtmp)
365 struct monst *mtmp;
366 {
367 	struct obj *otmp;
368 
369 	mstatusline(mtmp);
370 	if (notonhead) return;	/* don't show minvent for long worm tail */
371 
372 #ifndef GOLDOBJ
373 	if (mtmp->minvent || mtmp->mgold) {
374 #else
375 	if (mtmp->minvent) {
376 #endif
377 	    for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
378 		otmp->dknown = 1;	/* treat as "seen" */
379 	    (void) display_minventory(mtmp, MINV_ALL, (char *)0);
380 	} else {
381 	    pline("%s is not carrying anything.", noit_Monnam(mtmp));
382 	}
383 }
384 
385 #endif /*OVLB*/
386 #ifdef OVL1
387 
388 /*
389  * Return the object's physical location.  This only makes sense for
390  * objects that are currently on the level (i.e. migrating objects
391  * are nowhere).  By default, only things that can be seen (in hero's
392  * inventory, monster's inventory, or on the ground) are reported.
393  * By adding BURIED_TOO and/or CONTAINED_TOO flags, you can also get
394  * the location of buried and contained objects.  Note that if an
395  * object is carried by a monster, its reported position may change
396  * from turn to turn.  This function returns FALSE if the position
397  * is not available or subject to the constraints above.
398  */
399 boolean
get_obj_location(obj,xp,yp,locflags)400 get_obj_location(obj, xp, yp, locflags)
401 struct obj *obj;
402 xchar *xp, *yp;
403 int locflags;
404 {
405 	switch (obj->where) {
406 	    case OBJ_INVENT:
407 		*xp = u.ux;
408 		*yp = u.uy;
409 		return TRUE;
410 	    case OBJ_FLOOR:
411 		*xp = obj->ox;
412 		*yp = obj->oy;
413 		return TRUE;
414 	    case OBJ_MINVENT:
415 		if (obj->ocarry->mx) {
416 		    *xp = obj->ocarry->mx;
417 		    *yp = obj->ocarry->my;
418 		    return TRUE;
419 		}
420 		break;	/* !mx => migrating monster */
421 	    case OBJ_BURIED:
422 		if (locflags & BURIED_TOO) {
423 		    *xp = obj->ox;
424 		    *yp = obj->oy;
425 		    return TRUE;
426 		}
427 		break;
428 	    case OBJ_CONTAINED:
429 		if (locflags & CONTAINED_TOO)
430 		    return get_obj_location(obj->ocontainer, xp, yp, locflags);
431 		break;
432 	}
433 	*xp = *yp = 0;
434 	return FALSE;
435 }
436 
437 boolean
get_mon_location(mon,xp,yp,locflags)438 get_mon_location(mon, xp, yp, locflags)
439 struct monst *mon;
440 xchar *xp, *yp;
441 int locflags;	/* non-zero means get location even if monster is buried */
442 {
443 	if (mon == &youmonst) {
444 	    *xp = u.ux;
445 	    *yp = u.uy;
446 	    return TRUE;
447 	} else if (mon->mx > 0 && (!mon->mburied || locflags)) {
448 	    *xp = mon->mx;
449 	    *yp = mon->my;
450 	    return TRUE;
451 	} else {	/* migrating or buried */
452 	    *xp = *yp = 0;
453 	    return FALSE;
454 	}
455 }
456 
457 /* used by revive() and animate_statue() */
458 struct monst *
montraits(obj,cc)459 montraits(obj,cc)
460 struct obj *obj;
461 coord *cc;
462 {
463 	struct monst *mtmp = (struct monst *)0;
464 	struct monst *mtmp2 = (struct monst *)0;
465 
466 	if (obj->oxlth && (obj->oattached == OATTACHED_MONST))
467 		mtmp2 = get_mtraits(obj, TRUE);
468 	if (mtmp2) {
469 		/* save_mtraits() validated mtmp2->mnum */
470 		mtmp2->data = &mons[mtmp2->mnum];
471 		if (mtmp2->mhpmax <= 0 && !is_rider(mtmp2->data))
472 			return (struct monst *)0;
473 		mtmp = makemon(mtmp2->data,
474 				cc->x, cc->y, NO_MINVENT|MM_NOWAIT|MM_NOCOUNTBIRTH);
475 		if (!mtmp) return mtmp;
476 
477 		/* heal the monster */
478 		if (mtmp->mhpmax > mtmp2->mhpmax && is_rider(mtmp2->data))
479 			mtmp2->mhpmax = mtmp->mhpmax;
480 		mtmp2->mhp = mtmp2->mhpmax;
481 		/* Get these ones from mtmp */
482 		mtmp2->minvent = mtmp->minvent; /*redundant*/
483 		/* monster ID is available if the monster died in the current
484 		   game, but should be zero if the corpse was in a bones level
485 		   (we cleared it when loading bones) */
486 		if (!mtmp2->m_id)
487 		    mtmp2->m_id = mtmp->m_id;
488 		mtmp2->mx   = mtmp->mx;
489 		mtmp2->my   = mtmp->my;
490 		mtmp2->mux  = mtmp->mux;
491 		mtmp2->muy  = mtmp->muy;
492 		mtmp2->mw   = mtmp->mw;
493 		mtmp2->wormno = mtmp->wormno;
494 		mtmp2->misc_worn_check = mtmp->misc_worn_check;
495 		mtmp2->weapon_check = mtmp->weapon_check;
496 		mtmp2->mtrapseen = mtmp->mtrapseen;
497 		mtmp2->mflee = mtmp->mflee;
498 		mtmp2->mburied = mtmp->mburied;
499 		mtmp2->mundetected = mtmp->mundetected;
500 		mtmp2->mfleetim = mtmp->mfleetim;
501 		mtmp2->mlstmv = mtmp->mlstmv;
502 		mtmp2->m_ap_type = mtmp->m_ap_type;
503 		/* set these ones explicitly */
504 		mtmp2->mavenge = 0;
505 		mtmp2->meating = 0;
506 		mtmp2->mleashed = 0;
507 		mtmp2->mtrapped = 0;
508 		mtmp2->msleeping = 0;
509 		mtmp2->mfrozen = 0;
510 		mtmp2->mcanmove = 1;
511 		/* most cancelled monsters return to normal,
512 		   but some need to stay cancelled */
513 		if (!dmgtype(mtmp2->data, AD_SEDU)
514 #ifdef SEDUCE
515 				&& !dmgtype(mtmp2->data, AD_SSEX)
516 #endif
517 		    ) mtmp2->mcan = 0;
518 		mtmp2->mcansee = 1;	/* set like in makemon */
519 		mtmp2->mblinded = 0;
520 		mtmp2->mstun = 0;
521 		mtmp2->mconf = 0;
522 		replmon(mtmp,mtmp2);
523 	}
524 	return mtmp2;
525 }
526 
527 /*
528  * get_container_location() returns the following information
529  * about the outermost container:
530  * loc argument gets set to:
531  *	OBJ_INVENT	if in hero's inventory; return 0.
532  *	OBJ_FLOOR	if on the floor; return 0.
533  *	OBJ_BURIED	if buried; return 0.
534  *	OBJ_MINVENT	if in monster's inventory; return monster.
535  * container_nesting is updated with the nesting depth of the containers
536  * if applicable.
537  */
538 struct monst *
get_container_location(obj,loc,container_nesting)539 get_container_location(obj, loc, container_nesting)
540 struct obj *obj;
541 int *loc;
542 int *container_nesting;
543 {
544 	if (!obj || !loc)
545 		return 0;
546 
547 	if (container_nesting) *container_nesting = 0;
548 	while (obj && obj->where == OBJ_CONTAINED) {
549 		if (container_nesting) *container_nesting += 1;
550 		obj = obj->ocontainer;
551 	}
552 	if (obj) {
553 	    *loc = obj->where;	/* outermost container's location */
554 	    if (obj->where == OBJ_MINVENT) return obj->ocarry;
555 	}
556 	return (struct monst *)0;
557 }
558 
559 /*
560  * Attempt to revive the given corpse, return the revived monster if
561  * successful.  Note: this does NOT use up the corpse if it fails.
562  */
563 struct monst *
revive(obj)564 revive(obj)
565 register struct obj *obj;
566 {
567 	register struct monst *mtmp = (struct monst *)0;
568 	struct obj *container = (struct obj *)0;
569 	int container_nesting = 0;
570 	schar savetame = 0;
571 	boolean recorporealization = FALSE;
572 	boolean in_container = FALSE;
573 	if(obj->otyp == CORPSE) {
574 		int montype = obj->corpsenm;
575 		xchar x, y;
576 
577 		if (obj->where == OBJ_CONTAINED) {
578 			/* deal with corpses in [possibly nested] containers */
579 			struct monst *carrier;
580 			int holder = 0;
581 
582 			container = obj->ocontainer;
583 			carrier = get_container_location(container, &holder,
584 							&container_nesting);
585 			switch(holder) {
586 			    case OBJ_MINVENT:
587 				x = carrier->mx; y = carrier->my;
588 				in_container = TRUE;
589 				break;
590 			    case OBJ_INVENT:
591 				x = u.ux; y = u.uy;
592 				in_container = TRUE;
593 				break;
594 			    case OBJ_FLOOR:
595 				if (!get_obj_location(obj, &x, &y, CONTAINED_TOO))
596 					return (struct monst *) 0;
597 				in_container = TRUE;
598 				break;
599 			    default:
600 			    	return (struct monst *)0;
601 			}
602 		} else {
603 			/* only for invent, minvent, or floor */
604 			if (!get_obj_location(obj, &x, &y, 0))
605 			    return (struct monst *) 0;
606 		}
607 		if (in_container) {
608 			/* Rules for revival from containers:
609 			   - the container cannot be locked
610 			   - the container cannot be heavily nested (>2 is arbitrary)
611 			   - the container cannot be a statue or bag of holding
612 			     (except in very rare cases for the latter)
613 			*/
614 			if (!x || !y || container->olocked || container_nesting > 2 ||
615 			    container->otyp == STATUE ||
616 			    (container->otyp == BAG_OF_HOLDING && rn2(40)))
617 				return (struct monst *)0;
618 		}
619 
620 		if (MON_AT(x,y)) {
621 		    coord new_xy;
622 
623 		    if (enexto(&new_xy, x, y, &mons[montype]))
624 			x = new_xy.x,  y = new_xy.y;
625 		}
626 
627 		if(cant_create(&montype, TRUE)) {
628 			/* make a zombie or worm instead */
629 			mtmp = makemon(&mons[montype], x, y,
630 				       NO_MINVENT|MM_NOWAIT);
631 			if (mtmp) {
632 				mtmp->mhp = mtmp->mhpmax = 100;
633 				mon_adjust_speed(mtmp, 2, (struct obj *)0); /* MFAST */
634 			}
635 		} else {
636 		    if (obj->oxlth && (obj->oattached == OATTACHED_MONST)) {
637 			    coord xy;
638 			    xy.x = x; xy.y = y;
639 		    	    mtmp = montraits(obj, &xy);
640 		    	    if (mtmp && mtmp->mtame && !mtmp->isminion)
641 				wary_dog(mtmp, TRUE);
642 		    } else
643  		            mtmp = makemon(&mons[montype], x, y,
644 				       NO_MINVENT|MM_NOWAIT|MM_NOCOUNTBIRTH);
645 		    if (mtmp) {
646 			if (obj->oxlth && (obj->oattached == OATTACHED_M_ID)) {
647 			    unsigned m_id;
648 			    struct monst *ghost;
649 			    (void) memcpy((genericptr_t)&m_id,
650 				    (genericptr_t)obj->oextra, sizeof(m_id));
651 			    ghost = find_mid(m_id, FM_FMON);
652 		    	    if (ghost && ghost->data == &mons[PM_GHOST]) {
653 		    		    int x2, y2;
654 		    		    x2 = ghost->mx; y2 = ghost->my;
655 		    		    if (ghost->mtame)
656 		    		    	savetame = ghost->mtame;
657 		    		    if (canseemon(ghost))
658 		    		  	pline("%s is suddenly drawn into its former body!",
659 						Monnam(ghost));
660 				    mondead(ghost);
661 				    recorporealization = TRUE;
662 				    newsym(x2, y2);
663 			    }
664 			    /* don't mess with obj->oxlth here */
665 			    obj->oattached = OATTACHED_NOTHING;
666 			}
667 			/* Monster retains its name */
668 			if (obj->onamelth)
669 			    mtmp = christen_monst(mtmp, ONAME(obj));
670 			/* flag the quest leader as alive. */
671 			if (mtmp->data->msound == MS_LEADER || mtmp->m_id ==
672 				quest_status.leader_m_id)
673 			    quest_status.leader_is_dead = FALSE;
674 		    }
675 		}
676 		if (mtmp) {
677 			if (obj->oeaten)
678 				mtmp->mhp = eaten_stat(mtmp->mhp, obj);
679 			/* track that this monster was revived at least once */
680 			mtmp->mrevived = 1;
681 
682 			if (recorporealization) {
683 				/* If mtmp is revivification of former tame ghost*/
684 				if (savetame) {
685 				    struct monst *mtmp2 = tamedog(mtmp, (struct obj *)0);
686 				    if (mtmp2) {
687 					mtmp2->mtame = savetame;
688 					mtmp = mtmp2;
689 				    }
690 				}
691 				/* was ghost, now alive, it's all very confusing */
692 				mtmp->mconf = 1;
693 			}
694 
695 			switch (obj->where) {
696 			    case OBJ_INVENT:
697 				useup(obj);
698 				break;
699 			    case OBJ_FLOOR:
700 				/* in case MON_AT+enexto for invisible mon */
701 				x = obj->ox,  y = obj->oy;
702 				/* not useupf(), which charges */
703 				if (obj->quan > 1L)
704 				    obj = splitobj(obj, 1L);
705 				delobj(obj);
706 				newsym(x, y);
707 				break;
708 			    case OBJ_MINVENT:
709 				m_useup(obj->ocarry, obj);
710 				break;
711 			    case OBJ_CONTAINED:
712 				obj_extract_self(obj);
713 				obfree(obj, (struct obj *) 0);
714 				break;
715 			    default:
716 				panic("revive");
717 			}
718 		}
719 	}
720 	return mtmp;
721 }
722 
723 STATIC_OVL void
revive_egg(obj)724 revive_egg(obj)
725 struct obj *obj;
726 {
727 	/*
728 	 * Note: generic eggs with corpsenm set to NON_PM will never hatch.
729 	 */
730 	if (obj->otyp != EGG) return;
731 	if (obj->corpsenm != NON_PM && !dead_species(obj->corpsenm, TRUE))
732 	    attach_egg_hatch_timeout(obj);
733 }
734 
735 /* try to revive all corpses and eggs carried by `mon' */
736 int
unturn_dead(mon)737 unturn_dead(mon)
738 struct monst *mon;
739 {
740 	struct obj *otmp, *otmp2;
741 	struct monst *mtmp2;
742 	char owner[BUFSZ], corpse[BUFSZ];
743 	boolean youseeit;
744 	int once = 0, res = 0;
745 
746 	youseeit = (mon == &youmonst) ? TRUE : canseemon(mon);
747 	otmp2 = (mon == &youmonst) ? invent : mon->minvent;
748 
749 	while ((otmp = otmp2) != 0) {
750 	    otmp2 = otmp->nobj;
751 	    if (otmp->otyp == EGG)
752 		revive_egg(otmp);
753 	    if (otmp->otyp != CORPSE) continue;
754 	    /* save the name; the object is liable to go away */
755 	    if (youseeit) Strcpy(corpse, corpse_xname(otmp, TRUE));
756 
757 	    /* for a merged group, only one is revived; should this be fixed? */
758 	    if ((mtmp2 = revive(otmp)) != 0) {
759 		++res;
760 		if (youseeit) {
761 		    if (!once++) Strcpy(owner,
762 					(mon == &youmonst) ? "Your" :
763 					s_suffix(Monnam(mon)));
764 		    pline("%s %s suddenly comes alive!", owner, corpse);
765 		} else if (canseemon(mtmp2))
766 		    pline("%s suddenly appears!", Amonnam(mtmp2));
767 	    }
768 	}
769 	return res;
770 }
771 #endif /*OVL1*/
772 
773 #ifdef OVLB
774 static const char charged_objs[] = { WAND_CLASS, WEAPON_CLASS, ARMOR_CLASS, 0 };
775 
776 STATIC_OVL void
costly_cancel(obj)777 costly_cancel(obj)
778 register struct obj *obj;
779 {
780 	char objroom;
781 	struct monst *shkp = (struct monst *)0;
782 
783 	if (obj->no_charge) return;
784 
785 	switch (obj->where) {
786 	case OBJ_INVENT:
787 		if (obj->unpaid) {
788 		    shkp = shop_keeper(*u.ushops);
789 		    if (!shkp) return;
790 		    Norep("You cancel an unpaid object, you pay for it!");
791 		    bill_dummy_object(obj);
792 		}
793 		break;
794 	case OBJ_FLOOR:
795 		objroom = *in_rooms(obj->ox, obj->oy, SHOPBASE);
796 		shkp = shop_keeper(objroom);
797 		if (!shkp || !inhishop(shkp)) return;
798 		if (costly_spot(u.ux, u.uy) && objroom == *u.ushops) {
799 		    Norep("You cancel it, you pay for it!");
800 		    bill_dummy_object(obj);
801 		} else
802 		    (void) stolen_value(obj, obj->ox, obj->oy, FALSE, FALSE);
803 		break;
804 	}
805 }
806 
807 /* cancel obj, possibly carried by you or a monster */
808 void
cancel_item(obj)809 cancel_item(obj)
810 register struct obj *obj;
811 {
812 	boolean	u_ring = (obj == uleft) || (obj == uright);
813 	register boolean holy = (obj->otyp == POT_WATER && obj->blessed);
814 
815 	switch(obj->otyp) {
816 		case RIN_GAIN_STRENGTH:
817 			if ((obj->owornmask & W_RING) && u_ring) {
818 				ABON(A_STR) -= obj->spe;
819 				flags.botl = 1;
820 			}
821 			break;
822 		case RIN_GAIN_CONSTITUTION:
823 			if ((obj->owornmask & W_RING) && u_ring) {
824 				ABON(A_CON) -= obj->spe;
825 				flags.botl = 1;
826 			}
827 			break;
828 		case RIN_ADORNMENT:
829 			if ((obj->owornmask & W_RING) && u_ring) {
830 				ABON(A_CHA) -= obj->spe;
831 				flags.botl = 1;
832 			}
833 			break;
834 		case RIN_INCREASE_ACCURACY:
835 			if ((obj->owornmask & W_RING) && u_ring)
836 				u.uhitinc -= obj->spe;
837 			break;
838 		case RIN_INCREASE_DAMAGE:
839 			if ((obj->owornmask & W_RING) && u_ring)
840 				u.udaminc -= obj->spe;
841 			break;
842 		case GAUNTLETS_OF_DEXTERITY:
843 			if ((obj->owornmask & W_ARMG) && (obj == uarmg)) {
844 				ABON(A_DEX) -= obj->spe;
845 				flags.botl = 1;
846 			}
847 			break;
848 		case HELM_OF_BRILLIANCE:
849 			if ((obj->owornmask & W_ARMH) && (obj == uarmh)) {
850 				ABON(A_INT) -= obj->spe;
851 				ABON(A_WIS) -= obj->spe;
852 				flags.botl = 1;
853 			}
854 			break;
855 		/* case RIN_PROTECTION:  not needed */
856 	}
857 	if (objects[obj->otyp].oc_magic
858 	    || (obj->spe && (obj->oclass == ARMOR_CLASS ||
859 			     obj->oclass == WEAPON_CLASS || is_weptool(obj)))
860 	    || obj->otyp == POT_ACID || obj->otyp == POT_SICKNESS) {
861 	    if (obj->spe != ((obj->oclass == WAND_CLASS) ? -1 : 0) &&
862 	       obj->otyp != WAN_CANCELLATION &&
863 		 /* can't cancel cancellation */
864 		 obj->otyp != MAGIC_LAMP &&
865 		 obj->otyp != CANDELABRUM_OF_INVOCATION) {
866 		costly_cancel(obj);
867 		obj->spe = (obj->oclass == WAND_CLASS) ? -1 : 0;
868 	    }
869 	    switch (obj->oclass) {
870 	      case SCROLL_CLASS:
871 		costly_cancel(obj);
872 		obj->otyp = SCR_BLANK_PAPER;
873 		obj->spe = 0;
874 		break;
875 	      case SPBOOK_CLASS:
876 		if (obj->otyp != SPE_CANCELLATION &&
877 			obj->otyp != SPE_BOOK_OF_THE_DEAD) {
878 		    costly_cancel(obj);
879 		    obj->otyp = SPE_BLANK_PAPER;
880 		}
881 		break;
882 	      case POTION_CLASS:
883 		costly_cancel(obj);
884 		if (obj->otyp == POT_SICKNESS ||
885 		    obj->otyp == POT_SEE_INVISIBLE) {
886 	    /* sickness is "biologically contaminated" fruit juice; cancel it
887 	     * and it just becomes fruit juice... whereas see invisible
888 	     * tastes like "enchanted" fruit juice, it similarly cancels.
889 	     */
890 		    obj->otyp = POT_FRUIT_JUICE;
891 		} else {
892 	            obj->otyp = POT_WATER;
893 		    obj->odiluted = 0; /* same as any other water */
894 		}
895 		break;
896 	    }
897 	}
898 	if (holy) costly_cancel(obj);
899 	unbless(obj);
900 	uncurse(obj);
901 #ifdef INVISIBLE_OBJECTS
902 	if (obj->oinvis) obj->oinvis = 0;
903 #endif
904 	return;
905 }
906 
907 /* Remove a positive enchantment or charge from obj,
908  * possibly carried by you or a monster
909  */
910 boolean
drain_item(obj)911 drain_item(obj)
912 register struct obj *obj;
913 {
914 	boolean u_ring;
915 
916 	/* Is this a charged/enchanted object? */
917 	if (!obj || (!objects[obj->otyp].oc_charged &&
918 			obj->oclass != WEAPON_CLASS &&
919 			obj->oclass != ARMOR_CLASS && !is_weptool(obj)) ||
920 			obj->spe <= 0)
921 	    return (FALSE);
922 	if (obj_resists(obj, 10, 90))
923 	    return (FALSE);
924 
925 	/* Charge for the cost of the object */
926 	costly_cancel(obj);	/* The term "cancel" is okay for now */
927 
928 	/* Drain the object and any implied effects */
929 	obj->spe--;
930 	u_ring = (obj == uleft) || (obj == uright);
931 	switch(obj->otyp) {
932 	case RIN_GAIN_STRENGTH:
933 	    if ((obj->owornmask & W_RING) && u_ring) {
934 	    	ABON(A_STR)--;
935 	    	flags.botl = 1;
936 	    }
937 	    break;
938 	case RIN_GAIN_CONSTITUTION:
939 	    if ((obj->owornmask & W_RING) && u_ring) {
940 	    	ABON(A_CON)--;
941 	    	flags.botl = 1;
942 	    }
943 	    break;
944 	case RIN_ADORNMENT:
945 	    if ((obj->owornmask & W_RING) && u_ring) {
946 	    	ABON(A_CHA)--;
947 	    	flags.botl = 1;
948 	    }
949 	    break;
950 	case RIN_INCREASE_ACCURACY:
951 	    if ((obj->owornmask & W_RING) && u_ring)
952 	    	u.uhitinc--;
953 	    break;
954 	case RIN_INCREASE_DAMAGE:
955 	    if ((obj->owornmask & W_RING) && u_ring)
956 	    	u.udaminc--;
957 	    break;
958 	case HELM_OF_BRILLIANCE:
959 	    if ((obj->owornmask & W_ARMH) && (obj == uarmh)) {
960 	    	ABON(A_INT)--;
961 	    	ABON(A_WIS)--;
962 	    	flags.botl = 1;
963 	    }
964 	    break;
965 	case GAUNTLETS_OF_DEXTERITY:
966 	    if ((obj->owornmask & W_ARMG) && (obj == uarmg)) {
967 	    	ABON(A_DEX)--;
968 	    	flags.botl = 1;
969 	    }
970 	    break;
971 	case RIN_PROTECTION:
972 	    flags.botl = 1;
973 	    break;
974 	}
975 	if (carried(obj)) update_inventory();
976 	return (TRUE);
977 }
978 
979 #endif /*OVLB*/
980 #ifdef OVL0
981 
982 boolean
obj_resists(obj,ochance,achance)983 obj_resists(obj, ochance, achance)
984 struct obj *obj;
985 int ochance, achance;	/* percent chance for ordinary objects, artifacts */
986 {
987 	if (obj->otyp == AMULET_OF_YENDOR ||
988 	    obj->otyp == SPE_BOOK_OF_THE_DEAD ||
989 	    obj->otyp == CANDELABRUM_OF_INVOCATION ||
990 	    obj->otyp == BELL_OF_OPENING ||
991 	    (obj->otyp == CORPSE && is_rider(&mons[obj->corpsenm]))) {
992 		return TRUE;
993 	} else {
994 		int chance = rn2(100);
995 
996 		return((boolean)(chance < (obj->oartifact ? achance : ochance)));
997 	}
998 }
999 
1000 boolean
obj_shudders(obj)1001 obj_shudders(obj)
1002 struct obj *obj;
1003 {
1004 	int	zap_odds;
1005 
1006 	if (obj->oclass == WAND_CLASS)
1007 		zap_odds = 3;	/* half-life = 2 zaps */
1008 	else if (obj->cursed)
1009 		zap_odds = 3;	/* half-life = 2 zaps */
1010 	else if (obj->blessed)
1011 		zap_odds = 12;	/* half-life = 8 zaps */
1012 	else
1013 		zap_odds = 8;	/* half-life = 6 zaps */
1014 
1015 	/* adjust for "large" quantities of identical things */
1016 	if(obj->quan > 4L) zap_odds /= 2;
1017 
1018 	return((boolean)(! rn2(zap_odds)));
1019 }
1020 #endif /*OVL0*/
1021 #ifdef OVLB
1022 
1023 /* Use up at least minwt number of things made of material mat.
1024  * There's also a chance that other stuff will be used up.  Finally,
1025  * there's a random factor here to keep from always using the stuff
1026  * at the top of the pile.
1027  */
1028 STATIC_OVL void
polyuse(objhdr,mat,minwt)1029 polyuse(objhdr, mat, minwt)
1030     struct obj *objhdr;
1031     int mat, minwt;
1032 {
1033     register struct obj *otmp, *otmp2;
1034 
1035     for(otmp = objhdr; minwt > 0 && otmp; otmp = otmp2) {
1036 	otmp2 = otmp->nexthere;
1037 	if (otmp == uball || otmp == uchain) continue;
1038 	if (obj_resists(otmp, 0, 0)) continue;	/* preserve unique objects */
1039 #ifdef MAIL
1040 	if (otmp->otyp == SCR_MAIL) continue;
1041 #endif
1042 
1043 	if (((int) objects[otmp->otyp].oc_material == mat) ==
1044 		(rn2(minwt + 1) != 0)) {
1045 	    /* appropriately add damage to bill */
1046 	    if (costly_spot(otmp->ox, otmp->oy)) {
1047 		if (*u.ushops)
1048 			addtobill(otmp, FALSE, FALSE, FALSE);
1049 		else
1050 			(void)stolen_value(otmp,
1051 					   otmp->ox, otmp->oy, FALSE, FALSE);
1052 	    }
1053 	    if (otmp->quan < LARGEST_INT)
1054 		minwt -= (int)otmp->quan;
1055 	    else
1056 		minwt = 0;
1057 	    delobj(otmp);
1058 	}
1059     }
1060 }
1061 
1062 /*
1063  * Polymorph some of the stuff in this pile into a monster, preferably
1064  * a golem of the kind okind.
1065  */
1066 STATIC_OVL void
create_polymon(obj,okind)1067 create_polymon(obj, okind)
1068     struct obj *obj;
1069     int okind;
1070 {
1071 	struct permonst *mdat = (struct permonst *)0;
1072 	struct monst *mtmp;
1073 	const char *material;
1074 	int pm_index;
1075 
1076 	/* no golems if you zap only one object -- not enough stuff */
1077 	if(!obj || (!obj->nexthere && obj->quan == 1L)) return;
1078 
1079 	/* some of these choices are arbitrary */
1080 	switch(okind) {
1081 	case IRON:
1082 	case METAL:
1083 	case MITHRIL:
1084 	    pm_index = PM_IRON_GOLEM;
1085 	    material = "metal ";
1086 	    break;
1087 	case COPPER:
1088 	case SILVER:
1089 	case PLATINUM:
1090 	case GEMSTONE:
1091 	case MINERAL:
1092 	    pm_index = rn2(2) ? PM_STONE_GOLEM : PM_CLAY_GOLEM;
1093 	    material = "lithic ";
1094 	    break;
1095 	case 0:
1096 	case FLESH:
1097 	    /* there is no flesh type, but all food is type 0, so we use it */
1098 	    pm_index = PM_FLESH_GOLEM;
1099 	    material = "organic ";
1100 	    break;
1101 	case WOOD:
1102 	    pm_index = PM_WOOD_GOLEM;
1103 	    material = "wood ";
1104 	    break;
1105 	case LEATHER:
1106 	    pm_index = PM_LEATHER_GOLEM;
1107 	    material = "leather ";
1108 	    break;
1109 	case CLOTH:
1110 	    pm_index = PM_ROPE_GOLEM;
1111 	    material = "cloth ";
1112 	    break;
1113 	case BONE:
1114 	    pm_index = PM_SKELETON;     /* nearest thing to "bone golem" */
1115 	    material = "bony ";
1116 	    break;
1117 	case GOLD:
1118 	    pm_index = PM_GOLD_GOLEM;
1119 	    material = "gold ";
1120 	    break;
1121 	case GLASS:
1122 	    pm_index = PM_GLASS_GOLEM;
1123 	    material = "glassy ";
1124 	    break;
1125 	case PAPER:
1126 	    pm_index = PM_PAPER_GOLEM;
1127 	    material = "paper ";
1128 	    break;
1129 	default:
1130 	    /* if all else fails... */
1131 	    pm_index = PM_STRAW_GOLEM;
1132 	    material = "";
1133 	    break;
1134 	}
1135 
1136 	if (!(mvitals[pm_index].mvflags & G_GENOD))
1137 		mdat = &mons[pm_index];
1138 
1139 	mtmp = makemon(mdat, obj->ox, obj->oy, NO_MM_FLAGS);
1140 	polyuse(obj, okind, (int)mons[pm_index].cwt);
1141 
1142 	if(mtmp && cansee(mtmp->mx, mtmp->my)) {
1143 	    pline("Some %sobjects meld, and %s arises from the pile!",
1144 		  material, a_monnam(mtmp));
1145 	}
1146 }
1147 
1148 /* Assumes obj is on the floor. */
1149 void
do_osshock(obj)1150 do_osshock(obj)
1151 struct obj *obj;
1152 {
1153 	long i;
1154 
1155 #ifdef MAIL
1156 	if (obj->otyp == SCR_MAIL) return;
1157 #endif
1158 	obj_zapped = TRUE;
1159 
1160 	if(poly_zapped < 0) {
1161 	    /* some may metamorphosize */
1162 	    for (i = obj->quan; i; i--)
1163 		if (! rn2(Luck + 45)) {
1164 		    poly_zapped = objects[obj->otyp].oc_material;
1165 		    break;
1166 		}
1167 	}
1168 
1169 	/* if quan > 1 then some will survive intact */
1170 	if (obj->quan > 1L) {
1171 	    if (obj->quan > LARGEST_INT)
1172 		obj = splitobj(obj, (long)rnd(30000));
1173 	    else
1174 		obj = splitobj(obj, (long)rnd((int)obj->quan - 1));
1175 	}
1176 
1177 	/* appropriately add damage to bill */
1178 	if (costly_spot(obj->ox, obj->oy)) {
1179 		if (*u.ushops)
1180 			addtobill(obj, FALSE, FALSE, FALSE);
1181 		else
1182 			(void)stolen_value(obj,
1183 					   obj->ox, obj->oy, FALSE, FALSE);
1184 	}
1185 
1186 	/* zap the object */
1187 	delobj(obj);
1188 }
1189 
1190 /*
1191  * Polymorph the object to the given object ID.  If the ID is STRANGE_OBJECT
1192  * then pick random object from the source's class (this is the standard
1193  * "polymorph" case).  If ID is set to a specific object, inhibit fusing
1194  * n objects into 1.  This could have been added as a flag, but currently
1195  * it is tied to not being the standard polymorph case. The new polymorphed
1196  * object replaces obj in its link chains.  Return value is a pointer to
1197  * the new object.
1198  *
1199  * This should be safe to call for an object anywhere.
1200  */
1201 struct obj *
poly_obj(obj,id)1202 poly_obj(obj, id)
1203 	struct obj *obj;
1204 	int id;
1205 {
1206 	struct obj *otmp;
1207 	xchar ox, oy;
1208 	boolean can_merge = (id == STRANGE_OBJECT);
1209 	int obj_location = obj->where;
1210 
1211 	if (obj->otyp == BOULDER && In_sokoban(&u.uz))
1212 	    change_luck(-1);	/* Sokoban guilt */
1213 	if (id == STRANGE_OBJECT) { /* preserve symbol */
1214 	    int try_limit = 3;
1215 	    /* Try up to 3 times to make the magic-or-not status of
1216 	       the new item be the same as it was for the old one. */
1217 	    otmp = (struct obj *)0;
1218 	    do {
1219 		if (otmp) delobj(otmp);
1220 		otmp = mkobj(obj->oclass, FALSE);
1221 	    } while (--try_limit > 0 &&
1222 		  objects[obj->otyp].oc_magic != objects[otmp->otyp].oc_magic);
1223 	} else {
1224 	    /* literally replace obj with this new thing */
1225 	    otmp = mksobj(id, FALSE, FALSE);
1226 	/* Actually more things use corpsenm but they polymorph differently */
1227 #define USES_CORPSENM(typ) ((typ)==CORPSE || (typ)==STATUE || (typ)==FIGURINE)
1228 	    if (USES_CORPSENM(obj->otyp) && USES_CORPSENM(id))
1229 		otmp->corpsenm = obj->corpsenm;
1230 #undef USES_CORPSENM
1231 	}
1232 
1233 	/* preserve quantity */
1234 	otmp->quan = obj->quan;
1235 	/* preserve the shopkeepers (lack of) interest */
1236 	otmp->no_charge = obj->no_charge;
1237 	/* preserve inventory letter if in inventory */
1238 	if (obj_location == OBJ_INVENT)
1239 	    otmp->invlet = obj->invlet;
1240 #ifdef MAIL
1241 	/* You can't send yourself 100 mail messages and then
1242 	 * polymorph them into useful scrolls
1243 	 */
1244 	if (obj->otyp == SCR_MAIL) {
1245 		otmp->otyp = SCR_MAIL;
1246 		otmp->spe = 1;
1247 	}
1248 #endif
1249 
1250 	/* avoid abusing eggs laid by you */
1251 	if (obj->otyp == EGG && obj->spe) {
1252 		int mnum, tryct = 100;
1253 
1254 		/* first, turn into a generic egg */
1255 		if (otmp->otyp == EGG)
1256 		    kill_egg(otmp);
1257 		else {
1258 		    otmp->otyp = EGG;
1259 		    otmp->owt = weight(otmp);
1260 		}
1261 		otmp->corpsenm = NON_PM;
1262 		otmp->spe = 0;
1263 
1264 		/* now change it into something layed by the hero */
1265 		while (tryct--) {
1266 		    mnum = can_be_hatched(random_monster());
1267 		    if (mnum != NON_PM && !dead_species(mnum, TRUE)) {
1268 			otmp->spe = 1;	/* layed by hero */
1269 			otmp->corpsenm = mnum;
1270 			attach_egg_hatch_timeout(otmp);
1271 			break;
1272 		    }
1273 		}
1274 	}
1275 
1276 	/* keep special fields (including charges on wands) */
1277 	if (index(charged_objs, otmp->oclass)) otmp->spe = obj->spe;
1278 	otmp->recharged = obj->recharged;
1279 
1280 	otmp->cursed = obj->cursed;
1281 	otmp->blessed = obj->blessed;
1282 	otmp->oeroded = obj->oeroded;
1283 	otmp->oeroded2 = obj->oeroded2;
1284 	if (!is_flammable(otmp) && !is_rustprone(otmp)) otmp->oeroded = 0;
1285 	if (!is_corrodeable(otmp) && !is_rottable(otmp)) otmp->oeroded2 = 0;
1286 	if (is_damageable(otmp))
1287 	    otmp->oerodeproof = obj->oerodeproof;
1288 
1289 	/* Keep chest/box traps and poisoned ammo if we may */
1290 	if (obj->otrapped && Is_box(otmp)) otmp->otrapped = TRUE;
1291 
1292 	if (obj->opoisoned && is_poisonable(otmp))
1293 		otmp->opoisoned = TRUE;
1294 
1295 	if (id == STRANGE_OBJECT && obj->otyp == CORPSE) {
1296 	/* turn crocodile corpses into shoes */
1297 	    if (obj->corpsenm == PM_CROCODILE) {
1298 		otmp->otyp = LOW_BOOTS;
1299 		otmp->oclass = ARMOR_CLASS;
1300 		otmp->spe = 0;
1301 		otmp->oeroded = 0;
1302 		otmp->oerodeproof = TRUE;
1303 		otmp->quan = 1L;
1304 		otmp->cursed = FALSE;
1305 	    }
1306 	}
1307 
1308 	/* no box contents --KAA */
1309 	if (Has_contents(otmp)) delete_contents(otmp);
1310 
1311 	/* 'n' merged objects may be fused into 1 object */
1312 	if (otmp->quan > 1L && (!objects[otmp->otyp].oc_merge ||
1313 				(can_merge && otmp->quan > (long)rn2(1000))))
1314 	    otmp->quan = 1L;
1315 
1316 	switch (otmp->oclass) {
1317 
1318 	case TOOL_CLASS:
1319 	    if (otmp->otyp == MAGIC_LAMP) {
1320 		otmp->otyp = OIL_LAMP;
1321 		otmp->age = 1500L;	/* "best" oil lamp possible */
1322 	    } else if (otmp->otyp == MAGIC_MARKER) {
1323 		otmp->recharged = 1;	/* degraded quality */
1324 	    }
1325 	    /* don't care about the recharge count of other tools */
1326 	    break;
1327 
1328 	case WAND_CLASS:
1329 	    while (otmp->otyp == WAN_WISHING || otmp->otyp == WAN_POLYMORPH)
1330 		otmp->otyp = rnd_class(WAN_LIGHT, WAN_LIGHTNING);
1331 	    /* altering the object tends to degrade its quality
1332 	       (analogous to spellbook `read count' handling) */
1333 	    if ((int)otmp->recharged < rn2(7))	/* recharge_limit */
1334 		otmp->recharged++;
1335 	    break;
1336 
1337 	case POTION_CLASS:
1338 	    while (otmp->otyp == POT_POLYMORPH)
1339 		otmp->otyp = rnd_class(POT_GAIN_ABILITY, POT_WATER);
1340 	    break;
1341 
1342 	case SPBOOK_CLASS:
1343 	    while (otmp->otyp == SPE_POLYMORPH)
1344 		otmp->otyp = rnd_class(SPE_DIG, SPE_BLANK_PAPER);
1345 	    /* reduce spellbook abuse */
1346 	    otmp->spestudied = obj->spestudied + 1;
1347 	    break;
1348 
1349 	case GEM_CLASS:
1350 	    if (otmp->quan > (long) rnd(4) &&
1351 		    objects[obj->otyp].oc_material == MINERAL &&
1352 		    objects[otmp->otyp].oc_material != MINERAL) {
1353 		otmp->otyp = ROCK;	/* transmutation backfired */
1354 		otmp->quan /= 2L;	/* some material has been lost */
1355 	    }
1356 	    break;
1357 	}
1358 
1359 	/* update the weight */
1360 	otmp->owt = weight(otmp);
1361 
1362 	/* for now, take off worn items being polymorphed */
1363 	if (obj_location == OBJ_INVENT) {
1364 	    if (id == STRANGE_OBJECT)
1365 		remove_worn_item(obj, TRUE);
1366 	    else {
1367 		/* This is called only for stone to flesh.  It's a lot simpler
1368 		 * than it otherwise might be.  We don't need to check for
1369 		 * special effects when putting them on (no meat objects have
1370 		 * any) and only three worn masks are possible.
1371 		 */
1372 		otmp->owornmask = obj->owornmask;
1373 		remove_worn_item(obj, TRUE);
1374 		setworn(otmp, otmp->owornmask);
1375 		if (otmp->owornmask & LEFT_RING)
1376 		    uleft = otmp;
1377 		if (otmp->owornmask & RIGHT_RING)
1378 		    uright = otmp;
1379 		if (otmp->owornmask & W_WEP)
1380 		    uwep = otmp;
1381 		if (otmp->owornmask & W_SWAPWEP)
1382 		    uswapwep = otmp;
1383 		if (otmp->owornmask & W_QUIVER)
1384 		    uquiver = otmp;
1385 		goto no_unwear;
1386 	    }
1387 	}
1388 
1389 	/* preserve the mask in case being used by something else */
1390 	otmp->owornmask = obj->owornmask;
1391 no_unwear:
1392 
1393 	if (obj_location == OBJ_FLOOR && obj->otyp == BOULDER &&
1394 		otmp->otyp != BOULDER)
1395 	    unblock_point(obj->ox, obj->oy);
1396 
1397 	/* ** we are now done adjusting the object ** */
1398 
1399 
1400 	/* swap otmp for obj */
1401 	replace_object(obj, otmp);
1402 	if (obj_location == OBJ_INVENT) {
1403 	    /*
1404 	     * We may need to do extra adjustments for the hero if we're
1405 	     * messing with the hero's inventory.  The following calls are
1406 	     * equivalent to calling freeinv on obj and addinv on otmp,
1407 	     * while doing an in-place swap of the actual objects.
1408 	     */
1409 	    freeinv_core(obj);
1410 	    addinv_core1(otmp);
1411 	    addinv_core2(otmp);
1412 	}
1413 
1414 	if ((!carried(otmp) || obj->unpaid) &&
1415 		get_obj_location(otmp, &ox, &oy, BURIED_TOO|CONTAINED_TOO) &&
1416 		costly_spot(ox, oy)) {
1417 	    register struct monst *shkp =
1418 		shop_keeper(*in_rooms(ox, oy, SHOPBASE));
1419 
1420 	    if ((!obj->no_charge ||
1421 		 (Has_contents(obj) &&
1422 		    (contained_cost(obj, shkp, 0L, FALSE, FALSE) != 0L)))
1423 	       && inhishop(shkp)) {
1424 		if(shkp->mpeaceful) {
1425 		    if(*u.ushops && *in_rooms(u.ux, u.uy, 0) ==
1426 			    *in_rooms(shkp->mx, shkp->my, 0) &&
1427 			    !costly_spot(u.ux, u.uy))
1428 			make_angry_shk(shkp, ox, oy);
1429 		    else {
1430 			pline("%s gets angry!", Monnam(shkp));
1431 			hot_pursuit(shkp);
1432 		    }
1433 		} else Norep("%s is furious!", Monnam(shkp));
1434 	    }
1435 	}
1436 	delobj(obj);
1437 	return otmp;
1438 }
1439 
1440 /*
1441  * Object obj was hit by the effect of the wand/spell otmp.  Return
1442  * non-zero if the wand/spell had any effect.
1443  */
1444 int
bhito(obj,otmp)1445 bhito(obj, otmp)
1446 struct obj *obj, *otmp;
1447 {
1448 	int res = 1;	/* affected object by default */
1449 	xchar refresh_x, refresh_y;
1450 
1451 	if (obj->bypass) {
1452 		/* The bypass bit is currently only used as follows:
1453 		 *
1454 		 * POLYMORPH - When a monster being polymorphed drops something
1455 		 *             from its inventory as a result of the change.
1456 		 *             If the items fall to the floor, they are not
1457 		 *             subject to direct subsequent polymorphing
1458 		 *             themselves on that same zap. This makes it
1459 		 *             consistent with items that remain in the
1460 		 *             monster's inventory. They are not polymorphed
1461 		 *             either.
1462 		 * UNDEAD_TURNING - When an undead creature gets killed via
1463 		 *	       undead turning, prevent its corpse from being
1464 		 *	       immediately revived by the same effect.
1465 		 *
1466 		 * The bypass bit on all objects is reset each turn, whenever
1467 		 * flags.bypasses is set.
1468 		 *
1469 		 * We check the obj->bypass bit above AND flags.bypasses
1470 		 * as a safeguard against any stray occurrence left in an obj
1471 		 * struct someplace, although that should never happen.
1472 		 */
1473 		if (flags.bypasses)
1474 			return 0;
1475 		else {
1476 #ifdef DEBUG
1477 			pline("%s for a moment.", Tobjnam(obj, "pulsate"));
1478 #endif
1479 			obj->bypass = 0;
1480 		}
1481 	}
1482 
1483 	/*
1484 	 * Some parts of this function expect the object to be on the floor
1485 	 * obj->{ox,oy} to be valid.  The exception to this (so far) is
1486 	 * for the STONE_TO_FLESH spell.
1487 	 */
1488 	if (!(obj->where == OBJ_FLOOR || otmp->otyp == SPE_STONE_TO_FLESH))
1489 	    impossible("bhito: obj is not floor or Stone To Flesh spell");
1490 
1491 	if (obj == uball) {
1492 		res = 0;
1493 	} else if (obj == uchain) {
1494 		if (otmp->otyp == WAN_OPENING || otmp->otyp == SPE_KNOCK) {
1495 		    unpunish();
1496 		    makeknown(otmp->otyp);
1497 		} else
1498 		    res = 0;
1499 	} else
1500 	switch(otmp->otyp) {
1501 	case WAN_POLYMORPH:
1502 	case SPE_POLYMORPH:
1503 		if (obj->otyp == WAN_POLYMORPH ||
1504 			obj->otyp == SPE_POLYMORPH ||
1505 			obj->otyp == POT_POLYMORPH ||
1506 			obj_resists(obj, 5, 95)) {
1507 		    res = 0;
1508 		    break;
1509 		}
1510 		/* KMH, conduct */
1511 		u.uconduct.polypiles++;
1512 		/* any saved lock context will be dangerously obsolete */
1513 		if (Is_box(obj)) (void) boxlock(obj, otmp);
1514 
1515 		if (obj_shudders(obj)) {
1516 		    if (cansee(obj->ox, obj->oy))
1517 			makeknown(otmp->otyp);
1518 		    do_osshock(obj);
1519 		    break;
1520 		}
1521 		obj = poly_obj(obj, STRANGE_OBJECT);
1522 		newsym(obj->ox,obj->oy);
1523 		break;
1524 	case WAN_PROBING:
1525 		res = !obj->dknown;
1526 		/* target object has now been "seen (up close)" */
1527 		obj->dknown = 1;
1528 		if (Is_container(obj) || obj->otyp == STATUE) {
1529 		    if (!obj->cobj)
1530 			pline("%s empty.", Tobjnam(obj, "are"));
1531 		    else {
1532 			struct obj *o;
1533 			/* view contents (not recursively) */
1534 			for (o = obj->cobj; o; o = o->nobj)
1535 			    o->dknown = 1;	/* "seen", even if blind */
1536 			(void) display_cinventory(obj);
1537 		    }
1538 		    res = 1;
1539 		}
1540 		if (res) makeknown(WAN_PROBING);
1541 		break;
1542 	case WAN_STRIKING:
1543 	case SPE_FORCE_BOLT:
1544 		if (obj->otyp == BOULDER)
1545 			fracture_rock(obj);
1546 		else if (obj->otyp == STATUE)
1547 			(void) break_statue(obj);
1548 		else {
1549 			if (!flags.mon_moving)
1550 			    (void)hero_breaks(obj, obj->ox, obj->oy, FALSE);
1551 			else
1552 			    (void)breaks(obj, obj->ox, obj->oy);
1553 			res = 0;
1554 		}
1555 		/* BUG[?]: shouldn't this depend upon you seeing it happen? */
1556 		makeknown(otmp->otyp);
1557 		break;
1558 	case WAN_CANCELLATION:
1559 	case SPE_CANCELLATION:
1560 		cancel_item(obj);
1561 #ifdef TEXTCOLOR
1562 		newsym(obj->ox,obj->oy);	/* might change color */
1563 #endif
1564 		break;
1565 	case SPE_DRAIN_LIFE:
1566 		(void) drain_item(obj);
1567 		break;
1568 	case WAN_TELEPORTATION:
1569 	case SPE_TELEPORT_AWAY:
1570 		rloco(obj);
1571 		break;
1572 	case WAN_MAKE_INVISIBLE:
1573 #ifdef INVISIBLE_OBJECTS
1574 		obj->oinvis = TRUE;
1575 		newsym(obj->ox,obj->oy);	/* make object disappear */
1576 #endif
1577 		break;
1578 	case WAN_UNDEAD_TURNING:
1579 	case SPE_TURN_UNDEAD:
1580 		if (obj->otyp == EGG)
1581 			revive_egg(obj);
1582 		else
1583 			res = !!revive(obj);
1584 		break;
1585 	case WAN_OPENING:
1586 	case SPE_KNOCK:
1587 	case WAN_LOCKING:
1588 	case SPE_WIZARD_LOCK:
1589 		if(Is_box(obj))
1590 			res = boxlock(obj, otmp);
1591 		else
1592 			res = 0;
1593 		if (res /* && otmp->oclass == WAND_CLASS */)
1594 			makeknown(otmp->otyp);
1595 		break;
1596 	case WAN_SLOW_MONSTER:		/* no effect on objects */
1597 	case SPE_SLOW_MONSTER:
1598 	case WAN_SPEED_MONSTER:
1599 	case WAN_NOTHING:
1600 	case SPE_HEALING:
1601 	case SPE_EXTRA_HEALING:
1602 		res = 0;
1603 		break;
1604 	case SPE_STONE_TO_FLESH:
1605 		refresh_x = obj->ox; refresh_y = obj->oy;
1606 		if (objects[obj->otyp].oc_material != MINERAL &&
1607 			objects[obj->otyp].oc_material != GEMSTONE) {
1608 		    res = 0;
1609 		    break;
1610 		}
1611 		/* add more if stone objects are added.. */
1612 		switch (objects[obj->otyp].oc_class) {
1613 		    case ROCK_CLASS:	/* boulders and statues */
1614 			if (obj->otyp == BOULDER) {
1615 			    obj = poly_obj(obj, HUGE_CHUNK_OF_MEAT);
1616 			    goto smell;
1617 			} else if (obj->otyp == STATUE) {
1618 			    xchar oox, ooy;
1619 
1620 			    (void) get_obj_location(obj, &oox, &ooy, 0);
1621 			    refresh_x = oox; refresh_y = ooy;
1622 			    if (vegetarian(&mons[obj->corpsenm])) {
1623 				/* Don't animate monsters that aren't flesh */
1624 				obj = poly_obj(obj, MEATBALL);
1625 			    	goto smell;
1626 			    }
1627 			    if (!animate_statue(obj, oox, ooy,
1628 						ANIMATE_SPELL, (int *)0)) {
1629 				struct obj *item;
1630 makecorpse:			if (mons[obj->corpsenm].geno &
1631 							(G_NOCORPSE|G_UNIQ)) {
1632 				    res = 0;
1633 				    break;
1634 				}
1635 				/* Unlikely to get here since genociding
1636 				 * monsters also sets the G_NOCORPSE flag.
1637 				 * Drop the contents, poly_obj looses them.
1638 				 */
1639 				while ((item = obj->cobj) != 0) {
1640 				    obj_extract_self(item);
1641 				    place_object(item, oox, ooy);
1642 				}
1643 				obj = poly_obj(obj, CORPSE);
1644 				break;
1645 			    }
1646 			} else { /* new rock class object... */
1647 			    /* impossible? */
1648 			    res = 0;
1649 			}
1650 			break;
1651 		    case TOOL_CLASS:	/* figurine */
1652 		    {
1653 			struct monst *mon;
1654 			xchar oox, ooy;
1655 
1656 			if (obj->otyp != FIGURINE) {
1657 			    res = 0;
1658 			    break;
1659 			}
1660 			if (vegetarian(&mons[obj->corpsenm])) {
1661 			    /* Don't animate monsters that aren't flesh */
1662 			    obj = poly_obj(obj, MEATBALL);
1663 			    goto smell;
1664 			}
1665 			(void) get_obj_location(obj, &oox, &ooy, 0);
1666 			refresh_x = oox; refresh_y = ooy;
1667 			mon = makemon(&mons[obj->corpsenm],
1668 				      oox, ooy, NO_MM_FLAGS);
1669 			if (mon) {
1670 			    delobj(obj);
1671 			    if (cansee(mon->mx, mon->my))
1672 				pline_The("figurine animates!");
1673 			    break;
1674 			}
1675 			goto makecorpse;
1676 		    }
1677 		    /* maybe add weird things to become? */
1678 		    case RING_CLASS:	/* some of the rings are stone */
1679 			obj = poly_obj(obj, MEAT_RING);
1680 			goto smell;
1681 		    case WAND_CLASS:	/* marble wand */
1682 			obj = poly_obj(obj, MEAT_STICK);
1683 			goto smell;
1684 		    case GEM_CLASS:	/* rocks & gems */
1685 			obj = poly_obj(obj, MEATBALL);
1686 smell:
1687 			if (herbivorous(youmonst.data) &&
1688 			    (!carnivorous(youmonst.data) ||
1689 			     Role_if(PM_MONK) || !u.uconduct.unvegetarian))
1690 			    Norep("You smell the odor of meat.");
1691 			else
1692 			    Norep("You smell a delicious smell.");
1693 			break;
1694 		    case WEAPON_CLASS:	/* crysknife */
1695 		    	/* fall through */
1696 		    default:
1697 			res = 0;
1698 			break;
1699 		}
1700 		newsym(refresh_x, refresh_y);
1701 		break;
1702 	default:
1703 		impossible("What an interesting effect (%d)", otmp->otyp);
1704 		break;
1705 	}
1706 	return res;
1707 }
1708 
1709 /* returns nonzero if something was hit */
1710 int
bhitpile(obj,fhito,tx,ty)1711 bhitpile(obj,fhito,tx,ty)
1712     struct obj *obj;
1713     int FDECL((*fhito), (OBJ_P,OBJ_P));
1714     int tx, ty;
1715 {
1716     int hitanything = 0;
1717     register struct obj *otmp, *next_obj;
1718 
1719     if (obj->otyp == SPE_FORCE_BOLT || obj->otyp == WAN_STRIKING) {
1720 	struct trap *t = t_at(tx, ty);
1721 
1722 	/* We can't settle for the default calling sequence of
1723 	   bhito(otmp) -> break_statue(otmp) -> activate_statue_trap(ox,oy)
1724 	   because that last call might end up operating on our `next_obj'
1725 	   (below), rather than on the current object, if it happens to
1726 	   encounter a statue which mustn't become animated. */
1727 	if (t && t->ttyp == STATUE_TRAP &&
1728 	    activate_statue_trap(t, tx, ty, TRUE) && obj->otyp == WAN_STRIKING)
1729 	    makeknown(obj->otyp);
1730     }
1731 
1732     poly_zapped = -1;
1733     for(otmp = level.objects[tx][ty]; otmp; otmp = next_obj) {
1734 	/* Fix for polymorph bug, Tim Wright */
1735 	next_obj = otmp->nexthere;
1736 	hitanything += (*fhito)(otmp, obj);
1737     }
1738     if(poly_zapped >= 0)
1739 	create_polymon(level.objects[tx][ty], poly_zapped);
1740 
1741     return hitanything;
1742 }
1743 #endif /*OVLB*/
1744 #ifdef OVL1
1745 
1746 /*
1747  * zappable - returns 1 if zap is available, 0 otherwise.
1748  *	      it removes a charge from the wand if zappable.
1749  * added by GAN 11/03/86
1750  */
1751 int
zappable(wand)1752 zappable(wand)
1753 register struct obj *wand;
1754 {
1755 	if(wand->spe < 0 || (wand->spe == 0 && rn2(121)))
1756 		return 0;
1757 	if(wand->spe == 0)
1758 		You("wrest one last charge from the worn-out wand.");
1759 	wand->spe--;
1760 	return 1;
1761 }
1762 
1763 /*
1764  * zapnodir - zaps a NODIR wand/spell.
1765  * added by GAN 11/03/86
1766  */
1767 void
zapnodir(obj)1768 zapnodir(obj)
1769 register struct obj *obj;
1770 {
1771 	boolean known = FALSE;
1772 
1773 	switch(obj->otyp) {
1774 		case WAN_LIGHT:
1775 		case SPE_LIGHT:
1776 			litroom(TRUE,obj);
1777 			if (!Blind) known = TRUE;
1778 			break;
1779 		case WAN_SECRET_DOOR_DETECTION:
1780 		case SPE_DETECT_UNSEEN:
1781 			if(!findit()) return;
1782 			if (!Blind) known = TRUE;
1783 			break;
1784 		case WAN_CREATE_MONSTER:
1785 			known = create_critters(rn2(23) ? 1 : rn1(7,2),
1786 					(struct permonst *)0);
1787 			break;
1788 		case WAN_WISHING:
1789 			known = TRUE;
1790 			if(Luck + rn2(5) < 0) {
1791 				pline("Unfortunately, nothing happens.");
1792 				break;
1793 			}
1794 			makewish();
1795 			break;
1796 		case WAN_ENLIGHTENMENT:
1797 			known = TRUE;
1798 			You_feel("self-knowledgeable...");
1799 			display_nhwindow(WIN_MESSAGE, FALSE);
1800 			enlightenment(FALSE);
1801 			pline_The("feeling subsides.");
1802 			exercise(A_WIS, TRUE);
1803 			break;
1804 	}
1805 	if (known && !objects[obj->otyp].oc_name_known) {
1806 		makeknown(obj->otyp);
1807 		more_experienced(0,10);
1808 	}
1809 }
1810 #endif /*OVL1*/
1811 #ifdef OVL0
1812 
1813 STATIC_OVL void
backfire(otmp)1814 backfire(otmp)
1815 struct obj *otmp;
1816 {
1817 	otmp->in_use = TRUE;	/* in case losehp() is fatal */
1818 	pline("%s suddenly explodes!", The(xname(otmp)));
1819 	losehp(d(otmp->spe+2,6), "exploding wand", KILLED_BY_AN);
1820 	useup(otmp);
1821 }
1822 
1823 static NEARDATA const char zap_syms[] = { WAND_CLASS, 0 };
1824 
1825 int
dozap()1826 dozap()
1827 {
1828 	register struct obj *obj;
1829 	int	damage;
1830 
1831 	if(check_capacity((char *)0)) return(0);
1832 	obj = getobj(zap_syms, "zap");
1833 	if(!obj) return(0);
1834 
1835 	check_unpaid(obj);
1836 
1837 	/* zappable addition done by GAN 11/03/86 */
1838 	if(!zappable(obj)) pline(nothing_happens);
1839 	else if(obj->cursed && !rn2(100)) {
1840 		backfire(obj);	/* the wand blows up in your face! */
1841 		exercise(A_STR, FALSE);
1842 		return(1);
1843 	} else if(!(objects[obj->otyp].oc_dir == NODIR) && !getdir((char *)0)) {
1844 		if (!Blind)
1845 		    pline("%s glows and fades.", The(xname(obj)));
1846 		/* make him pay for knowing !NODIR */
1847 	} else if(!u.dx && !u.dy && !u.dz && !(objects[obj->otyp].oc_dir == NODIR)) {
1848 	    if ((damage = zapyourself(obj, TRUE)) != 0) {
1849 		char buf[BUFSZ];
1850 		Sprintf(buf, "zapped %sself with a wand", uhim());
1851 		losehp(damage, buf, NO_KILLER_PREFIX);
1852 	    }
1853 	} else {
1854 
1855 		/*	Are we having fun yet?
1856 		 * weffects -> buzz(obj->otyp) -> zhitm (temple priest) ->
1857 		 * attack -> hitum -> known_hitum -> ghod_hitsu ->
1858 		 * buzz(AD_ELEC) -> destroy_item(WAND_CLASS) ->
1859 		 * useup -> obfree -> dealloc_obj -> free(obj)
1860 		 */
1861 		current_wand = obj;
1862 		weffects(obj);
1863 		obj = current_wand;
1864 		current_wand = 0;
1865 	}
1866 	if (obj && obj->spe < 0) {
1867 	    pline("%s to dust.", Tobjnam(obj, "turn"));
1868 	    useup(obj);
1869 	}
1870 	update_inventory();	/* maybe used a charge */
1871 	return(1);
1872 }
1873 
1874 int
zapyourself(obj,ordinary)1875 zapyourself(obj, ordinary)
1876 struct obj *obj;
1877 boolean ordinary;
1878 {
1879 	int	damage = 0;
1880 	char buf[BUFSZ];
1881 
1882 	switch(obj->otyp) {
1883 		case WAN_STRIKING:
1884 		    makeknown(WAN_STRIKING);
1885 		case SPE_FORCE_BOLT:
1886 		    if(Antimagic) {
1887 			shieldeff(u.ux, u.uy);
1888 			pline("Boing!");
1889 		    } else {
1890 			if (ordinary) {
1891 			    You("bash yourself!");
1892 			    damage = d(2,12);
1893 			} else
1894 			    damage = d(1 + obj->spe,6);
1895 			exercise(A_STR, FALSE);
1896 		    }
1897 		    break;
1898 
1899 		case WAN_LIGHTNING:
1900 		    makeknown(WAN_LIGHTNING);
1901 		    if (!Shock_resistance) {
1902 			You("shock yourself!");
1903 			damage = d(12,6);
1904 			exercise(A_CON, FALSE);
1905 		    } else {
1906 			shieldeff(u.ux, u.uy);
1907 			You("zap yourself, but seem unharmed.");
1908 			ugolemeffects(AD_ELEC, d(12,6));
1909 		    }
1910 		    destroy_item(WAND_CLASS, AD_ELEC);
1911 		    destroy_item(RING_CLASS, AD_ELEC);
1912 		    if (!resists_blnd(&youmonst)) {
1913 			    You(are_blinded_by_the_flash);
1914 			    make_blinded((long)rnd(100),FALSE);
1915 			    if (!Blind) Your(vision_clears);
1916 		    }
1917 		    break;
1918 
1919 		case SPE_FIREBALL:
1920 		    You("explode a fireball on top of yourself!");
1921 		    explode(u.ux, u.uy, 11, d(6,6), WAND_CLASS, EXPL_FIERY);
1922 		    break;
1923 		case WAN_FIRE:
1924 		    makeknown(WAN_FIRE);
1925 		case FIRE_HORN:
1926 		    if (Fire_resistance) {
1927 			shieldeff(u.ux, u.uy);
1928 			You_feel("rather warm.");
1929 			ugolemeffects(AD_FIRE, d(12,6));
1930 		    } else {
1931 			pline("You've set yourself afire!");
1932 			damage = d(12,6);
1933 		    }
1934 		    burn_away_slime();
1935 		    (void) burnarmor(&youmonst);
1936 		    destroy_item(SCROLL_CLASS, AD_FIRE);
1937 		    destroy_item(POTION_CLASS, AD_FIRE);
1938 		    destroy_item(SPBOOK_CLASS, AD_FIRE);
1939 		    break;
1940 
1941 		case WAN_COLD:
1942 		    makeknown(WAN_COLD);
1943 		case SPE_CONE_OF_COLD:
1944 		case FROST_HORN:
1945 		    if (Cold_resistance) {
1946 			shieldeff(u.ux, u.uy);
1947 			You_feel("a little chill.");
1948 			ugolemeffects(AD_COLD, d(12,6));
1949 		    } else {
1950 			You("imitate a popsicle!");
1951 			damage = d(12,6);
1952 		    }
1953 		    destroy_item(POTION_CLASS, AD_COLD);
1954 		    break;
1955 
1956 		case WAN_MAGIC_MISSILE:
1957 		    makeknown(WAN_MAGIC_MISSILE);
1958 		case SPE_MAGIC_MISSILE:
1959 		    if(Antimagic) {
1960 			shieldeff(u.ux, u.uy);
1961 			pline_The("missiles bounce!");
1962 		    } else {
1963 			damage = d(4,6);
1964 			pline("Idiot!  You've shot yourself!");
1965 		    }
1966 		    break;
1967 
1968 		case WAN_POLYMORPH:
1969 		    if (!Unchanging)
1970 		    	makeknown(WAN_POLYMORPH);
1971 		case SPE_POLYMORPH:
1972 		    if (!Unchanging)
1973 		    	polyself(FALSE);
1974 		    break;
1975 
1976 		case WAN_CANCELLATION:
1977 		case SPE_CANCELLATION:
1978 		    (void) cancel_monst(&youmonst, obj, TRUE, FALSE, TRUE);
1979 		    break;
1980 
1981 		case SPE_DRAIN_LIFE:
1982 			if (!Drain_resistance) {
1983 				losexp("life drainage");
1984 				makeknown(obj->otyp);
1985 			}
1986 			damage = 0;	/* No additional damage */
1987 			break;
1988 
1989 		case WAN_MAKE_INVISIBLE: {
1990 		    /* have to test before changing HInvis but must change
1991 		     * HInvis before doing newsym().
1992 		     */
1993 		    int msg = !Invis && !Blind && !BInvis;
1994 
1995 		    if (BInvis && uarmc->otyp == MUMMY_WRAPPING) {
1996 			/* A mummy wrapping absorbs it and protects you */
1997 		        You_feel("rather itchy under your %s.", xname(uarmc));
1998 		        break;
1999 		    }
2000 		    if (ordinary || !rn2(10)) {	/* permanent */
2001 			HInvis |= FROMOUTSIDE;
2002 		    } else {			/* temporary */
2003 		    	incr_itimeout(&HInvis, d(obj->spe, 250));
2004 		    }
2005 		    if (msg) {
2006 			makeknown(WAN_MAKE_INVISIBLE);
2007 			newsym(u.ux, u.uy);
2008 			self_invis_message();
2009 		    }
2010 		    break;
2011 		}
2012 
2013 		case WAN_SPEED_MONSTER:
2014 		    if (!(HFast & INTRINSIC)) {
2015 			if (!Fast)
2016 			    You("speed up.");
2017 			else
2018 			    Your("quickness feels more natural.");
2019 			makeknown(WAN_SPEED_MONSTER);
2020 			exercise(A_DEX, TRUE);
2021 		    }
2022 		    HFast |= FROMOUTSIDE;
2023 		    break;
2024 
2025 		case WAN_SLEEP:
2026 		    makeknown(WAN_SLEEP);
2027 		case SPE_SLEEP:
2028 		    if(Sleep_resistance) {
2029 			shieldeff(u.ux, u.uy);
2030 			You("don't feel sleepy!");
2031 		    } else {
2032 			pline_The("sleep ray hits you!");
2033 			fall_asleep(-rnd(50), TRUE);
2034 		    }
2035 		    break;
2036 
2037 		case WAN_SLOW_MONSTER:
2038 		case SPE_SLOW_MONSTER:
2039 		    if(HFast & (TIMEOUT | INTRINSIC)) {
2040 			u_slow_down();
2041 			makeknown(obj->otyp);
2042 		    }
2043 		    break;
2044 
2045 		case WAN_TELEPORTATION:
2046 		case SPE_TELEPORT_AWAY:
2047 		    tele();
2048 		    break;
2049 
2050 		case WAN_DEATH:
2051 		case SPE_FINGER_OF_DEATH:
2052 		    if (nonliving(youmonst.data) || is_demon(youmonst.data)) {
2053 			pline((obj->otyp == WAN_DEATH) ?
2054 			  "The wand shoots an apparently harmless beam at you."
2055 			  : "You seem no deader than before.");
2056 			break;
2057 		    }
2058 		    Sprintf(buf, "shot %sself with a death ray", uhim());
2059 		    killer = buf;
2060 		    killer_format = NO_KILLER_PREFIX;
2061 		    You("irradiate yourself with pure energy!");
2062 		    You("die.");
2063 		    makeknown(obj->otyp);
2064 			/* They might survive with an amulet of life saving */
2065 		    done(DIED);
2066 		    break;
2067 		case WAN_UNDEAD_TURNING:
2068 		    makeknown(WAN_UNDEAD_TURNING);
2069 		case SPE_TURN_UNDEAD:
2070 		    (void) unturn_dead(&youmonst);
2071 		    if (is_undead(youmonst.data)) {
2072 			You_feel("frightened and %sstunned.",
2073 			     Stunned ? "even more " : "");
2074 			make_stunned(HStun + rnd(30), FALSE);
2075 		    } else
2076 			You("shudder in dread.");
2077 		    break;
2078 		case SPE_HEALING:
2079 		case SPE_EXTRA_HEALING:
2080 		    healup(d(6, obj->otyp == SPE_EXTRA_HEALING ? 8 : 4),
2081 			   0, FALSE, (obj->otyp == SPE_EXTRA_HEALING));
2082 		    You_feel("%sbetter.",
2083 			obj->otyp == SPE_EXTRA_HEALING ? "much " : "");
2084 		    break;
2085 		case WAN_LIGHT:	/* (broken wand) */
2086 		 /* assert( !ordinary ); */
2087 		    damage = d(obj->spe, 25);
2088 #ifdef TOURIST
2089 		case EXPENSIVE_CAMERA:
2090 #endif
2091 		    damage += rnd(25);
2092 		    if (!resists_blnd(&youmonst)) {
2093 			You(are_blinded_by_the_flash);
2094 			make_blinded((long)damage, FALSE);
2095 			makeknown(obj->otyp);
2096 			if (!Blind) Your(vision_clears);
2097 		    }
2098 		    damage = 0;	/* reset */
2099 		    break;
2100 		case WAN_OPENING:
2101 		    if (Punished) makeknown(WAN_OPENING);
2102 		case SPE_KNOCK:
2103 		    if (Punished) Your("chain quivers for a moment.");
2104 		    break;
2105 		case WAN_DIGGING:
2106 		case SPE_DIG:
2107 		case SPE_DETECT_UNSEEN:
2108 		case WAN_NOTHING:
2109 		case WAN_LOCKING:
2110 		case SPE_WIZARD_LOCK:
2111 		    break;
2112 		case WAN_PROBING:
2113 		    for (obj = invent; obj; obj = obj->nobj)
2114 			obj->dknown = 1;
2115 		    /* note: `obj' reused; doesn't point at wand anymore */
2116 		    makeknown(WAN_PROBING);
2117 		    ustatusline();
2118 		    break;
2119 		case SPE_STONE_TO_FLESH:
2120 		    {
2121 		    struct obj *otemp, *onext;
2122 		    boolean didmerge;
2123 
2124 		    if (u.umonnum == PM_STONE_GOLEM)
2125 			(void) polymon(PM_FLESH_GOLEM);
2126 		    if (Stoned) fix_petrification();	/* saved! */
2127 		    /* but at a cost.. */
2128 		    for (otemp = invent; otemp; otemp = onext) {
2129 			onext = otemp->nobj;
2130 			(void) bhito(otemp, obj);
2131 			}
2132 		    /*
2133 		     * It is possible that we can now merge some inventory.
2134 		     * Do a higly paranoid merge.  Restart from the beginning
2135 		     * until no merges.
2136 		     */
2137 		    do {
2138 			didmerge = FALSE;
2139 			for (otemp = invent; !didmerge && otemp; otemp = otemp->nobj)
2140 			    for (onext = otemp->nobj; onext; onext = onext->nobj)
2141 			    	if (merged(&otemp, &onext)) {
2142 			    		didmerge = TRUE;
2143 			    		break;
2144 			    		}
2145 		    } while (didmerge);
2146 		    }
2147 		    break;
2148 		default: impossible("object %d used?",obj->otyp);
2149 		    break;
2150 	}
2151 	return(damage);
2152 }
2153 
2154 #ifdef STEED
2155 /* you've zapped a wand downwards while riding
2156  * Return TRUE if the steed was hit by the wand.
2157  * Return FALSE if the steed was not hit by the wand.
2158  */
2159 STATIC_OVL boolean
zap_steed(obj)2160 zap_steed(obj)
2161 struct obj *obj;	/* wand or spell */
2162 {
2163 	int steedhit = FALSE;
2164 
2165 	switch (obj->otyp) {
2166 
2167 	   /*
2168 	    * Wands that are allowed to hit the steed
2169 	    * Carefully test the results of any that are
2170 	    * moved here from the bottom section.
2171 	    */
2172 		case WAN_PROBING:
2173 		    probe_monster(u.usteed);
2174 		    makeknown(WAN_PROBING);
2175 		    steedhit = TRUE;
2176 		    break;
2177 		case WAN_TELEPORTATION:
2178 		case SPE_TELEPORT_AWAY:
2179 		    /* you go together */
2180 		    tele();
2181 		    if(Teleport_control || !couldsee(u.ux0, u.uy0) ||
2182 			(distu(u.ux0, u.uy0) >= 16))
2183 				makeknown(obj->otyp);
2184 		    steedhit = TRUE;
2185 		    break;
2186 
2187 		/* Default processing via bhitm() for these */
2188 		case SPE_CURE_SICKNESS:
2189 		case WAN_MAKE_INVISIBLE:
2190 		case WAN_CANCELLATION:
2191 		case SPE_CANCELLATION:
2192 		case WAN_POLYMORPH:
2193 		case SPE_POLYMORPH:
2194 		case WAN_STRIKING:
2195 		case SPE_FORCE_BOLT:
2196 		case WAN_SLOW_MONSTER:
2197 		case SPE_SLOW_MONSTER:
2198 		case WAN_SPEED_MONSTER:
2199 		case SPE_HEALING:
2200 		case SPE_EXTRA_HEALING:
2201 		case SPE_DRAIN_LIFE:
2202 		case WAN_OPENING:
2203 		case SPE_KNOCK:
2204 		    (void) bhitm(u.usteed, obj);
2205 		    steedhit = TRUE;
2206 		    break;
2207 
2208 		default:
2209 		    steedhit = FALSE;
2210 		    break;
2211 	}
2212 	return steedhit;
2213 }
2214 #endif
2215 
2216 #endif /*OVL0*/
2217 #ifdef OVL3
2218 
2219 /*
2220  * cancel a monster (possibly the hero).  inventory is cancelled only
2221  * if the monster is zapping itself directly, since otherwise the
2222  * effect is too strong.  currently non-hero monsters do not zap
2223  * themselves with cancellation.
2224  */
2225 boolean
cancel_monst(mdef,obj,youattack,allow_cancel_kill,self_cancel)2226 cancel_monst(mdef, obj, youattack, allow_cancel_kill, self_cancel)
2227 register struct monst	*mdef;
2228 register struct obj	*obj;
2229 boolean			youattack, allow_cancel_kill, self_cancel;
2230 {
2231 	boolean	youdefend = (mdef == &youmonst);
2232 	static const char writing_vanishes[] =
2233 				"Some writing vanishes from %s head!";
2234 	static const char your[] = "your";	/* should be extern */
2235 
2236 	if (youdefend ? (!youattack && Antimagic)
2237 		      : resist(mdef, obj->oclass, 0, NOTELL))
2238 		return FALSE;	/* resisted cancellation */
2239 
2240 	if (self_cancel) {	/* 1st cancel inventory */
2241 	    struct obj *otmp;
2242 
2243 	    for (otmp = (youdefend ? invent : mdef->minvent);
2244 			    otmp; otmp = otmp->nobj)
2245 		cancel_item(otmp);
2246 	    if (youdefend) {
2247 		flags.botl = 1;	/* potential AC change */
2248 		find_ac();
2249 	    }
2250 	}
2251 
2252 	/* now handle special cases */
2253 	if (youdefend) {
2254 	    if (Upolyd) {
2255 		if ((u.umonnum == PM_CLAY_GOLEM) && !Blind)
2256 		    pline(writing_vanishes, your);
2257 
2258 		if (Unchanging)
2259 		    Your("amulet grows hot for a moment, then cools.");
2260 		else
2261 		    rehumanize();
2262 	    }
2263 	} else {
2264 	    mdef->mcan = TRUE;
2265 
2266 	    if (is_were(mdef->data) && mdef->data->mlet != S_HUMAN)
2267 		were_change(mdef);
2268 
2269 	    if (mdef->data == &mons[PM_CLAY_GOLEM]) {
2270 		if (canseemon(mdef))
2271 		    pline(writing_vanishes, s_suffix(mon_nam(mdef)));
2272 
2273 		if (allow_cancel_kill) {
2274 		    if (youattack)
2275 			killed(mdef);
2276 		    else
2277 			monkilled(mdef, "", AD_SPEL);
2278 		}
2279 	    }
2280 	}
2281 	return TRUE;
2282 }
2283 
2284 /* you've zapped an immediate type wand up or down */
2285 STATIC_OVL boolean
zap_updown(obj)2286 zap_updown(obj)
2287 struct obj *obj;	/* wand or spell */
2288 {
2289 	boolean striking = FALSE, disclose = FALSE;
2290 	int x, y, xx, yy, ptmp;
2291 	struct obj *otmp;
2292 	struct engr *e;
2293 	struct trap *ttmp;
2294 	char buf[BUFSZ];
2295 
2296 	/* some wands have special effects other than normal bhitpile */
2297 	/* drawbridge might change <u.ux,u.uy> */
2298 	x = xx = u.ux;	/* <x,y> is zap location */
2299 	y = yy = u.uy;	/* <xx,yy> is drawbridge (portcullis) position */
2300 	ttmp = t_at(x, y); /* trap if there is one */
2301 
2302 	switch (obj->otyp) {
2303 	case WAN_PROBING:
2304 	    ptmp = 0;
2305 	    if (u.dz < 0) {
2306 		You("probe towards the %s.", ceiling(x,y));
2307 	    } else {
2308 		ptmp += bhitpile(obj, bhito, x, y);
2309 		You("probe beneath the %s.", surface(x,y));
2310 		ptmp += display_binventory(x, y, TRUE);
2311 	    }
2312 	    if (!ptmp) Your("probe reveals nothing.");
2313 	    return TRUE;	/* we've done our own bhitpile */
2314 	case WAN_OPENING:
2315 	case SPE_KNOCK:
2316 	    /* up or down, but at closed portcullis only */
2317 	    if (is_db_wall(x,y) && find_drawbridge(&xx, &yy)) {
2318 		open_drawbridge(xx, yy);
2319 		disclose = TRUE;
2320 	    } else if (u.dz > 0 && (x == xdnstair && y == ydnstair) &&
2321 			/* can't use the stairs down to quest level 2 until
2322 			   leader "unlocks" them; give feedback if you try */
2323 			on_level(&u.uz, &qstart_level) && !ok_to_quest()) {
2324 		pline_The("stairs seem to ripple momentarily.");
2325 		disclose = TRUE;
2326 	    }
2327 	    break;
2328 	case WAN_STRIKING:
2329 	case SPE_FORCE_BOLT:
2330 	    striking = TRUE;
2331 	    /*FALLTHRU*/
2332 	case WAN_LOCKING:
2333 	case SPE_WIZARD_LOCK:
2334 	    /* down at open bridge or up or down at open portcullis */
2335 	    if ((levl[x][y].typ == DRAWBRIDGE_DOWN) ? (u.dz > 0) :
2336 			(is_drawbridge_wall(x,y) && !is_db_wall(x,y)) &&
2337 		    find_drawbridge(&xx, &yy)) {
2338 		if (!striking)
2339 		    close_drawbridge(xx, yy);
2340 		else
2341 		    destroy_drawbridge(xx, yy);
2342 		disclose = TRUE;
2343 	    } else if (striking && u.dz < 0 && rn2(3) &&
2344 			!Is_airlevel(&u.uz) && !Is_waterlevel(&u.uz) &&
2345 			!Underwater && !Is_qstart(&u.uz)) {
2346 		/* similar to zap_dig() */
2347 		pline("A rock is dislodged from the %s and falls on your %s.",
2348 		      ceiling(x, y), body_part(HEAD));
2349 		losehp(rnd((uarmh && is_metallic(uarmh)) ? 2 : 6),
2350 		       "falling rock", KILLED_BY_AN);
2351 		if ((otmp = mksobj_at(ROCK, x, y, FALSE, FALSE)) != 0) {
2352 		    (void)xname(otmp);	/* set dknown, maybe bknown */
2353 		    stackobj(otmp);
2354 		}
2355 		newsym(x, y);
2356 	    } else if (!striking && ttmp && ttmp->ttyp == TRAPDOOR && u.dz > 0) {
2357 		if (!Blind) {
2358 			if (ttmp->tseen) {
2359 				pline("A trap door beneath you closes up then vanishes.");
2360 				disclose = TRUE;
2361 			} else {
2362 				You("see a swirl of %s beneath you.",
2363 					is_ice(x,y) ? "frost" : "dust");
2364 			}
2365 		} else {
2366 			You_hear("a twang followed by a thud.");
2367 		}
2368 		deltrap(ttmp);
2369 		ttmp = (struct trap *)0;
2370 		newsym(x, y);
2371 	    }
2372 	    break;
2373 	case SPE_STONE_TO_FLESH:
2374 	    if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ||
2375 		     Underwater || (Is_qstart(&u.uz) && u.dz < 0)) {
2376 		pline(nothing_happens);
2377 	    } else if (u.dz < 0) {	/* we should do more... */
2378 		pline("Blood drips on your %s.", body_part(FACE));
2379 	    } else if (u.dz > 0 && !OBJ_AT(u.ux, u.uy)) {
2380 		/*
2381 		Print this message only if there wasn't an engraving
2382 		affected here.  If water or ice, act like waterlevel case.
2383 		*/
2384 		e = engr_at(u.ux, u.uy);
2385 		if (!(e && e->engr_type == ENGRAVE)) {
2386 		    if (is_pool(u.ux, u.uy) || is_ice(u.ux, u.uy))
2387 			pline(nothing_happens);
2388 		    else
2389 			pline("Blood %ss %s your %s.",
2390 			      is_lava(u.ux, u.uy) ? "boil" : "pool",
2391 			      Levitation ? "beneath" : "at",
2392 			      makeplural(body_part(FOOT)));
2393 		}
2394 	    }
2395 	    break;
2396 	default:
2397 	    break;
2398 	}
2399 
2400 	if (u.dz > 0) {
2401 	    /* zapping downward */
2402 	    (void) bhitpile(obj, bhito, x, y);
2403 
2404 	    /* subset of engraving effects; none sets `disclose' */
2405 	    if ((e = engr_at(x, y)) != 0 && e->engr_type != HEADSTONE) {
2406 		switch (obj->otyp) {
2407 		case WAN_POLYMORPH:
2408 		case SPE_POLYMORPH:
2409 		    del_engr(e);
2410 		    make_engr_at(x, y, random_engraving(buf), moves, (xchar)0);
2411 		    break;
2412 		case WAN_CANCELLATION:
2413 		case SPE_CANCELLATION:
2414 		case WAN_MAKE_INVISIBLE:
2415 		    del_engr(e);
2416 		    break;
2417 		case WAN_TELEPORTATION:
2418 		case SPE_TELEPORT_AWAY:
2419 		    rloc_engr(e);
2420 		    break;
2421 		case SPE_STONE_TO_FLESH:
2422 		    if (e->engr_type == ENGRAVE) {
2423 			/* only affects things in stone */
2424 			pline_The(Hallucination ?
2425 			    "floor runs like butter!" :
2426 			    "edges on the floor get smoother.");
2427 			wipe_engr_at(x, y, d(2,4));
2428 			}
2429 		    break;
2430 		case WAN_STRIKING:
2431 		case SPE_FORCE_BOLT:
2432 		    wipe_engr_at(x, y, d(2,4));
2433 		    break;
2434 		default:
2435 		    break;
2436 		}
2437 	    }
2438 	}
2439 
2440 	return disclose;
2441 }
2442 
2443 #endif /*OVL3*/
2444 #ifdef OVLB
2445 
2446 /* called for various wand and spell effects - M. Stephenson */
2447 void
weffects(obj)2448 weffects(obj)
2449 register struct	obj	*obj;
2450 {
2451 	int otyp = obj->otyp;
2452 	boolean disclose = FALSE, was_unkn = !objects[otyp].oc_name_known;
2453 
2454 	exercise(A_WIS, TRUE);
2455 #ifdef STEED
2456 	if (u.usteed && (objects[otyp].oc_dir != NODIR) &&
2457 	    !u.dx && !u.dy && (u.dz > 0) && zap_steed(obj)) {
2458 		disclose = TRUE;
2459 	} else
2460 #endif
2461 	if (objects[otyp].oc_dir == IMMEDIATE) {
2462 	    obj_zapped = FALSE;
2463 
2464 	    if (u.uswallow) {
2465 		(void) bhitm(u.ustuck, obj);
2466 		/* [how about `bhitpile(u.ustuck->minvent)' effect?] */
2467 	    } else if (u.dz) {
2468 		disclose = zap_updown(obj);
2469 	    } else {
2470 		(void) bhit(u.dx,u.dy, rn1(8,6),ZAPPED_WAND, bhitm,bhito, obj);
2471 	    }
2472 	    /* give a clue if obj_zapped */
2473 	    if (obj_zapped)
2474 		You_feel("shuddering vibrations.");
2475 
2476 	} else if (objects[otyp].oc_dir == NODIR) {
2477 	    zapnodir(obj);
2478 
2479 	} else {
2480 	    /* neither immediate nor directionless */
2481 
2482 	    if (otyp == WAN_DIGGING || otyp == SPE_DIG)
2483 		zap_dig();
2484 	    else if (otyp >= SPE_MAGIC_MISSILE && otyp <= SPE_FINGER_OF_DEATH)
2485 		buzz(otyp - SPE_MAGIC_MISSILE + 10,
2486 		     u.ulevel / 2 + 1,
2487 		     u.ux, u.uy, u.dx, u.dy);
2488 	    else if (otyp >= WAN_MAGIC_MISSILE && otyp <= WAN_LIGHTNING)
2489 		buzz(otyp - WAN_MAGIC_MISSILE,
2490 		     (otyp == WAN_MAGIC_MISSILE) ? 2 : 6,
2491 		     u.ux, u.uy, u.dx, u.dy);
2492 	    else
2493 		impossible("weffects: unexpected spell or wand");
2494 	    disclose = TRUE;
2495 	}
2496 	if (disclose && was_unkn) {
2497 	    makeknown(otyp);
2498 	    more_experienced(0,10);
2499 	}
2500 	return;
2501 }
2502 #endif /*OVLB*/
2503 #ifdef OVL0
2504 
2505 /*
2506  * Generate the to damage bonus for a spell. Based on the hero's intelligence
2507  */
2508 int
spell_damage_bonus()2509 spell_damage_bonus()
2510 {
2511     int tmp, intell = ACURR(A_INT);
2512 
2513     /* Punish low intellegence before low level else low intellegence
2514        gets punished only when high level */
2515     if (intell < 10)
2516 	tmp = -3;
2517     else if (u.ulevel < 5)
2518 	tmp = 0;
2519     else if (intell < 14)
2520 	tmp = 0;
2521     else if (intell <= 18)
2522 	tmp = 1;
2523     else		/* helm of brilliance */
2524 	tmp = 2;
2525 
2526     return tmp;
2527 }
2528 
2529 /*
2530  * Generate the to hit bonus for a spell.  Based on the hero's skill in
2531  * spell class and dexterity.
2532  */
2533 STATIC_OVL int
spell_hit_bonus(skill)2534 spell_hit_bonus(skill)
2535 int skill;
2536 {
2537     int hit_bon = 0;
2538     int dex = ACURR(A_DEX);
2539 
2540     switch (P_SKILL(spell_skilltype(skill))) {
2541 	case P_ISRESTRICTED:
2542 	case P_UNSKILLED:   hit_bon = -4; break;
2543 	case P_BASIC:       hit_bon =  0; break;
2544 	case P_SKILLED:     hit_bon =  2; break;
2545 	case P_EXPERT:      hit_bon =  3; break;
2546     }
2547 
2548     if (dex < 4)
2549 	hit_bon -= 3;
2550     else if (dex < 6)
2551 	hit_bon -= 2;
2552     else if (dex < 8)
2553 	hit_bon -= 1;
2554     else if (dex < 14)
2555 	hit_bon -= 0;		/* Will change when print stuff below removed */
2556     else
2557 	hit_bon += dex - 14; /* Even increment for dextrous heroes (see weapon.c abon) */
2558 
2559     return hit_bon;
2560 }
2561 
2562 const char *
exclam(force)2563 exclam(force)
2564 register int force;
2565 {
2566 	/* force == 0 occurs e.g. with sleep ray */
2567 	/* note that large force is usual with wands so that !! would
2568 		require information about hand/weapon/wand */
2569 	return (const char *)((force < 0) ? "?" : (force <= 4) ? "." : "!");
2570 }
2571 
2572 void
hit(str,mtmp,force)2573 hit(str,mtmp,force)
2574 register const char *str;
2575 register struct monst *mtmp;
2576 register const char *force;		/* usually either "." or "!" */
2577 {
2578 	if((!cansee(bhitpos.x,bhitpos.y) && !canspotmon(mtmp) &&
2579 	     !(u.uswallow && mtmp == u.ustuck))
2580 	   || !flags.verbose)
2581 	    pline("%s %s it.", The(str), vtense(str, "hit"));
2582 	else pline("%s %s %s%s", The(str), vtense(str, "hit"),
2583 		   mon_nam(mtmp), force);
2584 }
2585 
2586 void
miss(str,mtmp)2587 miss(str,mtmp)
2588 register const char *str;
2589 register struct monst *mtmp;
2590 {
2591 	pline("%s %s %s.", The(str), vtense(str, "miss"),
2592 	      ((cansee(bhitpos.x,bhitpos.y) || canspotmon(mtmp))
2593 	       && flags.verbose) ?
2594 	      mon_nam(mtmp) : "it");
2595 }
2596 #endif /*OVL0*/
2597 #ifdef OVL1
2598 
2599 /*
2600  *  Called for the following distance effects:
2601  *	when a weapon is thrown (weapon == THROWN_WEAPON)
2602  *	when an object is kicked (KICKED_WEAPON)
2603  *	when an IMMEDIATE wand is zapped (ZAPPED_WAND)
2604  *	when a light beam is flashed (FLASHED_LIGHT)
2605  *	when a mirror is applied (INVIS_BEAM)
2606  *  A thrown/kicked object falls down at the end of its range or when a monster
2607  *  is hit.  The variable 'bhitpos' is set to the final position of the weapon
2608  *  thrown/zapped.  The ray of a wand may affect (by calling a provided
2609  *  function) several objects and monsters on its path.  The return value
2610  *  is the monster hit (weapon != ZAPPED_WAND), or a null monster pointer.
2611  *
2612  *  Check !u.uswallow before calling bhit().
2613  *  This function reveals the absence of a remembered invisible monster in
2614  *  necessary cases (throwing or kicking weapons).  The presence of a real
2615  *  one is revealed for a weapon, but if not a weapon is left up to fhitm().
2616  */
2617 struct monst *
bhit(ddx,ddy,range,weapon,fhitm,fhito,obj)2618 bhit(ddx,ddy,range,weapon,fhitm,fhito,obj)
2619 register int ddx,ddy,range;		/* direction and range */
2620 int weapon;				/* see values in hack.h */
2621 int FDECL((*fhitm), (MONST_P, OBJ_P)),	/* fns called when mon/obj hit */
2622     FDECL((*fhito), (OBJ_P, OBJ_P));
2623 struct obj *obj;			/* object tossed/used */
2624 {
2625 	struct monst *mtmp;
2626 	uchar typ;
2627 	boolean shopdoor = FALSE, point_blank = TRUE;
2628 
2629 	if (weapon == KICKED_WEAPON) {
2630 	    /* object starts one square in front of player */
2631 	    bhitpos.x = u.ux + ddx;
2632 	    bhitpos.y = u.uy + ddy;
2633 	    range--;
2634 	} else {
2635 	    bhitpos.x = u.ux;
2636 	    bhitpos.y = u.uy;
2637 	}
2638 
2639 	if (weapon == FLASHED_LIGHT) {
2640 	    tmp_at(DISP_BEAM, cmap_to_glyph(S_flashbeam));
2641 	} else if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM)
2642 	    tmp_at(DISP_FLASH, obj_to_glyph(obj));
2643 
2644 	while(range-- > 0) {
2645 	    int x,y;
2646 
2647 	    bhitpos.x += ddx;
2648 	    bhitpos.y += ddy;
2649 	    x = bhitpos.x; y = bhitpos.y;
2650 
2651 	    if(!isok(x, y)) {
2652 		bhitpos.x -= ddx;
2653 		bhitpos.y -= ddy;
2654 		break;
2655 	    }
2656 
2657 	    if(is_pick(obj) && inside_shop(x, y) &&
2658 					   (mtmp = shkcatch(obj, x, y))) {
2659 		tmp_at(DISP_END, 0);
2660 		return(mtmp);
2661 	    }
2662 
2663 	    typ = levl[bhitpos.x][bhitpos.y].typ;
2664 
2665 	    /* iron bars will block anything big enough */
2666 	    if ((weapon == THROWN_WEAPON || weapon == KICKED_WEAPON) &&
2667 		    typ == IRONBARS &&
2668 		    hits_bars(&obj, x - ddx, y - ddy,
2669 			      point_blank ? 0 : !rn2(5), 1)) {
2670 		/* caveat: obj might now be null... */
2671 		bhitpos.x -= ddx;
2672 		bhitpos.y -= ddy;
2673 		break;
2674 	    }
2675 
2676 	    if (weapon == ZAPPED_WAND && find_drawbridge(&x,&y))
2677 		switch (obj->otyp) {
2678 		    case WAN_OPENING:
2679 		    case SPE_KNOCK:
2680 			if (is_db_wall(bhitpos.x, bhitpos.y)) {
2681 			    if (cansee(x,y) || cansee(bhitpos.x,bhitpos.y))
2682 				makeknown(obj->otyp);
2683 			    open_drawbridge(x,y);
2684 			}
2685 			break;
2686 		    case WAN_LOCKING:
2687 		    case SPE_WIZARD_LOCK:
2688 			if ((cansee(x,y) || cansee(bhitpos.x, bhitpos.y))
2689 			    && levl[x][y].typ == DRAWBRIDGE_DOWN)
2690 			    makeknown(obj->otyp);
2691 			close_drawbridge(x,y);
2692 			break;
2693 		    case WAN_STRIKING:
2694 		    case SPE_FORCE_BOLT:
2695 			if (typ != DRAWBRIDGE_UP)
2696 			    destroy_drawbridge(x,y);
2697 			makeknown(obj->otyp);
2698 			break;
2699 		}
2700 
2701 	    if ((mtmp = m_at(bhitpos.x, bhitpos.y)) != 0) {
2702 		notonhead = (bhitpos.x != mtmp->mx ||
2703 			     bhitpos.y != mtmp->my);
2704 		if (weapon != FLASHED_LIGHT) {
2705 			if(weapon != ZAPPED_WAND) {
2706 			    if(weapon != INVIS_BEAM) tmp_at(DISP_END, 0);
2707 			    if (cansee(bhitpos.x,bhitpos.y) && !canspotmon(mtmp)) {
2708 				if (weapon != INVIS_BEAM) {
2709 				    map_invisible(bhitpos.x, bhitpos.y);
2710 				    return(mtmp);
2711 				}
2712 			    } else
2713 				return(mtmp);
2714 			}
2715 			if (weapon != INVIS_BEAM) {
2716 			    (*fhitm)(mtmp, obj);
2717 			    range -= 3;
2718 			}
2719 		} else {
2720 		    /* FLASHED_LIGHT hitting invisible monster
2721 		       should pass through instead of stop so
2722 		       we call flash_hits_mon() directly rather
2723 		       than returning mtmp back to caller. That
2724 		       allows the flash to keep on going. Note
2725 		       that we use mtmp->minvis not canspotmon()
2726 		       because it makes no difference whether
2727 		       the hero can see the monster or not.*/
2728 		    if (mtmp->minvis) {
2729 			obj->ox = u.ux,  obj->oy = u.uy;
2730 			(void) flash_hits_mon(mtmp, obj);
2731 		    } else {
2732 			tmp_at(DISP_END, 0);
2733 		    	return(mtmp); 	/* caller will call flash_hits_mon */
2734 		    }
2735 		}
2736 	    } else {
2737 		if (weapon == ZAPPED_WAND && obj->otyp == WAN_PROBING &&
2738 		   glyph_is_invisible(levl[bhitpos.x][bhitpos.y].glyph)) {
2739 		    unmap_object(bhitpos.x, bhitpos.y);
2740 		    newsym(x, y);
2741 		}
2742 	    }
2743 	    if(fhito) {
2744 		if(bhitpile(obj,fhito,bhitpos.x,bhitpos.y))
2745 		    range--;
2746 	    } else {
2747 		if(weapon == KICKED_WEAPON &&
2748 		      ((obj->oclass == COIN_CLASS &&
2749 			 OBJ_AT(bhitpos.x, bhitpos.y)) ||
2750 			    ship_object(obj, bhitpos.x, bhitpos.y,
2751 					costly_spot(bhitpos.x, bhitpos.y)))) {
2752 			tmp_at(DISP_END, 0);
2753 			return (struct monst *)0;
2754 		}
2755 	    }
2756 	    if(weapon == ZAPPED_WAND && (IS_DOOR(typ) || typ == SDOOR)) {
2757 		switch (obj->otyp) {
2758 		case WAN_OPENING:
2759 		case WAN_LOCKING:
2760 		case WAN_STRIKING:
2761 		case SPE_KNOCK:
2762 		case SPE_WIZARD_LOCK:
2763 		case SPE_FORCE_BOLT:
2764 		    if (doorlock(obj, bhitpos.x, bhitpos.y)) {
2765 			if (cansee(bhitpos.x, bhitpos.y) ||
2766 			    (obj->otyp == WAN_STRIKING))
2767 			    makeknown(obj->otyp);
2768 			if (levl[bhitpos.x][bhitpos.y].doormask == D_BROKEN
2769 			    && *in_rooms(bhitpos.x, bhitpos.y, SHOPBASE)) {
2770 			    shopdoor = TRUE;
2771 			    add_damage(bhitpos.x, bhitpos.y, 400L);
2772 			}
2773 		    }
2774 		    break;
2775 		}
2776 	    }
2777 	    if(!ZAP_POS(typ) || closed_door(bhitpos.x, bhitpos.y)) {
2778 		bhitpos.x -= ddx;
2779 		bhitpos.y -= ddy;
2780 		break;
2781 	    }
2782 	    if(weapon != ZAPPED_WAND && weapon != INVIS_BEAM) {
2783 		/* 'I' present but no monster: erase */
2784 		/* do this before the tmp_at() */
2785 		if (glyph_is_invisible(levl[bhitpos.x][bhitpos.y].glyph)
2786 			&& cansee(x, y)) {
2787 		    unmap_object(bhitpos.x, bhitpos.y);
2788 		    newsym(x, y);
2789 		}
2790 		tmp_at(bhitpos.x, bhitpos.y);
2791 		delay_output();
2792 		/* kicked objects fall in pools */
2793 		if((weapon == KICKED_WEAPON) &&
2794 		   (is_pool(bhitpos.x, bhitpos.y) ||
2795 		   is_lava(bhitpos.x, bhitpos.y)))
2796 		    break;
2797 #ifdef SINKS
2798 		if(IS_SINK(typ) && weapon != FLASHED_LIGHT)
2799 		    break;	/* physical objects fall onto sink */
2800 #endif
2801 	    }
2802 	    /* limit range of ball so hero won't make an invalid move */
2803 	    if (weapon == THROWN_WEAPON && range > 0 &&
2804 		obj->otyp == HEAVY_IRON_BALL) {
2805 		struct obj *bobj;
2806 		struct trap *t;
2807 		if ((bobj = sobj_at(BOULDER, x, y)) != 0) {
2808 		    if (cansee(x,y))
2809 			pline("%s hits %s.",
2810 			      The(distant_name(obj, xname)), an(xname(bobj)));
2811 		    range = 0;
2812 		} else if (obj == uball) {
2813 		    if (!test_move(x - ddx, y - ddy, ddx, ddy, TEST_MOVE)) {
2814 			/* nb: it didn't hit anything directly */
2815 			if (cansee(x,y))
2816 			    pline("%s jerks to an abrupt halt.",
2817 				  The(distant_name(obj, xname))); /* lame */
2818 			range = 0;
2819 		    } else if (In_sokoban(&u.uz) && (t = t_at(x, y)) != 0 &&
2820 			       (t->ttyp == PIT || t->ttyp == SPIKED_PIT ||
2821 				t->ttyp == HOLE || t->ttyp == TRAPDOOR)) {
2822 			/* hero falls into the trap, so ball stops */
2823 			range = 0;
2824 		    }
2825 		}
2826 	    }
2827 
2828 	    /* thrown/kicked missile has moved away from its starting spot */
2829 	    point_blank = FALSE;	/* affects passing through iron bars */
2830 	}
2831 
2832 	if (weapon != ZAPPED_WAND && weapon != INVIS_BEAM) tmp_at(DISP_END, 0);
2833 
2834 	if(shopdoor)
2835 	    pay_for_damage("destroy", FALSE);
2836 
2837 	return (struct monst *)0;
2838 }
2839 
2840 struct monst *
boomhit(dx,dy)2841 boomhit(dx, dy)
2842 int dx, dy;
2843 {
2844 	register int i, ct;
2845 	int boom = S_boomleft;	/* showsym[] index  */
2846 	struct monst *mtmp;
2847 
2848 	bhitpos.x = u.ux;
2849 	bhitpos.y = u.uy;
2850 
2851 	for (i = 0; i < 8; i++) if (xdir[i] == dx && ydir[i] == dy) break;
2852 	tmp_at(DISP_FLASH, cmap_to_glyph(boom));
2853 	for (ct = 0; ct < 10; ct++) {
2854 		if(i == 8) i = 0;
2855 		boom = (boom == S_boomleft) ? S_boomright : S_boomleft;
2856 		tmp_at(DISP_CHANGE, cmap_to_glyph(boom));/* change glyph */
2857 		dx = xdir[i];
2858 		dy = ydir[i];
2859 		bhitpos.x += dx;
2860 		bhitpos.y += dy;
2861 		if(MON_AT(bhitpos.x, bhitpos.y)) {
2862 			mtmp = m_at(bhitpos.x,bhitpos.y);
2863 			m_respond(mtmp);
2864 			tmp_at(DISP_END, 0);
2865 			return(mtmp);
2866 		}
2867 		if(!ZAP_POS(levl[bhitpos.x][bhitpos.y].typ) ||
2868 		   closed_door(bhitpos.x, bhitpos.y)) {
2869 			bhitpos.x -= dx;
2870 			bhitpos.y -= dy;
2871 			break;
2872 		}
2873 		if(bhitpos.x == u.ux && bhitpos.y == u.uy) { /* ct == 9 */
2874 			if(Fumbling || rn2(20) >= ACURR(A_DEX)) {
2875 				/* we hit ourselves */
2876 				(void) thitu(10, rnd(10), (struct obj *)0,
2877 					"boomerang");
2878 				break;
2879 			} else {	/* we catch it */
2880 				tmp_at(DISP_END, 0);
2881 				You("skillfully catch the boomerang.");
2882 				return(&youmonst);
2883 			}
2884 		}
2885 		tmp_at(bhitpos.x, bhitpos.y);
2886 		delay_output();
2887 		if(ct % 5 != 0) i++;
2888 #ifdef SINKS
2889 		if(IS_SINK(levl[bhitpos.x][bhitpos.y].typ))
2890 			break;	/* boomerang falls on sink */
2891 #endif
2892 	}
2893 	tmp_at(DISP_END, 0);	/* do not leave last symbol */
2894 	return (struct monst *)0;
2895 }
2896 
2897 STATIC_OVL int
zhitm(mon,type,nd,ootmp)2898 zhitm(mon, type, nd, ootmp)			/* returns damage to mon */
2899 register struct monst *mon;
2900 register int type, nd;
2901 struct obj **ootmp;	/* to return worn armor for caller to disintegrate */
2902 {
2903 	register int tmp = 0;
2904 	register int abstype = abs(type) % 10;
2905 	boolean sho_shieldeff = FALSE;
2906 	boolean spellcaster = is_hero_spell(type); /* maybe get a bonus! */
2907 
2908 	*ootmp = (struct obj *)0;
2909 	switch(abstype) {
2910 	case ZT_MAGIC_MISSILE:
2911 		if (resists_magm(mon)) {
2912 		    sho_shieldeff = TRUE;
2913 		    break;
2914 		}
2915 		tmp = d(nd,6);
2916 		if (spellcaster)
2917 		    tmp += spell_damage_bonus();
2918 #ifdef WIZ_PATCH_DEBUG
2919 		if (spellcaster)
2920 		    pline("Damage = %d + %d", tmp-spell_damage_bonus(),
2921 			spell_damage_bonus());
2922 #endif
2923 		break;
2924 	case ZT_FIRE:
2925 		if (resists_fire(mon)) {
2926 		    sho_shieldeff = TRUE;
2927 		    break;
2928 		}
2929 		tmp = d(nd,6);
2930 		if (resists_cold(mon)) tmp += 7;
2931 		if (spellcaster)
2932 		    tmp += spell_damage_bonus();
2933 #ifdef WIZ_PATCH_DEBUG
2934 		if (spellcaster)
2935 		    pline("Damage = %d + %d",tmp-spell_damage_bonus(),
2936 			spell_damage_bonus());
2937 #endif
2938 		if (burnarmor(mon)) {
2939 		    if (!rn2(3)) (void)destroy_mitem(mon, POTION_CLASS, AD_FIRE);
2940 		    if (!rn2(3)) (void)destroy_mitem(mon, SCROLL_CLASS, AD_FIRE);
2941 		    if (!rn2(5)) (void)destroy_mitem(mon, SPBOOK_CLASS, AD_FIRE);
2942 		}
2943 		break;
2944 	case ZT_COLD:
2945 		if (resists_cold(mon)) {
2946 		    sho_shieldeff = TRUE;
2947 		    break;
2948 		}
2949 		tmp = d(nd,6);
2950 		if (resists_fire(mon)) tmp += d(nd, 3);
2951 		if (spellcaster)
2952 		    tmp += spell_damage_bonus();
2953 #ifdef WIZ_PATCH_DEBUG
2954 		if (spellcaster)
2955 		    pline("Damage = %d + %d", tmp-spell_damage_bonus(),
2956 			spell_damage_bonus());
2957 #endif
2958 		if (!rn2(3)) (void)destroy_mitem(mon, POTION_CLASS, AD_COLD);
2959 		break;
2960 	case ZT_SLEEP:
2961 		tmp = 0;
2962 		(void)sleep_monst(mon, d(nd, 25),
2963 				type == ZT_WAND(ZT_SLEEP) ? WAND_CLASS : '\0');
2964 		break;
2965 	case ZT_DEATH:		/* death/disintegration */
2966 		if(abs(type) != ZT_BREATH(ZT_DEATH)) {	/* death */
2967 		    if(mon->data == &mons[PM_DEATH]) {
2968 			mon->mhpmax += mon->mhpmax/2;
2969 			if (mon->mhpmax >= MAGIC_COOKIE)
2970 			    mon->mhpmax = MAGIC_COOKIE - 1;
2971 			mon->mhp = mon->mhpmax;
2972 			tmp = 0;
2973 			break;
2974 		    }
2975 		    if (nonliving(mon->data) || is_demon(mon->data) ||
2976 			    resists_magm(mon)) {	/* similar to player */
2977 			sho_shieldeff = TRUE;
2978 			break;
2979 		    }
2980 		    type = -1; /* so they don't get saving throws */
2981 		} else {
2982 		    struct obj *otmp2;
2983 
2984 		    if (resists_disint(mon)) {
2985 			sho_shieldeff = TRUE;
2986 		    } else if (mon->misc_worn_check & W_ARMS) {
2987 			/* destroy shield; victim survives */
2988 			*ootmp = which_armor(mon, W_ARMS);
2989 		    } else if (mon->misc_worn_check & W_ARM) {
2990 			/* destroy body armor, also cloak if present */
2991 			*ootmp = which_armor(mon, W_ARM);
2992 			if ((otmp2 = which_armor(mon, W_ARMC)) != 0)
2993 			    m_useup(mon, otmp2);
2994 		    } else {
2995 			/* no body armor, victim dies; destroy cloak
2996 			   and shirt now in case target gets life-saved */
2997 			tmp = MAGIC_COOKIE;
2998 			if ((otmp2 = which_armor(mon, W_ARMC)) != 0)
2999 			    m_useup(mon, otmp2);
3000 #ifdef TOURIST
3001 			if ((otmp2 = which_armor(mon, W_ARMU)) != 0)
3002 			    m_useup(mon, otmp2);
3003 #endif
3004 		    }
3005 		    type = -1;	/* no saving throw wanted */
3006 		    break;	/* not ordinary damage */
3007 		}
3008 		tmp = mon->mhp+1;
3009 		break;
3010 	case ZT_LIGHTNING:
3011 		if (resists_elec(mon)) {
3012 		    sho_shieldeff = TRUE;
3013 		    tmp = 0;
3014 		    /* can still blind the monster */
3015 		} else
3016 		    tmp = d(nd,6);
3017 		if (spellcaster)
3018 		    tmp += spell_damage_bonus();
3019 #ifdef WIZ_PATCH_DEBUG
3020 		if (spellcaster)
3021 		    pline("Damage = %d + %d", tmp-spell_damage_bonus(),
3022 			spell_damage_bonus());
3023 #endif
3024 		if (!resists_blnd(mon) &&
3025 				!(type > 0 && u.uswallow && mon == u.ustuck)) {
3026 			register unsigned rnd_tmp = rnd(50);
3027 			mon->mcansee = 0;
3028 			if((mon->mblinded + rnd_tmp) > 127)
3029 				mon->mblinded = 127;
3030 			else mon->mblinded += rnd_tmp;
3031 		}
3032 		if (!rn2(3)) (void)destroy_mitem(mon, WAND_CLASS, AD_ELEC);
3033 		/* not actually possible yet */
3034 		if (!rn2(3)) (void)destroy_mitem(mon, RING_CLASS, AD_ELEC);
3035 		break;
3036 	case ZT_POISON_GAS:
3037 		if (resists_poison(mon)) {
3038 		    sho_shieldeff = TRUE;
3039 		    break;
3040 		}
3041 		tmp = d(nd,6);
3042 		break;
3043 	case ZT_ACID:
3044 		if (resists_acid(mon)) {
3045 		    sho_shieldeff = TRUE;
3046 		    break;
3047 		}
3048 		tmp = d(nd,6);
3049 		if (!rn2(6)) erode_obj(MON_WEP(mon), TRUE, TRUE);
3050 		if (!rn2(6)) erode_armor(mon, TRUE);
3051 		break;
3052 	}
3053 	if (sho_shieldeff) shieldeff(mon->mx, mon->my);
3054 	if (is_hero_spell(type) && (Role_if(PM_KNIGHT) && u.uhave.questart))
3055 	    tmp *= 2;
3056 	if (tmp > 0 && type >= 0 &&
3057 		resist(mon, type < ZT_SPELL(0) ? WAND_CLASS : '\0', 0, NOTELL))
3058 	    tmp /= 2;
3059 	if (tmp < 0) tmp = 0;		/* don't allow negative damage */
3060 #ifdef WIZ_PATCH_DEBUG
3061 	pline("zapped monster hp = %d (= %d - %d)", mon->mhp-tmp,mon->mhp,tmp);
3062 #endif
3063 	mon->mhp -= tmp;
3064 	return(tmp);
3065 }
3066 
3067 STATIC_OVL void
zhitu(type,nd,fltxt,sx,sy)3068 zhitu(type, nd, fltxt, sx, sy)
3069 int type, nd;
3070 const char *fltxt;
3071 xchar sx, sy;
3072 {
3073 	int dam = 0;
3074 
3075 	switch (abs(type) % 10) {
3076 	case ZT_MAGIC_MISSILE:
3077 	    if (Antimagic) {
3078 		shieldeff(sx, sy);
3079 		pline_The("missiles bounce off!");
3080 	    } else {
3081 		dam = d(nd,6);
3082 		exercise(A_STR, FALSE);
3083 	    }
3084 	    break;
3085 	case ZT_FIRE:
3086 	    if (Fire_resistance) {
3087 		shieldeff(sx, sy);
3088 		You("don't feel hot!");
3089 		ugolemeffects(AD_FIRE, d(nd, 6));
3090 	    } else {
3091 		dam = d(nd, 6);
3092 	    }
3093 	    burn_away_slime();
3094 	    if (burnarmor(&youmonst)) {	/* "body hit" */
3095 		if (!rn2(3)) destroy_item(POTION_CLASS, AD_FIRE);
3096 		if (!rn2(3)) destroy_item(SCROLL_CLASS, AD_FIRE);
3097 		if (!rn2(5)) destroy_item(SPBOOK_CLASS, AD_FIRE);
3098 	    }
3099 	    break;
3100 	case ZT_COLD:
3101 	    if (Cold_resistance) {
3102 		shieldeff(sx, sy);
3103 		You("don't feel cold.");
3104 		ugolemeffects(AD_COLD, d(nd, 6));
3105 	    } else {
3106 		dam = d(nd, 6);
3107 	    }
3108 	    if (!rn2(3)) destroy_item(POTION_CLASS, AD_COLD);
3109 	    break;
3110 	case ZT_SLEEP:
3111 	    if (Sleep_resistance) {
3112 		shieldeff(u.ux, u.uy);
3113 		You("don't feel sleepy.");
3114 	    } else {
3115 		fall_asleep(-d(nd,25), TRUE); /* sleep ray */
3116 	    }
3117 	    break;
3118 	case ZT_DEATH:
3119 	    if (abs(type) == ZT_BREATH(ZT_DEATH)) {
3120 		if (Disint_resistance) {
3121 		    You("are not disintegrated.");
3122 		    break;
3123 		} else if (uarms) {
3124 		    /* destroy shield; other possessions are safe */
3125 		    (void) destroy_arm(uarms);
3126 		    break;
3127 		} else if (uarm) {
3128 		    /* destroy suit; if present, cloak goes too */
3129 		    if (uarmc) (void) destroy_arm(uarmc);
3130 		    (void) destroy_arm(uarm);
3131 		    break;
3132 		}
3133 		/* no shield or suit, you're dead; wipe out cloak
3134 		   and/or shirt in case of life-saving or bones */
3135 		if (uarmc) (void) destroy_arm(uarmc);
3136 #ifdef TOURIST
3137 		if (uarmu) (void) destroy_arm(uarmu);
3138 #endif
3139 	    } else if (nonliving(youmonst.data) || is_demon(youmonst.data)) {
3140 		shieldeff(sx, sy);
3141 		You("seem unaffected.");
3142 		break;
3143 	    } else if (Antimagic) {
3144 		shieldeff(sx, sy);
3145 		You("aren't affected.");
3146 		break;
3147 	    }
3148 	    killer_format = KILLED_BY_AN;
3149 	    killer = fltxt;
3150 	    /* when killed by disintegration breath, don't leave corpse */
3151 	    u.ugrave_arise = (type == -ZT_BREATH(ZT_DEATH)) ? -3 : NON_PM;
3152 	    done(DIED);
3153 	    return; /* lifesaved */
3154 	case ZT_LIGHTNING:
3155 	    if (Shock_resistance) {
3156 		shieldeff(sx, sy);
3157 		You("aren't affected.");
3158 		ugolemeffects(AD_ELEC, d(nd, 6));
3159 	    } else {
3160 		dam = d(nd, 6);
3161 		exercise(A_CON, FALSE);
3162 	    }
3163 	    if (!rn2(3)) destroy_item(WAND_CLASS, AD_ELEC);
3164 	    if (!rn2(3)) destroy_item(RING_CLASS, AD_ELEC);
3165 	    break;
3166 	case ZT_POISON_GAS:
3167 	    poisoned("blast", A_DEX, "poisoned blast", 15);
3168 	    break;
3169 	case ZT_ACID:
3170 	    if (Acid_resistance) {
3171 		dam = 0;
3172 	    } else {
3173 		pline_The("acid burns!");
3174 		dam = d(nd,6);
3175 		exercise(A_STR, FALSE);
3176 	    }
3177 	    /* using two weapons at once makes both of them more vulnerable */
3178 	    if (!rn2(u.twoweap ? 3 : 6)) erode_obj(uwep, TRUE, TRUE);
3179 	    if (u.twoweap && !rn2(3)) erode_obj(uswapwep, TRUE, TRUE);
3180 	    if (!rn2(6)) erode_armor(&youmonst, TRUE);
3181 	    break;
3182 	}
3183 
3184 	if (Half_spell_damage && dam &&
3185 	   type < 0 && (type > -20 || type < -29)) /* !Breath */
3186 	    dam = (dam + 1) / 2;
3187 	losehp(dam, fltxt, KILLED_BY_AN);
3188 	return;
3189 }
3190 
3191 #endif /*OVL1*/
3192 #ifdef OVLB
3193 
3194 /*
3195  * burn scrolls and spellbooks on floor at position x,y
3196  * return the number of scrolls and spellbooks burned
3197  */
3198 int
burn_floor_paper(x,y,give_feedback,u_caused)3199 burn_floor_paper(x, y, give_feedback, u_caused)
3200 int x, y;
3201 boolean give_feedback;	/* caller needs to decide about visibility checks */
3202 boolean u_caused;
3203 {
3204 	struct obj *obj, *obj2;
3205 	long i, scrquan, delquan;
3206 	char buf1[BUFSZ], buf2[BUFSZ];
3207 	int cnt = 0;
3208 
3209 	for (obj = level.objects[x][y]; obj; obj = obj2) {
3210 	    obj2 = obj->nexthere;
3211 	    if (obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS) {
3212 		if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL ||
3213 			obj_resists(obj, 2, 100))
3214 		    continue;
3215 		scrquan = obj->quan;	/* number present */
3216 		delquan = 0;		/* number to destroy */
3217 		for (i = scrquan; i > 0; i--)
3218 		    if (!rn2(3)) delquan++;
3219 		if (delquan) {
3220 		    /* save name before potential delobj() */
3221 		    if (give_feedback) {
3222 			obj->quan = 1;
3223 			Strcpy(buf1, (x == u.ux && y == u.uy) ?
3224 				xname(obj) : distant_name(obj, xname));
3225 			obj->quan = 2;
3226 		    	Strcpy(buf2, (x == u.ux && y == u.uy) ?
3227 				xname(obj) : distant_name(obj, xname));
3228 			obj->quan = scrquan;
3229 		    }
3230 		    /* useupf(), which charges, only if hero caused damage */
3231 		    if (u_caused) useupf(obj, delquan);
3232 		    else if (delquan < scrquan) obj->quan -= delquan;
3233 		    else delobj(obj);
3234 		    cnt += delquan;
3235 		    if (give_feedback) {
3236 			if (delquan > 1)
3237 			    pline("%ld %s burn.", delquan, buf2);
3238 			else
3239 			    pline("%s burns.", An(buf1));
3240 		    }
3241 		}
3242 	    }
3243 	}
3244 	return cnt;
3245 }
3246 
3247 /* will zap/spell/breath attack score a hit against armor class `ac'? */
3248 STATIC_OVL int
zap_hit(ac,type)3249 zap_hit(ac, type)
3250 int ac;
3251 int type;	/* either hero cast spell type or 0 */
3252 {
3253     int chance = rn2(20);
3254     int spell_bonus = type ? spell_hit_bonus(type) : 0;
3255 
3256     /* small chance for naked target to avoid being hit */
3257     if (!chance) return rnd(10) < ac+spell_bonus;
3258 
3259     /* very high armor protection does not achieve invulnerability */
3260     ac = AC_VALUE(ac);
3261 
3262     return (3 - chance) < ac+spell_bonus;
3263 }
3264 
3265 /* type ==   0 to   9 : you shooting a wand */
3266 /* type ==  10 to  19 : you casting a spell */
3267 /* type ==  20 to  29 : you breathing as a monster */
3268 /* type == -10 to -19 : monster casting spell */
3269 /* type == -20 to -29 : monster breathing at you */
3270 /* type == -30 to -39 : monster shooting a wand */
3271 /* called with dx = dy = 0 with vertical bolts */
3272 void
buzz(type,nd,sx,sy,dx,dy)3273 buzz(type,nd,sx,sy,dx,dy)
3274 register int type, nd;
3275 register xchar sx,sy;
3276 register int dx,dy;
3277 {
3278     int range, abstype = abs(type) % 10;
3279     struct rm *lev;
3280     register xchar lsx, lsy;
3281     struct monst *mon;
3282     coord save_bhitpos;
3283     boolean shopdamage = FALSE;
3284     register const char *fltxt;
3285     struct obj *otmp;
3286     int spell_type;
3287 
3288     /* if its a Hero Spell then get its SPE_TYPE */
3289     spell_type = is_hero_spell(type) ? SPE_MAGIC_MISSILE + abstype : 0;
3290 
3291     fltxt = flash_types[(type <= -30) ? abstype : abs(type)];
3292     if(u.uswallow) {
3293 	register int tmp;
3294 
3295 	if(type < 0) return;
3296 	tmp = zhitm(u.ustuck, type, nd, &otmp);
3297 	if(!u.ustuck)	u.uswallow = 0;
3298 	else	pline("%s rips into %s%s",
3299 		      The(fltxt), mon_nam(u.ustuck), exclam(tmp));
3300 	/* Using disintegration from the inside only makes a hole... */
3301 	if (tmp == MAGIC_COOKIE)
3302 	    u.ustuck->mhp = 0;
3303 	if (u.ustuck->mhp < 1)
3304 	    killed(u.ustuck);
3305 	return;
3306     }
3307     if(type < 0) newsym(u.ux,u.uy);
3308     range = rn1(7,7);
3309     if(dx == 0 && dy == 0) range = 1;
3310     save_bhitpos = bhitpos;
3311 
3312     tmp_at(DISP_BEAM, zapdir_to_glyph(dx, dy, abstype));
3313     while(range-- > 0) {
3314 	lsx = sx; sx += dx;
3315 	lsy = sy; sy += dy;
3316 	if(isok(sx,sy) && (lev = &levl[sx][sy])->typ) {
3317 	    mon = m_at(sx, sy);
3318 	    if(cansee(sx,sy)) {
3319 		/* reveal/unreveal invisible monsters before tmp_at() */
3320 		if (mon && !canspotmon(mon))
3321 		    map_invisible(sx, sy);
3322 		else if (!mon && glyph_is_invisible(levl[sx][sy].glyph)) {
3323 		    unmap_object(sx, sy);
3324 		    newsym(sx, sy);
3325 		}
3326 		if(ZAP_POS(lev->typ) || cansee(lsx,lsy))
3327 		    tmp_at(sx,sy);
3328 		delay_output(); /* wait a little */
3329 	    }
3330 	} else
3331 	    goto make_bounce;
3332 
3333 	/* hit() and miss() need bhitpos to match the target */
3334 	bhitpos.x = sx,  bhitpos.y = sy;
3335 	/* Fireballs only damage when they explode */
3336 	if (type != ZT_SPELL(ZT_FIRE))
3337 	    range += zap_over_floor(sx, sy, type, &shopdamage);
3338 
3339 	if (mon) {
3340 	    if (type == ZT_SPELL(ZT_FIRE)) break;
3341 	    if (type >= 0) mon->mstrategy &= ~STRAT_WAITMASK;
3342 #ifdef STEED
3343 	    buzzmonst:
3344 #endif
3345 	    if (zap_hit(find_mac(mon), spell_type)) {
3346 		if (mon_reflects(mon, (char *)0)) {
3347 		    if(cansee(mon->mx,mon->my)) {
3348 			hit(fltxt, mon, exclam(0));
3349 			shieldeff(mon->mx, mon->my);
3350 			(void) mon_reflects(mon, "But it reflects from %s %s!");
3351 		    }
3352 		    dx = -dx;
3353 		    dy = -dy;
3354 		} else {
3355 		    boolean mon_could_move = mon->mcanmove;
3356 		    int tmp = zhitm(mon, type, nd, &otmp);
3357 
3358 		    if (is_rider(mon->data) && abs(type) == ZT_BREATH(ZT_DEATH)) {
3359 			if (canseemon(mon)) {
3360 			    hit(fltxt, mon, ".");
3361 			    pline("%s disintegrates.", Monnam(mon));
3362 			    pline("%s body reintegrates before your %s!",
3363 				  s_suffix(Monnam(mon)),
3364 				  (eyecount(youmonst.data) == 1) ?
3365 				  	body_part(EYE) : makeplural(body_part(EYE)));
3366 			    pline("%s resurrects!", Monnam(mon));
3367 			}
3368 			mon->mhp = mon->mhpmax;
3369 			break; /* Out of while loop */
3370 		    }
3371 		    if (mon->data == &mons[PM_DEATH] && abstype == ZT_DEATH) {
3372 			if (canseemon(mon)) {
3373 			    hit(fltxt, mon, ".");
3374 			    pline("%s absorbs the deadly %s!", Monnam(mon),
3375 				  type == ZT_BREATH(ZT_DEATH) ?
3376 					"blast" : "ray");
3377 			    pline("It seems even stronger than before.");
3378 			}
3379 			break; /* Out of while loop */
3380 		    }
3381 
3382 		    if (tmp == MAGIC_COOKIE) { /* disintegration */
3383 			struct obj *otmp2, *m_amulet = mlifesaver(mon);
3384 
3385 			if (canseemon(mon)) {
3386 			    if (!m_amulet)
3387 				pline("%s is disintegrated!", Monnam(mon));
3388 			    else
3389 				hit(fltxt, mon, "!");
3390 			}
3391 #ifndef GOLDOBJ
3392 			mon->mgold = 0L;
3393 #endif
3394 
3395 /* note: worn amulet of life saving must be preserved in order to operate */
3396 #define oresist_disintegration(obj) \
3397 		(objects[obj->otyp].oc_oprop == DISINT_RES || \
3398 		 obj_resists(obj, 5, 50) || is_quest_artifact(obj) || \
3399 		 obj == m_amulet)
3400 
3401 			for (otmp = mon->minvent; otmp; otmp = otmp2) {
3402 			    otmp2 = otmp->nobj;
3403 			    if (!oresist_disintegration(otmp)) {
3404 				obj_extract_self(otmp);
3405 				obfree(otmp, (struct obj *)0);
3406 			    }
3407 			}
3408 
3409 			if (type < 0)
3410 			    monkilled(mon, (char *)0, -AD_RBRE);
3411 			else
3412 			    xkilled(mon, 2);
3413 		    } else if(mon->mhp < 1) {
3414 			if(type < 0)
3415 			    monkilled(mon, fltxt, AD_RBRE);
3416 			else
3417 			    killed(mon);
3418 		    } else {
3419 			if (!otmp) {
3420 			    /* normal non-fatal hit */
3421 			    hit(fltxt, mon, exclam(tmp));
3422 			} else {
3423 			    /* some armor was destroyed; no damage done */
3424 			    if (canseemon(mon))
3425 				pline("%s %s is disintegrated!",
3426 				      s_suffix(Monnam(mon)),
3427 				      distant_name(otmp, xname));
3428 			    m_useup(mon, otmp);
3429 			}
3430 			if (mon_could_move && !mon->mcanmove)	/* ZT_SLEEP */
3431 			    slept_monst(mon);
3432 		    }
3433 		}
3434 		range -= 2;
3435 	    } else {
3436 		miss(fltxt,mon);
3437 	    }
3438 	} else if (sx == u.ux && sy == u.uy && range >= 0) {
3439 	    nomul(0);
3440 #ifdef STEED
3441 	    if (u.usteed && !rn2(3) && !mon_reflects(u.usteed, (char *)0)) {
3442 		    mon = u.usteed;
3443 		    goto buzzmonst;
3444 	    } else
3445 #endif
3446 	    if (zap_hit((int) u.uac, 0)) {
3447 		range -= 2;
3448 		pline("%s hits you!", The(fltxt));
3449 		if (Reflecting) {
3450 		    if (!Blind) {
3451 		    	(void) ureflects("But %s reflects from your %s!", "it");
3452 		    } else
3453 			pline("For some reason you are not affected.");
3454 		    dx = -dx;
3455 		    dy = -dy;
3456 		    shieldeff(sx, sy);
3457 		} else {
3458 		    zhitu(type, nd, fltxt, sx, sy);
3459 		}
3460 	    } else {
3461 		pline("%s whizzes by you!", The(fltxt));
3462 	    }
3463 	    if (abstype == ZT_LIGHTNING && !resists_blnd(&youmonst)) {
3464 		You(are_blinded_by_the_flash);
3465 		make_blinded((long)d(nd,50),FALSE);
3466 		if (!Blind) Your(vision_clears);
3467 	    }
3468 	    stop_occupation();
3469 	    nomul(0);
3470 	}
3471 
3472 	if(!ZAP_POS(lev->typ) || (closed_door(sx, sy) && (range >= 0))) {
3473 	    int bounce;
3474 	    uchar rmn;
3475 
3476  make_bounce:
3477 	    if (type == ZT_SPELL(ZT_FIRE)) {
3478 		sx = lsx;
3479 		sy = lsy;
3480 		break; /* fireballs explode before the wall */
3481 	    }
3482 	    bounce = 0;
3483 	    range--;
3484 	    if(range && isok(lsx, lsy) && cansee(lsx,lsy))
3485 		pline("%s bounces!", The(fltxt));
3486 	    if(!dx || !dy || !rn2(20)) {
3487 		dx = -dx;
3488 		dy = -dy;
3489 	    } else {
3490 		if(isok(sx,lsy) && ZAP_POS(rmn = levl[sx][lsy].typ) &&
3491 		   !closed_door(sx,lsy) &&
3492 		   (IS_ROOM(rmn) || (isok(sx+dx,lsy) &&
3493 				     ZAP_POS(levl[sx+dx][lsy].typ))))
3494 		    bounce = 1;
3495 		if(isok(lsx,sy) && ZAP_POS(rmn = levl[lsx][sy].typ) &&
3496 		   !closed_door(lsx,sy) &&
3497 		   (IS_ROOM(rmn) || (isok(lsx,sy+dy) &&
3498 				     ZAP_POS(levl[lsx][sy+dy].typ))))
3499 		    if(!bounce || rn2(2))
3500 			bounce = 2;
3501 
3502 		switch(bounce) {
3503 		case 0: dx = -dx; /* fall into... */
3504 		case 1: dy = -dy; break;
3505 		case 2: dx = -dx; break;
3506 		}
3507 		tmp_at(DISP_CHANGE, zapdir_to_glyph(dx,dy,abstype));
3508 	    }
3509 	}
3510     }
3511     tmp_at(DISP_END,0);
3512     if (type == ZT_SPELL(ZT_FIRE))
3513 	explode(sx, sy, type, d(12,6), 0, EXPL_FIERY);
3514     if (shopdamage)
3515 	pay_for_damage(abstype == ZT_FIRE ?  "burn away" :
3516 		       abstype == ZT_COLD ?  "shatter" :
3517 		       abstype == ZT_DEATH ? "disintegrate" : "destroy", FALSE);
3518     bhitpos = save_bhitpos;
3519 }
3520 #endif /*OVLB*/
3521 #ifdef OVL0
3522 
3523 void
melt_ice(x,y)3524 melt_ice(x, y)
3525 xchar x, y;
3526 {
3527 	struct rm *lev = &levl[x][y];
3528 	struct obj *otmp;
3529 
3530 	if (lev->typ == DRAWBRIDGE_UP)
3531 	    lev->drawbridgemask &= ~DB_ICE;	/* revert to DB_MOAT */
3532 	else {	/* lev->typ == ICE */
3533 #ifdef STUPID
3534 	    if (lev->icedpool == ICED_POOL) lev->typ = POOL;
3535 	    else lev->typ = MOAT;
3536 #else
3537 	    lev->typ = (lev->icedpool == ICED_POOL ? POOL : MOAT);
3538 #endif
3539 	    lev->icedpool = 0;
3540 	}
3541 	obj_ice_effects(x, y, FALSE);
3542 	unearth_objs(x, y);
3543 	if (Underwater) vision_recalc(1);
3544 	newsym(x,y);
3545 	if (cansee(x,y)) Norep("The ice crackles and melts.");
3546 	if ((otmp = sobj_at(BOULDER, x, y)) != 0) {
3547 	    if (cansee(x,y)) pline("%s settles...", An(xname(otmp)));
3548 	    do {
3549 		obj_extract_self(otmp);	/* boulder isn't being pushed */
3550 		if (!boulder_hits_pool(otmp, x, y, FALSE))
3551 		    impossible("melt_ice: no pool?");
3552 		/* try again if there's another boulder and pool didn't fill */
3553 	    } while (is_pool(x,y) && (otmp = sobj_at(BOULDER, x, y)) != 0);
3554 	    newsym(x,y);
3555 	}
3556 	if (x == u.ux && y == u.uy)
3557 		spoteffects(TRUE);	/* possibly drown, notice objects */
3558 }
3559 
3560 /* Burn floor scrolls, evaporate pools, etc...  in a single square.  Used
3561  * both for normal bolts of fire, cold, etc... and for fireballs.
3562  * Sets shopdamage to TRUE if a shop door is destroyed, and returns the
3563  * amount by which range is reduced (the latter is just ignored by fireballs)
3564  */
3565 int
zap_over_floor(x,y,type,shopdamage)3566 zap_over_floor(x, y, type, shopdamage)
3567 xchar x, y;
3568 int type;
3569 boolean *shopdamage;
3570 {
3571 	struct monst *mon;
3572 	int abstype = abs(type) % 10;
3573 	struct rm *lev = &levl[x][y];
3574 	int rangemod = 0;
3575 
3576 	if(abstype == ZT_FIRE) {
3577 	    struct trap *t = t_at(x, y);
3578 
3579 	    if (t && t->ttyp == WEB) {
3580 		/* a burning web is too flimsy to notice if you can't see it */
3581 		if (cansee(x,y)) Norep("A web bursts into flames!");
3582 		(void) delfloortrap(t);
3583 		if (cansee(x,y)) newsym(x,y);
3584 	    }
3585 	    if(is_ice(x, y)) {
3586 		melt_ice(x, y);
3587 	    } else if(is_pool(x,y)) {
3588 		const char *msgtxt = "You hear hissing gas.";
3589 		if(lev->typ != POOL) {	/* MOAT or DRAWBRIDGE_UP */
3590 		    if (cansee(x,y)) msgtxt = "Some water evaporates.";
3591 		} else {
3592 		    register struct trap *ttmp;
3593 
3594 		    rangemod -= 3;
3595 		    lev->typ = ROOM;
3596 		    ttmp = maketrap(x, y, PIT);
3597 		    if (ttmp) ttmp->tseen = 1;
3598 		    if (cansee(x,y)) msgtxt = "The water evaporates.";
3599 		}
3600 		Norep(msgtxt);
3601 		if (lev->typ == ROOM) newsym(x,y);
3602 	    } else if(IS_FOUNTAIN(lev->typ)) {
3603 		    if (cansee(x,y))
3604 			pline("Steam billows from the fountain.");
3605 		    rangemod -= 1;
3606 		    dryup(x, y, type > 0);
3607 	    }
3608 	}
3609 	else if(abstype == ZT_COLD && (is_pool(x,y) || is_lava(x,y))) {
3610 		boolean lava = is_lava(x,y);
3611 		boolean moat = (!lava && (lev->typ != POOL) &&
3612 				(lev->typ != WATER) &&
3613 				!Is_medusa_level(&u.uz) &&
3614 				!Is_waterlevel(&u.uz));
3615 
3616 		if (lev->typ == WATER) {
3617 		    /* For now, don't let WATER freeze. */
3618 		    if (cansee(x,y))
3619 			pline_The("water freezes for a moment.");
3620 		    else
3621 			You_hear("a soft crackling.");
3622 		    rangemod -= 1000;	/* stop */
3623 		} else {
3624 		    rangemod -= 3;
3625 		    if (lev->typ == DRAWBRIDGE_UP) {
3626 			lev->drawbridgemask &= ~DB_UNDER;  /* clear lava */
3627 			lev->drawbridgemask |= (lava ? DB_FLOOR : DB_ICE);
3628 		    } else {
3629 			if (!lava)
3630 			    lev->icedpool =
3631 				    (lev->typ == POOL ? ICED_POOL : ICED_MOAT);
3632 			lev->typ = (lava ? ROOM : ICE);
3633 		    }
3634 		    bury_objs(x,y);
3635 		    if(cansee(x,y)) {
3636 			if(moat)
3637 				Norep("The moat is bridged with ice!");
3638 			else if(lava)
3639 				Norep("The lava cools and solidifies.");
3640 			else
3641 				Norep("The water freezes.");
3642 			newsym(x,y);
3643 		    } else if(flags.soundok && !lava)
3644 			You_hear("a crackling sound.");
3645 
3646 		    if (x == u.ux && y == u.uy) {
3647 			if (u.uinwater) {   /* not just `if (Underwater)' */
3648 			    /* leave the no longer existent water */
3649 			    u.uinwater = 0;
3650 			    u.uundetected = 0;
3651 			    docrt();
3652 			    vision_full_recalc = 1;
3653 			} else if (u.utrap && u.utraptype == TT_LAVA) {
3654 			    if (Passes_walls) {
3655 				You("pass through the now-solid rock.");
3656 			    } else {
3657 				u.utrap = rn1(50,20);
3658 				u.utraptype = TT_INFLOOR;
3659 				You("are firmly stuck in the cooling rock.");
3660 			    }
3661 			}
3662 		    } else if ((mon = m_at(x,y)) != 0) {
3663 			/* probably ought to do some hefty damage to any
3664 			   non-ice creature caught in freezing water;
3665 			   at a minimum, eels are forced out of hiding */
3666 			if (is_swimmer(mon->data) && mon->mundetected) {
3667 			    mon->mundetected = 0;
3668 			    newsym(x,y);
3669 			}
3670 		    }
3671 		}
3672 		obj_ice_effects(x,y,TRUE);
3673 	}
3674 	if(closed_door(x, y)) {
3675 		int new_doormask = -1;
3676 		const char *see_txt = 0, *sense_txt = 0, *hear_txt = 0;
3677 		rangemod = -1000;
3678 		switch(abstype) {
3679 		case ZT_FIRE:
3680 		    new_doormask = D_NODOOR;
3681 		    see_txt = "The door is consumed in flames!";
3682 		    sense_txt = "smell smoke.";
3683 		    break;
3684 		case ZT_COLD:
3685 		    new_doormask = D_NODOOR;
3686 		    see_txt = "The door freezes and shatters!";
3687 		    sense_txt = "feel cold.";
3688 		    break;
3689 		case ZT_DEATH:
3690 		    /* death spells/wands don't disintegrate */
3691 		    if(abs(type) != ZT_BREATH(ZT_DEATH))
3692 			goto def_case;
3693 		    new_doormask = D_NODOOR;
3694 		    see_txt = "The door disintegrates!";
3695 		    hear_txt = "crashing wood.";
3696 		    break;
3697 		case ZT_LIGHTNING:
3698 		    new_doormask = D_BROKEN;
3699 		    see_txt = "The door splinters!";
3700 		    hear_txt = "crackling.";
3701 		    break;
3702 		default:
3703 		def_case:
3704 		    if(cansee(x,y)) {
3705 			pline_The("door absorbs %s %s!",
3706 			      (type < 0) ? "the" : "your",
3707 			      abs(type) < ZT_SPELL(0) ? "bolt" :
3708 			      abs(type) < ZT_BREATH(0) ? "spell" :
3709 			      "blast");
3710 		    } else You_feel("vibrations.");
3711 		    break;
3712 		}
3713 		if (new_doormask >= 0) {	/* door gets broken */
3714 		    if (*in_rooms(x, y, SHOPBASE)) {
3715 			if (type >= 0) {
3716 			    add_damage(x, y, 400L);
3717 			    *shopdamage = TRUE;
3718 			} else	/* caused by monster */
3719 			    add_damage(x, y, 0L);
3720 		    }
3721 		    lev->doormask = new_doormask;
3722 		    unblock_point(x, y);	/* vision */
3723 		    if (cansee(x, y)) {
3724 			pline(see_txt);
3725 			newsym(x, y);
3726 		    } else if (sense_txt) {
3727 			You(sense_txt);
3728 		    } else if (hear_txt) {
3729 			if (flags.soundok) You_hear(hear_txt);
3730 		    }
3731 		    if (picking_at(x, y)) {
3732 			stop_occupation();
3733 			reset_pick();
3734 		    }
3735 		}
3736 	}
3737 
3738 	if(OBJ_AT(x, y) && abstype == ZT_FIRE)
3739 		if (burn_floor_paper(x, y, FALSE, type > 0) && couldsee(x, y)) {
3740 		    newsym(x,y);
3741 		    You("%s of smoke.",
3742 			!Blind ? "see a puff" : "smell a whiff");
3743 		}
3744 	if ((mon = m_at(x,y)) != 0) {
3745 		/* Cannot use wakeup() which also angers the monster */
3746 		mon->msleeping = 0;
3747 		if(mon->m_ap_type) seemimic(mon);
3748 		if(type >= 0) {
3749 		    setmangry(mon);
3750 		    if(mon->ispriest && *in_rooms(mon->mx, mon->my, TEMPLE))
3751 			ghod_hitsu(mon);
3752 		    if(mon->isshk && !*u.ushops)
3753 			hot_pursuit(mon);
3754 		}
3755 	}
3756 	return rangemod;
3757 }
3758 
3759 #endif /*OVL0*/
3760 #ifdef OVL3
3761 
3762 void
fracture_rock(obj)3763 fracture_rock(obj)	/* fractured by pick-axe or wand of striking */
3764 register struct obj *obj;		   /* no texts here! */
3765 {
3766 	/* A little Sokoban guilt... */
3767 	if (obj->otyp == BOULDER && In_sokoban(&u.uz) && !flags.mon_moving)
3768 	    change_luck(-1);
3769 
3770 	obj->otyp = ROCK;
3771 	obj->quan = (long) rn1(60, 7);
3772 	obj->owt = weight(obj);
3773 	obj->oclass = GEM_CLASS;
3774 	obj->known = FALSE;
3775 	obj->onamelth = 0;		/* no names */
3776 	obj->oxlth = 0;			/* no extra data */
3777 	obj->oattached = OATTACHED_NOTHING;
3778 	if (obj->where == OBJ_FLOOR) {
3779 		obj_extract_self(obj);		/* move rocks back on top */
3780 		place_object(obj, obj->ox, obj->oy);
3781 		if(!does_block(obj->ox,obj->oy,&levl[obj->ox][obj->oy]))
3782 	    		unblock_point(obj->ox,obj->oy);
3783 		if(cansee(obj->ox,obj->oy))
3784 		    newsym(obj->ox,obj->oy);
3785 	}
3786 }
3787 
3788 /* handle statue hit by striking/force bolt/pick-axe */
3789 boolean
break_statue(obj)3790 break_statue(obj)
3791 register struct obj *obj;
3792 {
3793 	/* [obj is assumed to be on floor, so no get_obj_location() needed] */
3794 	struct trap *trap = t_at(obj->ox, obj->oy);
3795 	struct obj *item;
3796 
3797 	if (trap && trap->ttyp == STATUE_TRAP &&
3798 		activate_statue_trap(trap, obj->ox, obj->oy, TRUE))
3799 	    return FALSE;
3800 	/* drop any objects contained inside the statue */
3801 	while ((item = obj->cobj) != 0) {
3802 	    obj_extract_self(item);
3803 	    place_object(item, obj->ox, obj->oy);
3804 	}
3805 	if (Role_if(PM_ARCHEOLOGIST) && !flags.mon_moving && (obj->spe & STATUE_HISTORIC)) {
3806 	    You_feel("guilty about damaging such a historic statue.");
3807 	    adjalign(-1);
3808 	}
3809 	obj->spe = 0;
3810 	fracture_rock(obj);
3811 	return TRUE;
3812 }
3813 
3814 const char * const destroy_strings[] = {	/* also used in trap.c */
3815 	"freezes and shatters", "freeze and shatter", "shattered potion",
3816 	"boils and explodes", "boil and explode", "boiling potion",
3817 	"catches fire and burns", "catch fire and burn", "burning scroll",
3818 	"catches fire and burns", "catch fire and burn", "burning book",
3819 	"turns to dust and vanishes", "turn to dust and vanish", "",
3820 	"breaks apart and explodes", "break apart and explode", "exploding wand"
3821 };
3822 
3823 void
destroy_item(osym,dmgtyp)3824 destroy_item(osym, dmgtyp)
3825 register int osym, dmgtyp;
3826 {
3827 	register struct obj *obj, *obj2;
3828 	register int dmg, xresist, skip;
3829 	register long i, cnt, quan;
3830 	register int dindx;
3831 	const char *mult;
3832 
3833 	for(obj = invent; obj; obj = obj2) {
3834 	    obj2 = obj->nobj;
3835 	    if(obj->oclass != osym) continue; /* test only objs of type osym */
3836 	    if(obj->oartifact) continue; /* don't destroy artifacts */
3837 	    if(obj->in_use && obj->quan == 1) continue; /* not available */
3838 	    xresist = skip = 0;
3839 #ifdef GCC_WARN
3840 	    dmg = dindx = 0;
3841 	    quan = 0L;
3842 #endif
3843 	    switch(dmgtyp) {
3844 		case AD_COLD:
3845 		    if(osym == POTION_CLASS && obj->otyp != POT_OIL) {
3846 			quan = obj->quan;
3847 			dindx = 0;
3848 			dmg = rnd(4);
3849 		    } else skip++;
3850 		    break;
3851 		case AD_FIRE:
3852 		    xresist = (Fire_resistance && obj->oclass != POTION_CLASS);
3853 
3854 		    if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
3855 			skip++;
3856 		    if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
3857 			skip++;
3858 			if (!Blind)
3859 			    pline("%s glows a strange %s, but remains intact.",
3860 				The(xname(obj)), hcolor("dark red"));
3861 		    }
3862 		    quan = obj->quan;
3863 		    switch(osym) {
3864 			case POTION_CLASS:
3865 			    dindx = 1;
3866 			    dmg = rnd(6);
3867 			    break;
3868 			case SCROLL_CLASS:
3869 			    dindx = 2;
3870 			    dmg = 1;
3871 			    break;
3872 			case SPBOOK_CLASS:
3873 			    dindx = 3;
3874 			    dmg = 1;
3875 			    break;
3876 			default:
3877 			    skip++;
3878 			    break;
3879 		    }
3880 		    break;
3881 		case AD_ELEC:
3882 		    xresist = (Shock_resistance && obj->oclass != RING_CLASS);
3883 		    quan = obj->quan;
3884 		    switch(osym) {
3885 			case RING_CLASS:
3886 			    if(obj->otyp == RIN_SHOCK_RESISTANCE)
3887 				    { skip++; break; }
3888 			    dindx = 4;
3889 			    dmg = 0;
3890 			    break;
3891 			case WAND_CLASS:
3892 			    if(obj->otyp == WAN_LIGHTNING) { skip++; break; }
3893 #if 0
3894 			    if (obj == current_wand) { skip++; break; }
3895 #endif
3896 			    dindx = 5;
3897 			    dmg = rnd(10);
3898 			    break;
3899 			default:
3900 			    skip++;
3901 			    break;
3902 		    }
3903 		    break;
3904 		default:
3905 		    skip++;
3906 		    break;
3907 	    }
3908 	    if(!skip) {
3909 		if (obj->in_use) --quan; /* one will be used up elsewhere */
3910 		for(i = cnt = 0L; i < quan; i++)
3911 		    if(!rn2(3)) cnt++;
3912 
3913 		if(!cnt) continue;
3914 		if(cnt == quan)	mult = "Your";
3915 		else	mult = (cnt == 1L) ? "One of your" : "Some of your";
3916 		pline("%s %s %s!", mult, xname(obj),
3917 			(cnt > 1L) ? destroy_strings[dindx*3 + 1]
3918 				  : destroy_strings[dindx*3]);
3919 		if(osym == POTION_CLASS && dmgtyp != AD_COLD) {
3920 		    if (!breathless(youmonst.data) || haseyes(youmonst.data))
3921 		    	potionbreathe(obj);
3922 		}
3923 		if (obj->owornmask) {
3924 		    if (obj->owornmask & W_RING) /* ring being worn */
3925 			Ring_gone(obj);
3926 		    else
3927 			setnotworn(obj);
3928 		}
3929 		if (obj == current_wand) current_wand = 0;	/* destroyed */
3930 		for (i = 0; i < cnt; i++)
3931 		    useup(obj);
3932 		if(dmg) {
3933 		    if(xresist)	You("aren't hurt!");
3934 		    else {
3935 			const char *how = destroy_strings[dindx * 3 + 2];
3936 			boolean one = (cnt == 1L);
3937 
3938 			losehp(dmg, one ? how : (const char *)makeplural(how),
3939 			       one ? KILLED_BY_AN : KILLED_BY);
3940 			exercise(A_STR, FALSE);
3941 		    }
3942 		}
3943 	    }
3944 	}
3945 	return;
3946 }
3947 
3948 int
destroy_mitem(mtmp,osym,dmgtyp)3949 destroy_mitem(mtmp, osym, dmgtyp)
3950 struct monst *mtmp;
3951 int osym, dmgtyp;
3952 {
3953 	struct obj *obj, *obj2;
3954 	int skip, tmp = 0;
3955 	long i, cnt, quan;
3956 	int dindx;
3957 	boolean vis;
3958 
3959 	if (mtmp == &youmonst) {	/* this simplifies artifact_hit() */
3960 	    destroy_item(osym, dmgtyp);
3961 	    return 0;	/* arbitrary; value doesn't matter to artifact_hit() */
3962 	}
3963 
3964 	vis = canseemon(mtmp);
3965 	for(obj = mtmp->minvent; obj; obj = obj2) {
3966 	    obj2 = obj->nobj;
3967 	    if(obj->oclass != osym) continue; /* test only objs of type osym */
3968 	    skip = 0;
3969 	    quan = 0L;
3970 	    dindx = 0;
3971 
3972 	    switch(dmgtyp) {
3973 		case AD_COLD:
3974 		    if(osym == POTION_CLASS && obj->otyp != POT_OIL) {
3975 			quan = obj->quan;
3976 			dindx = 0;
3977 			tmp++;
3978 		    } else skip++;
3979 		    break;
3980 		case AD_FIRE:
3981 		    if (obj->otyp == SCR_FIRE || obj->otyp == SPE_FIREBALL)
3982 			skip++;
3983 		    if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
3984 			skip++;
3985 			if (vis)
3986 			    pline("%s glows a strange %s, but remains intact.",
3987 				The(distant_name(obj, xname)),
3988 				hcolor("dark red"));
3989 		    }
3990 		    quan = obj->quan;
3991 		    switch(osym) {
3992 			case POTION_CLASS:
3993 			    dindx = 1;
3994 			    tmp++;
3995 			    break;
3996 			case SCROLL_CLASS:
3997 			    dindx = 2;
3998 			    tmp++;
3999 			    break;
4000 			case SPBOOK_CLASS:
4001 			    dindx = 3;
4002 			    tmp++;
4003 			    break;
4004 			default:
4005 			    skip++;
4006 			    break;
4007 		    }
4008 		    break;
4009 		case AD_ELEC:
4010 		    quan = obj->quan;
4011 		    switch(osym) {
4012 			case RING_CLASS:
4013 			    if(obj->otyp == RIN_SHOCK_RESISTANCE)
4014 				    { skip++; break; }
4015 			    dindx = 4;
4016 			    break;
4017 			case WAND_CLASS:
4018 			    if(obj->otyp == WAN_LIGHTNING) { skip++; break; }
4019 			    dindx = 5;
4020 			    tmp++;
4021 			    break;
4022 			default:
4023 			    skip++;
4024 			    break;
4025 		    }
4026 		    break;
4027 		default:
4028 		    skip++;
4029 		    break;
4030 	    }
4031 	    if(!skip) {
4032 		for(i = cnt = 0L; i < quan; i++)
4033 		    if(!rn2(3)) cnt++;
4034 
4035 		if(!cnt) continue;
4036 		if (vis) pline("%s %s %s!",
4037 			s_suffix(Monnam(mtmp)), xname(obj),
4038 			(cnt > 1L) ? destroy_strings[dindx*3 + 1]
4039 				  : destroy_strings[dindx*3]);
4040 		for(i = 0; i < cnt; i++) m_useup(mtmp, obj);
4041 	    }
4042 	}
4043 	return(tmp);
4044 }
4045 
4046 #endif /*OVL3*/
4047 #ifdef OVL2
4048 
4049 int
resist(mtmp,oclass,damage,tell)4050 resist(mtmp, oclass, damage, tell)
4051 struct monst *mtmp;
4052 char oclass;
4053 int damage, tell;
4054 {
4055 	int resisted;
4056 	int alev, dlev;
4057 
4058 	/* attack level */
4059 	switch (oclass) {
4060 	    case WAND_CLASS:	alev = 12;	 break;
4061 	    case TOOL_CLASS:	alev = 10;	 break;	/* instrument */
4062 	    case WEAPON_CLASS:	alev = 10;	 break;	/* artifact */
4063 	    case SCROLL_CLASS:	alev =  9;	 break;
4064 	    case POTION_CLASS:	alev =  6;	 break;
4065 	    case RING_CLASS:	alev =  5;	 break;
4066 	    default:		alev = u.ulevel; break;	/* spell */
4067 	}
4068 	/* defense level */
4069 	dlev = (int)mtmp->m_lev;
4070 	if (dlev > 50) dlev = 50;
4071 	else if (dlev < 1) dlev = is_mplayer(mtmp->data) ? u.ulevel : 1;
4072 
4073 	resisted = rn2(100 + alev - dlev) < mtmp->data->mr;
4074 	if (resisted) {
4075 	    if (tell) {
4076 		shieldeff(mtmp->mx, mtmp->my);
4077 		pline("%s resists!", Monnam(mtmp));
4078 	    }
4079 	    damage = (damage + 1) / 2;
4080 	}
4081 
4082 	if (damage) {
4083 	    mtmp->mhp -= damage;
4084 	    if (mtmp->mhp < 1) {
4085 		if(m_using) monkilled(mtmp, "", AD_RBRE);
4086 		else killed(mtmp);
4087 	    }
4088 	}
4089 	return(resisted);
4090 }
4091 
4092 void
makewish()4093 makewish()
4094 {
4095 	char buf[BUFSZ];
4096 	struct obj *otmp, nothing;
4097 	int tries = 0;
4098 
4099 	nothing = zeroobj;  /* lint suppression; only its address matters */
4100 	if (flags.verbose) You("may wish for an object.");
4101 retry:
4102 	getlin("For what do you wish?", buf);
4103 	if(buf[0] == '\033') buf[0] = 0;
4104 	/*
4105 	 *  Note: if they wished for and got a non-object successfully,
4106 	 *  otmp == &zeroobj.  That includes gold, or an artifact that
4107 	 *  has been denied.  Wishing for "nothing" requires a separate
4108 	 *  value to remain distinct.
4109 	 */
4110 	otmp = readobjnam(buf, &nothing, TRUE);
4111 	if (!otmp) {
4112 	    pline("Nothing fitting that description exists in the game.");
4113 	    if (++tries < 5) goto retry;
4114 	    pline(thats_enough_tries);
4115 	    otmp = readobjnam((char *)0, (struct obj *)0, TRUE);
4116 	    if (!otmp) return;	/* for safety; should never happen */
4117 	} else if (otmp == &nothing) {
4118 	    /* explicitly wished for "nothing", presumeably attempting
4119 	       to retain wishless conduct */
4120 	    return;
4121 	}
4122 
4123 	/* KMH, conduct */
4124 	u.uconduct.wishes++;
4125 
4126 	if (otmp != &zeroobj) {
4127 	    /* The(aobjnam()) is safe since otmp is unidentified -dlc */
4128 	    (void) hold_another_object(otmp, u.uswallow ?
4129 				       "Oops!  %s out of your reach!" :
4130 				       (Is_airlevel(&u.uz) ||
4131 					Is_waterlevel(&u.uz) ||
4132 					levl[u.ux][u.uy].typ < IRONBARS ||
4133 					levl[u.ux][u.uy].typ >= ICE) ?
4134 				       "Oops!  %s away from you!" :
4135 				       "Oops!  %s to the floor!",
4136 				       The(aobjnam(otmp,
4137 					     Is_airlevel(&u.uz) || u.uinwater ?
4138 						   "slip" : "drop")),
4139 				       (const char *)0);
4140 	    u.ublesscnt += rn1(100,50);  /* the gods take notice */
4141 	}
4142 }
4143 
4144 #endif /*OVL2*/
4145 
4146 /*zap.c*/
4147