monster sanity checking
Add some more checks for monsters when the sanity_check option is enabled.
This commit is contained in:
71
src/mon.c
71
src/mon.c
@@ -13,7 +13,8 @@
|
|||||||
|
|
||||||
STATIC_VAR boolean vamp_rise_msg;
|
STATIC_VAR boolean vamp_rise_msg;
|
||||||
|
|
||||||
STATIC_DCL void FDECL(sanity_check_single_mon, (struct monst *, const char *));
|
STATIC_DCL void FDECL(sanity_check_single_mon, (struct monst *, BOOLEAN_P,
|
||||||
|
const char *));
|
||||||
STATIC_DCL boolean FDECL(restrap, (struct monst *));
|
STATIC_DCL boolean FDECL(restrap, (struct monst *));
|
||||||
STATIC_DCL long FDECL(mm_aggression, (struct monst *, struct monst *));
|
STATIC_DCL long FDECL(mm_aggression, (struct monst *, struct monst *));
|
||||||
STATIC_DCL long FDECL(mm_displacement, (struct monst *, struct monst *));
|
STATIC_DCL long FDECL(mm_displacement, (struct monst *, struct monst *));
|
||||||
@@ -41,35 +42,75 @@ const char *warnings[] = {
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
sanity_check_single_mon(mtmp, msg)
|
sanity_check_single_mon(mtmp, chk_geno, msg)
|
||||||
struct monst *mtmp;
|
struct monst *mtmp;
|
||||||
|
boolean chk_geno;
|
||||||
const char *msg;
|
const char *msg;
|
||||||
{
|
{
|
||||||
if (DEADMONSTER(mtmp))
|
if (DEADMONSTER(mtmp))
|
||||||
return;
|
return;
|
||||||
if (mtmp->data < &mons[LOW_PM] || mtmp->data >= &mons[NUMMONS])
|
if (mtmp->data < &mons[LOW_PM] || mtmp->data >= &mons[NUMMONS]) {
|
||||||
impossible("illegal mon data (%s)", msg);
|
impossible("illegal mon data %s; mnum=%d (%s)",
|
||||||
|
fmt_ptr((genericptr_t) mtmp->data), mtmp->mnum, msg);
|
||||||
|
} else {
|
||||||
|
int mndx = monsndx(mtmp->data);
|
||||||
|
|
||||||
|
if (mtmp->mnum != mndx) {
|
||||||
|
impossible("monster mnum=%d, monsndx=%d (%s)",
|
||||||
|
mtmp->mnum, mndx, msg);
|
||||||
|
mtmp->mnum = mndx;
|
||||||
|
}
|
||||||
|
if (chk_geno && (mvitals[mndx].mvflags & G_GENOD) != 0)
|
||||||
|
impossible("genocided %s in play (%s)", mons[mndx].mname, msg);
|
||||||
|
}
|
||||||
|
if (mtmp->isshk && !has_eshk(mtmp))
|
||||||
|
impossible("shk without eshk (%s)", msg);
|
||||||
|
if (mtmp->ispriest && !has_epri(mtmp))
|
||||||
|
impossible("priest without epri (%s)", msg);
|
||||||
|
if (mtmp->isgd && !has_egd(mtmp))
|
||||||
|
impossible("guard without egd (%s)", msg);
|
||||||
|
if (mtmp->isminion && !has_emin(mtmp))
|
||||||
|
impossible("minion without emin (%s)", msg);
|
||||||
|
/* guardian angel on astral level is tame but has emin rather than edog */
|
||||||
|
if (mtmp->mtame && !has_edog(mtmp) && !mtmp->isminion)
|
||||||
|
impossible("pet without edog (%s)", msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
mon_sanity_check()
|
mon_sanity_check()
|
||||||
{
|
{
|
||||||
int x,y;
|
int x, y;
|
||||||
struct monst *mtmp = fmon;
|
struct monst *mtmp, *m;
|
||||||
|
|
||||||
while (mtmp) {
|
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
|
||||||
sanity_check_single_mon(mtmp, "fmon");
|
sanity_check_single_mon(mtmp, TRUE, "fmon");
|
||||||
mtmp = mtmp->nmon;
|
x = mtmp->mx, y = mtmp->my;
|
||||||
|
if (!isok(x, y) || (x == 0 && !mtmp->isgd))
|
||||||
|
impossible("mon (%s) claims to be at <%d,%d>?",
|
||||||
|
fmt_ptr((genericptr_t) mtmp), x, y);
|
||||||
|
else if (level.monsters[x][y] != mtmp)
|
||||||
|
impossible("mon (%s) at <%d,%d> is not there!",
|
||||||
|
fmt_ptr((genericptr_t) mtmp), x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (x = 0; x < COLNO; x++)
|
for (x = 0; x < COLNO; x++)
|
||||||
for (y = 0; y < ROWNO; y++)
|
for (y = 0; y < ROWNO; y++)
|
||||||
if ((mtmp = m_at(x,y)) != 0)
|
if ((mtmp = level.monsters[x][y]) != 0) {
|
||||||
sanity_check_single_mon(mtmp, "m_at");
|
for (m = fmon; m; m = m->nmon)
|
||||||
|
if (m == mtmp)
|
||||||
|
break;
|
||||||
|
if (!m)
|
||||||
|
impossible("map mon (%s) at <%d,%d> not in fmon list!",
|
||||||
|
fmt_ptr((genericptr_t) mtmp), x, y);
|
||||||
|
else if ((mtmp->mx != x || mtmp->my != y)
|
||||||
|
&& mtmp->data != &mons[PM_LONG_WORM])
|
||||||
|
impossible("map mon (%s) at <%d,%d> is found at <%d,%d>?",
|
||||||
|
fmt_ptr((genericptr_t) mtmp),
|
||||||
|
mtmp->mx, mtmp->my, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
mtmp = migrating_mons;
|
for (mtmp = migrating_mons; mtmp; mtmp = mtmp->nmon) {
|
||||||
while (mtmp) {
|
sanity_check_single_mon(mtmp, FALSE, "migr");
|
||||||
sanity_check_single_mon(mtmp, "migr");
|
|
||||||
mtmp = mtmp->nmon;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,9 @@
|
|||||||
/* NetHack may be freely redistributed. See license for details. */
|
/* NetHack may be freely redistributed. See license for details. */
|
||||||
|
|
||||||
#include "hack.h"
|
#include "hack.h"
|
||||||
|
/*
|
||||||
/* These routines provide basic data for any type of monster. */
|
* These routines provide basic data for any type of monster.
|
||||||
|
*/
|
||||||
|
|
||||||
/* set up an individual monster's base type (initial creation, shapechange) */
|
/* set up an individual monster's base type (initial creation, shapechange) */
|
||||||
void
|
void
|
||||||
@@ -16,6 +17,7 @@ int flag;
|
|||||||
int new_speed, old_speed = mon->data ? mon->data->mmove : 0;
|
int new_speed, old_speed = mon->data ? mon->data->mmove : 0;
|
||||||
|
|
||||||
mon->data = ptr;
|
mon->data = ptr;
|
||||||
|
mon->mnum = (short) monsndx(ptr);
|
||||||
if (flag == -1)
|
if (flag == -1)
|
||||||
return; /* "don't care" */
|
return; /* "don't care" */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user