rnd-20010122-3-src
[rocksndiamonds.git] / src / game.c
index ab7dbb5576784c19827a55245935f8097e0f98fa..a4940d9692de05210c2eb74ec6468f82e68477b9 100644 (file)
@@ -1,7 +1,7 @@
 /***********************************************************
 * Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-* (c) 1995-2000 Artsoft Entertainment                      *
+* (c) 1995-2001 Artsoft Entertainment                      *
 *               Holger Schemel                             *
 *               Detmolder Strasse 189                      *
 *               33604 Bielefeld                            *
 
 /* for Explode() */
 #define EX_PHASE_START         0
-#define EX_NORMAL              0
-#define EX_CENTER              1
-#define EX_BORDER              2
+#define EX_NO_EXPLOSION                0
+#define EX_NORMAL              1
+#define EX_CENTER              2
+#define EX_BORDER              3
 
 /* special positions in the game control window (relative to control window) */
 #define XX_LEVEL               37
@@ -533,6 +534,7 @@ void InitGame()
   game.timegate_time_left = 0;
   game.switchgate_pos = 0;
   game.balloon_dir = MV_NO_MOVING;
+  game.explosions_delayed = TRUE;
 
   for (i=0; i<4; i++)
   {
@@ -554,6 +556,7 @@ void InitGame()
       AmoebaNr[x][y] = 0;
       JustStopped[x][y] = 0;
       Stop[x][y] = FALSE;
+      ExplodeField[x][y] = EX_NO_EXPLOSION;
     }
   }
 
@@ -671,10 +674,33 @@ void InitGame()
     }
   }
 
+  game.version = (tape.playing ? tape.game_version : level.game_version);
   game.emulation = (emulate_bd ? EMU_BOULDERDASH :
                    emulate_sb ? EMU_SOKOBAN :
                    emulate_sp ? EMU_SUPAPLEX : EMU_NONE);
 
+  /* dynamically adjust element properties according to game engine version */
+  {
+    static int ep_slippery[] =
+    {
+      EL_BETON,
+      EL_MAUERWERK,
+      EL_MAUER_LEBT,
+      EL_MAUER_X,
+      EL_MAUER_Y,
+      EL_MAUER_XY
+    };
+    static int ep_slippery_num = sizeof(ep_slippery)/sizeof(int);
+
+    for (i=0; i<ep_slippery_num; i++)
+    {
+      if (game.version >= GAME_VERSION_2_0)
+       Elementeigenschaften2[ep_slippery[i]] |= EP_BIT_SLIPPERY_GEMS;
+      else
+       Elementeigenschaften2[ep_slippery[i]] &= ~EP_BIT_SLIPPERY_GEMS;
+    }
+  }
+
   if (BorderElement == EL_LEERRAUM)
   {
     SBX_Left = 0;
@@ -761,8 +787,8 @@ void InitGame()
 
   OpenDoor(DOOR_OPEN_ALL);
 
-  if (setup.sound_music)
-    PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
+  if (setup.sound_music && num_bg_loops)
+    PlayMusic(level_nr % num_bg_loops);
 
   KeyboardAutoRepeatOff();
 
@@ -960,7 +986,9 @@ void GameWon()
       StopSound(SND_SIRR);
   }
 
+#if 0
   FadeSounds();
+#endif
 
   /* Hero disappears */
   DrawLevelField(ExitX, ExitY);
@@ -981,11 +1009,13 @@ void GameWon()
   {
     leveldir_current->handicap_level++;
     SaveLevelSetup_SeriesInfo();
-
-    if (level_nr < leveldir_current->last_level)
-      raise_level = TRUE;
   }
 
+  if (level_editor_test_game)
+    local_player->score = -1;  /* no highscore when playing from editor */
+  else if (level_nr < leveldir_current->last_level)
+    raise_level = TRUE;                /* advance to next level */
+
   if ((hi_pos = NewHiScore()) >= 0) 
   {
     game_status = HALLOFFAME;
@@ -1170,17 +1200,16 @@ void RemoveMovingField(int x, int y)
   }
 
   if (Feld[x][y] == EL_BLOCKED &&
-      (Store[oldx][oldy] == EL_MORAST_LEER ||
-       Store[oldx][oldy] == EL_MAGIC_WALL_EMPTY ||
-       Store[oldx][oldy] == EL_MAGIC_WALL_BD_EMPTY ||
-       Store[oldx][oldy] == EL_AMOEBE_NASS))
-  {
-    Feld[oldx][oldy] = Store[oldx][oldy];
-    Store[oldx][oldy] = Store2[oldx][oldy] = 0;
-  }
+      (Feld[oldx][oldy] == EL_QUICKSAND_EMPTYING ||
+       Feld[oldx][oldy] == EL_MAGIC_WALL_EMPTYING ||
+       Feld[oldx][oldy] == EL_MAGIC_WALL_BD_EMPTYING ||
+       Feld[oldx][oldy] == EL_AMOEBA_DRIPPING))
+    Feld[oldx][oldy] = get_next_element(Feld[oldx][oldy]);
   else
     Feld[oldx][oldy] = EL_LEERRAUM;
 
