rnd-20020803-1-src
[rocksndiamonds.git] / src / game.c
index 020cdc8910375e5e1271d8f6c561cb41c685b48a..bc31c194de0672b1a07164c40710502c6d7562ca 100644 (file)
@@ -1,7 +1,7 @@
 /***********************************************************
 * Rocks'n'Diamonds -- McDuffin Strikes Back!               *
 *----------------------------------------------------------*
-* (c) 1995-2001 Artsoft Entertainment                      *
+* (c) 1995-2002 Artsoft Entertainment                      *
 *               Holger Schemel                             *
 *               Detmolder Strasse 189                      *
 *               33604 Bielefeld                            *
 #define DX_TIME                        (DX + XX_TIME)
 #define DY_TIME                        (DY + YY_TIME)
 
+/* values for initial player move delay (initial delay counter value) */
+#define INITIAL_MOVE_DELAY_OFF -1
+#define INITIAL_MOVE_DELAY_ON  0
+
 /* values for player movement speed (which is in fact a delay value) */
 #define MOVE_DELAY_NORMAL_SPEED        8
 #define MOVE_DELAY_HIGH_SPEED  4
@@ -136,6 +140,7 @@ static struct
   { ".burning",                SND_ACTION_BURNING,     TRUE },
   { ".growing",                SND_ACTION_UNKNOWN,     TRUE },
   { ".attacking",      SND_ACTION_UNKNOWN,     TRUE },
+  { ".activated",      SND_ACTION_UNKNOWN,     TRUE },
 
   /* other (non-loop) sound actions are optional */
   { ".stepping",       SND_ACTION_MOVING,      FALSE }, /* discrete moving */
@@ -491,9 +496,18 @@ void DrawGameDoorValues()
           int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW);
 }
 
-void InitGameEngine()
+
+/*
+  =============================================================================
+  InitGameSound()
+  -----------------------------------------------------------------------------
+  initialize sound effect lookup table for element actions
+  =============================================================================
+*/
+
+void InitGameSound()
 {
-  static int sound_effect_properties[NUM_SOUND_EFFECTS];
+  int sound_effect_properties[NUM_SOUND_EFFECTS];
   int i, j;
 
 #if 0
@@ -575,12 +589,87 @@ void InitGameEngine()
 #endif
 }
 
+
+/*
+  =============================================================================
+  InitGameEngine()
+  -----------------------------------------------------------------------------
+  initialize game engine due to level / tape version number
+  =============================================================================
+*/
+
+static void InitGameEngine()
+{
+  int i;
+
+  game.engine_version = (tape.playing ? tape.engine_version :
+                        level.game_version);
+
+#if 0
+    printf("level %d: level version == %06d\n", level_nr, level.game_version);
+    printf("          tape version == %06d [%s] [file: %06d]\n",
+          tape.engine_version, (tape.playing ? "PLAYING" : "RECORDING"),
+          tape.file_version);
+    printf("       => game.engine_version == %06d\n", game.engine_version);
+#endif
+
+  /* dynamically adjust player properties according to game engine version */
+  game.initial_move_delay =
+    (game.engine_version <= VERSION_IDENT(2,0,1) ? INITIAL_MOVE_DELAY_ON :
+     INITIAL_MOVE_DELAY_OFF);
+
+  /* dynamically adjust player properties according to level information */
+  game.initial_move_delay_value =
+    (level.double_speed ? MOVE_DELAY_HIGH_SPEED : MOVE_DELAY_NORMAL_SPEED);
+
+  /* dynamically adjust element properties according to game engine version */
+  {
+    static int ep_em_slippery_wall[] =
+    {
+      EL_BETON,
+      EL_MAUERWERK,
+      EL_MAUER_LEBT,
+      EL_MAUER_X,
+      EL_MAUER_Y,
+      EL_MAUER_XY
+    };
+    static int ep_em_slippery_wall_num = SIZEOF_ARRAY_INT(ep_em_slippery_wall);
+
+    for (i=0; i<ep_em_slippery_wall_num; i++)
+    {
+      if (level.em_slippery_gems)      /* special EM style gems behaviour */
+       Elementeigenschaften2[ep_em_slippery_wall[i]] |=
+         EP_BIT_EM_SLIPPERY_WALL;
+      else
+       Elementeigenschaften2[ep_em_slippery_wall[i]] &=
+         ~EP_BIT_EM_SLIPPERY_WALL;
+    }
+
+    /* "EL_MAUERND" was not slippery for EM gems in version 2.0.1 */
+    if (level.em_slippery_gems && game.engine_version > VERSION_IDENT(2,0,1))
+      Elementeigenschaften2[EL_MAUERND] |=  EP_BIT_EM_SLIPPERY_WALL;
+    else
+      Elementeigenschaften2[EL_MAUERND] &= ~EP_BIT_EM_SLIPPERY_WALL;
+  }
+}
+
+
+/*
+  =============================================================================
+  InitGame()
+  -----------------------------------------------------------------------------
+  initialize and start new game
+  =============================================================================
+*/
+
 void InitGame()
 {
-  int i, j, x, y;
   boolean emulate_bd = TRUE;   /* unless non-BOULDERDASH elements found */
   boolean emulate_sb = TRUE;   /* unless non-SOKOBAN     elements found */
   boolean emulate_sp = TRUE;   /* unless non-SUPAPLEX    elements found */
+  int i, j, x, y;
+
+  InitGameEngine();
 
 #if DEBUG
 #if USE_NEW_AMOEBA_CODE
@@ -636,9 +725,8 @@ void InitGame()
     player->last_move_dir = MV_NO_MOVING;
     player->is_moving = FALSE;
 
-    player->move_delay = -1;   /* no initial move delay */
-    player->move_delay_value =
-      (level.double_speed ? MOVE_DELAY_HIGH_SPEED : MOVE_DELAY_NORMAL_SPEED);
+    player->move_delay       = game.initial_move_delay;
+    player->move_delay_value = game.initial_move_delay_value;
 
     player->push_delay = 0;
     player->push_delay_value = 5;
@@ -729,6 +817,10 @@ void InitGame()
     }
   }
 
