rnd-20030416-1-src
[rocksndiamonds.git] / src / game.c
index 2aa04493ae021cc38666cecea459ec18d6e87768..338e670b5f686b818847cef68dc46279d0cbfd7e 100644 (file)
@@ -113,6 +113,8 @@ static void PlaySoundLevel(int, int, int);
 static void PlaySoundLevelNearest(int, int, int);
 static void PlaySoundLevelAction(int, int, int);
 static void PlaySoundLevelElementAction(int, int, int, int);
+static void PlaySoundLevelActionIfLoop(int, int, int);
+static void StopSoundLevelActionIfLoop(int, int, int);
 
 static void MapGameButtons();
 static void HandleGameButtons(struct GadgetInfo *);
@@ -152,7 +154,7 @@ struct ChangingElementInfo
 
 static struct ChangingElementInfo changing_element_list[] =
 {
-  { EL_NUT_CRACKING,           EL_EMERALD,              6, NULL, NULL, NULL },
+  { EL_NUT_BREAKING,           EL_EMERALD,              6, NULL, NULL, NULL },
   { EL_PEARL_BREAKING,         EL_EMPTY,                8, NULL, NULL, NULL },
   { EL_EXIT_OPENING,           EL_EXIT_OPEN,           29, NULL, NULL, NULL },
 
@@ -213,33 +215,33 @@ void GetPlayerConfig()
 
 static int getBeltNrFromBeltElement(int element)
 {
-  return (element < EL_CONVEYOR_BELT2_LEFT ? 0 :
-         element < EL_CONVEYOR_BELT3_LEFT ? 1 :
-         element < EL_CONVEYOR_BELT4_LEFT ? 2 : 3);
+  return (element < EL_CONVEYOR_BELT_2_LEFT ? 0 :
+         element < EL_CONVEYOR_BELT_3_LEFT ? 1 :
+         element < EL_CONVEYOR_BELT_4_LEFT ? 2 : 3);
 }
 
 static int getBeltNrFromBeltActiveElement(int element)
 {
-  return (element < EL_CONVEYOR_BELT2_LEFT_ACTIVE ? 0 :
-         element < EL_CONVEYOR_BELT3_LEFT_ACTIVE ? 1 :
-         element < EL_CONVEYOR_BELT4_LEFT_ACTIVE ? 2 : 3);
+  return (element < EL_CONVEYOR_BELT_2_LEFT_ACTIVE ? 0 :
+         element < EL_CONVEYOR_BELT_3_LEFT_ACTIVE ? 1 :
+         element < EL_CONVEYOR_BELT_4_LEFT_ACTIVE ? 2 : 3);
 }
 
 static int getBeltNrFromBeltSwitchElement(int element)
 {
-  return (element < EL_CONVEYOR_BELT2_SWITCH_LEFT ? 0 :
-         element < EL_CONVEYOR_BELT3_SWITCH_LEFT ? 1 :
-         element < EL_CONVEYOR_BELT4_SWITCH_LEFT ? 2 : 3);
+  return (element < EL_CONVEYOR_BELT_2_SWITCH_LEFT ? 0 :
+         element < EL_CONVEYOR_BELT_3_SWITCH_LEFT ? 1 :
+         element < EL_CONVEYOR_BELT_4_SWITCH_LEFT ? 2 : 3);
 }
 
 static int getBeltDirNrFromBeltSwitchElement(int element)
 {
   static int belt_base_element[4] =
   {
-    EL_CONVEYOR_BELT1_SWITCH_LEFT,
-    EL_CONVEYOR_BELT2_SWITCH_LEFT,
-    EL_CONVEYOR_BELT3_SWITCH_LEFT,
-    EL_CONVEYOR_BELT4_SWITCH_LEFT
+    EL_CONVEYOR_BELT_1_SWITCH_LEFT,
+    EL_CONVEYOR_BELT_2_SWITCH_LEFT,
+    EL_CONVEYOR_BELT_3_SWITCH_LEFT,
+    EL_CONVEYOR_BELT_4_SWITCH_LEFT
   };
 
   int belt_nr = getBeltNrFromBeltSwitchElement(element);
@@ -279,16 +281,16 @@ static void InitField(int x, int y, boolean init_game)
          stored_player[0].use_murphy_graphic = TRUE;
        }
 
-       Feld[x][y] = EL_PLAYER1;
+       Feld[x][y] = EL_PLAYER_1;
       }
       /* no break! */
-    case EL_PLAYER1:
-    case EL_PLAYER2:
-    case EL_PLAYER3:
-    case EL_PLAYER4:
+    case EL_PLAYER_1:
+    case EL_PLAYER_2:
+    case EL_PLAYER_3:
+    case EL_PLAYER_4:
       if (init_game)
       {
-       struct PlayerInfo *player = &stored_player[Feld[x][y] - EL_PLAYER1];
+       struct PlayerInfo *player = &stored_player[Feld[x][y] - EL_PLAYER_1];
        int jx = player->jx, jy = player->jy;
 
        player->present = TRUE;
@@ -320,15 +322,15 @@ static void InitField(int x, int y, boolean init_game)
 
     case EL_STONEBLOCK:
       if (x < lev_fieldx-1 && Feld[x+1][y] == EL_ACID)
-       Feld[x][y] = EL_ACIDPOOL_TOPLEFT;
+       Feld[x][y] = EL_ACID_POOL_TOPLEFT;
       else if (x > 0 && Feld[x-1][y] == EL_ACID)
-       Feld[x][y] = EL_ACIDPOOL_TOPRIGHT;
-      else if (y > 0 && Feld[x][y-1] == EL_ACIDPOOL_TOPLEFT)
-       Feld[x][y] = EL_ACIDPOOL_BOTTOMLEFT;
+       Feld[x][y] = EL_ACID_POOL_TOPRIGHT;
+      else if (y > 0 && Feld[x][y-1] == EL_ACID_POOL_TOPLEFT)
+       Feld[x][y] = EL_ACID_POOL_BOTTOMLEFT;
       else if (y > 0 && Feld[x][y-1] == EL_ACID)
-       Feld[x][y] = EL_ACIDPOOL_BOTTOM;
-      else if (y > 0 && Feld[x][y-1] == EL_ACIDPOOL_TOPRIGHT)
-       Feld[x][y] = EL_ACIDPOOL_BOTTOMRIGHT;
+       Feld[x][y] = EL_ACID_POOL_BOTTOM;
+      else if (y > 0 && Feld[x][y-1] == EL_ACID_POOL_TOPRIGHT)
+       Feld[x][y] = EL_ACID_POOL_BOTTOMRIGHT;
       break;
 
     case EL_BUG_RIGHT:
@@ -377,7 +379,7 @@ static void InitField(int x, int y, boolean init_game)
     case EL_AMOEBA_DROP:
       if (y == lev_fieldy - 1)
       {
-       Feld[x][y] = EL_AMOEBA_CREATING;
+       Feld[x][y] = EL_AMOEBA_GROWING;
        Store[x][y] = EL_AMOEBA_WET;
       }
       break;
@@ -407,31 +409,31 @@ static void InitField(int x, int y, boolean init_game)
       Feld[x][y] = EL_EMPTY;
       break;
 
-    case EL_EM_KEY1_FILE:
-      Feld[x][y] = EL_EM_KEY1;
+    case EL_EM_KEY_1_FILE:
+      Feld[x][y] = EL_EM_KEY_1;
       break;
-    case EL_EM_KEY2_FILE:
-      Feld[x][y] = EL_EM_KEY2;
+    case EL_EM_KEY_2_FILE:
+      Feld[x][y] = EL_EM_KEY_2;
       break;
-    case EL_EM_KEY3_FILE:
-      Feld[x][y] = EL_EM_KEY3;
+    case EL_EM_KEY_3_FILE:
+      Feld[x][y] = EL_EM_KEY_3;
       break;
-    case EL_EM_KEY4_FILE:
-      Feld[x][y] = EL_EM_KEY4;
+    case EL_EM_KEY_4_FILE:
+      Feld[x][y] = EL_EM_KEY_4;
       break;
 
-    case EL_CONVEYOR_BELT1_SWITCH_LEFT:
-    case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:
-    case EL_CONVEYOR_BELT1_SWITCH_RIGHT:
-    case EL_CONVEYOR_BELT2_SWITCH_LEFT:
-    case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:
-    case EL_CONVEYOR_BELT2_SWITCH_RIGHT:
-    case EL_CONVEYOR_BELT3_SWITCH_LEFT:
-    case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:
-    case EL_CONVEYOR_BELT3_SWITCH_RIGHT:
-    case EL_CONVEYOR_BELT4_SWITCH_LEFT:
-    case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:
-    case EL_CONVEYOR_BELT4_SWITCH_RIGHT:
+    case EL_CONVEYOR_BELT_1_SWITCH_LEFT:
+    case EL_CONVEYOR_BELT_1_SWITCH_MIDDLE:
+    case EL_CONVEYOR_BELT_1_SWITCH_RIGHT:
+    case EL_CONVEYOR_BELT_2_SWITCH_LEFT:
+    case EL_CONVEYOR_BELT_2_SWITCH_MIDDLE:
+    case EL_CONVEYOR_BELT_2_SWITCH_RIGHT:
+    case EL_CONVEYOR_BELT_3_SWITCH_LEFT:
+    case EL_CONVEYOR_BELT_3_SWITCH_MIDDLE:
+    case EL_CONVEYOR_BELT_3_SWITCH_RIGHT:
+    case EL_CONVEYOR_BELT_4_SWITCH_LEFT:
+    case EL_CONVEYOR_BELT_4_SWITCH_MIDDLE:
+    case EL_CONVEYOR_BELT_4_SWITCH_RIGHT:
       if (init_game)
       {
        int belt_nr = getBeltNrFromBeltSwitchElement(Feld[x][y]);
@@ -473,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,
-                          el2edimg(EL_KEY1 + j));
+                          el2edimg(EL_KEY_1 + j));
 
   DrawText(DX + XX_EMERALDS, DY + YY_EMERALDS,
-          int2str(local_player->gems_still_needed, 3), FONT_DEFAULT_SMALL);
+          int2str(local_player->gems_still_needed, 3), FONT_TEXT_2);
   DrawText(DX + XX_DYNAMITE, DY + YY_DYNAMITE,
-          int2str(local_player->dynamite, 3), FONT_DEFAULT_SMALL);
+          int2str(local_player->dynamite, 3), FONT_TEXT_2);
   DrawText(DX + XX_SCORE, DY + YY_SCORE,
-          int2str(local_player->score, 5), FONT_DEFAULT_SMALL);
+          int2str(local_player->score, 5), FONT_TEXT_2);
   DrawText(DX + XX_TIME, DY + YY_TIME,
-          int2str(TimeLeft, 3), FONT_DEFAULT_SMALL);
+          int2str(TimeLeft, 3), FONT_TEXT_2);
 }
 
 
@@ -524,28 +526,22 @@ static void InitGameEngine()
     {
       EL_STEELWALL,
       EL_WALL,
-      EL_WALL_GROWING,
-      EL_WALL_GROWING_X,
-      EL_WALL_GROWING_Y,
-      EL_WALL_GROWING_XY
+      EL_EXPANDABLE_WALL,
+      EL_EXPANDABLE_WALL_HORIZONTAL,
+      EL_EXPANDABLE_WALL_VERTICAL,
+      EL_EXPANDABLE_WALL_ANY
     };
     static int ep_em_slippery_wall_num = SIZEOF_ARRAY_INT(ep_em_slippery_wall);
 
+    /* special EM style gems behaviour */
     for (i=0; i<ep_em_slippery_wall_num; i++)
