revisit the forcefight crash fix

The previous fix prevents the crash from 'the()' when NO_GLYPH was
used as an index into the defsyms array, but it resulted in giving
feedback of "you attack thin air" regardless of what was at the
target location, reverting to the situation that the buggy code was
attempting to address in the first place.  Handle that differently
by removing the unseen monster glyph sooner.  Also, the underwater
handling wasn't working as intended.

I blamed Derek's pudding farming patch for introducing the problem,
but all that did was replace the offending line(s) with different
indentation.  The older post-3.4.3 patch which produced the problem
was mine.  Sorry, Derek.
This commit is contained in:
PatR
2015-04-18 20:02:40 -07:00
parent ce05d14e74
commit 8246c1b7c7
+50 -32
View File
@@ -1,4 +1,4 @@
/* NetHack 3.5 hack.c $NHDT-Date$ $NHDT-Branch$:$NHDT-Revision$ */ /* NetHack 3.5 hack.c $NHDT-Date: 1429412557 2015/04/19 03:02:37 $ $NHDT-Branch: master $:$NHDT-Revision: 1.143 $ */
/* NetHack 3.5 hack.c $Date: 2013/10/26 21:33:47 $ $Revision: 1.120 $ */ /* NetHack 3.5 hack.c $Date: 2013/10/26 21:33:47 $ $Revision: 1.120 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -1336,49 +1336,67 @@ domove()
if (context.forcefight || if (context.forcefight ||
/* remembered an 'I' && didn't use a move command */ /* remembered an 'I' && didn't use a move command */
(glyph_is_invisible(levl[x][y].glyph) && !context.nopick)) { (glyph_is_invisible(levl[x][y].glyph) && !context.nopick)) {
struct obj *boulder = sobj_at(BOULDER, x, y); struct obj *boulder = 0;
boolean explo = (Upolyd && attacktype(youmonst.data, AT_EXPL)), boolean explo = (Upolyd && attacktype(youmonst.data, AT_EXPL)),
solid = !accessible(x, y); solid = !accessible(x, y);
int glyph = glyph_at(x, y); /* might be monster */ int glyph = glyph_at(x, y); /* might be monster */
char buf[BUFSZ]; char buf[BUFSZ];
/* if a statue is displayed at the target location, if (!Underwater) {
player is attempting to attack it [and boulder boulder = sobj_at(BOULDER, x, y);
handlng below is suitable for handling that] */ /* if a statue is displayed at the target location,
if (glyph_is_statue(glyph) || player is attempting to attack it [and boulder
(Hallucination && glyph_is_monster(glyph))) handlng below is suitable for handling that] */
boulder = sobj_at(STATUE, x, y); if (glyph_is_statue(glyph) ||
(Hallucination && glyph_is_monster(glyph)))
boulder = sobj_at(STATUE, x, y);
/* force fight at boulder/statue or wall/door while wielding /* force fight at boulder/statue or wall/door while wielding
pick: start digging to break the boulder or wall */ pick: start digging to break the boulder or wall */
if (context.forcefight && if (context.forcefight &&
/* can we dig? */ /* can we dig? */
uwep && dig_typ(uwep, x, y) && uwep && dig_typ(uwep, x, y) &&
/* should we dig? */ /* should we dig? */
!glyph_is_invisible(glyph) && !glyph_is_invisible(glyph) &&
!glyph_is_monster(glyph)) { !glyph_is_monster(glyph)) {
(void)use_pick_axe2(uwep); (void)use_pick_axe2(uwep);
return; return;
} }
}
/* about to become known empty -- remove 'I' if present */
unmap_object(x, y);
if (boulder) map_object(boulder, TRUE);
newsym(x, y);
glyph = glyph_at(x, y); /* might have just changed */
if (boulder) if (boulder)
Strcpy(buf, ansimpleoname(boulder)); Strcpy(buf, ansimpleoname(boulder));
else if (solid && glyph_is_cmap(glyph)) else if (Underwater && !is_pool(x, y))
Strcpy(buf, the(defsyms[glyph_to_cmap(glyph)].explanation)); /* Underwater, targetting non-water; the map just shows blank
else if (!Underwater) because you don't see remembered terrain while underwater;
Strcpy(buf, "thin air"); although the hero can attack an adjacent monster this way,
else if (is_pool(x, y)) assume he can't reach out far enough to distinguish terrain */
Strcpy(buf, "empty water"); Sprintf(buf, (Is_waterlevel(&u.uz) && levl[x][y].typ == AIR) ?
else /* Underwater, targetting non-water */ "an air bubble" : "nothing");
Sprintf(buf, "a vacant spot on the %s", surface(x,y)); else if (solid)
/* glyph might indicate unseen terrain if hero is blind;
unlike searching, this won't reveal what that terrain is
(except for solid rock, where the glyph would otherwise
yield ludicrous "dark part of a room") */
Strcpy(buf, (levl[x][y].typ == STONE) ? "solid rock" :
glyph_is_cmap(glyph) ?
the(defsyms[glyph_to_cmap(glyph)].explanation) :
(const char *)"an unknown obstacle");
/* note: 'solid' is misleadingly named and catches pools
of water and lava as well as rock and walls */
else
Strcpy(buf, "thin air");
You("%s%s %s.", You("%s%s %s.",
!(boulder || solid) ? "" : !(boulder || solid) ? "" : !explo ? "harmlessly " : "futilely ",
!explo ? "harmlessly " : "futilely ",
explo ? "explode at" : "attack", explo ? "explode at" : "attack",
buf); buf);
unmap_object(x, y); /* known empty -- remove 'I' if present */
if (boulder) map_object(boulder, TRUE);
newsym(x, y);
nomul(0); nomul(0);
if (explo) { if (explo) {
wake_nearby(); wake_nearby();