/* An object you're wearing has been taken off by a monster (theft or seduction). Also used if a worn item gets transformed (stone to flesh). */ void remove_worn_item(struct obj *obj, boolean unchain_ball) { /* whether to unpunish or just unwield */ if (donning(obj)) cancel_don(); if (!obj->owornmask) return; if (obj->owornmask & W_ARMOR) { if (obj == uskin) { impossible("Removing embedded scales?"); skinback(TRUE); /* uarm = uskin; uskin = 0; */ } if (obj == uarm) Armor_off(); else if (obj == uarmc) Cloak_off(); else if (obj == uarmf) Boots_off(); else if (obj == uarmg) Gloves_off(); else if (obj == uarmh) Helmet_off(); else if (obj == uarms) Shield_off(); else if (obj == uarmu) Shirt_off(); /* catchall -- should never happen */ else setworn(NULL, obj->owornmask & W_ARMOR); } else if (obj->owornmask & W_AMUL) { Amulet_off(); } else if (obj->owornmask & W_RING) { Ring_gone(obj); } else if (obj->owornmask & W_TOOL) { Blindf_off(obj); } else if (obj->owornmask & (W_WEP | W_SWAPWEP | W_QUIVER)) { if (obj == uwep) uwepgone(); if (obj == uswapwep) uswapwepgone(); if (obj == uquiver) uqwepgone(); } if (obj->owornmask & (W_BALL | W_CHAIN)) { if (unchain_ball) unpunish(); } else if (obj->owornmask) { /* catchall */ setnotworn(obj); } }
/* Returns 1 when something was stolen (or at least, when N should flee now) * Returns -1 if the monster died in the attempt * Avoid stealing the object stealoid */ int steal(struct monst *mtmp, char *objnambuf) { struct obj *otmp; int tmp, could_petrify, named = 0, armordelay; boolean monkey_business; /* true iff an animal is doing the thievery */ if (objnambuf) *objnambuf = '\0'; /* the following is true if successful on first of two attacks. */ if (!monnear(mtmp, u.ux, u.uy)) return 0; /* food being eaten might already be used up but will not have been removed from inventory yet; we don't want to steal that, so this will cause it to be removed now */ if (occupation) maybe_finished_meal(FALSE); if (!invent || (inv_cnt() == 1 && uskin)) { nothing_to_steal: /* Not even a thousand men in armor can strip a naked man. */ if (Blind) pline("Somebody tries to rob you, but finds nothing to steal."); else pline("%s tries to rob you, but there is nothing to steal!", Monnam(mtmp)); return 1; /* let her flee */ } /* Monkey or mugger robbing you. You don't wanna be charmed/seduced by a mugger. */ monkey_business = is_robber(mtmp->data); if (monkey_business) { ; /* skip ring special cases */ } else if (Adornment & LEFT_RING) { otmp = uleft; goto gotobj; } else if (Adornment & RIGHT_RING) { otmp = uright; goto gotobj; } tmp = 0; for (otmp = invent; otmp; otmp = otmp->nobj) if ((!uarm || otmp != uarmc) && otmp != uskin #ifdef INVISIBLE_OBJECTS && (!otmp->oinvis || perceives(mtmp->data)) #endif ) tmp += ((otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) ? 5 : 1); if (!tmp) goto nothing_to_steal; tmp = rn2(tmp); for (otmp = invent; otmp; otmp = otmp->nobj) if ((!uarm || otmp != uarmc) && otmp != uskin #ifdef INVISIBLE_OBJECTS && (!otmp->oinvis || perceives(mtmp->data)) #endif ) if ((tmp -= ((otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)) ? 5 : 1)) < 0) break; if (!otmp) { warning("Steal fails!"); return 0; } /* can't steal gloves while wielding - so steal the wielded item. */ if (otmp == uarmg && uwep) otmp = uwep; /* can't steal armor while wearing cloak - so steal the cloak. */ else if (otmp == uarm && uarmc) otmp = uarmc; else if (otmp == uarmu && uarmc) otmp = uarmc; else if (otmp == uarmu && uarm) otmp = uarm; gotobj: if (otmp->o_id == stealoid) return 0; /* animals can't overcome curse stickiness nor unlock chains */ if (monkey_business) { boolean ostuck; /* is the player prevented from voluntarily giving up this item? (ignores loadstones; the !can_carry() check will catch those) */ if (otmp == uball) ostuck = TRUE; /* effectively worn; curse is implicit */ else if (otmp == uquiver || (otmp == uswapwep && !u.twoweap)) ostuck = FALSE; /* not really worn; curse doesn't matter */ else ostuck = (otmp->cursed && otmp->owornmask); if (ostuck || !can_carry(mtmp, otmp)) { static const char * const how[] = { "steal","snatch","grab","take" }; cant_take: pline("%s tries to %s your %s but gives up.", Monnam(mtmp), how[rn2(SIZE(how))], (otmp->owornmask & W_ARMOR) ? equipname(otmp) : cxname(otmp)); /* the fewer items you have, the less likely the thief is going to stick around to try again (0) instead of running away (1) */ return !rn2(inv_cnt() / 5 + 2); } } if (otmp->otyp == LEASH && otmp->leashmon) { if (monkey_business && otmp->cursed) goto cant_take; o_unleash(otmp); } /* you're going to notice the theft... */ stop_occupation(); if ((otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL))){ switch(otmp->oclass) { case TOOL_CLASS: case AMULET_CLASS: case RING_CLASS: case FOOD_CLASS: /* meat ring */ remove_worn_item(otmp, TRUE); break; case ARMOR_CLASS: armordelay = objects[otmp->otyp].oc_delay; /* Stop putting on armor which has been stolen. */ if (donning(otmp)) { remove_worn_item(otmp, TRUE); break; } else if (monkey_business) { /* animals usually don't have enough patience to take off items which require extra time */ if (armordelay >= 1 && rn2(10)) goto cant_take; remove_worn_item(otmp, TRUE); break; } else { int curssv = otmp->cursed; int slowly; boolean seen = canspotmon(level, mtmp); otmp->cursed = 0; /* can't charm you without first waking you */ if (multi < 0 && is_fainted()) unmul(NULL); slowly = (armordelay >= 1 || multi < 0); if (flags.female) pline("%s charms you. You gladly %s your %s.", !seen ? "She" : Monnam(mtmp), curssv ? "let her take" : slowly ? "start removing" : "hand over", equipname(otmp)); else pline("%s seduces you and %s off your %s.", !seen ? "She" : Adjmonnam(mtmp, "beautiful"), curssv ? "helps you to take" : slowly ? "you start taking" : "you take", equipname(otmp)); named++; /* the following is to set multi for later on */ nomul(-armordelay, "taking off clothes"); remove_worn_item(otmp, TRUE); otmp->cursed = curssv; if (multi < 0){ /* multi = 0; nomovemsg = 0; afternmv = 0; */ stealoid = otmp->o_id; stealmid = mtmp->m_id; afternmv = stealarm; return 0; } } break; default: warning("Tried to steal a strange worn thing. [%d]", otmp->oclass); } } else if (otmp->owornmask) remove_worn_item(otmp, TRUE); /* do this before removing it from inventory */ if (objnambuf) strcpy(objnambuf, yname(otmp)); /* set mavenge bit so knights won't suffer an * alignment penalty during retaliation; */ mtmp->mavenge = 1; freeinv(otmp); pline("%s stole %s.", named ? "She" : Monnam(mtmp), doname(otmp)); could_petrify = (otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm])); mpickobj(mtmp,otmp); /* may free otmp */ if (could_petrify && !(mtmp->misc_worn_check & W_ARMG)) { minstapetrify(mtmp, TRUE); return -1; } return (multi < 0) ? 0 : 1; }
static void break_armor(void) { struct obj *otmp; if (breakarm(youmonst.data)) { if ((otmp = uarm) != 0) { if (donning(otmp)) cancel_don(); pline("You break out of your armor!"); exercise(A_STR, FALSE); Armor_gone(); useup(otmp); } if ((otmp = uarmc) != 0) { if (otmp->oartifact) { pline("Your %s falls off!", cloak_simple_name(otmp)); Cloak_off(); dropx(otmp); } else { pline("Your %s tears apart!", cloak_simple_name(otmp)); Cloak_off(); useup(otmp); } } if (uarmu) { pline("Your shirt rips to shreds!"); useup(uarmu); } } else if (sliparm(youmonst.data)) { if (((otmp = uarm) != 0) && (racial_exception(&youmonst, otmp) < 1)) { if (donning(otmp)) cancel_don(); pline("Your armor falls around you!"); Armor_gone(); dropx(otmp); } if ((otmp = uarmc) != 0) { if (is_whirly(youmonst.data)) pline("Your %s falls, unsupported!", cloak_simple_name(otmp)); else pline("You shrink out of your %s!", cloak_simple_name(otmp)); Cloak_off(); dropx(otmp); } if ((otmp = uarmu) != 0) { if (is_whirly(youmonst.data)) pline("You seep right through your shirt!"); else pline("You become much too small for your shirt!"); setworn(NULL, otmp->owornmask & W_ARMU); dropx(otmp); } } if (has_horns(youmonst.data)) { if ((otmp = uarmh) != 0) { if (is_flimsy(otmp) && !donning(otmp)) { char hornbuf[BUFSZ], yourbuf[BUFSZ]; /* Future possiblities: This could damage/destroy helmet */ sprintf(hornbuf, "horn%s", plur(num_horns(youmonst.data))); pline("Your %s %s through %s %s.", hornbuf, vtense(hornbuf, "pierce"), shk_your(yourbuf, otmp), xname(otmp)); } else { if (donning(otmp)) cancel_don(); pline("Your helmet falls to the %s!", surface(u.ux, u.uy)); Helmet_off(); dropx(otmp); } } } if (nohands(youmonst.data) || verysmall(youmonst.data)) { if ((otmp = uarmg) != 0) { if (donning(otmp)) cancel_don(); /* Drop weapon along with gloves */ pline("You drop your gloves%s!", uwep ? " and weapon" : ""); drop_weapon(0); Gloves_off(); dropx(otmp); } if ((otmp = uarms) != 0) { pline("You can no longer hold your shield!"); Shield_off(); dropx(otmp); } if ((otmp = uarmh) != 0) { if (donning(otmp)) cancel_don(); pline("Your helmet falls to the %s!", surface(u.ux, u.uy)); Helmet_off(); dropx(otmp); } } if (nohands(youmonst.data) || verysmall(youmonst.data) || slithy(youmonst.data) || youmonst.data->mlet == S_CENTAUR) { if ((otmp = uarmf) != 0) { if (donning(otmp)) cancel_don(); if (is_whirly(youmonst.data)) pline("Your boots fall away!"); else pline("Your boots %s off your feet!", verysmall(youmonst.data) ? "slide" : "are pushed"); Boots_off(); dropx(otmp); } } }
static void break_armor (void) { struct obj *otmp; if (breakarm(youmonst.data)) { if ((otmp = uarm) != 0) { if (donning(otmp)) cancel_don(); You("break out of your armor!"); exercise(A_STR, false); (void) Armor_gone(); useup(otmp); } if ((otmp = uarmc) != 0) { if(otmp->oartifact) { Your("%s falls off!", cloak_simple_name(otmp)); (void) Cloak_off(); dropx(otmp); } else { Your("%s tears apart!", cloak_simple_name(otmp)); (void) Cloak_off(); useup(otmp); } } if (uarmu) { Your("shirt rips to shreds!"); useup(uarmu); } } else if (sliparm(youmonst.data)) { if (((otmp = uarm) != 0) && (racial_exception(&youmonst, otmp) < 1)) { if (donning(otmp)) cancel_don(); Your("armor falls around you!"); (void) Armor_gone(); dropx(otmp); } if ((otmp = uarmc) != 0) { if (is_whirly(youmonst.data)) Your("%s falls, unsupported!", cloak_simple_name(otmp)); else You("shrink out of your %s!", cloak_simple_name(otmp)); (void) Cloak_off(); dropx(otmp); } if ((otmp = uarmu) != 0) { if (is_whirly(youmonst.data)) You("seep right through your shirt!"); else You("become much too small for your shirt!"); setworn((struct obj *)0, otmp->owornmask & W_ARMU); dropx(otmp); } } if (has_horns(youmonst.data)) { if ((otmp = uarmh) != 0) { if (is_flimsy(otmp) && !donning(otmp)) { /* Future possiblities: This could damage/destroy helmet */ message_object(MSG_YOUR_HORNS_PIERCE_O, otmp); } else { if (donning(otmp)) cancel_don(); Your("helmet falls to the %s!", surface(u.ux, u.uy)); (void) Helmet_off(); dropx(otmp); } } } if (nohands(youmonst.data) || verysmall(youmonst.data)) { if ((otmp = uarmg) != 0) { if (donning(otmp)) cancel_don(); /* Drop weapon along with gloves */ You("drop your gloves%s!", uwep ? " and weapon" : ""); drop_weapon(0); (void) Gloves_off(); dropx(otmp); } if ((otmp = uarms) != 0) { You("can no longer hold your shield!"); (void) Shield_off(); dropx(otmp); } if ((otmp = uarmh) != 0) { if (donning(otmp)) cancel_don(); Your("helmet falls to the %s!", surface(u.ux, u.uy)); (void) Helmet_off(); dropx(otmp); } } if (nohands(youmonst.data) || verysmall(youmonst.data) || slithy(youmonst.data) || youmonst.data->mlet == S_CENTAUR) { if ((otmp = uarmf) != 0) { if (donning(otmp)) cancel_don(); if (is_whirly(youmonst.data)) Your("boots fall away!"); else Your("boots %s off your feet!", verysmall(youmonst.data) ? "slide" : "are pushed"); (void) Boots_off(); dropx(otmp); } } }