-    {
-      if (level.em_slippery_gems)      /* special EM style gems behaviour */
-       Properties2[ep_em_slippery_wall[i]] |=
-         EP_BIT_EM_SLIPPERY_WALL;
-      else
-       Properties2[ep_em_slippery_wall[i]] &=
-         ~EP_BIT_EM_SLIPPERY_WALL;
-    }
+      SET_PROPERTY(ep_em_slippery_wall[i], EP_EM_SLIPPERY_WALL,
+                  level.em_slippery_gems);
 
-    /* "EL_WALL_GROWING_ACTIVE" wasn't slippery for EM gems in version 2.0.1 */
-    if (level.em_slippery_gems && game.engine_version > VERSION_IDENT(2,0,1))
-      Properties2[EL_WALL_GROWING_ACTIVE] |= EP_BIT_EM_SLIPPERY_WALL;
-    else
-      Properties2[EL_WALL_GROWING_ACTIVE] &=~EP_BIT_EM_SLIPPERY_WALL;
+    /* "EL_EXPANDABLE_WALL_GROWING" wasn't slippery for EM gems in 2.0.1 */
+    SET_PROPERTY(EL_EXPANDABLE_WALL_GROWING, EP_EM_SLIPPERY_WALL,
+                (level.em_slippery_gems &&
+                 game.engine_version > VERSION_IDENT(2,0,1)));
   }
 
   /* initialize changing elements information */
@@ -612,7 +608,7 @@ void InitGame()
     struct PlayerInfo *player = &stored_player[i];
 
     player->index_nr = i;
-    player->element_nr = EL_PLAYER1 + i;
+    player->element_nr = EL_PLAYER_1 + i;
 
     player->present = FALSE;
     player->active = FALSE;
@@ -641,9 +637,10 @@ void InitGame()
     player->Pushing = FALSE;
     player->Switching = FALSE;
     player->GfxPos = 0;
-    player->Frame = 0;
-
+    player->GfxDir = MV_NO_MOVING;
     player->GfxAction = ACTION_DEFAULT;
+    player->Frame = 0;
+    player->StepFrame = 0;
 
     player->use_murphy_graphic = FALSE;
     player->use_disk_red_graphic = FALSE;
@@ -655,6 +652,8 @@ void InitGame()
 
     player->is_moving = FALSE;
     player->is_waiting = FALSE;
+    player->is_digging = FALSE;
+    player->is_collecting = FALSE;
 
     player->move_delay       = game.initial_move_delay;
     player->move_delay_value = game.initial_move_delay_value;
@@ -734,6 +733,7 @@ void InitGame()
       GfxFrame[x][y] = 0;
       GfxAction[x][y] = ACTION_DEFAULT;
       GfxRandom[x][y] = INIT_GFX_RANDOM();
+      GfxElement[x][y] = EL_UNDEFINED;
     }
   }
 
@@ -909,16 +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), FONT_DEFAULT_SMALL);
+    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), FONT_SPECIAL_NARROW, FONT_OPAQUE);
+               int2str(level_nr, 3), FONT_LEVEL_NUMBER, BLIT_OPAQUE);
     BlitBitmap(drawto, drawto,
               DX + XX_EMERALDS, DY + YY_EMERALDS + 1,
-              getFontWidth(FONT_SPECIAL_NARROW) * 3,
-              getFontHeight(FONT_SPECIAL_NARROW) - 1,
+              getFontWidth(FONT_LEVEL_NUMBER) * 3,
+              getFontHeight(FONT_LEVEL_NUMBER) - 1,
               DX + XX_LEVEL - 1, DY + YY_LEVEL + 1);
   }
 
@@ -938,7 +937,7 @@ void InitGame()
 
   OpenDoor(DOOR_OPEN_ALL);
 
-  PlaySoundStereo(SND_GAME_STARTING, SOUND_MAX_RIGHT);
+  PlaySoundStereo(SND_GAME_STARTING, SOUND_MIDDLE);
   if (setup.sound_music)
     PlayMusic(level_nr);
 
@@ -1094,25 +1093,25 @@ void GameWon()
 
   local_player->LevelSolved = FALSE;
 
-  PlaySoundStereo(SND_GAME_WINNING, SOUND_MAX_RIGHT);
+  PlaySoundStereo(SND_GAME_WINNING, SOUND_MIDDLE);
 
   if (TimeLeft)
   {
     if (!tape.playing && setup.sound_loops)
-      PlaySoundExt(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_VOLUME, SOUND_MAX_RIGHT,
+      PlaySoundExt(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_VOLUME, SOUND_MIDDLE,
                   SND_CTRL_PLAY_LOOP);
 
     while (TimeLeft > 0)
     {
       if (!tape.playing && !setup.sound_loops)
-       PlaySoundStereo(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_RIGHT);
+       PlaySoundStereo(SND_GAME_LEVELTIME_BONUS, SOUND_MIDDLE);
       if (TimeLeft > 0 && !(TimeLeft % 10))
-       RaiseScore(level.score[SC_ZEITBONUS]);
+       RaiseScore(level.score[SC_TIME_BONUS]);
       if (TimeLeft > 100 && !(TimeLeft % 10))
        TimeLeft -= 10;
       else
        TimeLeft--;
-      DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_DEFAULT_SMALL);
+      DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_TEXT_2);
       BackToFront();
 
       if (!tape.playing)
@@ -1125,20 +1124,20 @@ void GameWon()
   else if (level.time == 0)            /* level without time limit */
   {
     if (!tape.playing && setup.sound_loops)
-      PlaySoundExt(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_VOLUME, SOUND_MAX_RIGHT,
+      PlaySoundExt(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_VOLUME, SOUND_MIDDLE,
                   SND_CTRL_PLAY_LOOP);
 
     while (TimePlayed < 999)
     {
       if (!tape.playing && !setup.sound_loops)
-       PlaySoundStereo(SND_GAME_LEVELTIME_BONUS, SOUND_MAX_RIGHT);
+       PlaySoundStereo(SND_GAME_LEVELTIME_BONUS, SOUND_MIDDLE);
       if (TimePlayed < 999 && !(TimePlayed % 10))
-       RaiseScore(level.score[SC_ZEITBONUS]);
+       RaiseScore(level.score[SC_TIME_BONUS]);
       if (TimePlayed < 900 && !(TimePlayed % 10))
        TimePlayed += 10;
       else
        TimePlayed++;
-      DrawText(DX_TIME, DY_TIME, int2str(TimePlayed, 3), FONT_DEFAULT_SMALL);
+      DrawText(DX_TIME, DY_TIME, int2str(TimePlayed, 3), FONT_TEXT_2);
       BackToFront();
 
       if (!tape.playing)
@@ -1259,12 +1258,19 @@ int NewHiScore()
   return position;
 }
 
-static void InitPlayerGfxAnimation(struct PlayerInfo *player, int action)
+void InitPlayerGfxAnimation(struct PlayerInfo *player, int action, int dir)
 {
-  if (player->GfxAction != action)
+  if (player->GfxAction != action || player->GfxDir != dir)
   {
+#if 0
+    printf("Player frame reset! (%d => %d, %d => %d)\n",
+          player->GfxAction, action, player->GfxDir, dir);
+#endif
+
     player->GfxAction = action;
+    player->GfxDir = dir;
     player->Frame = 0;
+    player->StepFrame = 0;
   }
 }
 
@@ -1372,6 +1378,7 @@ static int MovingOrBlocked2ElementIfNotLeaving(int x, int y)
 static void RemoveField(int x, int y)
 {
   Feld[x][y] = EL_EMPTY;
+  GfxElement[x][y] = EL_EMPTY;
   MovPos[x][y] = 0;
   MovDir[x][y] = 0;
   MovDelay[x][y] = 0;
@@ -1401,7 +1408,7 @@ void RemoveMovingField(int x, int y)
       (Feld[oldx][oldy] == EL_QUICKSAND_EMPTYING ||
        Feld[oldx][oldy] == EL_MAGIC_WALL_EMPTYING ||
        Feld[oldx][oldy] == EL_BD_MAGIC_WALL_EMPTYING ||
-       Feld[oldx][oldy] == EL_AMOEBA_DRIPPING))
+       Feld[oldx][oldy] == EL_AMOEBA_DROPPING))
     Feld[oldx][oldy] = get_next_element(Feld[oldx][oldy]);
   else
     Feld[oldx][oldy] = EL_EMPTY;
@@ -1455,19 +1462,21 @@ void CheckDynamite(int x, int y)
     if (MovDelay[x][y] != 0)
     {
       DrawDynamite(x, y);
-
-      /* !!! correct: "PlaySoundLevelActionIfLoop" etc. !!! */
-      PlaySoundLevelAction(x, y, ACTION_ACTIVE);
+      PlaySoundLevelActionIfLoop(x, y, ACTION_ACTIVE);
 
       return;
     }
   }
 
+#if 1
+  StopSoundLevelActionIfLoop(x, y, ACTION_ACTIVE);
+#else
   if (Feld[x][y] == EL_DYNAMITE_ACTIVE ||
       Feld[x][y] == EL_SP_DISK_RED_ACTIVE)
     StopSound(SND_DYNAMITE_ACTIVE);
   else
     StopSound(SND_DYNABOMB_ACTIVE);
+#endif
 
   Bang(x, y);
 }
@@ -1538,16 +1547,16 @@ void Explode(int ex, int ey, int phase, int mode)
       {
        switch(StorePlayer[ex][ey])
        {
-         case EL_PLAYER2:
+         case EL_PLAYER_2:
            Store[x][y] = EL_EMERALD_RED;
            break;
-         case EL_PLAYER3:
+         case EL_PLAYER_3:
            Store[x][y] = EL_EMERALD;
            break;
-         case EL_PLAYER4:
+         case EL_PLAYER_4:
            Store[x][y] = EL_EMERALD_PURPLE;
            break;
-         case EL_PLAYER1:
+         case EL_PLAYER_1:
          default:
            Store[x][y] = EL_EMERALD_YELLOW;
            break;
@@ -1596,13 +1605,14 @@ void Explode(int ex, int ey, int phase, int mode)
       if (AmoebaNr[x][y] &&
          (element == EL_AMOEBA_FULL ||
           element == EL_BD_AMOEBA ||
-          element == EL_AMOEBA_CREATING))
+          element == EL_AMOEBA_GROWING))
       {
        AmoebaCnt[AmoebaNr[x][y]]--;
        AmoebaCnt2[AmoebaNr[x][y]]--;
       }
 
       Feld[x][y] = EL_EXPLOSION;
+      GfxElement[x][y] = EL_EMPTY;
       MovDir[x][y] = MovPos[x][y] = 0;
       AmoebaNr[x][y] = 0;
       ExplodePhase[x][y] = 1;
@@ -1674,7 +1684,7 @@ void Explode(int ex, int ey, int phase, int mode)
     int frame = getGraphicAnimationFrame(graphic, phase - delay);
 
     if (phase == delay)
