diff --git a/doc/fixes36.4 b/doc/fixes36.4 index 529cbfeca..c199560c4 100644 --- a/doc/fixes36.4 +++ b/doc/fixes36.4 @@ -1,4 +1,4 @@ -$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.4 $ $NHDT-Date: 1576287569 2019/12/14 01:39:29 $ +$NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.12 $ $NHDT-Date: 1576638499 2019/12/18 03:08:19 $ fixes36.4 contains a terse summary of changes made to 3.6.3 in order to produce 3.6.4. @@ -16,6 +16,12 @@ message "your knapsack can't accomodate any more items" when picking stuff up pending; vary the message rather than add more convoluted pickup code dozen-ish assorted spelling/typo fixes in messages and source comments fix potential buffer overflow when parsing run-time configuration file +wizard mode wishing for terrain would leave it unmapped if done while blind +wizard mode terrain wish could leave hero in water (severe vision limits) or + in lava (trapped, sinking) which wasn't there any more +flying hero can go down (via '>') holes or trap doors instead of escaping trap +polymorphed hero hiding on the ceiling can now use '>' to unhide instead of + being told "you can't go down here" Platform- and/or Interface-Specific Fixes or Features diff --git a/src/do.c b/src/do.c index b7bb737b9..8bbed39de 100644 --- a/src/do.c +++ b/src/do.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 do.c $NHDT-Date: 1576181796 2019/12/12 20:16:36 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.197 $ */ +/* NetHack 3.6 do.c $NHDT-Date: 1576638499 2019/12/18 03:08:19 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.198 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1000,6 +1000,24 @@ dodown() : surface(u.ux, u.uy)); return 0; /* didn't move */ } + + if (Upolyd && ceiling_hider(&mons[u.umonnum]) && u.uundetected) { + u.uundetected = 0; + if (Flying) { /* lurker above */ + You("fly out of hiding."); + } else { /* piercer */ + You("drop to the %s.", surface(u.ux, u.uy)); + if (is_pool_or_lava(u.ux, u.uy)) { + pooleffects(FALSE); + } else { + (void) pickup(1); + if ((trap = t_at(u.ux, u.uy)) != 0) + dotrap(trap, TOOKPLUNGE); + } + } + return 1; /* came out of hiding; might need '>' again to go down */ + } + if (!stairs_down && !ladder_down) { trap = t_at(u.ux, u.uy); if (trap && (uteetering_at_seen_pit(trap) || uescaped_shaft(trap))) { diff --git a/src/hack.c b/src/hack.c index a48b92cf5..79fe7408c 100644 --- a/src/hack.c +++ b/src/hack.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 hack.c $NHDT-Date: 1568509227 2019/09/15 01:00:27 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.216 $ */ +/* NetHack 3.6 hack.c $NHDT-Date: 1576638500 2019/12/18 03:08:20 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.220 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Derek S. Ray, 2015. */ /* NetHack may be freely redistributed. See license for details. */ @@ -2124,6 +2124,10 @@ boolean newspot; /* true if called by spoteffects */ } /* not mounted */ + /* if hiding on ceiling then don't automatically enter pool */ + if (Upolyd && ceiling_hider(&mons[u.umonnum]) && u.uundetected) + return FALSE; + /* drown(),lava_effects() return true if hero changes location while surviving the problem */ if (is_lava(u.ux, u.uy)) { diff --git a/src/objnam.c b/src/objnam.c index e54b20732..aa5d7713d 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 objnam.c $NHDT-Date: 1575245076 2019/12/02 00:04:36 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.255 $ */ +/* NetHack 3.6 objnam.c $NHDT-Date: 1576638500 2019/12/18 03:08:20 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.257 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2011. */ /* NetHack may be freely redistributed. See license for details. */ @@ -3663,14 +3663,17 @@ struct obj *no_wish; goto typfnd; } } -/* Let wizards wish for traps and furniture. - * Must come after objects check so wizards can still wish for - * trap objects like beartraps. - * Disallow such topology tweaks for WIZKIT startup wishes. - */ + + /* + * Let wizards wish for traps and furniture. + * Must come after objects check so wizards can still wish for + * trap objects like beartraps. + * Disallow such topology tweaks for WIZKIT startup wishes. + */ wiztrap: if (wizard && !program_state.wizkit_wishing) { struct rm *lev; + boolean madeterrain = FALSE; int trap, x = u.ux, y = u.uy; for (trap = NO_TRAP + 1; trap < TRAPNUM; trap++) { @@ -3693,7 +3696,8 @@ struct obj *no_wish; return (struct obj *) &zeroobj; } - /* furniture and terrain */ + /* furniture and terrain (use at your own risk; can clobber stairs + or place furniture on existing traps which shouldn't be allowed) */ lev = &levl[x][y]; p = eos(bp); if (!BSTRCMPI(bp, p - 8, "fountain")) { @@ -3702,43 +3706,36 @@ struct obj *no_wish; if (!strncmpi(bp, "magic ", 6)) lev->blessedftn = 1; pline("A %sfountain.", lev->blessedftn ? "magic " : ""); - newsym(x, y); - return (struct obj *) &zeroobj; - } - if (!BSTRCMPI(bp, p - 6, "throne")) { + madeterrain = TRUE; + } else if (!BSTRCMPI(bp, p - 6, "throne")) { lev->typ = THRONE; pline("A throne."); - newsym(x, y); - return (struct obj *) &zeroobj; - } - if (!BSTRCMPI(bp, p - 4, "sink")) { + madeterrain = TRUE; + } else if (!BSTRCMPI(bp, p - 4, "sink")) { lev->typ = SINK; level.flags.nsinks++; pline("A sink."); - newsym(x, y); - return (struct obj *) &zeroobj; - } + madeterrain = TRUE; + /* ("water" matches "potion of water" rather than terrain) */ - if (!BSTRCMPI(bp, p - 4, "pool") || !BSTRCMPI(bp, p - 4, "moat")) { + } else if (!BSTRCMPI(bp, p - 4, "pool") + || !BSTRCMPI(bp, p - 4, "moat")) { lev->typ = !BSTRCMPI(bp, p - 4, "pool") ? POOL : MOAT; del_engr_at(x, y); pline("A %s.", (lev->typ == POOL) ? "pool" : "moat"); /* Must manually make kelp! */ water_damage_chain(level.objects[x][y], TRUE); - newsym(x, y); - return (struct obj *) &zeroobj; - } - if (!BSTRCMPI(bp, p - 4, "lava")) { /* also matches "molten lava" */ + madeterrain = TRUE; + + /* also matches "molten lava" */ + } else if (!BSTRCMPI(bp, p - 4, "lava")) { lev->typ = LAVAPOOL; del_engr_at(x, y); pline("A pool of molten lava."); if (!(Levitation || Flying)) - (void) lava_effects(); - newsym(x, y); - return (struct obj *) &zeroobj; - } - - if (!BSTRCMPI(bp, p - 5, "altar")) { + pooleffects(FALSE); + madeterrain = TRUE; + } else if (!BSTRCMPI(bp, p - 5, "altar")) { aligntyp al; lev->typ = ALTAR; @@ -3751,37 +3748,43 @@ struct obj *no_wish; else if (!strncmpi(bp, "unaligned ", 10)) al = A_NONE; else /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */ - al = (!rn2(6)) ? A_NONE : rn2((int) A_LAWFUL + 2) - 1; + al = !rn2(6) ? A_NONE : (rn2((int) A_LAWFUL + 2) - 1); lev->altarmask = Align2amask(al); pline("%s altar.", An(align_str(al))); - newsym(x, y); - return (struct obj *) &zeroobj; - } - - if (!BSTRCMPI(bp, p - 5, "grave") - || !BSTRCMPI(bp, p - 9, "headstone")) { + madeterrain = TRUE; + } else if (!BSTRCMPI(bp, p - 5, "grave") + || !BSTRCMPI(bp, p - 9, "headstone")) { make_grave(x, y, (char *) 0); pline("%s.", IS_GRAVE(lev->typ) ? "A grave" : "Can't place a grave here"); - newsym(x, y); - return (struct obj *) &zeroobj; - } - - if (!BSTRCMPI(bp, p - 4, "tree")) { + madeterrain = TRUE; + } else if (!BSTRCMPI(bp, p - 4, "tree")) { lev->typ = TREE; pline("A tree."); - newsym(x, y); block_point(x, y); - return (struct obj *) &zeroobj; - } - - if (!BSTRCMPI(bp, p - 4, "bars")) { + madeterrain = TRUE; + } else if (!BSTRCMPI(bp, p - 4, "bars")) { lev->typ = IRONBARS; pline("Iron bars."); - newsym(x, y); + madeterrain = TRUE; + } + + if (madeterrain) { + feel_newsym(x, y); /* map the spot where the wish occurred */ + /* hero started at but might not be there anymore (create + lava, decline to die, and get teleported away to safety) */ + if (u.uinwater && !is_pool(u.ux, u.uy)) { + u.uinwater = 0; /* leave the water */ + docrt(); + vision_full_recalc = 1; + } else if (u.utrap && u.utraptype == TT_LAVA + && !is_lava(u.ux, u.uy)) { + reset_utrap(FALSE); + } + /* cast 'const' away; caller won't modify this */ return (struct obj *) &zeroobj; } - } + } /* end of wizard mode traps and terrain */ if (!oclass && !typ) { if (!strncmpi(bp, "polearm", 7)) { diff --git a/src/trap.c b/src/trap.c index cc15f22cc..b6db81148 100644 --- a/src/trap.c +++ b/src/trap.c @@ -1,4 +1,4 @@ -/* NetHack 3.6 trap.c $NHDT-Date: 1576274483 2019/12/13 22:01:23 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.325 $ */ +/* NetHack 3.6 trap.c $NHDT-Date: 1576638501 2019/12/18 03:08:21 $ $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.329 $ */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /*-Copyright (c) Robert Patrick Rankin, 2013. */ /* NetHack may be freely redistributed. See license for details. */ @@ -489,8 +489,9 @@ unsigned ftflags; ; /* KMH -- You can't escape the Sokoban level traps */ else if (Levitation || u.ustuck || (!Can_fall_thru(&u.uz) && !levl[u.ux][u.uy].candig) - || ((Flying || is_clinger(youmonst.data)) - && !(ftflags & TOOKPLUNGE)) + || ((Flying || is_clinger(youmonst.data) + || (ceiling_hider(youmonst.data) && u.uundetected)) + && !(ftflags & TOOKPLUNGE)) || (Inhell && !u.uevent.invoked && newlevel == bottom)) { dont_fall = "don't fall in."; } else if (youmonst.data->msize >= MZ_HUGE) { @@ -3746,6 +3747,7 @@ drown() boolean inpool_ok = FALSE, crawl_ok; int i, x, y; + feel_newsym(u.ux, u.uy); /* in case Blind, map the water here */ /* happily wading in the same contiguous pool */ if (u.uinwater && is_pool(u.ux - u.dx, u.uy - u.dy) && (Swimming || Amphibious)) { @@ -5262,6 +5264,7 @@ lava_effects() int dmg = d(6, 6); /* only applicable for water walking */ boolean usurvive, boil_away; + feel_newsym(u.ux, u.uy); /* in case Blind, map the lava here */ burn_away_slime(); if (likes_lava(youmonst.data)) return FALSE; @@ -5386,7 +5389,10 @@ sink_into_lava() static const char sink_deeper[] = "You sink deeper into the lava."; if (!u.utrap || u.utraptype != TT_LAVA) { - ; /* do nothing; this shouldn't happen */ + ; /* do nothing; this usually won't happen but could after + * polymorphing from a flier into a ceiling hider and then hiding; + * allmain() only checks whether the hero is at a lava location, + * not whether he or she is currently sinking */ } else if (!is_lava(u.ux, u.uy)) { reset_utrap(FALSE); /* this shouldn't happen either */ } else if (!u.uinvulnerable) {