[gnome-nibbles] Fix corner-case handling of tail teleportation



commit 9f819cdaedd4a23f52ebc27ea0ec0267ffc5b461
Author: Michael Catanzaro <mcatanzaro gnome org>
Date:   Sun Jul 20 17:03:33 2014 -0500

    Fix corner-case handling of tail teleportation
    
    What we do here is really insane. After our tail moves into the
    teleporter, we erase it from the text board and remove its clutter
    actor, but then intentionally leave the tail pointer stationary,
    trusting to the gnibbles_worm_get_tail_direction function to position it
    properly on the next turn, then warping and moving the tail pointer an
    extra time on that turn. This kind of works because
    gnibbles_worm_get_tail_direction() operates on the clutter actors, which
    are stored in a linked list and do know their position. But it's also
    super fragile if we do anything interesting with the teleporters (e.g.
    teleport immediately on the next move, because we came at a teleporter
    from a particular direction). So instead of this
    don't-move-then-move-twice nonsense, assume that if we ever do not know
    which direction to move in it's because we're at a teleporter, and try
    to use it.
    
    Also, add a couple sensible assertions to make sure this assumption
    always holds.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=654072

 src/warpmanager.c |   26 ++++++++++++++++++--------
 src/worm.c        |   22 +++-------------------
 2 files changed, 21 insertions(+), 27 deletions(-)
---
diff --git a/src/warpmanager.c b/src/warpmanager.c
index ed8b4af..4244be2 100644
--- a/src/warpmanager.c
+++ b/src/warpmanager.c
@@ -148,8 +148,21 @@ gnibbles_warpmanager_worm_change_pos (GnibblesWarpManager * warpmanager,
 
       worm->xhead = x;
       worm->yhead = y;
+
+      return;
     }
   }
+
+  g_assert_not_reached ();
+}
+
+static gboolean
+is_adjacent_to_warp (gint x, gint y, GnibblesWarp * warp)
+{
+  return abs (warp->x - x) <= 1 && abs (warp->y - y) <= 1
+      || abs (warp->x + 1 - x) <= 1 && abs (warp->y - y) <= 1
+      || abs (warp->x - x) <= 1 && abs (warp->y + 1 -y) <= 1
+      || abs (warp->x + 1 - x) <= 1 && abs (warp->y + 1 - y) <= 1;
 }
 
 void
@@ -159,14 +172,7 @@ gnibbles_warpmanager_worm_change_tail_pos (GnibblesWarpManager * warpmanager,
   int i, x, y, good;
 
   for (i = 0; i < warpmanager->numwarps; i++) {
-    if ((worm->xtail == warpmanager->warps[i]->x &&
-        worm->ytail == warpmanager->warps[i]->y) ||
-        (worm->xtail == warpmanager->warps[i]->x + 1 &&
-        worm->ytail == warpmanager->warps[i]->y) ||
-        (worm->xtail == warpmanager->warps[i]->x &&
-        worm->ytail == warpmanager->warps[i]->y + 1) ||
-        (worm->xtail == warpmanager->warps[i]->x + 1 &&
-        worm->ytail == warpmanager->warps[i]->y + 1)) {
+    if (is_adjacent_to_warp (worm->xtail, worm->ytail, warpmanager->warps[i])) {
 
         x = warpmanager->warps[i]->wx;
         y = warpmanager->warps[i]->wy;
@@ -185,8 +191,12 @@ gnibbles_warpmanager_worm_change_tail_pos (GnibblesWarpManager * warpmanager,
 
       worm->xtail = x;
       worm->ytail = y;
+
+      return;
     }
   }
+
+  g_assert_not_reached ();
 }
 
 void
diff --git a/src/worm.c b/src/worm.c
index 0a576f6..6546e8c 100644
--- a/src/worm.c
+++ b/src/worm.c
@@ -429,29 +429,13 @@ gnibbles_worm_move_tail_pointer (GnibblesWorm *worm)
         worm->ytail = BOARDHEIGHT - 1;
       break;
     default:
+      /* OK, we're teleporting */
       break;
   }
 
-  if (board->walls[worm->xtail][worm->ytail] == WARPLETTER) {
+  if (tail_dir == -1) {
     gnibbles_warpmanager_worm_change_tail_pos (warpmanager, worm);
-    tail_dir = gnibbles_worm_get_tail_direction (worm);
-    board->walls[worm->xtail][worm->ytail] = EMPTYCHAR;
-    switch (tail_dir) {
-      case WORMRIGHT:
-        worm->xtail++;
-        break;
-      case WORMDOWN:
-        worm->ytail++;
-        break;
-      case WORMLEFT:
-        worm->xtail--;
-        break;
-      case WORMUP:
-        worm->ytail--;
-        break;
-      default:
-        break;
-      }
+    board->walls[worm->xtail][worm->ytail] = worm->number + WORMCHAR;
   }
 
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]