extern boolean validvamp(struct monst *, int *, int);
extern int select_newcham_form(struct monst *);
extern void mgender_from_permonst(struct monst *, struct permonst *);
-extern int newcham(struct monst *, struct permonst *, boolean, boolean);
+extern int newcham(struct monst *, struct permonst *, unsigned);
extern int can_be_hatched(int);
extern int egg_type_from_parent(int, boolean);
extern boolean dead_species(int, boolean);
#define ECMD_CANCEL 0x02 /* cmd canceled by user */
#define ECMD_FAIL 0x04 /* cmd failed to finish, maybe with a yafm */
+/* flags for newcham() */
+#define NO_NC_FLAGS 0U
+#define NC_SHOW_MSG 0x01U
+#define NC_VIA_WAND_OR_SPELL 0x02U
+
/* values returned from getobj() callback functions */
enum getobj_callback_returns {
/* generally invalid - can't be used for this purpose. will give a "silly
if (could_poly || could_slime) {
(void) newcham(u.ustuck, could_slime ? &mons[PM_GREEN_SLIME] : 0,
- FALSE, could_slime);
+ could_slime ? NC_SHOW_MSG : NO_NC_FLAGS);
} else if (could_petrify) {
minstapetrify(u.ustuck, TRUE);
} else if (could_grow) {
if (poly || slimer) {
struct permonst *ptr = slimer ? &mons[PM_GREEN_SLIME] : 0;
- (void) newcham(mtmp, ptr, FALSE, cansee(mtmp->mx, mtmp->my));
+ (void) newcham(mtmp, ptr,
+ cansee(mtmp->mx, mtmp->my) ? NC_SHOW_MSG : 0);
}
/* limit "instant" growth to prevent potential abuse */
to the level's difficulty but ignoring the changer's usual
type selection, so was inappropriate for vampshifters.
Let newcham() pick the shape. */
- && newcham(mtmp, (struct permonst *) 0, FALSE, FALSE))
+ && newcham(mtmp, (struct permonst *) 0, NO_NC_FLAGS))
allow_minvent = FALSE;
} else if (mndx == PM_WIZARD_OF_YENDOR) {
mtmp->iswiz = TRUE;
}
if (is_vampshifter(mdef)
- && newcham(mdef, &mons[mdef->cham], FALSE, FALSE)) {
+ && newcham(mdef, &mons[mdef->cham], NO_NC_FLAGS)) {
if (g.vis) {
/* 'it' -- previous form is no longer available and
using that would be excessively verbose */
/* various checks similar to dog_eat and meatobj.
* after monkilled() to provide better message ordering */
if (mdef->cham >= LOW_PM) {
- (void) newcham(magr, (struct permonst *) 0, FALSE, TRUE);
+ (void) newcham(magr, (struct permonst *) 0, NC_SHOW_MSG);
} else if (pd == &mons[PM_GREEN_SLIME] && !slimeproof(pa)) {
- (void) newcham(magr, &mons[PM_GREEN_SLIME], FALSE, TRUE);
+ (void) newcham(magr, &mons[PM_GREEN_SLIME], NC_SHOW_MSG);
} else if (pd == &mons[PM_WRAITH]) {
(void) grow_up(magr, (struct monst *) 0);
/* don't grow up twice */
else
monkilled(mdef, "", AD_RBRE);
}
- } else if (newcham(mdef, (struct permonst *) 0, FALSE, FALSE)) {
+ } else if (newcham(mdef, (struct permonst *) 0, NO_NC_FLAGS)) {
if (g.vis) { /* either seen or adjacent */
boolean was_seen = !!strcmpi("It", Before),
verbosely = flags.verbose || !was_seen;
delobj(otmp);
ptr = mtmp->data;
if (poly) {
- if (newcham(mtmp, (struct permonst *) 0, FALSE, vis))
+ if (newcham(mtmp, (struct permonst *) 0,
+ vis ? NC_SHOW_MSG : NO_NC_FLAGS))
ptr = mtmp->data;
} else if (grow) {
ptr = grow_up(mtmp, (struct monst *) 0);
delobj(otmp); /* munch */
ptr = mtmp->data;
if (poly) {
- if (newcham(mtmp, (struct permonst *) 0, FALSE, vis))
+ if (newcham(mtmp, (struct permonst *) 0,
+ vis ? NC_SHOW_MSG : NO_NC_FLAGS))
ptr = mtmp->data;
} else if (grow) {
ptr = grow_up(mtmp, (struct monst *) 0);
ptr = original_ptr;
delobj(otmp);
if (poly) {
- if (newcham(mtmp, (struct permonst *) 0, FALSE, vis))
+ if (newcham(mtmp, (struct permonst *) 0,
+ vis ? NC_SHOW_MSG : NO_NC_FLAGS))
ptr = mtmp->data;
} else if (grow) {
ptr = grow_up(mtmp, (struct monst *) 0);
if (enexto(&new_xy, mtmp->mx, mtmp->my, &mons[mndx]))
rloc_to(mtmp, new_xy.x, new_xy.y);
}
- (void) newcham(mtmp, &mons[mndx], FALSE, FALSE);
+ (void) newcham(mtmp, &mons[mndx], NO_NC_FLAGS);
if (mtmp->data == &mons[mndx])
mtmp->cham = NON_PM;
else
/* it's a golem, and not a stone golem */
if (canseemon(mtmp))
pline("%s solidifies...", Monnam(mtmp));
- if (newcham(mtmp, &mons[PM_STONE_GOLEM], FALSE, FALSE)) {
+ if (newcham(mtmp, &mons[PM_STONE_GOLEM], NO_NC_FLAGS)) {
if (canseemon(mtmp))
pline("Now it's %s.", an(pmname(mtmp->data, Mgender(mtmp))));
} else {
pline("%s!", buf);
display_nhwindow(WIN_MESSAGE, FALSE);
}
- (void) newcham(mtmp, &mons[mndx], FALSE, FALSE);
+ (void) newcham(mtmp, &mons[mndx], NO_NC_FLAGS);
if (mtmp->data == &mons[mndx])
mtmp->cham = NON_PM;
else
mtmp->mfrozen = 0;
set_mon_min_mhpmax(mtmp, 10); /* mtmp->mhpmax=max(mtmp->m_lev+1,10) */
mtmp->mhp = mtmp->mhpmax;
- (void) newcham(mtmp, &mons[mtmp->cham], FALSE, TRUE);
+ (void) newcham(mtmp, &mons[mtmp->cham], NC_SHOW_MSG);
newsym(mtmp->mx, mtmp->my);
return FALSE; /* didn't petrify */
}
if (mcham >= LOW_PM) {
unsigned mcan = mon->mcan;
- (void) newcham(mon, &mons[mcham], FALSE, FALSE);
+ (void) newcham(mon, &mons[mcham], NO_NC_FLAGS);
mon->cham = NON_PM;
/* newcham() may uncancel a polymorphing monster; override that */
if (mcan)
}
}
if (dochng) {
- if (newcham(mon, ptr, FALSE, msg) && is_vampshifter(mon)) {
+ if (newcham(mon, ptr, msg ? NC_SHOW_MSG : 0) && is_vampshifter(mon)) {
/* for vampshift, override the 10% chance for sex change */
ptr = mon->data;
if (!is_male(ptr) && !is_female(ptr) && !is_neuter(ptr))
int
newcham(
struct monst *mtmp,
- struct permonst *mdat,
- boolean polyspot, /* change is the result of wand or spell of polymorph */
- boolean msg) /* "The oldmon turns into a newmon!" */
+ struct permonst *mdat, unsigned ncflags)
{
- int hpn, hpd;
- int mndx, tryct;
+ boolean polyspot = ((ncflags & NC_VIA_WAND_OR_SPELL) !=0),
+ /* "The oldmon turns into a newmon!" */
+ msg = ((ncflags & NC_SHOW_MSG) != 0);
+ int hpn, hpd, mndx, tryct;
struct permonst *olddata = mtmp->data;
char *p, oldname[BUFSZ], l_oldname[BUFSZ], newname[BUFSZ];
&& (g.mvitals[mtmp->cham].mvflags & G_GENOD));
if ((g.mvitals[mndx].mvflags & G_GENOD) || kill_cham) {
if (mtmp->cham >= LOW_PM && !kill_cham)
- (void) newcham(mtmp, (struct permonst *) 0, FALSE, TRUE);
+ (void) newcham(mtmp, (struct permonst *) 0, NC_SHOW_MSG);
else
mondead(mtmp);
}
reslt = 1;
domsg = FALSE;
} else if (is_vampshifter(mon)) {
- reslt = newcham(mon, ptr, FALSE, FALSE);
+ reslt = newcham(mon, ptr, NO_NC_FLAGS);
}
if (reslt && domsg) {
return 2;
case MUSE_WAN_POLYMORPH:
mzapwand(mtmp, otmp, TRUE);
- (void) newcham(mtmp, muse_newcham_mon(mtmp), TRUE, FALSE);
+ (void) newcham(mtmp, muse_newcham_mon(mtmp), NC_VIA_WAND_OR_SPELL);
if (oseen)
makeknown(WAN_POLYMORPH);
return 2;
m_useup(mtmp, otmp);
if (vismon)
pline("%s suddenly mutates!", Monnam(mtmp));
- (void) newcham(mtmp, muse_newcham_mon(mtmp), FALSE, FALSE);
+ (void) newcham(mtmp, muse_newcham_mon(mtmp), NO_NC_FLAGS);
if (oseen)
makeknown(POT_POLYMORPH);
return 2;
worm_move(mtmp);
newsym(g.trapx, g.trapy);
- (void) newcham(mtmp, (struct permonst *) 0, FALSE, FALSE);
+ (void) newcham(mtmp, (struct permonst *) 0, NO_NC_FLAGS);
return 2;
case MUSE_BAG:
return mloot_container(mtmp, otmp, vismon);
for, make it start out looking like what was asked for */
if (mtmp->cham != NON_PM && firstchoice != NON_PM
&& mtmp->cham != firstchoice)
- (void) newcham(mtmp, &mons[firstchoice], FALSE, FALSE);
+ (void) newcham(mtmp, &mons[firstchoice], NO_NC_FLAGS);
}
return madeany;
}
/* if hero has protection from shape changers, cham field will
be NON_PM; otherwise, set form to match the statue */
if (mon && mon->cham >= LOW_PM)
- (void) newcham(mon, mptr, FALSE, FALSE);
+ (void) newcham(mon, mptr, NO_NC_FLAGS);
} else {
if (cause == ANIMATE_SPELL)
mmflags |= MM_ADJACENTOK;
if (resists_magm(mtmp)) {
shieldeff(mtmp->mx, mtmp->my);
} else if (!resist(mtmp, WAND_CLASS, 0, NOTELL)) {
- (void) newcham(mtmp, (struct permonst *) 0, FALSE, in_sight);
+ (void) newcham(mtmp, (struct permonst *) 0,
+ in_sight ? NC_SHOW_MSG : NO_NC_FLAGS);
if (in_sight)
seetrap(trap);
}
if (!resists_magm(steed) && !resist(steed, WAND_CLASS, 0, NOTELL)) {
struct permonst *mdat = steed->data;
- (void) newcham(steed, (struct permonst *) 0, FALSE, FALSE);
+ (void) newcham(steed, (struct permonst *) 0, NO_NC_FLAGS);
if (!can_saddle(steed) || !can_ride(steed)) {
dismount_steed(DISMOUNT_POLY);
} else {
/* this assumes newcham() won't fail; since hero has
a slime attack, green slimes haven't been geno'd */
You("turn %s into slime.", mon_nam(mdef));
- if (newcham(mdef, &mons[PM_GREEN_SLIME], FALSE, FALSE))
+ if (newcham(mdef, &mons[PM_GREEN_SLIME], NO_NC_FLAGS))
pd = mdef->data;
}
/* munslime attempt could have been fatal */
return; /* physical damage only */
if (!rn2(4) && !slimeproof(pd)) {
if (!munslime(mdef, FALSE) && !DEADMONSTER(mdef)) {
- if (newcham(mdef, &mons[PM_GREEN_SLIME], FALSE,
- (boolean) (g.vis && canseemon(mdef))))
+ unsigned ncflags = NO_NC_FLAGS;
+
+ if (g.vis && canseemon(mdef))
+ ncflags |= NC_SHOW_MSG;
+ if (newcham(mdef, &mons[PM_GREEN_SLIME], ncflags))
pd = mdef->data;
mdef->mstrategy &= ~STRAT_WAITFORU;
mhm->hitflags = MM_HIT;
/* force vampire in bat, cloud, or wolf form to revert back to
vampire form now instead of dealing with that when it dies */
if (is_vampshifter(mdef)
- && newcham(mdef, &mons[mdef->cham], FALSE, FALSE)) {
+ && newcham(mdef, &mons[mdef->cham], NO_NC_FLAGS)) {
You("engulf it, then expel it.");
if (canspotmon(mdef))
pline("It turns into %s.", a_monnam(mdef));
/* g.context.bypasses = TRUE; ## for make_corpse() */
/* no corpse after system shock */
xkilled(mtmp, XKILL_GIVEMSG | XKILL_NOCORPSE);
- } else if (newcham(mtmp, (struct permonst *) 0,
- 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)
- || engulfing_u(mtmp)))
- learn_it = TRUE;
+ } else {
+ unsigned ncflags = NO_NC_FLAGS;
+
+ if (polyspot)
+ ncflags |= NC_VIA_WAND_OR_SPELL;
+ if (give_msg)
+ ncflags |= NC_SHOW_MSG;
+ if (newcham(mtmp, (struct permonst *) 0, ncflags) != 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],
+ ncflags) != 0)) {
+ if (give_msg && (canspotmon(mtmp)
+ || engulfing_u(mtmp)))
+ learn_it = TRUE;
+ }
}
/* do this even if polymorphed failed (otherwise using
char *name = Monnam(mtmp);
/* turn into flesh golem */
- if (newcham(mtmp, &mons[PM_FLESH_GOLEM], FALSE, FALSE)) {
+ if (newcham(mtmp, &mons[PM_FLESH_GOLEM], NO_NC_FLAGS)) {
if (canseemon(mtmp))
pline("%s turns to flesh!", name);
} else {
free_omonst(corpse);
if (mtmp->cham == PM_DOPPELGANGER) {
/* change shape to match the corpse */
- (void) newcham(mtmp, mptr, FALSE, FALSE);
+ (void) newcham(mtmp, mptr, NO_NC_FLAGS);
} else if (mtmp->data->mlet == S_ZOMBIE) {
mtmp->mhp = mtmp->mhpmax = 100;
mon_adjust_speed(mtmp, 2, (struct obj *) 0); /* MFAST */
ptr = mon->data;
/* this golem handling is redundant... */
if (is_golem(ptr) && ptr != &mons[PM_FLESH_GOLEM])
- (void) newcham(mon, &mons[PM_FLESH_GOLEM], TRUE, FALSE);
+ (void) newcham(mon, &mons[PM_FLESH_GOLEM],
+ NC_VIA_WAND_OR_SPELL);
} else if ((ptr->geno & (G_NOCORPSE | G_UNIQ)) != 0) {
/* didn't revive but can't leave corpse either */
res = 0;