rnd-20030220-1-src
[rocksndiamonds.git] / src / game.c
index 0ae6ce5159a9821c9740e9d404a1280ba808a3b1..629b323f1721143fe3cb0269347f08992dfaa471 100644 (file)
@@ -89,6 +89,8 @@
 #define DOUBLE_PLAYER_SPEED(p) (HALVE_MOVE_DELAY((p)->move_delay_value))
 #define HALVE_PLAYER_SPEED(p)  (DOUBLE_MOVE_DELAY((p)->move_delay_value))
 
+#define        INIT_GFX_RANDOM()       (SimpleRND(1000000))
+
 /* game button identifiers */
 #define GAME_CTRL_ID_STOP              0
 #define GAME_CTRL_ID_PAUSE             1
 #define NUM_GAME_BUTTONS               6
 
 /* forward declaration for internal use */
+#if 0
+static void ResetGfxAnimation(int, int);
+#endif
+
 static void InitBeltMovement(void);
 static void CloseAllOpenTimegates(void);
 static void CheckGravityMovement(struct PlayerInfo *);
@@ -115,9 +121,6 @@ static void HandleGameButtons(struct GadgetInfo *);
 
 static struct GadgetInfo *game_gadget[NUM_GAME_BUTTONS];
 
-#define IS_ANIMATED(g)         (graphic_info[g].anim_frames > 1)
-#define IS_LOOP_SOUND(s)       (sound_info[s].loop)
-
 
 /* ------------------------------------------------------------------------- */
 /* definition of elements that automatically change to other elements after  */
@@ -161,6 +164,9 @@ static struct ChangingElementInfo changing_element_list[] =
   { EL_TIMEGATE_OPENING,       EL_TIMEGATE_OPEN,       29, NULL, NULL, NULL },
   { EL_TIMEGATE_CLOSING,       EL_TIMEGATE_CLOSED,     29, NULL, NULL, NULL },
 
+  { EL_ACID_SPLASH_LEFT,       EL_EMPTY,                8, NULL, NULL, NULL },
+  { EL_ACID_SPLASH_RIGHT,      EL_EMPTY,                8, NULL, NULL, NULL },
+
   { EL_SP_BUGGY_BASE,          EL_SP_BUGGY_BASE_ACTIVATING, 0,
     InitBuggyBase, NULL, NULL },
   { EL_SP_BUGGY_BASE_ACTIVATING,EL_SP_BUGGY_BASE_ACTIVE, 0,
@@ -187,60 +193,6 @@ static struct ChangingElementInfo changing_element[MAX_NUM_ELEMENTS];
 #define IS_AUTO_CHANGING(e)  (changing_element[e].base_element != EL_UNDEFINED)
 
 
-
-#ifdef DEBUG
-#if 0
-static unsigned int getStateCheckSum(int counter)
-{
-  int x, y;
-  unsigned int mult = 1;
-  unsigned int checksum = 0;
-  /*
-  static short lastFeld[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
-  */
-  static boolean first_game = TRUE;
-
-  for (y=0; y<lev_fieldy; y++) for(x=0; x<lev_fieldx; x++)
-  {
-    /*
-    if (counter == 3)
-    {
-      if (first_game)
-       lastFeld[x][y] = Feld[x][y];
-      else if (lastFeld[x][y] != Feld[x][y])
-       printf("DIFF: [%d][%d]: lastFeld == %d != %d == Feld\n",
-              x, y, lastFeld[x][y], Feld[x][y]);
-    }
-    */
-
-    checksum += mult++ * Ur[x][y];
-    checksum += mult++ * Feld[x][y];
-
-    /*
-    checksum += mult++ * MovPos[x][y];
-    checksum += mult++ * MovDir[x][y];
-    checksum += mult++ * MovDelay[x][y];
-    checksum += mult++ * Store[x][y];
-    checksum += mult++ * Store2[x][y];
-    checksum += mult++ * StorePlayer[x][y];
-    checksum += mult++ * ExplodePhase[x][y];
-    checksum += mult++ * AmoebaNr[x][y];
-    checksum += mult++ * JustStopped[x][y];
-    checksum += mult++ * Stop[x][y];
-    */
-  }
-
-  if (counter == 3 && first_game)
-    first_game = FALSE;
-
-  return checksum;
-}
-#endif
-#endif
-
-
-
-
 void GetPlayerConfig()
 {
   if (!audio.sound_available)
@@ -324,6 +276,10 @@ static void InitField(int x, int y, boolean init_game)
          Feld[x][y] = EL_SP_MURPHY_CLONE;
          break;
        }
+       else
+       {
+         stored_player[0].use_murphy_graphic = TRUE;
+       }
 
        Feld[x][y] = EL_PLAYER1;
       }
@@ -519,16 +475,16 @@ void DrawGameDoorValues()
     for (j=0; j<4; j++)
       if (stored_player[i].key[j])
        DrawMiniGraphicExt(drawto, DX_KEYS + j * MINI_TILEX, DY_KEYS,
-                          IMG_KEY1 + j);
+                          el2edimg(EL_KEY1 + j));
 
   DrawText(DX + XX_EMERALDS, DY + YY_EMERALDS,
-          int2str(local_player->gems_still_needed, 3), FS_SMALL, FC_YELLOW);
+          int2str(local_player->gems_still_needed, 3), FONT_DEFAULT_SMALL);
   DrawText(DX + XX_DYNAMITE, DY + YY_DYNAMITE,
-          int2str(local_player->dynamite, 3), FS_SMALL, FC_YELLOW);
+          int2str(local_player->dynamite, 3), FONT_DEFAULT_SMALL);
   DrawText(DX + XX_SCORE, DY + YY_SCORE,
-          int2str(local_player->score, 5), FS_SMALL, FC_YELLOW);
+          int2str(local_player->score, 5), FONT_DEFAULT_SMALL);
   DrawText(DX + XX_TIME, DY + YY_TIME,
-          int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW);
+          int2str(TimeLeft, 3), FONT_DEFAULT_SMALL);
 }
 
 
@@ -689,6 +645,10 @@ void InitGame()
     player->GfxPos = 0;
     player->Frame = 0;
 
+    player->GfxAction = ACTION_DEFAULT;
+
+    player->use_murphy_graphic = FALSE;
+
     player->actual_frame_counter = 0;
 
     player->frame_reset_delay = 0;
@@ -696,6 +656,9 @@ void InitGame()
     player->last_move_dir = MV_NO_MOVING;
     player->is_moving = FALSE;
 