+  Store[oldx][oldy] = Store2[oldx][oldy] = 0;
+
   Feld[newx][newy] = EL_LEERRAUM;
   MovPos[oldx][oldy] = MovDir[oldx][oldy] = MovDelay[oldx][oldy] = 0;
   MovPos[newx][newy] = MovDir[newx][newy] = MovDelay[newx][newy] = 0;
@@ -1249,11 +1278,17 @@ void CheckDynamite(int x, int y)
 void Explode(int ex, int ey, int phase, int mode)
 {
   int x, y;
-  int num_phase = 9, delay = 2;
+  int num_phase = 9, delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
   int last_phase = num_phase * delay;
   int half_phase = (num_phase / 2) * delay;
   int first_phase_after_start = EX_PHASE_START + 1;
 
+  if (game.explosions_delayed)
+  {
+    ExplodeField[ex][ey] = mode;
+    return;
+  }
+
   if (phase == EX_PHASE_START)         /* initialize 'Store[][]' field */
   {
     int center_element = Feld[ex][ey];
@@ -1428,6 +1463,9 @@ void Explode(int ex, int ey, int phase, int mode)
     if (CAN_MOVE(element) || COULD_MOVE(element))
       InitMovDir(x, y);
     DrawLevelField(x, y);
+
+    if (IS_PLAYER(x, y) && !PLAYERINFO(x,y)->present)
+      StorePlayer[x][y] = 0;
   }
   else if (!(phase % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
   {
@@ -1441,7 +1479,15 @@ void Explode(int ex, int ey, int phase, int mode)
     if (phase == delay)
       ErdreichAnbroeckeln(SCREENX(x), SCREENY(y));
 
-    DrawGraphic(SCREENX(x), SCREENY(y), graphic + (phase / delay - 1));
+    graphic += (phase / delay - 1);
+
+    if (IS_PFORTE(Store[x][y]))
+    {
+      DrawLevelElement(x, y, Store[x][y]);
+      DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic);
+    }
+    else
+      DrawGraphic(SCREENX(x), SCREENY(y), graphic);
   }
 }
 
@@ -1851,6 +1897,13 @@ void Impact(int x, int y)
        return;
       }
     }
+    else if ((element == EL_SP_INFOTRON || element == EL_SP_ZONK) &&
+            (smashed == EL_SP_SNIKSNAK || smashed == EL_SP_ELECTRON ||
+             smashed == EL_SP_DISK_ORANGE))
+    {
+      Bang(x, y+1);
+      return;
+    }
     else if (element == EL_FELSBROCKEN ||
             element == EL_SP_ZONK ||
             element == EL_BD_ROCK)
