]> granicus.if.org Git - nethack/commitdiff
Fix: rn2(0) when trying to displace peaceful out of trap
authorcopperwater <aosdict@gmail.com>
Mon, 12 Mar 2018 02:20:32 +0000 (22:20 -0400)
committerPasi Kallinen <paxed@alt.org>
Wed, 15 Apr 2020 05:46:47 +0000 (08:46 +0300)
A side effect of making is_safepet() count peacefuls. Now checks
directly for a trapped, peaceful monster and says "they can't move out
of the trap"; this is inconsistent with pet behavior, and pet behavior
should probably be changed to be in line with it (ie they can't be
displaced out of a trap at all.)

Also refactor the code here a bit: a bunch of different if statements
have the exact same resetting code and steed resetting code in them.
Change this to a boolean flag and put the resetting code in one place
checked by that flag.

src/hack.c

index 013fc43b063f86405e7bd3ae823f74c5467d5408..d88bd94215cdd08f63c5a7b0546cb9c5a065eb75 100644 (file)
@@ -1802,40 +1802,48 @@ domove_core()
      * be caught by the normal falling-monster code.
      */
     if (is_safepet(mtmp) && !(is_hider(mtmp->data) && mtmp->mundetected)) {
+        /* if it turns out we can't actually move */
+        boolean didnt_move = FALSE;
+
+        /* seemimic/newsym should be done before moving hero, otherwise
+           the display code will draw the hero here before we possibly
+           cancel the swap below (we can ignore steed mx,my here) */
+        u.ux = u.ux0, u.uy = u.uy0;
         mtmp->mundetected = 0;
         if (M_AP_TYPE(mtmp))
             seemimic(mtmp);
+        u.ux = mtmp->mx, u.uy = mtmp->my; /* resume swapping positions */
 
         if (mtmp->mtrapped && (trap = t_at(mtmp->mx, mtmp->my)) != 0
             && is_pit(trap->ttyp)
             && sobj_at(BOULDER, trap->tx, trap->ty)) {
             /* can't swap places with pet pinned in a pit by a boulder */
-            u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
-            if (u.usteed)
-                u.usteed->mx = u.ux, u.usteed->my = u.uy;
+            didnt_move = TRUE;
         } else if (u.ux0 != x && u.uy0 != y && NODIAG(mtmp->data - mons)) {
             /* can't swap places when pet can't move to your spot */
-            u.ux = u.ux0, u.uy = u.uy0;
-            if (u.usteed)
-                u.usteed->mx = u.ux, u.usteed->my = u.uy;
             You("stop.  %s can't move diagonally.", upstart(y_monnam(mtmp)));
+            didnt_move = TRUE;
         } else if (u_with_boulder
                     && !(verysmall(mtmp->data)
                          && (!mtmp->minvent || (curr_mon_load(mtmp) <= 600)))) {
             /* can't swap places when pet won't fit there with the boulder */
-            u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
-            if (u.usteed)
-                u.usteed->mx = u.ux, u.usteed->my = u.uy;
             You("stop.  %s won't fit into the same spot that you're at.",
                  upstart(y_monnam(mtmp)));
+            didnt_move = TRUE;
         } else if (u.ux0 != x && u.uy0 != y && bad_rock(mtmp->data, x, u.uy0)
                    && bad_rock(mtmp->data, u.ux0, y)
                    && (bigmonst(mtmp->data) || (curr_mon_load(mtmp) > 600))) {
             /* can't swap places when pet won't fit thru the opening */
-            u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
-            if (u.usteed)
-                u.usteed->mx = u.ux, u.usteed->my = u.uy;
             You("stop.  %s won't fit through.", upstart(y_monnam(mtmp)));
+            didnt_move = TRUE;
+        } else if (mtmp->mpeaceful && !mtmp->mtame && mtmp->mtrapped) {
+            /* TODO: pets can get angered when displaced out of a trap.
+             * Having peaceful monsters simply refuse is inconsistent.
+             * Probably, pets should not be able to be displaced out of a
+             * trap like a pit or bear trap at all. */
+            You("stop.  %s can't move out of that trap.",
+                upstart(y_monnam(mtmp)));
+            didnt_move = TRUE;
         } else if (mtmp->mpeaceful && !mtmp->mtame
                    && (!goodpos(u.ux0, u.uy0, mtmp, 0)
                        || t_at(u.ux0, u.uy0) != NULL
@@ -1844,9 +1852,9 @@ domove_core()
                        || mtmp->m_id == g.quest_status.leader_m_id)) {
             /* displacing peaceful into unsafe or trapped space, or trying to
              * displace quest leader, Oracle, or priest */
-            u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
             You("stop.  %s doesn't want to swap places.",
                 upstart(y_monnam(mtmp)));
+            didnt_move = TRUE;
         } else {
             /* if trapped, there's a chance the pet goes wild */
             if (mtmp->mtrapped) {
@@ -1916,6 +1924,12 @@ domove_core()
                 break;
             }
         }
+
+        if (didnt_move) {
+            u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
+            if (u.usteed)
+                u.usteed->mx = u.ux, u.usteed->my = u.uy;
+        }
     }
 
     reset_occupations();