rnd-20031008-1-src
[rocksndiamonds.git] / src / game.c
index 2062caa865f2ea33868c83e0ee0534bb35d60bc8..a67f9def973370667b5e45266cbfd76c70ecb4fd 100644 (file)
@@ -251,6 +251,22 @@ static struct ChangingElementInfo change_delay_list[] =
     NULL,
     NULL
   },
+  {
+    EL_SP_EXIT_OPENING,
+    EL_SP_EXIT_OPEN,
+    29,
+    NULL,
+    NULL,
+    NULL
+  },
+  {
+    EL_SP_EXIT_CLOSING,
+    EL_SP_EXIT_CLOSED,
+    29,
+    NULL,
+    NULL,
+    NULL
+  },
   {
     EL_SWITCHGATE_OPENING,
     EL_SWITCHGATE_OPEN,
@@ -1016,6 +1032,9 @@ void InitGame()
     player->Frame = 0;
     player->StepFrame = 0;
 
+    player->switch_x = -1;
+    player->switch_y = -1;
+
     player->use_murphy_graphic = FALSE;
     player->use_disk_red_graphic = FALSE;
 
@@ -1083,6 +1102,7 @@ void InitGame()
   game.timegate_time_left = 0;
   game.switchgate_pos = 0;
   game.balloon_dir = MV_NO_MOVING;
+  game.gravity = level.initial_gravity;
   game.explosions_delayed = TRUE;
 
   game.envelope_active = FALSE;
@@ -1668,11 +1688,15 @@ void GameWon()
   }
 
   /* close exit door after last player */
-  if (Feld[ExitX][ExitY] == EL_EXIT_OPEN && AllPlayersGone)
+  if ((Feld[ExitX][ExitY] == EL_EXIT_OPEN ||
+       Feld[ExitX][ExitY] == EL_SP_EXIT_OPEN) && AllPlayersGone)
   {
-    Feld[ExitX][ExitY] = EL_EXIT_CLOSING;
+    int element = Feld[ExitX][ExitY];
+
+    Feld[ExitX][ExitY] = (element == EL_EXIT_OPEN ? EL_EXIT_CLOSING :
+                         EL_SP_EXIT_CLOSING);
 
-    PlaySoundLevelElementAction(ExitX, ExitY, EL_EXIT_OPEN, ACTION_CLOSING);
+    PlaySoundLevelElementAction(ExitX, ExitY, element, ACTION_CLOSING);
   }
 
   /* Hero disappears */
@@ -3095,6 +3119,11 @@ void Impact(int x, int y)
        else
        {
          CheckElementChange(x, y + 1, smashed, CE_SMASHED);
+
+         CheckTriggeredElementSideChange(x, y + 1, smashed, CH_SIDE_TOP,
+                                         CE_OTHER_IS_SWITCHING);
+         CheckElementSideChange(x, y + 1, smashed, CH_SIDE_TOP,
+                                CE_SWITCHED, -1);
        }
       }
       else
@@ -4228,6 +4257,11 @@ void StartMoving(int x, int y)
            element1 != EL_DRAGON && element2 != EL_DRAGON &&
            element1 != EL_FLAMES && element2 != EL_FLAMES)
        {
+#if 1
+         ResetGfxAnimation(x, y);
+         GfxAction[x][y] = ACTION_ATTACKING;
+#endif
+
          if (IS_PLAYER(x, y))
            DrawPlayerField(x, y);
          else
@@ -4241,6 +4275,7 @@ void StartMoving(int x, int y)
            Feld[newx1][newy1] = EL_FLAMES;
          if (IN_LEV_FIELD(newx2, newy2) && Feld[newx2][newy2] == EL_EMPTY)
            Feld[newx2][newy2] = EL_FLAMES;
+
          return;
        }
       }
@@ -5086,7 +5121,10 @@ void CheckExitSP(int x, int y)
     return;
   }
 
-  Feld[x][y] = EL_SP_EXIT_OPEN;
+  if (AllPlayersGone)  /* do not re-open exit door closed after last player */
+    return;
+
+  Feld[x][y] = EL_SP_EXIT_OPENING;
 
   PlaySoundLevelNearest(x, y, SND_CLASS_SP_EXIT_OPENING);
 }
@@ -6250,7 +6288,7 @@ void GameActions()
     }
   }
 
