rnd-20020527-1-src
[rocksndiamonds.git] / src / game.c
index e76ca5a9e5853e481aecc9c540b353720f87990a..aa2d2464e3cd92a48f7c08c1d98907940098a525 100644 (file)
@@ -100,43 +100,53 @@ static void CloseAllOpenTimegates(void);
 static void CheckGravityMovement(struct PlayerInfo *);
 static void KillHeroUnlessProtected(int, int);
 
+void PlaySoundLevel(int, int, int);
+void PlaySoundLevelAction(int, int, int);
+
 static void MapGameButtons();
 static void HandleGameButtons(struct GadgetInfo *);
 
 static struct GadgetInfo *game_gadget[NUM_GAME_BUTTONS];
 
-static boolean is_loop_sound[NUM_SOUND_EFFECTS];
-static boolean is_loop_sound_initialized = FALSE;
-static int loop_sounds[] =
+#define SND_ACTION_UNKNOWN             0
+#define SND_ACTION_WAITING             1
+#define SND_ACTION_MOVING              2
+#define SND_ACTION_COLLECTING          3
+#define SND_ACTION_IMPACT              4
+#define SND_ACTION_PUSHING             5
+#define SND_ACTION_ACTIVATING          6
+
+#define NUM_SND_ACTIONS                        7
+
+static struct
 {
-  SND_BD_MAGIC_WALL_RUNNING,
-  SND_BD_BUTTERFLY_MOVING,
-  SND_BD_FIREFLY_MOVING,
-  SND_SP_SNIKSNAK_MOVING,
-  SND_SP_ELECTRON_MOVING,
-  SND_DYNAMITE_BURNING,
-  SND_BUG_MOVING,
-  SND_SPACESHIP_MOVING,
-  SND_YAMYAM_MOVING,
-  SND_YAMYAM_WAITING,
-  SND_ROBOT_WHEEL_RUNNING,
-  SND_MAGIC_WALL_RUNNING,
-  SND_BALLOON_MOVING,
-  SND_MOLE_MOVING,
-  SND_TIMEGATE_WHEEL_RUNNING,
-  SND_CONVEYOR_BELT_RUNNING,
-  SND_DYNABOMB_BURNING,
-  SND_PACMAN_MOVING,
-  SND_PENGUIN_MOVING,
-  SND_PIG_MOVING,
-  SND_DRAGON_MOVING,
-  SND_DRAGON_BREATHING_FIRE
+  char *text;
+  int value;
+  boolean is_loop;
+} sound_action_properties[] =
+{
+  /* insert _all_ loop sound actions here */
+  { ".waiting",                SND_ACTION_WAITING,     TRUE },
+  { ".moving",         SND_ACTION_MOVING,      TRUE }, /* continuos moving */
+  { ".running",                SND_ACTION_UNKNOWN,     TRUE },
+  { ".burning",                SND_ACTION_UNKNOWN,     TRUE },
+  { ".growing",                SND_ACTION_UNKNOWN,     TRUE },
+  { ".attacking",      SND_ACTION_UNKNOWN,     TRUE },
+
+  /* other (non-loop) sound actions are optional */
+  { ".stepping",       SND_ACTION_MOVING,      FALSE }, /* discrete moving */
+  { ".collecting",     SND_ACTION_COLLECTING,  FALSE },
+  { ".impact",         SND_ACTION_IMPACT,      FALSE },
+  { ".pushing",                SND_ACTION_PUSHING,     FALSE },
+  { ".activating",     SND_ACTION_ACTIVATING,  FALSE },
+  { NULL,              0,                      0 },
 };
+static int element_action_sound[NUM_LEVEL_ELEMENTS][NUM_SND_ACTIONS];
+static boolean is_loop_sound[NUM_SOUND_EFFECTS];
 
 #define IS_LOOP_SOUND(x)       (is_loop_sound[x])
 
 
-
 #ifdef DEBUG
 #if 0
 static unsigned int getStateCheckSum(int counter)
@@ -475,6 +485,89 @@ void DrawGameDoorValues()
           int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW);
 }
 
