-/* NetHack 3.6 steal.c $NHDT-Date: 1446713643 2015/11/05 08:54:03 $ $NHDT-Branch: master $:$NHDT-Revision: 1.65 $ */
+/* NetHack 3.6 steal.c $NHDT-Date: 1496614914 2017/06/04 22:21:54 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.69 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
+/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
/* JNetHack Copyright */
return freed_otmp;
}
+/* called for AD_SAMU (the Wizard and quest nemeses) */
void
stealamulet(mtmp)
struct monst *mtmp;
{
- struct obj *otmp = (struct obj *) 0;
- int real = 0, fake = 0;
-
- /* select the artifact to steal */
- if (u.uhave.amulet) {
- real = AMULET_OF_YENDOR;
- fake = FAKE_AMULET_OF_YENDOR;
- } else if (u.uhave.questart) {
+ char buf[BUFSZ];
+ struct obj *otmp = 0, *obj = 0;
+ int real = 0, fake = 0, n;
+
+ /* target every quest artifact, not just current role's;
+ if hero has more than one, choose randomly so that player
+ can't use inventory ordering to influence the theft */
+ for (n = 0, obj = invent; obj; obj = obj->nobj)
+ if (any_quest_artifact(obj))
+ ++n, otmp = obj;
+ if (n > 1) {
+ n = rnd(n);
for (otmp = invent; otmp; otmp = otmp->nobj)
- if (is_quest_artifact(otmp))
+ if (any_quest_artifact(otmp) && !--n)
break;
- if (!otmp)
- return; /* should we panic instead? */
- } else if (u.uhave.bell) {
- real = BELL_OF_OPENING;
- fake = BELL;
- } else if (u.uhave.book) {
- real = SPE_BOOK_OF_THE_DEAD;
- } else if (u.uhave.menorah) {
- real = CANDELABRUM_OF_INVOCATION;
- } else
- return; /* you have nothing of special interest */
+ }
if (!otmp) {
+ /* if we didn't find any quest arifact, find another valuable item */
+ if (u.uhave.amulet) {
+ real = AMULET_OF_YENDOR;
+ fake = FAKE_AMULET_OF_YENDOR;
+ } else if (u.uhave.bell) {
+ real = BELL_OF_OPENING;
+ fake = BELL;
+ } else if (u.uhave.book) {
+ real = SPE_BOOK_OF_THE_DEAD;
+ } else if (u.uhave.menorah) {
+ real = CANDELABRUM_OF_INVOCATION;
+ } else
+ return; /* you have nothing of special interest */
+
/* If we get here, real and fake have been set up. */
- for (otmp = invent; otmp; otmp = otmp->nobj)
- if (otmp->otyp == real || (otmp->otyp == fake && !mtmp->iswiz))
- break;
+ for (n = 0, obj = invent; obj; obj = obj->nobj)
+ if (obj->otyp == real || (obj->otyp == fake && !mtmp->iswiz))
+ ++n, otmp = obj;
+ if (n > 1) {
+ n = rnd(n);
+ for (otmp = invent; otmp; otmp = otmp->nobj)
+ if ((otmp->otyp == real
+ || (otmp->otyp == fake && !mtmp->iswiz)) && !--n)
+ break;
+ }
}
if (otmp) { /* we have something to snatch */
+ /* take off outer gear if we're targetting [hypothetical]
+ quest artifact suit, shirt, gloves, or rings */
+ if ((otmp == uarm || otmp == uarmu) && uarmc)
+ remove_worn_item(uarmc, FALSE);
+ if (otmp == uarmu && uarm)
+ remove_worn_item(uarm, FALSE);
+ if ((otmp == uarmg || ((otmp == uright || otmp == uleft) && uarmg))
+ && uwep) {
+ /* gloves are about to be unworn; unwield weapon(s) first */
+ if (u.twoweap) /* remove_worn_item(uswapwep) indirectly */
+ remove_worn_item(uswapwep, FALSE); /* clears u.twoweap */
+ remove_worn_item(uwep, FALSE);
+ }
+ if ((otmp == uright || otmp == uleft) && uarmg)
+ /* calls Gloves_off() to handle wielded cockatrice corpse */
+ remove_worn_item(uarmg, FALSE);
+
+ /* finally, steal the target item */
if (otmp->owornmask)
remove_worn_item(otmp, TRUE);
if (otmp->unpaid)
subfrombill(otmp, shop_keeper(*u.ushops));
freeinv(otmp);
- /* mpickobj wont merge otmp because none of the above things
- to steal are mergable */
- (void) mpickobj(mtmp, otmp); /* may merge and free otmp */
+ Strcpy(buf, doname(otmp));
+ (void) mpickobj(mtmp, otmp); /* could merge and free otmp but won't */
/*JP
- pline("%s stole %s!", Monnam(mtmp), doname(otmp));
+ pline("%s steals %s!", Monnam(mtmp), buf);
*/
- pline("%s\82Í%s\82ð\93\90\82ñ\82¾\81I", Monnam(mtmp), doname(otmp));
+ pline("%s\82Í%s\82ð\93\90\82ñ\82¾\81I", Monnam(mtmp), buf);
if (can_teleport(mtmp->data) && !tele_restrict(mtmp))
(void) rloc(mtmp, TRUE);
}
if (mon->mhp > 0) {
mon->misc_worn_check &= ~obj->owornmask;
update_mon = TRUE;
- /* don't charge for an owned saddle on dead steed (provided
- that the hero is within the same shop at the time) */
- } else if (mon->mtame && (obj->owornmask & W_SADDLE) && !obj->unpaid
- && costly_spot(omx, omy)
+
+ /* don't charge for an owned saddle on dead steed (provided
+ that the hero is within the same shop at the time) */
+ } else if (mon->mtame && (obj->owornmask & W_SADDLE) != 0L
+ && !obj->unpaid && costly_spot(omx, omy)
/* being at costly_spot guarantees lev->roomno is not 0 */
&& index(in_rooms(u.ux, u.uy, SHOPBASE),
levl[omx][omy].roomno)) {
/* some monsters bypass the normal rules for moving between levels or
even leaving the game entirely; when that happens, prevent them from
- taking the Amulet or invocation tools with them */
+ taking the Amulet, invocation items, or quest artifact with them */
void
mdrop_special_objs(mon)
struct monst *mon;
for (obj = mon->minvent; obj; obj = otmp) {
otmp = obj->nobj;
/* the Amulet, invocation tools, and Rider corpses resist even when
- artifacts and ordinary objects are given 0% resistance chance */
- if (obj_resists(obj, 0, 0)) {
+ artifacts and ordinary objects are given 0% resistance chance;
+ current role's quest artifact is rescued too--quest artifacts
+ for the other roles are not */
+ if (obj_resists(obj, 0, 0) || is_quest_artifact(obj)) {
obj_extract_self(obj);
mdrop_obj(mon, obj, FALSE);
}