@@ -2428,8 +2481,8 @@ void StartMoving(int x, int y)
       if (IS_FREE(x, y+1))
       {
        InitMovingField(x, y, MV_DOWN);
-       Feld[x][y] = EL_FELSBROCKEN;
-       Store[x][y] = EL_MORAST_LEER;
+       Feld[x][y] = EL_QUICKSAND_EMPTYING;
+       Store[x][y] = EL_FELSBROCKEN;
       }
       else if (Feld[x][y+1] == EL_MORAST_LEER)
       {
@@ -2445,21 +2498,24 @@ void StartMoving(int x, int y)
 
        Feld[x][y] = EL_MORAST_LEER;
        Feld[x][y+1] = EL_MORAST_VOLL;
+       Store[x][y+1] = Store[x][y];
+       Store[x][y] = 0;
       }
     }
     else if ((element == EL_FELSBROCKEN || element == EL_BD_ROCK) &&
             Feld[x][y+1] == EL_MORAST_LEER)
     {
       InitMovingField(x, y, MV_DOWN);
-      Store[x][y] = EL_MORAST_VOLL;
+      Feld[x][y] = EL_QUICKSAND_FILLING;
+      Store[x][y] = element;
     }
     else if (element == EL_MAGIC_WALL_FULL)
     {
       if (IS_FREE(x, y+1))
       {
        InitMovingField(x, y, MV_DOWN);
-       Feld[x][y] = EL_CHANGED(Store2[x][y]);
-       Store[x][y] = EL_MAGIC_WALL_EMPTY;
+       Feld[x][y] = EL_MAGIC_WALL_EMPTYING;
+       Store[x][y] = EL_CHANGED(Store[x][y]);
       }
       else if (Feld[x][y+1] == EL_MAGIC_WALL_EMPTY)
       {
@@ -2475,8 +2531,8 @@ void StartMoving(int x, int y)
 
        Feld[x][y] = EL_MAGIC_WALL_EMPTY;
        Feld[x][y+1] = EL_MAGIC_WALL_FULL;
-       Store2[x][y+1] = EL_CHANGED(Store2[x][y]);
-       Store2[x][y] = 0;
+       Store[x][y+1] = EL_CHANGED(Store[x][y]);
+       Store[x][y] = 0;
       }
     }
     else if (element == EL_MAGIC_WALL_BD_FULL)
@@ -2484,8 +2540,8 @@ void StartMoving(int x, int y)
       if (IS_FREE(x, y+1))
       {
        InitMovingField(x, y, MV_DOWN);
-       Feld[x][y] = EL_CHANGED2(Store2[x][y]);
-       Store[x][y] = EL_MAGIC_WALL_BD_EMPTY;
+       Feld[x][y] = EL_MAGIC_WALL_BD_EMPTYING;
+       Store[x][y] = EL_CHANGED2(Store[x][y]);
       }
       else if (Feld[x][y+1] == EL_MAGIC_WALL_BD_EMPTY)
       {
@@ -2501,8 +2557,8 @@ void StartMoving(int x, int y)
 
        Feld[x][y] = EL_MAGIC_WALL_BD_EMPTY;
        Feld[x][y+1] = EL_MAGIC_WALL_BD_FULL;
-       Store2[x][y+1] = EL_CHANGED2(Store2[x][y]);
-       Store2[x][y] = 0;
+       Store[x][y+1] = EL_CHANGED2(Store[x][y]);
+       Store[x][y] = 0;
       }
     }
     else if (CAN_CHANGE(element) &&
@@ -2510,10 +2566,10 @@ void StartMoving(int x, int y)
              Feld[x][y+1] == EL_MAGIC_WALL_BD_EMPTY))
     {
       InitMovingField(x, y, MV_DOWN);
-      Store[x][y] =
-       (Feld[x][y+1] == EL_MAGIC_WALL_EMPTY ? EL_MAGIC_WALL_FULL :
-        EL_MAGIC_WALL_BD_FULL);
-      Store2[x][y+1] = element;
+      Feld[x][y] =
+       (Feld[x][y+1] == EL_MAGIC_WALL_EMPTY ? EL_MAGIC_WALL_FILLING :
+        EL_MAGIC_WALL_BD_FILLING);
+      Store[x][y] = element;
     }
     else if (CAN_SMASH(element) && Feld[x][y+1] == EL_SALZSAEURE)
     {
@@ -2535,12 +2591,22 @@ void StartMoving(int x, int y)
       Feld[x][y] = EL_AMOEBING;
       Store[x][y] = EL_AMOEBE_NASS;
     }
+    /* Store[x][y+1] must be zero, because:
+       (EL_MORAST_VOLL -> EL_FELSBROCKEN): Store[x][y+1] == EL_MORAST_LEER
+    */
+#if 0
 #if OLD_GAME_BEHAVIOUR
     else if (IS_SLIPPERY(Feld[x][y+1]) && !Store[x][y+1])
 #else
     else if (IS_SLIPPERY(Feld[x][y+1]) && !Store[x][y+1] &&
             !IS_FALLING(x, y+1) && !JustStopped[x][y+1] &&
             element != EL_DX_SUPABOMB)