+    player->is_moving = FALSE;
+    player->is_waiting = FALSE;
+
     player->move_delay       = game.initial_move_delay;
     player->move_delay_value = game.initial_move_delay_value;
 
@@ -773,6 +736,7 @@ void InitGame()
 
       GfxFrame[x][y] = 0;
       GfxAction[x][y] = ACTION_DEFAULT;
+      GfxRandom[x][y] = INIT_GFX_RANDOM();
     }
   }
 
@@ -949,14 +913,15 @@ void InitGame()
 
   if (level_nr < 100)
     DrawText(DX + XX_LEVEL, DY + YY_LEVEL,
-            int2str(level_nr, 2), FS_SMALL, FC_YELLOW);
+            int2str(level_nr, 2), FONT_DEFAULT_SMALL);
   else
   {
     DrawTextExt(drawto, DX + XX_EMERALDS, DY + YY_EMERALDS,
-               int2str(level_nr, 3), FS_SMALL, FC_SPECIAL3, FONT_OPAQUE);
+               int2str(level_nr, 3), FONT_SPECIAL_NARROW, FONT_OPAQUE);
     BlitBitmap(drawto, drawto,
               DX + XX_EMERALDS, DY + YY_EMERALDS + 1,
-              FONT5_XSIZE * 3, FONT5_YSIZE - 1,
+              getFontWidth(FONT_SPECIAL_NARROW) * 3,
+              getFontHeight(FONT_SPECIAL_NARROW) - 1,
               DX + XX_LEVEL - 1, DY + YY_LEVEL + 1);
   }
 
@@ -1150,7 +1115,7 @@ void GameWon()
        TimeLeft -= 10;
       else
        TimeLeft--;
-      DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW);
+      DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_DEFAULT_SMALL);
       BackToFront();
 
       if (!tape.playing)
@@ -1176,7 +1141,7 @@ void GameWon()
        TimePlayed += 10;
       else
        TimePlayed++;
-      DrawText(DX_TIME, DY_TIME, int2str(TimePlayed, 3), FS_SMALL, FC_YELLOW);
+      DrawText(DX_TIME, DY_TIME, int2str(TimePlayed, 3), FONT_DEFAULT_SMALL);
       BackToFront();
 
       if (!tape.playing)
@@ -1301,6 +1266,35 @@ int NewHiScore()
   return position;
 }
 
+static void ResetRandomAnimationValue(int x, int y)
+{
+  GfxRandom[x][y] = INIT_GFX_RANDOM();
+}
+
+static void ResetGfxAnimation(int x, int y)
+{
+#if 0
+#if 1
+  int element = Feld[x][y];
+  int graphic = el2img(element);
+
+  /* reset random value not until one full delay cycle was reached */
+  if (ANIM_MODE(graphic) == ANIM_RANDOM &&
+      GfxFrame[x][y] > ANIM_DELAY(graphic))
+#endif
+    ResetRandomAnimationValue(x, y);
+#endif
+
+  GfxFrame[x][y] = 0;
+  GfxAction[x][y] = ACTION_DEFAULT;
+
+#if 0
+  if (Feld[x][y] == EL_ROCK)
+    printf("ResetGfxAnimation: EL_ROCK [%d, %d]\n",
+          JustStopped[x][y], MovDir[x][y]);
+#endif
+}
+
 void InitMovingField(int x, int y, int direction)
 {
   int element = Feld[x][y];
@@ -1308,10 +1302,9 @@ void InitMovingField(int x, int y, int direction)
   int newy = y + (direction == MV_UP   ? -1 : direction == MV_DOWN  ? +1 : 0);
 
   if (!JustStopped[x][y] || direction != MovDir[x][y])
-    GfxFrame[x][y] = 0;
+    ResetGfxAnimation(x, y);
 
-  MovDir[x][y] = direction;
-  MovDir[newx][newy] = direction;
+  MovDir[newx][newy] = MovDir[x][y] = direction;
 
   if (Feld[newx][newy] == EL_EMPTY)
     Feld[newx][newy] = EL_BLOCKED;
@@ -1320,6 +1313,10 @@ void InitMovingField(int x, int y, int direction)
     GfxAction[x][y] = ACTION_FALLING;
   else
     GfxAction[x][y] = ACTION_MOVING;
+
+  GfxFrame[newx][newy] = GfxFrame[x][y];
+  GfxAction[newx][newy] = GfxAction[x][y];
+  GfxRandom[newx][newy] = GfxRandom[x][y];
 }
 
 void Moving2Blocked(int x, int y, int *goes_to_x, int *goes_to_y)
@@ -1460,17 +1457,15 @@ void DrawDynamite(int x, int y)
 
 void CheckDynamite(int x, int y)
 {
-  int element = Feld[x][y];
-
   if (MovDelay[x][y] != 0)     /* dynamite is still waiting to explode */
   {
     MovDelay[x][y]--;
 
     if (MovDelay[x][y] != 0)
     {
-      if (checkDrawLevelGraphicAnimation(x, y, el2img(element)))
-       DrawDynamite(x, y);
+      DrawDynamite(x, y);
 
+      /* !!! correct: "PlaySoundLevelActionIfLoop" etc. !!! */
       PlaySoundLevelAction(x, y, ACTION_ACTIVE);
 
       return;
@@ -1529,7 +1524,7 @@ void Explode(int ex, int ey, int phase, int mode)
        RemoveMovingField(x, y);
       }
 
-      if (IS_MASSIVE(element) || element == EL_FLAMES)
+      if (IS_INDESTRUCTIBLE(element) || element == EL_FLAMES)
        continue;
 
       if (IS_PLAYER(x, y) && SHIELD_ON(PLAYERINFO(x, y)))
@@ -1731,7 +1726,7 @@ void DynaExplode(int ex, int ey)
       int y = ey + j * xy[i % 4][1];
       int element;
 
-      if (!IN_LEV_FIELD(x, y) || IS_MASSIVE(Feld[x][y]))
+      if (!IN_LEV_FIELD(x, y) || IS_INDESTRUCTIBLE(Feld[x][y]))
        break;
 
       element = Feld[x][y];
@@ -1802,27 +1797,27 @@ void Bang(int x, int y)
   }
 }
 
-void Blurb(int x, int y)
+void SplashAcid(int x, int y)
 {
   int element = Feld[x][y];
 
   if (element != EL_ACID_SPLASH_LEFT &&
-      element != EL_ACID_SPLASH_RIGHT) /* start */
+      element != EL_ACID_SPLASH_RIGHT)
   {
     PlaySoundLevel(x, y, SND_ACID_SPLASHING);
+
     if (IN_LEV_FIELD(x-1, y) && IS_FREE(x-1, y) &&
        (!IN_LEV_FIELD(x-1, y-1) ||
         !CAN_FALL(MovingOrBlocked2Element(x-1, y-1))))
-    {
       Feld[x-1][y] = EL_ACID_SPLASH_LEFT;
-    }
+
     if (IN_LEV_FIELD(x+1, y) && IS_FREE(x+1, y) &&
        (!IN_LEV_FIELD(x+1, y-1) ||
         !CAN_FALL(MovingOrBlocked2Element(x+1, y-1))))
-    {
       Feld[x+1][y] = EL_ACID_SPLASH_RIGHT;
-    }
   }
+
+#if 0
   else                                                         /* go on */
   {
     int graphic = (element == EL_ACID_SPLASH_LEFT ?
@@ -1849,6 +1844,7 @@ void Blurb(int x, int y)
       }
     }
   }
+#endif
 }
 
 static void InitBeltMovement()
@@ -2163,18 +2159,29 @@ void Impact(int x, int y)
       return;
 
     object_hit = (!IS_FREE(x, y+1) && (!IS_MOVING(x, y+1) ||
-                                     MovDir[x][y+1]!=MV_DOWN ||
-                                     MovPos[x][y+1]<=TILEY/2));
+                                     MovDir[x][y+1] != MV_DOWN ||
+                                     MovPos[x][y+1] <= TILEY / 2));
     if (object_hit)
       smashed = MovingOrBlocked2Element(x, y+1);
   }
 
   if (!lastline && smashed == EL_ACID) /* element falls into acid */
   {
-    Blurb(x, y);
+    SplashAcid(x, y);
     return;
   }
 
+#if 1
+  if (lastline || object_hit)
+  {
+#if 0
+    MovDir[x][y] = 0;
+#endif
+    ResetGfxAnimation(x, y);
+    DrawLevelField(x, y);
+  }
+#endif
+
   if ((element == EL_BOMB ||
        element == EL_SP_DISK_ORANGE ||
        element == EL_DX_SUPABOMB) &&
@@ -2200,6 +2207,8 @@ void Impact(int x, int y)
     {
       Feld[x][y] = EL_AMOEBA_CREATING;
       Store[x][y] = EL_AMOEBA_WET;
+
+      ResetRandomAnimationValue(x, y);
     }
     return;
   }
@@ -2330,6 +2339,13 @@ void Impact(int x, int y)
     return;
   }
 
+#if 0
+  printf("::: -> %d,%d [%d]\n", element, ACTION_IMPACT,
+        element_info[element].sound[ACTION_IMPACT]);
+
+  PlaySound(177);
+#endif
+
   /* play sound of object that hits the ground */
   if (lastline || object_hit)
     PlaySoundLevelElementAction(x, y, element, ACTION_IMPACT);
@@ -2903,14 +2919,22 @@ void StartMoving(int x, int y)
         EL_BD_MAGIC_WALL_FILLING);
       Store[x][y] = element;
     }
+#if 0
     else if (CAN_SMASH(element) && Feld[x][y+1] == EL_ACID)
+#else
+    else if (CAN_FALL(element) && Feld[x][y+1] == EL_ACID)
+#endif
     {
-      Blurb(x, y);
+      SplashAcid(x, y);
 
       InitMovingField(x, y, MV_DOWN);
       started_moving = TRUE;
 
       Store[x][y] = EL_ACID;
+#if 0
+      /* !!! TEST !!! better use "_FALLING" etc. !!! */
+      GfxAction[x][y+1] = ACTION_ACTIVE;
+#endif
     }
     else if (CAN_SMASH(element) && Feld[x][y+1] == EL_BLOCKED &&
             JustStopped[x][y])
@@ -2927,6 +2951,9 @@ void StartMoving(int x, int y)
     }
     else if (IS_FREE(x, y+1))
     {
+      if (JustStopped[x][y])   /* prevent animation from being restarted */
+       MovDir[x][y] = MV_DOWN;
+
       InitMovingField(x, y, MV_DOWN);
       started_moving = TRUE;
     }
@@ -3044,8 +3071,12 @@ void StartMoving(int x, int y)
       MovDelay[x][y]--;
 
       if (element == EL_ROBOT ||
-         element == EL_YAMYAM || element == EL_DARK_YAMYAM)
+         element == EL_YAMYAM ||
+         element == EL_DARK_YAMYAM)
       {
+#if 1
+       DrawLevelElementAnimationIfNeeded(x, y, element);
+#else
        if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
        {
          int graphic = el2img(element);
@@ -3053,7 +3084,11 @@ void StartMoving(int x, int y)
 
          DrawGraphic(SCREENX(x), SCREENY(y), graphic, frame);
        }
+#endif
 
+#if 1
+       PlaySoundLevelAction(x, y, ACTION_WAITING);
+#else
        if (MovDelay[x][y] % 4 == 3)
        {
          if (element == EL_YAMYAM)
@@ -3061,9 +3096,10 @@ void StartMoving(int x, int y)
          else if (element == EL_DARK_YAMYAM)
            PlaySoundLevel(x, y, SND_DARK_YAMYAM_WAITING);
        }
+#endif
       }
       else if (element == EL_SP_ELECTRON)
-       DrawLevelElementAnimation(x, y, element);
+       DrawLevelElementAnimationIfNeeded(x, y, element);
       else if (element == EL_DRAGON)
       {
        int i;
@@ -3140,7 +3176,7 @@ void StartMoving(int x, int y)
             IN_LEV_FIELD(newx, newy) &&
             MovDir[x][y] == MV_DOWN && Feld[newx][newy] == EL_ACID)
     {
-      Blurb(x, y);
+      SplashAcid(x, y);
       Store[x][y] = EL_ACID;
     }
     else if (element == EL_PENGUIN && IN_LEV_FIELD(newx, newy))
@@ -3321,11 +3357,11 @@ void StartMoving(int x, int y)
               element == EL_SP_SNIKSNAK || element == EL_MOLE)
        DrawLevelField(x, y);
       else if (element == EL_BD_BUTTERFLY || element == EL_BD_FIREFLY)
