NetHack->aNetHack
[aNetHack.git] / src / steal.c
bloba973bf7a291890269428fe57a64375bcce9919bc
1 /* NetHack 3.6 steal.c $NHDT-Date: 1456618998 2016/02/28 00:23:18 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.67 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
5 #include "hack.h"
7 STATIC_PTR int NDECL(stealarm);
9 STATIC_DCL const char *FDECL(equipname, (struct obj *));
11 STATIC_OVL const char *
12 equipname(otmp)
13 register struct obj *otmp;
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));
30 /* proportional subset of gold; return value actually fits in an int */
31 long
32 somegold(lmoney)
33 long lmoney;
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
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);
56 return (long) igold;
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.
67 struct obj *
68 findgold(chain)
69 register struct obj *chain;
71 while (chain && chain->otyp != GOLD_PIECE)
72 chain = chain->nobj;
73 return chain;
77 * Steal gold coins only. Leprechauns don't care for lesser coins.
79 void
80 stealgold(mtmp)
81 register struct monst *mtmp;
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;
89 /* skip lesser coins on the floor */
90 while (fgold && fgold->otyp != GOLD_PIECE)
91 fgold = fgold->nexthere;
93 /* Do you have real gold? */
94 ygold = findgold(invent);
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));
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);
122 } else if (ygold) {
123 const int gold_price = objects[GOLD_PIECE].oc_cost;
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;
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 */
145 STATIC_PTR int
146 stealarm(VOID_ARGS)
148 register struct monst *mtmp;
149 register struct obj *otmp;
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;
172 break;
175 botm:
176 stealoid = 0;
177 return 0;
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 */
187 if (donning(obj))
188 cancel_don();
189 if (!obj->owornmask)
190 return;
192 if (obj->owornmask & W_ARMOR) {
193 if (obj == uskin) {
194 impossible("Removing embedded scales?");
195 skinback(TRUE); /* uarm = uskin; uskin = 0; */
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();
229 if (obj->owornmask & (W_BALL | W_CHAIN)) {
230 if (unchain_ball)
231 unpunish();
232 } else if (obj->owornmask) {
233 /* catchall */
234 setnotworn(obj);
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
244 steal(mtmp, objnambuf)
245 struct monst *mtmp;
246 char *objnambuf;
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;
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;
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);
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 */
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;
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;
303 if (!otmp) {
304 impossible("Steal fails!");
305 return 0;
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;
322 gotobj:
323 if (otmp->o_id == stealoid)
324 return 0;
326 if (otmp->otyp == BOULDER && !throws_rocks(mtmp->data)) {
327 if (!retrycnt++)
328 goto retry;
329 goto cant_take;
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)));
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);
363 if (otmp->otyp == LEASH && otmp->leashmon) {
364 if (monkey_business && otmp->cursed)
365 goto cant_take;
366 o_unleash(otmp);
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();
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);
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) {
431 multi = 0;
432 afternmv = 0;
434 stealoid = otmp->o_id;
435 stealmid = mtmp->m_id;
436 afternmv = stealarm;
437 return 0;
440 break;
441 default:
442 impossible("Tried to steal a strange worn thing. [%d]",
443 otmp->oclass);
445 } else if (otmp->owornmask)
446 remove_worn_item(otmp, TRUE);
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;
454 mtmp->mavenge = 1;
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;
467 return (multi < 0) ? 0 : 1;
470 /* Returns 1 if otmp is free'd, 0 otherwise. */
472 mpickobj(mtmp, otmp)
473 register struct monst *mtmp;
474 register struct obj *otmp;
476 int freed_otmp;
477 boolean snuff_otmp = FALSE;
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;
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;
509 /* called for AD_SAMU (the Wizard and quest nemeses) */
510 void
511 stealamulet(mtmp)
512 struct monst *mtmp;
514 char buf[BUFSZ];
515 struct obj *otmp = 0, *obj = 0;
516 int real = 0, fake = 0, n;
518 /* target every quest artifact, not just current role's;
519 if hero has more than one, choose randomly so that player
520 can't use inventory ordering to influence the theft */
521 for (n = 0, obj = invent; obj; obj = obj->nobj)
522 if (any_quest_artifact(obj))
523 ++n, otmp = obj;
524 if (n > 1) {
525 n = rnd(n);
526 for (otmp = invent; otmp; otmp = otmp->nobj)
527 if (any_quest_artifact(otmp) && !--n)
528 break;
531 if (!otmp) {
532 /* if we didn't find any quest arifact, find another valuable item */
533 if (u.uhave.amulet) {
534 real = AMULET_OF_YENDOR;
535 fake = FAKE_AMULET_OF_YENDOR;
536 } else if (u.uhave.bell) {
537 real = BELL_OF_OPENING;
538 fake = BELL;
539 } else if (u.uhave.book) {
540 real = SPE_BOOK_OF_THE_DEAD;
541 } else if (u.uhave.menorah) {
542 real = CANDELABRUM_OF_INVOCATION;
543 } else
544 return; /* you have nothing of special interest */
546 /* If we get here, real and fake have been set up. */
547 for (n = 0, obj = invent; obj; obj = obj->nobj)
548 if (obj->otyp == real || (obj->otyp == fake && !mtmp->iswiz))
549 ++n, otmp = obj;
550 if (n > 1) {
551 n = rnd(n);
552 for (otmp = invent; otmp; otmp = otmp->nobj)
553 if ((otmp->otyp == real
554 || (otmp->otyp == fake && !mtmp->iswiz)) && !--n)
555 break;
559 if (otmp) { /* we have something to snatch */
560 /* take off outer gear if we're targetting [hypothetical]
561 quest artifact suit, shirt, gloves, or rings */
562 if ((otmp == uarm || otmp == uarmu) && uarmc)
563 (void) Cloak_off();
564 if (otmp == uarmu && uarm)
565 (void) Armor_off();
566 if ((otmp == uarmg || ((otmp == uright || otmp == uleft) && uarmg))
567 && uwep) {
568 /* gloves are about to be unworn; unwield weapon(s) first */
569 if (u.twoweap)
570 uswapwepgone(); /* will clear u.twoweap */
571 uwepgone();
573 if ((otmp == uright || otmp == uleft) && uarmg)
574 (void) Gloves_off(); /* handles wielded cockatrice corpse */
576 /* finally, steal the target item */
577 if (otmp->owornmask)
578 remove_worn_item(otmp, TRUE);
579 if (otmp->unpaid)
580 subfrombill(otmp, shop_keeper(*u.ushops));
581 freeinv(otmp);
582 Strcpy(buf, doname(otmp));
583 (void) mpickobj(mtmp, otmp); /* could merge and free otmp but won't */
584 pline("%s steals %s!", Monnam(mtmp), buf);
585 if (can_teleport(mtmp->data) && !tele_restrict(mtmp))
586 (void) rloc(mtmp, TRUE);
590 /* when a mimic gets poked with something, it might take that thing
591 (at present, only implemented for when the hero does the poking) */
592 void
593 maybe_absorb_item(mon, obj, ochance, achance)
594 struct monst *mon;
595 struct obj *obj;
596 int ochance, achance; /* percent chance for ordinary item, artifact */
598 if (obj == uball || obj == uchain || obj->oclass == ROCK_CLASS
599 || obj_resists(obj, 100 - ochance, 100 - achance)
600 || !touch_artifact(obj, mon))
601 return;
603 if (carried(obj)) {
604 if (obj->owornmask)
605 remove_worn_item(obj, TRUE);
606 if (obj->unpaid)
607 subfrombill(obj, shop_keeper(*u.ushops));
608 if (cansee(mon->mx, mon->my)) {
609 const char *MonName = Monnam(mon);
611 /* mon might be invisible; avoid "It pulls ... and absorbs it!" */
612 if (!strcmp(MonName, "It"))
613 MonName = "Something";
614 pline("%s pulls %s away from you and absorbs %s!", MonName,
615 yname(obj), (obj->quan > 1L) ? "them" : "it");
616 } else {
617 const char *hand_s = body_part(HAND);
619 if (bimanual(obj))
620 hand_s = makeplural(hand_s);
621 pline("%s %s pulled from your %s!", upstart(yname(obj)),
622 otense(obj, "are"), hand_s);
624 freeinv(obj);
625 } else {
626 /* not carried; presumably thrown or kicked */
627 if (canspotmon(mon))
628 pline("%s absorbs %s!", Monnam(mon), yname(obj));
630 /* add to mon's inventory */
631 (void) mpickobj(mon, obj);
634 /* drop one object taken from a (possibly dead) monster's inventory */
635 void
636 mdrop_obj(mon, obj, verbosely)
637 struct monst *mon;
638 struct obj *obj;
639 boolean verbosely;
641 int omx = mon->mx, omy = mon->my;
642 boolean update_mon = FALSE;
644 if (obj->owornmask) {
645 /* perform worn item handling if the monster is still alive */
646 if (mon->mhp > 0) {
647 mon->misc_worn_check &= ~obj->owornmask;
648 update_mon = TRUE;
650 /* don't charge for an owned saddle on dead steed (provided
651 that the hero is within the same shop at the time) */
652 } else if (mon->mtame && (obj->owornmask & W_SADDLE) != 0L
653 && !obj->unpaid && costly_spot(omx, omy)
654 /* being at costly_spot guarantees lev->roomno is not 0 */
655 && index(in_rooms(u.ux, u.uy, SHOPBASE),
656 levl[omx][omy].roomno)) {
657 obj->no_charge = 1;
659 /* this should be done even if the monster has died */
660 if (obj->owornmask & W_WEP)
661 setmnotwielded(mon, obj);
662 obj->owornmask = 0L;
664 /* obj_no_longer_held(obj); -- done by place_object */
665 if (verbosely && cansee(omx, omy))
666 pline("%s drops %s.", Monnam(mon), distant_name(obj, doname));
667 if (!flooreffects(obj, omx, omy, "fall")) {
668 place_object(obj, omx, omy);
669 stackobj(obj);
671 /* do this last, after placing obj on floor; removing steed's saddle
672 throws rider, possibly inflicting fatal damage and producing bones */
673 if (update_mon)
674 update_mon_intrinsics(mon, obj, FALSE, TRUE);
677 /* some monsters bypass the normal rules for moving between levels or
678 even leaving the game entirely; when that happens, prevent them from
679 taking the Amulet, invocation items, or quest artifact with them */
680 void
681 mdrop_special_objs(mon)
682 struct monst *mon;
684 struct obj *obj, *otmp;
686 for (obj = mon->minvent; obj; obj = otmp) {
687 otmp = obj->nobj;
688 /* the Amulet, invocation tools, and Rider corpses resist even when
689 artifacts and ordinary objects are given 0% resistance chance;
690 current role's quest artifact is rescued too--quest artifacts
691 for the other roles are not */
692 if (obj_resists(obj, 0, 0) || is_quest_artifact(obj)) {
693 obj_extract_self(obj);
694 mdrop_obj(mon, obj, FALSE);
699 /* release the objects the creature is carrying */
700 void
701 relobj(mtmp, show, is_pet)
702 struct monst *mtmp;
703 int show;
704 boolean is_pet; /* If true, pet should keep wielded/worn items */
706 struct obj *otmp;
707 int omx = mtmp->mx, omy = mtmp->my;
709 /* vault guard's gold goes away rather than be dropped... */
710 if (mtmp->isgd && (otmp = findgold(mtmp->minvent)) != 0) {
711 if (canspotmon(mtmp))
712 pline("%s gold %s.", s_suffix(Monnam(mtmp)),
713 canseemon(mtmp) ? "vanishes" : "seems to vanish");
714 obj_extract_self(otmp);
715 obfree(otmp, (struct obj *) 0);
716 } /* isgd && has gold */
718 while ((otmp = (is_pet ? droppables(mtmp) : mtmp->minvent)) != 0) {
719 obj_extract_self(otmp);
720 mdrop_obj(mtmp, otmp, is_pet && flags.verbose);
723 if (show && cansee(omx, omy))
724 newsym(omx, omy);
727 /*steal.c*/