diff --git a/include/extern.h b/include/extern.h index 6fd1df12f..6f355fa07 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.6 extern.h $NHDT-Date: 1513130012 2017/12/13 01:53:32 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.621 $ */ +/* NetHack 3.6 extern.h $NHDT-Date: 1514769568 2018/01/01 01:19:28 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.622 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1397,6 +1397,7 @@ E void FDECL(restore_cham, (struct monst *)); E boolean FDECL(hideunder, (struct monst *)); E void FDECL(hide_monst, (struct monst *)); E void FDECL(mon_animal_list, (BOOLEAN_P)); +E boolean FDECL(validvamp, (struct monst *, int *, int)); E int FDECL(select_newcham_form, (struct monst *)); E void FDECL(mgender_from_permonst, (struct monst *, struct permonst *)); E int FDECL(newcham, diff --git a/src/mon.c b/src/mon.c index a872b93a9..62fb34a8f 100644 --- a/src/mon.c +++ b/src/mon.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 mon.c $NHDT-Date: 1505266804 2017/09/13 01:40:04 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.244 $ */ +/* NetHack 3.6 mon.c $NHDT-Date: 1514769571 2018/01/01 01:19:31 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.246 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -23,7 +23,6 @@ STATIC_DCL void FDECL(kill_eggs, (struct obj *)); STATIC_DCL int FDECL(pickvampshape, (struct monst *)); STATIC_DCL boolean FDECL(isspecmon, (struct monst *)); STATIC_DCL boolean FDECL(validspecmon, (struct monst *, int)); -STATIC_DCL boolean FDECL(validvamp, (struct monst *, int *, int)); STATIC_DCL struct permonst *FDECL(accept_newcham_form, (int)); STATIC_DCL struct obj *FDECL(make_corpse, (struct monst *, unsigned)); STATIC_DCL void FDECL(m_detach, (struct monst *, struct permonst *)); @@ -3162,7 +3161,7 @@ int mndx; } /* prevent wizard mode user from specifying invalid vampshifter shape */ -STATIC_OVL boolean +boolean validvamp(mon, mndx_p, monclass) struct monst *mon; int *mndx_p, monclass; diff --git a/src/sp_lev.c b/src/sp_lev.c index 170a6e251..e2d362c6c 100644 --- a/src/sp_lev.c +++ b/src/sp_lev.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 sp_lev.c $NHDT-Date: 1514720301 2017/12/31 11:38:21 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.94 $ */ +/* NetHack 3.6 sp_lev.c $NHDT-Date: 1514769572 2018/01/01 01:19:32 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.95 $ */ /* Copyright (c) 1989 by Jean-Christophe Collet */ /* NetHack may be freely redistributed. See license for details. */ @@ -1589,11 +1589,14 @@ struct mkroom *croom; mtmp = christen_monst(mtmp, m->name.str); /* - * This is currently hardwired for mimics only. It should - * eventually be expanded. + * This doesn't complain if an attempt is made to give a + * non-mimic/non-shapechanger an appearance or to give a + * shapechanger a non-monster shape, it just refuses to comply. */ if (m->appear_as.str - && ((mtmp->data->mlet == S_MIMIC) || mtmp->cham >= LOW_PM) + && ((mtmp->data->mlet == S_MIMIC) + /* shapechanger (chameleons, et al, and vampires) */ + || (mtmp->cham >= LOW_PM && m->appear == M_AP_MONSTER)) && !Protection_from_shape_changers) { int i; @@ -1658,7 +1661,29 @@ struct mkroom *croom; mndx = select_newcham_form(mtmp); else mndx = name_to_mon(m->appear_as.str); - if ((mndx != NON_PM) && (&mons[mndx] != mtmp->data)) { + + if (mndx == NON_PM || (is_vampshifter(mtmp) + && !validvamp(mtmp, &mndx, S_HUMAN))) { + impossible("create_monster: invalid %s (\"%s\")", + (mtmp->data->mlet == S_MIMIC) + ? "mimic appearance" + : (mtmp->data == &mons[PM_WIZARD_OF_YENDOR]) + ? "Wizard appearance" + : is_vampshifter(mtmp) + ? "vampire shape" + : "chameleon shape", + m->appear_as.str); + } else if (&mons[mndx] == mtmp->data) { + /* explicitly forcing a mimic to appear as itself */ + mtmp->m_ap_type = M_AP_NOTHING; + mtmp->mappearance = 0; + } else if (mtmp->data->mlet == S_MIMIC + || mtmp->data == &mons[PM_WIZARD_OF_YENDOR]) { + /* this is ordinarily only used for Wizard clones + and hasn't been exhaustively tested for mimics */ + mtmp->m_ap_type = M_AP_MONSTER; + mtmp->mappearance = mndx; + } else { /* chameleon or vampire */ struct permonst *mdat = &mons[mndx]; struct permonst *olddata = mtmp->data;