-      DrawCrumbledSand(SCREENX(x), SCREENY(y));
+      DrawLevelFieldCrumbledSand(x, y);
 
     if (IS_PFORTE(Store[x][y]))
     {
@@ -1702,7 +1712,7 @@ void DynaExplode(int ex, int ey)
 
   if (IS_ACTIVE_BOMB(Feld[ex][ey]))
   {
-    player = &stored_player[Feld[ex][ey] - EL_DYNABOMB_PLAYER1_ACTIVE];
+    player = &stored_player[Feld[ex][ey] - EL_DYNABOMB_PLAYER_1_ACTIVE];
     dynabomb_size = player->dynabomb_size;
     dynabomb_xl = player->dynabomb_xl;
     player->dynabombs_left++;
@@ -1766,13 +1776,13 @@ void Bang(int x, int y)
       RaiseScoreElement(element);
       Explode(x, y, EX_PHASE_START, EX_NORMAL);
       break;
-    case EL_DYNABOMB_PLAYER1_ACTIVE:
-    case EL_DYNABOMB_PLAYER2_ACTIVE:
-    case EL_DYNABOMB_PLAYER3_ACTIVE:
-    case EL_DYNABOMB_PLAYER4_ACTIVE:
-    case EL_DYNABOMB_NR:
-    case EL_DYNABOMB_SZ:
-    case EL_DYNABOMB_XL:
+    case EL_DYNABOMB_PLAYER_1_ACTIVE:
+    case EL_DYNABOMB_PLAYER_2_ACTIVE:
+    case EL_DYNABOMB_PLAYER_3_ACTIVE:
+    case EL_DYNABOMB_PLAYER_4_ACTIVE:
+    case EL_DYNABOMB_INCREASE_NUMBER:
+    case EL_DYNABOMB_INCREASE_SIZE:
+    case EL_DYNABOMB_INCREASE_POWER:
       DynaExplode(x, y);
       break;
     case EL_PENGUIN:
@@ -1814,17 +1824,17 @@ static void InitBeltMovement()
 {
   static int belt_base_element[4] =
   {
-    EL_CONVEYOR_BELT1_LEFT,
-    EL_CONVEYOR_BELT2_LEFT,
-    EL_CONVEYOR_BELT3_LEFT,
-    EL_CONVEYOR_BELT4_LEFT
+    EL_CONVEYOR_BELT_1_LEFT,
+    EL_CONVEYOR_BELT_2_LEFT,
+    EL_CONVEYOR_BELT_3_LEFT,
+    EL_CONVEYOR_BELT_4_LEFT
   };
   static int belt_base_active_element[4] =
   {
-    EL_CONVEYOR_BELT1_LEFT_ACTIVE,
-    EL_CONVEYOR_BELT2_LEFT_ACTIVE,
-    EL_CONVEYOR_BELT3_LEFT_ACTIVE,
-    EL_CONVEYOR_BELT4_LEFT_ACTIVE
+    EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
+    EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
+    EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
+    EL_CONVEYOR_BELT_4_LEFT_ACTIVE
   };
 
   int x, y, i, j;
@@ -1875,24 +1885,24 @@ static void ToggleBeltSwitch(int x, int y)
 {
   static int belt_base_element[4] =
   {
-    EL_CONVEYOR_BELT1_LEFT,
-    EL_CONVEYOR_BELT2_LEFT,
-    EL_CONVEYOR_BELT3_LEFT,
-    EL_CONVEYOR_BELT4_LEFT
+    EL_CONVEYOR_BELT_1_LEFT,
+    EL_CONVEYOR_BELT_2_LEFT,
+    EL_CONVEYOR_BELT_3_LEFT,
+    EL_CONVEYOR_BELT_4_LEFT
   };
   static int belt_base_active_element[4] =
   {
-    EL_CONVEYOR_BELT1_LEFT_ACTIVE,
-    EL_CONVEYOR_BELT2_LEFT_ACTIVE,
-    EL_CONVEYOR_BELT3_LEFT_ACTIVE,
-    EL_CONVEYOR_BELT4_LEFT_ACTIVE
+    EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
+    EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
+    EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
+    EL_CONVEYOR_BELT_4_LEFT_ACTIVE
   };
   static int belt_base_switch_element[4] =
   {
-    EL_CONVEYOR_BELT1_SWITCH_LEFT,
-    EL_CONVEYOR_BELT2_SWITCH_LEFT,
-    EL_CONVEYOR_BELT3_SWITCH_LEFT,
-    EL_CONVEYOR_BELT4_SWITCH_LEFT
+    EL_CONVEYOR_BELT_1_SWITCH_LEFT,
+    EL_CONVEYOR_BELT_2_SWITCH_LEFT,
+    EL_CONVEYOR_BELT_3_SWITCH_LEFT,
+    EL_CONVEYOR_BELT_4_SWITCH_LEFT
   };
   static int belt_move_dir[4] =
   {
@@ -1995,13 +2005,21 @@ static void ToggleSwitchgateSwitch(int x, int y)
               element == EL_SWITCHGATE_OPENING)
       {
        Feld[xx][yy] = EL_SWITCHGATE_CLOSING;
+#if 1
+       PlaySoundLevelAction(xx, yy, ACTION_CLOSING);
+#else
        PlaySoundLevel(xx, yy, SND_SWITCHGATE_CLOSING);
+#endif
       }
       else if (element == EL_SWITCHGATE_CLOSED ||
               element == EL_SWITCHGATE_CLOSING)
       {
        Feld[xx][yy] = EL_SWITCHGATE_OPENING;
+#if 1
+       PlaySoundLevelAction(xx, yy, ACTION_OPENING);
+#else
        PlaySoundLevel(xx, yy, SND_SWITCHGATE_OPENING);
+#endif
       }
     }
   }
@@ -2163,7 +2181,7 @@ void Impact(int x, int y)
       Bang(x, y+1);
     else
     {
-      Feld[x][y] = EL_AMOEBA_CREATING;
+      Feld[x][y] = EL_AMOEBA_GROWING;
       Store[x][y] = EL_AMOEBA_WET;
 
       ResetRandomAnimationValue(x, y);
@@ -2249,8 +2267,8 @@ void Impact(int x, int y)
        }
        else if (smashed == EL_NUT)
        {
-         Feld[x][y+1] = EL_NUT_CRACKING;
-         PlaySoundLevel(x, y, SND_NUT_CRACKING);
+         Feld[x][y+1] = EL_NUT_BREAKING;
+         PlaySoundLevel(x, y, SND_NUT_BREAKING);
          RaiseScoreElement(EL_NUT);
          return;
        }
@@ -2290,9 +2308,9 @@ void Impact(int x, int y)
        Feld[x][y+1] == EL_BD_MAGIC_WALL_ACTIVE))
   {
     if (Feld[x][y+1] == EL_MAGIC_WALL_ACTIVE)
-      PlaySoundLevel(x, y, SND_MAGIC_WALL_CHANGING);
+      PlaySoundLevel(x, y, SND_MAGIC_WALL_FILLING);
     else if (Feld[x][y+1] == EL_BD_MAGIC_WALL_ACTIVE)
-      PlaySoundLevel(x, y, SND_BD_MAGIC_WALL_CHANGING);
+      PlaySoundLevel(x, y, SND_BD_MAGIC_WALL_FILLING);
 
     return;
   }
@@ -2411,11 +2429,11 @@ void TurnRound(int x, int y)
 
     if (IN_LEV_FIELD(left_x, left_y) &&
        (IS_FREE_OR_PLAYER(left_x, left_y) ||
-        IS_MAMPF2(Feld[left_x][left_y])))
+        IS_FOOD_DARK_YAMYAM(Feld[left_x][left_y])))
       can_turn_left = TRUE;
     if (IN_LEV_FIELD(right_x, right_y) &&
        (IS_FREE_OR_PLAYER(right_x, right_y) ||
-        IS_MAMPF2(Feld[right_x][right_y])))
+        IS_FOOD_DARK_YAMYAM(Feld[right_x][right_y])))
       can_turn_right = TRUE;
 
     if (can_turn_left && can_turn_right)
@@ -2702,7 +2720,7 @@ void TurnRound(int x, int y)
             Feld[newx][newy] == EL_ACID ||
             (element == EL_PENGUIN &&
              (Feld[newx][newy] == EL_EXIT_OPEN ||
-              IS_MAMPF3(Feld[newx][newy])))))
+              IS_FOOD_PENGUIN(Feld[newx][newy])))))
          return;
 
        MovDir[x][y] =
@@ -2714,7 +2732,7 @@ void TurnRound(int x, int y)
             Feld[newx][newy] == EL_ACID ||
             (element == EL_PENGUIN &&
              (Feld[newx][newy] == EL_EXIT_OPEN ||
-              IS_MAMPF3(Feld[newx][newy])))))
+              IS_FOOD_PENGUIN(Feld[newx][newy])))))
          return;
 
        MovDir[x][y] = old_move_dir;
@@ -2771,7 +2789,11 @@ void StartMoving(int x, int y)
 
        Feld[x][y] = EL_QUICKSAND_EMPTYING;
        Store[x][y] = EL_ROCK;
+#if 1
+       PlaySoundLevelAction(x, y, ACTION_EMPTYING);
+#else
        PlaySoundLevel(x, y, SND_QUICKSAND_EMPTYING);
+#endif
       }
       else if (Feld[x][y+1] == EL_QUICKSAND_EMPTY)
       {
@@ -2789,7 +2811,11 @@ void StartMoving(int x, int y)
        Feld[x][y+1] = EL_QUICKSAND_FULL;
        Store[x][y+1] = Store[x][y];
        Store[x][y] = 0;
-       PlaySoundLevel(x, y, SND_QUICKSAND_SLIPPING);
+#if 1
+       PlaySoundLevelAction(x, y, ACTION_FILLING);
+#else
+       PlaySoundLevel(x, y, SND_QUICKSAND_FILLING);
+#endif
       }
     }
     else if ((element == EL_ROCK || element == EL_BD_ROCK) &&
@@ -2800,7 +2826,11 @@ void StartMoving(int x, int y)
 
       Feld[x][y] = EL_QUICKSAND_FILLING;
       Store[x][y] = element;
+#if 1
+      PlaySoundLevelAction(x, y, ACTION_FILLING);
+#else
       PlaySoundLevel(x, y, SND_QUICKSAND_FILLING);
+#endif
     }
     else if (element == EL_MAGIC_WALL_FULL)
     {
@@ -2910,7 +2940,7 @@ void StartMoving(int x, int y)
     }
     else if (element == EL_AMOEBA_DROP)
     {
-      Feld[x][y] = EL_AMOEBA_CREATING;
+      Feld[x][y] = EL_AMOEBA_GROWING;
       Store[x][y] = EL_AMOEBA_WET;
     }
     /* Store[x][y+1] must be zero, because:
@@ -2992,8 +3022,8 @@ void StartMoving(int x, int y)
 
     if (!MovDelay[x][y])       /* start new movement phase */
     {
-      /* all objects that can change their move direction after each step */
-      /* (MAMPFER, MAMPFER2 and PACMAN go straight until they hit a wall  */
+      /* all objects that can change their move direction after each step
+        (YAMYAM, DARK_YAMYAM and PACMAN go straight until they hit a wall */
 
       if (element != EL_YAMYAM &&
          element != EL_DARK_YAMYAM &&
@@ -3029,10 +3059,10 @@ void StartMoving(int x, int y)
        int dir = MovDir[x][y];
        int dx = (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
        int dy = (dir == MV_UP   ? -1 : dir == MV_DOWN  ? +1 : 0);
-       int graphic = (dir == MV_LEFT   ? IMG_FLAMES1_LEFT :
-                      dir == MV_RIGHT  ? IMG_FLAMES1_RIGHT :
-                      dir == MV_UP     ? IMG_FLAMES1_UP :
-                      dir == MV_DOWN   ? IMG_FLAMES1_DOWN : IMG_EMPTY);
+       int graphic = (dir == MV_LEFT   ? IMG_FLAMES_1_LEFT :
+                      dir == MV_RIGHT  ? IMG_FLAMES_1_RIGHT :
+                      dir == MV_UP     ? IMG_FLAMES_1_UP :
+                      dir == MV_DOWN   ? IMG_FLAMES_1_DOWN : IMG_EMPTY);
        int frame = getGraphicAnimationFrame(graphic, -1);
 
        for (i=1; i<=3; i++)
@@ -3109,7 +3139,7 @@ void StartMoving(int x, int y)
        Feld[x][y] = EL_EMPTY;
        DrawLevelField(x, y);
 
-       PlaySoundLevel(newx, newy, SND_PENGUIN_PASSING_EXIT);
+       PlaySoundLevel(newx, newy, SND_PENGUIN_PASSING);
        if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
          DrawGraphicThruMask(SCREENX(newx),SCREENY(newy), el2img(element), 0);
 
@@ -3120,7 +3150,7 @@ void StartMoving(int x, int y)
 
        return;
       }
-      else if (IS_MAMPF3(Feld[newx][newy]))
+      else if (IS_FOOD_PENGUIN(Feld[newx][newy]))
       {
        if (DigField(local_player, newx, newy, 0, 0, DF_DIG) == MF_MOVING)
          DrawLevelField(newx, newy);
@@ -3148,7 +3178,7 @@ void StartMoving(int x, int y)
          DrawLevelField(newx, newy);
        }
 
-       PlaySoundLevel(x, y, SND_PIG_EATING);
+       PlaySoundLevel(x, y, SND_PIG_DIGGING);
       }
       else if (!IS_FREE(newx, newy))
       {
@@ -3212,10 +3242,10 @@ void StartMoving(int x, int y)
        DrawLevelField(newx, newy);
       }
 
-      PlaySoundLevel(x, y, SND_YAMYAM_EATING);
+      PlaySoundLevel(x, y, SND_YAMYAM_DIGGING);
     }
     else if (element == EL_DARK_YAMYAM && IN_LEV_FIELD(newx, newy) &&
-            IS_MAMPF2(Feld[newx][newy]))
+            IS_FOOD_DARK_YAMYAM(Feld[newx][newy]))
     {
       if (AmoebaNr[newx][newy])
       {
@@ -3233,7 +3263,7 @@ void StartMoving(int x, int y)
        DrawLevelField(newx, newy);
       }
 
-      PlaySoundLevel(x, y, SND_DARK_YAMYAM_EATING);
+      PlaySoundLevel(x, y, SND_DARK_YAMYAM_DIGGING);
     }
     else if ((element == EL_PACMAN || element == EL_MOLE)
             && IN_LEV_FIELD(newx, newy) && IS_AMOEBOID(Feld[newx][newy]))
