From: PatR Date: Sun, 28 Feb 2016 00:23:24 +0000 (-0800) Subject: address #H4247 & #4248 - theft of quest artifact X-Git-Tag: NetHack-3.6.1_RC01~896 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=850ed0cba623cb403122a7ab280402a83383e92d;p=nethack 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. --- diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 7003206ed..dc0c8e9af 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -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 diff --git a/include/obj.h b/include/obj.h index f2acaf80e..d03aec2ec 100644 --- a/include/obj.h +++ b/include/obj.h @@ -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) \ diff --git a/src/mhitu.c b/src/mhitu.c index d8c85a133..872ef8a17 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -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: diff --git a/src/steal.c b/src/steal.c index 4b5378d96..b3e5cb1f5 100644 --- a/src/steal.c +++ b/src/steal.c @@ -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; - - /* 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) + (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); } diff --git a/src/wizard.c b/src/wizard.c index 2f7d2e7e4..f8d72c1c0 100644 --- a/src/wizard.c +++ b/src/wizard.c @@ -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; }