+void InitGameEngine()
+{
+  static int sound_effect_properties[NUM_SOUND_EFFECTS];
+  int i, j;
+
+#if 0
+  debug_print_timestamp(0, NULL);
+#endif
+
+  for (i=0; i<NUM_SND_ACTIONS; i++)
+    for (j=0; j<NUM_LEVEL_ELEMENTS; j++)
+      element_action_sound[j][i] = -1;
+
+  for (i=0; i<NUM_SOUND_EFFECTS; i++)
+  {
+    int len_effect_text = strlen(sound_effects[i].text);
+
+    sound_effect_properties[i] = SND_ACTION_UNKNOWN;
+    is_loop_sound[i] = FALSE;
+
+    /* determine all loop sounds and identify certain sound classes */
+
+    j = 0;
+    while (sound_action_properties[j].text)
+    {
+      int len_action_text = strlen(sound_action_properties[j].text);
+
+      if (len_action_text < len_effect_text &&
+         strcmp(&sound_effects[i].text[len_effect_text - len_action_text],
+                sound_action_properties[j].text) == 0)
+      {
+       sound_effect_properties[i] = sound_action_properties[j].value;
+
+       if (sound_action_properties[j].is_loop)
+         is_loop_sound[i] = TRUE;
+      }
+
+      j++;
+    }
+
+    /* associate elements and some selected sound actions */
+
+    for (j=0; j<NUM_LEVEL_ELEMENTS; j++)
+    {
+      if (element_info[j].sound_class_name)
+      {
+       int len_class_text = strlen(element_info[j].sound_class_name);
+
+       if (len_class_text < len_effect_text &&
+           strncmp(sound_effects[i].text,
+                   element_info[j].sound_class_name, len_class_text) == 0)
+       {
+         int sound_action_value = sound_effect_properties[i];
+
+         element_action_sound[j][sound_action_value] = i;
+       }
+      }
+    }
+  }
+
+#if 0
+  debug_print_timestamp(0, "InitGameEngine");
+#endif
+
+#if 0
+  /* TEST ONLY */
+  {
+    int element = EL_ROBOT;
+    int sound_action = SND_ACTION_COLLECTING;
+    int j = 0;
+
+    while (sound_action_properties[j].text)
+    {
+      if (sound_action_properties[j].value == sound_action)
+       printf("element %d, sound action '%s'  == %d\n",
+              element, sound_action_properties[j].text,
+              element_action_sound[element][sound_action]);
+      j++;
+    }
+  }
+#endif
+}
+
 void InitGame()
 {
   int i, j, x, y;
@@ -728,20 +821,6 @@ void InitGame()
     }
   }
 
-  /* initialize sound effect properties */
-  if (!is_loop_sound_initialized)
-  {
-    int i;
-
-    for (i=0; i<NUM_SOUND_EFFECTS; i++)
-      is_loop_sound[i] = FALSE;
-
-    for (i=0; i<SIZEOF_ARRAY_INT(loop_sounds); i++)
-      is_loop_sound[loop_sounds[i]] = TRUE;
-
-    is_loop_sound_initialized = TRUE;
-  }
-
   game.version = (tape.playing ? tape.game_version : level.game_version);
   game.emulation = (emulate_bd ? EMU_BOULDERDASH :
                    emulate_sb ? EMU_SOKOBAN :
@@ -2137,8 +2216,12 @@ void Impact(int x, int y)
         break;
     }
 
+#if 1
+    PlaySoundLevelAction(x, y, SND_ACTION_IMPACT);
+#else
     if (sound >= 0)
       PlaySoundLevel(x, y, sound);
+#endif
   }
 }
 
@@ -2777,6 +2860,7 @@ void StartMoving(int x, int y)
       if (element!=EL_MAMPFER && element!=EL_MAMPFER2 && element!=EL_PACMAN)
       {
        TurnRound(x, y);
+
        if (MovDelay[x][y] && (element == EL_KAEFER ||
                               element == EL_FLIEGER ||
                               element == EL_SP_SNIKSNAK ||
@@ -2854,43 +2938,14 @@ void StartMoving(int x, int y)
        }
       }
 
-      if (MovDelay[x][y])
+      if (MovDelay[x][y])      /* element still has to wait some time */
+      {
+       PlaySoundLevelAction(x, y, SND_ACTION_WAITING);
+
        return;
+      }
     }
 