@@ -3249,7 +3279,7 @@ void StartMoving(int x, int y)
       if (element == EL_MOLE)
       {
        Feld[newx][newy] = EL_AMOEBA_SHRINKING;
-       PlaySoundLevel(x, y, SND_MOLE_EATING);
+       PlaySoundLevel(x, y, SND_MOLE_DIGGING);
        MovDelay[newx][newy] = 0;       /* start amoeba shrinking delay */
        return;                         /* wait for shrinking amoeba */
       }
@@ -3257,7 +3287,7 @@ void StartMoving(int x, int y)
       {
        Feld[newx][newy] = EL_EMPTY;
        DrawLevelField(newx, newy);
-       PlaySoundLevel(x, y, SND_PACMAN_EATING);
+       PlaySoundLevel(x, y, SND_PACMAN_DIGGING);
       }
     }
     else if (element == EL_MOLE && IN_LEV_FIELD(newx, newy) &&
@@ -3313,7 +3343,7 @@ void ContinueMoving(int x, int y)
   int newx = x + dx, newy = y + dy;
   int step = (horiz_move ? dx : dy) * TILEX / 8;
 
-  if (element == EL_AMOEBA_DROP || element == EL_AMOEBA_DRIPPING)
+  if (element == EL_AMOEBA_DROP || element == EL_AMOEBA_DROPPING)
     step /= 2;
   else if (element == EL_QUICKSAND_FILLING ||
           element == EL_QUICKSAND_EMPTYING)
@@ -3363,7 +3393,7 @@ void ContinueMoving(int x, int y)
        yy = y + xy[i][1];
 
        if (IN_LEV_FIELD(xx, yy) && Feld[xx][yy] == EL_SAND)
-         DrawLevelField(xx, yy);       /* for "DrawCrumbledSand()" */
+         DrawLevelField(xx, yy);       /* for "crumbled sand" */
       }
     }
 
@@ -3405,7 +3435,7 @@ void ContinueMoving(int x, int y)
        Feld[x][y] = EL_BD_MAGIC_WALL_DEAD;
       element = Feld[newx][newy] = Store[x][y];
     }
-    else if (element == EL_AMOEBA_DRIPPING)
+    else if (element == EL_AMOEBA_DROPPING)
     {
       Feld[x][y] = get_next_element(element);
       element = Feld[newx][newy] = Store[x][y];
@@ -3629,7 +3659,7 @@ void AmoebeUmwandelnBD(int ax, int ay, int new_element)
       if (AmoebaNr[x][y] == group_nr &&
          (Feld[x][y] == EL_AMOEBA_DEAD ||
           Feld[x][y] == EL_BD_AMOEBA ||
-          Feld[x][y] == EL_AMOEBA_CREATING))
+          Feld[x][y] == EL_AMOEBA_GROWING))
       {
        AmoebaNr[x][y] = 0;
        Feld[x][y] = new_element;
@@ -3657,10 +3687,14 @@ void AmoebeWaechst(int x, int y)
 
     if (DelayReached(&sound_delay, sound_delay_value))
     {
+#if 1
+      PlaySoundLevelElementAction(x, y, Store[x][y], ACTION_GROWING);
+#else
       if (Store[x][y] == EL_BD_AMOEBA)
-       PlaySoundLevel(x, y, SND_BD_AMOEBA_CREATING);
+       PlaySoundLevel(x, y, SND_BD_AMOEBA_GROWING);
       else
-       PlaySoundLevel(x, y, SND_AMOEBA_CREATING);
+       PlaySoundLevel(x, y, SND_AMOEBA_GROWING);
+#endif
       sound_delay_value = 30;
     }
   }
@@ -3670,10 +3704,10 @@ void AmoebeWaechst(int x, int y)
     MovDelay[x][y]--;
     if (MovDelay[x][y]/2 && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
     {
-      int frame = getGraphicAnimationFrame(IMG_AMOEBA_CREATING,
+      int frame = getGraphicAnimationFrame(IMG_AMOEBA_GROWING,
                                           6 - MovDelay[x][y]);
 
-      DrawGraphic(SCREENX(x), SCREENY(y), IMG_AMOEBA_CREATING, frame);
+      DrawGraphic(SCREENX(x), SCREENY(y), IMG_AMOEBA_GROWING, frame);
     }
 
     if (!MovDelay[x][y])
@@ -3725,6 +3759,7 @@ void AmoebeAbleger(int ax, int ay)
 {
   int i;
   int element = Feld[ax][ay];
+  int graphic = el2img(element);
   int newax = ax, neway = ay;
   static int xy[4][2] =
   {
@@ -3741,6 +3776,9 @@ void AmoebeAbleger(int ax, int ay)
     return;
   }
 
+  if (IS_ANIMATED(graphic))
+    DrawLevelGraphicAnimationIfNeeded(ax, ay, graphic);
+
   if (!MovDelay[ax][ay])       /* start making new amoeba field */
     MovDelay[ax][ay] = RND(FRAMES_PER_SECOND * 25 / (1 + level.amoeba_speed));
 
@@ -3846,18 +3884,22 @@ void AmoebeAbleger(int ax, int ay)
   if (element != EL_AMOEBA_WET || neway < ay || !IS_FREE(newax, neway) ||
       (neway == lev_fieldy - 1 && newax != ax))
   {
-    Feld[newax][neway] = EL_AMOEBA_CREATING;   /* creation of new amoeba */
+    Feld[newax][neway] = EL_AMOEBA_GROWING;    /* creation of new amoeba */
     Store[newax][neway] = element;
   }
   else if (neway == ay)
   {
     Feld[newax][neway] = EL_AMOEBA_DROP;       /* drop left/right of amoeba */
-    PlaySoundLevel(newax, neway, SND_AMOEBA_DROP_CREATING);
+#if 1
+    PlaySoundLevelAction(newax, neway, ACTION_GROWING);
+#else
+    PlaySoundLevel(newax, neway, SND_AMOEBA_GROWING);
+#endif
   }
   else
   {
     InitMovingField(ax, ay, MV_DOWN);          /* drop dripping from amoeba */
-    Feld[ax][ay] = EL_AMOEBA_DRIPPING;
+    Feld[ax][ay] = EL_AMOEBA_DROPPING;
     Store[ax][ay] = EL_AMOEBA_DROP;
     ContinueMoving(ax, ay);
     return;
@@ -3872,8 +3914,12 @@ void Life(int ax, int ay)
   static int life[4] = { 2, 3, 3, 3 }; /* parameters for "game of life" */
   int life_time = 40;
   int element = Feld[ax][ay];
+  int graphic = el2img(element);
   boolean changed = FALSE;
 
+  if (IS_ANIMATED(graphic))
+    DrawLevelGraphicAnimationIfNeeded(ax, ay, graphic);
+
   if (Stop[ax][ay])
     return;
 
@@ -3903,7 +3949,7 @@ void Life(int ax, int ay)
        continue;
 
       if (((Feld[x][y] == element ||
-           (element == EL_GAMEOFLIFE && IS_PLAYER(x, y))) &&
+           (element == EL_GAME_OF_LIFE && IS_PLAYER(x, y))) &&
           !Stop[x][y]) ||
          (IS_FREE(x, y) && Stop[x][y]))
        nachbarn++;
@@ -3925,7 +3971,7 @@ void Life(int ax, int ay)
       if (nachbarn >= life[2] && nachbarn <= life[3])
       {
        Feld[xx][yy] = element;
-       MovDelay[xx][yy] = (element == EL_GAMEOFLIFE ? 0 : life_time-1);
+       MovDelay[xx][yy] = (element == EL_GAME_OF_LIFE ? 0 : life_time-1);
        if (!Stop[xx][yy])
          DrawLevelField(xx, yy);
        Stop[xx][yy] = TRUE;
@@ -3935,8 +3981,8 @@ void Life(int ax, int ay)
   }
 
   if (changed)
-    PlaySoundLevel(ax, ay, element == EL_GAMEOFLIFE ? SND_GAMEOFLIFE_CREATING :
-                  SND_BIOMAZE_CREATING);
+    PlaySoundLevel(ax, ay, element == EL_BIOMAZE ? SND_BIOMAZE_GROWING :
+                  SND_GAME_OF_LIFE_GROWING);
 }
 
 static void InitRobotWheel(int x, int y)
@@ -3970,21 +4016,37 @@ void CheckExit(int x, int y)
   if (local_player->gems_still_needed > 0 ||
       local_player->sokobanfields_still_needed > 0 ||
       local_player->lights_still_needed > 0)
+  {
+    int element = Feld[x][y];
+    int graphic = el2img(element);
+
+    if (IS_ANIMATED(graphic))
+      DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
+
     return;
+  }
 
   Feld[x][y] = EL_EXIT_OPENING;
 
-  PlaySoundLevelNearest(x, y, SND_EXIT_OPENING);
+  PlaySoundLevelNearest(x, y, SND_CLASS_EXIT_OPENING);
 }
 
 void CheckExitSP(int x, int y)
 {
   if (local_player->gems_still_needed > 0)
+  {
+    int element = Feld[x][y];
+    int graphic = el2img(element);
+
+    if (IS_ANIMATED(graphic))
+      DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
+
     return;
+  }
 
   Feld[x][y] = EL_SP_EXIT_OPEN;
 
-  PlaySoundLevelNearest(x, y, SND_SP_EXIT_OPENING);
+  PlaySoundLevelNearest(x, y, SND_CLASS_SP_EXIT_OPENING);
 }
 
 static void CloseAllOpenTimegates()
@@ -4000,7 +4062,11 @@ static void CloseAllOpenTimegates()
       if (element == EL_TIMEGATE_OPEN || element == EL_TIMEGATE_OPENING)
       {
        Feld[x][y] = EL_TIMEGATE_CLOSING;
+#if 1
+       PlaySoundLevelAction(x, y, ACTION_CLOSING);
+#else
        PlaySoundLevel(x, y, SND_TIMEGATE_CLOSING);
+#endif
       }
     }
   }