-       DrawLevelElementAnimation(x, y, element);
+       DrawLevelElementAnimationIfNeeded(x, y, element);
       else if (element == EL_SATELLITE)
-       DrawLevelElementAnimation(x, y, element);
+       DrawLevelElementAnimationIfNeeded(x, y, element);
       else if (element == EL_SP_ELECTRON)
-       DrawLevelElementAnimation(x, y, element);
+       DrawLevelElementAnimationIfNeeded(x, y, element);
 
       if (DONT_TOUCH(element))
        TestIfBadThingTouchesHero(x, y);
@@ -3460,9 +3496,20 @@ void ContinueMoving(int x, int y)
     MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0;
     MovDelay[newx][newy] = 0;
 
+#if 0
+    /* all done in "InitMovingField()" */
     GfxAction[newx][newy] = GfxAction[x][y];   /* keep action one frame */
-    GfxAction[x][y] = ACTION_DEFAULT;
+    GfxRandom[newx][newy] = GfxRandom[x][y];   /* keep same random value */
+#endif
 
+    /* copy animation control values to new field */
+    GfxFrame[newx][newy]  = GfxFrame[x][y];
+    GfxAction[newx][newy] = GfxAction[x][y];
+    GfxRandom[newx][newy] = GfxRandom[x][y];
+
+    ResetGfxAnimation(x, y);   /* reset animation values for old field */
+
+#if 1
 #if 0
     if (!CAN_MOVE(element))
       MovDir[newx][newy] = 0;
@@ -3475,6 +3522,7 @@ void ContinueMoving(int x, int y)
     if (!CAN_MOVE(element) ||
        (element == EL_SPRING && MovDir[newx][newy] == MV_DOWN))
       MovDir[newx][newy] = 0;
+#endif
 #endif
 
     DrawLevelField(x, y);
@@ -3999,38 +4047,6 @@ static void StopRobotWheel(int x, int y)
     ZX = ZY = -1;
 }
 
-#if 1
-void RobotWheel(int x, int y)
-{
-  if (!MovDelay[x][y])         /* next animation frame */
-    MovDelay[x][y] = level.time_wheel * FRAMES_PER_SECOND;
-
-  if (MovDelay[x][y])          /* wait some time before next frame */
-  {
-    MovDelay[x][y]--;
-    if (MovDelay[x][y])
-    {
-      if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
-      {
-       int frame = getGraphicAnimationFrame(IMG_ROBOT_WHEEL_ACTIVE, -1);
-
-       DrawGraphic(SCREENX(x), SCREENY(y), IMG_ROBOT_WHEEL_ACTIVE, frame);
-      }
-
-      PlaySoundLevel(x, y, SND_ROBOT_WHEEL_ACTIVE);
-
-      return;
-    }
-  }
-
-  Feld[x][y] = EL_ROBOT_WHEEL;
-  DrawLevelField(x, y);
-
-  if (ZX == x && ZY == y)
-    ZX = ZY = -1;
-}
-#endif
-
 static void InitTimegateWheel(int x, int y)
 {
   MovDelay[x][y] = level.time_wheel * FRAMES_PER_SECOND;
@@ -4041,106 +4057,6 @@ static void RunTimegateWheel(int x, int y)
   PlaySoundLevel(x, y, SND_TIMEGATE_SWITCH_ACTIVE);
 }
 
-#if 1
-void TimegateWheel(int x, int y)
-{
-  if (!MovDelay[x][y])         /* next animation frame */
-    MovDelay[x][y] = level.time_wheel * FRAMES_PER_SECOND;
-
-  if (MovDelay[x][y])          /* wait some time before next frame */
-  {
-    MovDelay[x][y]--;
-    if (MovDelay[x][y])
-    {
-      if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
-      {
-       int frame = getGraphicAnimationFrame(IMG_TIMEGATE_SWITCH_ACTIVE, -1);
-
-       DrawGraphic(SCREENX(x), SCREENY(y), IMG_TIMEGATE_SWITCH_ACTIVE, frame);
-      }
-
-      PlaySoundLevel(x, y, SND_TIMEGATE_SWITCH_ACTIVE);
-
-      return;
-    }
-  }
-
-  Feld[x][y] = EL_TIMEGATE_SWITCH;
-  DrawLevelField(x, y);
-
-  /* THIS HAS NO EFFECT AT ALL! */
-#if 1
-  /* !!! THIS LOOKS WRONG !!! */
-  if (ZX == x && ZY == y)
-    ZX = ZY = -1;
-#endif
-
-}
-#endif
-
-#if 1
-void NussKnacken(int x, int y)
-{
-  if (!MovDelay[x][y])         /* next animation frame */
-    MovDelay[x][y] = 7;
-
-  if (MovDelay[x][y])          /* wait some time before next frame */
-  {
-    MovDelay[x][y]--;
-    if (MovDelay[x][y])
-    {
-      if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
-      {
-       int frame = getGraphicAnimationFrame(IMG_NUT_CRACKING,
-                                            6 - MovDelay[x][y]);
-
-       DrawGraphic(SCREENX(x), SCREENY(y), IMG_NUT_CRACKING, frame);
-      }
-
-      return;
-    }
-  }
-
-  Feld[x][y] = EL_EMERALD;
-  DrawLevelField(x, y);
-}
-#endif
-
-#if 1
-void BreakingPearl(int x, int y)
-{
-  if (!MovDelay[x][y])         /* next animation frame */
-    MovDelay[x][y] = 9;
-
-  if (MovDelay[x][y])          /* wait some time before next frame */
-  {
-    MovDelay[x][y]--;
-    if (MovDelay[x][y])
-    {
-      if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
-      {
-       int frame = getGraphicAnimationFrame(IMG_PEARL_BREAKING,
-                                            8 - MovDelay[x][y]);
-
-       DrawGraphic(SCREENX(x), SCREENY(y), IMG_PEARL_BREAKING, frame);
-      }
-
-      return;
-    }
-  }
-
-  Feld[x][y] = EL_EMPTY;
-  DrawLevelField(x, y);
-}
-#endif
-
-void SiebAktivieren(int x, int y, int type)
-{
-  int graphic = (type == 1 ? IMG_MAGIC_WALL_FULL : IMG_BD_MAGIC_WALL_FULL);
-
-  DrawLevelGraphicAnimation(x, y, graphic);
-}
-
 void CheckExit(int x, int y)
 {
   if (local_player->gems_still_needed > 0 ||
@@ -4163,169 +4079,6 @@ void CheckExitSP(int x, int y)
   PlaySoundLevelNearest(x, y, SND_SP_EXIT_OPENING);
 }
 
-#if 1
-void AusgangstuerOeffnen(int x, int y)
-{
-  int delay = 6;
-
-  if (!MovDelay[x][y])         /* next animation frame */
-    MovDelay[x][y] = 5 * delay;
-
-  if (MovDelay[x][y])          /* wait some time before next frame */
-  {
-    int tuer;
-
-    MovDelay[x][y]--;
-    tuer = MovDelay[x][y] / delay;
-
-    if (!(MovDelay[x][y] % delay))
-    {
-      if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
-      {
-       int frame = getGraphicAnimationFrame(IMG_EXIT_OPENING,
-                                            29 - MovDelay[x][y]);
-
-       DrawGraphic(SCREENX(x), SCREENY(y), IMG_EXIT_OPENING, frame);
-      }
-    }
-
-    if (MovDelay[x][y])
-      return;
-  }
-
-  Feld[x][y] = EL_EXIT_OPEN;
-  DrawLevelField(x, y);
-}
-#endif
-
-#if 1
-void OpenSwitchgate(int x, int y)
-{
-  int delay = 6;
-
-  if (!MovDelay[x][y])         /* next animation frame */
-    MovDelay[x][y] = 5 * delay;
-
-  if (MovDelay[x][y])          /* wait some time before next frame */
-  {
-    MovDelay[x][y]--;
-
-    if (!(MovDelay[x][y] % delay))
-    {
-      if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
-      {
-       int frame = getGraphicAnimationFrame(IMG_SWITCHGATE_OPENING,
-                                            29 - MovDelay[x][y]);
-
-       DrawGraphic(SCREENX(x), SCREENY(y), IMG_SWITCHGATE_OPENING, frame);
-      }
-    }
-
-    if (MovDelay[x][y])
-      return;
-  }
-
-  Feld[x][y] = EL_SWITCHGATE_OPEN;
-  DrawLevelField(x, y);
-}
-#endif
-
-#if 1
-void CloseSwitchgate(int x, int y)
-{
-  int delay = 6;
-
-  if (!MovDelay[x][y])         /* next animation frame */
-    MovDelay[x][y] = 5 * delay;
-
-  if (MovDelay[x][y])          /* wait some time before next frame */
-  {
-    MovDelay[x][y]--;
-
-    if (!(MovDelay[x][y] % delay))
-    {
-      if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
-      {
-       int frame = getGraphicAnimationFrame(IMG_SWITCHGATE_CLOSING,
-                                            29 - MovDelay[x][y]);
-
-       DrawGraphic(SCREENX(x), SCREENY(y), IMG_SWITCHGATE_CLOSING, frame);
-      }
-    }
-
-    if (MovDelay[x][y])
-      return;
-  }
-
-  Feld[x][y] = EL_SWITCHGATE_CLOSED;
-  DrawLevelField(x, y);
-}
-#endif
-
-#if 1
-void OpenTimegate(int x, int y)
-{
-  int delay = 6;
-
-  if (!MovDelay[x][y])         /* next animation frame */
-    MovDelay[x][y] = 5 * delay;
-
-  if (MovDelay[x][y])          /* wait some time before next frame */
-  {
-    MovDelay[x][y]--;
-
-    if (!(MovDelay[x][y] % delay))
-    {
-      if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
-      {
-       int frame = getGraphicAnimationFrame(IMG_TIMEGATE_OPENING,
-                                            29 - MovDelay[x][y]);
-
-       DrawGraphic(SCREENX(x), SCREENY(y), IMG_TIMEGATE_OPENING, frame);
-      }
-    }
-
-    if (MovDelay[x][y])
-      return;
-  }
-
-  Feld[x][y] = EL_TIMEGATE_OPEN;
-  DrawLevelField(x, y);
-}
-#endif
-
-#if 1
-void CloseTimegate(int x, int y)
-{
-  int delay = 6;
-
-  if (!MovDelay[x][y])         /* next animation frame */
-    MovDelay[x][y] = 5 * delay;
-
-  if (MovDelay[x][y])          /* wait some time before next frame */
-  {
-    MovDelay[x][y]--;
-
-    if (!(MovDelay[x][y] % delay))
-    {
-      if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
-      {
-       int frame = getGraphicAnimationFrame(IMG_TIMEGATE_CLOSING,
-                                            29 - MovDelay[x][y]);
-
-       DrawGraphic(SCREENX(x), SCREENY(y), IMG_TIMEGATE_CLOSING, frame);
-      }
-    }
-
-    if (MovDelay[x][y])
-      return;
-  }
-
-  Feld[x][y] = EL_TIMEGATE_CLOSED;
-  DrawLevelField(x, y);
-}
-#endif
-
 static void CloseAllOpenTimegates()
 {
   int x, y;
@@ -4634,79 +4387,6 @@ static void WarnBuggyBase(int x, int y)
   }
 }
 
-#if 1
-void CheckBuggyBase(int x, int y)
-{
-  int element = Feld[x][y];
-
-  if (element == EL_SP_BUGGY_BASE)
-  {
-    if (MovDelay[x][y] == 0)   /* wait some time before activating base */
-    {
-      GfxFrame[x][y] = 0;
-
-      InitBuggyBase(x, y);
-    }
-
-    MovDelay[x][y]--;
-
-    if (MovDelay[x][y] != 0)
-    {
-      DrawLevelElementAnimation(x, y, element);
-    }
-    else
-    {
-      Feld[x][y] = EL_SP_BUGGY_BASE_ACTIVATING;
-      DrawLevelField(x, y);
-    }
-  }
-  else if (element == EL_SP_BUGGY_BASE_ACTIVATING)
-  {
-    if (MovDelay[x][y] == 0)   /* display activation warning of buggy base */
-    {
-      GfxFrame[x][y] = 0;
-
-      InitBuggyBase(x, y);
-    }
-
-    MovDelay[x][y]--;
-
-    if (MovDelay[x][y] != 0)
-    {
-      DrawLevelElementAnimation(x, y, element);
-    }
-    else
-    {
-      Feld[x][y] = EL_SP_BUGGY_BASE_ACTIVE;
-      DrawLevelField(x, y);
-    }
-  }
-  else if (element == EL_SP_BUGGY_BASE_ACTIVE)
-  {
-    if (MovDelay[x][y] == 0)   /* start activating buggy base */
-    {
-      GfxFrame[x][y] = 0;
-
-      InitBuggyBase(x, y);
-    }
-
-    MovDelay[x][y]--;
-
-    if (MovDelay[x][y] != 0)
-    {
-      DrawLevelElementAnimation(x, y, element);
-
-      WarnBuggyBase(x, y);
-    }
-    else
-    {
-      Feld[x][y] = EL_SP_BUGGY_BASE;
-      DrawLevelField(x, y);
-    }
-  }
-}
-#endif
-
 static void InitTrap(int x, int y)
 {
   MovDelay[x][y] = 2 * FRAMES_PER_SECOND + RND(5 * FRAMES_PER_SECOND);
@@ -4721,76 +4401,10 @@ static void ChangeActiveTrap(int x, int y)
 {
   int graphic = IMG_TRAP_ACTIVE;
 
-  /* if animation frame already drawn, correct crumbled sand border */
-  if (IS_ANIMATED(graphic))
-    if (checkDrawLevelGraphicAnimation(x, y, graphic))
-      DrawCrumbledSand(SCREENX(x), SCREENY(y));
-}
-
-#if 1
-void CheckTrap(int x, int y)
-{
-  int element = Feld[x][y];
-
-  if (element == EL_TRAP)
-  {
-    if (MovDelay[x][y] == 0)   /* wait some time before activating trap */
-      MovDelay[x][y] = 2 * FRAMES_PER_SECOND + RND(5 * FRAMES_PER_SECOND);
-
-    MovDelay[x][y]--;
-
-    if (MovDelay[x][y] != 0)
-    {
-      /* do nothing while waiting */
-    }
-    else
-    {
-      Feld[x][y] = EL_TRAP_ACTIVE;
-      PlaySoundLevel(x, y, SND_TRAP_ACTIVATING);
-    }
-  }
-  else if (element == EL_TRAP_ACTIVE)
-  {
-    int delay = 4;
-    int num_frames = 8;
-
-    if (MovDelay[x][y] == 0)   /* start activating trap */
-    {
-      MovDelay[x][y] = num_frames * delay;
-      GfxFrame[x][y] = 0;
-    }
-
-    MovDelay[x][y]--;
-
-    if (MovDelay[x][y] != 0)
-    {
-      if (DrawLevelElementAnimation(x, y, element))
-       DrawCrumbledSand(SCREENX(x), SCREENY(y));
-    }
-    else
-    {
-      Feld[x][y] = EL_TRAP;
-      DrawLevelField(x, y);
-    }
-  }
-}
-#endif
-
-#if 1
-static void DrawBeltAnimation(int x, int y, int element)
-{
-  int belt_nr = getBeltNrFromBeltActiveElement(element);
-  int belt_dir = game.belt_dir[belt_nr];
-
-  if (belt_dir != MV_NO_MOVING)
-  {
-    DrawLevelElementAnimation(x, y, element);
-
-    if (!(FrameCounter % 2))
-      PlaySoundLevelAction(x, y, ACTION_ACTIVE);
-  }
+  /* if new animation frame was drawn, correct crumbled sand border */
+  if (IS_NEW_FRAME(GfxFrame[x][y], graphic))
+    DrawCrumbledSand(SCREENX(x), SCREENY(y));
 }
-#endif
 
 static void ChangeElement(int x, int y)
 {
@@ -4799,7 +4413,9 @@ static void ChangeElement(int x, int y)
   if (MovDelay[x][y] == 0)             /* initialize element change */
   {
     MovDelay[x][y] = changing_element[element].change_delay + 1;
-    GfxFrame[x][y] = 0;
+
+    ResetGfxAnimation(x, y);
+    ResetRandomAnimationValue(x, y);
 
     if (changing_element[element].pre_change_function)
       changing_element[element].pre_change_function(x, y);
@@ -4810,7 +4426,7 @@ static void ChangeElement(int x, int y)
   if (MovDelay[x][y] != 0)             /* continue element change */
   {
     if (IS_ANIMATED(el2img(element)))
-      DrawLevelElementAnimation(x, y, element);
+      DrawLevelElementAnimationIfNeeded(x, y, element);
 
     if (changing_element[element].change_function)
       changing_element[element].change_function(x, y);
@@ -4818,7 +4434,9 @@ static void ChangeElement(int x, int y)
   else                                 /* finish element change */
   {
     Feld[x][y] = changing_element[element].next_element;
-    GfxFrame[x][y] = 0;
+
+    ResetGfxAnimation(x, y);
+    ResetRandomAnimationValue(x, y);
 
     DrawLevelField(x, y);
 
@@ -4972,7 +4590,7 @@ void GameActions()
 {
   static unsigned long action_delay = 0;
   unsigned long action_delay_value;
-  int sieb_x = 0, sieb_y = 0;
+  int magic_wall_x = 0, magic_wall_y = 0;
   int i, x, y, element, graphic;
   byte *recorded_player_action;
   byte summarized_player_action = 0;
@@ -5110,12 +4728,23 @@ void GameActions()
     element = Feld[x][y];
     graphic = el2img(element);
 
+#if 1
+    if (graphic_info[graphic].anim_global_sync)
+      GfxFrame[x][y] = FrameCounter;
+#endif
+
+    if (ANIM_MODE(graphic) == ANIM_RANDOM &&
+       IS_NEXT_FRAME(GfxFrame[x][y], graphic))
+      ResetRandomAnimationValue(x, y);
+
+    SetRandomAnimationValue(x, y);
+
     if (IS_INACTIVE(element))
     {
 
 #if 1
       if (IS_ANIMATED(graphic))
-       DrawLevelGraphicAnimation(x, y, graphic);
+       DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
 #endif
 
       continue;
@@ -5125,18 +4754,10 @@ void GameActions()
     {
       StartMoving(x, y);
 
-#if 1
-#if 0
-      if (Feld[x][y] == EL_EMERALD &&
-         IS_ANIMATED(graphic) &&
-         !IS_MOVING(x, y))
-       DrawLevelGraphicAnimation(x, y, graphic);
-#else
       if (IS_ANIMATED(graphic) &&
-         !IS_MOVING(x, y))
-       DrawLevelGraphicAnimation(x, y, graphic);
-#endif
-#endif
+         !IS_MOVING(x, y) &&
+         !Stop[x][y])
+       DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
 
       if (IS_GEM(element) || element == EL_SP_INFOTRON)
        EdelsteinFunkeln(x, y);
@@ -5152,7 +4773,7 @@ void GameActions()
              element == EL_SHIELD_NORMAL ||
              element == EL_SHIELD_DEADLY) &&
             IS_ANIMATED(graphic))
-      DrawLevelGraphicAnimation(x, y, graphic);
+      DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
 #endif
 
     else if (IS_MOVING(x, y))
@@ -5181,9 +4802,11 @@ void GameActions()
     else if (element == EL_TIMEGATE_SWITCH_ACTIVE)
       TimegateWheel(x, y);
 #endif
+#if 0
     else if (element == EL_ACID_SPLASH_LEFT ||
             element == EL_ACID_SPLASH_RIGHT)
-      Blurb(x, y);
+      SplashAcid(x, y);
+#endif
 #if 0
     else if (element == EL_NUT_CRACKING)
       NussKnacken(x, y);
@@ -5234,7 +4857,7 @@ void GameActions()
     else if (element == EL_EXPLOSION)
       ;        /* drawing of correct explosion animation is handled separately */
     else if (IS_ANIMATED(graphic))
-      DrawLevelGraphicAnimation(x, y, graphic);
+      DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
 #endif
 
     if (IS_BELT_ACTIVE(element))
@@ -5242,29 +4865,19 @@ void GameActions()
 
     if (game.magic_wall_active)
     {
-      boolean sieb = FALSE;
       int jx = local_player->jx, jy = local_player->jy;
 
-      if (element == EL_MAGIC_WALL_FULL ||
-         element == EL_MAGIC_WALL_ACTIVE ||
-         element == EL_MAGIC_WALL_EMPTYING)
-      {
-       SiebAktivieren(x, y, 1);
-       sieb = TRUE;
-      }
-      else if (element == EL_BD_MAGIC_WALL_FULL ||
-              element == EL_BD_MAGIC_WALL_ACTIVE ||
-              element == EL_BD_MAGIC_WALL_EMPTYING)
-      {
-       SiebAktivieren(x, y, 2);
-       sieb = TRUE;
-      }
-
       /* play the element sound at the position nearest to the player */
-      if (sieb && ABS(x-jx)+ABS(y-jy) < ABS(sieb_x-jx)+ABS(sieb_y-jy))
+      if ((element == EL_MAGIC_WALL_FULL ||
+          element == EL_MAGIC_WALL_ACTIVE ||
+          element == EL_MAGIC_WALL_EMPTYING ||
+          element == EL_BD_MAGIC_WALL_FULL ||
+          element == EL_BD_MAGIC_WALL_ACTIVE ||
+          element == EL_BD_MAGIC_WALL_EMPTYING) &&
+         ABS(x-jx) + ABS(y-jy) < ABS(magic_wall_x-jx) + ABS(magic_wall_y-jy))
       {
-       sieb_x = x;
-       sieb_y = y;
+       magic_wall_x = x;
+       magic_wall_y = y;
       }
     }
   }
@@ -5332,14 +4945,14 @@ void GameActions()
   {
     if (!(game.magic_wall_time_left % 4))
     {
-      int element = Feld[sieb_x][sieb_y];
+      int element = Feld[magic_wall_x][magic_wall_y];
 
       if (element == EL_BD_MAGIC_WALL_FULL ||
          element == EL_BD_MAGIC_WALL_ACTIVE ||
          element == EL_BD_MAGIC_WALL_EMPTYING)
-       PlaySoundLevel(sieb_x, sieb_y, SND_BD_MAGIC_WALL_ACTIVE);
+       PlaySoundLevel(magic_wall_x, magic_wall_y, SND_BD_MAGIC_WALL_ACTIVE);
       else
-       PlaySoundLevel(sieb_x, sieb_y, SND_MAGIC_WALL_ACTIVE);
+       PlaySoundLevel(magic_wall_x, magic_wall_y, SND_MAGIC_WALL_ACTIVE);
     }
 
     if (game.magic_wall_time_left > 0)
@@ -5427,14 +5040,14 @@ void GameActions()
       if (TimeLeft <= 10 && setup.time_limit)
        PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MAX_RIGHT);
 
-      DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW);
+      DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_DEFAULT_SMALL);
 
       if (!TimeLeft && setup.time_limit)
        for (i=0; i<MAX_PLAYERS; i++)
          KillHero(&stored_player[i]);
     }
     else if (level.time == 0 && !AllPlayersGone) /* level without time limit */
-      DrawText(DX_TIME, DY_TIME, int2str(TimePlayed, 3), FS_SMALL, FC_YELLOW);
+      DrawText(DX_TIME, DY_TIME, int2str(TimePlayed, 3), FONT_DEFAULT_SMALL);
   }
 
   DrawAllPlayers();