+#endif
+#else
+    else if ((IS_SLIPPERY(Feld[x][y+1]) ||
+             (IS_SLIPPERY_GEMS(Feld[x][y+1]) && IS_GEM(element))) &&
+            !IS_FALLING(x, y+1) && !JustStopped[x][y+1] &&
+            element != EL_DX_SUPABOMB && element != EL_SP_DISK_ORANGE)
 #endif
     {
       boolean left  = (x>0 && IS_FREE(x-1, y) &&
@@ -2897,10 +2963,16 @@ void ContinueMoving(int x, int y)
   int newx = x + dx, newy = y + dy;
   int step = (horiz_move ? dx : dy) * TILEX / 8;
 
-  if (element == EL_TROPFEN)
+  if (element == EL_TROPFEN || element == EL_AMOEBA_DRIPPING)
     step /= 2;
-  else if (Store[x][y] == EL_MORAST_VOLL || Store[x][y] == EL_MORAST_LEER)
+  else if (element == EL_QUICKSAND_FILLING ||
+          element == EL_QUICKSAND_EMPTYING)
     step /= 4;
+  else if (element == EL_MAGIC_WALL_FILLING ||
+          element == EL_MAGIC_WALL_BD_FILLING ||
+          element == EL_MAGIC_WALL_EMPTYING ||
+          element == EL_MAGIC_WALL_BD_EMPTYING)
+    step /= 2;
   else if (CAN_FALL(element) && horiz_move &&
           y < lev_fieldy-1 && IS_BELT(Feld[x][y+1]))
     step /= 2;
@@ -2945,54 +3017,55 @@ void ContinueMoving(int x, int y)
       }
     }
 
-    if (Store[x][y] == EL_MORAST_VOLL)
+    if (element == EL_QUICKSAND_FILLING)
     {
-      Store[x][y] = 0;
-      Feld[newx][newy] = EL_MORAST_VOLL;
-      element = EL_MORAST_VOLL;
+      element = Feld[newx][newy] = get_next_element(element);
+      Store[newx][newy] = Store[x][y];
     }
-    else if (Store[x][y] == EL_MORAST_LEER)
+    else if (element == EL_QUICKSAND_EMPTYING)
     {
-      Store[x][y] = 0;
-      Feld[x][y] = EL_MORAST_LEER;
+      Feld[x][y] = get_next_element(element);
+      element = Feld[newx][newy] = Store[x][y];
     }
-    else if (Store[x][y] == EL_MAGIC_WALL_FULL)
+    else if (element == EL_MAGIC_WALL_FILLING)
     {
-      Store[x][y] = 0;
-      element = Feld[newx][newy] =
-       (game.magic_wall_active ? EL_MAGIC_WALL_FULL : EL_MAGIC_WALL_DEAD);
+      element = Feld[newx][newy] = get_next_element(element);
+      if (!game.magic_wall_active)
+       element = Feld[newx][newy] = EL_MAGIC_WALL_DEAD;
+      Store[newx][newy] = Store[x][y];
     }
-    else if (Store[x][y] == EL_MAGIC_WALL_EMPTY)
+    else if (element == EL_MAGIC_WALL_EMPTYING)
     {
-      Store[x][y] = Store2[x][y] = 0;
-      Feld[x][y] = (game.magic_wall_active ? EL_MAGIC_WALL_EMPTY :
-                   EL_MAGIC_WALL_DEAD);
+      Feld[x][y] = get_next_element(element);
+      if (!game.magic_wall_active)
+       Feld[x][y] = EL_MAGIC_WALL_DEAD;
+      element = Feld[newx][newy] = Store[x][y];
     }
-    else if (Store[x][y] == EL_MAGIC_WALL_BD_FULL)
+    else if (element == EL_MAGIC_WALL_BD_FILLING)
     {
-      Store[x][y] = 0;
-      element = Feld[newx][newy] =
-       (game.magic_wall_active ? EL_MAGIC_WALL_BD_FULL :
-        EL_MAGIC_WALL_BD_DEAD);
+      element = Feld[newx][newy] = get_next_element(element);
+      if (!game.magic_wall_active)
+       element = Feld[newx][newy] = EL_MAGIC_WALL_BD_DEAD;
+      Store[newx][newy] = Store[x][y];
     }
-    else if (Store[x][y] == EL_MAGIC_WALL_BD_EMPTY)
+    else if (element == EL_MAGIC_WALL_BD_EMPTYING)
     {
-      Store[x][y] = Store2[x][y] = 0;
-      Feld[x][y] = (game.magic_wall_active ? EL_MAGIC_WALL_BD_EMPTY :
-                   EL_MAGIC_WALL_BD_DEAD);
+      Feld[x][y] = get_next_element(element);
+      if (!game.magic_wall_active)
+       Feld[x][y] = EL_MAGIC_WALL_BD_DEAD;
+      element = Feld[newx][newy] = Store[x][y];
     }
