rnd-20010120-2-src
[rocksndiamonds.git] / src / game.c
index 708021370a7ad3070709730611f4f61edb6225fb..af833f159489d776a35fac2cb04ac489ad6f9971 100644 (file)
@@ -1,23 +1,22 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-*  (c) 1995-98 Artsoft Entertainment                       *
-*              Holger Schemel                              *
-*              Oststrasse 11a                              *
-*              33604 Bielefeld                             *
-*              phone: ++49 +521 290471                     *
-*              email: aeglos@valinor.owl.de                *
+* (c) 1995-2001 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  game.c                                                  *
+* game.c                                                   *
 ***********************************************************/
 
+#include "libgame/libgame.h"
+
 #include "game.h"
-#include "misc.h"
 #include "tools.h"
 #include "screens.h"
-#include "sound.h"
 #include "init.h"
-#include "buttons.h"
 #include "files.h"
 #include "tape.h"
 #include "joystick.h"
@@ -167,20 +166,21 @@ static unsigned int getStateCheckSum(int counter)
 
 void GetPlayerConfig()
 {
-  if (sound_status == SOUND_OFF)
+  if (!audio.sound_available)
     setup.sound = FALSE;
 
-  if (!sound_loops_allowed)
+  if (!audio.loops_available)
   {
     setup.sound_loops = FALSE;
     setup.sound_music = FALSE;
   }
 
-  if (!fullscreen_available)
+  if (!video.fullscreen_available)
     setup.fullscreen = FALSE;
 
   setup.sound_simple = setup.sound;
 
+  SetAudioMode(setup.sound);
   InitJoysticks();
 }
 
