rnd-20020407-2-src
[rocksndiamonds.git] / src / game.c
index 3db4e1bc77d9d44717e3c7e1b913be7b625fbe07..f0bf7dd9600b8bef766243fad5256c9fdd382372 100644 (file)
 #include "init.h"
 #include "files.h"
 #include "tape.h"
-#include "joystick.h"
 #include "network.h"
 
 /* this switch controls how rocks move horizontally */
 #define OLD_GAME_BEHAVIOUR     FALSE
 
+/* EXPERIMENTAL STUFF */
+#define USE_NEW_AMOEBA_CODE    FALSE
+
 /* for DigField() */
 #define DF_NO_PUSH             0
 #define DF_DIG                 1
@@ -171,10 +173,10 @@ void GetPlayerConfig()
     setup.sound = FALSE;
 
   if (!audio.loops_available)
-  {
     setup.sound_loops = FALSE;
+
+  if (!audio.music_available)
     setup.sound_music = FALSE;
-  }
 
   if (!video.fullscreen_available)
     setup.fullscreen = FALSE;
@@ -268,7 +270,7 @@ static void InitField(int x, int y, boolean init_game)
 
          StorePlayer[x][y] = Feld[x][y];
 
-         if (options.verbose)
+         if (options.debug)
          {
            printf("Player %d activated.\n", player->element_nr);
            printf("[Local player is %d and currently %s.]\n",
@@ -437,6 +439,14 @@ void InitGame()
   boolean emulate_sb = TRUE;   /* unless non-SOKOBAN     elements found */
   boolean emulate_sp = TRUE;   /* unless non-SUPAPLEX    elements found */
 
+#if DEBUG
+#if USE_NEW_AMOEBA_CODE
+  printf("Using new amoeba code.\n");
+#else
+  printf("Using old amoeba code.\n");
+#endif
+#endif
+
   /* don't play tapes over network */
   network_playing = (options.network && !tape.playing);
 
@@ -485,6 +495,7 @@ void InitGame()
 
     player->move_delay = 0;
     player->last_move_dir = MV_NO_MOVING;
+    player->is_moving = FALSE;
 
     player->move_delay_value =
       (level.double_speed ? MOVE_DELAY_HIGH_SPEED : MOVE_DELAY_NORMAL_SPEED);
@@ -658,7 +669,7 @@ void InitGame()
        tape.player_participates[i] = TRUE;
   }
 
-  if (options.verbose)
+  if (options.debug)
   {
     for (i=0; i<MAX_PLAYERS; i++)
     {
@@ -681,7 +692,7 @@ void InitGame()
 
   /* dynamically adjust element properties according to game engine version */
   {
-    static int ep_slippery[] =
+    static int ep_em_slippery_wall[] =
     {
       EL_BETON,
       EL_MAUERWERK,
@@ -690,14 +701,30 @@ void InitGame()
       EL_MAUER_Y,
       EL_MAUER_XY
     };
-    static int ep_slippery_num = sizeof(ep_slippery)/sizeof(int);
+#if 1
+    static int ep_em_slippery_wall_num = SIZEOF_ARRAY_INT(ep_em_slippery_wall);
+#else
+    static int ep_em_slippery_wall_num =
+      sizeof(ep_em_slippery_wall) / sizeof(int);
+#endif
+
+    /*
+    printf("level %d: game.version == %06d\n", level_nr, level.game_version);
+    printf("         file_version == %06d\n", level.file_version);
+    */
 
-    for (i=0; i<ep_slippery_num; i++)
+    for (i=0; i<ep_em_slippery_wall_num; i++)
     {
+#if 1
+      if (level.em_slippery_gems)      /* special EM style gems behaviour */
+#else
       if (game.version >= GAME_VERSION_2_0)
-       Elementeigenschaften2[ep_slippery[i]] |= EP_BIT_SLIPPERY_GEMS;
+#endif
+       Elementeigenschaften2[ep_em_slippery_wall[i]] |=
+         EP_BIT_EM_SLIPPERY_WALL;
       else
-       Elementeigenschaften2[ep_slippery[i]] &= ~EP_BIT_SLIPPERY_GEMS;
+       Elementeigenschaften2[ep_em_slippery_wall[i]] &=
+         ~EP_BIT_EM_SLIPPERY_WALL;
     }
   }
 
@@ -775,6 +802,7 @@ void InitGame()
           int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW);
 
   UnmapGameButtons();
+  UnmapTapeButtons();
   game_gadget[SOUND_CTRL_ID_MUSIC]->checked = setup.sound_music;
   game_gadget[SOUND_CTRL_ID_LOOPS]->checked = setup.sound_loops;
   game_gadget[SOUND_CTRL_ID_SIMPLE]->checked = setup.sound_simple;
@@ -792,7 +820,7 @@ void InitGame()
 
   KeyboardAutoRepeatOff();
 
-  if (options.verbose)
+  if (options.debug)
   {
     for (i=0; i<4; i++)
       printf("Player %d %sactive.\n",
@@ -941,12 +969,12 @@ void GameWon()
 
   if (TimeLeft)
   {
-    if (setup.sound_loops)
+    if (!tape.playing && setup.sound_loops)
       PlaySoundExt(SND_SIRR, PSND_MAX_VOLUME, PSND_MAX_RIGHT, PSND_LOOP);
 
     while(TimeLeft > 0)
     {
-      if (!setup.sound_loops)
+      if (!tape.playing && !setup.sound_loops)
        PlaySoundStereo(SND_SIRR, PSND_MAX_RIGHT);
       if (TimeLeft > 0 && !(TimeLeft % 10))
        RaiseScore(level.score[SC_ZEITBONUS]);
@@ -956,20 +984,22 @@ void GameWon()
        TimeLeft--;
       DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW);
       BackToFront();
-      Delay(10);
+
+      if (!tape.playing)
+       Delay(10);
     }
 
-    if (setup.sound_loops)
+    if (!tape.playing && setup.sound_loops)
       StopSound(SND_SIRR);
   }
   else if (level.time == 0)            /* level without time limit */
   {
-    if (setup.sound_loops)
+    if (!tape.playing && setup.sound_loops)
       PlaySoundExt(SND_SIRR, PSND_MAX_VOLUME, PSND_MAX_RIGHT, PSND_LOOP);
 
     while(TimePlayed < 999)
     {
-      if (!setup.sound_loops)
+      if (!tape.playing && !setup.sound_loops)
        PlaySoundStereo(SND_SIRR, PSND_MAX_RIGHT);
       if (TimePlayed < 999 && !(TimePlayed % 10))
        RaiseScore(level.score[SC_ZEITBONUS]);
@@ -979,10 +1009,12 @@ void GameWon()
        TimePlayed++;
       DrawText(DX_TIME, DY_TIME, int2str(TimePlayed, 3), FS_SMALL, FC_YELLOW);
       BackToFront();
-      Delay(10);
+
+      if (!tape.playing)
+       Delay(10);
     }
 
-    if (setup.sound_loops)
+    if (!tape.playing && setup.sound_loops)
       StopSound(SND_SIRR);
   }
 
@@ -1021,13 +1053,19 @@ void GameWon()
     game_status = HALLOFFAME;
     DrawHallOfFame(hi_pos);
     if (raise_level)
+    {
       level_nr++;
+      TapeErase();
+    }
   }
   else
   {
     game_status = MAINMENU;
     if (raise_level)
+    {
       level_nr++;
+      TapeErase();
+    }
     DrawMainMenu();
   }
 
@@ -2604,7 +2642,7 @@ void StartMoving(int x, int y)
 #endif
 #else
     else if ((IS_SLIPPERY(Feld[x][y+1]) ||
-             (IS_SLIPPERY_GEMS(Feld[x][y+1]) && IS_GEM(element))) &&
+             (IS_EM_SLIPPERY_WALL(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
@@ -4200,9 +4238,10 @@ 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 jx = player->jx, jy = player->jy;
   int left     = player_action & JOY_LEFT;
   int right    = player_action & JOY_RIGHT;
   int up       = player_action & JOY_UP;
@@ -4220,7 +4259,9 @@ 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)
@@ -4232,15 +4273,20 @@ static void PlayerActions(struct PlayerInfo *player, byte player_action)
       moved = MoveFigure(player, dx, dy);
     }
 
+#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
   {
@@ -4250,23 +4296,49 @@ static void PlayerActions(struct PlayerInfo *player, byte player_action)
     SnapField(player, 0, 0);
     CheckGravityMovement(player);
 
+#if 1
+    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 (++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);
 
@@ -4290,6 +4362,7 @@ static void PlayerActions(struct PlayerInfo *player, byte player_action)
       }
     }
   }
+#endif
 }
 
 void GameActions()
