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