@@ -4101,12 +4167,16 @@ void MauerWaechst(int x, int y)
 void MauerAbleger(int ax, int ay)
 {
   int element = Feld[ax][ay];
+  int graphic = el2img(element);
   boolean oben_frei = FALSE, unten_frei = FALSE;
   boolean links_frei = FALSE, rechts_frei = FALSE;
   boolean oben_massiv = FALSE, unten_massiv = FALSE;
   boolean links_massiv = FALSE, rechts_massiv = FALSE;
   boolean new_wall = FALSE;
 
+  if (IS_ANIMATED(graphic))
+    DrawLevelGraphicAnimationIfNeeded(ax, ay, graphic);
+
   if (!MovDelay[ax][ay])       /* start building new wall */
     MovDelay[ax][ay] = 6;
 
@@ -4126,57 +4196,59 @@ void MauerAbleger(int ax, int ay)
   if (IN_LEV_FIELD(ax+1, ay) && IS_FREE(ax+1, ay))
     rechts_frei = TRUE;
 
-  if (element == EL_WALL_GROWING_Y || element == EL_WALL_GROWING_XY)
+  if (element == EL_EXPANDABLE_WALL_VERTICAL ||
+      element == EL_EXPANDABLE_WALL_ANY)
   {
     if (oben_frei)
     {
-      Feld[ax][ay-1] = EL_WALL_GROWING_ACTIVE;
+      Feld[ax][ay-1] = EL_EXPANDABLE_WALL_GROWING;
       Store[ax][ay-1] = element;
       MovDir[ax][ay-1] = MV_UP;
       if (IN_SCR_FIELD(SCREENX(ax), SCREENY(ay-1)))
        DrawGraphic(SCREENX(ax), SCREENY(ay - 1),
-                   IMG_WALL_GROWING_ACTIVE_UP, 0);
+                   IMG_EXPANDABLE_WALL_GROWING_UP, 0);
       new_wall = TRUE;
     }
     if (unten_frei)
     {
-      Feld[ax][ay+1] = EL_WALL_GROWING_ACTIVE;
+      Feld[ax][ay+1] = EL_EXPANDABLE_WALL_GROWING;
       Store[ax][ay+1] = element;
       MovDir[ax][ay+1] = MV_DOWN;
       if (IN_SCR_FIELD(SCREENX(ax), SCREENY(ay+1)))
        DrawGraphic(SCREENX(ax), SCREENY(ay + 1),
-                   IMG_WALL_GROWING_ACTIVE_DOWN, 0);
+                   IMG_EXPANDABLE_WALL_GROWING_DOWN, 0);
       new_wall = TRUE;
     }
   }
 
-  if (element == EL_WALL_GROWING_X || element == EL_WALL_GROWING_XY ||
-      element == EL_WALL_GROWING)
+  if (element == EL_EXPANDABLE_WALL_HORIZONTAL ||
+      element == EL_EXPANDABLE_WALL_ANY ||
+      element == EL_EXPANDABLE_WALL)
   {
     if (links_frei)
     {
-      Feld[ax-1][ay] = EL_WALL_GROWING_ACTIVE;
+      Feld[ax-1][ay] = EL_EXPANDABLE_WALL_GROWING;
       Store[ax-1][ay] = element;
       MovDir[ax-1][ay] = MV_LEFT;
       if (IN_SCR_FIELD(SCREENX(ax-1), SCREENY(ay)))
        DrawGraphic(SCREENX(ax - 1), SCREENY(ay),
-                   IMG_WALL_GROWING_ACTIVE_LEFT, 0);
+                   IMG_EXPANDABLE_WALL_GROWING_LEFT, 0);
       new_wall = TRUE;
     }
 
     if (rechts_frei)
     {
-      Feld[ax+1][ay] = EL_WALL_GROWING_ACTIVE;
+      Feld[ax+1][ay] = EL_EXPANDABLE_WALL_GROWING;
       Store[ax+1][ay] = element;
       MovDir[ax+1][ay] = MV_RIGHT;
       if (IN_SCR_FIELD(SCREENX(ax+1), SCREENY(ay)))
        DrawGraphic(SCREENX(ax + 1), SCREENY(ay),
-                   IMG_WALL_GROWING_ACTIVE_RIGHT, 0);
+                   IMG_EXPANDABLE_WALL_GROWING_RIGHT, 0);
       new_wall = TRUE;
     }
   }
 
-  if (element == EL_WALL_GROWING && (links_frei || rechts_frei))
+  if (element == EL_EXPANDABLE_WALL && (links_frei || rechts_frei))
     DrawLevelField(ax, ay);
 
   if (!IN_LEV_FIELD(ax, ay-1) || IS_MAUER(Feld[ax][ay-1]))
@@ -4189,13 +4261,18 @@ void MauerAbleger(int ax, int ay)
     rechts_massiv = TRUE;
 
   if (((oben_massiv && unten_massiv) ||
-       element == EL_WALL_GROWING_X || element == EL_WALL_GROWING) &&
+       element == EL_EXPANDABLE_WALL_HORIZONTAL ||
+       element == EL_EXPANDABLE_WALL) &&
       ((links_massiv && rechts_massiv) ||
-       element == EL_WALL_GROWING_Y))
+       element == EL_EXPANDABLE_WALL_VERTICAL))
     Feld[ax][ay] = EL_WALL;
 
   if (new_wall)
-    PlaySoundLevel(ax, ay, SND_WALL_GROWING);
+#if 1
+    PlaySoundLevelAction(ax, ay, ACTION_GROWING);
+#else
+    PlaySoundLevel(ax, ay, SND_EXPANDABLE_WALL_GROWING);
+#endif
 }
 
 void CheckForDragon(int x, int y)
@@ -4301,7 +4378,7 @@ static void ChangeActiveTrap(int x, int y)
 
   /* if new animation frame was drawn, correct crumbled sand border */
   if (IS_NEW_FRAME(GfxFrame[x][y], graphic))
-    DrawCrumbledSand(SCREENX(x), SCREENY(y));
+    DrawLevelFieldCrumbledSand(x, y);
 }
 
 static void ChangeElement(int x, int y)
@@ -4393,7 +4470,14 @@ static void PlayerActions(struct PlayerInfo *player, byte player_action)
     SnapField(player, 0, 0);
     CheckGravityMovement(player);
 
-    InitPlayerGfxAnimation(player, ACTION_DEFAULT);
+    if (player->MovPos == 0)
+    {
+#if 0
+      printf("Trying... Player frame reset\n");
+#endif
+
+      InitPlayerGfxAnimation(player, ACTION_DEFAULT, player->MovDir);
+    }
 
     if (player->MovPos == 0)   /* needed for tape.playing */
       player->is_moving = FALSE;
@@ -4494,11 +4578,13 @@ void GameActions()
 
   ScrollScreen(NULL, SCROLL_GO_ON);
 
+#if 0
   FrameCounter++;
   TimeFrames++;
 
   for (i=0; i<MAX_PLAYERS; i++)
     stored_player[i].Frame++;
+#endif
 
   for (y=0; y<lev_fieldy; y++) for (x=0; x<lev_fieldx; x++)
   {
@@ -4530,10 +4616,8 @@ 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))
@@ -4541,13 +4625,14 @@ void GameActions()
 
     SetRandomAnimationValue(x, y);
 
+#if 1
+    PlaySoundLevelActionIfLoop(x, y, GfxAction[x][y]);
+#endif
+
     if (IS_INACTIVE(element))
     {
-
-#if 1
       if (IS_ANIMATED(graphic))
        DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
-#endif
 
       continue;
     }
@@ -4564,8 +4649,6 @@ void GameActions()
       if (IS_GEM(element) || element == EL_SP_INFOTRON)
        EdelsteinFunkeln(x, y);
     }
-
-#if 1
     else if ((element == EL_ACID ||
              element == EL_EXIT_OPEN ||
              element == EL_SP_EXIT_OPEN ||
@@ -4576,8 +4659,6 @@ void GameActions()
              element == EL_SHIELD_DEADLY) &&
             IS_ANIMATED(graphic))
       DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
-#endif
-
     else if (IS_MOVING(x, y))
       ContinueMoving(x, y);
     else if (IS_ACTIVE_BOMB(element))
@@ -4586,7 +4667,7 @@ void GameActions()
     else if (element == EL_EXPLOSION && !game.explosions_delayed)
       Explode(x, y, ExplodePhase[x][y], EX_NORMAL);
 #endif
-    else if (element == EL_AMOEBA_CREATING)
+    else if (element == EL_AMOEBA_GROWING)
       AmoebeWaechst(x, y);
     else if (element == EL_AMOEBA_SHRINKING)
       AmoebaDisappearing(x, y);
@@ -4596,71 +4677,27 @@ void GameActions()
       AmoebeAbleger(x, y);
 #endif
 
-    else if (element == EL_GAMEOFLIFE || element == EL_BIOMAZE)
+    else if (element == EL_GAME_OF_LIFE || element == EL_BIOMAZE)
       Life(x, y);
-#if 0
-    else if (element == EL_ROBOT_WHEEL_ACTIVE)
-      RobotWheel(x, y);
-    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)
-      SplashAcid(x, y);
-#endif
-#if 0
-    else if (element == EL_NUT_CRACKING)
-      NussKnacken(x, y);
-    else if (element == EL_PEARL_BREAKING)
-      BreakingPearl(x, y);
-#endif
     else if (element == EL_EXIT_CLOSED)
       CheckExit(x, y);
     else if (element == EL_SP_EXIT_CLOSED)
       CheckExitSP(x, y);
-#if 0
-    else if (element == EL_EXIT_OPENING)
-      AusgangstuerOeffnen(x, y);
-#endif
-    else if (element == EL_WALL_GROWING_ACTIVE)
+    else if (element == EL_EXPANDABLE_WALL_GROWING)
       MauerWaechst(x, y);
-    else if (element == EL_WALL_GROWING ||
-            element == EL_WALL_GROWING_X ||
-            element == EL_WALL_GROWING_Y ||
-            element == EL_WALL_GROWING_XY)
+    else if (element == EL_EXPANDABLE_WALL ||
+            element == EL_EXPANDABLE_WALL_HORIZONTAL ||
+            element == EL_EXPANDABLE_WALL_VERTICAL ||
+            element == EL_EXPANDABLE_WALL_ANY)
       MauerAbleger(x, y);
     else if (element == EL_FLAMES)
       CheckForDragon(x, y);
-#if 0
-    else if (element == EL_SP_BUGGY_BASE ||
-            element == EL_SP_BUGGY_BASE_ACTIVATING ||
-            element == EL_SP_BUGGY_BASE_ACTIVE)
-      CheckBuggyBase(x, y);
-    else if (element == EL_TRAP ||
-            element == EL_TRAP_ACTIVE)
-      CheckTrap(x, y);
-    else if (IS_BELT_ACTIVE(element))
-      DrawBeltAnimation(x, y, element);
-    else if (element == EL_SWITCHGATE_OPENING)
-      OpenSwitchgate(x, y);
-    else if (element == EL_SWITCHGATE_CLOSING)
-      CloseSwitchgate(x, y);
-    else if (element == EL_TIMEGATE_OPENING)
-      OpenTimegate(x, y);
-    else if (element == EL_TIMEGATE_CLOSING)
-      CloseTimegate(x, y);
-#endif
-
     else if (IS_AUTO_CHANGING(element))
       ChangeElement(x, y);
