- restore intended behaviour of kill_genocided_monsters().
It has been incorrect since the chameleon overhaul in June 2004.
- eliminate CHAM_ORDINARY and use NON_PM instead.
unsigned m_id;
short mnum; /* permanent monster index number */
short cham; /* if shapeshifter, orig mons[] idx goes here */
-#define CHAM_ORDINARY 0 /* not a shapechanger */
short movement; /* movement points (derived from permonst definition and added effects */
uchar m_lev; /* adjusted difficulty level of monster */
aligntyp malign; /* alignment of this monster, relative to the
#define MAX_EGG_HATCH_TIME 200 /* longest an egg can remain unhatched */
#define stale_egg(egg) ((monstermoves - (egg)->age) > (2*MAX_EGG_HATCH_TIME))
#define ofood(o) ((o)->otyp == CORPSE || (o)->otyp == EGG || (o)->otyp == TIN)
-#define polyfodder(obj) (ofood(obj) && \
- pm_to_cham((obj)->corpsenm) != CHAM_ORDINARY)
+#define polyfodder(obj) (ofood(obj) && pm_to_cham((obj)->corpsenm) != NON_PM)
#define mlevelgain(obj) (ofood(obj) && (obj)->corpsenm == PM_WRAITH)
#define mhealup(obj) (ofood(obj) && (obj)->corpsenm == PM_NURSE)
struct monst *mtmp;
{
mtmp->meating = 0;
- if (mtmp->m_ap_type && mtmp->mappearance && mtmp->cham == CHAM_ORDINARY) {
+ if (mtmp->m_ap_type && mtmp->mappearance && mtmp->cham == NON_PM) {
/* was eating a mimic and now appearance needs resetting */
mtmp->m_ap_type = 0;
mtmp->mappearance = 0;
-/* SCCS Id: @(#)makemon.c 3.5 2005/11/02 */
+/* SCCS Id: @(#)makemon.c 3.5 2006/03/11 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
if (mndx == PM_VLAD_THE_IMPALER)
mitem = CANDELABRUM_OF_INVOCATION;
- mtmp->cham = CHAM_ORDINARY; /* default is "not a shapechanger" */
- if ((mcham = pm_to_cham(mndx)) != CHAM_ORDINARY) {
+ mtmp->cham = NON_PM; /* default is "not a shapechanger" */
+ if ((mcham = pm_to_cham(mndx)) != NON_PM) {
/* this is a shapechanger after all */
if (Protection_from_shape_changers) {
- ; /* stuck in its natural form (CHAM_ORDINARY) */
+ ; /* stuck in its natural form (NON_PM) */
} else {
/* General shapechangers start out with random form
(this explicitly picks something from the normal
if (mattk->adtyp == AD_DGST) {
/* various checks similar to dog_eat and meatobj.
* after monkilled() to provide better message ordering */
- if (mdef->cham != CHAM_ORDINARY) {
+ if (mdef->cham >= LOW_PM) {
(void) newcham(magr, (struct permonst *)0, FALSE, TRUE);
} else if (mdef->data == &mons[PM_GREEN_SLIME]) {
(void) newcham(magr, &mons[PM_GREEN_SLIME], FALSE, TRUE);
}
/* Special demon handling code */
- if((mtmp->cham == CHAM_ORDINARY) && is_demon(mdat) && !range2
+ if((mtmp->cham == NON_PM) && is_demon(mdat) && !range2
&& mtmp->data != &mons[PM_BALROG]
&& mtmp->data != &mons[PM_SUCCUBUS]
&& mtmp->data != &mons[PM_INCUBUS])
if (!mtmp->mcan && !rn2(13)) (void)msummon(mtmp);
/* Special lycanthrope handling code */
- if((mtmp->cham == CHAM_ORDINARY) && is_were(mdat) && !range2) {
+ if((mtmp->cham == NON_PM) && is_were(mdat) && !range2) {
if(is_human(mdat)) {
if(!rn2(5 - (night() * 2)) && !mtmp->mcan) new_were(mtmp);
}
}
-#define Athome (Inhell && (mtmp->cham == CHAM_ORDINARY))
+#define Athome (Inhell && (mtmp->cham == NON_PM))
int
demon_talk(mtmp) /* returns 1 if it won't attack. */
return mndx;
}
-/* return monster index if chameleon, or CHAM_ORDINARY if not */
+/* return monster index if chameleon, or NON_PM if not */
int
pm_to_cham(mndx)
int mndx;
{
- int mcham = CHAM_ORDINARY;
+ int mcham = NON_PM;
/*
* As of 3.5.0 we just check M2_SHAPESHIFTER instead of having a
* big switch statement with hardcoded shapeshifter types here.
*/
- if (mndx > LOW_PM && is_shapeshifter(&mons[mndx])) mcham = mndx;
+ if (mndx >= LOW_PM && is_shapeshifter(&mons[mndx])) mcham = mndx;
return mcham;
}
mon_regen(mtmp, FALSE);
/* possibly polymorph shapechangers and lycanthropes */
- if (mtmp->cham != CHAM_ORDINARY) {
+ if (mtmp->cham >= LOW_PM) {
if (is_vampshifter(mtmp) || mtmp->data->mlet == S_VAMPIRE)
decide_to_shapeshift(mtmp,0);
else if (!rn2(6))
int mndx = mtmp->cham;
int x = mtmp->mx, y = mtmp->my;
/* this only happens if shapeshifted */
- if (mndx != CHAM_ORDINARY && mndx != monsndx(mtmp->data)) {
+ if (mndx >= LOW_PM && mndx != monsndx(mtmp->data)) {
char buf[BUFSZ];
boolean in_door = amorphous(mtmp->data) &&
closed_door(mtmp->mx,mtmp->my);
}
newcham(mtmp, &mons[mndx], FALSE, FALSE);
if (mtmp->data == &mons[mndx])
- mtmp->cham = CHAM_ORDINARY;
+ mtmp->cham = NON_PM;
else
mtmp->cham = mndx;
if ((!Blind && canseemon(mtmp)) || sensemon(mtmp))
mptr = mtmp->data; /* save this for m_detach() */
/* restore chameleon, lycanthropes to true form at death */
- if (mtmp->cham != CHAM_ORDINARY) {
+ if (mtmp->cham >= LOW_PM) {
set_mon_data(mtmp, &mons[mtmp->cham], -1);
- mtmp->cham = CHAM_ORDINARY;
+ mtmp->cham = NON_PM;
}
else if (mtmp->data == &mons[PM_WEREJACKAL])
set_mon_data(mtmp, &mons[PM_HUMAN_WEREJACKAL], -1);
for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp)) continue;
mcham = (int) mtmp->cham;
- if (mcham != CHAM_ORDINARY) {
+ if (mcham >= LOW_PM) {
(void) newcham(mtmp, &mons[mcham],
FALSE, FALSE);
- mtmp->cham = CHAM_ORDINARY;
+ mtmp->cham = NON_PM;
}
if(is_were(mtmp->data) && mtmp->data->mlet != S_HUMAN)
new_were(mtmp);
if (Protection_from_shape_changers) {
mcham = (int) mon->cham;
- if (mcham != CHAM_ORDINARY) {
- mon->cham = CHAM_ORDINARY;
+ if (mcham >= LOW_PM) {
+ mon->cham = NON_PM;
(void) newcham(mon, &mons[mcham], FALSE, FALSE);
} else if (is_were(mon->data) && !is_human(mon->data)) {
new_were(mon);
}
- } else if (mon->cham == CHAM_ORDINARY) {
+ } else if (mon->cham == NON_PM) {
mon->cham = pm_to_cham(monsndx(mon->data));
}
}
restrap(mtmp)
register struct monst *mtmp;
{
- if((mtmp->cham != CHAM_ORDINARY) || mtmp->mcan || mtmp->m_ap_type ||
+ if((mtmp->cham >= LOW_PM) || mtmp->mcan || mtmp->m_ap_type ||
cansee(mtmp->mx, mtmp->my) || rn2(3) || (mtmp == u.ustuck) ||
(sensemon(mtmp) && distu(mtmp->mx, mtmp->my) <= 2))
return(FALSE);
* If we're shifted and getting low on hp, maybe shift back.
* If we're not already shifted and in good health, maybe shift.
*/
- if ((mon->mhp <= mon->mhpmax / 6) && rn2(4))
+ if ((mon->mhp <= mon->mhpmax / 6) &&
+ rn2(4) && (mon->cham >= LOW_PM))
(void) newcham(mon, &mons[mon->cham], FALSE, msg);
- } else if (mon->data->mlet == S_VAMPIRE && mon->cham == CHAM_ORDINARY
- && !rn2(6) && (mon->mhp > mon->mhpmax - ((mon->mhpmax / 10) + 1))) {
+ } else if (mon->data->mlet == S_VAMPIRE && mon->cham == NON_PM &&
+ !rn2(6) && (mon->mhp > mon->mhpmax - ((mon->mhpmax / 10) + 1))) {
(void) newcham(mon, (struct permonst *)0, FALSE, msg);
}
}
}
mndx = !rn2(4) ? PM_FOG_CLOUD : PM_VAMPIRE_BAT;
break;
- case CHAM_ORDINARY:
+ case NON_PM: /* ordinary */
{
struct obj *m_armr = which_armor(mon, W_ARM);
kill_genocided_monsters()
{
struct monst *mtmp, *mtmp2;
- boolean kill_cham[NUMMONS];
+ boolean kill_cham;
int mndx;
- kill_cham[CHAM_ORDINARY] = FALSE; /* (this is mndx==0) */
- for (mndx = LOW_PM; mndx < NUMMONS; mndx++)
- kill_cham[mndx] = (mvitals[mndx].mvflags & G_GENOD) != 0;
/*
* Called during genocide, and again upon level change. The latter
* catches up with any migrating monsters as they finally arrive at
* 2) otherwise, force every chameleon which is imitating
* any genocided species to take on a new form.
*/
- for (mtmp = fmon; mtmp; mtmp = mtmp2) {
+ for (mtmp = fmon; mtmp; mtmp = mtmp2, kill_cham = FALSE) {
mtmp2 = mtmp->nmon;
if (DEADMONSTER(mtmp)) continue;
mndx = monsndx(mtmp->data);
- if ((mvitals[mndx].mvflags & G_GENOD) || kill_cham[mtmp->cham]) {
- if ((mtmp->cham != CHAM_ORDINARY) && !kill_cham[mtmp->cham])
- (void) newcham(mtmp, (struct permonst *)0, FALSE, FALSE);
+ if (mtmp->cham >= LOW_PM && (mvitals[mtmp->cham].mvflags & G_GENOD))
+ kill_cham = TRUE;
+ if ((mvitals[mndx].mvflags & G_GENOD) || kill_cham) {
+ if (mtmp->cham >= LOW_PM && !kill_cham)
+ (void) newcham(mtmp, (struct permonst *)0, FALSE, FALSE);
else
- mondead(mtmp);
+ mondead(mtmp);
}
if (mtmp->minvent) kill_eggs(mtmp->minvent);
}
struct permonst *ptr;
{
int reslt = 0;
- if (mon->cham != CHAM_ORDINARY) {
+ if (mon->cham >= LOW_PM) {
if (ptr == &mons[mon->cham])
- mon->cham = CHAM_ORDINARY;
+ mon->cham = NON_PM;
reslt = newcham(mon, ptr, FALSE, FALSE);
- } else if (mon->cham == CHAM_ORDINARY && ptr != mon->data) {
+ } else if (mon->cham == NON_PM && ptr != mon->data) {
mon->cham = monsndx(mon->data);
reslt = newcham(mon, ptr, FALSE, FALSE);
}
/*
* ants
*/
- /* Never use M2_SHAPESHIFTER for mons[0] as long as CHAM_ORDINARY==0 */
MON("giant ant", S_ANT,
LVL(2, 18, 3, 0, 0), (G_GENO|G_SGROUP|3),
A(ATTK(AT_BITE, AD_PHYS, 1, 4),
return FALSE;
if (!stuck && !immobile &&
- (mtmp->cham == CHAM_ORDINARY) && monstr[monsndx(mdat)] < 6) {
+ (mtmp->cham == NON_PM) && monstr[monsndx(mdat)] < 6) {
boolean ignore_boulders = (verysmall(mdat) ||
throws_rocks(mdat) ||
passes_walls(mdat));
}
nomore(MUSE_WAN_POLYMORPH);
if(obj->otyp == WAN_POLYMORPH && obj->spe > 0
- && (mtmp->cham == CHAM_ORDINARY)
+ && (mtmp->cham == NON_PM)
&& monstr[monsndx(mdat)] < 6) {
m.misc = obj;
m.has_misc = MUSE_WAN_POLYMORPH;
}
nomore(MUSE_POT_POLYMORPH);
if(obj->otyp == POT_POLYMORPH
- && (mtmp->cham == CHAM_ORDINARY)
+ && (mtmp->cham == NON_PM)
&& monstr[monsndx(mdat)] < 6) {
m.misc = obj;
m.has_misc = MUSE_POT_POLYMORPH;
}
else if (mtmp->mpeaceful) Strcat(info, ", peaceful");
if (mtmp->meating) Strcat(info, ", eating");
- if (mtmp->meating && (mtmp->cham == CHAM_ORDINARY) &&
+ if (mtmp->meating && (mtmp->cham == NON_PM) &&
mtmp->mappearance && mtmp->m_ap_type) {
Sprintf(eos(info), ", mimicing %s",
(mtmp->m_ap_type == M_AP_FURNITURE) ?
}
if (mtmp) {
madeany = TRUE;
- if (mtmp->cham != CHAM_ORDINARY && firstchoice != NON_PM)
+ if (mtmp->cham >= LOW_PM && firstchoice != NON_PM)
(void)newcham(mtmp, &mons[firstchoice], FALSE, FALSE);
}
}
mon = makemon(&mons[PM_DOPPELGANGER], x, y,
NO_MINVENT | MM_NOCOUNTBIRTH | MM_ADJACENTOK);
/* if hero has protection from shape changers, cham field will
- be CHAM_ORDINARY; otherwise, set form to match the statue */
- if (mon && mon->cham != CHAM_ORDINARY)
+ be NON_PM; otherwise, set form to match the statue */
+ if (mon && mon->cham >= LOW_PM)
(void) newcham(mon, mptr, FALSE, FALSE);
} else
mon = makemon(mptr, x, y, (cause == ANIMATE_SPELL) ?
/* natural shapechangers aren't affected by system shock
(unless protection from shapechangers is interfering
with their metabolism...) */
- if (mtmp->cham == CHAM_ORDINARY && !rn2(25)) {
+ if (mtmp->cham == NON_PM && !rn2(25)) {
if (canseemon(mtmp)) {
pline("%s shudders!", Monnam(mtmp));
learn_it = TRUE;