@@ -671,10 +671,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)
+       Elementeigenschaften1[ep_slippery[i]] |= EP_BIT_SLIPPERY;
+      else
+       Elementeigenschaften1[ep_slippery[i]] &= ~EP_BIT_SLIPPERY;
+    }
+  }
+
   if (BorderElement == EL_LEERRAUM)
   {
     SBX_Left = 0;
@@ -731,7 +754,7 @@ void InitGame()
             int2str(level_nr, 2), FS_SMALL, FC_YELLOW);
   else
   {
-    DrawTextExt(drawto, gc, DX + XX_EMERALDS, DY + YY_EMERALDS,
+    DrawTextExt(drawto, DX + XX_EMERALDS, DY + YY_EMERALDS,
                int2str(level_nr, 3), FS_SMALL, FC_SPECIAL3);
     BlitBitmap(drawto, drawto,
               DX + XX_EMERALDS, DY + YY_EMERALDS + 1,
@@ -761,8 +784,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 +983,9 @@ void GameWon()
       StopSound(SND_SIRR);
   }
 
+#if 0
   FadeSounds();
+#endif
 
   /* Hero disappears */
   DrawLevelField(ExitX, ExitY);
@@ -981,11 +1006,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;
@@ -1169,9 +1196,13 @@ void RemoveMovingField(int x, int y)
       return;
   }
 
-  if (Feld[x][y] == EL_BLOCKED &&
-      (Store[oldx][oldy] == EL_MORAST_LEER ||
-       Store[oldx][oldy] == EL_MAGIC_WALL_EMPTY ||
+  if (Feld[x][y] == EL_BLOCKED && Feld[oldx][oldy] == EL_QUICKSAND_EMPTYING)
+  {
+    Feld[oldx][oldy] = EL_MORAST_LEER;
+    Store[oldx][oldy] = Store2[oldx][oldy] = 0;
+  }
+  else if (Feld[x][y] == EL_BLOCKED &&
+      (Store[oldx][oldy] == EL_MAGIC_WALL_EMPTY ||
        Store[oldx][oldy] == EL_MAGIC_WALL_BD_EMPTY ||
        Store[oldx][oldy] == EL_AMOEBE_NASS))
   {
@@ -2428,8 +2459,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,13 +2476,16 @@ 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)
     {
@@ -2535,12 +2569,21 @@ 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_FALLING(x, y+1) && !JustStopped[x][y+1] &&
+            element != EL_DX_SUPABOMB)
 #endif
     {
       boolean left  = (x>0 && IS_FREE(x-1, y) &&
@@ -2899,7 +2942,7 @@ void ContinueMoving(int x, int y)
 
   if (element == EL_TROPFEN)
     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 (CAN_FALL(element) && horiz_move &&
           y < lev_fieldy-1 && IS_BELT(Feld[x][y+1]))
@@ -2945,16 +2988,17 @@ void ContinueMoving(int x, int y)
       }
     }
 
-    if (Store[x][y] == EL_MORAST_VOLL)
+    if (element == EL_QUICKSAND_FILLING)
     {
+      element = Feld[newx][newy] = EL_MORAST_VOLL;
+      Store[newx][newy] = Store[x][y];
       Store[x][y] = 0;
-      Feld[newx][newy] = EL_MORAST_VOLL;
-      element = EL_MORAST_VOLL;
     }
-    else if (Store[x][y] == EL_MORAST_LEER)
+    else if (element == EL_QUICKSAND_EMPTYING)
     {
-      Store[x][y] = 0;
       Feld[x][y] = EL_MORAST_LEER;
+      element = Feld[newx][newy] = Store[x][y];
+      Store[x][y] = 0;
     }
     else if (Store[x][y] == EL_MAGIC_WALL_FULL)
     {
@@ -5403,12 +5447,10 @@ int DigField(struct PlayerInfo *player,
       RemoveField(x, y);
       player->key[key_nr] = TRUE;
       RaiseScoreElement(EL_SCHLUESSEL);
-      DrawMiniGraphicExt(drawto, gc,
-                        DX_KEYS+key_nr*MINI_TILEX, DY_KEYS,
-                        GFX_SCHLUESSEL1+key_nr);
-      DrawMiniGraphicExt(window, gc,
-                        DX_KEYS+key_nr*MINI_TILEX, DY_KEYS,
-                        GFX_SCHLUESSEL1+key_nr);
+      DrawMiniGraphicExt(drawto, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS,
+                        GFX_SCHLUESSEL1 + key_nr);
+      DrawMiniGraphicExt(window, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS,
+                        GFX_SCHLUESSEL1 + key_nr);
       PlaySoundLevel(x, y, SND_PONG);
       break;
     }
@@ -5423,12 +5465,10 @@ int DigField(struct PlayerInfo *player,
       RemoveField(x, y);
       player->key[key_nr] = TRUE;
       RaiseScoreElement(EL_SCHLUESSEL);
-      DrawMiniGraphicExt(drawto, gc,
-                        DX_KEYS+key_nr*MINI_TILEX, DY_KEYS,
-                        GFX_SCHLUESSEL1+key_nr);
-      DrawMiniGraphicExt(window, gc,
-                        DX_KEYS+key_nr*MINI_TILEX, DY_KEYS,
-                        GFX_SCHLUESSEL1+key_nr);
+      DrawMiniGraphicExt(drawto, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS,
+                        GFX_SCHLUESSEL1 + key_nr);
+      DrawMiniGraphicExt(window, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS,
+                        GFX_SCHLUESSEL1 + key_nr);
       PlaySoundLevel(x, y, SND_PONG);
       break;
     }
@@ -6086,7 +6126,7 @@ void CreateGameButtons()
 
   for (i=0; i<NUM_GAME_BUTTONS; i++)
   {
-    Bitmap gd_bitmap = pix[PIX_DOOR];
+    Bitmap *gd_bitmap = pix[PIX_DOOR];
     struct GadgetInfo *gi;
     int button_type;
     boolean checked;
@@ -6231,26 +6271,27 @@ 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 (sound_loops_allowed)
+      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;
 
     case SOUND_CTRL_ID_LOOPS:
       if (setup.sound_loops)
        setup.sound_loops = FALSE;
-      else if (sound_loops_allowed)
+      else if (audio.loops_available)
        setup.sound = setup.sound_loops = TRUE;
       break;
 
     case SOUND_CTRL_ID_SIMPLE:
       if (setup.sound_simple)
        setup.sound_simple = FALSE;
-      else if (sound_status==SOUND_AVAILABLE)
+      else if (audio.sound_available)
        setup.sound = setup.sound_simple = TRUE;
       break;