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

@@ -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);