-
-#if 1
     else if (element == EL_EXPLOSION)
       ;        /* drawing of correct explosion animation is handled separately */
     else if (IS_ANIMATED(graphic))
       DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
-#endif
 
     if (IS_BELT_ACTIVE(element))
       PlaySoundLevelAction(x, y, ACTION_ACTIVE);
@@ -4840,16 +4877,16 @@ void GameActions()
       TimeLeft--;
 
       if (TimeLeft <= 10 && setup.time_limit)
-       PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MAX_RIGHT);
+       PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MIDDLE);
 
-      DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_DEFAULT_SMALL);
+      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), FONT_DEFAULT_SMALL);
+      DrawText(DX_TIME, DY_TIME, int2str(TimePlayed, 3), FONT_TEXT_2);
   }
 
   DrawAllPlayers();
@@ -4872,6 +4909,33 @@ void GameActions()
 
     redraw_mask |= REDRAW_FPS;
   }
+
+#if 0
+  if (stored_player[0].jx != stored_player[0].last_jx ||
+      stored_player[0].jy != stored_player[0].last_jy)
+    printf("::: %d, %d, %d, %d, %d\n",
+          stored_player[0].MovDir,
+          stored_player[0].MovPos,
+          stored_player[0].GfxPos,
+          stored_player[0].Frame,
+          stored_player[0].StepFrame);
+#endif
+
+#if 1
+  FrameCounter++;
+  TimeFrames++;
+
+  for (i=0; i<MAX_PLAYERS; i++)
+  {
+    int move_frames =
+      MOVE_DELAY_NORMAL_SPEED /  stored_player[i].move_delay_value;
+
+    stored_player[i].Frame += move_frames;
+
+    if (stored_player[i].MovPos != 0)
+      stored_player[i].StepFrame += move_frames;
+  }
+#endif
 }
 
 static boolean AllPlayersInSight(struct PlayerInfo *player, int x, int y)
@@ -4966,11 +5030,18 @@ static void CheckGravityMovement(struct PlayerInfo *player)
 
     if (field_under_player_is_free &&
        !player_is_moving_to_valid_field &&
-       !IS_TUBE(Feld[jx][jy]))
+       !IS_WALKABLE_UNDER(Feld[jx][jy]))
       player->programmed_action = MV_DOWN;
   }
 }
 
