OSDN Git Service

import nethack-3.6.0
[jnethack/source.git] / src / steal.c
1 /* NetHack 3.6  steal.c $NHDT-Date: 1446713643 2015/11/05 08:54:03 $  $NHDT-Branch: master $:$NHDT-Revision: 1.65 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed.  See license for details. */
4
5 #include "hack.h"
6
7 STATIC_PTR int NDECL(stealarm);
8
9 STATIC_DCL const char *FDECL(equipname, (struct obj *));
10
11 STATIC_OVL const char *
12 equipname(otmp)
13 register struct obj *otmp;
14 {
15     return ((otmp == uarmu)
16                 ? "shirt"
17                 : (otmp == uarmf)
18                       ? "boots"
19                       : (otmp == uarms)
20                             ? "shield"
21                             : (otmp == uarmg)
22                                   ? "gloves"
23                                   : (otmp == uarmc)
24                                         ? cloak_simple_name(otmp)
25                                         : (otmp == uarmh)
26                                               ? helm_simple_name(otmp)
27                                               : suit_simple_name(otmp));
28 }
29
30 /* proportional subset of gold; return value actually fits in an int */
31 long
32 somegold(lmoney)
33 long lmoney;
34 {
35 #ifdef LINT /* long conv. ok */
36     int igold = 0;
37 #else
38     int igold = (lmoney >= (long) LARGEST_INT) ? LARGEST_INT : (int) lmoney;
39 #endif
40
41     if (igold < 50)
42         ; /* all gold */
43     else if (igold < 100)
44         igold = rn1(igold - 25 + 1, 25);
45     else if (igold < 500)
46         igold = rn1(igold - 50 + 1, 50);
47     else if (igold < 1000)
48         igold = rn1(igold - 100 + 1, 100);
49     else if (igold < 5000)
50         igold = rn1(igold - 500 + 1, 500);
51     else if (igold < 10000)
52         igold = rn1(igold - 1000 + 1, 1000);
53     else
54         igold = rn1(igold - 5000 + 1, 5000);
55
56     return (long) igold;
57 }
58
59 /*
60  * Find the first (and hopefully only) gold object in a chain.
61  * Used when leprechaun (or you as leprechaun) looks for
62  * someone else's gold.  Returns a pointer so the gold may
63  * be seized without further searching.
64  * May search containers too.
65  * Deals in gold only, as leprechauns don't care for lesser coins.
66 */
67 struct obj *
68 findgold(chain)
69 register struct obj *chain;
70 {
71     while (chain && chain->otyp != GOLD_PIECE)
72         chain = chain->nobj;
73     return chain;
74 }
75
76 /*
77  * Steal gold coins only.  Leprechauns don't care for lesser coins.
78 */
79 void
80 stealgold(mtmp)
81 register struct monst *mtmp;
82 {
83     register struct obj *fgold = g_at(u.ux, u.uy);
84     register struct obj *ygold;
85     register long tmp;
86     struct monst *who;
87     const char *whose, *what;
88
89     /* skip lesser coins on the floor */
90     while (fgold && fgold->otyp != GOLD_PIECE)
91         fgold = fgold->nexthere;
92
93     /* Do you have real gold? */
94     ygold = findgold(invent);
95
96     if (fgold && (!ygold || fgold->quan > ygold->quan || !rn2(5))) {
97         obj_extract_self(fgold);
98         add_to_minv(mtmp, fgold);
99         newsym(u.ux, u.uy);
100         if (u.usteed) {
101             who = u.usteed;
102             whose = s_suffix(y_monnam(who));
103             what = makeplural(mbodypart(who, FOOT));
104         } else {
105             who = &youmonst;
106             whose = "your";
107             what = makeplural(body_part(FOOT));
108         }
109         /* [ avoid "between your rear regions" :-] */
110         if (slithy(who->data))
111             what = "coils";
112         /* reduce "rear hooves/claws" to "hooves/claws" */
113         if (!strncmp(what, "rear ", 5))
114             what += 5;
115         pline("%s quickly snatches some gold from %s %s %s!", Monnam(mtmp),
116               (Levitation || Flying) ? "beneath" : "between", whose, what);
117         if (!ygold || !rn2(5)) {
118             if (!tele_restrict(mtmp))
119                 (void) rloc(mtmp, TRUE);
120             monflee(mtmp, 0, FALSE, FALSE);
121         }
122     } else if (ygold) {
123         const int gold_price = objects[GOLD_PIECE].oc_cost;
124
125         tmp = (somegold(money_cnt(invent)) + gold_price - 1) / gold_price;
126         tmp = min(tmp, ygold->quan);
127         if (tmp < ygold->quan)
128             ygold = splitobj(ygold, tmp);
129         else
130             setnotworn(ygold);
131         freeinv(ygold);
132         add_to_minv(mtmp, ygold);
133         Your("purse feels lighter.");
134         if (!tele_restrict(mtmp))
135             (void) rloc(mtmp, TRUE);
136         monflee(mtmp, 0, FALSE, FALSE);
137         context.botl = 1;
138     }
139 }
140
141 /* steal armor after you finish taking it off */
142 unsigned int stealoid; /* object to be stolen */
143 unsigned int stealmid; /* monster doing the stealing */
144
145 STATIC_PTR int
146 stealarm(VOID_ARGS)
147 {
148     register struct monst *mtmp;
149     register struct obj *otmp;
150
151     for (otmp = invent; otmp; otmp = otmp->nobj) {
152         if (otmp->o_id == stealoid) {
153             for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
154                 if (mtmp->m_id == stealmid) {
155                     if (DEADMONSTER(mtmp))
156                         impossible("stealarm(): dead monster stealing");
157                     if (!dmgtype(mtmp->data, AD_SITM)) /* polymorphed */
158                         goto botm;
159                     if (otmp->unpaid)
160                         subfrombill(otmp, shop_keeper(*u.ushops));
161                     freeinv(otmp);
162                     pline("%s steals %s!", Monnam(mtmp), doname(otmp));
163                     (void) mpickobj(mtmp, otmp); /* may free otmp */
164                     /* Implies seduction, "you gladly hand over ..."
165                        so we don't set mavenge bit here. */
166                     monflee(mtmp, 0, FALSE, FALSE);
167                     if (!tele_restrict(mtmp))
168                         (void) rloc(mtmp, TRUE);
169                     break;
170                 }
171             }
172             break;
173         }
174     }
175 botm:
176     stealoid = 0;
177     return 0;
178 }
179
180 /* An object you're wearing has been taken off by a monster (theft or
181    seduction).  Also used if a worn item gets transformed (stone to flesh). */
182 void
183 remove_worn_item(obj, unchain_ball)
184 struct obj *obj;
185 boolean unchain_ball; /* whether to unpunish or just unwield */
186 {
187     if (donning(obj))
188         cancel_don();
189     if (!obj->owornmask)
190         return;
191
192     if (obj->owornmask & W_ARMOR) {
193         if (obj == uskin) {
194             impossible("Removing embedded scales?");
195             skinback(TRUE); /* uarm = uskin; uskin = 0; */
196         }
197         if (obj == uarm)
198             (void) Armor_off();
199         else if (obj == uarmc)
200             (void) Cloak_off();
201         else if (obj == uarmf)
202             (void) Boots_off();
203         else if (obj == uarmg)
204             (void) Gloves_off();
205         else if (obj == uarmh)
206             (void) Helmet_off();
207         else if (obj == uarms)
208             (void) Shield_off();
209         else if (obj == uarmu)
210             (void) Shirt_off();
211         /* catchall -- should never happen */
212         else
213             setworn((struct obj *) 0, obj->owornmask & W_ARMOR);
214     } else if (obj->owornmask & W_AMUL) {
215         Amulet_off();
216     } else if (obj->owornmask & W_RING) {
217         Ring_gone(obj);
218     } else if (obj->owornmask & W_TOOL) {
219         Blindf_off(obj);
220     } else if (obj->owornmask & W_WEAPON) {
221         if (obj == uwep)
222             uwepgone();
223         if (obj == uswapwep)
224             uswapwepgone();
225         if (obj == uquiver)
226             uqwepgone();
227     }
228
229     if (obj->owornmask & (W_BALL | W_CHAIN)) {
230         if (unchain_ball)
231             unpunish();
232     } else if (obj->owornmask) {
233         /* catchall */
234         setnotworn(obj);
235     }
236 }
237
238 /* Returns 1 when something was stolen (or at least, when N should flee now)
239  * Returns -1 if the monster died in the attempt
240  * Avoid stealing the object stealoid
241  * Nymphs and monkeys won't steal coins
242  */
243 int
244 steal(mtmp, objnambuf)
245 struct monst *mtmp;
246 char *objnambuf;
247 {
248     struct obj *otmp;
249     int tmp, could_petrify, armordelay, olddelay, named = 0, retrycnt = 0;
250     boolean monkey_business, /* true iff an animal is doing the thievery */
251         was_doffing;
252
253     if (objnambuf)
254         *objnambuf = '\0';
255     /* the following is true if successful on first of two attacks. */
256     if (!monnear(mtmp, u.ux, u.uy))
257         return 0;
258
259     /* food being eaten might already be used up but will not have
260        been removed from inventory yet; we don't want to steal that,
261        so this will cause it to be removed now */
262     if (occupation)
263         (void) maybe_finished_meal(FALSE);
264
265     if (!invent || (inv_cnt(FALSE) == 1 && uskin)) {
266     nothing_to_steal:
267         /* Not even a thousand men in armor can strip a naked man. */
268         if (Blind)
269             pline("Somebody tries to rob you, but finds nothing to steal.");
270         else
271             pline("%s tries to rob you, but there is nothing to steal!",
272                   Monnam(mtmp));
273         return 1; /* let her flee */
274     }
275
276     monkey_business = is_animal(mtmp->data);
277     if (monkey_business || uarmg) {
278         ; /* skip ring special cases */
279     } else if (Adornment & LEFT_RING) {
280         otmp = uleft;
281         goto gotobj;
282     } else if (Adornment & RIGHT_RING) {
283         otmp = uright;
284         goto gotobj;
285     }
286
287 retry:
288     tmp = 0;
289     for (otmp = invent; otmp; otmp = otmp->nobj)
290         if ((!uarm || otmp != uarmc) && otmp != uskin
291             && otmp->oclass != COIN_CLASS)
292             tmp += (otmp->owornmask & (W_ARMOR | W_ACCESSORY)) ? 5 : 1;
293     if (!tmp)
294         goto nothing_to_steal;
295     tmp = rn2(tmp);
296     for (otmp = invent; otmp; otmp = otmp->nobj)
297         if ((!uarm || otmp != uarmc) && otmp != uskin
298             && otmp->oclass != COIN_CLASS) {
299             tmp -= (otmp->owornmask & (W_ARMOR | W_ACCESSORY)) ? 5 : 1;
300             if (tmp < 0)
301                 break;
302         }
303     if (!otmp) {
304         impossible("Steal fails!");
305         return 0;
306     }
307     /* can't steal ring(s) while wearing gloves */
308     if ((otmp == uleft || otmp == uright) && uarmg)
309         otmp = uarmg;
310     /* can't steal gloves while wielding - so steal the wielded item. */
311     if (otmp == uarmg && uwep)
312         otmp = uwep;
313     /* can't steal armor while wearing cloak - so steal the cloak. */
314     else if (otmp == uarm && uarmc)
315         otmp = uarmc;
316     /* can't steal shirt while wearing cloak or suit */
317     else if (otmp == uarmu && uarmc)
318         otmp = uarmc;
319     else if (otmp == uarmu && uarm)
320         otmp = uarm;
321
322 gotobj:
323     if (otmp->o_id == stealoid)
324         return 0;
325
326     if (otmp->otyp == BOULDER && !throws_rocks(mtmp->data)) {
327         if (!retrycnt++)
328             goto retry;
329         goto cant_take;
330     }
331     /* animals can't overcome curse stickiness nor unlock chains */
332     if (monkey_business) {
333         boolean ostuck;
334         /* is the player prevented from voluntarily giving up this item?
335            (ignores loadstones; the !can_carry() check will catch those) */
336         if (otmp == uball)
337             ostuck = TRUE; /* effectively worn; curse is implicit */
338         else if (otmp == uquiver || (otmp == uswapwep && !u.twoweap))
339             ostuck = FALSE; /* not really worn; curse doesn't matter */
340         else
341             ostuck = ((otmp->cursed && otmp->owornmask)
342                       /* nymphs can steal rings from under
343                          cursed weapon but animals can't */
344                       || (otmp == uright && welded(uwep))
345                       || (otmp == uleft && welded(uwep) && bimanual(uwep)));
346
347         if (ostuck || can_carry(mtmp, otmp) == 0) {
348             static const char *const how[] = { "steal", "snatch", "grab",
349                                                "take" };
350         cant_take:
351             pline("%s tries to %s %s%s but gives up.", Monnam(mtmp),
352                   how[rn2(SIZE(how))],
353                   (otmp->owornmask & W_ARMOR) ? "your " : "",
354                   (otmp->owornmask & W_ARMOR) ? equipname(otmp)
355                                               : yname(otmp));
356             /* the fewer items you have, the less likely the thief
357                is going to stick around to try again (0) instead of
358                running away (1) */
359             return !rn2(inv_cnt(FALSE) / 5 + 2);
360         }
361     }
362
363     if (otmp->otyp == LEASH && otmp->leashmon) {
364         if (monkey_business && otmp->cursed)
365             goto cant_take;
366         o_unleash(otmp);
367     }
368
369     was_doffing = doffing(otmp);
370     /* stop donning/doffing now so that afternmv won't be clobbered
371        below; stop_occupation doesn't handle donning/doffing */
372     olddelay = stop_donning(otmp);
373     /* you're going to notice the theft... */
374     stop_occupation();
375
376     if (otmp->owornmask & (W_ARMOR | W_ACCESSORY)) {
377         switch (otmp->oclass) {
378         case TOOL_CLASS:
379         case AMULET_CLASS:
380         case RING_CLASS:
381         case FOOD_CLASS: /* meat ring */
382             remove_worn_item(otmp, TRUE);
383             break;
384         case ARMOR_CLASS:
385             armordelay = objects[otmp->otyp].oc_delay;
386             if (olddelay > 0 && olddelay < armordelay)
387                 armordelay = olddelay;
388             if (monkey_business) {
389                 /* animals usually don't have enough patience
390                    to take off items which require extra time */
391                 if (armordelay >= 1 && !olddelay && rn2(10))
392                     goto cant_take;
393                 remove_worn_item(otmp, TRUE);
394                 break;
395             } else {
396                 int curssv = otmp->cursed;
397                 int slowly;
398                 boolean seen = canspotmon(mtmp);
399
400                 otmp->cursed = 0;
401                 /* can't charm you without first waking you */
402                 if (Unaware)
403                     unmul((char *) 0);
404                 slowly = (armordelay >= 1 || multi < 0);
405                 if (flags.female)
406                     pline("%s charms you.  You gladly %s your %s.",
407                           !seen ? "She" : Monnam(mtmp),
408                           curssv ? "let her take"
409                                  : !slowly ? "hand over"
410                                            : was_doffing ? "continue removing"
411                                                          : "start removing",
412                           equipname(otmp));
413                 else
414                     pline("%s seduces you and %s off your %s.",
415                           !seen ? "She" : Adjmonnam(mtmp, "beautiful"),
416                           curssv
417                               ? "helps you to take"
418                               : !slowly ? "you take"
419                                         : was_doffing ? "you continue taking"
420                                                       : "you start taking",
421                           equipname(otmp));
422                 named++;
423                 /* the following is to set multi for later on */
424                 nomul(-armordelay);
425                 multi_reason = "taking off clothes";
426                 nomovemsg = 0;
427                 remove_worn_item(otmp, TRUE);
428                 otmp->cursed = curssv;
429                 if (multi < 0) {
430                     /*
431                     multi = 0;
432                     afternmv = 0;
433                     */
434                     stealoid = otmp->o_id;
435                     stealmid = mtmp->m_id;
436                     afternmv = stealarm;
437                     return 0;
438                 }
439             }
440             break;
441         default:
442             impossible("Tried to steal a strange worn thing. [%d]",
443                        otmp->oclass);
444         }
445     } else if (otmp->owornmask)
446         remove_worn_item(otmp, TRUE);
447
448     /* do this before removing it from inventory */
449     if (objnambuf)
450         Strcpy(objnambuf, yname(otmp));
451     /* set mavenge bit so knights won't suffer an
452      * alignment penalty during retaliation;
453      */
454     mtmp->mavenge = 1;
455
456     if (otmp->unpaid)
457         subfrombill(otmp, shop_keeper(*u.ushops));
458     freeinv(otmp);
459     pline("%s stole %s.", named ? "She" : Monnam(mtmp), doname(otmp));
460     could_petrify =
461         (otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm]));
462     (void) mpickobj(mtmp, otmp); /* may free otmp */
463     if (could_petrify && !(mtmp->misc_worn_check & W_ARMG)) {
464         minstapetrify(mtmp, TRUE);
465         return -1;
466     }
467     return (multi < 0) ? 0 : 1;
468 }
469
470 /* Returns 1 if otmp is free'd, 0 otherwise. */
471 int
472 mpickobj(mtmp, otmp)
473 register struct monst *mtmp;
474 register struct obj *otmp;
475 {
476     int freed_otmp;
477     boolean snuff_otmp = FALSE;
478
479     /* if monster is acquiring a thrown or kicked object, the throwing
480        or kicking code shouldn't continue to track and place it */
481     if (otmp == thrownobj)
482         thrownobj = 0;
483     else if (otmp == kickedobj)
484         kickedobj = 0;
485     /* don't want hidden light source inside the monster; assumes that
486        engulfers won't have external inventories; whirly monsters cause
487        the light to be extinguished rather than letting it shine thru */
488     if (obj_sheds_light(otmp) && attacktype(mtmp->data, AT_ENGL)) {
489         /* this is probably a burning object that you dropped or threw */
490         if (u.uswallow && mtmp == u.ustuck && !Blind)
491             pline("%s out.", Tobjnam(otmp, "go"));
492         snuff_otmp = TRUE;
493     }
494     /* for hero owned object on shop floor, mtmp is taking possession
495        and if it's eventually dropped in a shop, shk will claim it */
496     if (!mtmp->mtame)
497         otmp->no_charge = 0;
498     /* Must do carrying effects on object prior to add_to_minv() */
499     carry_obj_effects(otmp);
500     /* add_to_minv() might free otmp [if merged with something else],
501        so we have to call it after doing the object checks */
502     freed_otmp = add_to_minv(mtmp, otmp);
503     /* and we had to defer this until object is in mtmp's inventory */
504     if (snuff_otmp)
505         snuff_light_source(mtmp->mx, mtmp->my);
506     return freed_otmp;
507 }
508
509 void
510 stealamulet(mtmp)
511 struct monst *mtmp;
512 {
513     struct obj *otmp = (struct obj *) 0;
514     int real = 0, fake = 0;
515
516     /* select the artifact to steal */
517     if (u.uhave.amulet) {
518         real = AMULET_OF_YENDOR;
519         fake = FAKE_AMULET_OF_YENDOR;
520     } else if (u.uhave.questart) {
521         for (otmp = invent; otmp; otmp = otmp->nobj)
522             if (is_quest_artifact(otmp))
523                 break;
524         if (!otmp)
525             return; /* should we panic instead? */
526     } else if (u.uhave.bell) {
527         real = BELL_OF_OPENING;
528         fake = BELL;
529     } else if (u.uhave.book) {
530         real = SPE_BOOK_OF_THE_DEAD;
531     } else if (u.uhave.menorah) {
532         real = CANDELABRUM_OF_INVOCATION;
533     } else
534         return; /* you have nothing of special interest */
535
536     if (!otmp) {
537         /* If we get here, real and fake have been set up. */
538         for (otmp = invent; otmp; otmp = otmp->nobj)
539             if (otmp->otyp == real || (otmp->otyp == fake && !mtmp->iswiz))
540                 break;
541     }
542
543     if (otmp) { /* we have something to snatch */
544         if (otmp->owornmask)
545             remove_worn_item(otmp, TRUE);
546         if (otmp->unpaid)
547             subfrombill(otmp, shop_keeper(*u.ushops));
548         freeinv(otmp);
549         /* mpickobj wont merge otmp because none of the above things
550            to steal are mergable */
551         (void) mpickobj(mtmp, otmp); /* may merge and free otmp */
552         pline("%s stole %s!", Monnam(mtmp), doname(otmp));
553         if (can_teleport(mtmp->data) && !tele_restrict(mtmp))
554             (void) rloc(mtmp, TRUE);
555     }
556 }
557
558 /* when a mimic gets poked with something, it might take that thing
559    (at present, only implemented for when the hero does the poking) */
560 void
561 maybe_absorb_item(mon, obj, ochance, achance)
562 struct monst *mon;
563 struct obj *obj;
564 int ochance, achance; /* percent chance for ordinary item, artifact */
565 {
566     if (obj == uball || obj == uchain || obj->oclass == ROCK_CLASS
567         || obj_resists(obj, 100 - ochance, 100 - achance)
568         || !touch_artifact(obj, mon))
569         return;
570
571     if (carried(obj)) {
572         if (obj->owornmask)
573             remove_worn_item(obj, TRUE);
574         if (obj->unpaid)
575             subfrombill(obj, shop_keeper(*u.ushops));
576         if (cansee(mon->mx, mon->my)) {
577             const char *MonName = Monnam(mon);
578
579             /* mon might be invisible; avoid "It pulls ... and absorbs it!" */
580             if (!strcmp(MonName, "It"))
581                 MonName = "Something";
582             pline("%s pulls %s away from you and absorbs %s!", MonName,
583                   yname(obj), (obj->quan > 1L) ? "them" : "it");
584         } else {
585             const char *hand_s = body_part(HAND);
586
587             if (bimanual(obj))
588                 hand_s = makeplural(hand_s);
589             pline("%s %s pulled from your %s!", upstart(yname(obj)),
590                   otense(obj, "are"), hand_s);
591         }
592         freeinv(obj);
593     } else {
594         /* not carried; presumably thrown or kicked */
595         if (canspotmon(mon))
596             pline("%s absorbs %s!", Monnam(mon), yname(obj));
597     }
598     /* add to mon's inventory */
599     (void) mpickobj(mon, obj);
600 }
601
602 /* drop one object taken from a (possibly dead) monster's inventory */
603 void
604 mdrop_obj(mon, obj, verbosely)
605 struct monst *mon;
606 struct obj *obj;
607 boolean verbosely;
608 {
609     int omx = mon->mx, omy = mon->my;
610     boolean update_mon = FALSE;
611
612     if (obj->owornmask) {
613         /* perform worn item handling if the monster is still alive */
614         if (mon->mhp > 0) {
615             mon->misc_worn_check &= ~obj->owornmask;
616             update_mon = TRUE;
617             /* don't charge for an owned saddle on dead steed (provided
618                that the hero is within the same shop at the time) */
619         } else if (mon->mtame && (obj->owornmask & W_SADDLE) && !obj->unpaid
620                    && costly_spot(omx, omy)
621                    /* being at costly_spot guarantees lev->roomno is not 0 */
622                    && index(in_rooms(u.ux, u.uy, SHOPBASE),
623                             levl[omx][omy].roomno)) {
624             obj->no_charge = 1;
625         }
626         /* this should be done even if the monster has died */
627         if (obj->owornmask & W_WEP)
628             setmnotwielded(mon, obj);
629         obj->owornmask = 0L;
630     }
631     /* obj_no_longer_held(obj); -- done by place_object */
632     if (verbosely && cansee(omx, omy))
633         pline("%s drops %s.", Monnam(mon), distant_name(obj, doname));
634     if (!flooreffects(obj, omx, omy, "fall")) {
635         place_object(obj, omx, omy);
636         stackobj(obj);
637     }
638     /* do this last, after placing obj on floor; removing steed's saddle
639        throws rider, possibly inflicting fatal damage and producing bones */
640     if (update_mon)
641         update_mon_intrinsics(mon, obj, FALSE, TRUE);
642 }
643
644 /* some monsters bypass the normal rules for moving between levels or
645    even leaving the game entirely; when that happens, prevent them from
646    taking the Amulet or invocation tools with them */
647 void
648 mdrop_special_objs(mon)
649 struct monst *mon;
650 {
651     struct obj *obj, *otmp;
652
653     for (obj = mon->minvent; obj; obj = otmp) {
654         otmp = obj->nobj;
655         /* the Amulet, invocation tools, and Rider corpses resist even when
656            artifacts and ordinary objects are given 0% resistance chance */
657         if (obj_resists(obj, 0, 0)) {
658             obj_extract_self(obj);
659             mdrop_obj(mon, obj, FALSE);
660         }
661     }
662 }
663
664 /* release the objects the creature is carrying */
665 void
666 relobj(mtmp, show, is_pet)
667 struct monst *mtmp;
668 int show;
669 boolean is_pet; /* If true, pet should keep wielded/worn items */
670 {
671     struct obj *otmp;
672     int omx = mtmp->mx, omy = mtmp->my;
673
674     /* vault guard's gold goes away rather than be dropped... */
675     if (mtmp->isgd && (otmp = findgold(mtmp->minvent)) != 0) {
676         if (canspotmon(mtmp))
677             pline("%s gold %s.", s_suffix(Monnam(mtmp)),
678                   canseemon(mtmp) ? "vanishes" : "seems to vanish");
679         obj_extract_self(otmp);
680         obfree(otmp, (struct obj *) 0);
681     } /* isgd && has gold */
682
683     while ((otmp = (is_pet ? droppables(mtmp) : mtmp->minvent)) != 0) {
684         obj_extract_self(otmp);
685         mdrop_obj(mtmp, otmp, is_pet && flags.verbose);
686     }
687
688     if (show && cansee(omx, omy))
689         newsym(omx, omy);
690 }
691
692 /*steal.c*/