@@ -4307,6 +4380,9 @@ void GameActions()
   action_delay_value =
     (tape.playing && tape.fast_forward ? FfwdFrameDelay : GameFrameDelay);
 
+  if (tape.playing && tape.index_search)
+    action_delay_value = 0;
+
   /* ---------- main game synchronization point ---------- */
 
   WaitUntilDelayReached(&action_delay, action_delay_value);
@@ -4341,11 +4417,6 @@ void GameActions()
   if (tape.pausing)
     return;
 
-  if (tape.playing)
-    TapePlayDelay();
-  else if (tape.recording)
-    TapeRecordDelay();
-
   recorded_player_action = (tape.playing ? TapePlayAction() : NULL);
 
   for (i=0; i<MAX_PLAYERS; i++)
@@ -4457,10 +4528,12 @@ void GameActions()
       AmoebeWaechst(x, y);
     else if (element == EL_DEAMOEBING)
       AmoebeSchrumpft(x, y);
-#if 0
+
+#if !USE_NEW_AMOEBA_CODE
     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)
@@ -4544,8 +4617,8 @@ void GameActions()
     }
   }
 
-#if 1
-  /* new experimental amoeba growth stuff*/
+#if USE_NEW_AMOEBA_CODE
+  /* new experimental amoeba growth stuff */
 #if 1
   if (!(FrameCounter % 8))
 #endif