-    else if (Store[x][y] == EL_SALZSAEURE)
+    else if (element == EL_AMOEBA_DRIPPING)
     {
-      Store[x][y] = 0;
-      Feld[newx][newy] = EL_SALZSAEURE;
-      element = EL_SALZSAEURE;
+      Feld[x][y] = get_next_element(element);
+      element = Feld[newx][newy] = Store[x][y];
     }
-    else if (Store[x][y] == EL_AMOEBE_NASS)
+    else if (Store[x][y] == EL_SALZSAEURE)
     {
-      Store[x][y] = 0;
-      Feld[x][y] = EL_AMOEBE_NASS;
+      element = Feld[newx][newy] = EL_SALZSAEURE;
     }
 
+    Store[x][y] = 0;
     MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0;
     MovDelay[newx][newy] = 0;
 
@@ -3382,16 +3455,16 @@ void AmoebeAbleger(int ax, int ay)
   if (element != EL_AMOEBE_NASS || neway < ay || !IS_FREE(newax, neway) ||
       (neway == lev_fieldy - 1 && newax != ax))
   {
-    Feld[newax][neway] = EL_AMOEBING;
+    Feld[newax][neway] = EL_AMOEBING;  /* simple growth of new amoeba tile */
     Store[newax][neway] = element;
   }
   else if (neway == ay)
-    Feld[newax][neway] = EL_TROPFEN;
+    Feld[newax][neway] = EL_TROPFEN;   /* drop left or right from amoeba */
   else
   {
-    InitMovingField(ax, ay, MV_DOWN);
-    Feld[ax][ay] = EL_TROPFEN;
-    Store[ax][ay] = EL_AMOEBE_NASS;
+    InitMovingField(ax, ay, MV_DOWN);  /* drop dripping out of amoeba */
+    Feld[ax][ay] = EL_AMOEBA_DRIPPING;
+    Store[ax][ay] = EL_TROPFEN;
     ContinueMoving(ax, ay);
     return;
   }
@@ -4177,6 +4250,8 @@ static void PlayerActions(struct PlayerInfo *player, byte player_action)
     SnapField(player, 0, 0);
     CheckGravityMovement(player);
 
+    player->last_move_dir = MV_NO_MOVING;
+
     if (++player->frame_reset_delay > player->move_delay_value)
       player->Frame = 0;
   }
@@ -4366,21 +4441,25 @@ void GameActions()
     {
       StartMoving(x, y);
 
-      if (IS_GEM(element))
+      if (IS_GEM(element) || element == EL_SP_INFOTRON)
        EdelsteinFunkeln(x, y);
     }
     else if (IS_MOVING(x, y))
       ContinueMoving(x, y);
     else if (IS_ACTIVE_BOMB(element))
       CheckDynamite(x, y);
-    else if (element == EL_EXPLODING)
+#if 0
+    else if (element == EL_EXPLODING && !game.explosions_delayed)
       Explode(x, y, Frame[x][y], EX_NORMAL);
+#endif
     else if (element == EL_AMOEBING)
       AmoebeWaechst(x, y);
     else if (element == EL_DEAMOEBING)
       AmoebeSchrumpft(x, y);
+#if 0
     else if (IS_AMOEBALIVE(element))
       AmoebeAbleger(x, y);
+#endif
     else if (element == EL_LIFE || element == EL_LIFE_ASYNC)
       Life(x, y);
     else if (element == EL_ABLENK_EIN)
@@ -4440,15 +4519,16 @@ void GameActions()
       boolean sieb = FALSE;
       int jx = local_player->jx, jy = local_player->jy;
 
-      if (element == EL_MAGIC_WALL_EMPTY || element == EL_MAGIC_WALL_FULL ||
-         Store[x][y] == EL_MAGIC_WALL_EMPTY)
+      if (element == EL_MAGIC_WALL_FULL ||
+         element == EL_MAGIC_WALL_EMPTY ||
+         element == EL_MAGIC_WALL_EMPTYING)
       {
        SiebAktivieren(x, y, 1);
        sieb = TRUE;
       }
-      else if (element == EL_MAGIC_WALL_BD_EMPTY ||
-              element == EL_MAGIC_WALL_BD_FULL ||
-              Store[x][y] == EL_MAGIC_WALL_BD_EMPTY)
+      else if (element == EL_MAGIC_WALL_BD_FULL ||
+              element == EL_MAGIC_WALL_BD_EMPTY ||
+              element == EL_MAGIC_WALL_BD_EMPTYING)
       {
        SiebAktivieren(x, y, 2);
        sieb = TRUE;
@@ -4463,6 +4543,65 @@ void GameActions()
     }
   }
 