-  if (TimeFrames >= (1000 / GameFrameDelay))
+  if (TimeFrames >= FRAMES_PER_SECOND)
   {
     TimeFrames = 0;
     TimePlayed++;
@@ -6417,7 +6455,7 @@ void ScrollLevel(int dx, int dy)
 
 static void CheckGravityMovement(struct PlayerInfo *player)
 {
-  if (level.gravity && !player->programmed_action)
+  if (game.gravity && !player->programmed_action)
   {
     int move_dir_vertical = player->action & (MV_UP | MV_DOWN);
     int move_dir_horizontal = player->action & (MV_LEFT | MV_RIGHT);
@@ -6786,13 +6824,14 @@ void ScrollFigure(struct PlayerInfo *player, int mode)
     player->last_jy = jy;
 
     if (Feld[jx][jy] == EL_EXIT_OPEN ||
-       Feld[jx][jy] == EL_SP_EXIT_OPEN)
+       Feld[jx][jy] == EL_SP_EXIT_OPEN ||
+       Feld[jx][jy] == EL_SP_EXIT_OPENING)     /* <-- special case */
     {
       DrawPlayer(player);      /* needed here only to cleanup last field */
       RemoveHero(player);
 
       if (local_player->friends_still_needed == 0 ||
-         Feld[jx][jy] == EL_SP_EXIT_OPEN)
+         IS_SP_ELEMENT(Feld[jx][jy]))
        player->LevelSolved = player->GameOver = TRUE;
     }
 
@@ -7415,6 +7454,7 @@ int DigField(struct PlayerInfo *player,
 
   switch (element)
   {
+#if 0
     case EL_ROBOT_WHEEL:
       Feld[x][y] = EL_ROBOT_WHEEL_ACTIVE;
       ZX = x;
@@ -7423,7 +7463,9 @@ int DigField(struct PlayerInfo *player,
       PlaySoundLevel(x, y, SND_ROBOT_WHEEL_ACTIVATING);
       return MF_ACTION;
       break;
+#endif
 
+#if 0
     case EL_SP_TERMINAL:
       {
        int xx, yy;
@@ -7444,7 +7486,9 @@ int DigField(struct PlayerInfo *player,
        return MF_ACTION;
       }
       break;
+#endif
 
+#if 0
     case EL_CONVEYOR_BELT_1_SWITCH_LEFT:
     case EL_CONVEYOR_BELT_1_SWITCH_MIDDLE:
     case EL_CONVEYOR_BELT_1_SWITCH_RIGHT:
@@ -7457,31 +7501,56 @@ int DigField(struct PlayerInfo *player,
     case EL_CONVEYOR_BELT_4_SWITCH_LEFT:
     case EL_CONVEYOR_BELT_4_SWITCH_MIDDLE:
     case EL_CONVEYOR_BELT_4_SWITCH_RIGHT:
+#if 1
+      if (!PLAYER_SWITCHING(player, x, y))
+#else
       if (!player->Switching)
+#endif
       {
        player->Switching = TRUE;
+       player->switch_x = x;
+       player->switch_y = y;
+
        ToggleBeltSwitch(x, y);
        PlaySoundLevel(x, y, SND_CLASS_CONVEYOR_BELT_SWITCH_ACTIVATING);
       }
       return MF_ACTION;
       break;
+#endif
 
+#if 0
     case EL_SWITCHGATE_SWITCH_UP:
     case EL_SWITCHGATE_SWITCH_DOWN:
+#if 1
+      if (!PLAYER_SWITCHING(player, x, y))
+#else
       if (!player->Switching)
+#endif
       {
        player->Switching = TRUE;
+       player->switch_x = x;
+       player->switch_y = y;
+
        ToggleSwitchgateSwitch(x, y);
        PlaySoundLevel(x, y, SND_CLASS_SWITCHGATE_SWITCH_ACTIVATING);
       }
       return MF_ACTION;
       break;
+#endif
 
+#if 0
     case EL_LIGHT_SWITCH:
     case EL_LIGHT_SWITCH_ACTIVE:
+#if 1
+      if (!PLAYER_SWITCHING(player, x, y))
+#else
       if (!player->Switching)
+#endif
       {
        player->Switching = TRUE;
+       player->switch_x = x;
+       player->switch_y = y;
+
        ToggleLightSwitch(x, y);
        PlaySoundLevel(x, y, element == EL_LIGHT_SWITCH ?
                       SND_LIGHT_SWITCH_ACTIVATING :
@@ -7489,14 +7558,18 @@ int DigField(struct PlayerInfo *player,
       }
       return MF_ACTION;
       break;
+#endif
 
+#if 0
     case EL_TIMEGATE_SWITCH:
       ActivateTimegateSwitch(x, y);
       PlaySoundLevel(x, y, SND_TIMEGATE_SWITCH_ACTIVATING);
 
       return MF_ACTION;
       break;
+#endif
 
+#if 0
     case EL_BALLOON_SWITCH_LEFT:
     case EL_BALLOON_SWITCH_RIGHT:
     case EL_BALLOON_SWITCH_UP:
@@ -7514,6 +7587,7 @@ int DigField(struct PlayerInfo *player,
 
       return MF_ACTION;
       break;
+#endif
 
     case EL_SP_PORT_LEFT:
     case EL_SP_PORT_RIGHT:
@@ -7554,7 +7628,7 @@ int DigField(struct PlayerInfo *player,
          element == EL_SP_GRAVITY_PORT_RIGHT ||
          element == EL_SP_GRAVITY_PORT_UP ||
          element == EL_SP_GRAVITY_PORT_DOWN)
-       level.gravity = !level.gravity;
+       game.gravity = !game.gravity;
 
       /* automatically move to the next field with double speed */
       player->programmed_action = move_direction;
@@ -7606,6 +7680,7 @@ int DigField(struct PlayerInfo *player,
       }
       break;
 
+#if 0
     case EL_LAMP:
       Feld[x][y] = EL_LAMP_ACTIVE;
       local_player->lights_still_needed--;
@@ -7613,7 +7688,9 @@ int DigField(struct PlayerInfo *player,
       PlaySoundLevel(x, y, SND_LAMP_ACTIVATING);
       return MF_ACTION;
       break;
+#endif
 
+#if 0
     case EL_TIME_ORB_FULL:
       Feld[x][y] = EL_TIME_ORB_EMPTY;
       TimeLeft += 10;
@@ -7622,6 +7699,7 @@ int DigField(struct PlayerInfo *player,
       PlaySoundStereo(SND_TIME_ORB_FULL_COLLECTING, SOUND_MIDDLE);
       return MF_ACTION;
       break;
+#endif
 
     default:
 
@@ -7639,7 +7717,9 @@ int DigField(struct PlayerInfo *player,
          if (!player->key[element - EL_GATE_1_GRAY])
            return MF_NO_ACTION;
        }
-       else if (element == EL_EXIT_OPEN || element == EL_SP_EXIT_OPEN)
+       else if (element == EL_EXIT_OPEN ||
+                element == EL_SP_EXIT_OPEN ||
+                element == EL_SP_EXIT_OPENING)
        {
          sound_action = ACTION_PASSING;        /* player is passing exit */
        }
@@ -7910,29 +7990,175 @@ int DigField(struct PlayerInfo *player,
 
        break;
       }
-      else
+      else if (IS_SWITCHABLE(element))
       {
+       if (PLAYER_SWITCHING(player, x, y))
+         return MF_ACTION;
+
 #if 1
+       PlaySoundLevelElementAction(x, y, element, ACTION_ACTIVATING);
+#endif
+
+       if (element == EL_ROBOT_WHEEL)
+       {
+         Feld[x][y] = EL_ROBOT_WHEEL_ACTIVE;
+         ZX = x;
+         ZY = y;
+
+         DrawLevelField(x, y);
+
+#if 0
+         PlaySoundLevel(x, y, SND_ROBOT_WHEEL_ACTIVATING);
+#endif
+       }
+       else if (element == EL_SP_TERMINAL)
+       {
+         int xx, yy;
+
+#if 0
+         PlaySoundLevel(x, y, SND_SP_TERMINAL_ACTIVATING);
+#endif
+
+         for (yy=0; yy<lev_fieldy; yy++)
+         {
+           for (xx=0; xx<lev_fieldx; xx++)
+           {
+             if (Feld[xx][yy] == EL_SP_DISK_YELLOW)
+               Bang(xx, yy);
+             else if (Feld[xx][yy] == EL_SP_TERMINAL)
+               Feld[xx][yy] = EL_SP_TERMINAL_ACTIVE;
+           }
+         }
+       }
+       else if (IS_BELT_SWITCH(element))
+       {
+#if 0
+         if (!PLAYER_SWITCHING(player, x, y))
+#endif
+         {
+           player->Switching = TRUE;
+           player->switch_x = x;
+           player->switch_y = y;
+
+           ToggleBeltSwitch(x, y);
+
+#if 0
+           PlaySoundLevel(x, y, SND_CLASS_CONVEYOR_BELT_SWITCH_ACTIVATING);
+#endif
+         }
+       }
+       else if (element == EL_SWITCHGATE_SWITCH_UP ||
+                element == EL_SWITCHGATE_SWITCH_DOWN)
+       {
+#if 0
+         if (!PLAYER_SWITCHING(player, x, y))
+#endif
+         {
+           player->Switching = TRUE;
+           player->switch_x = x;
+           player->switch_y = y;
+
+           ToggleSwitchgateSwitch(x, y);
+
+#if 0
+           PlaySoundLevel(x, y, SND_CLASS_SWITCHGATE_SWITCH_ACTIVATING);
+#endif
+         }
+       }
+       else if (element == EL_LIGHT_SWITCH ||
+                element == EL_LIGHT_SWITCH_ACTIVE)
+       {
+#if 0
+         if (!PLAYER_SWITCHING(player, x, y))
+#endif
+         {
+           player->Switching = TRUE;
+           player->switch_x = x;
+           player->switch_y = y;
+
+           ToggleLightSwitch(x, y);
+
+#if 0
+           PlaySoundLevel(x, y, element == EL_LIGHT_SWITCH ?
+                          SND_LIGHT_SWITCH_ACTIVATING :
+                          SND_LIGHT_SWITCH_DEACTIVATING);
+#endif
+         }
+       }
+       else if (element == EL_TIMEGATE_SWITCH)
+       {
+         ActivateTimegateSwitch(x, y);
+
+#if 0
+         PlaySoundLevel(x, y, SND_TIMEGATE_SWITCH_ACTIVATING);
+#endif
+       }
+       else if (element == EL_BALLOON_SWITCH_LEFT ||
+                element == EL_BALLOON_SWITCH_RIGHT ||
+                element == EL_BALLOON_SWITCH_UP ||
+                element == EL_BALLOON_SWITCH_DOWN ||
+                element == EL_BALLOON_SWITCH_ANY)
+       {
+         if (element == EL_BALLOON_SWITCH_ANY)
+           game.balloon_dir = move_direction;
+         else
+           game.balloon_dir = (element == EL_BALLOON_SWITCH_LEFT  ? MV_LEFT :
+                               element == EL_BALLOON_SWITCH_RIGHT ? MV_RIGHT :
+                               element == EL_BALLOON_SWITCH_UP    ? MV_UP :
+                               element == EL_BALLOON_SWITCH_DOWN  ? MV_DOWN :
+                               MV_NO_MOVING);
+
+#if 0
+         PlaySoundLevel(x, y, SND_CLASS_BALLOON_SWITCH_ACTIVATING);
+#endif
+       }
+       else if (element == EL_LAMP)
+       {
+         Feld[x][y] = EL_LAMP_ACTIVE;
+         local_player->lights_still_needed--;
+
+         DrawLevelField(x, y);
 
+#if 0
+         PlaySoundLevel(x, y, SND_LAMP_ACTIVATING);
+#endif
+       }
+       else if (element == EL_TIME_ORB_FULL)
+       {
+         Feld[x][y] = EL_TIME_ORB_EMPTY;
+         TimeLeft += 10;
+         DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_TEXT_2);
+
+         DrawLevelField(x, y);
+
+#if 0
+         PlaySoundStereo(SND_TIME_ORB_FULL_COLLECTING, SOUND_MIDDLE);
+#endif
+       }
+
+       return MF_ACTION;
+      }
+      else
+      {
 #if 1
+       if (!PLAYER_SWITCHING(player, x, y))
+#else
        if (!player->Switching)
+#endif
        {
          player->Switching = TRUE;
+         player->switch_x = x;
+         player->switch_y = y;
+
          CheckTriggeredElementSideChange(x, y, element, dig_side,
-                                         CE_OTHER_GETS_SWITCHED);
-         CheckElementSideChange(x, y, element, dig_side,
-                                CE_SWITCHED_BY_PLAYER, -1);
+                                         CE_OTHER_IS_SWITCHING);
+         CheckElementSideChange(x, y, element, dig_side, CE_SWITCHED, -1);
        }
-#endif
 
        CheckTriggeredElementSideChange(x, y, element, dig_side,
                                        CE_OTHER_GETS_PRESSED);
        CheckElementSideChange(x, y, element, dig_side,
                               CE_PRESSED_BY_PLAYER, -1);
-#else
-       CheckTriggeredElementChange(x, y, element, CE_OTHER_GETS_PRESSED);
-       CheckElementChange(x, y, element, CE_PRESSED_BY_PLAYER);
-#endif
       }
 
       return MF_NO_ACTION;