-    if (element == EL_KAEFER)
-      PlaySoundLevel(x, y, SND_BUG_MOVING);
-    else if (element == EL_FLIEGER)
-      PlaySoundLevel(x, y, SND_SPACESHIP_MOVING);
-    else if (element == EL_BUTTERFLY)
-      PlaySoundLevel(x, y, SND_BD_BUTTERFLY_MOVING);
-    else if (element == EL_FIREFLY)
-      PlaySoundLevel(x, y, SND_BD_FIREFLY_MOVING);
-    else if (element == EL_SP_SNIKSNAK)
-      PlaySoundLevel(x, y, SND_SP_SNIKSNAK_MOVING);
-    else if (element == EL_SP_ELECTRON)
-      PlaySoundLevel(x, y, SND_SP_ELECTRON_MOVING);
-    else if (element == EL_MAMPFER)
-      PlaySoundLevel(x, y, SND_YAMYAM_MOVING);
-    else if (element == EL_MAMPFER2)
-      PlaySoundLevel(x, y, SND_DARK_YAMYAM_MOVING);
-    else if (element == EL_BALLOON)
-      PlaySoundLevel(x, y, SND_BALLOON_MOVING);
-    else if (element == EL_SPRING_MOVING)
-      PlaySoundLevel(x, y, SND_SPRING_MOVING);
-    else if (element == EL_MOLE)
-      PlaySoundLevel(x, y, SND_MOLE_MOVING);
-    else if (element == EL_SONDE)
-      PlaySoundLevel(x, y, SND_SATELLITE_MOVING);
-    else if (element == EL_PACMAN)
-      PlaySoundLevel(x, y, SND_PACMAN_MOVING);
-    else if (element == EL_PINGUIN)
-      PlaySoundLevel(x, y, SND_PENGUIN_MOVING);
-    else if (element == EL_SCHWEIN)
-      PlaySoundLevel(x, y, SND_PIG_MOVING);
-    else if (element == EL_DRACHE)
-      PlaySoundLevel(x, y, SND_DRAGON_MOVING);
-
     /* now make next step */
 
     Moving2Blocked(x, y, &newx, &newy);        /* get next screen position */
@@ -3005,7 +3060,7 @@ void StartMoving(int x, int y)
          else
            DrawLevelField(x, y);
 
-         PlaySoundLevel(x, y, SND_DRAGON_BREATHING_FIRE);
+         PlaySoundLevel(x, y, SND_DRAGON_ATTACKING);
 
          MovDelay[x][y] = 50;
          Feld[newx][newy] = EL_BURNING;
@@ -3102,13 +3157,14 @@ void StartMoving(int x, int y)
       if (DONT_TOUCH(element))
        TestIfBadThingTouchesHero(x, y);
 
+      PlaySoundLevelAction(x, y, SND_ACTION_WAITING);
+
       return;
     }
 
-    if (element == EL_ROBOT && IN_SCR_FIELD(x, y))
-      PlaySoundLevel(x, y, SND_ROBOT_MOVING);
-
     InitMovingField(x, y, MovDir[x][y]);
+
+    PlaySoundLevelAction(x, y, SND_ACTION_MOVING);
   }
 
   if (MovDir[x][y])
@@ -5996,6 +6052,7 @@ int DigField(struct PlayerInfo *player,
                            element == EL_BALLOON_SEND_UP    ? MV_UP :
                            element == EL_BALLOON_SEND_DOWN  ? MV_DOWN :
                            MV_NO_MOVING);
+      PlaySoundLevel(x, y, SND_BALLOON_SWITCH_ACTIVATING);
 
       return MF_ACTION;
       break;
@@ -6235,6 +6292,8 @@ 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);
       }
       break;
 
@@ -6514,6 +6573,90 @@ void PlaySoundLevel(int x, int y, int nr)
   PlaySoundExt(nr, volume, stereo_position, type);
 }
 
