Fandom

Wikihack

Source:NetHack 3.4.0/apply.c

2,034pages on
this wiki
Add New Page
Talk0

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.

Below is the full text to apply.c from the source code of NetHack 3.4.0. To link to a particular line, write [[NetHack 3.4.0/apply.c#line123]], for example.

Warning! This is the source code from an old release. For the latest release, see Source code

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

Also on Fandom

Random Wiki