From: nethack.rankin Date: Thu, 1 Jun 2006 03:54:25 +0000 (+0000) Subject: recursive spoteffects (trunk only) X-Git-Tag: MOVE2GIT~995 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a72e370899fc3f4315d3fe07d8870fd6e00354a0;p=nethack recursive spoteffects (trunk only) Attempt to fix a buglist item: if hero poly'd into iron golem form enters a pool of water and drowning triggers reversion to human/whatever form due to water damage, he will fall into that pool again, crawl or teleport out, then redundantly crawl or teleport out for the initial entry. [ spoteffects -> drown -> losehp -> rehumanize -> polyman -> spoteffects -> drown ] I don't have a lot of confidence in this fix. It does handle the reported problem, and hasn't broken a couple of earlier tricky cases (ice melting to water, land mine turning into a pit). But drown() and lava_effects() seem to leave a trail of special case handling wherever they appear so they--or spoteffects, or both--ought to be redone somehow. --- diff --git a/doc/fixes35.0 b/doc/fixes35.0 index cbc8589dd..93494c9ae 100644 --- a/doc/fixes35.0 +++ b/doc/fixes35.0 @@ -143,6 +143,8 @@ don't give attribute adjustment messages ("you feel wise") unless the current meditating monsters stop meditating when affected by something which wakes sleeping mosnters monsters capable of hiding can't do so when trapped or while holding you +limit recursive calls to spoteffects (poly'd hero fell into water, reverted + to human because of it, fell into same water, then crawled out twice) Platform- and/or Interface-Specific Fixes diff --git a/src/hack.c b/src/hack.c index 01627cc04..8dfd01bc0 100644 --- a/src/hack.c +++ b/src/hack.c @@ -1,4 +1,4 @@ -/* SCCS Id: @(#)hack.c 3.5 2006/04/10 */ +/* SCCS Id: @(#)hack.c 3.5 2006/05/31 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -1504,10 +1504,28 @@ void spoteffects(pick) boolean pick; { + static int inspoteffects = 0; + static coord spotloc; + static int spotterrain; static struct trap *spottrap = (struct trap *)0; static unsigned spottraptyp = NO_TRAP; + struct trap *trap = t_at(u.ux, u.uy); register struct monst *mtmp; - + + /* prevent recursion from affecting the hero all over again + [hero poly'd to iron golem enters water here, drown() inflicts + damage that triggers rehumanize() which calls spoteffects()...] */ + if (inspoteffects && u.ux == spotloc.x && u.uy == spotloc.y && + /* except when reason is transformed terrain (ice -> water) */ + spotterrain == levl[u.ux][u.uy].typ && + /* or transformed trap (land mine -> pit) */ + (!spottrap || !trap || trap->ttyp == spottraptyp)) + return; + + ++inspoteffects; + spotterrain = levl[u.ux][u.uy].typ; + spotloc.x = u.ux, spotloc.y = u.uy; + if(u.uinwater) { int was_underwater; @@ -1552,10 +1570,13 @@ stillinwater:; pick = FALSE; } else #endif + /* drown(),lava_effects() return true if hero changes + location while surviving the problem */ if (is_lava(u.ux, u.uy)) { - if (lava_effects()) return; - } else if (!Wwalking && drown()) - return; + if (lava_effects()) goto spotdone; + } else if (!Wwalking) { + if (drown()) goto spotdone; + } } } check_special_room(FALSE); @@ -1564,7 +1585,6 @@ stillinwater:; dosinkfall(); #endif if (!in_steed_dismounting) { /* if dismounting, we'll check again later */ - struct trap *trap = t_at(u.ux, u.uy); boolean pit; /* @@ -1646,6 +1666,12 @@ stillinwater:; } mnexto(mtmp); /* have to move the monster */ } + spotdone: + if (!--inspoteffects) { + spotterrain = STONE; /* 0 */ + spotloc.x = spotloc.y = 0; + } + return; } /* returns first matching monster */