diff --git a/doc/fixes36.2 b/doc/fixes36.2 index 8fb98475e..4a4fd0fc3 100644 --- a/doc/fixes36.2 +++ b/doc/fixes36.2 @@ -125,6 +125,8 @@ poly'd shapechanger and hiding mimic will revert to normal when cancelled, like werecreature in beast form and non-Unchanging hero cancelled shapeshifter is no longer able to change shape cancelled shapeshifter hit by polymorph magic will become uncancelled +polymorph zap which creates a new long worm (or retains an old one via wizard + mode monpolycontrol) can hit that worm multiple times (tail segments) Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository diff --git a/src/worn.c b/src/worn.c index e7860c655..1eb1ed671 100644 --- a/src/worn.c +++ b/src/worn.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 worn.c $NHDT-Date: 1526728754 2018/05/19 11:19:14 $ $NHDT-Branch: NetHack-3.6.2 $:$NHDT-Revision: 1.51 $ */ +/* NetHack 3.6 worn.c $NHDT-Date: 1537234121 2018/09/18 01:28:41 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.55 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -710,6 +710,13 @@ clear_bypasses() struct obj *otmp, *nobj; struct monst *mtmp; + /* + * 'Object' bypass is also used for one monster function: + * polymorph control of long worms. Activated via setting + * context.bypasses even if no specific object has been + * bypassed. + */ + for (otmp = fobj; otmp; otmp = nobj) { nobj = otmp->nobj; if (otmp->bypass) { @@ -741,10 +748,19 @@ clear_bypasses() continue; for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) otmp->bypass = 0; + /* long worm created by polymorph has mon->mextra->mcorpsenm set + to PM_LONG_WORM to flag it as not being subject to further + polymorph (so polymorph zap won't hit monster to transform it + into a long worm, then hit that worm's tail and transform it + again on same zap); clearing mcorpsenm reverts worm to normal */ + if (mtmp->data == &mons[PM_LONG_WORM] && has_mcorpsenm(mtmp)) + MCORPSENM(mtmp) = NON_PM; } for (mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon) { for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj) otmp->bypass = 0; + /* no MCORPSENM(mtmp)==PM_LONG_WORM check here; long worms can't + be just created by polymorph and migrating at the same time */ } /* billobjs and mydogs chains don't matter here */ context.bypasses = FALSE; diff --git a/src/zap.c b/src/zap.c index 37b38e8ab..7a5ab3416 100644 --- a/src/zap.c +++ b/src/zap.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 zap.c $NHDT-Date: 1525012627 2018/04/29 14:37:07 $ $NHDT-Branch: master $:$NHDT-Revision: 1.277 $ */ +/* NetHack 3.6 zap.c $NHDT-Date: 1537234123 2018/09/18 01:28:43 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.287 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -222,7 +222,11 @@ struct obj *otmp; case WAN_POLYMORPH: case SPE_POLYMORPH: case POT_POLYMORPH: - if (resists_magm(mtmp)) { + if (mtmp->data == &mons[PM_LONG_WORM] && has_mcorpsenm(mtmp)) { + /* if a long worm has mcorpsenm set, it was polymophed by + the current zap and shouldn't be affected if hit again */ + ; + } else if (resists_magm(mtmp)) { /* magic resistance protects from polymorph traps, so make it guard against involuntary polymorph attacks too... */ shieldeff(mtmp->mx, mtmp->my); @@ -238,6 +242,7 @@ struct obj *otmp; if (polyspot) for (obj = mtmp->minvent; obj; obj = obj->nobj) bypass_obj(obj); + /* natural shapechangers aren't affected by system shock (unless protection from shapechangers is interfering with their metabolism...) */ @@ -261,6 +266,22 @@ struct obj *otmp; || (u.uswallow && mtmp == u.ustuck))) learn_it = TRUE; } + + /* do this even if polymorphed failed (otherwise using + flags.mon_polycontrol prompting to force mtmp to remain + 'long worm' would prompt again if zap hit another segment) */ + if (!DEADMONSTER(mtmp) && mtmp->data == &mons[PM_LONG_WORM]) { + if (!has_mcorpsenm(mtmp)) + newmcorpsenm(mtmp); + /* flag to indicate that mtmp became a long worm + on current zap, so further hits (on mtmp's new + tail) don't do further transforms */ + MCORPSENM(mtmp) = PM_LONG_WORM; + /* flag to indicate that cleanup is needed; object + bypass cleanup also clears mon->mextra->mcorpsenm + for all long worms on the level */ + context.bypasses = TRUE; + } } break; case WAN_CANCELLATION: