cham changes (trunk only)

This is a foundation patch for patches to follow.
- use a full short index for mon->cham field.
- The current system of providing CHAM_XXX values
  was limited to the 3 bits allocated in the bitfield and invalidated
  save/bones if the field was expanded.
- The current system didn't provide an easy backwards  change
  if multiple monster types wanted to use the bit, there was a one
  to one mapping:  For instance, if you wanted a CHAM_VAMPIRE,
  and you wanted vampires, vampire lords, and Vlad to use it, you
  would have to have CHAM_VAMPIRE, CHAM_VAMPIRE_LORD,
  and CHAM_VLAD defined to achieve that with the one-to-one backward
  mapping.
- This new way just uses the mon[] index in the mon->cham field and
  eliminates the need for CHAM_XXX  (CHAM_ORDINARY is still used).
- no longer requires the cham_to_pm mappings
This commit is contained in:
nethack.allison
2004-06-15 11:38:32 +00:00
parent 87507aed42
commit c8ef9338f0
22 changed files with 98 additions and 83 deletions

View File

@@ -251,7 +251,7 @@ moveloop()
stop_occupation();
else
nomul(0);
if (change == 1) polyself(FALSE);
if (change == 1) polyself(0);
else you_were();
change = 0;
}

View File

@@ -1,4 +1,4 @@
/* SCCS Id: @(#)apply.c 3.4 2003/11/18 */
/* SCCS Id: @(#)apply.c 3.4 2004/06/12 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */

View File

@@ -636,7 +636,7 @@ wiz_panic()
STATIC_PTR int
wiz_polyself()
{
polyself(TRUE);
polyself(1);
return 0;
}

View File

@@ -920,7 +920,7 @@ finish_meating(mtmp)
struct monst *mtmp;
{
mtmp->meating = 0;
if (mtmp->m_ap_type && mtmp->mappearance && !mtmp->cham) {
if (mtmp->m_ap_type && mtmp->mappearance && mtmp->cham == CHAM_ORDINARY) {
/* was eating a mimic and now appearance needs resetting */
mtmp->m_ap_type = 0;
mtmp->mappearance = 0;

View File

@@ -875,7 +875,7 @@ register int pm;
/* case PM_SANDESTIN: */
if (!Unchanging) {
You_feel("a change coming over you.");
polyself(FALSE);
polyself(0);
}
break;
case PM_MIND_FLAYER:

View File

@@ -581,7 +581,7 @@ drinksink()
case 10: pline("This water contains toxic wastes!");
if (!Unchanging) {
You("undergo a freakish metamorphosis!");
polyself(FALSE);
polyself(0);
}
break;
/* more odd messages --JJB */

View File

@@ -1,4 +1,4 @@
/* SCCS Id: @(#)mhitu.c 3.4 2003/11/26 */
/* SCCS Id: @(#)mhitu.c 3.4 2004/06/12 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -467,14 +467,14 @@ mattacku(mtmp)
}
/* Special demon handling code */
if(!mtmp->cham && is_demon(mdat) && !range2
if((mtmp->cham == CHAM_ORDINARY) && is_demon(mdat) && !range2
&& mtmp->data != &mons[PM_BALROG]
&& mtmp->data != &mons[PM_SUCCUBUS]
&& mtmp->data != &mons[PM_INCUBUS])
if(!mtmp->mcan && !rn2(13)) msummon(mtmp);
/* Special lycanthrope handling code */
if(!mtmp->cham && is_were(mdat) && !range2) {
if((mtmp->cham == CHAM_ORDINARY) && is_were(mdat) && !range2) {
if(is_human(mdat)) {
if(!rn2(5 - (night() * 2)) && !mtmp->mcan) new_were(mtmp);

View File

@@ -136,7 +136,7 @@ boolean talk;
}
}
#define Athome (Inhell && !mtmp->cham)
#define Athome (Inhell && (mtmp->cham == CHAM_ORDINARY))
int
demon_talk(mtmp) /* returns 1 if it won't attack. */

View File

@@ -1,4 +1,4 @@
/* SCCS Id: @(#)mon.c 3.4 2004/05/21 */
/* SCCS Id: @(#)mon.c 3.4 2004/06/12 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -120,30 +120,21 @@ int mndx, mode;
return mndx;
}
/* convert monster index to chameleon index */
/* return monster index if chameleon, or CHAM_ORDINARY if not */
int
pm_to_cham(mndx)
int mndx;
{
int mcham;
int mcham = CHAM_ORDINARY;
switch (mndx) {
case PM_CHAMELEON: mcham = CHAM_CHAMELEON; break;
case PM_DOPPELGANGER: mcham = CHAM_DOPPELGANGER; break;
case PM_SANDESTIN: mcham = CHAM_SANDESTIN; break;
default: mcham = CHAM_ORDINARY; break;
}
/*
* 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;
return mcham;
}
/* convert chameleon index to monster index */
STATIC_VAR short cham_to_pm[] = {
NON_PM, /* placeholder for CHAM_ORDINARY */
PM_CHAMELEON,
PM_DOPPELGANGER,
PM_SANDESTIN,
};
/* for deciding whether corpse will carry along full monster data */
#define KEEPTRAITS(mon) ((mon)->isshk || (mon)->mtame || \
unique_corpstat(mon->data) || \
@@ -1458,8 +1449,10 @@ register struct monst *mtmp;
mptr = mtmp->data; /* save this for m_detach() */
/* restore chameleon, lycanthropes to true form at death */
if (mtmp->cham)
set_mon_data(mtmp, &mons[cham_to_pm[mtmp->cham]], -1);
if (mtmp->cham != CHAM_ORDINARY) {
set_mon_data(mtmp, &mons[mtmp->cham], -1);
mtmp->cham = CHAM_ORDINARY;
}
else if (mtmp->data == &mons[PM_WEREJACKAL])
set_mon_data(mtmp, &mons[PM_HUMAN_WEREJACKAL], -1);
else if (mtmp->data == &mons[PM_WEREWOLF])
@@ -2174,10 +2167,10 @@ rescham()
for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp)) continue;
mcham = (int) mtmp->cham;
if (mcham) {
mtmp->cham = CHAM_ORDINARY;
(void) newcham(mtmp, &mons[cham_to_pm[mcham]],
if (mcham != CHAM_ORDINARY) {
(void) newcham(mtmp, &mons[mcham],
FALSE, FALSE);
mtmp->cham = CHAM_ORDINARY;
}
if(is_were(mtmp->data) && mtmp->data->mlet != S_HUMAN)
new_were(mtmp);
@@ -2218,9 +2211,9 @@ struct monst *mon;
if (Protection_from_shape_changers) {
mcham = (int) mon->cham;
if (mcham) {
if (mcham != CHAM_ORDINARY) {
mon->cham = CHAM_ORDINARY;
(void) newcham(mon, &mons[cham_to_pm[mcham]], FALSE, FALSE);
(void) newcham(mon, &mons[mcham], FALSE, FALSE);
} else if (is_were(mon->data) && !is_human(mon->data)) {
new_were(mon);
}
@@ -2234,7 +2227,7 @@ STATIC_OVL boolean
restrap(mtmp)
register struct monst *mtmp;
{
if(mtmp->cham || mtmp->mcan || mtmp->m_ap_type ||
if((mtmp->cham != CHAM_ORDINARY) || 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);
@@ -2313,24 +2306,39 @@ pick_animal()
return animal_list[rn2(animal_list_count)];
}
STATIC_OVL int
int
select_newcham_form(mon)
struct monst *mon;
{
int mndx = NON_PM;
switch (mon->cham) {
case CHAM_SANDESTIN:
case PM_SANDESTIN:
if (rn2(7)) mndx = pick_nasty();
break;
case CHAM_DOPPELGANGER:
case PM_DOPPELGANGER:
if (!rn2(7)) mndx = pick_nasty();
else if (rn2(3)) mndx = rn1(PM_WIZARD - PM_ARCHEOLOGIST + 1,
PM_ARCHEOLOGIST);
break;
case CHAM_CHAMELEON:
case PM_CHAMELEON:
if (!rn2(3)) mndx = pick_animal();
break;
case PM_VLAD_THE_IMPALER:
case PM_VAMPIRE_LORD:
case PM_VAMPIRE:
if (mon_has_special(mon) && /* ensure Vlad can carry it still */
mon->cham == PM_VLAD_THE_IMPALER) {
mndx = PM_VLAD_THE_IMPALER;
break;
}
if (!rn2(10) && mon->cham != PM_VAMPIRE) {
/* VAMPIRE_LORD || VLAD */
mndx = PM_WOLF;
break;
}
mndx = !rn2(4) ? PM_FOG_CLOUD : PM_VAMPIRE_BAT;
break;
case CHAM_ORDINARY:
{
struct obj *m_armr = which_armor(mon, W_ARM);
@@ -2649,12 +2657,12 @@ void
kill_genocided_monsters()
{
struct monst *mtmp, *mtmp2;
boolean kill_cham[CHAM_MAX_INDX+1];
boolean kill_cham[NUMMONS];
int mndx;
kill_cham[CHAM_ORDINARY] = FALSE; /* (this is mndx==0) */
for (mndx = 1; mndx <= CHAM_MAX_INDX; mndx++)
kill_cham[mndx] = (mvitals[cham_to_pm[mndx]].mvflags & G_GENOD) != 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
@@ -2671,7 +2679,7 @@ kill_genocided_monsters()
if (DEADMONSTER(mtmp)) continue;
mndx = monsndx(mtmp->data);
if ((mvitals[mndx].mvflags & G_GENOD) || kill_cham[mtmp->cham]) {
if (mtmp->cham && !kill_cham[mtmp->cham])
if ((mtmp->cham != CHAM_ORDINARY) && !kill_cham[mtmp->cham])
(void) newcham(mtmp, (struct permonst *)0, FALSE, FALSE);
else
mondead(mtmp);

View File

@@ -94,6 +94,7 @@ NEARDATA struct permonst mons[] = {
/*
* 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),
@@ -2357,7 +2358,7 @@ struct permonst _mons2[] = {
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(WT_HUMAN, 400, 0, MS_IMITATE, MZ_HUMAN), MR_SLEEP, 0,
M1_HUMANOID|M1_OMNIVORE,
M2_NOPOLY|M2_HUMAN|M2_HOSTILE|M2_STRONG|M2_COLLECT,
M2_NOPOLY|M2_HUMAN|M2_HOSTILE|M2_STRONG|M2_COLLECT|M2_SHAPESHIFTER,
M3_INFRAVISIBLE, HI_DOMESTIC),
MON("nurse", S_HUMAN,
LVL(11, 6, 0, 0, 0), (G_GENO|3),
@@ -2791,7 +2792,7 @@ struct permonst _mons2[] = {
A(ATTK(AT_WEAP, AD_PHYS, 2, 6), ATTK(AT_WEAP, AD_PHYS, 2, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(1500, 400, 0, MS_CUSS, MZ_HUMAN), MR_STONE, 0,
M1_HUMANOID, M2_NOPOLY|M2_STALK|M2_STRONG|M2_COLLECT,
M1_HUMANOID, M2_NOPOLY|M2_STALK|M2_STRONG|M2_COLLECT|M2_SHAPESHIFTER,
M3_INFRAVISIBLE|M3_INFRAVISION, CLR_GRAY),
/*
* sea monsters
@@ -2883,7 +2884,8 @@ struct permonst _mons2[] = {
A(ATTK(AT_BITE, AD_PHYS, 4, 2),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(100, 100, 0, MS_SILENT, MZ_TINY), 0, 0,
M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_NOPOLY|M2_HOSTILE, 0, CLR_BROWN),
M1_ANIMAL|M1_NOHANDS|M1_CARNIVORE, M2_NOPOLY|M2_HOSTILE|M2_SHAPESHIFTER,
0, CLR_BROWN),
MON("crocodile", S_LIZARD,
LVL(6, 9, 5, 0, 0), (G_GENO|1),
A(ATTK(AT_BITE, AD_PHYS, 4, 2), ATTK(AT_CLAW, AD_PHYS, 1,12),

View File

@@ -1,4 +1,4 @@
/* SCCS Id: @(#)muse.c 3.4 2002/12/23 */
/* SCCS Id: @(#)muse.c 3.4 2004/06/12 */
/* Copyright (C) 1990 by Ken Arromdee */
/* NetHack may be freely redistributed. See license for details. */
@@ -1588,7 +1588,8 @@ struct monst *mtmp;
if(dist2(x, y, mtmp->mux, mtmp->muy) > 36)
return FALSE;
if (!stuck && !immobile && !mtmp->cham && monstr[monsndx(mdat)] < 6) {
if (!stuck && !immobile &&
(mtmp->cham == CHAM_ORDINARY) && monstr[monsndx(mdat)] < 6) {
boolean ignore_boulders = (verysmall(mdat) ||
throws_rocks(mdat) ||
passes_walls(mdat));
@@ -1658,13 +1659,15 @@ struct monst *mtmp;
m.has_misc = MUSE_POT_SPEED;
}
nomore(MUSE_WAN_POLYMORPH);
if(obj->otyp == WAN_POLYMORPH && obj->spe > 0 && !mtmp->cham
if(obj->otyp == WAN_POLYMORPH && obj->spe > 0
&& (mtmp->cham == CHAM_ORDINARY)
&& monstr[monsndx(mdat)] < 6) {
m.misc = obj;
m.has_misc = MUSE_WAN_POLYMORPH;
}
nomore(MUSE_POT_POLYMORPH);
if(obj->otyp == POT_POLYMORPH && !mtmp->cham
if(obj->otyp == POT_POLYMORPH
&& (mtmp->cham == CHAM_ORDINARY)
&& monstr[monsndx(mdat)] < 6) {
m.misc = obj;
m.has_misc = MUSE_POT_POLYMORPH;

View File

@@ -309,7 +309,7 @@ register struct monst *mtmp;
}
else if (mtmp->mpeaceful) Strcat(info, ", peaceful");
if (mtmp->meating) Strcat(info, ", eating");
if (mtmp->meating && !mtmp->cham &&
if (mtmp->meating && (mtmp->cham == CHAM_ORDINARY) &&
mtmp->mappearance && mtmp->m_ap_type) {
Sprintf(eos(info), ", mimicing %s",
(mtmp->m_ap_type == M_AP_FURNITURE) ?

View File

@@ -225,13 +225,14 @@ dead: /* we come directly here if their experience level went to 0 or less */
}
void
polyself(forcecontrol)
boolean forcecontrol;
polyself(psflags)
int psflags;
{
char buf[BUFSZ];
int old_light, new_light;
int mntmp = NON_PM;
int tries=0;
boolean forcecontrol = (psflags == 1);
boolean draconian = (uarm &&
uarm->otyp >= GRAY_DRAGON_SCALE_MAIL &&
uarm->otyp <= YELLOW_DRAGON_SCALES);

View File

@@ -1,4 +1,4 @@
/* SCCS Id: @(#)potion.c 3.4 2003/11/26 */
/* SCCS Id: @(#)potion.c 3.4 2004/06/12 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -918,7 +918,7 @@ peffects(otmp)
break;
case POT_POLYMORPH:
You_feel("a little %s.", Hallucination ? "normal" : "strange");
if (!Unchanging) polyself(FALSE);
if (!Unchanging) polyself(0);
break;
default:
impossible("What a funny potion! (%u)", otmp->otyp);
@@ -1055,7 +1055,7 @@ boolean your_fault;
break;
case POT_POLYMORPH:
You_feel("a little %s.", Hallucination ? "normal" : "strange");
if (!Unchanging && !Antimagic) polyself(FALSE);
if (!Unchanging && !Antimagic) polyself(0);
break;
case POT_ACID:
if (!Acid_resistance) {

View File

@@ -1,4 +1,4 @@
/* SCCS Id: @(#)trap.c 3.4 2003/12/26 */
/* SCCS Id: @(#)trap.c 3.4 2004/06/12 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1100,7 +1100,7 @@ glovecheck: (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst);
deltrap(trap); /* delete trap before polymorph */
newsym(u.ux,u.uy); /* get rid of trap symbol */
You_feel("a change coming over you.");
polyself(FALSE);
polyself(0);
}
break;
}

View File

@@ -1,4 +1,4 @@
/* SCCS Id: @(#)zap.c 3.4 2003/11/26 */
/* SCCS Id: @(#)zap.c 3.4 2004/06/12 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -634,7 +634,7 @@ register struct obj *obj;
mtmp = makemon(&mons[montype], x, y,
NO_MINVENT | MM_NOWAIT);
if (mtmp) {
if (mtmp->cham == CHAM_DOPPELGANGER) {
if (mtmp->cham == PM_DOPPELGANGER) {
/* change shape to match the corpse */
(void) newcham(mtmp, mptr, FALSE, FALSE);
} else if (mtmp->data->mlet == S_ZOMBIE) {
@@ -1983,7 +1983,7 @@ boolean ordinary;
makeknown(WAN_POLYMORPH);
case SPE_POLYMORPH:
if (!Unchanging)
polyself(FALSE);
polyself(0);
break;
case WAN_CANCELLATION: