rnd-20030304-1-src
[rocksndiamonds.git] / src / game.c
index 48ec54275ed16ea36422b6c148ea4005f45be4e9..c95f398b8b51908de424165fdba307b8e0e4a708 100644 (file)
 
 #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);
@@ -276,6 +274,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;
       }
@@ -471,16 +473,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_TEXT_2);
   DrawText(DX + XX_DYNAMITE, DY + YY_DYNAMITE,
-          int2str(local_player->dynamite, 3), FS_SMALL, FC_YELLOW);
+          int2str(local_player->dynamite, 3), FONT_TEXT_2);
   DrawText(DX + XX_SCORE, DY + YY_SCORE,
-          int2str(local_player->score, 5), FS_SMALL, FC_YELLOW);
+          int2str(local_player->score, 5), FONT_TEXT_2);
   DrawText(DX + XX_TIME, DY + YY_TIME,
-          int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW);
+          int2str(TimeLeft, 3), FONT_TEXT_2);
 }
 
 
@@ -641,13 +643,19 @@ void InitGame()
     player->GfxPos = 0;
     player->Frame = 0;
 
-    player->actual_frame_counter = 0;
+    player->GfxAction = ACTION_DEFAULT;
 
-    player->frame_reset_delay = 0;
+    player->use_murphy_graphic = FALSE;
+    player->use_disk_red_graphic = FALSE;
+
+    player->actual_frame_counter = 0;
 
     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;
 
@@ -901,15 +909,15 @@ void InitGame()
             DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, DX, DY);
 
   if (level_nr < 100)
-    DrawText(DX + XX_LEVEL, DY + YY_LEVEL,
-            int2str(level_nr, 2), FS_SMALL, FC_YELLOW);
+    DrawText(DX + XX_LEVEL, DY + YY_LEVEL, int2str(level_nr, 2), FONT_TEXT_2);
   else
   {
     DrawTextExt(drawto, DX + XX_EMERALDS, DY + YY_EMERALDS,
-               int2str(level_nr, 3), FS_SMALL, FC_SPECIAL3, FONT_OPAQUE);
+               int2str(level_nr, 3), FONT_LEVEL_NUMBER, FONT_OPAQUE);
     BlitBitmap(drawto, drawto,
               DX + XX_EMERALDS, DY + YY_EMERALDS + 1,
-              FONT5_XSIZE * 3, FONT5_YSIZE - 1,
+              getFontWidth(FONT_LEVEL_NUMBER) * 3,
+              getFontHeight(FONT_LEVEL_NUMBER) - 1,
               DX + XX_LEVEL - 1, DY + YY_LEVEL + 1);
   }
 
@@ -1103,7 +1111,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_TEXT_2);
       BackToFront();
 
       if (!tape.playing)
@@ -1129,7 +1137,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_TEXT_2);
       BackToFront();
 
       if (!tape.playing)
@@ -1140,10 +1148,6 @@ void GameWon()
       StopSound(SND_GAME_LEVELTIME_BONUS);
   }
 
-#if 0
-  FadeSounds();
-#endif
-
   /* Hero disappears */
   DrawLevelField(ExitX, ExitY);
   BackToFront();
@@ -1254,6 +1258,15 @@ int NewHiScore()
   return position;
 }
 
+static void InitPlayerGfxAnimation(struct PlayerInfo *player, int action)
+{
+  if (player->GfxAction != action)
+  {
+    player->GfxAction = action;
+    player->Frame = 0;
+  }
+}
+
 static void ResetRandomAnimationValue(int x, int y)
 {
   GfxRandom[x][y] = INIT_GFX_RANDOM();
@@ -1261,26 +1274,8 @@ static void ResetRandomAnimationValue(int x, int y)
 
 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)
@@ -1435,12 +1430,19 @@ void DrawDynamite(int x, int y)
 
   frame = getGraphicAnimationFrame(graphic, GfxFrame[x][y]);
 
+#if 1
+  if (Store[x][y])
+    DrawGraphicThruMask(sx, sy, graphic, frame);
+  else
+    DrawGraphic(sx, sy, graphic, frame);
+#else
   if (game.emulation == EMU_SUPAPLEX)
     DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
   else if (Store[x][y])
     DrawGraphicThruMask(sx, sy, graphic, frame);
   else
     DrawGraphic(sx, sy, graphic, frame);
+#endif
 }
 
 void CheckDynamite(int x, int y)
@@ -1460,7 +1462,8 @@ void CheckDynamite(int x, int y)
     }
   }
 
-  if (Feld[x][y] == EL_DYNAMITE_ACTIVE)
+  if (Feld[x][y] == EL_DYNAMITE_ACTIVE ||
+      Feld[x][y] == EL_SP_DISK_RED_ACTIVE)
     StopSound(SND_DYNAMITE_ACTIVE);
   else
     StopSound(SND_DYNABOMB_ACTIVE);
@@ -1512,7 +1515,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)))
@@ -1714,7 +1717,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];
@@ -1804,35 +1807,6 @@ void SplashAcid(int x, int y)
         !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 ?
-                  IMG_ACID_SPLASH_LEFT :
-                  IMG_ACID_SPLASH_RIGHT);
-
-    if (!MovDelay[x][y])       /* initialize animation counter */
-      MovDelay[x][y] = 9;
-
-    if (MovDelay[x][y])                /* continue animation */
-    {
-      MovDelay[x][y]--;
-      if (MovDelay[x][y]/2 && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
-      {
-       int frame = getGraphicAnimationFrame(graphic, 8 - MovDelay[x][y]);
-
-        DrawGraphic(SCREENX(x), SCREENY(y), graphic, frame);
-      }
-
-      if (!MovDelay[x][y])
-      {
-       Feld[x][y] = EL_EMPTY;
-       DrawLevelField(x, y);
-      }
-    }
-  }
-#endif
 }
 
 static void InitBeltMovement()
@@ -2159,16 +2133,11 @@ void Impact(int x, int 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 ||
@@ -2900,7 +2869,11 @@ 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
     {
       SplashAcid(x, y);
 
@@ -2908,6 +2881,10 @@ void StartMoving(int x, int y)
       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])
@@ -3021,15 +2998,8 @@ void StartMoving(int x, int y)
          element != EL_DARK_YAMYAM &&
          element != EL_PACMAN)
       {
-#if 0
-  if (element == EL_SPRING)
-    printf("1--> %d\n", MovDir[x][y]);
-#endif
        TurnRound(x, y);
-#if 0
-  if (element == EL_SPRING)
-    printf("2--> %d\n", MovDir[x][y]);
-#endif
+
        if (MovDelay[x][y] && (element == EL_BUG ||
                               element == EL_SPACESHIP ||
                               element == EL_SP_SNIKSNAK ||
@@ -3047,29 +3017,8 @@ void StartMoving(int x, int y)
          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);
-         int frame = getGraphicAnimationFrame(graphic, MovDelay[x][y] % 8);
-
-         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)
-           PlaySoundLevel(x, y, SND_YAMYAM_WAITING);
-         else if (element == EL_DARK_YAMYAM)
-           PlaySoundLevel(x, y, SND_DARK_YAMYAM_WAITING);
-       }
-#endif
       }
       else if (element == EL_SP_ELECTRON)
        DrawLevelElementAnimationIfNeeded(x, y, element);
@@ -3469,16 +3418,10 @@ 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 */
-    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];
+    GfxAction[newx][newy] = GfxAction[x][y];   /* keep action one frame */
+    GfxRandom[newx][newy] = GfxRandom[x][y];   /* keep same random value */
 
     ResetGfxAnimation(x, y);   /* reset animation values for old field */
 
@@ -3519,15 +3462,6 @@ void ContinueMoving(int x, int y)
   }
   else                         /* still moving on */
   {
-#if 0
-    if (GfxAction[x][y] == ACTION_DEFAULT)
-    {
-      printf("reset GfxAction...\n");
-
-      GfxAction[x][y] = ACTION_MOVING;
-    }
-#endif
-
     DrawLevelField(x, y);
   }
 }
@@ -4077,47 +4011,37 @@ void EdelsteinFunkeln(int x, int y)
     return;
 
   if (Feld[x][y] == EL_BD_DIAMOND)
-#if 0
-    DrawLevelElementAnimation(x, y, el2img(Feld[x][y]));
-#else
     return;