@@ -4892,9 +4965,15 @@ boolean MoveFigure(struct PlayerInfo *player, int dx, int dy)
   if (!player->active || (!dx && !dy))
     return FALSE;
 
+#if 0
   if (!FrameReached(&player->move_delay, player->move_delay_value) &&
       !tape.playing)
     return FALSE;
+#else
+  if (!FrameReached(&player->move_delay, player->move_delay_value) &&
+      !(tape.playing && tape.game_version < GAME_VERSION_2_0))
+    return FALSE;
+#endif
 
   /* remove the last programmed player action */
   player->programmed_action = 0;
@@ -5023,12 +5102,16 @@ boolean MoveFigure(struct PlayerInfo *player, int dx, int dy)
     DrawLevelField(jx, jy);    /* for "ErdreichAnbroeckeln()" */
 
     player->last_move_dir = player->MovDir;
+    player->is_moving = TRUE;
   }
   else
   {
     CheckGravityMovement(player);
 
+    /*
     player->last_move_dir = MV_NO_MOVING;
+    */
+    player->is_moving = FALSE;
   }
 
   TestIfHeroTouchesBadThing(jx, jy);
@@ -5126,17 +5209,17 @@ void ScrollScreen(struct PlayerInfo *player, int mode)
     ScreenMovDir = MV_NO_MOVING;
 }
 
