From 9c0e47785ab15d8cfd39684e1d079d29fcd6f296 Mon Sep 17 00:00:00 2001 From: PatR Date: Wed, 27 Nov 2024 08:41:55 -0800 Subject: [PATCH] digging in ice If the spot in front of a closed drawbridge was ICE, digging there had issues.... --- doc/fixes3-7-0.txt | 2 ++ src/dig.c | 6 ++++-- src/do.c | 35 ++++++++++++++++++++--------------- src/mkmaze.c | 13 ++++++++----- src/trap.c | 41 ++++++++++++++++++++++++++++++----------- 5 files changed, 64 insertions(+), 33 deletions(-) diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index 605bc49d4..0538b7750 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -1481,6 +1481,8 @@ if eating a tin's contents caused the hero to choke to death or turn to stone, when hero who is poly'd into metallivore form eats a tin, bypass "smells like " feedback and the "Eat it?" prompt; just eat the contents along with the tin without asking +digging in ice was handled inconsistently, particularly if done at the span + spot in front of closed drawbridge Fixes to 3.7.0-x General Problems Exposed Via git Repository diff --git a/src/dig.c b/src/dig.c index bedae5cf9..826be653a 100644 --- a/src/dig.c +++ b/src/dig.c @@ -859,8 +859,9 @@ liquid_flow( } if (ttmp) - (void) delfloortrap(ttmp); /* will untrap monster is one is here */ + (void) delfloortrap(ttmp); /* will untrap monster if one is here */ /* if any objects were frozen here, they're released now */ + obj_ice_effects(x, y, TRUE); unearth_objs(x, y); if (fillmsg) @@ -2081,7 +2082,8 @@ bury_objs(int x, int y) } } -/* move objects from buriedobjlist to fobj/nexthere lists */ +/* move objects from buriedobjlist to fobj/nexthere lists; if caller + converts terrain from ice to something, it should call obj_ice_effects() */ void unearth_objs(int x, int y) { diff --git a/src/do.c b/src/do.c index b3feccec2..f4f7c3e4d 100644 --- a/src/do.c +++ b/src/do.c @@ -48,9 +48,9 @@ dodrop(void) */ boolean boulder_hits_pool( - struct obj *otmp, - coordxy rx, coordxy ry, - boolean pushing) + struct obj *otmp, /* the object falling into a pool or water or lava */ + coordxy rx, coordxy ry, /* coordinates of the pool */ + boolean pushing) /* for a boulder, whether or not it is being pushed */ { if (!otmp || otmp->otyp != BOULDER) { impossible("Not a boulder?"); @@ -138,8 +138,9 @@ boulder_hits_pool( losehp(Maybe_Half_Phys(dmg), /* lava damage */ "molten lava", KILLED_BY); } else if (!fills_up && flags.verbose - && (pushing ? !Blind : cansee(rx, ry))) + && (pushing ? !Blind : cansee(rx, ry))) { pline("It sinks without a trace!"); + } } /* boulder is now gone */ @@ -157,7 +158,10 @@ boulder_hits_pool( * away. */ boolean -flooreffects(struct obj *obj, coordxy x, coordxy y, const char *verb) +flooreffects( + struct obj *obj, /* the object landing on the floor */ + coordxy x, coordxy y, /* map coordinates for spot where it is landing */ + const char *verb) /* "fall", "drop", "land", &c */ { struct trap *t; struct monst *mtmp; @@ -236,12 +240,10 @@ flooreffects(struct obj *obj, coordxy x, coordxy y, const char *verb) You_hear("a CRASH! beneath you."); } else if (!Blind && cansee(x, y)) { pline_The("boulder %s%s.", - (ttyp == TRAPDOOR && !tseen) - ? "triggers and " : "", - (ttyp == TRAPDOOR) - ? "plugs a trap door" - : (ttyp == HOLE) ? "plugs a hole" - : "fills a pit"); + (ttyp == TRAPDOOR && !tseen) ? "triggers and " : "", + (ttyp == TRAPDOOR) ? "plugs a trap door" + : (ttyp == HOLE) ? "plugs a hole" + : "fills a pit"); } else { Soundeffect(se_boulder_drop, 100); You_hear("a boulder %s.", verb); @@ -252,10 +254,13 @@ flooreffects(struct obj *obj, coordxy x, coordxy y, const char *verb) * || mondied) -> mondead -> m_detach -> fill_pit. */ deletedwithboulder: - if ((t = t_at(x, y)) != 0) - deltrap(t); - if (u.utrap && u_at(x, y)) - reset_utrap(FALSE); + /* creating a pit in ice results in that ice being turned into + floor so we shouldn't need any special ice handing here */ + if ((t = t_at(x, y)) != 0) { + (void) delfloortrap(t); + if (u.utrap && u_at(x, y)) + reset_utrap(FALSE); + } useupf(obj, 1L); bury_objs(x, y); newsym(x, y); diff --git a/src/mkmaze.c b/src/mkmaze.c index 0687a6c30..c1e2b6205 100644 --- a/src/mkmaze.c +++ b/src/mkmaze.c @@ -78,19 +78,22 @@ set_levltyp(coordxy x, coordxy y, schar newtyp) if (isok(x, y) && newtyp >= STONE && newtyp < MAX_TYPE) { if (CAN_OVERWRITE_TERRAIN(levl[x][y].typ)) { schar oldtyp = levl[x][y].typ; - boolean was_ice = (levl[x][y].typ == ICE); + /* typ==ICE || (typ==DRAWBRIDGE_UP && drawbridgemask==DB_ICE) */ + boolean was_ice = is_ice(x, y); levl[x][y].typ = newtyp; /* TODO? * if oldtyp used flags or horizontal differently from - * from the way newtyp will use them, clear them. + * the way newtyp will use them, clear them. */ - if (IS_LAVA(newtyp)) + if (IS_LAVA(newtyp)) /* [what about IS_LAVA(oldtyp)=>.lit = 0?] */ levl[x][y].lit = 1; - - if (was_ice && newtyp != ICE) + if (was_ice && newtyp != ICE) { + /* frozen corpses resume rotting, no more ice to melt away */ + obj_ice_effects(x, y, TRUE); spot_stop_timers(x, y, MELT_ICE_AWAY); + } if ((IS_FOUNTAIN(oldtyp) != IS_FOUNTAIN(newtyp)) || (IS_SINK(oldtyp) != IS_SINK(newtyp))) count_level_features(); /* level.flags.nfountains,nsinks */ diff --git a/src/trap.c b/src/trap.c index 91103153c..a39ba8ddc 100644 --- a/src/trap.c +++ b/src/trap.c @@ -455,7 +455,7 @@ struct trap * maketrap(coordxy x, coordxy y, int typ) { static union vlaunchinfo zero_vl; - boolean oldplace; + boolean oldplace, was_ice, clear_flags; struct trap *ttmp; struct rm *lev = &levl[x][y]; @@ -473,10 +473,10 @@ maketrap(coordxy x, coordxy y, int typ) || (u.utraptype == TT_LAVA && !is_lava(x, y)))) reset_utrap(FALSE); /* old remain valid */ - } else if (!CAN_OVERWRITE_TERRAIN(lev->typ) - || (IS_FURNITURE(lev->typ) - && (typ != PIT && typ != HOLE)) + } else if (!CAN_OVERWRITE_TERRAIN(lev->typ) /* stairs */ || is_pool_or_lava(x, y) + || (IS_FURNITURE(lev->typ) && (typ != PIT && typ != HOLE)) + || (lev->typ == DRAWBRIDGE_UP && typ == MAGIC_PORTAL) || (IS_AIR(lev->typ) && typ != MAGIC_PORTAL) || (typ == LEVEL_TELEP && single_level_branch(&u.uz))) { /* no trap on top of furniture (caller usually screens the @@ -522,22 +522,41 @@ maketrap(coordxy x, coordxy y, int typ) && (is_hole(typ) || IS_DOOR(lev->typ) || IS_WALL(lev->typ))) add_damage(x, y, /* schedule repair */ ((IS_DOOR(lev->typ) || IS_WALL(lev->typ)) - && !svc.context.mon_moving) - ? SHOP_HOLE_COST - : 0L); - lev->doormask = 0; /* subsumes altarmask, icedpool... */ - if (IS_ROOM(lev->typ)) /* && !IS_AIR(lev->typ) */ + && !svc.context.mon_moving) ? SHOP_HOLE_COST : 0L); + + clear_flags = TRUE; /* assume lev->flags needs to be reset */ + /* DRAWBRIDGE_UP passes the IS_ROOM() test so check it first; + it also needs to retain lev->drawbridgemask */ + if (lev->typ == DRAWBRIDGE_UP) { + /* bridge is closed and we're putting a hole or pit at the span + spot; this trap will be deleted if/when the bridge is opened; + terrain becomes room floor even if it was moat, lava, or ice */ + clear_flags = FALSE; /* keep lev->drawbridgemask */ + was_ice = (lev->drawbridgemask & DB_UNDER) == DB_ICE; + lev->drawbridgemask &= ~DB_UNDER; + lev->drawbridgemask |= DB_FLOOR; + if (was_ice) { + /* subset of set_levltyp() after changing ice to floor; + frozen corpses resume rotting, no more ice to melt away */ + obj_ice_effects(x, y, TRUE); + spot_stop_timers(x, y, MELT_ICE_AWAY); + } + } else if (IS_ROOM(lev->typ)) { (void) set_levltyp(x, y, ROOM); + /* * some cases which can happen when digging * down while phazing thru solid areas */ - else if (lev->typ == STONE || lev->typ == SCORR) + } else if (lev->typ == STONE || lev->typ == SCORR) { (void) set_levltyp(x, y, CORR); - else if (IS_WALL(lev->typ) || lev->typ == SDOOR) + } else if (IS_WALL(lev->typ) || lev->typ == SDOOR) { (void) set_levltyp(x, y, svl.level.flags.is_maze_lev ? ROOM : svl.level.flags.is_cavernous_lev ? CORR : DOOR); + } + if (clear_flags) + lev->flags = 0; /* set_levltyp doesn't take care of this [yet?] */ unearth_objs(x, y); break;