melting ice timeout issues
Reported directly to devteam by entrez via email: > > I noticed some potential issues with (melting) ice: > > * Digging down into ice, or setting a land mine on the ice and > triggering it, doesn't remove the melt_ice timeout, so it can result > in a sequence like dig down -> pit fills with water -> freeze water > -> freezing water tries to set melt_ice timeout -> duplicate timeout > impossible. Or if you don't freeze the water again, melt_ice will > run on a non-ice surface, which might at least produce strange > messages. > > * Setting a land mine on ice: melting ice doesn't do anything with > the trap, so there is still a land mine which you can trigger by > flying over the water (the land mine's trigger is also still > described as being 'in a pile of soil', despite being underwater at > this point). Similar thing happens with bear traps. > > * Not really related to _melting_ ice, but an exploding land mine > doesn't reset the typ from ICE to FLOOR (like normal digging does), > so it will result in a square with a pit that is also an ice square, > where the ice can melt under the pit and produce a combination > pit/moat. If you then freeze the moat, the pit reappears on top of > the ice.
This commit is contained in:
@@ -646,6 +646,8 @@ breaching a shop wall, using locking magic to put a door there, then unlocking
|
||||
that door yielded a situation where subsequent shop damage repair
|
||||
produced invalid map data which resulted in an impossible() warning
|
||||
about "wall_angle: unknown" during map display
|
||||
melting ice timer could persist after the ice was gone from digging or from an
|
||||
exploding land mine
|
||||
|
||||
|
||||
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
|
||||
|
||||
@@ -897,6 +897,7 @@ extern int max_capacity(void);
|
||||
extern boolean check_capacity(const char *);
|
||||
extern int inv_cnt(boolean);
|
||||
extern long money_cnt(struct obj *);
|
||||
extern void spot_checks(xchar, xchar, schar);
|
||||
|
||||
/* ### hacklib.c ### */
|
||||
|
||||
@@ -2685,6 +2686,7 @@ extern void sink_into_lava(void);
|
||||
extern void sokoban_guilt(void);
|
||||
extern const char * trapname(int, boolean);
|
||||
extern void ignite_items(struct obj *);
|
||||
extern void trap_ice_effects(xchar x, xchar y, boolean ice_is_melting);
|
||||
|
||||
/* ### u_init.c ### */
|
||||
|
||||
|
||||
73
src/dig.c
73
src/dig.c
@@ -767,9 +767,9 @@ dighole(boolean pit_only, boolean by_magic, coord *cc)
|
||||
register struct trap *ttmp;
|
||||
struct rm *lev;
|
||||
struct obj *boulder_here;
|
||||
schar typ;
|
||||
schar typ, old_typ;
|
||||
xchar dig_x, dig_y;
|
||||
boolean nohole;
|
||||
boolean nohole, retval = TRUE;
|
||||
|
||||
if (!cc) {
|
||||
dig_x = u.ux;
|
||||
@@ -784,10 +784,11 @@ dighole(boolean pit_only, boolean by_magic, coord *cc)
|
||||
ttmp = t_at(dig_x, dig_y);
|
||||
lev = &levl[dig_x][dig_y];
|
||||
nohole = (!Can_dig_down(&u.uz) && !lev->candig);
|
||||
old_typ = lev->typ;
|
||||
|
||||
if ((ttmp && (ttmp->ttyp == MAGIC_PORTAL
|
||||
|| ttmp->ttyp == VIBRATING_SQUARE || nohole))
|
||||
|| (IS_ROCK(lev->typ) && lev->typ != SDOOR
|
||||
|| (IS_ROCK(old_typ) && old_typ != SDOOR
|
||||
&& (lev->wall_info & W_NONDIGGABLE) != 0)) {
|
||||
pline_The("%s %shere is too hard to dig in.", surface(dig_x, dig_y),
|
||||
(dig_x != u.ux || dig_y != u.uy) ? "t" : "");
|
||||
@@ -797,20 +798,19 @@ dighole(boolean pit_only, boolean by_magic, coord *cc)
|
||||
hliquid(is_lava(dig_x, dig_y) ? "lava" : "water"));
|
||||
wake_nearby(); /* splashing */
|
||||
|
||||
} else if (lev->typ == DRAWBRIDGE_DOWN
|
||||
} else if (old_typ == DRAWBRIDGE_DOWN
|
||||
|| (is_drawbridge_wall(dig_x, dig_y) >= 0)) {
|
||||
/* drawbridge_down is the platform crossing the moat when the
|
||||
bridge is extended; drawbridge_wall is the open "doorway" or
|
||||
closed "door" where the portcullis/mechanism is located */
|
||||
if (pit_only) {
|
||||
pline_The("drawbridge seems too hard to dig through.");
|
||||
return FALSE;
|
||||
retval = FALSE;
|
||||
} else {
|
||||
int x = dig_x, y = dig_y;
|
||||
/* if under the portcullis, the bridge is adjacent */
|
||||
(void) find_drawbridge(&x, &y);
|
||||
destroy_drawbridge(x, y);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
} else if ((boulder_here = sobj_at(BOULDER, dig_x, dig_y)) != 0) {
|
||||
@@ -828,13 +828,10 @@ dighole(boolean pit_only, boolean by_magic, coord *cc)
|
||||
(void) delfloortrap(ttmp);
|
||||
}
|
||||
delobj(boulder_here);
|
||||
return TRUE;
|
||||
|
||||
} else if (IS_GRAVE(lev->typ)) {
|
||||
} else if (IS_GRAVE(old_typ)) {
|
||||
digactualhole(dig_x, dig_y, BY_YOU, PIT);
|
||||
dig_up_grave(cc);
|
||||
return TRUE;
|
||||
} else if (lev->typ == DRAWBRIDGE_UP) {
|
||||
} else if (old_typ == DRAWBRIDGE_UP) {
|
||||
/* must be floor or ice, other cases handled above */
|
||||
/* dig "pit" and let fluid flow in (if possible) */
|
||||
typ = fillholetyp(dig_x, dig_y, FALSE);
|
||||
@@ -847,20 +844,19 @@ dighole(boolean pit_only, boolean by_magic, coord *cc)
|
||||
pline_The("%s %shere is too hard to dig in.",
|
||||
surface(dig_x, dig_y),
|
||||
(dig_x != u.ux || dig_y != u.uy) ? "t" : "");
|
||||
return FALSE;
|
||||
retval = FALSE;
|
||||
} else {
|
||||
lev->drawbridgemask &= ~DB_UNDER;
|
||||
lev->drawbridgemask |= (typ == LAVAPOOL) ? DB_LAVA : DB_MOAT;
|
||||
liquid_flow(dig_x, dig_y, typ, ttmp,
|
||||
"As you dig, the hole fills with %s!");
|
||||
}
|
||||
|
||||
lev->drawbridgemask &= ~DB_UNDER;
|
||||
lev->drawbridgemask |= (typ == LAVAPOOL) ? DB_LAVA : DB_MOAT;
|
||||
liquid_flow(dig_x, dig_y, typ, ttmp,
|
||||
"As you dig, the hole fills with %s!");
|
||||
return TRUE;
|
||||
|
||||
/* the following two are here for the wand of digging */
|
||||
} else if (IS_THRONE(lev->typ)) {
|
||||
} else if (IS_THRONE(old_typ)) {
|
||||
pline_The("throne is too hard to break apart.");
|
||||
|
||||
} else if (IS_ALTAR(lev->typ)) {
|
||||
} else if (IS_ALTAR(old_typ)) {
|
||||
pline_The("altar is too hard to break apart.");
|
||||
|
||||
} else {
|
||||
@@ -873,28 +869,25 @@ dighole(boolean pit_only, boolean by_magic, coord *cc)
|
||||
liquid_flow(dig_x, dig_y, typ, ttmp,
|
||||
"As you dig, the hole fills with %s!");
|
||||
}
|
||||
return TRUE;
|
||||
} else {
|
||||
/* magical digging disarms settable traps */
|
||||
if (by_magic && ttmp
|
||||
&& (ttmp->ttyp == LANDMINE || ttmp->ttyp == BEAR_TRAP)) {
|
||||
int otyp = (ttmp->ttyp == LANDMINE) ? LAND_MINE : BEARTRAP;
|
||||
|
||||
/* convert trap into buried object (deletes trap) */
|
||||
cnv_trap_obj(otyp, 1, ttmp, TRUE);
|
||||
}
|
||||
|
||||
/* finally we get to make a hole */
|
||||
if (nohole || pit_only)
|
||||
digactualhole(dig_x, dig_y, BY_YOU, PIT);
|
||||
else
|
||||
digactualhole(dig_x, dig_y, BY_YOU, HOLE);
|
||||
}
|
||||
|
||||
/* magical digging disarms settable traps */
|
||||
if (by_magic && ttmp
|
||||
&& (ttmp->ttyp == LANDMINE || ttmp->ttyp == BEAR_TRAP)) {
|
||||
int otyp = (ttmp->ttyp == LANDMINE) ? LAND_MINE : BEARTRAP;
|
||||
|
||||
/* convert trap into buried object (deletes trap) */
|
||||
cnv_trap_obj(otyp, 1, ttmp, TRUE);
|
||||
}
|
||||
|
||||
/* finally we get to make a hole */
|
||||
if (nohole || pit_only)
|
||||
digactualhole(dig_x, dig_y, BY_YOU, PIT);
|
||||
else
|
||||
digactualhole(dig_x, dig_y, BY_YOU, HOLE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
spot_checks(dig_x, dig_y, old_typ);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
22
src/hack.c
22
src/hack.c
@@ -3430,4 +3430,26 @@ money_cnt(struct obj *otmp)
|
||||
return 0L;
|
||||
}
|
||||
|
||||
void
|
||||
spot_checks(xchar x, xchar y, schar old_typ)
|
||||
{
|
||||
schar new_typ = levl[x][y].typ;
|
||||
boolean db_ice_now = FALSE;
|
||||
|
||||
switch (old_typ) {
|
||||
case DRAWBRIDGE_UP:
|
||||
db_ice_now = ((levl[x][y].drawbridgemask & DB_UNDER) == DB_ICE);
|
||||
/*FALLTHRU*/
|
||||
case ICE:
|
||||
if ((new_typ != old_typ) || !db_ice_now) {
|
||||
/* make sure there's no MELT_ICE_AWAY timer */
|
||||
if (spot_time_left(x, y, MELT_ICE_AWAY)) {
|
||||
spot_stop_timers(x, y, MELT_ICE_AWAY);
|
||||
}
|
||||
/* adjust things affected by the ice */
|
||||
obj_ice_effects(x, y, FALSE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*hack.c*/
|
||||
|
||||
@@ -1860,7 +1860,7 @@ timer_sanity_check(void)
|
||||
timer_element *curr;
|
||||
|
||||
/* this should be much more complete */
|
||||
for (curr = g.timer_base; curr; curr = curr->next)
|
||||
for (curr = g.timer_base; curr; curr = curr->next) {
|
||||
if (curr->kind == TIMER_OBJECT) {
|
||||
struct obj *obj = curr->arg.a_obj;
|
||||
|
||||
@@ -1868,7 +1868,20 @@ timer_sanity_check(void)
|
||||
impossible("timer sanity: untimed obj %s, timer %ld",
|
||||
fmt_ptr((genericptr_t) obj), curr->tid);
|
||||
}
|
||||
} else if (curr->kind == TIMER_LEVEL) {
|
||||
long where = curr->arg.a_long;
|
||||
xchar x = (xchar) ((where >> 16) & 0xFFFF),
|
||||
y = (xchar) (where & 0xFFFF);
|
||||
|
||||
if (!isok(x, y)) {
|
||||
impossible("timer sanity: spot timer %d at <%d,%d>",
|
||||
curr->tid, x, y);
|
||||
} else if (curr->func_index == MELT_ICE_AWAY && !is_ice(x, y)) {
|
||||
impossible("timer sanity: melt timer %d on non-ice %d <%d,%d>",
|
||||
curr->tid, levl[x][y].typ, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
20
src/trap.c
20
src/trap.c
@@ -2570,8 +2570,9 @@ blow_up_landmine(struct trap* trap)
|
||||
{
|
||||
int x = trap->tx, y = trap->ty, dbx, dby;
|
||||
struct rm *lev = &levl[x][y];
|
||||
schar typ;
|
||||
schar old_typ, typ;
|
||||
|
||||
old_typ = lev->typ;
|
||||
(void) scatter(x, y, 4,
|
||||
MAY_DESTROY | MAY_HIT | MAY_FRACTURE | VIS_EFFECTS,
|
||||
(struct obj *) 0);
|
||||
@@ -2607,6 +2608,7 @@ blow_up_landmine(struct trap* trap)
|
||||
}
|
||||
}
|
||||
}
|
||||
spot_checks(x, y, old_typ);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -5996,4 +5998,20 @@ ignite_items(struct obj* objchn)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
trap_ice_effects(xchar x, xchar y, boolean ice_is_melting)
|
||||
{
|
||||
struct trap *ttmp = t_at(x, y);
|
||||
|
||||
if (ttmp && ice_is_melting) {
|
||||
if (ttmp->ttyp == LANDMINE || ttmp->ttyp == BEAR_TRAP) {
|
||||
/* landmine or bear trap set on top of the ice falls
|
||||
into the water */
|
||||
int otyp = (ttmp->ttyp == LANDMINE) ? LAND_MINE : BEARTRAP;
|
||||
cnv_trap_obj(otyp, 1, ttmp, TRUE);
|
||||
} else {
|
||||
deltrap(ttmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*trap.c*/
|
||||
|
||||
@@ -4477,6 +4477,8 @@ melt_ice(xchar x, xchar y, const char *msg)
|
||||
lev->icedpool = 0;
|
||||
}
|
||||
spot_stop_timers(x, y, MELT_ICE_AWAY); /* no more ice to melt away */
|
||||
if (t_at(x, y))
|
||||
trap_ice_effects(x, y, TRUE); /* TRUE because ice_is_melting */
|
||||
obj_ice_effects(x, y, FALSE);
|
||||
unearth_objs(x, y);
|
||||
if (Underwater)
|
||||
|
||||
Reference in New Issue
Block a user