+  game.emulation = (emulate_bd ? EMU_BOULDERDASH :
+                   emulate_sb ? EMU_SOKOBAN :
+                   emulate_sp ? EMU_SUPAPLEX : EMU_NONE);
+
   /* correct non-moving belts to start moving left */
   for (i=0; i<4; i++)
     if (game.belt_dir[i] == MV_NO_MOVING)
@@ -828,49 +920,6 @@ 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_em_slippery_wall[] =
-    {
-      EL_BETON,
-      EL_MAUERWERK,
-      EL_MAUER_LEBT,
-      EL_MAUER_X,
-      EL_MAUER_Y,
-      EL_MAUER_XY
-    };
-#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_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)
-#endif
-       Elementeigenschaften2[ep_em_slippery_wall[i]] |=
-         EP_BIT_EM_SLIPPERY_WALL;
-      else
-       Elementeigenschaften2[ep_em_slippery_wall[i]] &=
-         ~EP_BIT_EM_SLIPPERY_WALL;
-    }
-  }
-
   if (BorderElement == EL_LEERRAUM)
   {
     SBX_Left = 0;
@@ -4167,6 +4216,7 @@ void MauerAbleger(int ax, int ay)
        DrawGraphic(SCREENX(ax-1), SCREENY(ay), GFX_MAUER_LEFT);
       new_wall = TRUE;
     }
+
     if (rechts_frei)
     {
       Feld[ax+1][ay] = EL_MAUERND;
@@ -4746,14 +4796,18 @@ void GameActions()
     else if (element == EL_SHIELD_PASSIVE)
     {
       DrawGraphicAnimation(x, y, GFX_SHIELD_PASSIVE, 6, 4, ANIM_NORMAL);
+#if 0
       if (!(FrameCounter % 4))
        PlaySoundLevel(x, y, SND_SHIELD_PASSIVE_ACTIVATED);
+#endif
     }
     else if (element == EL_SHIELD_ACTIVE)
     {
       DrawGraphicAnimation(x, y, GFX_SHIELD_ACTIVE, 6, 4, ANIM_NORMAL);
+#if 0
       if (!(FrameCounter % 4))
        PlaySoundLevel(x, y, SND_SHIELD_ACTIVE_ACTIVATED);
+#endif
     }
 
     if (game.magic_wall_active)
@@ -4917,6 +4971,19 @@ void GameActions()
       CloseAllOpenTimegates();
   }
 
+  for (i=0; i<MAX_PLAYERS; i++)
+  {
+    struct PlayerInfo *player = &stored_player[i];
+
+    if (SHIELD_ON(player))
+    {
+      if (player->shield_active_time_left)
+       PlaySoundLevel(player->jx, player->jy, SND_SHIELD_ACTIVE_ACTIVATED);
+      else if (player->shield_passive_time_left)
+       PlaySoundLevel(player->jx, player->jy, SND_SHIELD_PASSIVE_ACTIVATED);
+    }
+  }
+
   if (TimeFrames >= (1000 / GameFrameDelay))
   {
     TimeFrames = 0;
@@ -4924,12 +4991,14 @@ void GameActions()
 
     for (i=0; i<MAX_PLAYERS; i++)
     {
-      if (SHIELD_ON(&stored_player[i]))
+      struct PlayerInfo *player = &stored_player[i];
+
+      if (SHIELD_ON(player))
       {
-       stored_player[i].shield_passive_time_left--;
+       player->shield_passive_time_left--;
 
-       if (stored_player[i].shield_active_time_left > 0)
-         stored_player[i].shield_active_time_left--;
+       if (player->shield_active_time_left > 0)
+         player->shield_active_time_left--;
       }
     }
 
@@ -5150,7 +5219,7 @@ boolean MoveFigure(struct PlayerInfo *player, int dx, int dy)
     return FALSE;
 #else
   if (!FrameReached(&player->move_delay, player->move_delay_value) &&
-      !(tape.playing && tape.game_version < GAME_VERSION_2_0))
+      !(tape.playing && tape.file_version < FILE_VERSION_2_0))
     return FALSE;
 #endif
 
@@ -6014,7 +6083,7 @@ int DigField(struct PlayerInfo *player,
        return MF_NO_ACTION;
 #else
       if (!FrameReached(&player->push_delay, player->push_delay_value) &&
-         !(tape.playing && tape.game_version < GAME_VERSION_2_0) &&
+         !(tape.playing && tape.file_version < FILE_VERSION_2_0) &&
          element != EL_SPRING)
        return MF_NO_ACTION;
 #endif
@@ -6256,7 +6325,7 @@ int DigField(struct PlayerInfo *player,
        return MF_NO_ACTION;
 #else
       if (!FrameReached(&player->push_delay, player->push_delay_value) &&
-         !(tape.playing && tape.game_version < GAME_VERSION_2_0) &&
+         !(tape.playing && tape.file_version < FILE_VERSION_2_0) &&
          element != EL_BALLOON)
        return MF_NO_ACTION;
 #endif