OSDN Git Service

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