From 4bd7f265f1e80afb79cf3dff31d4ddeeca9e9deb Mon Sep 17 00:00:00 2001 From: PatR Date: Mon, 11 Dec 2023 19:54:20 -0800 Subject: [PATCH] wizard mode terrain wishing at drawbridge spot When trying to reproduce the wand of striking "interesting effect (0)" report, I tried wishing for lava under the castle drawbridge. That wasn't handling drawbridges properly. This fixes wishing for moat, lava, ice, or floor at a drawbridge span location whether the bridge is currently open of closed. It also allows wishing for room or floor or ground at room spots; that hasn't had much testing. Wishing for furniture, pool|moat|water, or lava at an ice location wasn't cancelling any pending melt timer. ice_descr() was declared as returning const but returns its non-const output buffer argument. Change to 'char *' so that wizterrainwish() can capitilize that output without jumping through any hoops. --- include/extern.h | 4 +- src/objnam.c | 123 ++++++++++++++++++++++++++++++++++++++--------- src/pager.c | 4 +- 3 files changed, 104 insertions(+), 27 deletions(-) diff --git a/include/extern.h b/include/extern.h index 8ec803c03..44c80fd84 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.7 extern.h $NHDT-Date: 1698264776 2023/10/25 20:12:56 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1296 $ */ +/* NetHack 3.7 extern.h $NHDT-Date: 1702349265 2023/12/12 02:47:45 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.1328 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2106,7 +2106,7 @@ extern char *monhealthdescr(struct monst *mon, boolean, char *); extern void mhidden_description(struct monst *, boolean, char *); extern boolean object_from_map(int, coordxy, coordxy, struct obj **); extern const char *waterbody_name(coordxy, coordxy); -extern const char *ice_descr(coordxy, coordxy, char *); +extern char *ice_descr(coordxy, coordxy, char *); extern boolean ia_checkfile(struct obj *); extern int do_screen_description(coord, boolean, int, char *, const char **, struct permonst **); diff --git a/src/objnam.c b/src/objnam.c index f295667a1..71c7a49f8 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 objnam.c $NHDT-Date: 1698264786 2023/10/25 20:13:06 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.398 $ */ +/* NetHack 3.7 objnam.c $NHDT-Date: 1702349266 2023/12/12 02:47:46 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.407 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -49,6 +49,7 @@ static boolean wishymatch(const char *, const char *, boolean); static short rnd_otyp_by_wpnskill(schar); static short rnd_otyp_by_namedesc(const char *, char, int); static struct obj *wizterrainwish(struct _readobjnam_data *); +static void dbterrainmesg(const char *, coordxy, coordxy); static void readobjnam_init(char *, struct _readobjnam_data *); static int readobjnam_preparse(struct _readobjnam_data *); static void readobjnam_parse_charges(struct _readobjnam_data *); @@ -3253,8 +3254,9 @@ static struct obj * wizterrainwish(struct _readobjnam_data *d) { struct rm *lev; - boolean madeterrain = FALSE, badterrain = FALSE, didblock; - int trap, oldtyp; + boolean madeterrain = FALSE, badterrain = FALSE, didblock, is_dbridge; + int trap; + unsigned oldtyp, ltyp; coordxy x = u.ux, y = u.uy; char *bp = d->bp, *p = d->p; @@ -3273,8 +3275,9 @@ wizterrainwish(struct _readobjnam_data *d) tname = trapname(trap, TRUE); pline("%s%s.", An(tname), (trap != MAGIC_PORTAL) ? "" : " to nowhere"); - } else + } else { pline("Creation of %s failed.", an(tname)); + } return &hands_obj; } @@ -3282,6 +3285,7 @@ wizterrainwish(struct _readobjnam_data *d) or place furniture on existing traps which shouldn't be allowed) */ lev = &levl[x][y]; oldtyp = lev->typ; + is_dbridge = (oldtyp == DRAWBRIDGE_DOWN || oldtyp == DRAWBRIDGE_UP); didblock = does_block(x, y, lev); p = eos(bp); if (!BSTRCMPI(bp, p - 8, "fountain")) { @@ -3312,39 +3316,76 @@ wizterrainwish(struct _readobjnam_data *d) long save_prop; const char *new_water; - lev->typ = !BSTRCMPI(bp, p - 4, "pool") ? POOL - : !BSTRCMPI(bp, p - 4, "moat") ? MOAT - : WATER; - lev->flags = 0; + ltyp = !BSTRCMPI(bp, p - 4, "pool") ? POOL + : !BSTRCMPI(bp, p - 4, "moat") ? MOAT + : WATER; + if (!is_dbridge) { + lev->typ = ltyp; + lev->flags = 0; + } else { + /* drawbridgemask overloads flags */ + lev->drawbridgemask &= ~DB_UNDER; + lev->drawbridgemask |= DB_MOAT; + } del_engr_at(x, y); - save_prop = EHalluc_resistance; - EHalluc_resistance = 1; - new_water = waterbody_name(x, y); - EHalluc_resistance = save_prop; - pline("%s.", An(new_water)); - /* Must manually make kelp! */ + if (!is_dbridge) { + save_prop = EHalluc_resistance; + EHalluc_resistance = 1; + new_water = waterbody_name(x, y); + EHalluc_resistance = save_prop; + pline("%s.", An(new_water)); + /* Must manually make kelp! */ + } else { + dbterrainmesg("Moat", x, y); + } water_damage_chain(gl.level.objects[x][y], TRUE); madeterrain = TRUE; /* also matches "molten lava" */ } else if (!BSTRCMPI(bp, p - 4, "lava") || !BSTRCMPI(bp, p - 12, "wall of lava")) { - lev->typ = !BSTRCMPI(bp, p - 12, "wall of lava") ? LAVAWALL : LAVAPOOL; - lev->flags = 0; + ltyp = !BSTRCMPI(bp, p - 12, "wall of lava") ? LAVAWALL : LAVAPOOL; + if (!is_dbridge) { + lev->typ = ltyp; + lev->flags = 0; + } else { + /* drawbridgemask overloads flags */ + lev->drawbridgemask &= ~DB_UNDER; + lev->drawbridgemask |= DB_LAVA; + } del_engr_at(x, y); - pline("A pool of molten lava."); - if (!(Levitation || Flying) || lev->typ == LAVAWALL) - pooleffects(FALSE); + if (!is_dbridge) { + pline("A %s of molten lava.", + (lev->typ == LAVAPOOL) ? "pool" : "wall"); + if (!(Levitation || Flying) || lev->typ == LAVAWALL) + pooleffects(FALSE); + } else { + dbterrainmesg("Lava", x, y); + } + fire_damage_chain(gl.level.objects[x][y], TRUE, TRUE, x, y); madeterrain = TRUE; } else if (!BSTRCMPI(bp, p - 3, "ice")) { - lev->typ = ICE; - lev->flags = 0; + if (!is_dbridge) { + lev->typ = ICE; + /* icedpool overloads flags; specifies what ice will melt into */ + lev->icedpool = (oldtyp == ROOM) ? ICED_POOL : ICED_MOAT; + } else { + /* drawbridgemask overloads flags */ + lev->drawbridgemask &= ~DB_UNDER; + lev->drawbridgemask |= DB_ICE; + } del_engr_at(x, y); if (!strncmpi(bp, "melting ", 8)) start_melt_ice_timeout(x, y, 0L); - pline("Ice."); + if (!is_dbridge) { + char icebuf[40]; + + pline("%s.", upstart(ice_descr(x, y, icebuf))); + } else { + dbterrainmesg("Ice", x, y); + } madeterrain = TRUE; } else if (!BSTRCMPI(bp, p - 5, "altar")) { aligntyp al; @@ -3500,6 +3541,30 @@ wizterrainwish(struct _readobjnam_data *d) pline("Secret corridor requires corridor location."); badterrain = TRUE; } + } else if (!BSTRCMPI(bp, p - 4, "room") + || !BSTRCMPI(bp, p - 5, "floor") + || !BSTRCMPI(bp, p - 6, "ground")) { + if (oldtyp == ROOM + || (IS_FURNITURE(oldtyp) && CAN_OVERWRITE_TERRAIN(oldtyp)) + || oldtyp == ICE || is_pool_or_lava(x, y)) { + struct trap *t; + + lev->typ = ROOM; + pline("Room floor."); + if (IS_FURNITURE(oldtyp)) + count_level_features(); + if ((t = t_at(x, y)) != 0 && t->ttyp != MAGIC_PORTAL) + deltrap(t); + madeterrain = TRUE; + } else if (is_dbridge) { + lev->drawbridgemask &= ~DB_UNDER; + lev->drawbridgemask |= DB_FLOOR; + dbterrainmesg("Floor", x, y); + madeterrain = TRUE; + } else { + pline("Room|floor|ground not allowed here."); + badterrain = TRUE; + } } if (madeterrain) { @@ -3510,7 +3575,7 @@ wizterrainwish(struct _readobjnam_data *d) if (u.uinwater && !is_pool(u.ux, u.uy)) { set_uinwater(0); /* u.uinwater = 0; leave the water */ docrt(); - /* [block/unblock_point was handled by docrt -> vision_recalc] */ + /* [block/unblock_point handled by docrt -> vision_recalc] */ } else { if (u.utrap && u.utraptype == TT_LAVA && !is_lava(u.ux, u.uy)) reset_utrap(FALSE); @@ -3527,6 +3592,8 @@ wizterrainwish(struct _readobjnam_data *d) /* fixups for replaced terrain that aren't handled above */ if (IS_FOUNTAIN(oldtyp) || IS_SINK(oldtyp)) count_level_features(); /* update level.flags.nfountains,nsinks */ + if (!is_ice(x, y)) + spot_stop_timers(x, y, MELT_ICE_AWAY); /* horizontal is overlaid by fountain->blessedftn, grave->disturbed */ if (IS_FOUNTAIN(oldtyp) || IS_GRAVE(oldtyp) || IS_WALL(oldtyp) || oldtyp == IRONBARS @@ -3553,6 +3620,16 @@ wizterrainwish(struct _readobjnam_data *d) return (struct obj *) 0; } +/* message common to several wizterrainwish() results */ +static void +dbterrainmesg( + const char *newtype, + coordxy x, coordxy y) +{ + pline("%s %s the drawbridge.", newtype, + (levl[x][y].typ == DRAWBRIDGE_UP) ? "in front of" : "under"); +} + #define TIN_UNDEFINED 0 #define TIN_EMPTY 1 #define TIN_SPINACH 2 diff --git a/src/pager.c b/src/pager.c index 6c8e94e0b..4c9d4b30f 100644 --- a/src/pager.c +++ b/src/pager.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 pager.c $NHDT-Date: 1698264788 2023/10/25 20:13:08 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.252 $ */ +/* NetHack 3.7 pager.c $NHDT-Date: 1702349268 2023/12/12 02:47:48 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.266 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2018. */ /* NetHack may be freely redistributed. See license for details. */ @@ -532,7 +532,7 @@ waterbody_name(coordxy x, coordxy y) return "water"; /* don't hallucinate this as some other liquid */ } -const char * +char * ice_descr(coordxy x, coordxy y, char *outbuf) { static const char *const icetyp[] = {