+void PlaySoundLevelAction(int x, int y, int sound_action)
+{
+  int element = Feld[x][y];
+  int sound_effect = element_action_sound[element][sound_action];
+
+#if 1
+  if (sound_effect != -1)
+    PlaySoundLevel(x, y, sound_effect);
+#else
+  if (sound_action == SND_ACTION_MOVING)
+  {
+    if (element == EL_KAEFER)
+      PlaySoundLevel(x, y, SND_BUG_MOVING);
+    else if (element == EL_FLIEGER)
+      PlaySoundLevel(x, y, SND_SPACESHIP_MOVING);
+    else if (element == EL_BUTTERFLY)
+      PlaySoundLevel(x, y, SND_BD_BUTTERFLY_MOVING);
+    else if (element == EL_FIREFLY)
+      PlaySoundLevel(x, y, SND_BD_FIREFLY_MOVING);
+    else if (element == EL_SP_SNIKSNAK)
+      PlaySoundLevel(x, y, SND_SP_SNIKSNAK_MOVING);
+    else if (element == EL_SP_ELECTRON)
+      PlaySoundLevel(x, y, SND_SP_ELECTRON_MOVING);
+    else if (element == EL_MAMPFER)
+      PlaySoundLevel(x, y, SND_YAMYAM_MOVING);
+    else if (element == EL_MAMPFER2)
+      PlaySoundLevel(x, y, SND_DARK_YAMYAM_MOVING);
+    else if (element == EL_BALLOON)
+      PlaySoundLevel(x, y, SND_BALLOON_MOVING);
+    else if (element == EL_SPRING_MOVING)
+      PlaySoundLevel(x, y, SND_SPRING_MOVING);
+    else if (element == EL_MOLE)
+      PlaySoundLevel(x, y, SND_MOLE_MOVING);
+    else if (element == EL_SONDE)
+      PlaySoundLevel(x, y, SND_SATELLITE_MOVING);
+    else if (element == EL_PACMAN)
+      PlaySoundLevel(x, y, SND_PACMAN_MOVING);
+    else if (element == EL_PINGUIN)
+      PlaySoundLevel(x, y, SND_PENGUIN_MOVING);
+    else if (element == EL_SCHWEIN)
+      PlaySoundLevel(x, y, SND_PIG_MOVING);
+    else if (element == EL_DRACHE)
+      PlaySoundLevel(x, y, SND_DRAGON_MOVING);
+    else if (element == EL_ROBOT)
+      PlaySoundLevel(x, y, SND_ROBOT_STEPPING);
+  }
+  else if (sound_action == SND_ACTION_WAITING)
+  {
+    if (element == EL_KAEFER)
+      PlaySoundLevel(x, y, SND_BUG_WAITING);
+    else if (element == EL_FLIEGER)
+      PlaySoundLevel(x, y, SND_SPACESHIP_WAITING);
+    else if (element == EL_BUTTERFLY)
+      PlaySoundLevel(x, y, SND_BD_BUTTERFLY_WAITING);
+    else if (element == EL_FIREFLY)
+      PlaySoundLevel(x, y, SND_BD_FIREFLY_WAITING);
+    else if (element == EL_SP_SNIKSNAK)
+      PlaySoundLevel(x, y, SND_SP_SNIKSNAK_WAITING);
+    else if (element == EL_SP_ELECTRON)
+      PlaySoundLevel(x, y, SND_SP_ELECTRON_WAITING);
+    else if (element == EL_MAMPFER)
+      PlaySoundLevel(x, y, SND_YAMYAM_WAITING);
+    else if (element == EL_MAMPFER2)
+      PlaySoundLevel(x, y, SND_DARK_YAMYAM_WAITING);
+    else if (element == EL_BALLOON)
+      PlaySoundLevel(x, y, SND_BALLOON_WAITING);
+    else if (element == EL_MOLE)
+      PlaySoundLevel(x, y, SND_MOLE_WAITING);
+    else if (element == EL_SONDE)
+      PlaySoundLevel(x, y, SND_SATELLITE_WAITING);
+    else if (element == EL_PACMAN)
+      PlaySoundLevel(x, y, SND_PACMAN_WAITING);
+    else if (element == EL_PINGUIN)
+      PlaySoundLevel(x, y, SND_PENGUIN_WAITING);
+    else if (element == EL_SCHWEIN)
+      PlaySoundLevel(x, y, SND_PIG_WAITING);
+    else if (element == EL_DRACHE)
+      PlaySoundLevel(x, y, SND_DRAGON_WAITING);
+    else if (element == EL_ROBOT)
+      PlaySoundLevel(x, y, SND_ROBOT_WAITING);
+  }
+#endif
+}
+
 void RaiseScore(int value)
 {
   local_player->score += value;