-void TestIfGoodThingHitsBadThing(int goodx, int goody, int move_dir)
+void TestIfGoodThingHitsBadThing(int good_x, int good_y, int good_move_dir)
 {
-  int i, killx = goodx, killy = goody;
-  static int xy[4][2] =
+  int i, kill_x = -1, kill_y = -1;
+  static int test_xy[4][2] =
   {
     { 0, -1 },
     { -1, 0 },
     { +1, 0 },
     { 0, +1 }
   };
-  static int xy_dir[4] =
+  static int test_dir[4] =
   {
     MV_UP,
     MV_LEFT,
@@ -5146,59 +5229,62 @@ void TestIfGoodThingHitsBadThing(int goodx, int goody, int move_dir)
 
   for (i=0; i<4; i++)
   {
-    int x, y, element;
+    int test_x, test_y, test_move_dir, test_element;
 
-    x = goodx + xy[i][0];
-    y = goody + xy[i][1];
-    if (!IN_LEV_FIELD(x, y))
+    test_x = good_x + test_xy[i][0];
+    test_y = good_y + test_xy[i][1];
+    if (!IN_LEV_FIELD(test_x, test_y))
       continue;
 
+    test_move_dir =
+      (IS_MOVING(test_x, test_y) ? MovDir[test_x][test_y] : MV_NO_MOVING);
+
 #if 0
-    element = Feld[x][y];
+    test_element = Feld[test_x][test_y];
 #else
-    element = MovingOrBlocked2ElementIfNotLeaving(x, y);
+    test_element = MovingOrBlocked2ElementIfNotLeaving(test_x, test_y);
 #endif
 
     /* 1st case: good thing is moving towards DONT_GO_TO style bad thing;
        2nd case: DONT_TOUCH style bad thing does not move away from good thing
     */
-    if ((DONT_GO_TO(element) && move_dir == xy_dir[i]) ||
-       (DONT_TOUCH(element) && MovDir[x][y] != xy_dir[i]))
+    if ((DONT_GO_TO(test_element) && good_move_dir == test_dir[i]) ||
+       (DONT_TOUCH(test_element) && test_move_dir != test_dir[i]))
     {
-      killx = x;
-      killy = y;
+      kill_x = test_x;
+      kill_y = test_y;
       break;
     }
   }
 
-  if (killx != goodx || killy != goody)
+  if (kill_x != -1 || kill_y != -1)
   {
-    if (IS_PLAYER(goodx, goody))
+    if (IS_PLAYER(good_x, good_y))
     {
-      struct PlayerInfo *player = PLAYERINFO(goodx, goody);
+      struct PlayerInfo *player = PLAYERINFO(good_x, good_y);
 
       if (player->shield_active_time_left > 0)
-       Bang(killx, killy);
-      else if (!PLAYER_PROTECTED(goodx, goody))
+       Bang(kill_x, kill_y);
+      else if (!PLAYER_PROTECTED(good_x, good_y))
        KillHero(player);
     }
     else
-      Bang(goodx, goody);
+      Bang(good_x, good_y);
   }
 }
 
-void TestIfBadThingHitsGoodThing(int badx, int bady, int move_dir)
+void TestIfBadThingHitsGoodThing(int bad_x, int bad_y, int bad_move_dir)
 {
-  int i, killx = badx, killy = bady;
-  int bad_element = Feld[badx][bady];
-  static int xy[4][2] =
+  int i, kill_x = -1, kill_y = -1;
+  int bad_element = Feld[bad_x][bad_y];
+  static int test_xy[4][2] =
   {
     { 0, -1 },
     { -1, 0 },
     { +1, 0 },
     { 0, +1 }
   };
-  static int xy_dir[4] =
+  static int test_dir[4] =
   {
     MV_UP,
     MV_LEFT,
@@ -5211,74 +5297,76 @@ void TestIfBadThingHitsGoodThing(int badx, int bady, int move_dir)
 
   for (i=0; i<4; i++)
   {
-    int x, y, element;
+    int test_x, test_y, test_move_dir, test_element;
 
-    x = badx + xy[i][0];
-    y = bady + xy[i][1];
-    if (!IN_LEV_FIELD(x, y))
+    test_x = bad_x + test_xy[i][0];
+    test_y = bad_y + test_xy[i][1];
+    if (!IN_LEV_FIELD(test_x, test_y))
       continue;
 
-    element = Feld[x][y];
+    test_move_dir =
+      (IS_MOVING(test_x, test_y) ? MovDir[test_x][test_y] : MV_NO_MOVING);
+
+    test_element = Feld[test_x][test_y];
 
     /* 1st case: good thing is moving towards DONT_GO_TO style bad thing;
        2nd case: DONT_TOUCH style bad thing does not move away from good thing
     */
-    if ((DONT_GO_TO(bad_element) && move_dir == xy_dir[i]) ||
-       (DONT_TOUCH(bad_element) && MovDir[x][y] != xy_dir[i]))
+    if ((DONT_GO_TO(bad_element) &&  bad_move_dir == test_dir[i]) ||
+       (DONT_TOUCH(bad_element) && test_move_dir != test_dir[i]))
     {
       /* good thing is player or penguin that does not move away */
-      if (IS_PLAYER(x, y))
+      if (IS_PLAYER(test_x, test_y))
       {
-       struct PlayerInfo *player = PLAYERINFO(x, y);
+       struct PlayerInfo *player = PLAYERINFO(test_x, test_y);
 
-       if (bad_element == EL_ROBOT && player->last_move_dir)
-         continue;     /* robot does not kill player if he moves */
+       if (bad_element == EL_ROBOT && player->is_moving)
+         continue;     /* robot does not kill player if he is moving */
 
-       killx = x;
-       killy = y;
+       kill_x = test_x;
+       kill_y = test_y;
        break;
       }
-      else if (element == EL_PINGUIN &&
-              (MovDir[x][y] != xy_dir[i] || !IS_MOVING(x, y)))
+      else if (test_element == EL_PINGUIN)
       {
-       killx = x;
-       killy = y;
+       kill_x = test_x;
+       kill_y = test_y;
        break;
       }
     }
   }
 
-  if (killx != badx || killy != bady)
+  if (kill_x != -1 || kill_y != -1)
   {
-    if (IS_PLAYER(killx, killy))
+    if (IS_PLAYER(kill_x, kill_y))
     {
-      struct PlayerInfo *player = PLAYERINFO(killx, killy);
+      struct PlayerInfo *player = PLAYERINFO(kill_x, kill_y);
 
 #if 0
       int dir = player->MovDir;
       int newx = player->jx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
       int newy = player->jy + (dir == MV_UP   ? -1 : dir == MV_DOWN  ? +1 : 0);
 
-      if (Feld[badx][bady] == EL_ROBOT && player->last_move_dir &&
-         newx != badx && newy != bady)
-       ;       /* robot does not kill player if he moves */
+      if (Feld[bad_x][bad_y] == EL_ROBOT && player->is_moving &&
+         newx != bad_x && newy != bad_y)
+       ;       /* robot does not kill player if he is moving */
       else
        printf("-> %d\n", player->MovDir);
 
-      if (Feld[badx][bady] == EL_ROBOT && player->last_move_dir &&
-         newx != badx && newy != bady)
-       ;       /* robot does not kill player if he moves */
+      if (Feld[bad_x][bad_y] == EL_ROBOT && player->is_moving &&
+         newx != bad_x && newy != bad_y)
+       ;       /* robot does not kill player if he is moving */
       else
        ;
 #endif
 
       if (player->shield_active_time_left > 0)
-       Bang(badx, bady);
-      else if (!PLAYER_PROTECTED(killx, killy))
+       Bang(bad_x, bad_y);
+      else if (!PLAYER_PROTECTED(kill_x, kill_y))
        KillHero(player);
     }
     else
-      Bang(killx, killy);
+      Bang(kill_x, kill_y);
   }
 }
 
@@ -5312,9 +5400,9 @@ void TestIfBadThingTouchesFriend(int x, int y)
   TestIfBadThingHitsGoodThing(x, y, MV_NO_MOVING);
 }
 
-void TestIfBadThingTouchesOtherBadThing(int badx, int bady)
+void TestIfBadThingTouchesOtherBadThing(int bad_x, int bad_y)
 {
-  int i, killx = badx, killy = bady;
+  int i, kill_x = bad_x, kill_y = bad_y;
   static int xy[4][2] =
   {
     { 0, -1 },
@@ -5327,8 +5415,8 @@ void TestIfBadThingTouchesOtherBadThing(int badx, int bady)
   {
     int x, y, element;
 
-    x=badx + xy[i][0];
-    y=bady + xy[i][1];
+    x = bad_x + xy[i][0];
+    y = bad_y + xy[i][1];
     if (!IN_LEV_FIELD(x, y))
       continue;
 
@@ -5336,14 +5424,14 @@ void TestIfBadThingTouchesOtherBadThing(int badx, int bady)
     if (IS_AMOEBOID(element) || element == EL_LIFE ||
        element == EL_AMOEBING || element == EL_TROPFEN)
     {
-      killx = x;
-      killy = y;
+      kill_x = x;
+      kill_y = y;
       break;
     }
   }
 
-  if (killx != badx || killy != bady)
-    Bang(badx, bady);
+  if (kill_x != bad_x || kill_y != bad_y)
+    Bang(bad_x, bad_y);
 }
 
 void KillHero(struct PlayerInfo *player)
@@ -5735,9 +5823,16 @@ int DigField(struct PlayerInfo *player,
 
       if (player->push_delay == 0)
        player->push_delay = FrameCounter;
+#if 0
       if (!FrameReached(&player->push_delay, player->push_delay_value) &&
          !tape.playing && element != EL_SPRING)
        return MF_NO_ACTION;
+#else
+      if (!FrameReached(&player->push_delay, player->push_delay_value) &&
+         !(tape.playing && tape.game_version < GAME_VERSION_2_0) &&
+         element != EL_SPRING)
+       return MF_NO_ACTION;
+#endif
 
       RemoveField(x, y);
       Feld[x+dx][y+dy] = element;
@@ -5970,9 +6065,16 @@ int DigField(struct PlayerInfo *player,
 
       if (player->push_delay == 0)
        player->push_delay = FrameCounter;
+#if 0
       if (!FrameReached(&player->push_delay, player->push_delay_value) &&
          !tape.playing && element != EL_BALLOON)
        return MF_NO_ACTION;
+#else
+      if (!FrameReached(&player->push_delay, player->push_delay_value) &&
+         !(tape.playing && tape.game_version < GAME_VERSION_2_0) &&
+         element != EL_BALLOON)
+       return MF_NO_ACTION;
+#endif
 
       if (IS_SB_ELEMENT(element))
       {
@@ -6203,6 +6305,31 @@ void RaiseScoreElement(int element)
   }
 }
 
+void RequestQuitGame(boolean ask_if_really_quit)
+{
+  if (AllPlayersGone ||
+      !ask_if_really_quit ||
+      level_editor_test_game ||
+      Request("Do you really want to quit the game ?",
+             REQ_ASK | REQ_STAY_CLOSED))
+  {
+#if defined(PLATFORM_UNIX)
+    if (options.network)
+      SendToServer_StopPlaying();
+    else
+#endif
+    {
+      game_status = MAINMENU;
+      DrawMainMenu();
+    }
+  }
+  else
+  {
+    OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
+  }
+}
+
+
 /* ---------- new game button stuff ---------------------------------------- */
 
 /* graphic position values for game buttons */
@@ -6351,30 +6478,7 @@ static void HandleGameButtons(struct GadgetInfo *gi)
   switch (id)
   {
     case GAME_CTRL_ID_STOP:
-      if (AllPlayersGone)
-      {
-       CloseDoor(DOOR_CLOSE_1);
-       game_status = MAINMENU;
-       DrawMainMenu();
-       break;
-      }
-
-      if (level_editor_test_game ||
-         Request("Do you really want to quit the game ?",
-                 REQ_ASK | REQ_STAY_CLOSED))
-      { 
-#if defined(PLATFORM_UNIX)
-       if (options.network)
-         SendToServer_StopPlaying();
-       else
-#endif
-       {
-         game_status = MAINMENU;
-         DrawMainMenu();
-       }
-      }
-      else
-       OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
+      RequestQuitGame(TRUE);
       break;
 
     case GAME_CTRL_ID_PAUSE:
@@ -6412,7 +6516,7 @@ static void HandleGameButtons(struct GadgetInfo *gi)
        setup.sound_music = FALSE;
        FadeMusic();
       }
-      else if (audio.loops_available)
+      else if (audio.music_available)
       { 
        setup.sound = setup.sound_music = TRUE;
        if (num_bg_loops)