-#endif
-  else
-  {
-    if (MovDelay[x][y] == 0)   /* next animation frame */
-      MovDelay[x][y] = 11 * !SimpleRND(500);
 
-    if (MovDelay[x][y] != 0)   /* wait some time before next frame */
-    {
-      MovDelay[x][y]--;
+  if (MovDelay[x][y] == 0)     /* next animation frame */
+    MovDelay[x][y] = 11 * !SimpleRND(500);
 
-      if (setup.direct_draw && MovDelay[x][y])
-       SetDrawtoField(DRAW_BUFFERED);
+  if (MovDelay[x][y] != 0)     /* wait some time before next frame */
+  {
+    MovDelay[x][y]--;
 
-#if 0
-      DrawGraphic(SCREENX(x), SCREENY(y), el2img(Feld[x][y]), 0);
-#else
-      DrawLevelElementAnimation(x, y, Feld[x][y]);
-#endif
+    if (setup.direct_draw && MovDelay[x][y])
+      SetDrawtoField(DRAW_BUFFERED);
 
-      if (MovDelay[x][y] != 0)
-      {
-       int frame = getGraphicAnimationFrame(IMG_TWINKLE_WHITE,
-                                            10 - MovDelay[x][y]);
+    DrawLevelElementAnimation(x, y, Feld[x][y]);
 
-       DrawGraphicThruMask(SCREENX(x), SCREENY(y), IMG_TWINKLE_WHITE, frame);
+    if (MovDelay[x][y] != 0)
+    {
+      int frame = getGraphicAnimationFrame(IMG_TWINKLE_WHITE,
+                                          10 - MovDelay[x][y]);
 
-       if (setup.direct_draw)
-       {
-         int dest_x, dest_y;
+      DrawGraphicThruMask(SCREENX(x), SCREENY(y), IMG_TWINKLE_WHITE, frame);
 
-         dest_x = FX + SCREENX(x) * TILEX;
-         dest_y = FY + SCREENY(y) * TILEY;
+      if (setup.direct_draw)
+      {
+       int dest_x, dest_y;
 
-         BlitBitmap(drawto_field, window,
-                    dest_x, dest_y, TILEX, TILEY, dest_x, dest_y);
-         SetDrawtoField(DRAW_DIRECT);
-       }
+       dest_x = FX + SCREENX(x) * TILEX;
+       dest_y = FY + SCREENY(y) * TILEY;
+
+       BlitBitmap(drawto_field, window,
+                  dest_x, dest_y, TILEX, TILEY, dest_x, dest_y);
+       SetDrawtoField(DRAW_DIRECT);
       }
     }
   }
@@ -4422,9 +4346,6 @@ static void PlayerActions(struct PlayerInfo *player, byte player_action)
 {
   static byte stored_player_action[MAX_PLAYERS];
   static int num_stored_actions = 0;
-#if 0
-  static boolean save_tape_entry = FALSE;
-#endif
   boolean moved = FALSE, snapped = FALSE, bombed = FALSE;
   int left     = player_action & JOY_LEFT;
   int right    = player_action & JOY_RIGHT;
@@ -4443,11 +4364,6 @@ static void PlayerActions(struct PlayerInfo *player, byte player_action)
 
   if (player_action)
   {
-#if 0
-    save_tape_entry = TRUE;
-#endif
-    player->frame_reset_delay = 0;
-
     if (button1)
       snapped = SnapField(player, dx, dy);
     else
@@ -4466,20 +4382,7 @@ static void PlayerActions(struct PlayerInfo *player, byte player_action)
       }
     }
 
-#if 0
-    if (tape.recording && (moved || snapped || bombed))
-    {
-      if (bombed && !moved)
-       player_action &= JOY_BUTTON;
-
-      stored_player_action[player->index_nr] = player_action;
-      save_tape_entry = TRUE;
-    }
-    else if (tape.playing && snapped)
-      SnapField(player, 0, 0);                 /* stop snapping */
-#else
     stored_player_action[player->index_nr] = player_action;
-#endif
   }
   else
   {
@@ -4489,74 +4392,17 @@ static void PlayerActions(struct PlayerInfo *player, byte player_action)
     SnapField(player, 0, 0);
     CheckGravityMovement(player);
 
-#if 1
+    InitPlayerGfxAnimation(player, ACTION_DEFAULT);
+
     if (player->MovPos == 0)   /* needed for tape.playing */
       player->is_moving = FALSE;
-#endif
-#if 0
-    if (player->MovPos == 0)   /* needed for tape.playing */
-      player->last_move_dir = MV_NO_MOVING;
-
-    /* !!! CHECK THIS AGAIN !!!
-       (Seems to be needed for some EL_ROBOT stuff, but breaks
-       tapes when walking through pipes!)
-    */
-
-    /* it seems that "player->last_move_dir" is misused as some sort of
-       "player->is_just_moving_in_this_moment", which is needed for the
-       robot stuff (robots don't kill players when they are moving)
-    */
-#endif 
-
-    /* if the player does not move for some time, reset animation to start */
-    if (++player->frame_reset_delay > player->move_delay_value)
-      player->Frame = 0;
   }
 
-#if 0
-  if (tape.recording && num_stored_actions >= MAX_PLAYERS && save_tape_entry)
-  {
-    TapeRecordAction(stored_player_action);
-    num_stored_actions = 0;
-    save_tape_entry = FALSE;
-  }
-#else
   if (tape.recording && num_stored_actions >= MAX_PLAYERS)
   {
     TapeRecordAction(stored_player_action);
     num_stored_actions = 0;
   }
-#endif
-
-#if 0
-  if (tape.playing && !tape.pausing && !player_action &&
-      tape.counter < tape.length)
-  {
-    int jx = player->jx, jy = player->jy;
-    int next_joy =
-      tape.pos[tape.counter].action[player->index_nr] & (JOY_LEFT|JOY_RIGHT);
-
-    if ((next_joy == JOY_LEFT || next_joy == JOY_RIGHT) &&
-       (player->MovDir != JOY_UP && player->MovDir != JOY_DOWN))
-    {
-      int dx = (next_joy == JOY_LEFT ? -1 : +1);
-
-      if (IN_LEV_FIELD(jx+dx, jy) && IS_PUSHABLE(Feld[jx+dx][jy]))
-      {
-       int el = Feld[jx+dx][jy];
-       int push_delay = (IS_SB_ELEMENT(el) || el == EL_SATELLITE ? 2 :
-                         (el == EL_BALLOON || el == EL_SPRING) ? 0 : 10);
-
-       if (tape.delay_played + push_delay >= tape.pos[tape.counter].delay)
-       {
-         player->MovDir = next_joy;
-         player->Frame = FrameCounter % 4;
-         player->Pushing = TRUE;
-       }
-      }
-    }
-  }
-#endif
 }
 
 void GameActions()
@@ -4647,30 +4493,12 @@ void GameActions()
 
   ScrollScreen(NULL, SCROLL_GO_ON);
 
-
-
-#ifdef DEBUG
-#if 0
-  if (TimeFrames == 0 && local_player->active)
-  {
-    extern unsigned int last_RND();
-
-    printf("DEBUG: %03d last RND was %d \t [state checksum is %d]\n",
-          TimePlayed, last_RND(), getStateCheckSum(TimePlayed));
-  }
-#endif
-#endif
-
-#ifdef DEBUG
-#if 0
-  if (GameFrameDelay >= 500)
-    printf("FrameCounter == %d\n", FrameCounter);
-#endif
-#endif
-
   FrameCounter++;
   TimeFrames++;
 
+  for (i=0; i<MAX_PLAYERS; i++)
+    stored_player[i].Frame++;
+
   for (y=0; y<lev_fieldy; y++) for (x=0; x<lev_fieldx; x++)
   {
     Stop[x][y] = FALSE;
@@ -5013,14 +4841,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_TEXT_2);
 
       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_TEXT_2);
   }
 
   DrawAllPlayers();