+/*
+  MoveFigureOneStep()
+  -----------------------------------------------------------------------------
+  dx, dy:              direction (non-diagonal) to try to move the player to
+  real_dx, real_dy:    direction as read from input device (can be diagonal)
+*/
+
 boolean MoveFigureOneStep(struct PlayerInfo *player,
                          int dx, int dy, int real_dx, int real_dy)
 {
@@ -5004,7 +5075,7 @@ boolean MoveFigureOneStep(struct PlayerInfo *player,
     if (element == EL_ACID && dx == 0 && dy == 1)
     {
       SplashAcid(jx, jy);
-      Feld[jx][jy] = EL_PLAYER1;
+      Feld[jx][jy] = EL_PLAYER_1;
       InitMovingField(jx, jy, MV_DOWN);
       Store[jx][jy] = EL_ACID;
       ContinueMoving(jx, jy);
@@ -5176,6 +5247,8 @@ boolean MoveFigure(struct PlayerInfo *player, int dx, int dy)
 #endif
 #endif
 
+  player->StepFrame = 0;
+
   if (moved & MF_MOVING)
   {
     if (old_jx != jx && old_jy == jy)
@@ -5183,7 +5256,7 @@ boolean MoveFigure(struct PlayerInfo *player, int dx, int dy)
     else if (old_jx == jx && old_jy != jy)
       player->MovDir = (old_jy < jy ? MV_DOWN : MV_UP);
 
-    DrawLevelField(jx, jy);    /* for "DrawCrumbledSand()" */
+    DrawLevelField(jx, jy);    /* for "crumbled sand" */
 
     player->last_move_dir = player->MovDir;
     player->is_moving = TRUE;
@@ -5243,7 +5316,7 @@ void ScrollFigure(struct PlayerInfo *player, int mode)
 
   if (player->MovPos == 0)
   {
-    if (IS_QUICK_GATE(Feld[last_jx][last_jy]))
+    if (IS_WALKABLE_THROUGH(Feld[last_jx][last_jy]))
     {
       /* continue with normal speed after quickly moving through gate */
       HALVE_PLAYER_SPEED(player);
@@ -5511,8 +5584,8 @@ void TestIfBadThingTouchesOtherBadThing(int bad_x, int bad_y)
       continue;
 
     element = Feld[x][y];
-    if (IS_AMOEBOID(element) || element == EL_GAMEOFLIFE ||
-       element == EL_AMOEBA_CREATING || element == EL_AMOEBA_DROP)
+    if (IS_AMOEBOID(element) || element == EL_GAME_OF_LIFE ||
+       element == EL_AMOEBA_GROWING || element == EL_AMOEBA_DROP)
     {
       kill_x = x;
       kill_y = y;
@@ -5555,7 +5628,7 @@ void BuryHero(struct PlayerInfo *player)
   if (!player->active)
     return;
 
-  PlaySoundLevel(jx, jy, SND_PLAYER_DYING);
+  PlaySoundLevel(jx, jy, SND_CLASS_PLAYER_DYING);
   PlaySoundLevel(jx, jy, SND_GAME_LOSING);
 
   player->GameOver = TRUE;
@@ -5584,6 +5657,25 @@ void RemoveHero(struct PlayerInfo *player)
   ExitY = ZY = jy;
 }
 
+#if 0
+/*
+  checkDiagonalPushing()
+  -----------------------------------------------------------------------------
+  check if diagonal input device direction results in pushing of object
+*/
+
+static boolean checkDiagonalPushing(int x, int y, int real_dx, int real_dy)
+{
+}
+#endif
+
+/*
+  DigField()
+  -----------------------------------------------------------------------------
+  x, y:                        field next to player (non-diagonal) to try to dig to
+  real_dx, real_dy:    direction as read from input device (can be diagonal)
+*/
+
 int DigField(struct PlayerInfo *player,
             int x, int y, int real_dx, int real_dy, int mode)
 {
@@ -5595,7 +5687,11 @@ int DigField(struct PlayerInfo *player,
                        dy == +1 ? MV_DOWN : MV_NO_MOVING);
   int element;
 
-  player->is_digging = FALSE;
+  if (player->MovPos == 0)
+  {
+    player->is_digging = FALSE;
+    player->is_collecting = FALSE;
+  }
 
   if (player->MovPos == 0)
     player->Pushing = FALSE;
@@ -5610,12 +5706,12 @@ int DigField(struct PlayerInfo *player,
   if (IS_MOVING(x, y) || IS_PLAYER(x, y))
     return MF_NO_ACTION;
 
-  if (IS_TUBE(Feld[jx][jy]))
+  if (IS_WALKABLE_UNDER(Feld[jx][jy]))
   {
     int i = 0;
     int tube_leave_directions[][2] =
     {
-      { EL_TUBE_ALL,                   MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN },
+      { EL_TUBE_ANY,                   MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN },
       { EL_TUBE_VERTICAL,                                   MV_UP | MV_DOWN },
       { EL_TUBE_HORIZONTAL,            MV_LEFT | MV_RIGHT                   },
       { EL_TUBE_VERTICAL_LEFT,         MV_LEFT |            MV_UP | MV_DOWN },
@@ -5653,6 +5749,13 @@ int DigField(struct PlayerInfo *player,
     case EL_SP_BUGGY_BASE:
     case EL_SP_BUGGY_BASE_ACTIVATING:
       RemoveField(x, y);
+#if 1
+      if (mode != DF_SNAP && element != EL_EMPTY)
+      {
+       GfxElement[x][y] = (CAN_BE_CRUMBLED(element) ? EL_SAND : element);
+       player->is_digging = TRUE;
+      }
+#endif
       PlaySoundLevelElementAction(x, y, element, ACTION_DIGGING);
       break;
 
@@ -5666,6 +5769,13 @@ int DigField(struct PlayerInfo *player,
     case EL_PEARL:
     case EL_CRYSTAL:
       RemoveField(x, y);
+#if 1
+      if (mode != DF_SNAP)
+      {
+       GfxElement[x][y] = element;
+       player->is_collecting = TRUE;
+      }
+#endif
       local_player->gems_still_needed -= (element == EL_DIAMOND ? 3 :
                                          element == EL_PEARL ? 5 :
                                          element == EL_CRYSTAL ? 8 : 1);
@@ -5673,8 +5783,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),
-              FONT_DEFAULT_SMALL);
+              int2str(local_player->gems_still_needed, 3), FONT_TEXT_2);
       PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING);
       break;
 
@@ -5694,9 +5803,9 @@ int DigField(struct PlayerInfo *player,
       if (level.time > 0)
       {
        TimeLeft += 10;
-       DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_DEFAULT_SMALL);
+       DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_TEXT_2);
       }
-      PlaySoundStereo(SND_EXTRA_TIME_COLLECTING, SOUND_MAX_RIGHT);
+      PlaySoundStereo(SND_EXTRA_TIME_COLLECTING, SOUND_MIDDLE);
       break;
 
     case EL_SHIELD_NORMAL:
@@ -5718,39 +5827,39 @@ int DigField(struct PlayerInfo *player,
       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), FONT_DEFAULT_SMALL);
+      DrawText(DX_DYNAMITE, DY_DYNAMITE, int2str(local_player->dynamite, 3),
+              FONT_TEXT_2);
       PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING);
       break;
 
-    case EL_DYNABOMB_NR:
+    case EL_DYNABOMB_INCREASE_NUMBER:
       RemoveField(x, y);
       player->dynabomb_count++;
       player->dynabombs_left++;
       RaiseScoreElement(EL_DYNAMITE);
-      PlaySoundLevel(x, y, SND_DYNABOMB_NR_COLLECTING);
+      PlaySoundLevel(x, y, SND_DYNABOMB_INCREASE_NUMBER_COLLECTING);
       break;
 
-    case EL_DYNABOMB_SZ:
+    case EL_DYNABOMB_INCREASE_SIZE:
       RemoveField(x, y);
       player->dynabomb_size++;
       RaiseScoreElement(EL_DYNAMITE);
-      PlaySoundLevel(x, y, SND_DYNABOMB_SZ_COLLECTING);
+      PlaySoundLevel(x, y, SND_DYNABOMB_INCREASE_SIZE_COLLECTING);
       break;
 
-    case EL_DYNABOMB_XL:
+    case EL_DYNABOMB_INCREASE_POWER:
       RemoveField(x, y);
       player->dynabomb_xl = TRUE;
       RaiseScoreElement(EL_DYNAMITE);
-      PlaySoundLevel(x, y, SND_DYNABOMB_XL_COLLECTING);
+      PlaySoundLevel(x, y, SND_DYNABOMB_INCREASE_POWER_COLLECTING);
       break;
 
-    case EL_KEY1:
-    case EL_KEY2:
-    case EL_KEY3:
-    case EL_KEY4:
+    case EL_KEY_1:
+    case EL_KEY_2:
+    case EL_KEY_3:
+    case EL_KEY_4:
     {
-      int key_nr = element - EL_KEY1;
+      int key_nr = element - EL_KEY_1;
       int graphic = el2edimg(element);
 
       RemoveField(x, y);
@@ -5760,17 +5869,17 @@ int DigField(struct PlayerInfo *player,
                         graphic);
       DrawMiniGraphicExt(window, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS,
                         graphic);
-      PlaySoundLevel(x, y, SND_KEY_COLLECTING);
+      PlaySoundLevel(x, y, SND_CLASS_KEY_COLLECTING);
       break;
     }
 
-    case EL_EM_KEY1:
-    case EL_EM_KEY2:
-    case EL_EM_KEY3:
-    case EL_EM_KEY4:
+    case EL_EM_KEY_1:
+    case EL_EM_KEY_2:
+    case EL_EM_KEY_3:
+    case EL_EM_KEY_4:
     {
-      int key_nr = element - EL_EM_KEY1;
-      int graphic = el2edimg(EL_KEY1 + key_nr);
+      int key_nr = element - EL_EM_KEY_1;
+      int graphic = el2edimg(EL_KEY_1 + key_nr);
 
       RemoveField(x, y);
       player->key[key_nr] = TRUE;
@@ -5779,7 +5888,7 @@ int DigField(struct PlayerInfo *player,
                         graphic);
       DrawMiniGraphicExt(window, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS,
                         graphic);
-      PlaySoundLevel(x, y, SND_KEY_COLLECTING);
+      PlaySoundLevel(x, y, SND_CLASS_KEY_COLLECTING);
       break;
     }
 
@@ -5813,23 +5922,23 @@ int DigField(struct PlayerInfo *player,
       }
       break;
 
-    case EL_CONVEYOR_BELT1_SWITCH_LEFT:
-    case EL_CONVEYOR_BELT1_SWITCH_MIDDLE:
-    case EL_CONVEYOR_BELT1_SWITCH_RIGHT:
-    case EL_CONVEYOR_BELT2_SWITCH_LEFT:
-    case EL_CONVEYOR_BELT2_SWITCH_MIDDLE:
-    case EL_CONVEYOR_BELT2_SWITCH_RIGHT:
-    case EL_CONVEYOR_BELT3_SWITCH_LEFT:
-    case EL_CONVEYOR_BELT3_SWITCH_MIDDLE:
-    case EL_CONVEYOR_BELT3_SWITCH_RIGHT:
-    case EL_CONVEYOR_BELT4_SWITCH_LEFT:
-    case EL_CONVEYOR_BELT4_SWITCH_MIDDLE:
-    case EL_CONVEYOR_BELT4_SWITCH_RIGHT:
+    case EL_CONVEYOR_BELT_1_SWITCH_LEFT:
+    case EL_CONVEYOR_BELT_1_SWITCH_MIDDLE:
+    case EL_CONVEYOR_BELT_1_SWITCH_RIGHT:
+    case EL_CONVEYOR_BELT_2_SWITCH_LEFT:
+    case EL_CONVEYOR_BELT_2_SWITCH_MIDDLE:
+    case EL_CONVEYOR_BELT_2_SWITCH_RIGHT:
+    case EL_CONVEYOR_BELT_3_SWITCH_LEFT:
+    case EL_CONVEYOR_BELT_3_SWITCH_MIDDLE:
+    case EL_CONVEYOR_BELT_3_SWITCH_RIGHT:
+    case EL_CONVEYOR_BELT_4_SWITCH_LEFT:
+    case EL_CONVEYOR_BELT_4_SWITCH_MIDDLE:
+    case EL_CONVEYOR_BELT_4_SWITCH_RIGHT:
       if (!player->Switching)
       {
        player->Switching = TRUE;
        ToggleBeltSwitch(x, y);
-       PlaySoundLevel(x, y, SND_CONVEYOR_BELT_SWITCH_ACTIVATING);
+       PlaySoundLevel(x, y, SND_CLASS_CONVEYOR_BELT_SWITCH_ACTIVATING);
       }
       return MF_ACTION;
       break;
@@ -5840,7 +5949,7 @@ int DigField(struct PlayerInfo *player,
       {
        player->Switching = TRUE;
        ToggleSwitchgateSwitch(x, y);
-       PlaySoundLevel(x, y, SND_SWITCHGATE_SWITCH_ACTIVATING);
+       PlaySoundLevel(x, y, SND_CLASS_SWITCHGATE_SWITCH_ACTIVATING);
       }
       return MF_ACTION;
       break;
@@ -5865,20 +5974,20 @@ int DigField(struct PlayerInfo *player,
       return MF_ACTION;
       break;
 
-    case EL_BALLOON_SEND_LEFT:
-    case EL_BALLOON_SEND_RIGHT:
-    case EL_BALLOON_SEND_UP:
-    case EL_BALLOON_SEND_DOWN:
-    case EL_BALLOON_SEND_ANY_DIRECTION:
-      if (element == EL_BALLOON_SEND_ANY_DIRECTION)
+    case EL_BALLOON_SWITCH_LEFT:
+    case EL_BALLOON_SWITCH_RIGHT:
+    case EL_BALLOON_SWITCH_UP:
+    case EL_BALLOON_SWITCH_DOWN:
+    case EL_BALLOON_SWITCH_ANY:
+      if (element == EL_BALLOON_SWITCH_ANY)
        game.balloon_dir = move_direction;
       else
-       game.balloon_dir = (element == EL_BALLOON_SEND_LEFT  ? MV_LEFT :
-                           element == EL_BALLOON_SEND_RIGHT ? MV_RIGHT :
-                           element == EL_BALLOON_SEND_UP    ? MV_UP :
-                           element == EL_BALLOON_SEND_DOWN  ? MV_DOWN :
+       game.balloon_dir = (element == EL_BALLOON_SWITCH_LEFT  ? MV_LEFT :
+                           element == EL_BALLOON_SWITCH_RIGHT ? MV_RIGHT :
+                           element == EL_BALLOON_SWITCH_UP    ? MV_UP :
+                           element == EL_BALLOON_SWITCH_DOWN  ? MV_DOWN :
                            MV_NO_MOVING);
-      PlaySoundLevel(x, y, SND_BALLOON_SWITCH_ACTIVATING);
+      PlaySoundLevel(x, y, SND_CLASS_BALLOON_SWITCH_ACTIVATING);
 
       return MF_ACTION;
       break;
@@ -5950,27 +6059,27 @@ int DigField(struct PlayerInfo *player,
       PlaySoundLevelElementAction(x, y, element, ACTION_PUSHING);
       break;
 
-    case EL_GATE1:
-    case EL_GATE2:
-    case EL_GATE3:
-    case EL_GATE4:
-      if (!player->key[element - EL_GATE1])
+    case EL_GATE_1:
+    case EL_GATE_2:
+    case EL_GATE_3:
+    case EL_GATE_4:
+      if (!player->key[element - EL_GATE_1])
        return MF_NO_ACTION;
       break;
 
-    case EL_GATE1_GRAY:
-    case EL_GATE2_GRAY:
-    case EL_GATE3_GRAY:
-    case EL_GATE4_GRAY:
-      if (!player->key[element - EL_GATE1_GRAY])
+    case EL_GATE_1_GRAY:
+    case EL_GATE_2_GRAY:
+    case EL_GATE_3_GRAY:
+    case EL_GATE_4_GRAY:
+      if (!player->key[element - EL_GATE_1_GRAY])
        return MF_NO_ACTION;
       break;
 
-    case EL_EM_GATE1:
-    case EL_EM_GATE2:
-    case EL_EM_GATE3:
-    case EL_EM_GATE4:
-      if (!player->key[element - EL_EM_GATE1])
+    case EL_EM_GATE_1:
+    case EL_EM_GATE_2:
+    case EL_EM_GATE_3:
+    case EL_EM_GATE_4:
+      if (!player->key[element - EL_EM_GATE_1])
        return MF_NO_ACTION;
       if (!IN_LEV_FIELD(x + dx, y + dy) || !IS_FREE(x + dx, y + dy))
        return MF_NO_ACTION;
@@ -5979,14 +6088,14 @@ int DigField(struct PlayerInfo *player,
       player->programmed_action = move_direction;
       DOUBLE_PLAYER_SPEED(player);
 
-      PlaySoundLevel(x, y, SND_GATE_PASSING);
+      PlaySoundLevel(x, y, SND_CLASS_GATE_PASSING);
       break;
 
-    case EL_EM_GATE1_GRAY:
-    case EL_EM_GATE2_GRAY:
-    case EL_EM_GATE3_GRAY:
-    case EL_EM_GATE4_GRAY:
-      if (!player->key[element - EL_EM_GATE1_GRAY])
+    case EL_EM_GATE_1_GRAY:
+    case EL_EM_GATE_2_GRAY:
+    case EL_EM_GATE_3_GRAY:
+    case EL_EM_GATE_4_GRAY:
+      if (!player->key[element - EL_EM_GATE_1_GRAY])
        return MF_NO_ACTION;
       if (!IN_LEV_FIELD(x + dx, y + dy) || !IS_FREE(x + dx, y + dy))
        return MF_NO_ACTION;
@@ -5995,7 +6104,11 @@ int DigField(struct PlayerInfo *player,
       player->programmed_action = move_direction;
       DOUBLE_PLAYER_SPEED(player);
 
+#if 1
+      PlaySoundLevelAction(x, y, ACTION_PASSING);
+#else
       PlaySoundLevel(x, y, SND_GATE_PASSING);
+#endif
       break;
 
     case EL_SWITCHGATE_OPEN:
@@ -6010,37 +6123,37 @@ int DigField(struct PlayerInfo *player,
       PlaySoundLevelElementAction(x, y, element, ACTION_PASSING);
       break;
 
-    case EL_SP_PORT1_LEFT:
-    case EL_SP_PORT2_LEFT:
-    case EL_SP_PORT1_RIGHT:
-    case EL_SP_PORT2_RIGHT:
-    case EL_SP_PORT1_UP:
-    case EL_SP_PORT2_UP:
-    case EL_SP_PORT1_DOWN:
-    case EL_SP_PORT2_DOWN:
-    case EL_SP_PORT_X:
-    case EL_SP_PORT_Y:
-    case EL_SP_PORT_XY:
+    case EL_SP_PORT_LEFT:
+    case EL_SP_PORT_RIGHT:
+    case EL_SP_PORT_UP:
+    case EL_SP_PORT_DOWN:
+    case EL_SP_PORT_HORIZONTAL:
+    case EL_SP_PORT_VERTICAL:
+    case EL_SP_PORT_ANY:
+    case EL_SP_GRAVITY_PORT_LEFT:
+    case EL_SP_GRAVITY_PORT_RIGHT:
+    case EL_SP_GRAVITY_PORT_UP:
+    case EL_SP_GRAVITY_PORT_DOWN:
       if ((dx == -1 &&
-          element != EL_SP_PORT1_LEFT &&
-          element != EL_SP_PORT2_LEFT &&
-          element != EL_SP_PORT_X &&
-          element != EL_SP_PORT_XY) ||
+          element != EL_SP_PORT_LEFT &&
+          element != EL_SP_GRAVITY_PORT_LEFT &&
+          element != EL_SP_PORT_HORIZONTAL &&
+          element != EL_SP_PORT_ANY) ||
          (dx == +1 &&
-          element != EL_SP_PORT1_RIGHT &&
-          element != EL_SP_PORT2_RIGHT &&
-          element != EL_SP_PORT_X &&
-          element != EL_SP_PORT_XY) ||
+          element != EL_SP_PORT_RIGHT &&
+          element != EL_SP_GRAVITY_PORT_RIGHT &&
+          element != EL_SP_PORT_HORIZONTAL &&
+          element != EL_SP_PORT_ANY) ||
          (dy == -1 &&
-          element != EL_SP_PORT1_UP &&
-          element != EL_SP_PORT2_UP &&
-          element != EL_SP_PORT_Y &&
-          element != EL_SP_PORT_XY) ||
+          element != EL_SP_PORT_UP &&
+          element != EL_SP_GRAVITY_PORT_UP &&
+          element != EL_SP_PORT_VERTICAL &&
+          element != EL_SP_PORT_ANY) ||
          (dy == +1 &&
-          element != EL_SP_PORT1_DOWN &&
-          element != EL_SP_PORT2_DOWN &&
-          element != EL_SP_PORT_Y &&
-          element != EL_SP_PORT_XY) ||
+          element != EL_SP_PORT_DOWN &&
+          element != EL_SP_GRAVITY_PORT_DOWN &&
+          element != EL_SP_PORT_VERTICAL &&
+          element != EL_SP_PORT_ANY) ||
          !IN_LEV_FIELD(x + dx, y + dy) ||
          !IS_FREE(x + dx, y + dy))
        return MF_NO_ACTION;
@@ -6049,10 +6162,10 @@ int DigField(struct PlayerInfo *player,
       player->programmed_action = move_direction;
       DOUBLE_PLAYER_SPEED(player);
 
-      PlaySoundLevel(x, y, SND_SP_PORT_PASSING);
+      PlaySoundLevel(x, y, SND_CLASS_SP_PORT_PASSING);
       break;
 
-    case EL_TUBE_ALL:
+    case EL_TUBE_ANY:
     case EL_TUBE_VERTICAL:
     case EL_TUBE_HORIZONTAL:
     case EL_TUBE_VERTICAL_LEFT:
@@ -6067,7 +6180,7 @@ int DigField(struct PlayerInfo *player,
        int i = 0;
        int tube_enter_directions[][2] =
        {
-         { EL_TUBE_ALL,                MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN },
+         { EL_TUBE_ANY,                MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN },
          { EL_TUBE_VERTICAL,                                MV_UP | MV_DOWN },
          { EL_TUBE_HORIZONTAL,         MV_LEFT | MV_RIGHT                   },
          { EL_TUBE_VERTICAL_LEFT,                MV_RIGHT | MV_UP | MV_DOWN },
@@ -6091,7 +6204,7 @@ int DigField(struct PlayerInfo *player,
        if (!(tube_enter_directions[i][1] & move_direction))
          return MF_NO_ACTION;  /* tube has no opening in this direction */
 
-       PlaySoundLevel(x, y, SND_TUBE_PASSING);
+       PlaySoundLevel(x, y, SND_CLASS_TUBE_PASSING);
       }
       break;
 
@@ -6107,9 +6220,9 @@ int DigField(struct PlayerInfo *player,
        return MF_NO_ACTION;
 
       if (element == EL_EXIT_OPEN)
-       PlaySoundLevel(x, y, SND_EXIT_PASSING);
+       PlaySoundLevel(x, y, SND_CLASS_EXIT_PASSING);
       else
-       PlaySoundLevel(x, y, SND_SP_EXIT_PASSING);
+       PlaySoundLevel(x, y, SND_CLASS_SP_EXIT_PASSING);
 
       break;
 
@@ -6124,9 +6237,9 @@ 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), FONT_DEFAULT_SMALL);
+      DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_TEXT_2);
       DrawLevelField(x, y);
-      PlaySoundStereo(SND_TIME_ORB_FULL_COLLECTING, SOUND_MAX_RIGHT);
+      PlaySoundStereo(SND_TIME_ORB_FULL_COLLECTING, SOUND_MIDDLE);
       return MF_ACTION;
       break;
 
@@ -6188,17 +6301,33 @@ int DigField(struct PlayerInfo *player,
          Feld[x+dx][y+dy] = EL_SOKOBAN_FIELD_FULL;
          local_player->sokobanfields_still_needed--;
          if (element == EL_SOKOBAN_OBJECT)
-           PlaySoundLevel(x, y, SND_SOKOBAN_FIELD_FILLING);
+#if 1
+           PlaySoundLevelAction(x+dx, y+dy, ACTION_FILLING);
+#else
+           PlaySoundLevel(x, y, SND_CLASS_SOKOBAN_FIELD_FILLING);
+#endif
          else
+#if 1
+           PlaySoundLevelAction(x+dx, y+dy, ACTION_PUSHING);
+#else
            PlaySoundLevel(x, y, SND_SOKOBAN_OBJECT_PUSHING);
+#endif
        }
        else
        {
          Feld[x+dx][y+dy] = EL_SOKOBAN_OBJECT;
          if (element == EL_SOKOBAN_FIELD_FULL)
+#if 1
+           PlaySoundLevelAction(x+dx, y+dy, ACTION_EMPTYING);
+#else
            PlaySoundLevel(x, y, SND_SOKOBAN_FIELD_EMPTYING);
+#endif
          else
+#if 1
+           PlaySoundLevelAction(x+dx, y+dy, ACTION_PUSHING);
+#else
            PlaySoundLevel(x, y, SND_SOKOBAN_OBJECT_PUSHING);
+#endif
        }
       }
       else
@@ -6218,7 +6347,7 @@ int DigField(struct PlayerInfo *player,
          game.emulation == EMU_SOKOBAN)
       {
        player->LevelSolved = player->GameOver = TRUE;
-       PlaySoundLevel(x, y, SND_SOKOBAN_GAME_SOLVING);
+       PlaySoundLevel(x, y, SND_GAME_SOKOBAN_SOLVING);
       }
 
       break;
@@ -6276,8 +6405,8 @@ int DigField(struct PlayerInfo *player,
 
   player->push_delay = 0;
 
-  if (Feld[x][y] != element)           /* really digged something */
-    player->is_digging = TRUE;
+  if (Feld[x][y] != element)           /* really digged/collected something */
+    player->is_collecting = !player->is_digging;
 
   return MF_MOVING;
 }
@@ -6299,7 +6428,13 @@ boolean SnapField(struct PlayerInfo *player, int dx, int dy)
       player->Pushing = FALSE;
 
     player->snapped = FALSE;
-    player->is_digging = FALSE;
+
+    if (player->MovPos == 0)
+    {
+      player->is_digging = FALSE;
+      player->is_collecting = FALSE;
+    }
+
     return FALSE;
   }
 
@@ -6316,6 +6451,8 @@ boolean SnapField(struct PlayerInfo *player, int dx, int dy)
 
   player->snapped = TRUE;
   player->is_digging = FALSE;
+  player->is_collecting = FALSE;
+
   DrawLevelField(x, y);
   BackToFront();
 
@@ -6351,7 +6488,7 @@ boolean PlaceBomb(struct PlayerInfo *player)
     player->dynamite--;
 
     DrawText(DX_DYNAMITE, DY_DYNAMITE, int2str(local_player->dynamite, 3),
-            FONT_DEFAULT_SMALL);
+            FONT_TEXT_2);
     if (IN_SCR_FIELD(SCREENX(jx), SCREENY(jy)))
     {
 #if 1
@@ -6364,18 +6501,18 @@ boolean PlaceBomb(struct PlayerInfo *player)
 #endif
     }
 
-    PlaySoundLevel(jx, jy, SND_DYNAMITE_DROPPING);
+    PlaySoundLevelAction(jx, jy, ACTION_DROPPING);
   }
   else
   {
     Feld[jx][jy] =
-      EL_DYNABOMB_PLAYER1_ACTIVE + (player->element_nr - EL_PLAYER1);
+      EL_DYNABOMB_PLAYER_1_ACTIVE + (player->element_nr - EL_PLAYER_1);
     player->dynabombs_left--;
 
     if (IN_SCR_FIELD(SCREENX(jx), SCREENY(jy)))
       DrawGraphicThruMask(SCREENX(jx), SCREENY(jy), el2img(Feld[jx][jy]), 0);
 
-    PlaySoundLevel(jx, jy, SND_DYNABOMB_DROPPING);
+    PlaySoundLevelAction(jx, jy, ACTION_DROPPING);
   }
 
   return TRUE;
@@ -6456,25 +6593,39 @@ static void PlaySoundLevelNearest(int x, int y, int sound_action)
                 sound_action);
 }
 
-static void PlaySoundLevelAction(int x, int y, int sound_action)
+static void PlaySoundLevelAction(int x, int y, int action)
 {
-  PlaySoundLevelElementAction(x, y, Feld[x][y], sound_action);
+  PlaySoundLevelElementAction(x, y, Feld[x][y], action);
 }
 
-static void PlaySoundLevelElementAction(int x, int y, int element,
-                                       int sound_action)
+static void PlaySoundLevelElementAction(int x, int y, int element, int action)
 {
-  int sound_effect = element_info[element].sound[sound_action];
+  int sound_effect = element_info[element].sound[action];
 
   if (sound_effect != SND_UNDEFINED)
     PlaySoundLevel(x, y, sound_effect);
 }
 
+static void PlaySoundLevelActionIfLoop(int x, int y, int action)
+{
+  int sound_effect = element_info[Feld[x][y]].sound[action];
+
+  if (sound_effect != SND_UNDEFINED && IS_LOOP_SOUND(sound_effect))
+    PlaySoundLevel(x, y, sound_effect);
+}
+
+static void StopSoundLevelActionIfLoop(int x, int y, int action)
+{
+  int sound_effect = element_info[Feld[x][y]].sound[action];
+
+  if (sound_effect != SND_UNDEFINED && IS_LOOP_SOUND(sound_effect))
+    StopSoundExt(sound_effect, SND_CTRL_STOP_SOUND);
+}
+
 void RaiseScore(int value)
 {
   local_player->score += value;
-  DrawText(DX_SCORE, DY_SCORE, int2str(local_player->score, 5),
-          FONT_DEFAULT_SMALL);
+  DrawText(DX_SCORE, DY_SCORE, int2str(local_player->score, 5), FONT_TEXT_2);
 }
 
 void RaiseScoreElement(int element)
@@ -6486,22 +6637,22 @@ void RaiseScoreElement(int element)
     case EL_EMERALD_YELLOW:
     case EL_EMERALD_RED:
     case EL_EMERALD_PURPLE:
-      RaiseScore(level.score[SC_EDELSTEIN]);
+      RaiseScore(level.score[SC_EMERALD]);
       break;
     case EL_DIAMOND:
-      RaiseScore(level.score[SC_DIAMANT]);
+      RaiseScore(level.score[SC_DIAMOND]);
       break;
     case EL_BUG:
     case EL_BD_BUTTERFLY:
-      RaiseScore(level.score[SC_KAEFER]);
+      RaiseScore(level.score[SC_BUG]);
       break;
     case EL_SPACESHIP:
     case EL_BD_FIREFLY:
-      RaiseScore(level.score[SC_FLIEGER]);
+      RaiseScore(level.score[SC_SPACESHIP]);
       break;
     case EL_YAMYAM:
     case EL_DARK_YAMYAM:
-      RaiseScore(level.score[SC_MAMPFER]);
+      RaiseScore(level.score[SC_YAMYAM]);
       break;
     case EL_ROBOT:
       RaiseScore(level.score[SC_ROBOT]);
@@ -6510,16 +6661,16 @@ void RaiseScoreElement(int element)
       RaiseScore(level.score[SC_PACMAN]);
       break;
     case EL_NUT:
-      RaiseScore(level.score[SC_KOKOSNUSS]);
+      RaiseScore(level.score[SC_NUT]);
       break;
     case EL_DYNAMITE:
-      RaiseScore(level.score[SC_DYNAMIT]);
+      RaiseScore(level.score[SC_DYNAMITE]);
       break;
-    case EL_KEY1:
-    case EL_KEY2:
-    case EL_KEY3:
-    case EL_KEY4:
-      RaiseScore(level.score[SC_SCHLUESSEL]);
+    case EL_KEY_1:
+    case EL_KEY_2:
+    case EL_KEY_3:
+    case EL_KEY_4:
+      RaiseScore(level.score[SC_KEY]);
       break;
     default:
       break;