From: PatR Date: Fri, 25 Mar 2016 23:49:01 +0000 (-0700) Subject: shapechanger polymorph bit X-Git-Tag: NetHack-3.6.1_RC01~856 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=41b8f38272e81f8d17fdeae858a48cec4e1911ce;p=nethack shapechanger polymorph bit Rescuing an old revision from bit rot: If one of fog clouds or vampire bats has been genocided and you try to polymorph a vampire disguised as the other, it won't change form because the shape it's currently in is the only candidate shape left for vampshifting. This makes shapechangers who fail to take on a new shape when polymorphed try again, specifying original form on the second try. It's unlikely to affect chameleons, but disguised vampires will sometimes become undisguised instead of seeming to be immune from polymorph. --- diff --git a/src/mon.c b/src/mon.c index b0eec652e..b3e95eca6 100644 --- a/src/mon.c +++ b/src/mon.c @@ -3209,7 +3209,7 @@ boolean msg; /* "The oldmon turns into a newmon!" */ int hpn, hpd; int mndx, tryct; struct permonst *olddata = mtmp->data; - char oldname[BUFSZ], l_oldname[BUFSZ], newname[BUFSZ]; + char *p, oldname[BUFSZ], l_oldname[BUFSZ], newname[BUFSZ]; /* Riders are immune to polymorph and green slime (but apparent Rider might actually be a doppelganger) */ @@ -3224,7 +3224,7 @@ boolean msg; /* "The oldmon turns into a newmon!" */ } /* we need this one whether msg is true or not */ Strcpy(l_oldname, x_monnam(mtmp, ARTICLE_THE, (char *) 0, - (has_mname(mtmp)) ? SUPPRESS_SADDLE : 0, FALSE)); + has_mname(mtmp) ? SUPPRESS_SADDLE : 0, FALSE)); /* mdat = 0 -> caller wants a random monster shape */ if (mdat == 0) { @@ -3247,23 +3247,18 @@ boolean msg; /* "The oldmon turns into a newmon!" */ } else if (mvitals[monsndx(mdat)].mvflags & G_GENOD) return 0; /* passed in mdat is genocided */ - if (mdat == mtmp->data) + if (mdat == olddata) return 0; /* still the same monster */ mgender_from_permonst(mtmp, mdat); - - if (In_endgame(&u.uz) && is_mplayer(olddata) && has_mname(mtmp)) { - /* mplayers start out as "Foo the Bar", but some of the - * titles are inappropriate when polymorphed, particularly - * into the opposite sex. players don't use ranks when - * polymorphed, so dropping the rank for mplayers seems - * reasonable. - */ - char *p = index(MNAME(mtmp), ' '); - - if (p) - *p = '\0'; - } + /* Endgame mplayers start out as "Foo the Bar", but some of the + * titles are inappropriate when polymorphed, particularly into + * the opposite sex. Player characters don't use ranks when + * polymorphed, so dropping rank for mplayers seems reasonable. + */ + if (In_endgame(&u.uz) && is_mplayer(olddata) + && has_mname(mtmp) && (p = strstr(MNAME(mtmp), " the ")) != 0) + *p = '\0'; if (mtmp->wormno) { /* throw tail away */ wormgone(mtmp); diff --git a/src/zap.c b/src/zap.c index 854c62fad..daa4d5ec6 100644 --- a/src/zap.c +++ b/src/zap.c @@ -221,11 +221,17 @@ struct obj *otmp; it guard against involuntary polymorph attacks too... */ shieldeff(mtmp->mx, mtmp->my); } else if (!resist(mtmp, otmp->oclass, 0, NOTELL)) { + boolean polyspot = (otyp != POT_POLYMORPH), + give_msg = (!Hallucination + && (canseemon(mtmp) + || (u.uswallow && mtmp == u.ustuck))); + /* dropped inventory (due to death by system shock, or loss of wielded weapon and/or worn armor due to limitations of new shape) won't be hit by this zap */ - for (obj = mtmp->minvent; obj; obj = obj->nobj) - bypass_obj(obj); + 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...) */ @@ -238,8 +244,15 @@ struct obj *otmp; /* no corpse after system shock */ xkilled(mtmp, 3); } else if (newcham(mtmp, (struct permonst *) 0, - (otyp != POT_POLYMORPH), FALSE)) { - if (!Hallucination && canspotmon(mtmp)) + polyspot, give_msg) != 0 + /* if shapechange failed because there aren't + enough eligible candidates (most likely for + vampshifter), try reverting to original form */ + || (mtmp->cham >= LOW_PM + && newcham(mtmp, &mons[mtmp->cham], + polyspot, give_msg) != 0)) { + if (give_msg && (canspotmon(mtmp) + || (u.uswallow && mtmp == u.ustuck))) learn_it = TRUE; } }