@@ -5338,13 +5166,13 @@ boolean MoveFigure(struct PlayerInfo *player, int dx, int dy)
     }
   }
 
-  if (!(moved & MF_MOVING) && !player->Pushing)
-    player->Frame = 0;
-  else
 #if 0
-    player->Frame = (player->Frame + 1) % 4;
+#if 1
+  InitPlayerGfxAnimation(player, ACTION_DEFAULT);
 #else
-    player->Frame += 1 * 0;
+  if (!(moved & MF_MOVING) && !player->Pushing)
+    player->Frame = 0;
+#endif
 #endif
 
   if (moved & MF_MOVING)
@@ -5390,8 +5218,6 @@ void ScrollFigure(struct PlayerInfo *player, int mode)
   {
     player->actual_frame_counter = FrameCounter;
     player->GfxPos = move_stepsize * (player->MovPos / move_stepsize);
-    if (player->Frame)
-      player->Frame += 1;
 
     if (Feld[last_jx][last_jy] == EL_EMPTY)
       Feld[last_jx][last_jy] = EL_PLAYER_IS_LEAVING;
@@ -5404,7 +5230,6 @@ void ScrollFigure(struct PlayerInfo *player, int mode)
 
   player->MovPos += (player->MovPos > 0 ? -1 : 1) * move_stepsize;
   player->GfxPos = move_stepsize * (player->MovPos / move_stepsize);
-  player->Frame += 1;
 
   if (Feld[last_jx][last_jy] == EL_PLAYER_IS_LEAVING)
     Feld[last_jx][last_jy] = EL_EMPTY;
@@ -5769,6 +5594,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;
 
@@ -5845,8 +5672,7 @@ int DigField(struct PlayerInfo *player,
        local_player->gems_still_needed = 0;
       RaiseScoreElement(element);
       DrawText(DX_EMERALDS, DY_EMERALDS,
-              int2str(local_player->gems_still_needed, 3),
-              FS_SMALL, FC_YELLOW);
+              int2str(local_player->gems_still_needed, 3), FONT_TEXT_2);
       PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING);
       break;
 