@@ -5588,7 +5201,7 @@ boolean MoveFigureOneStep(struct PlayerInfo *player,
   {
     if (element == EL_ACID && dx == 0 && dy == 1)
     {
-      Blurb(jx, jy);
+      SplashAcid(jx, jy);
       Feld[jx][jy] = EL_PLAYER1;
       InitMovingField(jx, jy, MV_DOWN);
       Store[jx][jy] = EL_ACID;
@@ -6183,6 +5796,8 @@ int DigField(struct PlayerInfo *player,
                        dy == +1 ? MV_DOWN : MV_NO_MOVING);
   int element;
 
+  player->is_digging = FALSE;
+
   if (player->MovPos == 0)
     player->Pushing = FALSE;
 
@@ -6260,7 +5875,7 @@ int DigField(struct PlayerInfo *player,
       RaiseScoreElement(element);
       DrawText(DX_EMERALDS, DY_EMERALDS,
               int2str(local_player->gems_still_needed, 3),
-              FS_SMALL, FC_YELLOW);
+              FONT_DEFAULT_SMALL);
       PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING);
       break;
 
@@ -6280,7 +5895,7 @@ int DigField(struct PlayerInfo *player,
       if (level.time > 0)
       {
        TimeLeft += 10;
-       DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW);
+       DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_DEFAULT_SMALL);
       }
       PlaySoundStereo(SND_EXTRA_TIME_COLLECTING, SOUND_MAX_RIGHT);
       break;
@@ -6304,8 +5919,7 @@ int DigField(struct PlayerInfo *player,
       player->dynamite++;
       RaiseScoreElement(EL_DYNAMITE);
       DrawText(DX_DYNAMITE, DY_DYNAMITE,
-              int2str(local_player->dynamite, 3),
-              FS_SMALL, FC_YELLOW);
+              int2str(local_player->dynamite, 3), FONT_DEFAULT_SMALL);
       PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING);
       break;
 
