extended ball&chain sanity check
Verify that the locations of ball and chain are consistent. If chain is on floor then ball is on floor or in hero's inventory else if chain is free then ball is free or in hero's inventory. When chain is on floor it is under hero or one step away from hero and when ball is on floor it is on chain or one step away from chain.
This commit is contained in:
33
src/ball.c
33
src/ball.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 ball.c $NHDT-Date: 1558920171 2019/05/27 01:22:51 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.38 $ */
|
||||
/* NetHack 3.6 ball.c $NHDT-Date: 1559554598 2019/06/03 09:36:38 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.39 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/*-Copyright (c) David Cohrs, 2006. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -853,7 +853,7 @@ drag_down()
|
||||
void
|
||||
bc_sanity_check()
|
||||
{
|
||||
int otyp;
|
||||
int otyp, freeball, freechain;
|
||||
const char *onam;
|
||||
|
||||
if (Punished && (!uball || !uchain)) {
|
||||
@@ -867,11 +867,18 @@ bc_sanity_check()
|
||||
(uchain && uball) ? " and " : "",
|
||||
uball ? "iron ball" : "");
|
||||
}
|
||||
/* ball is free when swallowed, changing levels, other times? */
|
||||
/* ball is free when swallowed, when changing levels or during air bubble
|
||||
management on Plane of Water (both of which start and end in between
|
||||
sanity checking cycles, so shouldn't be relevant), other times? */
|
||||
freechain = (!uchain || uchain->where == OBJ_FREE);
|
||||
freeball = (!uball || uball->where == OBJ_FREE
|
||||
/* lie to simplify the testing logic */
|
||||
|| (freechain && uball->where == OBJ_INVENT));
|
||||
if (uball && (uball->otyp != HEAVY_IRON_BALL
|
||||
|| (uball->where != OBJ_FLOOR
|
||||
&& uball->where != OBJ_INVENT
|
||||
&& uball->where != OBJ_FREE)
|
||||
|| (freeball ^ freechain)
|
||||
|| (uball->owornmask & W_BALL) == 0L
|
||||
|| (uball->owornmask & ~(W_BALL | W_WEAPON)) != 0L)) {
|
||||
otyp = uball->otyp;
|
||||
@@ -883,6 +890,7 @@ bc_sanity_check()
|
||||
if (uchain && (uchain->otyp != IRON_CHAIN
|
||||
|| (uchain->where != OBJ_FLOOR
|
||||
&& uchain->where != OBJ_FREE)
|
||||
|| (freechain ^ freeball)
|
||||
/* [could simplify this to owornmask != W_CHAIN] */
|
||||
|| (uchain->owornmask & W_CHAIN) == 0L
|
||||
|| (uchain->owornmask & ~W_CHAIN) != 0L)) {
|
||||
@@ -891,6 +899,25 @@ bc_sanity_check()
|
||||
impossible("uchain: type %d (%s), where %d, wornmask=0x%08lx",
|
||||
otyp, onam, uchain->where, uchain->owornmask);
|
||||
}
|
||||
if (uball && uchain && !(freeball && freechain)) {
|
||||
int bx, by, cx, cy, bdx, bdy, cdx, cdy;
|
||||
|
||||
/* non-free chain should be under or next to the hero;
|
||||
non-free ball should be on or next to the chain or else carried */
|
||||
cx = uchain->ox, cy = uchain->oy;
|
||||
cdx = cx - u.ux, cdy = cy - u.uy;
|
||||
cdx = abs(cdx), cdy = abs(cdy);
|
||||
if (uball->where == OBJ_INVENT) /* carried(uball) */
|
||||
bx = u.ux, by = u.uy; /* get_obj_location() */
|
||||
else
|
||||
bx = uball->ox, by = uball->oy;
|
||||
bdx = bx - cx, bdy = by - cy;
|
||||
bdx = abs(bdx), bdy = abs(bdy);
|
||||
if (cdx > 1 || cdy > 1 || bdx > 1 || bdy > 1)
|
||||
impossible(
|
||||
"b&c distance: you@<%d,%d>, chain@<%d,%d>, ball@<%d,%d>",
|
||||
u.ux, u.uy, cx, cy, bx, by);
|
||||
}
|
||||
/* [check bc_order too?] */
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user