@@ -5866,7 +5692,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_TEXT_2);
       }
       PlaySoundStereo(SND_EXTRA_TIME_COLLECTING, SOUND_MAX_RIGHT);
       break;
@@ -5888,10 +5714,10 @@ int DigField(struct PlayerInfo *player,
     case EL_SP_DISK_RED:
       RemoveField(x, y);
       player->dynamite++;
+      player->use_disk_red_graphic = (element == EL_SP_DISK_RED);
       RaiseScoreElement(EL_DYNAMITE);
-      DrawText(DX_DYNAMITE, DY_DYNAMITE,
-              int2str(local_player->dynamite, 3),
-              FS_SMALL, FC_YELLOW);
+      DrawText(DX_DYNAMITE, DY_DYNAMITE, int2str(local_player->dynamite, 3),
+              FONT_TEXT_2);
       PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING);
       break;
 
@@ -5923,14 +5749,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;
     }
@@ -5941,14 +5768,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;
     }
@@ -6064,7 +5892,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)
@@ -6085,7 +5915,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) &&
@@ -6291,7 +6122,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_TEXT_2);
       DrawLevelField(x, y);
       PlaySoundStereo(SND_TIME_ORB_FULL_COLLECTING, SOUND_MAX_RIGHT);
       return MF_ACTION;
@@ -6396,11 +6227,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;
 }
 
@@ -6421,6 +6297,7 @@ boolean SnapField(struct PlayerInfo *player, int dx, int dy)
       player->Pushing = FALSE;
 
     player->snapped = FALSE;
+    player->is_digging = FALSE;
     return FALSE;
   }
 
@@ -6436,6 +6313,7 @@ boolean SnapField(struct PlayerInfo *player, int dx, int dy)
     return FALSE;
 
   player->snapped = TRUE;
+  player->is_digging = FALSE;
   DrawLevelField(x, y);
   BackToFront();
 
@@ -6466,17 +6344,22 @@ boolean PlaceBomb(struct PlayerInfo *player)
 
   if (player->dynamite)
   {
-    Feld[jx][jy] = EL_DYNAMITE_ACTIVE;
+    Feld[jx][jy] = (player->use_disk_red_graphic ? EL_SP_DISK_RED_ACTIVE :
+                   EL_DYNAMITE_ACTIVE);
     player->dynamite--;
 
     DrawText(DX_DYNAMITE, DY_DYNAMITE, int2str(local_player->dynamite, 3),
-            FS_SMALL, FC_YELLOW);
+            FONT_TEXT_2);
     if (IN_SCR_FIELD(SCREENX(jx), SCREENY(jy)))
     {
+#if 1
+      DrawGraphicThruMask(SCREENX(jx), SCREENY(jy), el2img(Feld[jx][jy]), 0);
+#else
       if (game.emulation == EMU_SUPAPLEX)
        DrawGraphic(SCREENX(jx), SCREENY(jy), IMG_SP_DISK_RED, 0);
       else
        DrawGraphicThruMask(SCREENX(jx), SCREENY(jy), IMG_DYNAMITE_ACTIVE, 0);
+#endif
     }
 
     PlaySoundLevel(jx, jy, SND_DYNAMITE_DROPPING);
@@ -6588,8 +6471,7 @@ static void PlaySoundLevelElementAction(int x, int y, int element,
 void RaiseScore(int value)
 {
   local_player->score += value;
-  DrawText(DX_SCORE, DY_SCORE, int2str(local_player->score, 5),
-          FS_SMALL, FC_YELLOW);
+  DrawText(DX_SCORE, DY_SCORE, int2str(local_player->score, 5), FONT_TEXT_2);
 }
 
 void RaiseScoreElement(int element)