diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index 23d22abcc..caaa78e0b 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -1164,6 +1164,9 @@ avoid "wall_angle: unknown hwall mode 4" when using #terrain command to has been transformed into an open door while not in sight it was possible to produce a web at a water or lava location; it would not be visible but could trap the hero, resulting in drowning or incineration +engraving in an open doorway was allowed, engraving in closed one (presumably + via Passes_walls) was not, but closing the door on an engraving was; + change to allow engraving at closed door location Fixes to 3.7.0-x General Problems Exposed Via git Repository @@ -1555,6 +1558,7 @@ throttle the difficulty of the monsters in theme room "buried zombies" buried troll whose auto-revive timer expired might triger panic with "revive default case 6" throwing a helm of brilliance could yield "breaking odd object?" +sanity checking of engravings was stopping after first problem found Fixes to 3.7.0-x Platform and/or Interface Problems Exposed Via git Repository diff --git a/include/rm.h b/include/rm.h index 8f04fac8c..fb8c28c43 100644 --- a/include/rm.h +++ b/include/rm.h @@ -107,6 +107,14 @@ enum levl_typ_types { #define IS_AIR(typ) ((typ) == AIR || (typ) == CLOUD) #define IS_SOFT(typ) ((typ) == AIR || (typ) == CLOUD || IS_POOL(typ)) #define IS_WATERWALL(typ) ((typ) == WATER) +/* for surface checks when it's unknown whether a drawbridge is involved; + drawbridge_up is the spot in front of a closed drawbridge and not the + current surface at that spot; caveat: this evaluates its arguments more + than once and might make a function call */ +#define SURFACE_AT(x,y) \ + ((levl[x][y].typ == DRAWBRIDGE_UP) \ + ? db_under_typ(levl[x][y].drawbridgemask) \ + : levl[x][y].typ) /* * Note: secret doors (SDOOR) want to use both rm.doormask and diff --git a/src/dungeon.c b/src/dungeon.c index a88a95dbe..f5afef3ad 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -1720,10 +1720,12 @@ Can_rise_up(coordxy x, coordxy y, d_level *lev) boolean has_ceiling(d_level *lev) { - if (!(Is_astralevel(lev) || Is_firelevel(lev) - || Is_airlevel(lev) || Is_waterlevel(lev))) - return TRUE; - return FALSE; + /* FIXME: some (most? all?) of the quest home levels are conceptually + above ground and don't have ceilings outside of their buildings + but we don't presently check for that */ + if (In_endgame(lev) && !Is_earthlevel(lev)) + return FALSE; + return TRUE; } boolean @@ -1779,14 +1781,16 @@ const char * surface(coordxy x, coordxy y) { struct rm *lev = &levl[x][y]; + int levtyp = SURFACE_AT(x, y); if (u_at(x, y) && u.uswallow && is_animal(u.ustuck->data)) /* 'husk' is iffy but maw is wrong for 't' class */ return digests(u.ustuck->data) ? "maw" : enfolds(u.ustuck->data) ? "husk" : "nonesuch"; /* can't happen (fingers crossed...) */ - else if (IS_AIR(lev->typ) && Is_airlevel(&u.uz)) - return "air"; + else if (IS_AIR(levtyp)) + return Is_waterlevel(&u.uz) ? "air bubble" + : (levtyp == CLOUD) ? "cloud" : "air"; else if (is_pool(x, y)) return (Underwater && !Is_waterlevel(&u.uz)) ? "bottom" : hliquid("water"); @@ -1796,16 +1800,19 @@ surface(coordxy x, coordxy y) return hliquid("lava"); else if (lev->typ == DRAWBRIDGE_DOWN) return "bridge"; - else if (IS_ALTAR(levl[x][y].typ)) + else if (IS_ALTAR(levtyp)) return "altar"; - else if (IS_GRAVE(levl[x][y].typ)) + else if (IS_GRAVE(levtyp)) return "headstone"; - else if (IS_FOUNTAIN(levl[x][y].typ)) + else if (IS_FOUNTAIN(levtyp)) return "fountain"; else if (On_stairs(x, y)) return "stairs"; - else if ((IS_ROOM(lev->typ) && !Is_earthlevel(&u.uz)) - || IS_WALL(lev->typ) || IS_DOOR(lev->typ) || lev->typ == SDOOR) + else if (IS_WALL(levtyp) || levtyp == SDOOR) + return "wall"; /* 'surface' during Passes_walls */ + else if (IS_DOOR(levtyp)) + return "doorway"; /* even for closed door */ + else if (IS_ROOM(levtyp) && !Is_earthlevel(&u.uz)) return "floor"; else return "ground"; diff --git a/src/engrave.c b/src/engrave.c index 5221506a5..8566b08a1 100644 --- a/src/engrave.c +++ b/src/engrave.c @@ -407,6 +407,8 @@ stylus_ok(struct obj *obj) static boolean u_can_engrave(void) { + int levtyp = SURFACE_AT(u.ux, u.uy); + if (u.uswallow) { if (is_animal(u.ustuck->data)) { pline("What would you write? \"Jonah was here\"?"); @@ -420,18 +422,20 @@ u_can_engrave(void) } else if (is_lava(u.ux, u.uy)) { You_cant("write on the %s!", surface(u.ux, u.uy)); return FALSE; - } else if (is_pool(u.ux, u.uy) || IS_FOUNTAIN(levl[u.ux][u.uy].typ)) { + } else if (is_pool(u.ux, u.uy) || IS_FOUNTAIN(levtyp)) { You_cant("write on the %s!", surface(u.ux, u.uy)); return FALSE; - } - if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) /* in bubble */) { - You_cant("write in thin air!"); + } else if (IS_AIR(levtyp)) { + /* airlevel or inside bubble on waterlevel */ + You_cant("write in %s!", + (levtyp == CLOUD) ? "cloud vapor" : "thin air"); return FALSE; - } else if (!accessible(u.ux, u.uy)) { + } else if (!ACCESSIBLE(levtyp)) { /* stone, tree, wall, secret corridor, pool, lava, bars */ You_cant("write here."); return FALSE; } + if (cantwield(gy.youmonst.data)) { You_cant("even hold anything!"); return FALSE; @@ -1315,7 +1319,7 @@ void engraving_sanity_check(void) { struct engr *ep; - schar typ; + int levtyp; if (head_engr && (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz))) { impossible("engraving sanity: on plane of air/water"); @@ -1327,14 +1331,13 @@ engraving_sanity_check(void) if (!isok(x, y)) { impossible("engraving sanity: !isok <%i,%i>", x, y); - return; + continue; } - - typ = levl[x][y].typ; - if (typ == LAVAPOOL || typ == LAVAWALL || IS_POOL(typ) - || typ == AIR || !accessible(x, y)) { - impossible("engraving sanity: illegal surface (%i)", typ); - return; + levtyp = SURFACE_AT(x, y); + if (is_pool_or_lava(x, y) || IS_AIR(levtyp) || !ACCESSIBLE(levtyp)) { + impossible("engraving sanity: illegal surface (%d: \"%s\")", + levtyp, surface(x, y)); + continue; } } } diff --git a/src/monmove.c b/src/monmove.c index 45bc34e2c..4ff5b197d 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -1895,11 +1895,8 @@ closed_door(coordxy x, coordxy y) boolean accessible(coordxy x, coordxy y) { - int levtyp = levl[x][y].typ; - /* use underlying terrain in front of closed drawbridge */ - if (levtyp == DRAWBRIDGE_UP) - levtyp = db_under_typ(levl[x][y].drawbridgemask); + int levtyp = SURFACE_AT(x, y); return (boolean) (ACCESSIBLE(levtyp) && !closed_door(x, y)); }