diff --git a/doc/fixes37.0 b/doc/fixes37.0
index b0637b04f..49a4a3ef5 100644
--- a/doc/fixes37.0
+++ b/doc/fixes37.0
@@ -639,6 +639,8 @@ blessed scroll of remove curse read while confused blesses or curses any
scroll cursed the secondary weapon, that would be dropped and further
object traversal would process items on the floor at hero's spot
instead of the rest of inventory
+can now use m
to try to move to an adjacent boulder's spot without
+ pushing it; hero poly'd into a giant will succeed, others will fail
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
diff --git a/src/hack.c b/src/hack.c
index 47f502581..da66a9ea6 100644
--- a/src/hack.c
+++ b/src/hack.c
@@ -123,7 +123,40 @@ moverock(void)
rx = u.ux + 2 * u.dx; /* boulder destination position */
ry = u.uy + 2 * u.dy;
nomul(0);
+
+ /* using m towards an adjacent boulder steps over/onto it
+ if poly'd into a giant but is a no-op in other circumstances
+ unless the move attempt reveals an unseen boulder or lack of
+ remembered, unseen monster */
+ if (g.context.nopick) {
+ if (throws_rocks(g.youmonst.data)) {
+ /* player has used 'm' to move, so step to boulder's
+ spot without pushing it; hero is poly'd into a giant,
+ so exotic forms of locomotion are out, but might be
+ levitating (ring, potion, spell) or flying (amulet) */
+ You("%s over a boulder here.",
+ Levitation ? "float" : Flying ? "fly" : "step");
+ /* ["over" seems weird on air level but what else to say?] */
+ sokoban_guilt();
+ res = 0; /* move to */
+ } else {
+ int oldglyph = glyph_at(sx, sy);
+
+ feel_location(sx, sy);
+ There("is a boulder in your way.");
+ /* use a move if hero learns something; see test_move() for
+ how/why 'context.door_opened' is being dragged into this */
+ if (glyph_at(sx, sy) != oldglyph)
+ g.context.door_opened = g.context.move = TRUE;
+ res = -1; /* don't move to , so no soko guilt */
+ }
+ goto moverock_done; /* stop further push attempts */
+ }
if (Levitation || Is_airlevel(&u.uz)) {
+ /* FIXME? behavior in an air bubble on the water level should
+ be similar to being on the air level; both cases probably
+ ought to let push attempt proceed when flying (which implies
+ not levitating) */
if (Blind)
feel_location(sx, sy);
You("don't have enough leverage to push %s.", the(xname(otmp)));
@@ -864,8 +897,7 @@ test_move(int ux, int uy, int dx, int dy, int mode)
we haven't opened a door but we're going to
return False and without having 'door_opened'
set, 'move' would get reset by caller */
- g.context.door_opened
- = g.context.move = TRUE;
+ g.context.door_opened = g.context.move = TRUE;
/* since we've just lied about successfully
moving, we need to manually stop running */
nomul(0);