diff --git a/doc/fixes35.0 b/doc/fixes35.0 index b96003082..8983b30e5 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -353,6 +353,8 @@ spellcasting monsters' spell selection became less likely to choose harder Eye of the Aethiopica, Eyes of the Overworld, and Sceptre of Might must be worn or wielded rather than just carried to convey magic resistance Mitre of Holiness and Tsurugi of Muramasa convey Protection when worn/wielded +effectiveness of magic cancellation by worn armor has been reduced +Protection improves the effectiveness of magic cancellation Platform- and/or Interface-Specific Fixes diff --git a/src/mhitm.c b/src/mhitm.c index c25432fec..ade47bf26 100644 --- a/src/mhitm.c +++ b/src/mhitm.c @@ -719,7 +719,7 @@ mdamagem(magr, mdef, mattk) /* cancellation factor is the same as when attacking the hero */ armpro = magic_negation(mdef); - cancelled = magr->mcan || !((rn2(3) >= armpro) || !rn2(50)); + cancelled = magr->mcan || !(rn2(10) >= 3 * armpro); switch(mattk->adtyp) { case AD_DGST: diff --git a/src/mhitu.c b/src/mhitu.c index e16d982e7..204d8d7ad 100644 --- a/src/mhitu.c +++ b/src/mhitu.c @@ -819,44 +819,53 @@ int magic_negation(mon) struct monst *mon; { - struct obj *armor; - int armpro = 0; + struct obj *o; + long wearmask; + int armpro, mc = 0; + boolean is_you = (mon == &youmonst), gotprot = FALSE; - armor = (mon == &youmonst) ? uarm : which_armor(mon, W_ARM); - if (armor && armpro < objects[armor->otyp].a_can) - armpro = objects[armor->otyp].a_can; - armor = (mon == &youmonst) ? uarmc : which_armor(mon, W_ARMC); - if (armor && armpro < objects[armor->otyp].a_can) - armpro = objects[armor->otyp].a_can; - armor = (mon == &youmonst) ? uarmh : which_armor(mon, W_ARMH); - if (armor && armpro < objects[armor->otyp].a_can) - armpro = objects[armor->otyp].a_can; + for (o = is_you ? invent : mon->minvent; o; o = o->nobj) { + /* a_can field is only applicable for armor (which must be worn) */ + if ((o->owornmask & W_ARMOR) != 0L) { + armpro = objects[o->otyp].a_can; + if (armpro > mc) mc = armpro; + } + /* if we've already confirmed Protection, skip additional checks */ + if (gotprot) continue; - /* armor types for shirt, gloves, shoes, and shield don't currently - provide any magic cancellation but we might as well be complete */ -#ifdef TOURIST - armor = (mon == &youmonst) ? uarmu : which_armor(mon, W_ARMU); - if (armor && armpro < objects[armor->otyp].a_can) - armpro = objects[armor->otyp].a_can; -#endif - armor = (mon == &youmonst) ? uarmg : which_armor(mon, W_ARMG); - if (armor && armpro < objects[armor->otyp].a_can) - armpro = objects[armor->otyp].a_can; - armor = (mon == &youmonst) ? uarmf : which_armor(mon, W_ARMF); - if (armor && armpro < objects[armor->otyp].a_can) - armpro = objects[armor->otyp].a_can; - armor = (mon == &youmonst) ? uarms : which_armor(mon, W_ARMS); - if (armor && armpro < objects[armor->otyp].a_can) - armpro = objects[armor->otyp].a_can; + /* omit W_SWAPWEP+W_QUIVER; W_ART+W_ARTI handled by protects() */ + wearmask = W_ARMOR | W_RING | W_AMUL | W_TOOL; + if (o->oclass == WEAPON_CLASS || is_weptool(o)) wearmask |= W_WEP; + if (protects(o, ((o->owornmask & wearmask) != 0L) ? TRUE : FALSE)) + gotprot = TRUE; + } -#ifdef STEED - /* this one is really a stretch... */ - armor = (mon == &youmonst) ? 0 : which_armor(mon, W_SADDLE); - if (armor && armpro < objects[armor->otyp].a_can) - armpro = objects[armor->otyp].a_can; -#endif + /* extrinsic Protection increases mc factor */ + if (!gotprot) { + /* in case hero has extrinsic protection from some other source */ + if (is_you && EProtection) gotprot = TRUE; + /* high priests have innate intrinsic protection which is as + strong as extrinsic protection */ + if (mon->data == &mons[PM_HIGH_PRIEST]) gotprot = TRUE; + } + /* extrinsic Protection increases mc by 1 */ + if (gotprot && mc < 3) + mc += 1; - return armpro; + /* intrinsic Protection is weaker than Extrinsic (play balance; + obtaining divine protection is too easy) */ + if (!gotprot) { + if (is_you && ((HProtection && u.ublessed > 0) || u.uspellprot)) + gotprot = TRUE; + /* aligned priests and angels have innate intrinsic Protection */ + if (mon->data == &mons[PM_ALIGNED_PRIEST] || is_minion(mon->data)) + gotprot = TRUE; + } + /* intrinsic Protection confers minimum mc 1 instead of 0 */ + if (gotprot && mc < 1) + mc = 1; + + return mc; } /* @@ -913,7 +922,7 @@ hitmu(mtmp, mattk) * armor's special magic protection. Otherwise just use !mtmp->mcan. */ armpro = magic_negation(&youmonst); - uncancelled = !mtmp->mcan && ((rn2(3) >= armpro) || !rn2(50)); + uncancelled = !mtmp->mcan && (rn2(10) >= 3 * armpro); permdmg = 0; /* Now, adjust damages via resistances or specific attacks */ diff --git a/src/objects.c b/src/objects.c index 742d6d41b..46b4101e5 100644 --- a/src/objects.c +++ b/src/objects.c @@ -1,5 +1,4 @@ /* NetHack 3.5 objects.c $Date$ $Revision$ */ -/* SCCS Id: @(#)objects.c 3.5 2006/12/14 */ /* Copyright (c) Mike Threepoint, 1989. */ /* NetHack may be freely redistributed. See license for details. */ @@ -307,7 +306,7 @@ HELM("fedora", (char *)0, 1, 0, 0, 0, 0, 3, 1,10, 0, CLOTH, CLR_BROWN), HELM("cornuthaum", "conical hat", 0, 1, CLAIRVOYANT, - 3, 1, 4, 80,10, 2, CLOTH, CLR_BLUE), + 3, 1, 4, 80,10, 1, CLOTH, CLR_BLUE), HELM("dunce cap", "conical hat", 0, 1, 0, 3, 1, 4, 1,10, 0, CLOTH, CLR_BLUE), HELM("dented pot", (char *)0, @@ -371,33 +370,33 @@ ARMOR("crystal plate mail", (char *)0, 1, 0, 1, 0, 10, 5, 450, 820, 3, 2, ARM_SUIT, GLASS, CLR_WHITE), #ifdef TOURIST ARMOR("bronze plate mail", (char *)0, - 1, 0, 1, 0, 25, 5, 450, 400, 4, 0, ARM_SUIT, COPPER, HI_COPPER), + 1, 0, 1, 0, 25, 5, 450, 400, 4, 1, ARM_SUIT, COPPER, HI_COPPER), #else ARMOR("bronze plate mail", (char *)0, - 1, 0, 1, 0, 35, 5, 450, 400, 4, 0, ARM_SUIT, COPPER, HI_COPPER), + 1, 0, 1, 0, 35, 5, 450, 400, 4, 1, ARM_SUIT, COPPER, HI_COPPER), #endif ARMOR("splint mail", (char *)0, 1, 0, 1, 0, 62, 5, 400, 80, 4, 1, ARM_SUIT, IRON, HI_METAL), ARMOR("banded mail", (char *)0, - 1, 0, 1, 0, 72, 5, 350, 90, 4, 0, ARM_SUIT, IRON, HI_METAL), + 1, 0, 1, 0, 72, 5, 350, 90, 4, 1, ARM_SUIT, IRON, HI_METAL), ARMOR("dwarvish mithril-coat", (char *)0, - 1, 0, 0, 0, 10, 1, 150, 240, 4, 3, ARM_SUIT, MITHRIL, HI_METAL), + 1, 0, 0, 0, 10, 1, 150, 240, 4, 2, ARM_SUIT, MITHRIL, HI_METAL), ARMOR("elven mithril-coat", (char *)0, - 1, 0, 0, 0, 15, 1, 150, 240, 5, 3, ARM_SUIT, MITHRIL, HI_METAL), + 1, 0, 0, 0, 15, 1, 150, 240, 5, 2, ARM_SUIT, MITHRIL, HI_METAL), ARMOR("chain mail", (char *)0, 1, 0, 0, 0, 72, 5, 300, 75, 5, 1, ARM_SUIT, IRON, HI_METAL), ARMOR("orcish chain mail", "crude chain mail", 0, 0, 0, 0, 20, 5, 300, 75, 6, 1, ARM_SUIT, IRON, CLR_BLACK), ARMOR("scale mail", (char *)0, - 1, 0, 0, 0, 72, 5, 250, 45, 6, 0, ARM_SUIT, IRON, HI_METAL), + 1, 0, 0, 0, 72, 5, 250, 45, 6, 1, ARM_SUIT, IRON, HI_METAL), ARMOR("studded leather armor", (char *)0, 1, 0, 0, 0, 72, 3, 200, 15, 7, 1, ARM_SUIT, LEATHER, HI_LEATHER), ARMOR("ring mail", (char *)0, - 1, 0, 0, 0, 72, 5, 250, 100, 7, 0, ARM_SUIT, IRON, HI_METAL), + 1, 0, 0, 0, 72, 5, 250, 100, 7, 1, ARM_SUIT, IRON, HI_METAL), ARMOR("orcish ring mail", "crude ring mail", 0, 0, 0, 0, 20, 5, 250, 80, 8, 1, ARM_SUIT, IRON, CLR_BLACK), ARMOR("leather armor", (char *)0, - 1, 0, 0, 0, 82, 3, 150, 5, 8, 0, ARM_SUIT, LEATHER, HI_LEATHER), + 1, 0, 0, 0, 82, 3, 150, 5, 8, 1, ARM_SUIT, LEATHER, HI_LEATHER), ARMOR("leather jacket", (char *)0, 1, 0, 0, 0, 12, 0, 30, 10, 9, 0, ARM_SUIT, LEATHER, CLR_BLACK), @@ -414,15 +413,15 @@ ARMOR("T-shirt", (char *)0, CLOAK("mummy wrapping", (char *)0, 1, 0, 0, 0, 0, 3, 2, 10, 1, CLOTH, CLR_GRAY), CLOAK("elven cloak", "faded pall", - 0, 1, STEALTH, 8, 0, 10, 60, 9, 3, CLOTH, CLR_BLACK), + 0, 1, STEALTH, 8, 0, 10, 60, 9, 1, CLOTH, CLR_BLACK), CLOAK("orcish cloak", "coarse mantelet", - 0, 0, 0, 8, 0, 10, 40, 10, 2, CLOTH, CLR_BLACK), + 0, 0, 0, 8, 0, 10, 40, 10, 1, CLOTH, CLR_BLACK), CLOAK("dwarvish cloak", "hooded cloak", - 0, 0, 0, 8, 0, 10, 50, 10, 2, CLOTH, HI_CLOTH), + 0, 0, 0, 8, 0, 10, 50, 10, 1, CLOTH, HI_CLOTH), CLOAK("oilskin cloak", "slippery cloak", - 0, 0, 0, 8, 0, 10, 50, 9, 3, CLOTH, HI_CLOTH), + 0, 0, 0, 8, 0, 10, 50, 9, 2, CLOTH, HI_CLOTH), CLOAK("robe", (char *)0, - 1, 1, 0, 3, 0, 15, 50, 8, 3, CLOTH, CLR_RED), + 1, 1, 0, 3, 0, 15, 50, 8, 2, CLOTH, CLR_RED), CLOAK("alchemy smock", "apron", 0, 1, POISON_RES, 9, 0, 10, 50, 9, 1, CLOTH, CLR_WHITE), CLOAK("leather cloak", (char *)0, @@ -431,11 +430,11 @@ CLOAK("leather cloak", (char *)0, CLOAK("cloak of protection", "tattered cape", 0, 1, PROTECTION, 9, 0, 10, 50, 7, 3, CLOTH, HI_CLOTH), CLOAK("cloak of invisibility", "opera cloak", - 0, 1, INVIS, 10, 0, 10, 60, 9, 2, CLOTH, CLR_BRIGHT_MAGENTA), + 0, 1, INVIS, 10, 0, 10, 60, 9, 1, CLOTH, CLR_BRIGHT_MAGENTA), CLOAK("cloak of magic resistance", "ornamental cope", - 0, 1, ANTIMAGIC, 2, 0, 10, 60, 9, 3, CLOTH, CLR_WHITE), + 0, 1, ANTIMAGIC, 2, 0, 10, 60, 9, 1, CLOTH, CLR_WHITE), CLOAK("cloak of displacement", "piece of cloth", - 0, 1, DISPLACED, 10, 0, 10, 50, 9, 2, CLOTH, HI_CLOTH), + 0, 1, DISPLACED, 10, 0, 10, 50, 9, 1, CLOTH, HI_CLOTH), /* shields */ SHIELD("small shield", (char *)0, diff --git a/src/uhitm.c b/src/uhitm.c index f9434e474..9dae57f09 100644 --- a/src/uhitm.c +++ b/src/uhitm.c @@ -1356,7 +1356,7 @@ register struct attack *mattk; armpro = magic_negation(mdef); /* since hero can't be cancelled, only defender's armor applies */ - negated = !((rn2(3) >= armpro) || !rn2(50)); + negated = !(rn2(10) >= 3 * armpro); if (is_demon(youmonst.data) && !rn2(13) && !uwep && u.umonnum != PM_SUCCUBUS && u.umonnum != PM_INCUBUS