fix issue #326 - can't wish for were-foo corpse

"were{rat,jackal,wolf}" each occur twice in mons[], once for the
beast form and second time among '@' for the human form.  Wishing
for werecreature corpse or tin always matches the first entry so
yields the beast form, but all their beast forms are flagged as
no-corpse so the wish would fallback to a corpse with random monster
type.  Wishing for werecreature figurine worked but always produced
one that created its beast form if/when activated.

This fix allows specifying "human werecreature" to match the second
entry.  It's optional for corpse and tin; the wish code will now
switch to that implicitly if it gets a no-corpse were-form for
those.  It has to be specified explicitly to get a figurine that
will activate as the human form.  It works for ^G too.

Fixes #326
This commit is contained in:
PatR
2020-04-19 05:28:18 -07:00
parent 05403182eb
commit 2337252acf
3 changed files with 27 additions and 1 deletions

View File

@@ -770,6 +770,15 @@ const char **remainder_p;
{ "woodland nymph", PM_WOOD_NYMPH },
{ "halfling", PM_HOBBIT }, /* potential guess for polyself */
{ "genie", PM_DJINNI }, /* potential guess for ^G/#wizgenesis */
/* prefix used to workaround duplicate monster names for
monsters with alternate forms */
{ "human wererat", PM_HUMAN_WERERAT },
{ "human werejackal", PM_HUMAN_WEREJACKAL },
{ "human werewolf", PM_HUMAN_WEREWOLF },
/* for completeness */
{ "rat wererat", PM_WERERAT },
{ "jackal werejackal", PM_WEREJACKAL },
{ "wolf werewolf", PM_WEREWOLF },
/* Hyphenated names -- it would be nice to handle these via
fuzzymatch() but it isn't able to ignore trailing stuff */
{ "ki rin", PM_KI_RIN },

View File

@@ -4116,8 +4116,17 @@ struct obj *no_wish;
/* set otmp->corpsenm or dragon scale [mail] */
if (mntmp >= LOW_PM) {
int humanwere;
if (mntmp == PM_LONG_WORM_TAIL)
mntmp = PM_LONG_WORM;
/* werecreatures in beast form are all flagged no-corpse so for
corpses and tins, switch to their corresponding human form;
for figurines, override the can't-be-human restriction instead */
if (typ != FIGURINE && is_were(&mons[mntmp])
&& (g.mvitals[mntmp].mvflags & G_NOCORPSE) != 0
&& (humanwere = counter_were(mntmp)) != NON_PM)
mntmp = humanwere;
switch (typ) {
case TIN:
@@ -4144,7 +4153,8 @@ struct obj *no_wish;
set_corpsenm(otmp, mntmp);
break;
case FIGURINE:
if (!(mons[mntmp].geno & G_UNIQ) && !is_human(&mons[mntmp])
if (!(mons[mntmp].geno & G_UNIQ)
&& (!is_human(&mons[mntmp]) || is_were(&mons[mntmp]))
#ifdef MAIL_STRUCTURES
&& mntmp != PM_MAIL_DAEMON
#endif