address #H4247 & #4248 - theft of quest artifact

Two different reports complaining that having the Wizard steal the
hero's quest artifact is a bad thing.  This doesn't change that,
but it does make all quest artifacts become equal targets so that
wishing for other roles' artifacts doesn't offer such a safe way to
have whichever special attributes they provide.

Quest artifacts are actually higher priority targets for theft than
the Amulet.  I suspect that probably wasn't originally intended,
but I left things that way.  Taking quest artifacts leaves the hero
more vulnerable to future thefts, and once they're gone the Amulet
has priority over the invocation tools.
This commit is contained in:
PatR
2016-02-27 16:23:24 -08:00
parent f92f43a526
commit 850ed0cba6
5 changed files with 82 additions and 44 deletions

View File

@@ -169,6 +169,7 @@ if a long worm inherited inventory from a previous shape, and if an egg or
figurine in that inventory hatched or auto-activated, messages were
given when hero could see any tail segment even if head was unseen,
making it seem as if worm's inventory was kept in the visible segment
Wizard will now steal any quest artifact from hero, not just own role's
Platform- and/or Interface-Specific Fixes

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 obj.h $NHDT-Date: 1450306176 2015/12/16 22:49:36 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.51 $ */
/* NetHack 3.6 obj.h $NHDT-Date: 1456618994 2016/02/28 00:23:14 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.53 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -200,6 +200,8 @@ struct obj {
&& objects[otmp->otyp].oc_skill >= -P_SHURIKEN \
&& objects[otmp->otyp].oc_skill <= -P_BOW)
#define uslinging() (uwep && objects[uwep->otyp].oc_skill == P_SLING)
/* 'is_quest_artifact()' only applies to the current role's artifact */
#define any_quest_artifact(o) ((o)->oartifact >= ART_ORB_OF_DETECTION)
/* Armor */
#define is_shield(otmp) \

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 mhitu.c $NHDT-Date: 1451084422 2015/12/25 23:00:22 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.132 $ */
/* NetHack 3.6 mhitu.c $NHDT-Date: 1456618997 2016/02/28 00:23:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.135 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1321,11 +1321,11 @@ register struct attack *mattk;
case AD_SAMU:
hitmsg(mtmp, mattk);
/* when the Wiz hits, 1/20 steals the amulet */
if (u.uhave.amulet || u.uhave.bell || u.uhave.book || u.uhave.menorah
|| u.uhave.questart) /* carrying the Quest Artifact */
if (!rn2(20))
stealamulet(mtmp);
/* when the Wizard or quest nemesis hits, there's a 1/20 chance
to steal a quest artifact (any, not just the one for the hero's
own role) or the Amulet or one of the invocation tools */
if (!rn2(20))
stealamulet(mtmp);
break;
case AD_TLPT:

View File

@@ -1,4 +1,4 @@
/* 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: 1456618998 2016/02/28 00:23:18 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.67 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -506,50 +506,82 @@ register struct obj *otmp;
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;
char buf[BUFSZ];
struct obj *otmp = 0, *obj = 0;
int real = 0, fake = 0, n;
/* select the artifact to steal */
if (u.uhave.amulet) {
real = AMULET_OF_YENDOR;
fake = FAKE_AMULET_OF_YENDOR;
} else if (u.uhave.questart) {
/* 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))
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 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))
if (any_quest_artifact(otmp) && !--n)
break;
}
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 (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)
(void) Cloak_off();
if (otmp == uarmu && uarm)
(void) Armor_off();
if ((otmp == uarmg || ((otmp == uright || otmp == uleft) && uarmg))
&& uwep) {
/* gloves are about to be unworn; unwield weapon(s) first */
if (u.twoweap)
uswapwepgone(); /* will clear u.twoweap */
uwepgone();
}
if ((otmp == uright || otmp == uleft) && uarmg)
(void) Gloves_off(); /* handles wielded cockatrice corpse */
/* 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 */
pline("%s stole %s!", Monnam(mtmp), doname(otmp));
Strcpy(buf, doname(otmp));
(void) mpickobj(mtmp, otmp); /* could merge and free otmp but won't */
pline("%s steals %s!", Monnam(mtmp), buf);
if (can_teleport(mtmp->data) && !tele_restrict(mtmp))
(void) rloc(mtmp, TRUE);
}
@@ -643,7 +675,7 @@ boolean verbosely;
/* 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;
@@ -653,8 +685,10 @@ 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);
}

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 wizard.c $NHDT-Date: 1456185030 2016/02/22 23:50:30 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.47 $ */
/* NetHack 3.6 wizard.c $NHDT-Date: 1456618999 2016/02/28 00:23:19 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.48 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -119,7 +119,8 @@ register struct monst *mtmp;
register struct obj *otmp;
for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
if (otmp->otyp == AMULET_OF_YENDOR || is_quest_artifact(otmp)
if (otmp->otyp == AMULET_OF_YENDOR
|| any_quest_artifact(otmp)
|| otmp->otyp == BELL_OF_OPENING
|| otmp->otyp == CANDELABRUM_OF_INVOCATION
|| otmp->otyp == SPE_BOOK_OF_THE_DEAD)
@@ -175,7 +176,7 @@ register short otyp;
if (otyp) {
if (otmp->otyp == otyp)
return 1;
} else if (is_quest_artifact(otmp))
} else if (any_quest_artifact(otmp))
return 1;
}
return 0;
@@ -207,7 +208,7 @@ register short otyp;
if (otyp) {
if (otmp->otyp == otyp)
return otmp;
} else if (is_quest_artifact(otmp))
} else if (any_quest_artifact(otmp))
return otmp;
return (struct obj *) 0;
}