diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 163b1c38f..711d612e7 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -1,4 +1,4 @@ -NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.332 $ $NHDT-Date: 1602958104 2020/10/17 18:08:24 $ +NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.337 $ $NHDT-Date: 1603507384 2020/10/24 02:43:04 $ General Fixes and Modified Features ----------------------------------- @@ -280,6 +280,12 @@ when reporting that hero can't repair a chest's broken lock with key/pick/card pre-populate teleport destination prompt with travel destination ghosts cannot be renamed tossed upwards objects got two times half physical damage reduction +monster xorns could pass through iron bars but not eat them; monster rock + moles could no neither; now they can eat bars when adjacent and will + do so if the bars are blocking their path +hero poly'd into rust monster could implicitly eat bars when adjacent by + trying to move there, now when in rock mole form too; in xorn form + can explicitly eat them via 'e' after moving onto their spot Fixes to 3.7.0-x Problems that Were Exposed Via git Repository diff --git a/include/extern.h b/include/extern.h index a8151c034..e24e605b6 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1,4 +1,4 @@ -/* NetHack 3.7 extern.h $NHDT-Date: 1602270114 2020/10/09 19:01:54 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.867 $ */ +/* NetHack 3.7 extern.h $NHDT-Date: 1603507384 2020/10/24 02:43:04 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.873 $ */ /* Copyright (c) Steve Creps, 1988. */ /* NetHack may be freely redistributed. See license for details. */ @@ -874,6 +874,7 @@ E anything *FDECL(long_to_any, (long)); E anything *FDECL(monst_to_any, (struct monst *)); E anything *FDECL(obj_to_any, (struct obj *)); E boolean FDECL(revive_nasty, (int, int, const char *)); +E int FDECL(still_chewing, (XCHAR_P, XCHAR_P)); E void FDECL(movobj, (struct obj *, XCHAR_P, XCHAR_P)); E boolean FDECL(may_dig, (XCHAR_P, XCHAR_P)); E boolean FDECL(may_passwall, (XCHAR_P, XCHAR_P)); diff --git a/src/eat.c b/src/eat.c index ffc36dd25..f73c4d1d5 100644 --- a/src/eat.c +++ b/src/eat.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 eat.c $NHDT-Date: 1599258557 2020/09/04 22:29:17 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.233 $ */ +/* NetHack 3.7 eat.c $NHDT-Date: 1603507384 2020/10/24 02:43:04 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.235 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2012. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1449,7 +1449,8 @@ opentin(VOID_ARGS) { /* perhaps it was stolen (although that should cause interruption) */ if (!carried(g.context.tin.tin) - && (!obj_here(g.context.tin.tin, u.ux, u.uy) || !can_reach_floor(TRUE))) + && (!obj_here(g.context.tin.tin, u.ux, u.uy) + || !can_reach_floor(TRUE))) return 0; /* %% probably we should use tinoid */ if (g.context.tin.usedtime++ >= 50) { You("give up your attempt to open the tin."); @@ -2488,6 +2489,18 @@ doeat() } } + /* from floorfood(), &zeroobj means iron bars at current spot */ + if (otmp == &cg.zeroobj) { + /* hero in metallivore form is eating [diggable] iron bars + at current location so skip the other assorted checks; + operates as if digging rather than via the eat occupation */ + if (still_chewing(u.ux, u.uy) && levl[u.ux][u.uy].typ == IRONBARS) { + /* this is verbose, but player will see the hero rather than the + bars so wouldn't know that more turns of eating are required */ + You("pause to swallow."); + } + return 1; + } /* We have to make non-foods take 1 move to eat, unless we want to * do ridiculous amounts of coding to deal with partly eaten plate * mails, players who polymorph back to human in the middle of their @@ -3156,18 +3169,18 @@ int corpsecheck; /* 0, no check, 1, corpses, 2, tinnable corpses */ register struct obj *otmp; char qbuf[QBUFSZ]; char c; - boolean feeding = !strcmp(verb, "eat"), /* corpsecheck==0 */ - offering = !strcmp(verb, "sacrifice"); /* corpsecheck==1 */ + struct permonst *uptr = g.youmonst.data; + boolean feeding = !strcmp(verb, "eat"), /* corpsecheck==0 */ + offering = !strcmp(verb, "sacrifice"); /* corpsecheck==1 */ /* if we can't touch floor objects then use invent food only */ if (iflags.menu_requested /* command was preceded by 'm' prefix */ || !can_reach_floor(TRUE) || (feeding && u.usteed) || (is_pool_or_lava(u.ux, u.uy) - && (Wwalking || is_clinger(g.youmonst.data) - || (Flying && !Breathless)))) + && (Wwalking || is_clinger(uptr) || (Flying && !Breathless)))) goto skipfloor; - if (feeding && metallivorous(g.youmonst.data)) { + if (feeding && metallivorous(uptr)) { struct obj *gold; struct trap *ttmp = t_at(u.ux, u.uy); @@ -3188,8 +3201,30 @@ int corpsecheck; /* 0, no check, 1, corpses, 2, tinnable corpses */ return (struct obj *) 0; } } + if (levl[u.ux][u.uy].typ == IRONBARS) { + /* already verified that hero is metallivorous above */ + boolean nodig = (levl[u.ux][u.uy].wall_info & W_NONDIGGABLE) != 0; - if (g.youmonst.data != &mons[PM_RUST_MONSTER] + c = 'n'; + Strcpy(qbuf, "There are iron bars here"); + if (nodig || u.uhunger > 1500) { + pline("%s but you %s eat them.", qbuf, + nodig ? "cannot" : "are too full to"); + } else { + Strcat(qbuf, ((!g.context.digging.chew + || g.context.digging.pos.x != u.ux + || g.context.digging.pos.y != u.uy + || !on_level(&g.context.digging.level, &u.uz)) + ? "; eat them?" + : "; resume eating them?")); + c = yn_function(qbuf, ynqchars, 'n'); + } + if (c == 'y') + return (struct obj *) &cg.zeroobj; /* csst away 'const' */ + else if (c == 'q') + return (struct obj *) 0; + } + if (uptr != &mons[PM_RUST_MONSTER] && (gold = g_at(u.ux, u.uy)) != 0) { if (gold->quan == 1L) Sprintf(qbuf, "There is 1 gold piece here; eat it?"); diff --git a/src/hack.c b/src/hack.c index 941643a12..0e8efb024 100644 --- a/src/hack.c +++ b/src/hack.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 hack.c $NHDT-Date: 1600469617 2020/09/18 22:53:37 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.268 $ */ +/* NetHack 3.7 hack.c $NHDT-Date: 1603507385 2020/10/24 02:43:05 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.269 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -9,7 +9,6 @@ static void NDECL(maybe_wail); static int NDECL(moverock); -static int FDECL(still_chewing, (XCHAR_P, XCHAR_P)); static void NDECL(dosinkfall); static boolean FDECL(findtravelpath, (int)); static boolean FDECL(trapmove, (int, int, struct trap *)); @@ -394,7 +393,7 @@ moverock() * Chew on a wall, door, or boulder. [What about statues?] * Returns TRUE if still eating, FALSE when done. */ -static int +int still_chewing(x, y) xchar x, y; { @@ -418,7 +417,15 @@ xchar x, y; : "hard stone"); nomul(0); return 1; - } else if (g.context.digging.pos.x != x || g.context.digging.pos.y != y + } else if (lev->typ == IRONBARS + && metallivorous(g.youmonst.data) && u.uhunger > 1500) { + /* finishing eating via 'morehungry()' doesn't handle choking */ + You("are too full to eat the bars."); + nomul(0); + return 1; + } else if (!g.context.digging.chew + || g.context.digging.pos.x != x + || g.context.digging.pos.y != y || !on_level(&g.context.digging.level, &u.uz)) { g.context.digging.down = FALSE; g.context.digging.chew = TRUE; @@ -504,7 +511,20 @@ xchar x, y; digtxt = "chew through the tree."; lev->typ = ROOM; } else if (lev->typ == IRONBARS) { - digtxt = "eat through the bars."; + if (metallivorous(g.youmonst.data)) { /* should always be True here */ + /* arbitrary amount; unlike proper eating, nutrition is + bestowed in a lump sum at the end */ + int nut = (int) objects[HEAVY_IRON_BALL].oc_weight; + + /* lesshungry() requires that victual be set up, so skip it; + morehungry() of a negative amount will increase nutrition + without any possibility of choking to death on the meal; + updates hunger state and requests status update if changed */ + morehungry(-nut); + } + digtxt = (x == u.ux && y == u.uy) + ? "devour the iron bars." + : "eat through the bars."; dissolve_bars(x, y); } else if (lev->typ == SDOOR) { if (lev->doormask & D_TRAPPED) { @@ -745,8 +765,10 @@ int mode; pline("There is an obstacle there."); return FALSE; } else if (tmpr->typ == IRONBARS) { - if ((dmgtype(g.youmonst.data, AD_RUST) - || dmgtype(g.youmonst.data, AD_CORR)) && mode == DO_MOVE + if (mode == DO_MOVE + && (dmgtype(g.youmonst.data, AD_RUST) + || dmgtype(g.youmonst.data, AD_CORR) + || metallivorous(g.youmonst.data)) && still_chewing(x, y)) { return FALSE; } diff --git a/src/mondata.c b/src/mondata.c index 497beef06..5ccc48bb3 100644 --- a/src/mondata.c +++ b/src/mondata.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 mondata.c $NHDT-Date: 1596498186 2020/08/03 23:43:06 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.83 $ */ +/* NetHack 3.7 mondata.c $NHDT-Date: 1603507386 2020/10/24 02:43:06 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.86 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -334,7 +334,10 @@ struct permonst *mptr; { return (boolean) (passes_walls(mptr) || amorphous(mptr) || unsolid(mptr) || is_whirly(mptr) || verysmall(mptr) - || dmgtype(mptr, AD_CORR) || dmgtype(mptr, AD_RUST) + /* rust monsters and some puddings can destroy bars */ + || dmgtype(mptr, AD_RUST) || dmgtype(mptr, AD_CORR) + /* rock moles can eat bars */ + || metallivorous(mptr) || (slithy(mptr) && !bigmonst(mptr))); } diff --git a/src/monmove.c b/src/monmove.c index b367096e8..00986f4fb 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -1,4 +1,4 @@ -/* NetHack 3.7 monmove.c $NHDT-Date: 1600469618 2020/09/18 22:53:38 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.143 $ */ +/* NetHack 3.7 monmove.c $NHDT-Date: 1603507386 2020/10/24 02:43:06 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.146 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Michael Allison, 2006. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1477,9 +1477,12 @@ register int after; add_damage(mtmp->mx, mtmp->my, 0L); } } else if (levl[mtmp->mx][mtmp->my].typ == IRONBARS) { - /* 3.6.2: was using may_dig() but it doesn't handle bars */ + /* 3.6.2: was using may_dig() but that doesn't handle bars; + AD_RUST catches rust monsters but metallivorous() is + needed for xorns and rock moles */ if (!(levl[mtmp->mx][mtmp->my].wall_info & W_NONDIGGABLE) - && (dmgtype(ptr, AD_RUST) || dmgtype(ptr, AD_CORR))) { + && (dmgtype(ptr, AD_RUST) || dmgtype(ptr, AD_CORR) + || metallivorous(ptr))) { if (canseemon(mtmp)) pline("%s eats through the iron bars.", Monnam(mtmp)); dissolve_bars(mtmp->mx, mtmp->my); @@ -1631,6 +1634,8 @@ register int x, y; levl[x][y].typ = (Is_special(&u.uz) || *in_rooms(x, y, 0)) ? ROOM : CORR; levl[x][y].flags = 0; newsym(x, y); + if (x == u.ux && y == u.uy) + switch_terrain(); } boolean