@@ -6337,14 +5951,15 @@ int DigField(struct PlayerInfo *player,
     case EL_KEY4:
     {
       int key_nr = element - EL_KEY1;
+      int graphic = el2edimg(element);
 
       RemoveField(x, y);
       player->key[key_nr] = TRUE;
       RaiseScoreElement(element);
       DrawMiniGraphicExt(drawto, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS,
-                        IMG_KEY1 + key_nr);
+                        graphic);
       DrawMiniGraphicExt(window, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS,
-                        IMG_KEY1 + key_nr);
+                        graphic);
       PlaySoundLevel(x, y, SND_KEY_COLLECTING);
       break;
     }
@@ -6355,14 +5970,15 @@ int DigField(struct PlayerInfo *player,
     case EL_EM_KEY4:
     {
       int key_nr = element - EL_EM_KEY1;
+      int graphic = el2edimg(EL_KEY1 + key_nr);
 
       RemoveField(x, y);
       player->key[key_nr] = TRUE;
       RaiseScoreElement(element);
       DrawMiniGraphicExt(drawto, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS,
-                        IMG_KEY1 + key_nr);
+                        graphic);
       DrawMiniGraphicExt(window, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS,
-                        IMG_KEY1 + key_nr);
+                        graphic);
       PlaySoundLevel(x, y, SND_KEY_COLLECTING);
       break;
     }
@@ -6478,7 +6094,9 @@ int DigField(struct PlayerInfo *player,
     case EL_SPRING:
       if (mode == DF_SNAP)
        return MF_NO_ACTION;
+
       /* no "break" -- fall through to next case */
+
       /* the following elements can be pushed by "snapping" */
     case EL_BD_ROCK:
       if (dy)
@@ -6499,7 +6117,8 @@ int DigField(struct PlayerInfo *player,
        player->push_delay = FrameCounter;
 #if 0
       if (!FrameReached(&player->push_delay, player->push_delay_value) &&
-         !tape.playing && element != EL_SPRING)
+         !tape.playing &&
+         element != EL_SPRING)
        return MF_NO_ACTION;
 #else
       if (!FrameReached(&player->push_delay, player->push_delay_value) &&
@@ -6705,7 +6324,7 @@ int DigField(struct PlayerInfo *player,
     case EL_TIME_ORB_FULL:
       Feld[x][y] = EL_TIME_ORB_EMPTY;
       TimeLeft += 10;
-      DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW);
+      DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_DEFAULT_SMALL);
       DrawLevelField(x, y);
       PlaySoundStereo(SND_TIME_ORB_FULL_COLLECTING, SOUND_MAX_RIGHT);
       return MF_ACTION;
@@ -6810,11 +6429,56 @@ int DigField(struct PlayerInfo *player,
       break;
 
     default:
+      if (IS_PUSHABLE(element))
+      {
+       if (mode == DF_SNAP)
+         return MF_NO_ACTION;
+
+       if (CAN_FALL(element) && dy)
+         return MF_NO_ACTION;
+
+       player->Pushing = TRUE;
+
+       if (!IN_LEV_FIELD(x+dx, y+dy) || !IS_FREE(x+dx, y+dy))
+         return MF_NO_ACTION;
+
+       if (dx && real_dy)
+       {
+         if (IN_LEV_FIELD(jx, jy+real_dy) && !IS_SOLID(Feld[jx][jy+real_dy]))
+           return MF_NO_ACTION;
+       }
+       else if (dy && real_dx)
+       {
+         if (IN_LEV_FIELD(jx+real_dx, jy) && !IS_SOLID(Feld[jx+real_dx][jy]))
+           return MF_NO_ACTION;
+       }
+
+       if (player->push_delay == 0)
+         player->push_delay = FrameCounter;
+
+       if (!FrameReached(&player->push_delay, player->push_delay_value) &&
+           !(tape.playing && tape.file_version < FILE_VERSION_2_0))
+         return MF_NO_ACTION;
+
+       RemoveField(x, y);
+       Feld[x + dx][y + dy] = element;
+
+       player->push_delay_value = 2 + RND(8);
+
+       DrawLevelField(x + dx, y + dy);
+       PlaySoundLevelElementAction(x, y, element, ACTION_PUSHING);
+
+       break;
+      }
+
       return MF_NO_ACTION;
   }
 
   player->push_delay = 0;
 
+  if (Feld[x][y] != element)           /* really digged something */
+    player->is_digging = TRUE;
+
   return MF_MOVING;
 }
 
@@ -6835,6 +6499,7 @@ boolean SnapField(struct PlayerInfo *player, int dx, int dy)
       player->Pushing = FALSE;
 
     player->snapped = FALSE;
+    player->is_digging = FALSE;
     return FALSE;
   }
 
@@ -6850,6 +6515,7 @@ boolean SnapField(struct PlayerInfo *player, int dx, int dy)
     return FALSE;
 
   player->snapped = TRUE;
+  player->is_digging = FALSE;
   DrawLevelField(x, y);
   BackToFront();
 
@@ -6874,7 +6540,9 @@ boolean PlaceBomb(struct PlayerInfo *player)
     Store[jx][jy] = element;
 
   MovDelay[jx][jy] = 96;
-  GfxFrame[jx][jy] = 0;
+
+  ResetGfxAnimation(jx, jy);
+  ResetRandomAnimationValue(jx, jy);
 
   if (player->dynamite)
   {
@@ -6882,7 +6550,7 @@ boolean PlaceBomb(struct PlayerInfo *player)
     player->dynamite--;
 
     DrawText(DX_DYNAMITE, DY_DYNAMITE, int2str(local_player->dynamite, 3),
-            FS_SMALL, FC_YELLOW);
+            FONT_DEFAULT_SMALL);
     if (IN_SCR_FIELD(SCREENX(jx), SCREENY(jy)))
     {
       if (game.emulation == EMU_SUPAPLEX)
@@ -7001,7 +6669,7 @@ void RaiseScore(int value)
 {
   local_player->score += value;
   DrawText(DX_SCORE, DY_SCORE, int2str(local_player->score, 5),
-          FS_SMALL, FC_YELLOW);
+          FONT_DEFAULT_SMALL);
 }
 
 void RaiseScoreElement(int element)