+#if 1
+  /* new experimental amoeba growth stuff*/
+#if 1
+  if (!(FrameCounter % 8))
+#endif
+  {
+    static unsigned long random = 1684108901;
+
+    for (i = 0; i < level.amoeba_speed * 28 / 8; i++)
+    {
+#if 0
+      x = (random >> 10) % lev_fieldx;
+      y = (random >> 20) % lev_fieldy;
+#else
+      x = RND(lev_fieldx);
+      y = RND(lev_fieldy);
+#endif
+      element = Feld[x][y];
+
+      if (!IS_PLAYER(x,y) &&
+         (element == EL_LEERRAUM ||
+          element == EL_ERDREICH ||
+          element == EL_MORAST_LEER ||
+          element == EL_BLURB_LEFT ||
+          element == EL_BLURB_RIGHT))
+      {
+       if ((IN_LEV_FIELD(x, y-1) && Feld[x][y-1] == EL_AMOEBE_NASS) ||
+           (IN_LEV_FIELD(x-1, y) && Feld[x-1][y] == EL_AMOEBE_NASS) ||
+           (IN_LEV_FIELD(x+1, y) && Feld[x+1][y] == EL_AMOEBE_NASS) ||
+           (IN_LEV_FIELD(x, y+1) && Feld[x][y+1] == EL_AMOEBE_NASS))
+         Feld[x][y] = EL_TROPFEN;
+      }
+
+      random = random * 129 + 1;
+    }
+  }
+#endif
+
+#if 0
+  if (game.explosions_delayed)
+#endif
+  {
+    game.explosions_delayed = FALSE;
+
+    for (y=0; y<lev_fieldy; y++) for (x=0; x<lev_fieldx; x++)
+    {
+      element = Feld[x][y];
+
+      if (ExplodeField[x][y])
+       Explode(x, y, EX_PHASE_START, ExplodeField[x][y]);
+      else if (element == EL_EXPLODING)
+       Explode(x, y, Frame[x][y], EX_NORMAL);
+
+      ExplodeField[x][y] = EX_NO_EXPLOSION;
+    }
+
+    game.explosions_delayed = TRUE;
+  }
+
   if (game.magic_wall_active)
   {
     if (!(game.magic_wall_time_left % 4))
@@ -4477,7 +4616,8 @@ void GameActions()
        {
          element = Feld[x][y];
 
-         if (element == EL_MAGIC_WALL_EMPTY || element == EL_MAGIC_WALL_FULL)
+         if (element == EL_MAGIC_WALL_EMPTY ||
+             element == EL_MAGIC_WALL_FULL)
          {
            Feld[x][y] = EL_MAGIC_WALL_DEAD;
            DrawLevelField(x, y);
@@ -5100,7 +5240,9 @@ void TestIfBadThingHitsGoodThing(int badx, int bady)
     {
       struct PlayerInfo *player = PLAYERINFO(killx, killy);
 
-      if (player->shield_active_time_left > 0)
+      if (Feld[badx][bady] == EL_ROBOT && player->last_move_dir)
+       ;       /* robot does not kill player if he moves */
+      else if (player->shield_active_time_left > 0)
        Bang(badx, bady);
       else if (!PLAYER_PROTECTED(killx, killy))
        KillHero(player);
@@ -5210,7 +5352,8 @@ void RemoveHero(struct PlayerInfo *player)
   player->present = FALSE;
   player->active = FALSE;
 
-  StorePlayer[jx][jy] = 0;
+  if (!ExplodeField[jx][jy])
+    StorePlayer[jx][jy] = 0;
 
   for (i=0; i<MAX_PLAYERS; i++)
     if (stored_player[i].active)
@@ -6227,12 +6370,13 @@ static void HandleGameButtons(struct GadgetInfo *gi)
       if (setup.sound_music)
       { 
        setup.sound_music = FALSE;
-       FadeSound(background_loop[level_nr % num_bg_loops]);
+       FadeMusic();
       }
       else if (audio.loops_available)
       { 
        setup.sound = setup.sound_music = TRUE;
-       PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
+       if (num_bg_loops)
+         PlayMusic(level_nr % num_bg_loops);
       }
       break;