fix github issue #606 - shop wall repair
triggering an impossible warning about "wall_angle: unknown" due to the known conflict between door state and wall info which both overlay the flags field for map locations. Reported and diagnosed by vultur-cadens: if a shop's wall was dug open, followed by use of locking magic to plug the gap with a door, and then unlocking that door, the D_CLOSED door flag was left as invalid wall_info when shop damage was repaired. Map re-display complained. Leaving the door locked or opening it after unlocking did not result in any complaint because the values for those door states do not conflict with wall angle values. The problem was reproducible and is now fixed by adding an extra field to the shop damage structure. A similar change has been made to the vault guard's 'fake corridor' structure but I have no test case for that so don't know whether it makes any difference. At least it doesn't seem to have broken anything. Existing save and bones files are invalidated by the fixes. Fixes #606
This commit is contained in:
@@ -2971,16 +2971,44 @@ t_warn(struct rm *lev)
|
||||
static const char warn_str[] = "wall_angle: %s: case %d: seenv = 0x%x";
|
||||
const char *wname;
|
||||
|
||||
if (lev->typ == TUWALL)
|
||||
/* 3.7: non-T_wall cases added after shop repair (via breaching a wall,
|
||||
using locking magic to put a door there, then unlocking the door;
|
||||
D_CLOSED carried over to the wall) triggered warning for "unknown" */
|
||||
switch (lev->typ) {
|
||||
case TUWALL:
|
||||
wname = "tuwall";
|
||||
else if (lev->typ == TLWALL)
|
||||
break;
|
||||
case TLWALL:
|
||||
wname = "tlwall";
|
||||
else if (lev->typ == TRWALL)
|
||||
break;
|
||||
case TRWALL:
|
||||
wname = "trwall";
|
||||
else if (lev->typ == TDWALL)
|
||||
break;
|
||||
case TDWALL:
|
||||
wname = "tdwall";
|
||||
else
|
||||
break;
|
||||
case VWALL:
|
||||
wname = "vwall";
|
||||
break;
|
||||
case HWALL:
|
||||
wname = "hwall";
|
||||
break;
|
||||
case TLCORNER:
|
||||
wname = "tlcorner";
|
||||
break;
|
||||
case TRCORNER:
|
||||
wname = "trcorner";
|
||||
break;
|
||||
case BLCORNER:
|
||||
wname = "blcorner";
|
||||
break;
|
||||
case BRCORNER:
|
||||
wname = "brcorner";
|
||||
break;
|
||||
default:
|
||||
wname = "unknown";
|
||||
break;
|
||||
}
|
||||
impossible(warn_str, wname, lev->wall_info & WM_MASK,
|
||||
(unsigned int) lev->seenv);
|
||||
}
|
||||
|
||||
16
src/shk.c
16
src/shk.c
@@ -2720,9 +2720,10 @@ append_honorific(char *buf)
|
||||
{
|
||||
/* (chooses among [0]..[3] normally; [1]..[4] after the
|
||||
Wizard has been killed or invocation ritual performed) */
|
||||
static const char *const honored[] = { "good", "honored", "most gracious",
|
||||
"esteemed",
|
||||
"most renowned and sacred" };
|
||||
static const char *const honored[] = {
|
||||
"good", "honored", "most gracious", "esteemed",
|
||||
"most renowned and sacred"
|
||||
};
|
||||
|
||||
Strcat(buf, honored[rn2(SIZE(honored) - 1) + u.uevent.udemigod]);
|
||||
if (is_vampire(g.youmonst.data))
|
||||
@@ -3481,6 +3482,7 @@ add_damage(
|
||||
tmp_dam->place.y = y;
|
||||
tmp_dam->cost = cost;
|
||||
tmp_dam->typ = levl[x][y].typ;
|
||||
tmp_dam->flags = levl[x][y].flags;
|
||||
tmp_dam->next = g.level.damagelist;
|
||||
g.level.damagelist = tmp_dam;
|
||||
/* If player saw damage, display as a wall forever */
|
||||
@@ -3570,7 +3572,7 @@ discard_damage_struct(struct damage *dam)
|
||||
if (prev)
|
||||
prev->next = dam->next;
|
||||
}
|
||||
(void) memset(dam, 0, sizeof(struct damage));
|
||||
(void) memset(dam, 0, sizeof *dam);
|
||||
free((genericptr_t) dam);
|
||||
}
|
||||
|
||||
@@ -3802,10 +3804,14 @@ repair_damage(
|
||||
stop_picking = picking_at(x, y);
|
||||
|
||||
/* door or wall repair; trap, if any, is now gone;
|
||||
restore original terrain type and move any items away */
|
||||
restore original terrain type and move any items away;
|
||||
rm.doormask and rm.wall_info are both overlaid on rm.flags
|
||||
so the new flags value needs to match the restored typ */
|
||||
levl[x][y].typ = tmp_dam->typ;
|
||||
if (IS_DOOR(tmp_dam->typ))
|
||||
levl[x][y].doormask = D_CLOSED; /* arbitrary */
|
||||
else /* not a door; set rm.wall_info or whatever old flags are relevant */
|
||||
levl[x][y].flags = tmp_dam->flags;
|
||||
|
||||
litter = litter_getpos(&k, x, y, shkp);
|
||||
litter_scatter(litter, k, x, y, shkp);
|
||||
|
||||
59
src/vault.c
59
src/vault.c
@@ -83,6 +83,7 @@ clear_fcorr(struct monst *grd, boolean forceshow)
|
||||
if (lev->typ == CORR && cansee(fcx, fcy))
|
||||
sawcorridor = TRUE;
|
||||
lev->typ = egrd->fakecorr[fcbeg].ftyp;
|
||||
lev->flags = egrd->fakecorr[fcbeg].flags;
|
||||
if (IS_STWALL(lev->typ)) {
|
||||
/* destroy any trap here (pit dug by you, hole dug via
|
||||
wand while levitating or by monster, bear trap or land
|
||||
@@ -506,25 +507,29 @@ invault(void)
|
||||
EGD(guard)->fcbeg = 0;
|
||||
EGD(guard)->fakecorr[0].fx = x;
|
||||
EGD(guard)->fakecorr[0].fy = y;
|
||||
if (IS_WALL(levl[x][y].typ)) {
|
||||
EGD(guard)->fakecorr[0].ftyp = levl[x][y].typ;
|
||||
} else { /* the initial guard location is a dug door */
|
||||
EGD(guard)->fakecorr[0].ftyp = levl[x][y].typ;
|
||||
EGD(guard)->fakecorr[0].flags = levl[x][y].flags;
|
||||
if (!IS_WALL(levl[x][y].typ)) {
|
||||
/* the initial guard location happens to be a dug door */
|
||||
int vlt = EGD(guard)->vroom;
|
||||
xchar lowx = g.rooms[vlt].lx, hix = g.rooms[vlt].hx;
|
||||
xchar lowy = g.rooms[vlt].ly, hiy = g.rooms[vlt].hy;
|
||||
int typ = levl[x][y].typ;
|
||||
|
||||
if (x == lowx - 1 && y == lowy - 1)
|
||||
EGD(guard)->fakecorr[0].ftyp = TLCORNER;
|
||||
typ = TLCORNER;
|
||||
else if (x == hix + 1 && y == lowy - 1)
|
||||
EGD(guard)->fakecorr[0].ftyp = TRCORNER;
|
||||
typ = TRCORNER;
|
||||
else if (x == lowx - 1 && y == hiy + 1)
|
||||
EGD(guard)->fakecorr[0].ftyp = BLCORNER;
|
||||
typ = BLCORNER;
|
||||
else if (x == hix + 1 && y == hiy + 1)
|
||||
EGD(guard)->fakecorr[0].ftyp = BRCORNER;
|
||||
typ = BRCORNER;
|
||||
else if (y == lowy - 1 || y == hiy + 1)
|
||||
EGD(guard)->fakecorr[0].ftyp = HWALL;
|
||||
typ = HWALL;
|
||||
else if (x == lowx - 1 || x == hix + 1)
|
||||
EGD(guard)->fakecorr[0].ftyp = VWALL;
|
||||
typ = VWALL;
|
||||
|
||||
EGD(guard)->fakecorr[0].ftyp = typ;
|
||||
}
|
||||
levl[x][y].typ = DOOR;
|
||||
levl[x][y].doormask = D_NODOOR;
|
||||
@@ -581,14 +586,19 @@ wallify_vault(struct monst *grd)
|
||||
if ((trap = t_at(x, y)) != 0)
|
||||
deltrap(trap);
|
||||
if (x == lox)
|
||||
typ =
|
||||
(y == loy) ? TLCORNER : (y == hiy) ? BLCORNER : VWALL;
|
||||
typ = (y == loy) ? TLCORNER
|
||||
: (y == hiy) ? BLCORNER
|
||||
: VWALL;
|
||||
else if (x == hix)
|
||||
typ =
|
||||
(y == loy) ? TRCORNER : (y == hiy) ? BRCORNER : VWALL;
|
||||
typ = (y == loy) ? TRCORNER
|
||||
: (y == hiy) ? BRCORNER
|
||||
: VWALL;
|
||||
else /* not left or right side, must be top or bottom */
|
||||
typ = HWALL;
|
||||
levl[x][y].typ = typ;
|
||||
/* FIXME? both rm.doormask and rm.wall_info overlay
|
||||
rm.flags, so clearing doormask clobbers wall_info
|
||||
rather than reset it to the proper value. Do we care? */
|
||||
levl[x][y].doormask = 0;
|
||||
/*
|
||||
* hack: player knows walls are restored because of the
|
||||
@@ -789,6 +799,7 @@ gd_move(struct monst *grd)
|
||||
verbalize("You've been warned, knave!");
|
||||
mnexto(grd);
|
||||
levl[m][n].typ = egrd->fakecorr[0].ftyp;
|
||||
levl[m][n].flags = egrd->fakecorr[0].flags;
|
||||
newsym(m, n);
|
||||
grd->mpeaceful = 0;
|
||||
return -1;
|
||||
@@ -805,6 +816,7 @@ gd_move(struct monst *grd)
|
||||
n = grd->my;
|
||||
(void) rloc(grd, TRUE);
|
||||
levl[m][n].typ = egrd->fakecorr[0].ftyp;
|
||||
levl[m][n].flags = egrd->fakecorr[0].flags;
|
||||
newsym(m, n);
|
||||
grd->mpeaceful = 0;
|
||||
letknow:
|
||||
@@ -832,8 +844,8 @@ gd_move(struct monst *grd)
|
||||
if (egrd->fcend > 1) {
|
||||
if (egrd->fcend > 2 && in_fcorridor(grd, grd->mx, grd->my)
|
||||
&& !egrd->gddone && !in_fcorridor(grd, u.ux, u.uy)
|
||||
&& levl[egrd->fakecorr[0].fx][egrd->fakecorr[0].fy].typ
|
||||
== egrd->fakecorr[0].ftyp) {
|
||||
&& (levl[egrd->fakecorr[0].fx][egrd->fakecorr[0].fy].typ
|
||||
== egrd->fakecorr[0].ftyp)) {
|
||||
pline("%s, confused, disappears.", noit_Monnam(grd));
|
||||
disappear_msg_seen = TRUE;
|
||||
goto cleanup;
|
||||
@@ -902,7 +914,8 @@ gd_move(struct monst *grd)
|
||||
for (ny = y - 1; ny <= y + 1; ny++) {
|
||||
if ((nx == x || ny == y) && (nx != x || ny != y)
|
||||
&& isok(nx, ny)) {
|
||||
typ = (crm = &levl[nx][ny])->typ;
|
||||
crm = &levl[nx][ny];
|
||||
typ = crm->typ;
|
||||
if (!IS_STWALL(typ) && !IS_POOL(typ)) {
|
||||
if (in_fcorridor(grd, nx, ny))
|
||||
goto nextnxy;
|
||||
@@ -914,16 +927,11 @@ gd_move(struct monst *grd)
|
||||
egrd->gddone = 1;
|
||||
if (ACCESSIBLE(typ))
|
||||
goto newpos;
|
||||
#ifdef STUPID
|
||||
if (typ == SCORR)
|
||||
crm->typ = CORR;
|
||||
else
|
||||
crm->typ = DOOR;
|
||||
#else
|
||||
crm->typ = (typ == SCORR) ? CORR : DOOR;
|
||||
#endif
|
||||
if (crm->typ == DOOR)
|
||||
crm->doormask = D_NODOOR;
|
||||
else
|
||||
crm->flags = 0;
|
||||
goto proceed;
|
||||
}
|
||||
}
|
||||
@@ -971,6 +979,7 @@ gd_move(struct monst *grd)
|
||||
break;
|
||||
}
|
||||
crm->typ = CORR;
|
||||
crm->flags = 0;
|
||||
proceed:
|
||||
newspot = TRUE;
|
||||
unblock_point(nx, ny); /* doesn't block light */
|
||||
@@ -979,11 +988,15 @@ gd_move(struct monst *grd)
|
||||
|
||||
if ((nx != gx || ny != gy) || (grd->mx != gx || grd->my != gy)) {
|
||||
fcp = &(egrd->fakecorr[egrd->fcend]);
|
||||
/* fakecorr overflow does not occur because egrd->fakecorr[]
|
||||
is too small, but it has occurred when the same <x,y> are
|
||||
put into it repeatedly for some as yet unexplained reason */
|
||||
if (egrd->fcend++ == FCSIZ)
|
||||
panic("fakecorr overflow");
|
||||
fcp->fx = nx;
|
||||
fcp->fy = ny;
|
||||
fcp->ftyp = typ;
|
||||
fcp->flags = crm->flags;
|
||||
} else if (!egrd->gddone) {
|
||||
/* We're stuck, so try to find a new destination. */
|
||||
if (!find_guard_dest(grd, &egrd->gdx, &egrd->gdy)
|
||||
|
||||
Reference in New Issue
Block a user