1 /*	SCCS Id: @(#)apply.c	3.4	2003/11/18	*/
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4 
5 #include "hack.h"
6 #include "edog.h"
7 
8 static const char tools[] = { COIN_CLASS, TOOL_CLASS, WEAPON_CLASS, WAND_CLASS, 0 };
9 static const char tools_too[] = { COIN_CLASS, ALL_CLASSES, TOOL_CLASS, POTION_CLASS,
10 				  WEAPON_CLASS, WAND_CLASS, GEM_CLASS, 0 };
11 
12 #ifdef TOURIST
13 STATIC_DCL int FDECL(use_camera, (struct obj *));
14 #endif
15 STATIC_DCL int FDECL(use_towel, (struct obj *));
16 STATIC_DCL boolean FDECL(its_dead, (int,int,int *,struct obj*));
17 STATIC_DCL int FDECL(use_stethoscope, (struct obj *));
18 STATIC_DCL void FDECL(use_whistle, (struct obj *));
19 STATIC_DCL void FDECL(use_magic_whistle, (struct obj *));
20 STATIC_DCL void FDECL(use_leash, (struct obj *));
21 STATIC_DCL int FDECL(use_mirror, (struct obj *));
22 STATIC_DCL void FDECL(use_bell, (struct obj **));
23 STATIC_DCL void FDECL(use_candelabrum, (struct obj *));
24 STATIC_DCL void FDECL(use_candle, (struct obj **));
25 STATIC_DCL void FDECL(use_lamp, (struct obj *));
26 STATIC_DCL void FDECL(light_cocktail, (struct obj *));
27 STATIC_DCL void FDECL(use_tinning_kit, (struct obj *));
28 STATIC_DCL void FDECL(use_figurine, (struct obj **));
29 STATIC_DCL void FDECL(use_grease, (struct obj *));
30 STATIC_DCL void FDECL(use_trap, (struct obj *));
31 STATIC_DCL void FDECL(use_stone, (struct obj *));
32 STATIC_PTR int NDECL(set_trap);		/* occupation callback */
33 STATIC_DCL int FDECL(use_whip, (struct obj *));
34 STATIC_DCL int FDECL(use_pole, (struct obj *));
35 STATIC_DCL int FDECL(use_cream_pie, (struct obj *));
36 STATIC_DCL int FDECL(use_grapple, (struct obj *));
37 STATIC_DCL int FDECL(do_break_wand, (struct obj *));
38 STATIC_DCL int FDECL(do_flip_coin, (struct obj *));
39 STATIC_DCL boolean FDECL(figurine_location_checks,
40 				(struct obj *, coord *, BOOLEAN_P));
41 STATIC_DCL boolean NDECL(uhave_graystone);
42 STATIC_DCL void FDECL(add_class, (char *, CHAR_P));
43 
44 #ifdef	AMIGA
45 void FDECL( amii_speaker, ( struct obj *, char *, int ) );
46 #endif
47 
48 static const char no_elbow_room[] = "don't have enough elbow-room to maneuver.";
49 
50 #ifdef TOURIST
51 STATIC_OVL int
use_camera(obj)52 use_camera(obj)
53 	struct obj *obj;
54 {
55 	register struct monst *mtmp;
56 
57 	if(Underwater) {
58 		pline("Using your camera underwater would void the warranty.");
59 		return(0);
60 	}
61 	if(!getdir((char *)0)) return(0);
62 
63 	if (obj->spe <= 0) {
64 		pline("%s", nothing_happens);
65 		return (1);
66 	}
67 	consume_obj_charge(obj, TRUE);
68 
69 	if (obj->cursed && !rn2(2)) {
70 		(void) zapyourself(obj, TRUE);
71 	} else if (u.uswallow) {
72 		You("take a picture of %s %s.", s_suffix(mon_nam(u.ustuck)),
73 		    mbodypart(u.ustuck, STOMACH));
74 	} else if (u.dz) {
75 		You("take a picture of the %s.",
76 			(u.dz > 0) ? surface(u.ux,u.uy) : ceiling(u.ux,u.uy));
77 	} else if (!u.dx && !u.dy) {
78 		(void) zapyourself(obj, TRUE);
79 	} else if ((mtmp = bhit(u.dx, u.dy, COLNO, FLASHED_LIGHT,
80 				(int FDECL((*),(MONST_P,OBJ_P)))0,
81 				(int FDECL((*),(OBJ_P,OBJ_P)))0,
82 				obj, NULL)) != 0) {
83 		obj->ox = u.ux,  obj->oy = u.uy;
84 		(void) flash_hits_mon(mtmp, obj);
85 	}
86 	return 1;
87 }
88 #endif
89 
90 STATIC_OVL int
use_towel(obj)91 use_towel(obj)
92 	struct obj *obj;
93 {
94 	if(!freehand()) {
95 		You("have no free %s!", body_part(HAND));
96 		return 0;
97 	} else if (obj->owornmask) {
98 		You("cannot use it while you're wearing it!");
99 		return 0;
100 	} else if (obj->cursed) {
101 		long old;
102 		switch (rn2(3)) {
103 		case 2:
104 		    old = Glib;
105 		    Glib += rn1(10, 3);
106 		    Your("%s %s!", makeplural(body_part(HAND)),
107 			(old ? "are filthier than ever" : "get slimy"));
108 		    return 1;
109 		case 1:
110 		    if (!ublindf) {
111 			old = u.ucreamed;
112 			u.ucreamed += rn1(10, 3);
113 			pline("Yecch! Your %s %s gunk on it!", body_part(FACE),
114 			      (old ? "has more" : "now has"));
115 			make_blinded(Blinded + (long)u.ucreamed - old, TRUE);
116 		    } else {
117 			const char *what = (ublindf->otyp == LENSES) ?
118 					    "lenses" : "blindfold";
119 			if (ublindf->cursed) {
120 			    You("push your %s %s.", what,
121 				rn2(2) ? "cock-eyed" : "crooked");
122 			} else {
123 			    struct obj *saved_ublindf = ublindf;
124 			    You("push your %s off.", what);
125 			    Blindf_off(ublindf);
126 			    dropx(saved_ublindf);
127 			}
128 		    }
129 		    return 1;
130 		case 0:
131 		    break;
132 		}
133 	}
134 
135 	if (Glib) {
136 		Glib = 0;
137 		You("wipe off your %s.", makeplural(body_part(HAND)));
138 		return 1;
139 	} else if(u.ucreamed) {
140 		Blinded -= u.ucreamed;
141 		u.ucreamed = 0;
142 
143 		if (!Blinded) {
144 			pline("You've got the glop off.");
145 			Blinded = 1;
146 			make_blinded(0L,TRUE);
147 		} else {
148 			Your("%s feels clean now.", body_part(FACE));
149 		}
150 		return 1;
151 	}
152 
153 	Your("%s and %s are already clean.",
154 		body_part(FACE), makeplural(body_part(HAND)));
155 
156 	return 0;
157 }
158 
159 /* maybe give a stethoscope message based on floor objects */
160 STATIC_OVL boolean
its_dead(rx,ry,resp,tobj)161 its_dead(rx, ry, resp, tobj)
162 int rx, ry, *resp;
163 struct obj* tobj;
164 {
165 	struct obj *otmp;
166 	struct trap *ttmp;
167 
168 	if (!can_reach_floor()) return FALSE;
169 
170 	/* additional stethoscope messages from jyoung@apanix.apana.org.au */
171 	if (Hallucination && sobj_at(CORPSE, rx, ry)) {
172 	    /* (a corpse doesn't retain the monster's sex,
173 	       so we're forced to use generic pronoun here) */
174 	    You_hear("a voice say, \"It's dead, Jim.\"");
175 	    *resp = 1;
176 	    return TRUE;
177 	} else if (Role_if(PM_HEALER) && ((otmp = sobj_at(CORPSE, rx, ry)) != 0 ||
178 				    (otmp = sobj_at(STATUE, rx, ry)) != 0)) {
179 	    /* possibly should check uppermost {corpse,statue} in the pile
180 	       if both types are present, but it's not worth the effort */
181 	    if (vobj_at(rx, ry)->otyp == STATUE) otmp = vobj_at(rx, ry);
182 	    if (otmp->otyp == CORPSE) {
183 		You("determine that %s unfortunate being is dead.",
184 		    (rx == u.ux && ry == u.uy) ? "this" : "that");
185 	    } else {
186 		ttmp = t_at(rx, ry);
187 		pline("%s appears to be in %s health for a statue.",
188 		      The(mons[otmp->corpsenm].mname),
189 		      (ttmp && ttmp->ttyp == STATUE_TRAP) ?
190 			"extraordinary" : "excellent");
191 	    }
192 	    return TRUE;
193 	}
194 
195 	/* listening to eggs is a little fishy, but so is stethoscopes detecting alignment
196 	 * The overcomplex wording is because all the monster-naming functions operate
197 	 * on actual instances of the monsters, and we're dealing with just an index
198 	 * so we can avoid things like "a owlbear", etc. */
199 	if ((otmp = sobj_at(EGG,rx,ry))) {
200 		if (Hallucination) {
201 			pline("You listen to the egg and guess... %s?",rndmonnam());
202 		} else {
203 			if (stale_egg(otmp) || otmp->corpsenm == NON_PM) {
204 				pline("The egg doesn't make much noise at all.");
205 			} else {
206 				pline("You listen to the egg and guess... %s?",mons[otmp->corpsenm].mname);
207 				learn_egg_type(otmp->corpsenm);
208 			}
209 		}
210 		return TRUE;
211 	}
212 
213 	/* using a stethoscope on a safe?  You safe-cracker, you. */
214 	if ((otmp = sobj_at(IRON_SAFE,rx,ry))) {
215 		pick_lock(tobj,rx,ry,FALSE);
216 		return TRUE;
217 	}
218 
219 	return FALSE;
220 }
221 
222 static const char hollow_str[] = "a hollow sound.  This must be a secret %s!";
223 
224 /* Strictly speaking it makes no sense for usage of a stethoscope to
225    not take any time; however, unless it did, the stethoscope would be
226    almost useless.  As a compromise, one use per turn is free, another
227    uses up the turn; this makes curse status have a tangible effect. */
228 STATIC_OVL int
use_stethoscope(obj)229 use_stethoscope(obj)
230 	register struct obj *obj;
231 {
232 	static long last_used_move = -1;
233 	static short last_used_movement = 0;
234 	struct monst *mtmp;
235 	struct rm *lev;
236 	int rx, ry, res;
237 	boolean interference = (u.uswallow && is_whirly(u.ustuck->data) &&
238 				!rn2(Role_if(PM_HEALER) ? 10 : 3));
239 
240 	if (nohands(youmonst.data)) {	/* should also check for no ears and/or deaf */
241 		You("have no hands!");	/* not `body_part(HAND)' */
242 		return 0;
243 	} else if (!freehand()) {
244 		You("have no free %s.", body_part(HAND));
245 		return 0;
246 	}
247 	if (!getdir((char *)0)) return 0;
248 
249 	res = (moves == last_used_move) &&
250 	      (youmonst.movement == last_used_movement);
251 	last_used_move = moves;
252 	last_used_movement = youmonst.movement;
253 
254 #ifdef STEED
255 	if (u.usteed && u.dz > 0) {
256 		if (interference) {
257 			pline("%s interferes.", Monnam(u.ustuck));
258 			mstatusline(u.ustuck);
259 		} else
260 			mstatusline(u.usteed);
261 		return res;
262 	} else
263 #endif
264 	if (u.uswallow && (u.dx || u.dy || u.dz)) {
265 		mstatusline(u.ustuck);
266 		return res;
267 	} else if (u.uswallow && interference) {
268 		pline("%s interferes.", Monnam(u.ustuck));
269 		mstatusline(u.ustuck);
270 		return res;
271 	} else if (u.dz) {
272 		if (Underwater)
273 		    You_hear("faint splashing.");
274 		else if (u.dz < 0 || !can_reach_floor())
275 		    You_cant("reach the %s.",
276 			(u.dz > 0) ? surface(u.ux,u.uy) : ceiling(u.ux,u.uy));
277 		else if (its_dead(u.ux, u.uy, &res, obj))
278 		    ;	/* message already given */
279 		else if (Is_stronghold(&u.uz))
280 		    You_hear("the crackling of hellfire.");
281 		else
282 		    pline_The("%s seems healthy enough.", surface(u.ux,u.uy));
283 		return res;
284 	} else if (obj->cursed && !rn2(2)) {
285 		You_hear("your heart beat.");
286 		return res;
287 	}
288 	if (Stunned || (Confusion && !rn2(5))) confdir();
289 	if (!u.dx && !u.dy) {
290 		ustatusline();
291 		return res;
292 	}
293 	rx = u.ux + u.dx; ry = u.uy + u.dy;
294 	if (!isok(rx,ry)) {
295 		You_hear("a faint typing noise.");
296 		return 0;
297 	}
298 	if ((mtmp = m_at(rx,ry)) != 0) {
299 		mstatusline(mtmp);
300 		if (mtmp->mundetected) {
301 			mtmp->mundetected = 0;
302 			if (cansee(rx,ry)) newsym(mtmp->mx,mtmp->my);
303 		}
304 		/* workaround for Heisenberg's code */
305 		if (!canspotmon(mtmp) && mtmp->data != &mons[PM_QUANTUM_MECHANIC])
306 			map_invisible(rx,ry);
307 		return res;
308 	}
309 	if (glyph_is_invisible(levl[rx][ry].glyph)) {
310 		unmap_object(rx, ry);
311 		newsym(rx, ry);
312 		pline_The("invisible monster must have moved.");
313 	}
314 	lev = &levl[rx][ry];
315 	switch(lev->typ) {
316 	case SDOOR:
317 		You_hear(hollow_str, "door");
318 		cvt_sdoor_to_door(lev);		/* ->typ = DOOR */
319 		if (Blind) feel_location(rx,ry);
320 		else newsym(rx,ry);
321 		return res;
322 	case SCORR:
323 		You_hear(hollow_str, "passage");
324 		lev->typ = CORR;
325 		unblock_point(rx,ry);
326 		if (Blind) feel_location(rx,ry);
327 		else newsym(rx,ry);
328 		return res;
329 	}
330 
331 	if (!its_dead(rx, ry, &res, obj))
332 	    You("hear nothing special.");	/* not You_hear()  */
333 	return res;
334 }
335 
336 static const char whistle_str[] = "produce a %s whistling sound.";
337 
338 STATIC_OVL void
use_whistle(obj)339 use_whistle(obj)
340 struct obj *obj;
341 {
342 	You(whistle_str, obj->cursed ? "shrill" : "high");
343 	wake_nearby();
344 }
345 
346 STATIC_OVL void
use_magic_whistle(obj)347 use_magic_whistle(obj)
348 struct obj *obj;
349 {
350 	register struct monst *mtmp, *nextmon;
351 
352 	if(obj->cursed && !rn2(2)) {
353 		You("produce a high-pitched humming noise.");
354 		wake_nearby();
355 	} else {
356 		int pet_cnt = 0;
357 		You(whistle_str, Hallucination ? "normal" : "strange");
358 		for(mtmp = fmon; mtmp; mtmp = nextmon) {
359 		    nextmon = mtmp->nmon; /* trap might kill mon */
360 		    if (DEADMONSTER(mtmp)) continue;
361 		    if (mtmp->mtame) {
362 			if (mtmp->mtrapped) {
363 			    /* no longer in previous trap (affects mintrap) */
364 			    mtmp->mtrapped = 0;
365 			    fill_pit(mtmp->mx, mtmp->my);
366 			}
367 			mnexto(mtmp);
368 			if (canspotmon(mtmp)) ++pet_cnt;
369 			if (mintrap(mtmp) == 2) change_luck(-1);
370 		    }
371 		}
372 		if (pet_cnt > 0) makeknown(obj->otyp);
373 	}
374 }
375 
376 boolean
um_dist(x,y,n)377 um_dist(x,y,n)
378 register xchar x, y, n;
379 {
380 	return((boolean)(abs(u.ux - x) > n  || abs(u.uy - y) > n));
381 }
382 
383 int
number_leashed()384 number_leashed()
385 {
386 	register int i = 0;
387 	register struct obj *obj;
388 
389 	for(obj = invent; obj; obj = obj->nobj)
390 		if(obj->otyp == LEASH && obj->leashmon != 0) i++;
391 	return(i);
392 }
393 
394 void
o_unleash(otmp)395 o_unleash(otmp)		/* otmp is about to be destroyed or stolen */
396 register struct obj *otmp;
397 {
398 	register struct monst *mtmp;
399 
400 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
401 		if(mtmp->m_id == (unsigned)otmp->leashmon)
402 			mtmp->mleashed = 0;
403 	otmp->leashmon = 0;
404 }
405 
406 void
m_unleash(mtmp,feedback)407 m_unleash(mtmp, feedback)	/* mtmp is about to die, or become untame */
408 register struct monst *mtmp;
409 boolean feedback;
410 {
411 	register struct obj *otmp;
412 
413 	if (feedback) {
414 	    if (canseemon(mtmp))
415 		pline("%s pulls free of %s leash!", Monnam(mtmp), mhis(mtmp));
416 	    else
417 		Your("leash falls slack.");
418 	}
419 	for(otmp = invent; otmp; otmp = otmp->nobj)
420 		if(otmp->otyp == LEASH &&
421 				otmp->leashmon == (int)mtmp->m_id)
422 			otmp->leashmon = 0;
423 	mtmp->mleashed = 0;
424 }
425 
426 void
unleash_all()427 unleash_all()		/* player is about to die (for bones) */
428 {
429 	register struct obj *otmp;
430 	register struct monst *mtmp;
431 
432 	for(otmp = invent; otmp; otmp = otmp->nobj)
433 		if(otmp->otyp == LEASH) otmp->leashmon = 0;
434 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
435 		mtmp->mleashed = 0;
436 }
437 
438 #define MAXLEASHED	2
439 
440 /* ARGSUSED */
441 STATIC_OVL void
use_leash(obj)442 use_leash(obj)
443 struct obj *obj;
444 {
445 	coord cc;
446 	register struct monst *mtmp;
447 	int spotmon;
448 
449 	if(!obj->leashmon && number_leashed() >= MAXLEASHED) {
450 		You("cannot leash any more pets.");
451 		return;
452 	}
453 
454 	if(!get_adjacent_loc((char *)0, (char *)0, u.ux, u.uy, &cc)) return;
455 
456 	if((cc.x == u.ux) && (cc.y == u.uy)) {
457 #ifdef STEED
458 		if (u.usteed && u.dz > 0) {
459 		    mtmp = u.usteed;
460 		    spotmon = 1;
461 		    goto got_target;
462 		}
463 #endif
464 		pline("Leash yourself?  Very funny...");
465 		return;
466 	}
467 
468 	if(!(mtmp = m_at(cc.x, cc.y))) {
469 		There("is no creature there.");
470 		return;
471 	}
472 
473 	spotmon = canspotmon(mtmp);
474 #ifdef STEED
475  got_target:
476 #endif
477 
478 	if(!mtmp->mtame) {
479 	    if(!spotmon)
480 		There("is no creature there.");
481 	    else
482 		pline("%s %s leashed!", Monnam(mtmp), (!obj->leashmon) ?
483 				"cannot be" : "is not");
484 	    return;
485 	}
486 	if(!obj->leashmon) {
487 		if(mtmp->mleashed) {
488 			pline("This %s is already leashed.",
489 			      spotmon ? l_monnam(mtmp) : "monster");
490 			return;
491 		}
492 		You("slip the leash around %s%s.",
493 		    spotmon ? "your " : "", l_monnam(mtmp));
494 		mtmp->mleashed = 1;
495 		obj->leashmon = (int)mtmp->m_id;
496 		mtmp->msleeping = 0;
497 		return;
498 	}
499 	if(obj->leashmon != (int)mtmp->m_id) {
500 		pline("This leash is not attached to that creature.");
501 		return;
502 	} else {
503 		if(obj->cursed) {
504 			pline_The("leash would not come off!");
505 			obj->bknown = TRUE;
506 			return;
507 		}
508 		mtmp->mleashed = 0;
509 		obj->leashmon = 0;
510 		You("remove the leash from %s%s.",
511 		    spotmon ? "your " : "", l_monnam(mtmp));
512 	}
513 	return;
514 }
515 
516 struct obj *
get_mleash(mtmp)517 get_mleash(mtmp)	/* assuming mtmp->mleashed has been checked */
518 register struct monst *mtmp;
519 {
520 	register struct obj *otmp;
521 
522 	otmp = invent;
523 	while(otmp) {
524 		if(otmp->otyp == LEASH && otmp->leashmon == (int)mtmp->m_id)
525 			return(otmp);
526 		otmp = otmp->nobj;
527 	}
528 	return((struct obj *)0);
529 }
530 
531 boolean
next_to_u()532 next_to_u()
533 {
534 	register struct monst *mtmp;
535 	register struct obj *otmp;
536 
537 	for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
538 		if (DEADMONSTER(mtmp)) continue;
539 		if(mtmp->mleashed) {
540 			if (distu(mtmp->mx,mtmp->my) > 2) mnexto(mtmp);
541 			if (distu(mtmp->mx,mtmp->my) > 2) {
542 			    for(otmp = invent; otmp; otmp = otmp->nobj)
543 				if(otmp->otyp == LEASH &&
544 					otmp->leashmon == (int)mtmp->m_id) {
545 				    if(otmp->cursed) return(FALSE);
546 				    You_feel("%s leash go slack.",
547 					(number_leashed() > 1) ? "a" : "the");
548 				    mtmp->mleashed = 0;
549 				    otmp->leashmon = 0;
550 				}
551 			}
552 		}
553 	}
554 #ifdef STEED
555 	/* no pack mules for the Amulet */
556 	if (u.usteed && mon_has_amulet(u.usteed)) return FALSE;
557 #endif
558 	return(TRUE);
559 }
560 
561 void
check_leash(x,y)562 check_leash(x, y)
563 register xchar x, y;
564 {
565 	register struct obj *otmp;
566 	register struct monst *mtmp;
567 
568 	for (otmp = invent; otmp; otmp = otmp->nobj) {
569 	    if (otmp->otyp != LEASH || otmp->leashmon == 0) continue;
570 	    for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
571 		if (DEADMONSTER(mtmp)) continue;
572 		if ((int)mtmp->m_id == otmp->leashmon) break;
573 	    }
574 	    if (!mtmp) {
575 		impossible("leash in use isn't attached to anything?");
576 		otmp->leashmon = 0;
577 		continue;
578 	    }
579 	    if (dist2(u.ux,u.uy,mtmp->mx,mtmp->my) >
580 		    dist2(x,y,mtmp->mx,mtmp->my)) {
581 		if (!um_dist(mtmp->mx, mtmp->my, 3)) {
582 		    ;	/* still close enough */
583 		} else if (otmp->cursed && !breathless(mtmp->data)) {
584 		    if (um_dist(mtmp->mx, mtmp->my, 5) ||
585 			    (mtmp->mhp -= rnd(2)) <= 0) {
586 			long save_pacifism = u.uconduct.killer;
587 
588 			Your("leash chokes %s to death!", mon_nam(mtmp));
589 			/* hero might not have intended to kill pet, but
590 			   that's the result of his actions; gain experience,
591 			   lose pacifism, take alignment and luck hit, make
592 			   corpse less likely to remain tame after revival */
593 			xkilled(mtmp, 0);	/* no "you kill it" message */
594 			/* life-saving doesn't ordinarily reset this */
595 			if (mtmp->mhp > 0) u.uconduct.killer = save_pacifism;
596 		    } else {
597 			pline("%s chokes on the leash!", Monnam(mtmp));
598 			/* tameness eventually drops to 1 here (never 0) */
599 			if (mtmp->mtame && rn2(mtmp->mtame)) mtmp->mtame--;
600 		    }
601 		} else {
602 		    if (um_dist(mtmp->mx, mtmp->my, 5)) {
603 			pline("%s leash snaps loose!", s_suffix(Monnam(mtmp)));
604 			m_unleash(mtmp, FALSE);
605 		    } else {
606 			You("pull on the leash.");
607 			if (mtmp->data->msound != MS_SILENT)
608 			    switch (rn2(3)) {
609 			    case 0:  growl(mtmp);   break;
610 			    case 1:  yelp(mtmp);    break;
611 			    default: whimper(mtmp); break;
612 			    }
613 		    }
614 		}
615 	    }
616 	}
617 }
618 
619 #define WEAK	3	/* from eat.c */
620 
621 static const char look_str[] = "look %s.";
622 
623 STATIC_OVL int
use_mirror(obj)624 use_mirror(obj)
625 struct obj *obj;
626 {
627 	register struct monst *mtmp;
628 	register char mlet;
629 	boolean vis;
630 
631 	if(!getdir((char *)0)) return 0;
632 	if(obj->cursed && !rn2(2)) {
633 		if (!Blind)
634 			pline_The("mirror fogs up and doesn't reflect!");
635 		return 1;
636 	}
637 	if(!u.dx && !u.dy && !u.dz) {
638 		if(!Blind && !Invisible) {
639 		    if (u.umonnum == PM_FLOATING_EYE) {
640 			if (!Free_action) {
641 			pline("%s", Hallucination ?
642 			      "Yow!  The mirror stares back!" :
643 			      "Yikes!  You've frozen yourself!");
644 			nomul(-rnd((MAXULEV+6) - u.ulevel), "gazing into a mirror");
645 			} else You("stiffen momentarily under your gaze.");
646 		    } else if (is_vampire(youmonst.data))
647 			You("don't have a reflection.");
648 		    else if (u.umonnum == PM_UMBER_HULK) {
649 			pline("Huh?  That doesn't look like you!");
650 			make_confused(HConfusion + d(3,4),FALSE);
651 		    } else if (Hallucination)
652 			You(look_str, hcolor((char *)0));
653 		    else if (Sick)
654 			You(look_str, "peaked");
655 		    else if (u.uhs >= WEAK)
656 			You(look_str, "undernourished");
657 		    else You("look as %s as ever.",
658 				beautiful());
659 		} else {
660 			You_cant("see your %s %s.",
661 				beautiful(),
662 				body_part(FACE));
663 		}
664 		return 1;
665 	}
666 	if(u.uswallow) {
667 		if (!Blind) You("reflect %s %s.", s_suffix(mon_nam(u.ustuck)),
668 		    mbodypart(u.ustuck, STOMACH));
669 		return 1;
670 	}
671 	if(Underwater) {
672 		You(Hallucination ?
673 		    "give the fish a chance to fix their makeup." :
674 		    "reflect the murky water.");
675 		return 1;
676 	}
677 	if(u.dz) {
678 		if (!Blind)
679 		    You("reflect the %s.",
680 			(u.dz > 0) ? surface(u.ux,u.uy) : ceiling(u.ux,u.uy));
681 		return 1;
682 	}
683 	mtmp = bhit(u.dx, u.dy, COLNO, INVIS_BEAM,
684 		    (int FDECL((*),(MONST_P,OBJ_P)))0,
685 		    (int FDECL((*),(OBJ_P,OBJ_P)))0,
686 		    obj, NULL);
687 	if (!mtmp || !haseyes(mtmp->data))
688 		return 1;
689 
690 	vis = canseemon(mtmp);
691 	mlet = mtmp->data->mlet;
692 	if (mtmp->msleeping) {
693 		if (vis)
694 		    pline ("%s is too tired to look at your mirror.",
695 			    Monnam(mtmp));
696 	} else if (!mtmp->mcansee) {
697 	    if (vis)
698 		pline("%s can't see anything right now.", Monnam(mtmp));
699 	/* some monsters do special things */
700 	} else if (is_vampire(mtmp->data) || mlet == S_GHOST) {
701 	    if (vis)
702 		pline ("%s doesn't have a reflection.", Monnam(mtmp));
703 	} else if(!mtmp->mcan && !mtmp->minvis &&
704 					mtmp->data == &mons[PM_MEDUSA]) {
705 		if (mon_reflects(mtmp, "The gaze is reflected away by %s %s!"))
706 			return 1;
707 		if (vis)
708 			pline("%s is turned to stone!", Monnam(mtmp));
709 		stoned = TRUE;
710 		killed(mtmp);
711 	} else if(!mtmp->mcan && !mtmp->minvis &&
712 					mtmp->data == &mons[PM_FLOATING_EYE]) {
713 		int tmp = d((int)mtmp->m_lev, (int)mtmp->data->mattk[0].damd);
714 		if (!rn2(4)) tmp = 120;
715 		if (vis)
716 			pline("%s is frozen by its reflection.", Monnam(mtmp));
717 		else You_hear("%s stop moving.",something);
718 		mtmp->mcanmove = 0;
719 		if ( (int) mtmp->mfrozen + tmp > 127)
720 			mtmp->mfrozen = 127;
721 		else mtmp->mfrozen += tmp;
722 	} else if(!mtmp->mcan && !mtmp->minvis &&
723 		mtmp->data == &mons[PM_EVIL_EYE]) {
724 	    if (vis) {
725 		pline("%s sees its own glare in your mirror.",
726 			Monnam(mtmp));
727 		pline("%s is cancelled!", Monnam(mtmp));
728 	    }
729 	    mtmp->mcan = 1;
730 	    monflee(mtmp, 0, FALSE, TRUE);
731 	} else if(!mtmp->mcan && !mtmp->minvis &&
732 					mtmp->data == &mons[PM_UMBER_HULK]) {
733 		if (vis)
734 			pline ("%s confuses itself!", Monnam(mtmp));
735 		mtmp->mconf = 1;
736 	} else if(!mtmp->mcan && !mtmp->minvis && (mlet == S_NYMPH
737 				     || mtmp->data==&mons[PM_SUCCUBUS])) {
738 		if (vis) {
739 		    pline ("%s admires herself in your mirror.", Monnam(mtmp));
740 		    pline ("She takes it!");
741 		} else pline ("It steals your mirror!");
742 		setnotworn(obj); /* in case mirror was wielded */
743 		freeinv(obj);
744 		(void) mpickobj(mtmp,obj);
745 		if (!tele_restrict(mtmp)) (void) rloc(mtmp, FALSE);
746 	} else if(!mtmp->mcan && !mtmp->minvis && is_weeping(mtmp->data)) {
747 		if (vis)
748 			pline ("%s stares at its reflection with a stony expression.", Monnam(mtmp));
749 			mtmp->mcanmove = 0;
750 			mtmp->mfrozen = 1;
751 	} else if (!is_unicorn(mtmp->data) && !humanoid(mtmp->data) &&
752 			(!mtmp->minvis || perceives(mtmp->data)) && rn2(5)) {
753 		if (vis)
754 		    pline("%s is frightened by its reflection.", Monnam(mtmp));
755 		monflee(mtmp, d(2,4), FALSE, FALSE);
756 	} else if (!Blind) {
757 		if (mtmp->minvis && !See_invisible)
758 		    ;
759 		else if ((mtmp->minvis && !perceives(mtmp->data))
760 			 || !haseyes(mtmp->data))
761 		    pline("%s doesn't seem to notice its reflection.",
762 			Monnam(mtmp));
763 		else
764 		    pline("%s ignores %s reflection.",
765 			  Monnam(mtmp), mhis(mtmp));
766 	}
767 	return 1;
768 }
769 
770 STATIC_OVL void
use_bell(optr)771 use_bell(optr)
772 struct obj **optr;
773 {
774 	register struct obj *obj = *optr;
775 	struct monst *mtmp;
776 	boolean wakem = FALSE, learno = FALSE,
777 		ordinary = (obj->otyp != BELL_OF_OPENING || !obj->spe),
778 		invoking = (obj->otyp == BELL_OF_OPENING &&
779 			 invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy));
780 
781 	You("ring %s.", the(xname(obj)));
782 
783 	if (Underwater || (u.uswallow && ordinary)) {
784 #ifdef	AMIGA
785 	    amii_speaker( obj, "AhDhGqEqDhEhAqDqFhGw", AMII_MUFFLED_VOLUME );
786 #endif
787 	    pline("But the sound is muffled.");
788 
789 	} else if (invoking && ordinary) {
790 	    /* needs to be recharged... */
791 	    pline("But it makes no sound.");
792 	    learno = TRUE;	/* help player figure out why */
793 
794 	} else if (ordinary) {
795 #ifdef	AMIGA
796 	    amii_speaker( obj, "ahdhgqeqdhehaqdqfhgw", AMII_MUFFLED_VOLUME );
797 #endif
798 	    if (obj->cursed && !rn2(4) &&
799 		    /* note: once any of them are gone, we stop all of them */
800 		    !(mvitals[PM_WOOD_NYMPH].mvflags & G_GONE) &&
801 		    !(mvitals[PM_WATER_NYMPH].mvflags & G_GONE) &&
802 		    !(mvitals[PM_MOUNTAIN_NYMPH].mvflags & G_GONE) &&
803 		    (mtmp = makemon(mkclass(S_NYMPH, 0),
804 					u.ux, u.uy, NO_MINVENT)) != 0) {
805 		You("summon %s!", a_monnam(mtmp));
806 		if (!obj_resists(obj, 93, 100)) {
807 		    pline("%s shattered!", Tobjnam(obj, "have"));
808 		    useup(obj);
809 		    *optr = 0;
810 		} else switch (rn2(3)) {
811 			default:
812 				break;
813 			case 1:
814 				mon_adjust_speed(mtmp, 2, (struct obj *)0);
815 				break;
816 			case 2: /* no explanation; it just happens... */
817 				nomovemsg = "";
818 				nomul(-rnd(2), 0);
819 				break;
820 		}
821 	    }
822 	    wakem = TRUE;
823 
824 	} else {
825 	    /* charged Bell of Opening */
826 	    consume_obj_charge(obj, TRUE);
827 
828 	    if (u.uswallow) {
829 		if (!obj->cursed)
830 		    (void) openit();
831 		else
832 		    pline("%s", nothing_happens);
833 
834 	    } else if (obj->cursed) {
835 		coord mm;
836 
837 		mm.x = u.ux;
838 		mm.y = u.uy;
839 		mkundead(&mm, FALSE, NO_MINVENT);
840 		wakem = TRUE;
841 
842 	    } else  if (invoking) {
843 		pline("%s an unsettling shrill sound...",
844 		      Tobjnam(obj, "issue"));
845 #ifdef	AMIGA
846 		amii_speaker( obj, "aefeaefeaefeaefeaefe", AMII_LOUDER_VOLUME );
847 #endif
848 		obj->age = moves;
849 		learno = TRUE;
850 		wakem = TRUE;
851 
852 	    } else if (obj->blessed) {
853 		int res = 0;
854 
855 #ifdef	AMIGA
856 		amii_speaker( obj, "ahahahDhEhCw", AMII_SOFT_VOLUME );
857 #endif
858 		if (uchain) {
859 		    unpunish();
860 		    res = 1;
861 		}
862 		res += openit();
863 		switch (res) {
864 		  case 0:  pline("%s", nothing_happens); break;
865 		  case 1:  pline("%s opens...", Something);
866 			   learno = TRUE; break;
867 		  default: pline("Things open around you...");
868 			   learno = TRUE; break;
869 		}
870 
871 	    } else {  /* uncursed */
872 #ifdef	AMIGA
873 		amii_speaker( obj, "AeFeaeFeAefegw", AMII_OKAY_VOLUME );
874 #endif
875 		if (findit() != 0) learno = TRUE;
876 		else pline("%s", nothing_happens);
877 	    }
878 
879 	}	/* charged BofO */
880 
881 	if (learno) {
882 	    makeknown(BELL_OF_OPENING);
883 	    obj->known = 1;
884 	}
885 	if (wakem) wake_nearby();
886 }
887 
888 STATIC_OVL void
use_candelabrum(obj)889 use_candelabrum(obj)
890 register struct obj *obj;
891 {
892 	const char *s = (obj->spe != 1) ? "candles" : "candle";
893 
894 	if(Underwater) {
895 		You("cannot make fire under water.");
896 		return;
897 	}
898 	if(obj->lamplit) {
899 		You("snuff the %s.", s);
900 		end_burn(obj, TRUE);
901 		return;
902 	}
903 	if(obj->spe <= 0) {
904 		pline("This %s has no %s.", xname(obj), s);
905 		return;
906 	}
907 	if(u.uswallow || obj->cursed) {
908 		if (!Blind)
909 		    pline_The("%s %s for a moment, then %s.",
910 			      s, vtense(s, "flicker"), vtense(s, "die"));
911 		return;
912 	}
913 	if(obj->spe < 7) {
914 		There("%s only %d %s in %s.",
915 		      vtense(s, "are"), obj->spe, s, the(xname(obj)));
916 		if (!Blind)
917 		    pline("%s lit.  %s dimly.",
918 			  obj->spe == 1 ? "It is" : "They are",
919 			  Tobjnam(obj, "shine"));
920 	} else {
921 		pline("%s's %s burn%s", The(xname(obj)), s,
922 			(Blind ? "." : " brightly!"));
923 	}
924 	if (!invocation_pos(u.ux, u.uy)) {
925 		pline_The("%s %s being rapidly consumed!", s, vtense(s, "are"));
926 		obj->age /= 2;
927 		/* Fix for bug C343-424 "Unlit candelabrum becomes unlightable
928 		 *  if candles have exactly one turn of fuel left and it was
929 		 *  applied in the wrong location.".
930 		 * begin_burn() won't consume a candle when its age (i.e. its
931 		 * remaining turns) is 0.  Setting its age to 1 will consume it
932 		 * at the next call of begin_burn(). */
933 		if (obj->age == 0) {
934 			obj->age = 1;
935 		}
936 	} else {
937 		if(obj->spe == 7) {
938 		    if (Blind)
939 		      pline("%s a strange warmth!", Tobjnam(obj, "radiate"));
940 		    else
941 		      pline("%s with a strange light!", Tobjnam(obj, "glow"));
942 		}
943 		obj->known = 1;
944 	}
945 	begin_burn(obj, FALSE);
946 }
947 
948 STATIC_OVL void
use_candle(optr)949 use_candle(optr)
950 struct obj **optr;
951 {
952 	register struct obj *obj = *optr;
953 	register struct obj *otmp;
954 	const char *s = (obj->quan != 1) ? "candles" : "candle";
955 	char qbuf[QBUFSZ];
956 
957 	if(u.uswallow) {
958 		You(no_elbow_room);
959 		return;
960 	}
961 	if(Underwater) {
962 		pline("Sorry, fire and water don't mix.");
963 		return;
964 	}
965 
966 	otmp = carrying(CANDELABRUM_OF_INVOCATION);
967 	if(!otmp || otmp->spe == 7) {
968 		use_lamp(obj);
969 		return;
970 	}
971 
972 	Sprintf(qbuf, "Attach %s", the(xname(obj)));
973 	Sprintf(eos(qbuf), " to %s?",
974 		safe_qbuf(qbuf, sizeof(" to ?"), the(xname(otmp)),
975 			the(simple_typename(otmp->otyp)), "it"));
976 	if(yn(qbuf) == 'n') {
977 		if (!obj->lamplit)
978 		    You("try to light %s...", the(xname(obj)));
979 		use_lamp(obj);
980 		return;
981 	} else {
982 		if ((long)otmp->spe + obj->quan > 7L)
983 		    obj = splitobj(obj, 7L - (long)otmp->spe);
984 		else *optr = 0;
985 		You("attach %ld%s %s to %s.",
986 		    obj->quan, !otmp->spe ? "" : " more",
987 		    s, the(xname(otmp)));
988 		if (!otmp->spe || otmp->age > obj->age)
989 		    otmp->age = obj->age;
990 		otmp->spe += (int)obj->quan;
991 		if (otmp->lamplit && !obj->lamplit)
992 		    pline_The("new %s magically %s!", s, vtense(s, "ignite"));
993 		else if (!otmp->lamplit && obj->lamplit)
994 		    pline("%s out.", (obj->quan > 1L) ? "They go" : "It goes");
995 		if (obj->unpaid)
996 		    verbalize("You %s %s, you bought %s!",
997 			      otmp->lamplit ? "burn" : "use",
998 			      (obj->quan > 1L) ? "them" : "it",
999 			      (obj->quan > 1L) ? "them" : "it");
1000 		if (obj->quan < 7L && otmp->spe == 7)
1001 		    pline("%s now has seven%s candles attached.",
1002 			  The(xname(otmp)), otmp->lamplit ? " lit" : "");
1003 		/* candelabrum's light range might increase */
1004 		if (otmp->lamplit) obj_merge_light_sources(otmp, otmp);
1005 		/* candles are no longer a separate light source */
1006 		if (obj->lamplit) end_burn(obj, TRUE);
1007 		/* candles are now gone */
1008 		useupall(obj);
1009 	}
1010 }
1011 
1012 boolean
snuff_candle(otmp)1013 snuff_candle(otmp)  /* call in drop, throw, and put in box, etc. */
1014 register struct obj *otmp;
1015 {
1016 	register boolean candle = Is_candle(otmp);
1017 
1018 	if ((candle || otmp->otyp == CANDELABRUM_OF_INVOCATION) &&
1019 		otmp->lamplit) {
1020 	    char buf[BUFSZ];
1021 	    xchar x, y;
1022 	    register boolean many = candle ? otmp->quan > 1L : otmp->spe > 1;
1023 
1024 	    (void) get_obj_location(otmp, &x, &y, 0);
1025 	    if (otmp->where == OBJ_MINVENT ? cansee(x,y) : !Blind)
1026 		pline("%s %scandle%s flame%s extinguished.",
1027 		      Shk_Your(buf, otmp),
1028 		      (candle ? "" : "candelabrum's "),
1029 		      (many ? "s'" : "'s"), (many ? "s are" : " is"));
1030 	   end_burn(otmp, TRUE);
1031 	   return(TRUE);
1032 	}
1033 	return(FALSE);
1034 }
1035 
1036 /* called when lit lamp is hit by water or put into a container or
1037    you've been swallowed by a monster; obj might be in transit while
1038    being thrown or dropped so don't assume that its location is valid */
1039 boolean
snuff_lit(obj)1040 snuff_lit(obj)
1041 struct obj *obj;
1042 {
1043 	xchar x, y;
1044 
1045 	if (obj->lamplit) {
1046 	    if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
1047 		    obj->otyp == BRASS_LANTERN || obj->otyp == POT_OIL) {
1048 		(void) get_obj_location(obj, &x, &y, 0);
1049 		if (obj->where == OBJ_MINVENT ? cansee(x,y) : !Blind)
1050 		    pline("%s %s out!", Yname2(obj), otense(obj, "go"));
1051 		end_burn(obj, TRUE);
1052 		return TRUE;
1053 	    }
1054 	    if (snuff_candle(obj)) return TRUE;
1055 	}
1056 	return FALSE;
1057 }
1058 
1059 /* Called when potentially lightable object is affected by fire_damage().
1060    Return TRUE if object was lit and FALSE otherwise --ALI */
1061 boolean
catch_lit(obj)1062 catch_lit(obj)
1063 struct obj *obj;
1064 {
1065 	xchar x, y;
1066 
1067 	if (!obj->lamplit && (obj->otyp == MAGIC_LAMP || ignitable(obj))) {
1068 	    if ((obj->otyp == MAGIC_LAMP ||
1069 		 obj->otyp == CANDELABRUM_OF_INVOCATION) &&
1070 		obj->spe == 0)
1071 		return FALSE;
1072 	    else if (obj->otyp != MAGIC_LAMP && obj->age == 0)
1073 		return FALSE;
1074 	    if (!get_obj_location(obj, &x, &y, 0))
1075 		return FALSE;
1076 	    if (obj->otyp == CANDELABRUM_OF_INVOCATION && obj->cursed)
1077 		return FALSE;
1078 	    if ((obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
1079 		 obj->otyp == BRASS_LANTERN) && obj->cursed && !rn2(2))
1080 		return FALSE;
1081 	    if (obj->where == OBJ_MINVENT ? cansee(x,y) : !Blind)
1082 		pline("%s %s light!", Yname2(obj), otense(obj, "catch"));
1083 	    if (obj->otyp == POT_OIL) makeknown(obj->otyp);
1084 	    if (obj->unpaid && costly_spot(u.ux, u.uy) && (obj->where == OBJ_INVENT)) {
1085 	        /* if it catches while you have it, then it's your tough luck */
1086 		check_unpaid(obj);
1087 	        verbalize("That's in addition to the cost of %s %s, of course.",
1088 				Yname2(obj), obj->quan == 1 ? "itself" : "themselves");
1089 		bill_dummy_object(obj);
1090 	    }
1091 	    begin_burn(obj, FALSE);
1092 	    return TRUE;
1093 	}
1094 	return FALSE;
1095 }
1096 
1097 STATIC_OVL void
use_lamp(obj)1098 use_lamp(obj)
1099 struct obj *obj;
1100 {
1101 	char buf[BUFSZ];
1102 
1103 	if(Underwater) {
1104 		pline("This is not a diving lamp.");
1105 		return;
1106 	}
1107 	if(obj->lamplit) {
1108 		if(obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
1109 				obj->otyp == BRASS_LANTERN)
1110 		    pline("%s lamp is now off.", Shk_Your(buf, obj));
1111 		else
1112 		    You("snuff out %s.", yname(obj));
1113 		end_burn(obj, TRUE);
1114 		return;
1115 	}
1116 	/* magic lamps with an spe == 0 (wished for) cannot be lit */
1117 	if ((!Is_candle(obj) && obj->age == 0)
1118 			|| (obj->otyp == MAGIC_LAMP && obj->spe == 0)) {
1119 		if (obj->otyp == BRASS_LANTERN)
1120 			Your("lamp has run out of power.");
1121 		else pline("This %s has no oil.", xname(obj));
1122 		return;
1123 	}
1124 	if (obj->cursed && !rn2(2)) {
1125 		pline("%s for a moment, then %s.",
1126 		      Tobjnam(obj, "flicker"), otense(obj, "die"));
1127 	} else {
1128 		if(obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
1129 				obj->otyp == BRASS_LANTERN) {
1130 		    check_unpaid(obj);
1131 		    pline("%s lamp is now on.", Shk_Your(buf, obj));
1132 		} else {	/* candle(s) */
1133 		    pline("%s flame%s %s%s",
1134 			s_suffix(Yname2(obj)),
1135 			plur(obj->quan), otense(obj, "burn"),
1136 			Blind ? "." : " brightly!");
1137 		    if (obj->unpaid && costly_spot(u.ux, u.uy) &&
1138 			  obj->age == 20L * (long)objects[obj->otyp].oc_cost) {
1139 			const char *ithem = obj->quan > 1L ? "them" : "it";
1140 			verbalize("You burn %s, you bought %s!", ithem, ithem);
1141 			bill_dummy_object(obj);
1142 		    }
1143 		}
1144 		begin_burn(obj, FALSE);
1145 	}
1146 }
1147 
1148 STATIC_OVL void
light_cocktail(obj)1149 light_cocktail(obj)
1150 	struct obj *obj;	/* obj is a potion of oil */
1151 {
1152 	char buf[BUFSZ];
1153 
1154 	if (u.uswallow) {
1155 	    You(no_elbow_room);
1156 	    return;
1157 	}
1158 
1159 	if (obj->lamplit) {
1160 	    You("snuff the lit potion.");
1161 	    end_burn(obj, TRUE);
1162 	    /*
1163 	     * Free & add to re-merge potion.  This will average the
1164 	     * age of the potions.  Not exactly the best solution,
1165 	     * but its easy.
1166 	     */
1167 	    freeinv(obj);
1168 	    (void) addinv(obj);
1169 	    return;
1170 	} else if (Underwater) {
1171 	    There("is not enough oxygen to sustain a fire.");
1172 	    return;
1173 	}
1174 
1175 	You("light %s potion.%s", shk_your(buf, obj),
1176 	    Blind ? "" : "  It gives off a dim light.");
1177 	if (obj->unpaid && costly_spot(u.ux, u.uy)) {
1178 	    /* Normally, we shouldn't both partially and fully charge
1179 	     * for an item, but (Yendorian Fuel) Taxes are inevitable...
1180 	     */
1181 	    check_unpaid(obj);
1182 	    verbalize("That's in addition to the cost of the potion, of course.");
1183 	    bill_dummy_object(obj);
1184 	}
1185 	makeknown(obj->otyp);
1186 
1187 	if (obj->quan > 1L) {
1188 	    obj = splitobj(obj, 1L);
1189 	    begin_burn(obj, FALSE);	/* burn before free to get position */
1190 	    obj_extract_self(obj);	/* free from inv */
1191 
1192 	    /* shouldn't merge */
1193 	    obj = hold_another_object(obj, "You drop %s!",
1194 				      doname(obj), (const char *)0);
1195 	} else
1196 	    begin_burn(obj, FALSE);
1197 }
1198 
1199 static NEARDATA const char cuddly[] = { TOOL_CLASS, GEM_CLASS, 0 };
1200 
1201 int
dorub()1202 dorub()
1203 {
1204 	struct obj *obj = getobj(cuddly, "rub");
1205 
1206 	if (obj && obj->oclass == GEM_CLASS) {
1207 	    if (is_graystone(obj)) {
1208 		use_stone(obj);
1209 		return 1;
1210 	    } else {
1211 		pline("Sorry, I don't know how to use that.");
1212 		return 0;
1213 	    }
1214 	}
1215 
1216 	if (!obj || !wield_tool(obj, "rub")) return 0;
1217 
1218 	/* now uwep is obj */
1219 	if (uwep->otyp == MAGIC_LAMP) {
1220 	    if (uwep->spe > 0 && !rn2(3)) {
1221 		check_unpaid_usage(uwep, TRUE);		/* unusual item use */
1222 		djinni_from_bottle(uwep);
1223 		makeknown(MAGIC_LAMP);
1224 		uwep->otyp = OIL_LAMP;
1225 		uwep->spe = 0; /* for safety */
1226 		uwep->age = rn1(500,1000);
1227 		if (uwep->lamplit) begin_burn(uwep, TRUE);
1228 		update_inventory();
1229 	    } else if (rn2(2) && !Blind)
1230 		You("see a puff of smoke.");
1231 	    else pline("%s", nothing_happens);
1232 	} else if (obj->otyp == BRASS_LANTERN) {
1233 	    /* message from Adventure */
1234 	    pline("Rubbing the electric lamp is not particularly rewarding.");
1235 	    pline("Anyway, nothing exciting happens.");
1236 	} else pline("%s", nothing_happens);
1237 	return 1;
1238 }
1239 
1240 int
dojump()1241 dojump()
1242 {
1243 	/* Physical jump */
1244 	return jump(0);
1245 }
1246 
1247 int
jump(magic)1248 jump(magic)
1249 int magic; /* 0=Physical, otherwise skill level */
1250 {
1251 	coord cc;
1252 
1253 	if (!magic && (nolimbs(youmonst.data) || slithy(youmonst.data))) {
1254 		/* normally (nolimbs || slithy) implies !Jumping,
1255 		   but that isn't necessarily the case for knights */
1256 		You_cant("jump; you have no legs!");
1257 		return 0;
1258 	} else if (!magic && !Jumping) {
1259 		You_cant("jump very far.");
1260 		return 0;
1261 	} else if (u.uswallow) {
1262 		if (magic) {
1263 			You("bounce around a little.");
1264 			return 1;
1265 		}
1266 		pline("You've got to be kidding!");
1267 		return 0;
1268 	} else if (u.uinwater) {
1269 		if (magic) {
1270 			You("swish around a little.");
1271 			return 1;
1272 		}
1273 		pline("This calls for swimming, not jumping!");
1274 		return 0;
1275 	} else if (u.ustuck) {
1276 		if (u.ustuck->mtame && !Conflict && !u.ustuck->mconf) {
1277 		    You("pull free from %s.", mon_nam(u.ustuck));
1278 		    u.ustuck = 0;
1279 		    return 1;
1280 		}
1281 		if (magic) {
1282 			You("writhe a little in the grasp of %s!", mon_nam(u.ustuck));
1283 			return 1;
1284 		}
1285 		You("cannot escape from %s!", mon_nam(u.ustuck));
1286 		return 0;
1287 	} else if (Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) {
1288 		if (magic) {
1289 			You("flail around a little.");
1290 			return 1;
1291 		}
1292 		You("don't have enough traction to jump.");
1293 		return 0;
1294 	} else if (!magic && near_capacity() > UNENCUMBERED) {
1295 		You("are carrying too much to jump!");
1296 		return 0;
1297 	} else if (!magic && (u.uhunger <= 100 || ACURR(A_STR) < 6)) {
1298 		You("lack the strength to jump!");
1299 		return 0;
1300 	} else if (Wounded_legs) {
1301 		long wl = (Wounded_legs & BOTH_SIDES);
1302 		const char *bp = body_part(LEG);
1303 
1304 		if (wl == BOTH_SIDES) bp = makeplural(bp);
1305 #ifdef STEED
1306 		if (u.usteed)
1307 		    pline("%s is in no shape for jumping.", Monnam(u.usteed));
1308 		else
1309 #endif
1310 		Your("%s%s %s in no shape for jumping.",
1311 		     (wl == LEFT_SIDE) ? "left " :
1312 			(wl == RIGHT_SIDE) ? "right " : "",
1313 		     bp, (wl == BOTH_SIDES) ? "are" : "is");
1314 		return 0;
1315 	}
1316 #ifdef STEED
1317 	else if (u.usteed && u.utrap) {
1318 		pline("%s is stuck in a trap.", Monnam(u.usteed));
1319 		return (0);
1320 	}
1321 #endif
1322 
1323 	pline("Where do you want to jump?");
1324 	cc.x = u.ux;
1325 	cc.y = u.uy;
1326 	if (getpos(&cc, TRUE, "the desired position") < 0)
1327 		return 0;	/* user pressed ESC */
1328 	if (!magic && !(HJumping & ~INTRINSIC) && !EJumping &&
1329 			distu(cc.x, cc.y) != 5) {
1330 		/* The Knight jumping restriction still applies when riding a
1331 		 * horse.  After all, what shape is the knight piece in chess?
1332 		 */
1333 		pline("Illegal move!");
1334 		return 0;
1335 	} else if (distu(cc.x, cc.y) > (magic ? 6+magic*3 : 9)) {
1336 		pline("Too far!");
1337 		return 0;
1338 	} else if (!cansee(cc.x, cc.y)) {
1339 		You("cannot see where to land!");
1340 		return 0;
1341 	} else if (!isok(cc.x, cc.y)) {
1342 		You("cannot jump there!");
1343 		return 0;
1344 	} else {
1345 	    coord uc;
1346 	    int range, temp;
1347 
1348 	    if(u.utrap)
1349 		switch(u.utraptype) {
1350 		case TT_BEARTRAP: {
1351 		    register long side = rn2(3) ? LEFT_SIDE : RIGHT_SIDE;
1352 		    You("rip yourself free of the bear trap!  Ouch!");
1353 		    losehp(rnd(10), "jumping out of a bear trap", KILLED_BY);
1354 		    set_wounded_legs(side, rn1(1000,500));
1355 		    break;
1356 		  }
1357 		case TT_PIT:
1358 		    You("leap from the pit!");
1359 		    break;
1360 		case TT_WEB:
1361 		    You("tear the web apart as you pull yourself free!");
1362 		    deltrap(t_at(u.ux,u.uy));
1363 		    break;
1364 		case TT_LAVA:
1365 		    You("pull yourself above the lava!");
1366 		    u.utrap = 0;
1367 		    return 1;
1368 		case TT_INFLOOR:
1369 		    You("strain your %s, but you're still stuck in the floor.",
1370 			makeplural(body_part(LEG)));
1371 		    set_wounded_legs(LEFT_SIDE, rn1(10, 11));
1372 		    set_wounded_legs(RIGHT_SIDE, rn1(10, 11));
1373 		    return 1;
1374 		}
1375 
1376 	    /*
1377 	     * Check the path from uc to cc, calling hurtle_step at each
1378 	     * location.  The final position actually reached will be
1379 	     * in cc.
1380 	     */
1381 	    uc.x = u.ux;
1382 	    uc.y = u.uy;
1383 	    /* calculate max(abs(dx), abs(dy)) as the range */
1384 	    range = cc.x - uc.x;
1385 	    if (range < 0) range = -range;
1386 	    temp = cc.y - uc.y;
1387 	    if (temp < 0) temp = -temp;
1388 	    if (range < temp)
1389 		range = temp;
1390 	    (void) walk_path(&uc, &cc, hurtle_step, (genericptr_t)&range);
1391 
1392 	    /* A little Sokoban guilt... */
1393 	    if (In_sokoban(&u.uz))
1394 		sokoban_trickster();
1395 
1396 	    teleds(cc.x, cc.y, TRUE);
1397 	    nomul(-1, "jumping around");
1398 	    nomovemsg = "";
1399 	    morehungry(rnd(25));
1400 	    return 1;
1401 	}
1402 }
1403 
1404 boolean
tinnable(corpse)1405 tinnable(corpse)
1406 struct obj *corpse;
1407 {
1408 	if (corpse->otyp != CORPSE) return 0;
1409 	if (corpse->oeaten) return 0;
1410 	if (corpse->odrained) return 0;
1411 	if (!mons[corpse->corpsenm].cnutrit) return 0;
1412 	return 1;
1413 }
1414 
1415 STATIC_OVL void
use_tinning_kit(obj)1416 use_tinning_kit(obj)
1417 register struct obj *obj;
1418 {
1419 	register struct obj *corpse, *can;
1420 
1421 	/* This takes only 1 move.  If this is to be changed to take many
1422 	 * moves, we've got to deal with decaying corpses...
1423 	 */
1424 	if (obj->spe <= 0) {
1425 		You("seem to be out of tins.");
1426 		return;
1427 	}
1428 	if (!(corpse = floorfood("tin", 2))) return;
1429 	if (corpse->otyp == CORPSE && (corpse->oeaten || corpse->odrained)) {
1430 		You("cannot tin %s which is partly eaten.",something);
1431 		return;
1432 	}
1433 	if (touch_petrifies(&mons[corpse->corpsenm])
1434 		&& !Stone_resistance && !uarmg) {
1435 	    char kbuf[BUFSZ];
1436 
1437 	    if (poly_when_stoned(youmonst.data))
1438 		You("tin %s without wearing gloves.",
1439 			an(mons[corpse->corpsenm].mname));
1440 	    else {
1441 		pline("Tinning %s without wearing gloves is a fatal mistake...",
1442 			an(mons[corpse->corpsenm].mname));
1443 		Sprintf(kbuf, "trying to tin %s without gloves",
1444 			an(mons[corpse->corpsenm].mname));
1445 	    }
1446 	    instapetrify(kbuf);
1447 	}
1448 	if (is_rider(&mons[corpse->corpsenm])) {
1449 		(void) revive_corpse(corpse);
1450 		verbalize("Yes...  But War does not preserve its enemies...");
1451 		return;
1452 	}
1453 	if (mons[corpse->corpsenm].cnutrit == 0) {
1454 		pline("That's too insubstantial to tin.");
1455 		return;
1456 	}
1457 	consume_obj_charge(obj, TRUE);
1458 
1459 	if ((can = mksobj(TIN, FALSE, FALSE)) != 0) {
1460 	    static const char you_buy_it[] = "You tin it, you bought it!";
1461 
1462 	    can->corpsenm = corpse->corpsenm;
1463 	    can->cursed = obj->cursed;
1464 	    can->blessed = obj->blessed;
1465 	    can->owt = weight(can);
1466 	    can->known = 1;
1467 	    can->bknown = obj->bknown;
1468 	    can->spe = -1;  /* Mark tinned tins. No spinach allowed... */
1469 	    if (carried(corpse)) {
1470 		if (corpse->unpaid)
1471 		    verbalize(you_buy_it);
1472 		useup(corpse);
1473 	    } else {
1474 		if (costly_spot(corpse->ox, corpse->oy) && !corpse->no_charge)
1475 		    verbalize(you_buy_it);
1476 		useupf(corpse, 1L);
1477 	    }
1478 	    can = hold_another_object(can, "You make, but cannot pick up, %s.",
1479 				      doname(can), (const char *)0);
1480 	} else warning("Tinning failed.");
1481 }
1482 
1483 void
fix_attributes_and_properties(obj,attr_point)1484 fix_attributes_and_properties(obj, attr_point)
1485 struct obj *obj;
1486 int attr_point; /* number of attribute points per attribute we might fix */
1487 {
1488 #define PROP_COUNT 6		/* number of properties we're dealing with */
1489 	int attr_count = A_MAX*attr_point;
1490 	int idx, val, val_limit,
1491 	    trouble_count, unfixable_trbl, did_prop, did_attr;
1492 	int trouble_list[PROP_COUNT + attr_count];
1493 
1494 	if (obj && obj->cursed) {
1495 	    long lcount = (long) rnd(100);
1496 
1497 	    switch (rn2(6)) {
1498 	    case 0: make_sick(Sick ? Sick/3L + 1L : (long)rn1(ACURR(A_CON),20),
1499 			xname(obj), TRUE, SICK_NONVOMITABLE);
1500 		    break;
1501 	    case 1: make_blinded(Blinded + lcount, TRUE);
1502 		    break;
1503 	    case 2: if (!Confusion)
1504 			You("suddenly feel %s.",
1505 			    Hallucination ? "trippy" : "confused");
1506 		    make_confused(HConfusion + lcount, TRUE);
1507 		    break;
1508 	    case 3: make_stunned(HStun + lcount, TRUE);
1509 		    break;
1510 	    case 4: (void) adjattrib(rn2(A_MAX), -1, FALSE);
1511 		    break;
1512 	    case 5: (void) make_hallucinated(HHallucination + lcount, TRUE, 0L);
1513 		    break;
1514 	    }
1515 	    return;
1516 	}
1517 
1518 /*
1519  * Entries in the trouble list use a very simple encoding scheme.
1520  */
1521 #define prop2trbl(X)	((X) + A_MAX)
1522 #define attr2trbl(Y)	(Y)
1523 #define prop_trouble(X) trouble_list[trouble_count++] = prop2trbl(X)
1524 #define attr_trouble(Y) trouble_list[trouble_count++] = attr2trbl(Y)
1525 
1526 	trouble_count = unfixable_trbl = did_prop = did_attr = 0;
1527 
1528 	/* collect property troubles */
1529 	if (Sick) prop_trouble(SICK);
1530 	if (Blinded > (long)u.ucreamed) prop_trouble(BLINDED);
1531 	if (HHallucination) prop_trouble(HALLUC);
1532 	if (Vomiting) prop_trouble(VOMITING);
1533 	if (HConfusion) prop_trouble(CONFUSION);
1534 	if (HStun) prop_trouble(STUNNED);
1535 
1536 	unfixable_trbl = unfixable_trouble_count(TRUE);
1537 
1538 	/* collect attribute troubles */
1539 	for (idx = 0; idx < A_MAX; idx++) {
1540 	    val_limit = AMAX(idx);
1541 	    /* don't recover strength lost from hunger */
1542 	    if (idx == A_STR && u.uhs >= WEAK) val_limit--;
1543 	    /* don't recover more than 3 points worth of any attribute */
1544 	    if (val_limit > ABASE(idx) + attr_point) val_limit = ABASE(idx) + attr_point;
1545 
1546 	    for (val = ABASE(idx); val < val_limit; val++)
1547 		attr_trouble(idx);
1548 	    /* keep track of unfixed trouble, for message adjustment below */
1549 	    unfixable_trbl += (AMAX(idx) - val_limit);
1550 	}
1551 
1552 	if (trouble_count == 0) {
1553 	    pline("%s", nothing_happens);
1554 	    return;
1555 	} else if (trouble_count > 1) {		/* shuffle */
1556 	    int i, j, k;
1557 
1558 	    for (i = trouble_count - 1; i > 0; i--)
1559 		if ((j = rn2(i + 1)) != i) {
1560 		    k = trouble_list[j];
1561 		    trouble_list[j] = trouble_list[i];
1562 		    trouble_list[i] = k;
1563 		}
1564 	}
1565 
1566 	/*
1567 	 *		Chances for number of troubles to be fixed
1568 	 *		 0	1      2      3      4	    5	   6	  7
1569 	 *   blessed:  22.7%  22.7%  19.5%  15.4%  10.7%   5.7%   2.6%	 0.8%
1570 	 *  uncursed:  35.4%  35.4%  22.9%   6.3%    0	    0	   0	  0
1571 	 */
1572 	val_limit = rn2( d(2, (obj && obj->blessed) ? 4 : 2) );
1573 	if (val_limit > trouble_count) val_limit = trouble_count;
1574 
1575 	/* fix [some of] the troubles */
1576 	for (val = 0; val < val_limit; val++) {
1577 	    idx = trouble_list[val];
1578 
1579 	    switch (idx) {
1580 	    case prop2trbl(SICK):
1581 		make_sick(0L, (char *) 0, TRUE, SICK_ALL);
1582 		did_prop++;
1583 		break;
1584 	    case prop2trbl(BLINDED):
1585 		make_blinded((long)u.ucreamed, TRUE);
1586 		did_prop++;
1587 		break;
1588 	    case prop2trbl(HALLUC):
1589 		(void) make_hallucinated(0L, TRUE, 0L);
1590 		did_prop++;
1591 		break;
1592 	    case prop2trbl(VOMITING):
1593 		make_vomiting(0L, TRUE);
1594 		did_prop++;
1595 		break;
1596 	    case prop2trbl(CONFUSION):
1597 		make_confused(0L, TRUE);
1598 		did_prop++;
1599 		break;
1600 	    case prop2trbl(STUNNED):
1601 		make_stunned(0L, TRUE);
1602 		did_prop++;
1603 		break;
1604 	    default:
1605 		if (idx >= 0 && idx < A_MAX) {
1606 		    ABASE(idx) += 1;
1607 		    did_attr++;
1608 		} else
1609 		    panic("fix_attributes_and_properties: bad trouble? (%d)", idx);
1610 		break;
1611 	    }
1612 	}
1613 
1614 	if (did_attr)
1615 	    pline("This makes you feel %s!",
1616 		  (did_prop + did_attr) == (trouble_count + unfixable_trbl) ?
1617 		  "great" : "better");
1618 	else if (!did_prop)
1619 	    pline("Nothing seems to happen.");
1620 
1621 	flags.botl = (did_attr || did_prop);
1622 #undef PROP_COUNT
1623 #undef ATTR_COUNT
1624 #undef prop2trbl
1625 #undef attr2trbl
1626 #undef prop_trouble
1627 #undef attr_trouble
1628 }
1629 
1630 /*
1631  * Timer callback routine: turn figurine into monster
1632  */
1633 void
fig_transform(arg,timeout)1634 fig_transform(arg, timeout)
1635 genericptr_t arg;
1636 long timeout;
1637 {
1638 	struct obj *figurine = (struct obj *)arg;
1639 	struct monst *mtmp;
1640 	coord cc;
1641 	boolean cansee_spot, silent, okay_spot;
1642 	boolean redraw = FALSE;
1643 	char monnambuf[BUFSZ], carriedby[BUFSZ];
1644 
1645 	if (!figurine) {
1646 #ifdef DEBUG
1647 	    pline("null figurine in fig_transform()");
1648 #endif
1649 	    return;
1650 	}
1651 	silent = (timeout != monstermoves); /* happened while away */
1652 	okay_spot = get_obj_location(figurine, &cc.x, &cc.y, 0);
1653 	if (figurine->where == OBJ_INVENT ||
1654 	    figurine->where == OBJ_MINVENT)
1655 		okay_spot = enexto(&cc, cc.x, cc.y,
1656 				   &mons[figurine->corpsenm]);
1657 	if (!okay_spot ||
1658 	    !figurine_location_checks(figurine,&cc, TRUE)) {
1659 		/* reset the timer to try again later */
1660 		(void) start_timer((long)rnd(5000), TIMER_OBJECT,
1661 				FIG_TRANSFORM, (genericptr_t)figurine);
1662 		return;
1663 	}
1664 
1665 	cansee_spot = cansee(cc.x, cc.y);
1666 	mtmp = make_familiar(figurine, cc.x, cc.y, TRUE);
1667 	if (mtmp) {
1668 	    Sprintf(monnambuf, "%s",an(m_monnam(mtmp)));
1669 	    switch (figurine->where) {
1670 		case OBJ_INVENT:
1671 		    if (Blind)
1672 			You_feel("%s %s from your pack!", something,
1673 			    locomotion(mtmp->data,"drop"));
1674 		    else
1675 			You("see %s %s out of your pack!",
1676 			    monnambuf,
1677 			    locomotion(mtmp->data,"drop"));
1678 		    break;
1679 
1680 		case OBJ_FLOOR:
1681 		    if (cansee_spot && !silent) {
1682 			You("suddenly see a figurine transform into %s!",
1683 				monnambuf);
1684 			redraw = TRUE;	/* update figurine's map location */
1685 		    }
1686 		    break;
1687 
1688 		case OBJ_MINVENT:
1689 		    if (cansee_spot && !silent) {
1690 			struct monst *mon;
1691 			mon = figurine->ocarry;
1692 			/* figurine carring monster might be invisible */
1693 			if (canseemon(figurine->ocarry)) {
1694 			    Sprintf(carriedby, "%s pack",
1695 				     s_suffix(a_monnam(mon)));
1696 			}
1697 			else if (is_pool(mon->mx, mon->my))
1698 			    Strcpy(carriedby, "empty water");
1699 			else
1700 			    Strcpy(carriedby, "thin air");
1701 			You("see %s %s out of %s!", monnambuf,
1702 			    locomotion(mtmp->data, "drop"), carriedby);
1703 		    }
1704 		    break;
1705 #if 0
1706 		case OBJ_MIGRATING:
1707 		    break;
1708 #endif
1709 
1710 		default:
1711 		    warning("figurine came to life where? (%d)",
1712 				(int)figurine->where);
1713 		break;
1714 	    }
1715 	}
1716 	/* free figurine now */
1717 	obj_extract_self(figurine);
1718 	obfree(figurine, (struct obj *)0);
1719 	if (redraw) newsym(cc.x, cc.y);
1720 }
1721 
1722 STATIC_OVL boolean
figurine_location_checks(obj,cc,quietly)1723 figurine_location_checks(obj, cc, quietly)
1724 struct obj *obj;
1725 coord *cc;
1726 boolean quietly;
1727 {
1728 	xchar x,y;
1729 
1730 	if (carried(obj) && u.uswallow) {
1731 		if (!quietly)
1732 			You("don't have enough room in here.");
1733 		return FALSE;
1734 	}
1735 	x = cc->x; y = cc->y;
1736 	if (!isok(x,y)) {
1737 		if (!quietly)
1738 			You("cannot put the figurine there.");
1739 		return FALSE;
1740 	}
1741 	if (IS_ROCK(levl[x][y].typ) &&
1742 	    !(passes_walls(&mons[obj->corpsenm]) && may_passwall(x,y))) {
1743 		if (!quietly)
1744 		    You("cannot place a figurine in %s!",
1745 			IS_TREES(levl[x][y].typ) ? "a tree" : "solid rock");
1746 		return FALSE;
1747 	}
1748 	if (sobj_at(BOULDER,x,y) && !passes_walls(&mons[obj->corpsenm])
1749 			&& !throws_rocks(&mons[obj->corpsenm])) {
1750 		if (!quietly)
1751 			You("cannot fit the figurine on the boulder.");
1752 		return FALSE;
1753 	}
1754 	return TRUE;
1755 }
1756 
1757 STATIC_OVL void
use_figurine(optr)1758 use_figurine(optr)
1759 struct obj **optr;
1760 {
1761 	register struct obj *obj = *optr;
1762 	xchar x, y;
1763 	coord cc;
1764 
1765 	if (u.uswallow) {
1766 		/* can't activate a figurine while swallowed */
1767 		if (!figurine_location_checks(obj, (coord *)0, FALSE))
1768 			return;
1769 	}
1770 	if(!getdir((char *)0)) {
1771 		flags.move = multi = 0;
1772 		return;
1773 	}
1774 	x = u.ux + u.dx; y = u.uy + u.dy;
1775 	cc.x = x; cc.y = y;
1776 	/* Passing FALSE arg here will result in messages displayed */
1777 	if (!figurine_location_checks(obj, &cc, FALSE)) return;
1778 	You("%s and it transforms.",
1779 	    (u.dx||u.dy) ? "set the figurine beside you" :
1780 	    (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ||
1781 	     is_pool(cc.x, cc.y)) ?
1782 		"release the figurine" :
1783 	    (u.dz < 0 ?
1784 		"toss the figurine into the air" :
1785 		"set the figurine on the ground"));
1786 	(void) make_familiar(obj, cc.x, cc.y, FALSE);
1787 	(void) stop_timer(FIG_TRANSFORM, (genericptr_t)obj);
1788 	useup(obj);
1789 	*optr = 0;
1790 }
1791 
1792 static NEARDATA const char lubricables[] = { ALL_CLASSES, ALLOW_NONE, 0 };
1793 static NEARDATA const char need_to_remove_outer_armor[] =
1794 			"need to remove your %s to grease your %s.";
1795 
1796 STATIC_OVL void
use_grease(obj)1797 use_grease(obj)
1798 struct obj *obj;
1799 {
1800 	struct obj *otmp;
1801 	char buf[BUFSZ];
1802 
1803 	if (Glib) {
1804 	    pline("%s from your %s.", Tobjnam(obj, "slip"),
1805 		  makeplural(body_part(FINGER)));
1806 	    dropx(obj);
1807 	    return;
1808 	}
1809 
1810 	if (obj->spe > 0) {
1811 		if ((obj->cursed || Fumbling) && !rn2(2)) {
1812 			consume_obj_charge(obj, TRUE);
1813 
1814 			pline("%s from your %s.", Tobjnam(obj, "slip"),
1815 			      makeplural(body_part(FINGER)));
1816 			dropx(obj);
1817 			return;
1818 		}
1819 		otmp = getobj(lubricables, "grease");
1820 		if (!otmp) return;
1821 		if ((otmp->owornmask & WORN_ARMOR) && uarmc) {
1822 			Strcpy(buf, xname(uarmc));
1823 			You(need_to_remove_outer_armor, buf, xname(otmp));
1824 			return;
1825 		}
1826 #ifdef TOURIST
1827 		if ((otmp->owornmask & WORN_SHIRT) && (uarmc || uarm)) {
1828 			Strcpy(buf, uarmc ? xname(uarmc) : "");
1829 			if (uarmc && uarm) Strcat(buf, " and ");
1830 			Strcat(buf, uarm ? xname(uarm) : "");
1831 			You(need_to_remove_outer_armor, buf, xname(otmp));
1832 			return;
1833 		}
1834 #endif
1835 		consume_obj_charge(obj, TRUE);
1836 
1837 		if (otmp != &zeroobj) {
1838 			You("cover %s with a thick layer of grease.",
1839 			    yname(otmp));
1840 			otmp->greased = 1;
1841 			if (obj->cursed && !nohands(youmonst.data)) {
1842 			    incr_itimeout(&Glib, rnd(15));
1843 			    pline("Some of the grease gets all over your %s.",
1844 				makeplural(body_part(HAND)));
1845 			}
1846 		} else {
1847 			Glib += rnd(15);
1848 			You("coat your %s with grease.",
1849 			    makeplural(body_part(FINGER)));
1850 		}
1851 	} else {
1852 	    if (obj->known)
1853 		pline("%s empty.", Tobjnam(obj, "are"));
1854 	    else
1855 		pline("%s to be empty.", Tobjnam(obj, "seem"));
1856 	}
1857 	update_inventory();
1858 }
1859 
1860 static struct trapinfo {
1861 	struct obj *tobj;
1862 	xchar tx, ty;
1863 	int time_needed;
1864 	boolean force_bungle;
1865 } trapinfo;
1866 
1867 void
reset_trapset()1868 reset_trapset()
1869 {
1870 	trapinfo.tobj = 0;
1871 	trapinfo.force_bungle = 0;
1872 }
1873 
1874 /* touchstones - by Ken Arnold */
1875 STATIC_OVL void
use_stone(tstone)1876 use_stone(tstone)
1877 struct obj *tstone;
1878 {
1879     struct obj *obj;
1880     boolean do_scratch;
1881     const char *streak_color, *choices;
1882     char stonebuf[QBUFSZ];
1883     static const char scritch[] = "\"scritch, scritch\"";
1884     static const char allowall[3] = { COIN_CLASS, ALL_CLASSES, 0 };
1885     static const char justgems[3] = { ALLOW_NONE, GEM_CLASS, 0 };
1886 #ifndef GOLDOBJ
1887     struct obj goldobj;
1888 #endif
1889 
1890     /* in case it was acquired while blinded */
1891     if (!Blind) tstone->dknown = 1;
1892     /* when the touchstone is fully known, don't bother listing extra
1893        junk as likely candidates for rubbing */
1894     choices = (tstone->otyp == TOUCHSTONE && tstone->dknown &&
1895 		objects[TOUCHSTONE].oc_name_known) ? justgems : allowall;
1896     Sprintf(stonebuf, "rub on the stone%s", plur(tstone->quan));
1897     if ((obj = getobj(choices, stonebuf)) == 0)
1898 	return;
1899 #ifndef GOLDOBJ
1900     if (obj->oclass == COIN_CLASS) {
1901 	u.ugold += obj->quan;	/* keep botl up to date */
1902 	goldobj = *obj;
1903 	dealloc_obj(obj);
1904 	obj = &goldobj;
1905     }
1906 #endif
1907 
1908     if (obj == tstone && obj->quan == 1) {
1909 	You_cant("rub %s on itself.", the(xname(obj)));
1910 	return;
1911     }
1912 
1913     if (tstone->otyp == TOUCHSTONE && tstone->cursed &&
1914 	    obj->oclass == GEM_CLASS && !is_graystone(obj) &&
1915 	    !obj_resists(obj, 80, 100)) {
1916 	if (Blind)
1917 	    pline("You feel something shatter.");
1918 	else if (Hallucination)
1919 	    pline("Oh, wow, look at the pretty shards.");
1920 	else
1921 	    pline("A sharp crack shatters %s%s.",
1922 		  (obj->quan > 1) ? "one of " : "", the(xname(obj)));
1923 #ifndef GOLDOBJ
1924      /* assert(obj != &goldobj); */
1925 #endif
1926 	useup(obj);
1927 	return;
1928     }
1929 
1930     if (Blind) {
1931 	pline("%s", scritch);
1932 	return;
1933     } else if (Hallucination) {
1934 	pline("Oh wow, man: Fractals!");
1935 	return;
1936     }
1937 
1938     do_scratch = FALSE;
1939     streak_color = 0;
1940 
1941     switch (obj->oclass) {
1942     case GEM_CLASS:	/* these have class-specific handling below */
1943     case RING_CLASS:
1944 	if (tstone->otyp != TOUCHSTONE) {
1945 	    do_scratch = TRUE;
1946 	} else if (obj->oclass == GEM_CLASS && (tstone->blessed ||
1947 		(!tstone->cursed &&
1948 		    (Role_if(PM_ARCHEOLOGIST) || Race_if(PM_GNOME))))) {
1949 	    makeknown(TOUCHSTONE);
1950 	    makeknown(obj->otyp);
1951 	    prinv((char *)0, obj, 0L);
1952 	    return;
1953 	} else {
1954 	    /* either a ring or the touchstone was not effective */
1955 	    if (objects[obj->otyp].oc_material == GLASS) {
1956 		do_scratch = TRUE;
1957 		break;
1958 	    }
1959 	}
1960 	streak_color = c_obj_colors[objects[obj->otyp].oc_color];
1961 	break;		/* gem or ring */
1962 
1963     default:
1964 	switch (objects[obj->otyp].oc_material) {
1965 	case CLOTH:
1966 	    pline("%s a little more polished now.", Tobjnam(tstone, "look"));
1967 	    return;
1968 	case LIQUID:
1969 	    if (!obj->known)		/* note: not "whetstone" */
1970 		You("must think this is a wetstone, do you?");
1971 	    else
1972 		pline("%s a little wetter now.", Tobjnam(tstone, "are"));
1973 	    return;
1974 	case WAX:
1975 	    streak_color = "waxy";
1976 	    break;		/* okay even if not touchstone */
1977 	case WOOD:
1978 	    streak_color = "wooden";
1979 	    break;		/* okay even if not touchstone */
1980 	case GOLD:
1981 	    do_scratch = TRUE;	/* scratching and streaks */
1982 	    streak_color = "golden";
1983 	    break;
1984 	case SILVER:
1985 	    do_scratch = TRUE;	/* scratching and streaks */
1986 	    streak_color = "silvery";
1987 	    break;
1988 	default:
1989 	    /* Objects passing the is_flimsy() test will not
1990 	       scratch a stone.  They will leave streaks on
1991 	       non-touchstones and touchstones alike. */
1992 	    if (is_flimsy(obj))
1993 		streak_color = c_obj_colors[objects[obj->otyp].oc_color];
1994 	    else
1995 		do_scratch = (tstone->otyp != TOUCHSTONE);
1996 	    break;
1997 	}
1998 	break;		/* default oclass */
1999     }
2000 
2001     Sprintf(stonebuf, "stone%s", plur(tstone->quan));
2002     if (do_scratch)
2003 	pline("You make %s%sscratch marks on the %s.",
2004 	      streak_color ? streak_color : (const char *)"",
2005 	      streak_color ? " " : "", stonebuf);
2006     else if (streak_color)
2007 	pline("You see %s streaks on the %s.", streak_color, stonebuf);
2008     else
2009 	pline("%s", scritch);
2010     return;
2011 }
2012 
2013 /* Place a landmine/bear trap.  Helge Hafting */
2014 STATIC_OVL void
use_trap(otmp)2015 use_trap(otmp)
2016 struct obj *otmp;
2017 {
2018 	int ttyp, tmp;
2019 	const char *what = (char *)0;
2020 	char buf[BUFSZ];
2021 	const char *occutext = "setting the trap";
2022 
2023 	if (nohands(youmonst.data))
2024 	    what = "without hands";
2025 	else if (Stunned)
2026 	    what = "while stunned";
2027 	else if (u.uswallow)
2028 	    what = is_animal(u.ustuck->data) ? "while swallowed" :
2029 			"while engulfed";
2030 	else if (Underwater)
2031 	    what = "underwater";
2032 	else if (Levitation)
2033 	    what = "while levitating";
2034 	else if (is_pool(u.ux, u.uy))
2035 	    what = "in water";
2036 	else if (is_lava(u.ux, u.uy))
2037 	    what = "in lava";
2038 	else if (On_stairs(u.ux, u.uy))
2039 	    what = (u.ux == xdnladder || u.ux == xupladder) ?
2040 			"on the ladder" : "on the stairs";
2041 	else if (IS_FURNITURE(levl[u.ux][u.uy].typ) ||
2042 		IS_ROCK(levl[u.ux][u.uy].typ) ||
2043 		closed_door(u.ux, u.uy) || t_at(u.ux, u.uy))
2044 	    what = "here";
2045 	if (what) {
2046 	    You_cant("set a trap %s!",what);
2047 	    reset_trapset();
2048 	    return;
2049 	}
2050 	ttyp = (otmp->otyp == LAND_MINE) ? LANDMINE : BEAR_TRAP;
2051 	if (otmp == trapinfo.tobj &&
2052 		u.ux == trapinfo.tx && u.uy == trapinfo.ty) {
2053 	    You("resume setting %s %s.",
2054 		shk_your(buf, otmp),
2055 		defsyms[trap_to_defsym(what_trap(ttyp))].explanation);
2056 	    set_occupation(set_trap, occutext, 0);
2057 	    return;
2058 	}
2059 	trapinfo.tobj = otmp;
2060 	trapinfo.tx = u.ux,  trapinfo.ty = u.uy;
2061 	tmp = ACURR(A_DEX);
2062 	trapinfo.time_needed = (tmp > 17) ? 2 : (tmp > 12) ? 3 :
2063 				(tmp > 7) ? 4 : 5;
2064 	if (Blind) trapinfo.time_needed *= 2;
2065 	tmp = ACURR(A_STR);
2066 	if (ttyp == BEAR_TRAP && tmp < 18)
2067 	    trapinfo.time_needed += (tmp > 12) ? 1 : (tmp > 7) ? 2 : 4;
2068 	/*[fumbling and/or confusion and/or cursed object check(s)
2069 	   should be incorporated here instead of in set_trap]*/
2070 #ifdef STEED
2071 	if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) {
2072 	    boolean chance;
2073 
2074 	    if (Fumbling || otmp->cursed) chance = (rnl(10) > 3);
2075 	    else  chance = (rnl(10) > 5);
2076 	    You("aren't very skilled at reaching from %s.",
2077 		mon_nam(u.usteed));
2078 	    Sprintf(buf, "Continue your attempt to set %s?",
2079 		the(defsyms[trap_to_defsym(what_trap(ttyp))].explanation));
2080 	    if(yn(buf) == 'y') {
2081 		if (chance) {
2082 			switch(ttyp) {
2083 			    case LANDMINE:	/* set it off */
2084 			    	trapinfo.time_needed = 0;
2085 			    	trapinfo.force_bungle = TRUE;
2086 				break;
2087 			    case BEAR_TRAP:	/* drop it without arming it */
2088 				reset_trapset();
2089 				You("drop %s!",
2090 			  the(defsyms[trap_to_defsym(what_trap(ttyp))].explanation));
2091 				dropx(otmp);
2092 				return;
2093 			}
2094 		}
2095 	    } else {
2096 	    	reset_trapset();
2097 		return;
2098 	    }
2099 	}
2100 #endif
2101 	You("begin setting %s %s.",
2102 	    shk_your(buf, otmp),
2103 	    defsyms[trap_to_defsym(what_trap(ttyp))].explanation);
2104 	set_occupation(set_trap, occutext, 0);
2105 	return;
2106 }
2107 
2108 STATIC_PTR
2109 int
set_trap()2110 set_trap()
2111 {
2112 	struct obj *otmp = trapinfo.tobj;
2113 	struct trap *ttmp;
2114 	int ttyp;
2115 
2116 	if (!otmp || !carried(otmp) ||
2117 		u.ux != trapinfo.tx || u.uy != trapinfo.ty) {
2118 	    /* ?? */
2119 	    reset_trapset();
2120 	    return 0;
2121 	}
2122 
2123 	if (--trapinfo.time_needed > 0) return 1;	/* still busy */
2124 
2125 	ttyp = (otmp->otyp == LAND_MINE) ? LANDMINE : BEAR_TRAP;
2126 	ttmp = maketrap(u.ux, u.uy, ttyp);
2127 	if (ttmp) {
2128 	    ttmp->tseen = 1;
2129 	    ttmp->madeby_u = 1;
2130 	    newsym(u.ux, u.uy); /* if our hero happens to be invisible */
2131 	    if (*in_rooms(u.ux,u.uy,SHOPBASE)) {
2132 		add_damage(u.ux, u.uy, 0L);		/* schedule removal */
2133 	    }
2134 	    if (!trapinfo.force_bungle)
2135 		You("finish arming %s.",
2136 			the(defsyms[trap_to_defsym(what_trap(ttyp))].explanation));
2137 	    if (((otmp->cursed || Fumbling) && (rnl(10) > 5)) || trapinfo.force_bungle)
2138 		dotrap(ttmp,
2139 			(unsigned)(trapinfo.force_bungle ? FORCEBUNGLE : 0));
2140 	} else {
2141 	    /* this shouldn't happen */
2142 	    Your("trap setting attempt fails.");
2143 	}
2144 	useup(otmp);
2145 	reset_trapset();
2146 	return 0;
2147 }
2148 
2149 STATIC_OVL int
use_whip(obj)2150 use_whip(obj)
2151 struct obj *obj;
2152 {
2153     char buf[BUFSZ];
2154     struct monst *mtmp;
2155     struct obj *otmp;
2156     int rx, ry, proficient, res = 0;
2157     const char *msg_slipsfree = "The bullwhip slips free.";
2158     const char *msg_snap = "Snap!";
2159 
2160     if (obj != uwep) {
2161 	if (!wield_tool(obj, "lash")) return 0;
2162 	else res = 1;
2163     }
2164     if (!getdir((char *)0)) return res;
2165 
2166     if (Stunned || (Confusion && !rn2(5))) confdir();
2167     rx = u.ux + u.dx;
2168     ry = u.uy + u.dy;
2169     mtmp = m_at(rx, ry);
2170 
2171     /* fake some proficiency checks */
2172     proficient = 0;
2173     if (Role_if(PM_ARCHEOLOGIST)) ++proficient;
2174     if (ACURR(A_DEX) < 6) proficient--;
2175     else if (ACURR(A_DEX) >= 14) proficient += (ACURR(A_DEX) - 14);
2176     if (Fumbling) --proficient;
2177     if (proficient > 3) proficient = 3;
2178     if (proficient < 0) proficient = 0;
2179 
2180     if (u.uswallow && attack(u.ustuck)) {
2181 	There("is not enough room to flick your bullwhip.");
2182 
2183     } else if (Underwater) {
2184 	There("is too much resistance to flick your bullwhip.");
2185 
2186     } else if (u.dz < 0) {
2187 	You("flick a bug off of the %s.",ceiling(u.ux,u.uy));
2188 
2189     } else if ((!u.dx && !u.dy) || (u.dz > 0)) {
2190 	int dam;
2191 
2192 #ifdef STEED
2193 	/* Sometimes you hit your steed by mistake */
2194 	if (u.usteed && !rn2(proficient + 2)) {
2195 	    You("whip %s!", mon_nam(u.usteed));
2196 	    kick_steed();
2197 	    return 1;
2198 	}
2199 #endif
2200 	if (Levitation
2201 #ifdef STEED
2202 			|| u.usteed
2203 #endif
2204 		) {
2205 	    /* Have a shot at snaring something on the floor */
2206 	    otmp = level.objects[u.ux][u.uy];
2207 	    if (otmp && otmp->otyp == CORPSE && otmp->corpsenm == PM_HORSE) {
2208 		pline("Why beat a dead horse?");
2209 		return 1;
2210 	    }
2211 	    if (otmp && proficient) {
2212 		You("wrap your bullwhip around %s on the %s.",
2213 		    an(singular(otmp, xname)), surface(u.ux, u.uy));
2214 		if (rnl(6) || pickup_object(otmp, 1L, TRUE) < 1)
2215 		    pline("%s", msg_slipsfree);
2216 		return 1;
2217 	    }
2218 	}
2219 	dam = rnd(2) + dbon() + obj->spe;
2220 	if (dam <= 0) dam = 1;
2221 	You("hit your %s with your bullwhip.", body_part(FOOT));
2222 	Sprintf(buf, "killed %sself with %s bullwhip", uhim(), uhis());
2223 	losehp(dam, buf, NO_KILLER_PREFIX);
2224 	flags.botl = 1;
2225 	return 1;
2226 
2227     } else if ((Fumbling || Glib) && !rn2(5)) {
2228 	pline_The("bullwhip slips out of your %s.", body_part(HAND));
2229 	dropx(obj);
2230 
2231     } else if (u.utrap && u.utraptype == TT_PIT) {
2232 	/*
2233 	 *     Assumptions:
2234 	 *
2235 	 *	if you're in a pit
2236 	 *		- you are attempting to get out of the pit
2237 	 *		- or, if you are applying it towards a small
2238 	 *		  monster then it is assumed that you are
2239 	 *		  trying to hit it.
2240 	 *	else if the monster is wielding a weapon
2241 	 *		- you are attempting to disarm a monster
2242 	 *	else
2243 	 *		- you are attempting to hit the monster
2244 	 *
2245 	 *	if you're confused (and thus off the mark)
2246 	 *		- you only end up hitting.
2247 	 *
2248 	 */
2249 	const char *wrapped_what = (char *)0;
2250 
2251 	if (mtmp) {
2252 	    if (bigmonst(mtmp->data)) {
2253 		wrapped_what = strcpy(buf, mon_nam(mtmp));
2254 	    } else if (proficient) {
2255 		if (attack(mtmp)) return 1;
2256 		else pline("%s", msg_snap);
2257 	    }
2258 	}
2259 	if (!wrapped_what) {
2260 	    if (IS_FURNITURE(levl[rx][ry].typ))
2261 		wrapped_what = something;
2262 	    else if (sobj_at(BOULDER, rx, ry))
2263 		wrapped_what = "a boulder";
2264 	}
2265 	if (wrapped_what) {
2266 	    coord cc;
2267 
2268 	    cc.x = rx; cc.y = ry;
2269 	    You("wrap your bullwhip around %s.", wrapped_what);
2270 	    if (proficient && rn2(proficient + 2)) {
2271 		if (!mtmp || enexto(&cc, rx, ry, youmonst.data)) {
2272 		    You("yank yourself out of the pit!");
2273 		    teleds(cc.x, cc.y, TRUE);
2274 		    u.utrap = 0;
2275 		    vision_full_recalc = 1;
2276 		}
2277 	    } else {
2278 		pline("%s", msg_slipsfree);
2279 	    }
2280 	    if (mtmp) wakeup(mtmp);
2281 	} else pline("%s", msg_snap);
2282 
2283     } else if (mtmp) {
2284 	if (!canspotmon(mtmp) &&
2285 		!glyph_is_invisible(levl[rx][ry].glyph)) {
2286 	   pline("A monster is there that you couldn't see.");
2287 	   map_invisible(rx, ry);
2288 	}
2289 	otmp = MON_WEP(mtmp);	/* can be null */
2290 	if (otmp) {
2291 	    char onambuf[BUFSZ];
2292 	    const char *mon_hand;
2293 	    boolean gotit = proficient && (!Fumbling || !rn2(10));
2294 
2295 	    Strcpy(onambuf, cxname(otmp));
2296 	    if (gotit) {
2297 		mon_hand = mbodypart(mtmp, HAND);
2298 		if (bimanual(otmp)) mon_hand = makeplural(mon_hand);
2299 	    } else
2300 		mon_hand = 0;	/* lint suppression */
2301 
2302 	    You("wrap your bullwhip around %s %s.",
2303 		s_suffix(mon_nam(mtmp)), onambuf);
2304 	    if (gotit && otmp->cursed) {
2305 		pline("%s welded to %s %s%c",
2306 		      (otmp->quan == 1L) ? "It is" : "They are",
2307 		      mhis(mtmp), mon_hand,
2308 		      !otmp->bknown ? '!' : '.');
2309 		otmp->bknown = 1;
2310 		gotit = FALSE;	/* can't pull it free */
2311 	    }
2312 	    if (gotit) {
2313 		obj_extract_self(otmp);
2314 		possibly_unwield(mtmp, FALSE);
2315 		setmnotwielded(mtmp,otmp);
2316 
2317 		switch (rn2(proficient + 1)) {
2318 		case 2:
2319 		    /* to floor near you */
2320 		    You("yank %s %s to the %s!", s_suffix(mon_nam(mtmp)),
2321 			onambuf, surface(u.ux, u.uy));
2322 		    place_object(otmp, u.ux, u.uy);
2323 		    stackobj(otmp);
2324 		    break;
2325 		case 3:
2326 		    /* right to you */
2327 #if 0
2328 		    if (!rn2(25)) {
2329 			/* proficient with whip, but maybe not
2330 			   so proficient at catching weapons */
2331 			int hitu, hitvalu;
2332 
2333 			hitvalu = 8 + otmp->spe;
2334 			hitu = thitu(hitvalu,
2335 				     dmgval(otmp, &youmonst),
2336 				     otmp, (char *)0);
2337 			if (hitu) {
2338 			    pline_The("%s hits you as you try to snatch it!",
2339 				the(onambuf));
2340 			}
2341 			place_object(otmp, u.ux, u.uy);
2342 			stackobj(otmp);
2343 			break;
2344 		    }
2345 #endif /* 0 */
2346 		    /* right into your inventory */
2347 		    You("snatch %s %s!", s_suffix(mon_nam(mtmp)), onambuf);
2348 		    if (otmp->otyp == CORPSE &&
2349 			    touch_petrifies(&mons[otmp->corpsenm]) &&
2350 			    !uarmg && !Stone_resistance &&
2351 			    !(poly_when_stoned(youmonst.data) &&
2352 				polymon(PM_STONE_GOLEM))) {
2353 			char kbuf[BUFSZ];
2354 
2355 			Sprintf(kbuf, "%s corpse",
2356 				an(mons[otmp->corpsenm].mname));
2357 			pline("Snatching %s is a fatal mistake.", kbuf);
2358 			instapetrify(kbuf);
2359 		    }
2360 		    otmp = hold_another_object(otmp, "You drop %s!",
2361 					       doname(otmp), (const char *)0);
2362 		    break;
2363 		default:
2364 		    /* to floor beneath mon */
2365 		    You("yank %s from %s %s!", the(onambuf),
2366 			s_suffix(mon_nam(mtmp)), mon_hand);
2367 		    obj_no_longer_held(otmp);
2368 		    place_object(otmp, mtmp->mx, mtmp->my);
2369 		    stackobj(otmp);
2370 		    break;
2371 		}
2372 	    } else {
2373 		pline("%s", msg_slipsfree);
2374 	    }
2375 	    wakeup(mtmp);
2376 	} else {
2377 	    if (mtmp->m_ap_type &&
2378 		!Protection_from_shape_changers && !sensemon(mtmp))
2379 		stumble_onto_mimic(mtmp);
2380 	    else You("flick your bullwhip towards %s.", mon_nam(mtmp));
2381 	    if (proficient) {
2382 		if (attack(mtmp)) return 1;
2383 		else pline("%s", msg_snap);
2384 	    }
2385 	}
2386 
2387     } else if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) {
2388 	    /* it must be air -- water checked above */
2389 	    You("snap your whip through thin air.");
2390 
2391     } else {
2392 	pline("%s", msg_snap);
2393 
2394     }
2395     return 1;
2396 }
2397 
2398 
2399 static const char
2400 	not_enough_room[] = "There's not enough room here to use that.",
2401 	where_to_hit[] = "Where do you want to hit?",
2402 	cant_see_spot[] = "won't hit anything if you can't see that spot.",
2403 	cant_reach[] = "can't reach that spot from here.";
2404 
2405 /* Distance attacks by pole-weapons */
2406 STATIC_OVL int
use_pole(obj)2407 use_pole (obj)
2408 	struct obj *obj;
2409 {
2410 	int res = 0, typ, max_range = 4, min_range = 4;
2411 	coord cc;
2412 	struct monst *mtmp;
2413 
2414 
2415 	/* Are you allowed to use the pole? */
2416 	if (u.uswallow) {
2417 	    pline("%s", not_enough_room);
2418 	    return (0);
2419 	}
2420 	if (obj != uwep) {
2421 	    if (!wield_tool(obj, "swing")) return(0);
2422 	    else res = 1;
2423 	}
2424      /* assert(obj == uwep); */
2425 
2426 	/* Prompt for a location */
2427 	pline("%s", where_to_hit);
2428 	cc.x = u.ux;
2429 	cc.y = u.uy;
2430 	if (getpos(&cc, TRUE, "the spot to hit") < 0)
2431 	    return 0;	/* user pressed ESC */
2432 
2433 	/* Calculate range */
2434 	typ = uwep_skill_type();
2435 	if (typ == P_NONE || P_SKILL(typ) <= P_BASIC) max_range = 4;
2436 	else if (P_SKILL(typ) == P_SKILLED) max_range = 5;
2437 	else max_range = 8;
2438 	if (distu(cc.x, cc.y) > max_range) {
2439 	    pline("Too far!");
2440 	    return (res);
2441 	} else if (distu(cc.x, cc.y) < min_range) {
2442 	    pline("Too close!");
2443 	    return (res);
2444 	} else if (!cansee(cc.x, cc.y) &&
2445 		   ((mtmp = m_at(cc.x, cc.y)) == (struct monst *)0 ||
2446 		    !canseemon(mtmp))) {
2447 	    You(cant_see_spot);
2448 	    return (res);
2449 	} else if (!couldsee(cc.x, cc.y)) { /* Eyes of the Overworld */
2450 	    You(cant_reach);
2451 	    return res;
2452 	}
2453 
2454 	/* Attack the monster there */
2455 	if ((mtmp = m_at(cc.x, cc.y)) != (struct monst *)0) {
2456 	    int oldhp = mtmp->mhp;
2457 
2458 	    bhitpos = cc;
2459 	    check_caitiff(mtmp);
2460 	    (void) thitmonst(mtmp, uwep);
2461 	    /* check the monster's HP because thitmonst() doesn't return
2462 	     * an indication of whether it hit.  Not perfect (what if it's a
2463 	     * non-silver weapon on a shade?)
2464 	     */
2465 	    if (mtmp->mhp < oldhp)
2466 		u.uconduct.weaphit++;
2467 	} else
2468 	    /* Now you know that nothing is there... */
2469 	    pline("%s", nothing_happens);
2470 	return (1);
2471 }
2472 
2473 STATIC_OVL int
use_cream_pie(obj)2474 use_cream_pie(obj)
2475 struct obj *obj;
2476 {
2477 	boolean wasblind = Blind;
2478 	boolean wascreamed = u.ucreamed;
2479 	boolean several = FALSE;
2480 
2481 	if (obj->quan > 1L) {
2482 		several = TRUE;
2483 		obj = splitobj(obj, 1L);
2484 	}
2485 	if (Hallucination)
2486 		You("give yourself a facial.");
2487 	else
2488 		pline("You immerse your %s in %s%s.", body_part(FACE),
2489 			several ? "one of " : "",
2490 			several ? makeplural(the(xname(obj))) : the(xname(obj)));
2491 	if(can_blnd((struct monst*)0, &youmonst, AT_WEAP, obj)) {
2492 		int blindinc = rnd(25);
2493 		u.ucreamed += blindinc;
2494 		make_blinded(Blinded + (long)blindinc, FALSE);
2495 		if (!Blind || (Blind && wasblind))
2496 			pline("There's %ssticky goop all over your %s.",
2497 				wascreamed ? "more " : "",
2498 				body_part(FACE));
2499 		else /* Blind  && !wasblind */
2500 			You_cant("see through all the sticky goop on your %s.",
2501 				body_part(FACE));
2502 	}
2503 	if (obj->unpaid) {
2504 		verbalize("You used it, you bought it!");
2505 		bill_dummy_object(obj);
2506 	}
2507 	obj_extract_self(obj);
2508 	delobj(obj);
2509 	return(0);
2510 }
2511 
2512 STATIC_OVL int
use_grapple(obj)2513 use_grapple (obj)
2514 	struct obj *obj;
2515 {
2516 	int res = 0, typ, max_range = 4, tohit;
2517 	coord cc;
2518 	struct monst *mtmp;
2519 	struct obj *otmp;
2520 
2521 	/* Are you allowed to use the hook? */
2522 	if (u.uswallow) {
2523 	    pline("%s", not_enough_room);
2524 	    return (0);
2525 	}
2526 	if (obj != uwep) {
2527 	    if (!wield_tool(obj, "cast")) return(0);
2528 	    else res = 1;
2529 	}
2530      /* assert(obj == uwep); */
2531 
2532 	/* Prompt for a location */
2533 	pline("%s", where_to_hit);
2534 	cc.x = u.ux;
2535 	cc.y = u.uy;
2536 	if (getpos(&cc, TRUE, "the spot to hit") < 0)
2537 	    return 0;	/* user pressed ESC */
2538 
2539 	/* Calculate range */
2540 	typ = uwep_skill_type();
2541 	if (typ == P_NONE || P_SKILL(typ) <= P_BASIC) max_range = 4;
2542 	else if (P_SKILL(typ) == P_SKILLED) max_range = 5;
2543 	else max_range = 8;
2544 	if (distu(cc.x, cc.y) > max_range) {
2545 	    pline("Too far!");
2546 	    return (res);
2547 	} else if (!cansee(cc.x, cc.y)) {
2548 	    You(cant_see_spot);
2549 	    return (res);
2550 	} else if (!couldsee(cc.x, cc.y)) { /* Eyes of the Overworld */
2551 	    You(cant_reach);
2552 	    return res;
2553 	}
2554 
2555 	/* What do you want to hit? */
2556 	tohit = rn2(5);
2557 	if (typ != P_NONE && P_SKILL(typ) >= P_SKILLED) {
2558 	    winid tmpwin = create_nhwindow(NHW_MENU);
2559 	    anything any;
2560 	    char buf[BUFSZ];
2561 	    menu_item *selected;
2562 
2563 	    any.a_void = 0;	/* set all bits to zero */
2564 	    any.a_int = 1;	/* use index+1 (cant use 0) as identifier */
2565 	    start_menu(tmpwin);
2566 	    any.a_int++;
2567 	    Sprintf(buf, "an object on the %s", surface(cc.x, cc.y));
2568 	    add_menu(tmpwin, NO_GLYPH, MENU_DEFCNT, &any, 0, 0, ATR_NONE,
2569 			 buf, MENU_UNSELECTED);
2570 	    any.a_int++;
2571 	    add_menu(tmpwin, NO_GLYPH, MENU_DEFCNT, &any, 0, 0, ATR_NONE,
2572 			"a monster", MENU_UNSELECTED);
2573 	    any.a_int++;
2574 	    Sprintf(buf, "the %s", surface(cc.x, cc.y));
2575 	    add_menu(tmpwin, NO_GLYPH, MENU_DEFCNT, &any, 0, 0, ATR_NONE,
2576 			 buf, MENU_UNSELECTED);
2577 	    end_menu(tmpwin, "Aim for what?");
2578 	    tohit = rn2(4);
2579 	    if (select_menu(tmpwin, PICK_ONE, &selected) > 0 &&
2580 			rn2(P_SKILL(typ) > P_SKILLED ? 20 : 2))
2581 		tohit = selected[0].item.a_int - 1;
2582 	    free((genericptr_t)selected);
2583 	    destroy_nhwindow(tmpwin);
2584 	}
2585 
2586 	/* What did you hit? */
2587 	switch (tohit) {
2588 	case 0:	/* Trap */
2589 	    /* FIXME -- untrap needs to deal with non-adjacent traps */
2590 	    break;
2591 	case 1:	/* Object */
2592 	    if ((otmp = level.objects[cc.x][cc.y]) != 0) {
2593 		You("snag an object from the %s!", surface(cc.x, cc.y));
2594 		(void) pickup_object(otmp, 1L, FALSE);
2595 		/* If pickup fails, leave it alone */
2596 		newsym(cc.x, cc.y);
2597 		return (1);
2598 	    }
2599 	    break;
2600 	case 2:	/* Monster */
2601 	    if ((mtmp = m_at(cc.x, cc.y)) == (struct monst *)0) break;
2602 	    if (verysmall(mtmp->data) && !rn2(4) &&
2603 			enexto(&cc, u.ux, u.uy, (struct permonst *)0)) {
2604 		You("pull in %s!", mon_nam(mtmp));
2605 		mtmp->mundetected = 0;
2606 		rloc_to(mtmp, cc.x, cc.y);
2607 		return (1);
2608 	    } else if ((!bigmonst(mtmp->data) && !strongmonst(mtmp->data)) ||
2609 		       rn2(4)) {
2610 		(void) thitmonst(mtmp, uwep);
2611 		return (1);
2612 	    }
2613 	    /* FALL THROUGH */
2614 	case 3:	/* Surface */
2615 	    if (IS_AIR(levl[cc.x][cc.y].typ) || is_pool(cc.x, cc.y))
2616 		pline_The("hook slices through the %s.", surface(cc.x, cc.y));
2617 	    else {
2618 		You("are yanked toward the %s!", surface(cc.x, cc.y));
2619 		hurtle(sgn(cc.x-u.ux), sgn(cc.y-u.uy), 1, FALSE);
2620 		spoteffects(TRUE);
2621 	    }
2622 	    return (1);
2623 	default:	/* Yourself (oops!) */
2624 	    if (P_SKILL(typ) <= P_BASIC) {
2625 		You("hook yourself!");
2626 		losehp(rn1(10,10), "a grappling hook", KILLED_BY);
2627 		return (1);
2628 	    }
2629 	    break;
2630 	}
2631 	pline("%s", nothing_happens);
2632 	return (1);
2633 }
2634 
2635 
2636 #define BY_OBJECT	((struct monst *)0)
2637 
2638 /* return 1 if the wand is broken, hence some time elapsed */
2639 STATIC_OVL int
do_break_wand(obj)2640 do_break_wand(obj)
2641     struct obj *obj;
2642 {
2643     static const char nothing_else_happens[] = "But nothing else happens...";
2644     register int i, x, y;
2645     register struct monst *mon;
2646     int dmg, damage;
2647     boolean affects_objects, is_fragile;
2648     boolean shop_damage = FALSE;
2649     int expltype = EXPL_MAGICAL;
2650     char confirm[QBUFSZ], the_wand[BUFSZ], buf[BUFSZ];
2651 
2652     Strcpy(the_wand, yname(obj));
2653     Sprintf(confirm, "Are you really sure you want to break %s?",
2654 	safe_qbuf("", sizeof("Are you really sure you want to break ?"),
2655 				the_wand, ysimple_name(obj), "the wand"));
2656     if (yn(confirm) == 'n' ) return 0;
2657 
2658     is_fragile = (!strcmp(OBJ_DESCR(objects[obj->otyp]), "balsa"));
2659 
2660     if (nohands(youmonst.data)) {
2661 	You_cant("break %s without hands!", the_wand);
2662 	return 0;
2663     } else if (ACURR(A_STR) < (is_fragile ? 5 : 10)) {
2664 	You("don't have the strength to break %s!", the_wand);
2665 	return 0;
2666     }
2667     pline("Raising %s high above your %s, you %s it in two!",
2668 	  the_wand, body_part(HEAD), is_fragile ? "snap" : "break");
2669 
2670     /* [ALI] Do this first so that wand is removed from bill. Otherwise,
2671      * the freeinv() below also hides it from setpaid() which causes problems.
2672      */
2673     if (obj->unpaid) {
2674 	check_unpaid(obj);		/* Extra charge for use */
2675 	bill_dummy_object(obj);
2676     }
2677 
2678     current_wand = obj;		/* destroy_item might reset this */
2679     freeinv(obj);		/* hide it from destroy_item instead... */
2680     setnotworn(obj);		/* so we need to do this ourselves */
2681 
2682     if (obj->spe <= 0) {
2683 	pline("%s", nothing_else_happens);
2684 	goto discard_broken_wand;
2685     }
2686     obj->ox = u.ux;
2687     obj->oy = u.uy;
2688     dmg = obj->spe * 4;
2689     affects_objects = FALSE;
2690 
2691     switch (obj->otyp) {
2692     case WAN_NOTHING:
2693 	pline("Suddenly, and without warning, nothing happens.");
2694 	goto discard_broken_wand;
2695     case WAN_WISHING:
2696     case WAN_LOCKING:
2697     case WAN_PROBING:
2698     case WAN_ENLIGHTENMENT:
2699     case WAN_SECRET_DOOR_DETECTION:
2700 	pline("%s", nothing_else_happens);
2701 	goto discard_broken_wand;
2702     case WAN_OPENING:
2703 	/* make trap door if you broke a wand of opening */
2704 	if ((obj->spe > 2) && rn2(obj->spe - 2) && !u.uswallow &&
2705 	    !On_stairs(u.ux, u.uy) && (!IS_FURNITURE(levl[u.ux][u.uy].typ) &&
2706 	    !IS_ROCK(levl[u.ux][u.uy].typ) && !closed_door(u.ux, u.uy) &&
2707 	    !t_at(u.ux, u.uy) && Can_dig_down(&u.uz))) {
2708 		struct trap *ttmp;
2709 		ttmp = maketrap(u.ux, u.uy, TRAPDOOR);
2710 		    if (ttmp) {
2711 			ttmp->madeby_u = 1;
2712 			ttmp->tseen = 1;
2713 			newsym(u.ux, u.uy);
2714 			    if (*in_rooms(u.ux,u.uy,SHOPBASE)) {
2715 				add_damage(u.ux, u.uy, 0L);
2716 			    }
2717 		    }
2718 	}
2719 	goto discard_broken_wand;
2720     case WAN_DEATH:
2721     case WAN_LIGHTNING:
2722 	dmg *= 4;
2723 	goto wanexpl;
2724     case WAN_FIRE:
2725 	expltype = EXPL_FIERY;
2726 	/* make fire trap if you broke a wand of fire */
2727 	if ((obj->spe > 2) && rn2(obj->spe - 2) && !u.uswallow &&
2728 	    !On_stairs(u.ux, u.uy) && (!IS_FURNITURE(levl[u.ux][u.uy].typ) &&
2729 	    !IS_ROCK(levl[u.ux][u.uy].typ) &&
2730 	    !closed_door(u.ux, u.uy) && !t_at(u.ux, u.uy))) {
2731 		struct trap *ttmp;
2732 		ttmp = maketrap(u.ux, u.uy, FIRE_TRAP);
2733 		    if (ttmp) {
2734 			ttmp->madeby_u = 1;
2735 			ttmp->tseen = 1;
2736 			newsym(u.ux, u.uy);
2737 			    if (*in_rooms(u.ux,u.uy,SHOPBASE)) {
2738 				add_damage(u.ux, u.uy, 0L);
2739 			    }
2740 		    }
2741 	}
2742 	break;
2743     case WAN_COLD:
2744 	if (expltype == EXPL_MAGICAL) expltype = EXPL_FROSTY;
2745 	dmg *= 2;
2746 	/* make ice trap if you broke a wand of cold */
2747 	if ((obj->spe > 2) && rn2(obj->spe - 2) && !u.uswallow &&
2748 	    !On_stairs(u.ux, u.uy) && (!IS_FURNITURE(levl[u.ux][u.uy].typ) &&
2749 	    !IS_ROCK(levl[u.ux][u.uy].typ) &&
2750 	    !closed_door(u.ux, u.uy) && !t_at(u.ux, u.uy))) {
2751 		struct trap *ttmp;
2752 		ttmp = maketrap(u.ux, u.uy, ICE_TRAP);
2753 		    if (ttmp) {
2754 			ttmp->madeby_u = 1;
2755 			ttmp->tseen = 1;
2756 			newsym(u.ux, u.uy);
2757 			    if (*in_rooms(u.ux,u.uy,SHOPBASE)) {
2758 				add_damage(u.ux, u.uy, 0L);
2759 			    }
2760 		    }
2761 	}
2762 	break;
2763     case WAN_MAGIC_MISSILE:
2764     wanexpl:
2765 	explode(u.ux, u.uy,
2766 		(obj->otyp - WAN_MAGIC_MISSILE), dmg, WAND_CLASS, expltype);
2767 	makeknown(obj->otyp);	/* explode described the effect */
2768 	/* make magic trap if you broke a wand of magic missile */
2769 	if ((obj->spe > 2) && rn2(obj->spe - 2) && !u.uswallow &&
2770 	    !On_stairs(u.ux, u.uy) && (!IS_FURNITURE(levl[u.ux][u.uy].typ) &&
2771 	    !IS_ROCK(levl[u.ux][u.uy].typ) &&
2772 	    !closed_door(u.ux, u.uy) && !t_at(u.ux, u.uy))) {
2773 		struct trap *ttmp;
2774 		ttmp = maketrap(u.ux, u.uy, MAGIC_TRAP);
2775 		    if (ttmp) {
2776 			ttmp->madeby_u = 1;
2777 			ttmp->tseen = 1;
2778 			newsym(u.ux, u.uy);
2779 			    if (*in_rooms(u.ux,u.uy,SHOPBASE)) {
2780 				add_damage(u.ux, u.uy, 0L);
2781 			    }
2782 		    }
2783 	}
2784 	goto discard_broken_wand;
2785     case WAN_STRIKING:
2786 	/* we want this before the explosion instead of at the very end */
2787 	pline("A wall of force smashes down around you!");
2788 	dmg = d(1 + obj->spe,6);	/* normally 2d12 */
2789 	break;
2790     case WAN_TELEPORTATION:
2791 	/* WAC make tele trap if you broke a wand of teleport */
2792 	if ((obj->spe > 2) && rn2(obj->spe - 2) && !level.flags.noteleport &&
2793 	    !u.uswallow && !On_stairs(u.ux, u.uy) && (!IS_FURNITURE(levl[u.ux][u.uy].typ) &&
2794 	    !IS_ROCK(levl[u.ux][u.uy].typ) &&
2795 	    !closed_door(u.ux, u.uy) && !t_at(u.ux, u.uy))) {
2796 		struct trap *ttmp;
2797 		ttmp = maketrap(u.ux, u.uy, TELEP_TRAP);
2798 		    if (ttmp) {
2799 			ttmp->madeby_u = 1;
2800 			ttmp->tseen = 1;
2801 			newsym(u.ux, u.uy); /* if our hero happens to be invisible */
2802 			    if (*in_rooms(u.ux,u.uy,SHOPBASE)) {
2803 				/* shopkeeper will remove it */
2804 				add_damage(u.ux, u.uy, 0L);
2805 			    }
2806 		    }
2807 	}
2808 	affects_objects = TRUE;
2809 	break;
2810     case WAN_POLYMORPH:
2811 	/* make poly trap if you broke a wand of polymorph */
2812 	if ((obj->spe > 2) && rn2(obj->spe - 2) && !u.uswallow &&
2813 	    !On_stairs(u.ux, u.uy) && (!IS_FURNITURE(levl[u.ux][u.uy].typ) &&
2814 	    !IS_ROCK(levl[u.ux][u.uy].typ) &&
2815 	    !closed_door(u.ux, u.uy) && !t_at(u.ux, u.uy))) {
2816 		struct trap *ttmp;
2817 		ttmp = maketrap(u.ux, u.uy, POLY_TRAP);
2818 		    if (ttmp) {
2819 			ttmp->madeby_u = 1;
2820 			ttmp->tseen = 1;
2821 			newsym(u.ux, u.uy);
2822 			    if (*in_rooms(u.ux,u.uy,SHOPBASE)) {
2823 				add_damage(u.ux, u.uy, 0L);
2824 			    }
2825 		    }
2826 	}
2827 	affects_objects = TRUE;
2828 	break;
2829     case WAN_SLEEP:
2830 	/* make sleeping gas trap if you broke a wand of sleep */
2831 	if ((obj->spe > 2) && rn2(obj->spe - 2) && !u.uswallow &&
2832 	    !On_stairs(u.ux, u.uy) && (!IS_FURNITURE(levl[u.ux][u.uy].typ) &&
2833 	    !IS_ROCK(levl[u.ux][u.uy].typ) &&
2834 	    !closed_door(u.ux, u.uy) && !t_at(u.ux, u.uy))) {
2835 		struct trap *ttmp;
2836 		ttmp = maketrap(u.ux, u.uy, SLP_GAS_TRAP);
2837 		    if (ttmp) {
2838 			ttmp->madeby_u = 1;
2839 			ttmp->tseen = 1;
2840 			newsym(u.ux, u.uy);
2841 			    if (*in_rooms(u.ux,u.uy,SHOPBASE)) {
2842 				add_damage(u.ux, u.uy, 0L);
2843 			    }
2844 		    }
2845 	}
2846 	break;
2847     case WAN_CANCELLATION:
2848 	/* make anti-magic trap if you broke a wand of cancellation */
2849 	if ((obj->spe > 2) && rn2(obj->spe - 2) && !u.uswallow &&
2850 	    !On_stairs(u.ux, u.uy) && (!IS_FURNITURE(levl[u.ux][u.uy].typ) &&
2851 	    !IS_ROCK(levl[u.ux][u.uy].typ) &&
2852 	    !closed_door(u.ux, u.uy) && !t_at(u.ux, u.uy))) {
2853 		struct trap *ttmp;
2854 		ttmp = maketrap(u.ux, u.uy, ANTI_MAGIC);
2855 		    if (ttmp) {
2856 			ttmp->madeby_u = 1;
2857 			ttmp->tseen = 1;
2858 			newsym(u.ux, u.uy);
2859 			    if (*in_rooms(u.ux,u.uy,SHOPBASE)) {
2860 				add_damage(u.ux, u.uy, 0L);
2861 			    }
2862 		    }
2863 	}
2864 	affects_objects = TRUE;
2865 	break;
2866     case WAN_UNDEAD_TURNING:
2867 	affects_objects = TRUE;
2868 	break;
2869     default:
2870 	break;
2871     }
2872 
2873     /* magical explosion and its visual effect occur before specific effects */
2874     explode(obj->ox, obj->oy, 0, rnd(dmg), WAND_CLASS, EXPL_MAGICAL);
2875 
2876     /* this makes it hit us last, so that we can see the action first */
2877     for (i = 0; i <= 8; i++) {
2878 	bhitpos.x = x = obj->ox + xdir[i];
2879 	bhitpos.y = y = obj->oy + ydir[i];
2880 	if (!isok(x,y)) continue;
2881 
2882 	if (obj->otyp == WAN_DIGGING) {
2883 	    if(dig_check(BY_OBJECT, FALSE, x, y)) {
2884 		if (IS_WALL(levl[x][y].typ) || IS_DOOR(levl[x][y].typ)) {
2885 		    /* normally, pits and holes don't anger guards, but they
2886 		     * do if it's a wall or door that's being dug */
2887 		    watch_dig((struct monst *)0, x, y, TRUE);
2888 		    if (*in_rooms(x,y,SHOPBASE)) shop_damage = TRUE;
2889 		}
2890 		digactualhole(x, y, BY_OBJECT,
2891 			      (rn2(obj->spe) < 3 || !Can_dig_down(&u.uz)) ?
2892 			       PIT : HOLE);
2893 	    }
2894 	    continue;
2895 	} else if(obj->otyp == WAN_CREATE_MONSTER) {
2896 	    /* u.ux,u.uy creates it near you--x,y might create it in rock */
2897 	    (void) makemon((struct permonst *)0, u.ux, u.uy, NO_MM_FLAGS);
2898 	    continue;
2899 	} else {
2900 	    if (x == u.ux && y == u.uy) {
2901 		/* teleport objects first to avoid race with tele control and
2902 		   autopickup.  Other wand/object effects handled after
2903 		   possible wand damage is assessed */
2904 		if (obj->otyp == WAN_TELEPORTATION &&
2905 		    affects_objects && level.objects[x][y]) {
2906 		    (void) bhitpile(obj, bhito, x, y);
2907 		    if (flags.botl) bot();		/* potion effects */
2908 		}
2909 		damage = zapyourself(obj, FALSE);
2910 		if (damage) {
2911 		    Sprintf(buf, "killed %sself by breaking a wand", uhim());
2912 		    losehp(damage, buf, NO_KILLER_PREFIX);
2913 		}
2914 		if (flags.botl) bot();		/* blindness */
2915 	    } else if ((mon = m_at(x, y)) != 0) {
2916 		(void) bhitm(mon, obj);
2917 	     /* if (flags.botl) bot(); */
2918 	    }
2919 	    if (affects_objects && level.objects[x][y]) {
2920 		(void) bhitpile(obj, bhito, x, y);
2921 		if (flags.botl) bot();		/* potion effects */
2922 	    }
2923 	}
2924     }
2925 
2926     /* Note: if player fell thru, this call is a no-op.
2927        Damage is handled in digactualhole in that case */
2928     if (shop_damage) pay_for_damage("dig into", FALSE);
2929 
2930     if (obj->otyp == WAN_LIGHT)
2931 	litroom(TRUE, obj);	/* only needs to be done once */
2932 
2933  discard_broken_wand:
2934     obj = current_wand;		/* [see dozap() and destroy_item()] */
2935     current_wand = 0;
2936     if (obj)
2937 	delobj(obj);
2938     nomul(0, 0);
2939     return 1;
2940 }
2941 
2942 STATIC_OVL boolean
uhave_graystone()2943 uhave_graystone()
2944 {
2945 	register struct obj *otmp;
2946 
2947 	for(otmp = invent; otmp; otmp = otmp->nobj)
2948 		if(is_graystone(otmp))
2949 			return TRUE;
2950 	return FALSE;
2951 }
2952 
2953 STATIC_OVL int
do_flip_coin(obj)2954 do_flip_coin(obj)
2955 struct obj *obj;
2956 {
2957 #ifndef GOLDOBJ
2958     u.ugold += obj->quan;
2959     dealloc_obj(obj);
2960 #endif
2961 
2962     if (nohands(youmonst.data)) {
2963 	pline("And how would you flip the coin without hands?");
2964 	return 0;
2965     } else if (!freehand()) {
2966 	You("need at least one free %s.", body_part(HAND));
2967 	return 0;
2968     } else if (Underwater) {
2969 	pline("This coin wasn't designed to be flipped underwater.");
2970 	return 0;
2971     }
2972 
2973     You("flip %s coin.",
2974 #ifndef GOLDOBJ
2975 	(u.ugold > 1)
2976 #else
2977 	(obj->quan > 1)
2978 #endif
2979 	? "a" : "the");
2980 
2981     if (!Fumbling && !Glib && !Blind &&
2982 	((ACURR(A_DEX) + Luck) > 0) && rn2((ACURR(A_DEX) + Luck))) {
2983 	/* coin flipping is independent of other random
2984 	   functions, so use rand() intentionally here */
2985 	xchar ht = rand() % 2;
2986 	if (!Hallucination){
2987 	    pline("%s.", ht ? "Heads" : "Tails");
2988 	} else {
2989 	    /* purposefully doesn't use ht -- can't correctly see flip */
2990 	    pline("%s.", rn2(2) ? "Happy" : "Sad");
2991 	}
2992 	if (Hallucination && ht && !rn2(8))
2993 	    pline("Oh my, it %s at you!", rn2(2) ? "grins" : "winks");
2994     } else {
2995 	struct obj *gold;
2996 	You("try to catch the coin but it slips from your %s.",
2997 	    makeplural(body_part(HAND)));
2998 #ifndef GOLDOBJ
2999 	gold = mkgoldobj(1);
3000 #else
3001 	if (obj->quan > 1) gold = splitobj(obj, 1L);
3002 	else gold = obj;
3003 #endif
3004 	dropx(gold);
3005     }
3006     return 1;
3007 }
3008 
3009 STATIC_OVL void
add_class(cl,class)3010 add_class(cl, class)
3011 char *cl;
3012 char class;
3013 {
3014 	char tmp[2];
3015 	tmp[0] = class;
3016 	tmp[1] = '\0';
3017 	Strcat(cl, tmp);
3018 }
3019 
3020 int
doapply()3021 doapply()
3022 {
3023 	struct obj *obj;
3024 	register int res = 1;
3025 	char class_list[MAXOCLASSES+2];
3026 
3027 	if(check_capacity((char *)0)) return (0);
3028 
3029 	if (carrying(POT_OIL) || uhave_graystone())
3030 		Strcpy(class_list, tools_too);
3031 	else
3032 		Strcpy(class_list, tools),
3033 		add_class(class_list, SPBOOK_CLASS);
3034 	if (carrying(CREAM_PIE) || carrying(EUCALYPTUS_LEAF))
3035 		add_class(class_list, FOOD_CLASS);
3036 
3037 	obj = getobj(class_list, "use or apply");
3038 	if(!obj) return 0;
3039 
3040 	if (obj->oartifact && !touch_artifact(obj, &youmonst))
3041 	    return 1;	/* evading your grasp costs a turn; just be
3042 			   grateful that you don't drop it as well */
3043 
3044 	if (obj->oclass == WAND_CLASS)
3045 	    return do_break_wand(obj);
3046 	else if (obj->oclass == COIN_CLASS)
3047 	    return do_flip_coin(obj);
3048 	switch(obj->otyp){
3049 	case BLINDFOLD:
3050 	case LENSES:
3051 		if (obj == ublindf) {
3052 		    if (!cursed(obj)) Blindf_off(obj);
3053 		} else if (!ublindf)
3054 		    Blindf_on(obj);
3055 		else You("are already %s.",
3056 			ublindf->otyp == TOWEL ?     "covered by a towel" :
3057 			ublindf->otyp == BLINDFOLD ? "wearing a blindfold" :
3058 						     "wearing lenses");
3059 		break;
3060 	case CREAM_PIE:
3061 		res = use_cream_pie(obj);
3062 		break;
3063 	case BULLWHIP:
3064 		res = use_whip(obj);
3065 		break;
3066 	case GRAPPLING_HOOK:
3067 		res = use_grapple(obj);
3068 		break;
3069 	case LARGE_BOX:
3070 	case CHEST:
3071 	case ICE_BOX:
3072 	case SACK:
3073 	case BAG_OF_HOLDING:
3074 	case OILSKIN_SACK:
3075 	case IRON_SAFE:
3076 		/* return immediately as the container might be destroyed */
3077 		return use_container(obj, 1);
3078 	case BAG_OF_TRICKS:
3079 		res = bagotricks(obj);
3080 		break;
3081 	case CAN_OF_GREASE:
3082 		use_grease(obj);
3083 		break;
3084 	case LOCK_PICK:
3085 #ifdef TOURIST
3086 	case CREDIT_CARD:
3087 #endif
3088 	case SKELETON_KEY:
3089 		(void) pick_lock(obj,0,0,FALSE);
3090 		break;
3091 	case PICK_AXE:
3092 	case DWARVISH_MATTOCK:
3093 		res = use_pick_axe(obj);
3094 		break;
3095 	case TINNING_KIT:
3096 		use_tinning_kit(obj);
3097 		break;
3098 	case LEASH:
3099 		use_leash(obj);
3100 		break;
3101 #ifdef STEED
3102 	case SADDLE:
3103 		res = use_saddle(obj);
3104 		break;
3105 #endif
3106 	case MAGIC_WHISTLE:
3107 		use_magic_whistle(obj);
3108 		break;
3109 	case TIN_WHISTLE:
3110 		use_whistle(obj);
3111 		break;
3112 	case EUCALYPTUS_LEAF:
3113 		/* MRKR: Every Australian knows that a gum leaf makes an */
3114 		/*	 excellent whistle, especially if your pet is a  */
3115 		/*	 tame kangaroo named Skippy.			 */
3116 		if (obj->blessed) {
3117 		    use_magic_whistle(obj);
3118 		    /* sometimes the blessing will be worn off */
3119 		    if (!rn2(49)) {
3120 			if (!Blind) {
3121 			    char buf[BUFSZ];
3122 
3123 			    pline("%s %s %s.", Shk_Your(buf, obj),
3124 				  aobjnam(obj, "glow"), hcolor("brown"));
3125 			    obj->bknown = 1;
3126 			}
3127 			unbless(obj);
3128 		    }
3129 		} else {
3130 		    use_whistle(obj);
3131 		}
3132 		break;
3133 	case STETHOSCOPE:
3134 		res = use_stethoscope(obj);
3135 		break;
3136 	case MIRROR:
3137 		res = use_mirror(obj);
3138 		break;
3139 	case BELL:
3140 	case BELL_OF_OPENING:
3141 		use_bell(&obj);
3142 		break;
3143 	case CANDELABRUM_OF_INVOCATION:
3144 		use_candelabrum(obj);
3145 		break;
3146 	case WAX_CANDLE:
3147 	case TALLOW_CANDLE:
3148 		use_candle(&obj);
3149 		break;
3150 	case OIL_LAMP:
3151 	case MAGIC_LAMP:
3152 	case BRASS_LANTERN:
3153 		use_lamp(obj);
3154 		break;
3155 	case POT_OIL:
3156 		light_cocktail(obj);
3157 		break;
3158 #ifdef TOURIST
3159 	case EXPENSIVE_CAMERA:
3160 		res = use_camera(obj);
3161 		break;
3162 #endif
3163 	case TOWEL:
3164 		res = use_towel(obj);
3165 		break;
3166 	case CRYSTAL_BALL:
3167 		use_crystal_ball(obj);
3168 		break;
3169 	case MAGIC_MARKER:
3170 		res = dowrite(obj);
3171 		break;
3172 	case TIN_OPENER:
3173 		if(!carrying(TIN)) {
3174 			You("have no tin to open.");
3175 			goto xit;
3176 		}
3177 		You("cannot open a tin without eating or discarding its contents.");
3178 		if(flags.verbose)
3179 			pline("In order to eat, use the 'e' command.");
3180 		if(obj != uwep)
3181     pline("Opening the tin will be much easier if you wield the tin opener.");
3182 		goto xit;
3183 
3184 	case FIGURINE:
3185 		use_figurine(&obj);
3186 		break;
3187 	case UNICORN_HORN:
3188 		fix_attributes_and_properties(obj, 0);
3189 		break;
3190 	case WOODEN_FLUTE:
3191 	case MAGIC_FLUTE:
3192 	case TOOLED_HORN:
3193 	case FROST_HORN:
3194 	case FIRE_HORN:
3195 	case WOODEN_HARP:
3196 	case MAGIC_HARP:
3197 	case BUGLE:
3198 	case LEATHER_DRUM:
3199 	case DRUM_OF_EARTHQUAKE:
3200 		res = do_play_instrument(obj);
3201 		break;
3202 	case HORN_OF_PLENTY:	/* not a musical instrument */
3203 		if (obj->spe > 0) {
3204 		    struct obj *otmp;
3205 		    const char *what;
3206 
3207 		    consume_obj_charge(obj, TRUE);
3208 		    if (!rn2(13)) {
3209 			otmp = mkobj(POTION_CLASS, FALSE);
3210 			if (objects[otmp->otyp].oc_magic) do {
3211 			    otmp->otyp = rnd_class(POT_BOOZE, POT_WATER);
3212 				if (!rn2(131)) {       /* this number is very large on purpose */
3213 					otmp->otyp = (!rn2(5)) ? POT_VAMPIRE_BLOOD : POT_BLOOD;
3214 				}
3215 			} while (otmp->otyp == POT_SICKNESS);
3216 			what = "A potion";
3217 		    } else {
3218 			otmp = mkobj(FOOD_CLASS, FALSE);
3219 			if (otmp->otyp == FOOD_RATION && !rn2(7))
3220 			    otmp->otyp = LUMP_OF_ROYAL_JELLY;
3221 			what = "Some food";
3222 		    }
3223 		    pline("%s spills out.", what);
3224 		    otmp->blessed = obj->blessed;
3225 		    otmp->cursed = obj->cursed;
3226 		    otmp->bknown = obj->bknown;
3227 		    otmp->owt = weight(otmp);
3228 		    otmp = hold_another_object(otmp, u.uswallow ?
3229 				       "Oops!  %s out of your reach!" :
3230 					(Is_airlevel(&u.uz) ||
3231 					 Is_waterlevel(&u.uz) ||
3232 					 levl[u.ux][u.uy].typ < IRONBARS ||
3233 					 levl[u.ux][u.uy].typ >= ICE) ?
3234 					       "Oops!  %s away from you!" :
3235 					       "Oops!  %s to the floor!",
3236 					       The(aobjnam(otmp, "slip")),
3237 					       (const char *)0);
3238 		    makeknown(HORN_OF_PLENTY);
3239 		} else
3240 		    pline("%s", nothing_happens);
3241 		break;
3242 	case LAND_MINE:
3243 	case BEARTRAP:
3244 		use_trap(obj);
3245 		break;
3246 	case FLINT:
3247 	case LUCKSTONE:
3248 	case LOADSTONE:
3249 	case TOUCHSTONE:
3250 		use_stone(obj);
3251 		break;
3252 	case SPE_CONE_OF_COLD:
3253 	case SPE_FIREBALL:
3254 	case SPE_FORCE_BOLT:
3255 	case SPE_SLEEP:
3256 	case SPE_MAGIC_MISSILE:
3257 	case SPE_KNOCK:
3258 	case SPE_SLOW_MONSTER:
3259 	case SPE_WIZARD_LOCK:
3260 	case SPE_DIG:
3261 	case SPE_TURN_UNDEAD:
3262 	case SPE_POLYMORPH:
3263 	case SPE_TELEPORT_AWAY:
3264 	case SPE_CANCELLATION:
3265 	case SPE_FINGER_OF_DEATH:
3266 	case SPE_LIGHT:
3267 	case SPE_DETECT_UNSEEN:
3268 	case SPE_HEALING:
3269 	case SPE_EXTRA_HEALING:
3270 	case SPE_DRAIN_LIFE:
3271 	case SPE_STONE_TO_FLESH:
3272 	case SPE_REMOVE_CURSE:
3273 	case SPE_CONFUSE_MONSTER:
3274 	case SPE_DETECT_FOOD:
3275 	case SPE_CAUSE_FEAR:
3276 	case SPE_CHARM_MONSTER:
3277 	case SPE_MAGIC_MAPPING:
3278 	case SPE_CREATE_MONSTER:
3279 	case SPE_IDENTIFY:
3280 	case SPE_HASTE_SELF:
3281 	case SPE_DETECT_TREASURE:
3282 	case SPE_DETECT_MONSTERS:
3283 	case SPE_LEVITATION:
3284 	case SPE_RESTORE_ABILITY:
3285 	case SPE_INVISIBILITY:
3286 	case SPE_CURE_BLINDNESS:
3287 	case SPE_CURE_SICKNESS:
3288 	case SPE_CREATE_FAMILIAR:
3289 	case SPE_CLAIRVOYANCE:
3290 	case SPE_PROTECTION:
3291 	case SPE_JUMPING:
3292 		if (Underwater) {
3293 		    pline("You don't want to get the pages even more soggy, do you?");
3294 		    break;
3295 		} else {
3296 		    You("flip through the pages of the spellbook.");
3297 		    if (!Blind && Hallucination) {
3298 			You("enjoy the animation in the margins.");
3299 		    } else if (Blind) {
3300 			pline("The pages feel %s.", Hallucination ?
3301 				"freshly picked" : "rough and dry");
3302 		    /* This assumes that MAX_SPELL_STUDY is defined as 3 */
3303 		    } else if (obj->spestudied == 0) {
3304 		 	pline("The ink in this spellbook is fresh.");
3305 		    } else if (obj->spestudied == 1) {
3306 		 	pline("The ink in this spellbook is slightly faded.");
3307 		    } else if (obj->spestudied == 2) {
3308 		 	pline("The ink in this spellbook is very faded.");
3309 		    } else if (obj->spestudied == 3) {
3310 		 	pline("The ink in this spellbook is extremely faded.");
3311 		    } else if (obj->spestudied > 3) {
3312 		 	pline("The ink in this spellbook is barely visible.");
3313 		    }
3314 		}
3315 		break;
3316 	case SPE_BLANK_PAPER:
3317 		if (Underwater) {
3318 		    pline("You don't want to get the pages even more soggy, do you?");
3319 		    break;
3320 		} else {
3321 		    You("flip through the pages of the spellbook.");
3322 		    if (Blind) {
3323 			pline("The pages feel %s.", Hallucination ?
3324 				"freshly picked" : "rough and dry");
3325 		    } else {
3326 			pline("This spellbook %s.", Hallucination ?
3327 				"doesn't have much of a plot" : "has nothing written in it");
3328 		    }
3329 		}
3330 		makeknown(obj->otyp);
3331 		break;
3332 	case SPE_BOOK_OF_THE_DEAD:
3333 		if (Underwater) {
3334 		    pline("You don't want to get the pages even more soggy, do you?");
3335 		    break;
3336 		} else {
3337 		    You("flip through the pages of the spellbook.");
3338 		    You_hear("the pages make an unpleasant %s sound.",
3339 				Hallucination ? "chuckling" : "rustling");
3340 		}
3341 		break;
3342 	default:
3343 		/* Pole-weapons can strike at a distance */
3344 		if (is_pole(obj)) {
3345 			res = use_pole(obj);
3346 			break;
3347 		} else if (is_pick(obj) || is_axe(obj)) {
3348 			res = use_pick_axe(obj);
3349 			break;
3350 		}
3351 		pline("Sorry, I don't know how to use that.");
3352 	xit:
3353 		nomul(0, 0);
3354 		return 0;
3355 	}
3356 	if (res && obj && obj->oartifact) arti_speak(obj);
3357 	nomul(0, 0);
3358 	return res;
3359 }
3360 
3361 /* Keep track of unfixable troubles for purposes of messages saying you feel
3362  * great.
3363  */
3364 int
unfixable_trouble_count(is_horn)3365 unfixable_trouble_count(is_horn)
3366 	boolean is_horn;
3367 {
3368 	int unfixable_trbl = 0;
3369 
3370 	if (Stoned) unfixable_trbl++;
3371 	if (Strangled) unfixable_trbl++;
3372 	if (Wounded_legs
3373 #ifdef STEED
3374 		    && !u.usteed
3375 #endif
3376 				) unfixable_trbl++;
3377 	if (Slimed) unfixable_trbl++;
3378 	/* lycanthropy is not desirable, but it doesn't actually make you feel
3379 	   bad */
3380 
3381 	/* we'll assume that intrinsic stunning from being a bat/stalker
3382 	   doesn't make you feel bad */
3383 	if (!is_horn) {
3384 	    if (Confusion) unfixable_trbl++;
3385 	    if (Sick) unfixable_trbl++;
3386 	    if (HHallucination) unfixable_trbl++;
3387 	    if (Vomiting) unfixable_trbl++;
3388 	    if (HStun) unfixable_trbl++;
3389 	}
3390 	return unfixable_trbl;
3391 }
3392 
3393 /*apply.c*/
3394