rnd-20000718-1-src
[rocksndiamonds.git] / src / game.c
index b732e32c47c16cda02c32f1d03a3043d530d224f..14e6445da7ccb717999e5b7574d8d85b443f1418 100644 (file)
@@ -229,8 +229,17 @@ static void InitField(int x, int y, boolean init_game)
 {
   switch (Feld[x][y])
   {
-    case EL_SPIELFIGUR:
     case EL_SP_MURPHY:
+      if (init_game)
+      {
+       if (stored_player[0].present)
+       {
+         Feld[x][y] = EL_SP_MURPHY_CLONE;
+         break;
+       }
+      }
+      /* no break! */
+    case EL_SPIELFIGUR:
       if (init_game)
        Feld[x][y] = EL_SPIELER1;
       /* no break! */
@@ -1160,8 +1169,8 @@ void RemoveMovingField(int x, int y)
 
   if (Feld[x][y] == EL_BLOCKED &&
       (Store[oldx][oldy] == EL_MORAST_LEER ||
-       Store[oldx][oldy] == EL_SIEB_LEER ||
-       Store[oldx][oldy] == EL_SIEB2_LEER ||
+       Store[oldx][oldy] == EL_MAGIC_WALL_EMPTY ||
+       Store[oldx][oldy] == EL_MAGIC_WALL_BD_EMPTY ||
        Store[oldx][oldy] == EL_AMOEBE_NASS))
   {
     Feld[oldx][oldy] = Store[oldx][oldy];
@@ -1772,7 +1781,9 @@ void Impact(int x, int y)
     return;
   }
 
-  if ((element == EL_BOMBE || element == EL_SP_DISK_ORANGE) &&
+  if ((element == EL_BOMBE ||
+       element == EL_SP_DISK_ORANGE ||
+       element == EL_DX_SUPABOMB) &&
       (lastline || object_hit))        /* element is bomb */
   {
     Bang(x, y);
@@ -1802,11 +1813,12 @@ void Impact(int x, int y)
   if (!lastline && object_hit)         /* check which object was hit */
   {
     if (CAN_CHANGE(element) && 
-       (smashed == EL_SIEB_INAKTIV || smashed == EL_SIEB2_INAKTIV))
+       (smashed == EL_MAGIC_WALL_OFF || smashed == EL_MAGIC_WALL_BD_OFF))
     {
       int x, y;
       int activated_magic_wall =
-       (smashed == EL_SIEB_INAKTIV ? EL_SIEB_LEER : EL_SIEB2_LEER);
+       (smashed == EL_MAGIC_WALL_OFF ? EL_MAGIC_WALL_EMPTY :
+        EL_MAGIC_WALL_BD_EMPTY);
 
       /* activate magic wall / mill */
 
@@ -1837,10 +1849,13 @@ void Impact(int x, int y)
        return;
       }
     }
-    else if (element == EL_FELSBROCKEN || element == EL_SP_ZONK)
+    else if (element == EL_FELSBROCKEN ||
+            element == EL_SP_ZONK ||
+            element == EL_BD_ROCK)
     {
       if (IS_ENEMY(smashed) ||
          smashed == EL_BOMBE || smashed == EL_SP_DISK_ORANGE ||
+         smashed == EL_DX_SUPABOMB ||
          smashed == EL_SONDE || smashed == EL_SCHWEIN ||
          smashed == EL_DRACHE || smashed == EL_MOLE)
       {
@@ -1893,7 +1908,8 @@ void Impact(int x, int y)
 
   /* play sound of magic wall / mill */
   if (!lastline &&
-      (Feld[x][y+1] == EL_SIEB_LEER || Feld[x][y+1] == EL_SIEB2_LEER))
+      (Feld[x][y+1] == EL_MAGIC_WALL_EMPTY ||
+       Feld[x][y+1] == EL_MAGIC_WALL_BD_EMPTY))
   {
     PlaySoundLevel(x, y, SND_QUIRK);
     return;
@@ -1919,6 +1935,7 @@ void Impact(int x, int y)
        sound = SND_KLUMPF;
        break;
       case EL_FELSBROCKEN:
+      case EL_BD_ROCK:
        sound = SND_KLOPF;
        break;
       case EL_SP_ZONK:
@@ -2235,6 +2252,16 @@ void TurnRound(int x, int y)
     MovDir[x][y] = game.balloon_dir;
     MovDelay[x][y] = 0;
   }
+  else if (element == EL_SPRING_MOVING)
+  {
+    if (!IN_LEV_FIELD(move_x, move_y) || !IS_FREE(move_x, move_y) ||
+       (IN_LEV_FIELD(x, y+1) && IS_FREE(x, y+1)))
+    {
+      Feld[x][y] = EL_SPRING;
+      MovDir[x][y] = MV_NO_MOVING;
+    }
+    MovDelay[x][y] = 0;
+  }
   else if (element == EL_ROBOT || element == EL_SONDE || element == EL_PINGUIN)
   {
     int attr_x = -1, attr_y = -1;
@@ -2418,20 +2445,21 @@ void StartMoving(int x, int y)
        Feld[x][y+1] = EL_MORAST_VOLL;
       }
     }
-    else if (element == EL_FELSBROCKEN && Feld[x][y+1] == EL_MORAST_LEER)
+    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;
     }
-    else if (element == EL_SIEB_VOLL)
+    else if (element == EL_MAGIC_WALL_FULL)
     {
       if (IS_FREE(x, y+1))
       {
        InitMovingField(x, y, MV_DOWN);
        Feld[x][y] = EL_CHANGED(Store2[x][y]);
-       Store[x][y] = EL_SIEB_LEER;
+       Store[x][y] = EL_MAGIC_WALL_EMPTY;
       }
-      else if (Feld[x][y+1] == EL_SIEB_LEER)
+      else if (Feld[x][y+1] == EL_MAGIC_WALL_EMPTY)
       {
        if (!MovDelay[x][y])
          MovDelay[x][y] = TILEY/4 + 1;
@@ -2443,21 +2471,21 @@ void StartMoving(int x, int y)
            return;
        }
 
-       Feld[x][y] = EL_SIEB_LEER;
-       Feld[x][y+1] = EL_SIEB_VOLL;
+       Feld[x][y] = EL_MAGIC_WALL_EMPTY;
+       Feld[x][y+1] = EL_MAGIC_WALL_FULL;
        Store2[x][y+1] = EL_CHANGED(Store2[x][y]);
        Store2[x][y] = 0;
       }
     }
-    else if (element == EL_SIEB2_VOLL)
+    else if (element == EL_MAGIC_WALL_BD_FULL)
     {
       if (IS_FREE(x, y+1))
       {
        InitMovingField(x, y, MV_DOWN);
        Feld[x][y] = EL_CHANGED2(Store2[x][y]);
-       Store[x][y] = EL_SIEB2_LEER;
+       Store[x][y] = EL_MAGIC_WALL_BD_EMPTY;
       }
-      else if (Feld[x][y+1] == EL_SIEB2_LEER)
+      else if (Feld[x][y+1] == EL_MAGIC_WALL_BD_EMPTY)
       {
        if (!MovDelay[x][y])
          MovDelay[x][y] = TILEY/4 + 1;
@@ -2469,18 +2497,20 @@ void StartMoving(int x, int y)
            return;
        }
 
-       Feld[x][y] = EL_SIEB2_LEER;
-       Feld[x][y+1] = EL_SIEB2_VOLL;
+       Feld[x][y] = EL_MAGIC_WALL_BD_EMPTY;
+       Feld[x][y+1] = EL_MAGIC_WALL_BD_FULL;
        Store2[x][y+1] = EL_CHANGED2(Store2[x][y]);
        Store2[x][y] = 0;
       }
     }
     else if (CAN_CHANGE(element) &&
-            (Feld[x][y+1] == EL_SIEB_LEER || Feld[x][y+1] == EL_SIEB2_LEER))
+            (Feld[x][y+1] == EL_MAGIC_WALL_EMPTY ||
+             Feld[x][y+1] == EL_MAGIC_WALL_BD_EMPTY))
     {
       InitMovingField(x, y, MV_DOWN);
       Store[x][y] =
-       (Feld[x][y+1] == EL_SIEB_LEER ? EL_SIEB_VOLL : EL_SIEB2_VOLL);
+       (Feld[x][y+1] == EL_MAGIC_WALL_EMPTY ? EL_MAGIC_WALL_FULL :
+        EL_MAGIC_WALL_BD_FULL);
       Store2[x][y+1] = element;
     }
     else if (CAN_SMASH(element) && Feld[x][y+1] == EL_SALZSAEURE)
@@ -2507,7 +2537,8 @@ void StartMoving(int x, int y)
     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])
+            !IS_FALLING(x, y+1) && !JustStopped[x][y+1] &&
+            element != EL_DX_SUPABOMB)
 #endif
     {
       boolean left  = (x>0 && IS_FREE(x-1, y) &&
@@ -2517,7 +2548,9 @@ void StartMoving(int x, int y)
 
       if (left || right)
       {
-       if (left && right && game.emulation != EMU_BOULDERDASH)
+       if (left && right &&
+           (game.emulation != EMU_BOULDERDASH &&
+            element != EL_BD_ROCK && element != EL_EDELSTEIN_BD))
          left = !(right = RND(2));
 
        InitMovingField(x, y, left ? MV_LEFT : MV_RIGHT);
@@ -2539,7 +2572,8 @@ void StartMoving(int x, int y)
   {
     int newx, newy;
 
-    if ((element == EL_SONDE || element == EL_BALLOON)
+    if ((element == EL_SONDE || element == EL_BALLOON ||
+        element == EL_SPRING_MOVING)
        && JustBeingPushed(x, y))
       return;
 
@@ -2868,6 +2902,8 @@ void ContinueMoving(int x, int y)
   else if (CAN_FALL(element) && horiz_move &&
           y < lev_fieldy-1 && IS_BELT(Feld[x][y+1]))
     step /= 2;
+  else if (element == EL_SPRING_MOVING)
+    step*=2;
 
 #if OLD_GAME_BEHAVIOUR
   else if (CAN_FALL(element) && horiz_move && !IS_SP_ELEMENT(element))
@@ -2918,27 +2954,30 @@ void ContinueMoving(int x, int y)
       Store[x][y] = 0;
       Feld[x][y] = EL_MORAST_LEER;
     }
-    else if (Store[x][y] == EL_SIEB_VOLL)
+    else if (Store[x][y] == EL_MAGIC_WALL_FULL)
     {
       Store[x][y] = 0;
       element = Feld[newx][newy] =
-       (game.magic_wall_active ? EL_SIEB_VOLL : EL_SIEB_TOT);
+       (game.magic_wall_active ? EL_MAGIC_WALL_FULL : EL_MAGIC_WALL_DEAD);
     }
-    else if (Store[x][y] == EL_SIEB_LEER)
+    else if (Store[x][y] == EL_MAGIC_WALL_EMPTY)
     {
       Store[x][y] = Store2[x][y] = 0;
-      Feld[x][y] = (game.magic_wall_active ? EL_SIEB_LEER : EL_SIEB_TOT);
+      Feld[x][y] = (game.magic_wall_active ? EL_MAGIC_WALL_EMPTY :
+                   EL_MAGIC_WALL_DEAD);
     }
-    else if (Store[x][y] == EL_SIEB2_VOLL)
+    else if (Store[x][y] == EL_MAGIC_WALL_BD_FULL)
     {
       Store[x][y] = 0;
       element = Feld[newx][newy] =
-       (game.magic_wall_active ? EL_SIEB2_VOLL : EL_SIEB2_TOT);
+       (game.magic_wall_active ? EL_MAGIC_WALL_BD_FULL :
+        EL_MAGIC_WALL_BD_DEAD);
     }
-    else if (Store[x][y] == EL_SIEB2_LEER)
+    else if (Store[x][y] == EL_MAGIC_WALL_BD_EMPTY)
     {
       Store[x][y] = Store2[x][y] = 0;
-      Feld[x][y] = (game.magic_wall_active ? EL_SIEB2_LEER : EL_SIEB2_TOT);
+      Feld[x][y] = (game.magic_wall_active ? EL_MAGIC_WALL_BD_EMPTY :
+                   EL_MAGIC_WALL_BD_DEAD);
     }
     else if (Store[x][y] == EL_SALZSAEURE)
     {
@@ -3148,7 +3187,7 @@ void AmoebeUmwandelnBD(int ax, int ay, int new_element)
 
   if (done)
     PlaySoundLevel(ax, ay,
-                  (new_element == EL_FELSBROCKEN ? SND_KLOPF : SND_PLING));
+                  (new_element == EL_BD_ROCK ? SND_KLOPF : SND_PLING));
 }
 
 void AmoebeWaechst(int x, int y)
@@ -3332,7 +3371,7 @@ void AmoebeAbleger(int ax, int ay)
 
       if (element == EL_AMOEBE_BD && AmoebaCnt2[new_group_nr] >= 200)
       {
-       AmoebeUmwandelnBD(newax, neway, EL_FELSBROCKEN);
+       AmoebeUmwandelnBD(newax, neway, EL_BD_ROCK);
        return;
       }
     }
@@ -3552,7 +3591,7 @@ void BreakingPearl(int x, int y)
 
 void SiebAktivieren(int x, int y, int typ)
 {
-  int graphic = (typ == 1 ? GFX_SIEB_VOLL : GFX_SIEB2_VOLL) + 3;
+  int graphic = (typ == 1 ? GFX_MAGIC_WALL_FULL : GFX_MAGIC_WALL_BD_FULL) + 3;
 
   DrawGraphicAnimation(x, y, graphic, 4, 4, ANIM_REVERSE);
 }
@@ -4162,7 +4201,7 @@ static void PlayerActions(struct PlayerInfo *player, byte player_action)
       {
        int el = Feld[jx+dx][jy];
        int push_delay = (IS_SB_ELEMENT(el) || el == EL_SONDE ? 2 :
-                         el == EL_BALLOON ? 0 : 10);
+                         (el == EL_BALLOON || el == EL_SPRING) ? 0 : 10);
 
        if (tape.delay_played + push_delay >= tape.pos[tape.counter].delay)
        {
@@ -4399,14 +4438,15 @@ void GameActions()
       boolean sieb = FALSE;
       int jx = local_player->jx, jy = local_player->jy;
 
-      if (element == EL_SIEB_LEER || element == EL_SIEB_VOLL ||
-         Store[x][y] == EL_SIEB_LEER)
+      if (element == EL_MAGIC_WALL_EMPTY || element == EL_MAGIC_WALL_FULL ||
+         Store[x][y] == EL_MAGIC_WALL_EMPTY)
       {
        SiebAktivieren(x, y, 1);
        sieb = TRUE;
       }
-      else if (element == EL_SIEB2_LEER || element == EL_SIEB2_VOLL ||
-              Store[x][y] == EL_SIEB2_LEER)
+      else if (element == EL_MAGIC_WALL_BD_EMPTY ||
+              element == EL_MAGIC_WALL_BD_FULL ||
+              Store[x][y] == EL_MAGIC_WALL_BD_EMPTY)
       {
        SiebAktivieren(x, y, 2);
        sieb = TRUE;
@@ -4435,14 +4475,15 @@ void GameActions()
        {
          element = Feld[x][y];
 
-         if (element == EL_SIEB_LEER || element == EL_SIEB_VOLL)
+         if (element == EL_MAGIC_WALL_EMPTY || element == EL_MAGIC_WALL_FULL)
          {
-           Feld[x][y] = EL_SIEB_TOT;
+           Feld[x][y] = EL_MAGIC_WALL_DEAD;
            DrawLevelField(x, y);
          }
-         else if (element == EL_SIEB2_LEER || element == EL_SIEB2_VOLL)
+         else if (element == EL_MAGIC_WALL_BD_EMPTY ||
+                  element == EL_MAGIC_WALL_BD_FULL)
          {
-           Feld[x][y] = EL_SIEB2_TOT;
+           Feld[x][y] = EL_MAGIC_WALL_BD_DEAD;
            DrawLevelField(x, y);
          }
        }
@@ -5470,11 +5511,14 @@ int DigField(struct PlayerInfo *player,
       break;
 
     case EL_FELSBROCKEN:
+    case EL_BD_ROCK:
     case EL_BOMBE:
+    case EL_DX_SUPABOMB:
     case EL_KOKOSNUSS:
     case EL_ZEIT_LEER:
     case EL_SP_ZONK:
     case EL_SP_DISK_ORANGE:
+    case EL_SPRING:
       if (dy || mode == DF_SNAP)
        return MF_NO_ACTION;
 
@@ -5492,16 +5536,22 @@ int DigField(struct PlayerInfo *player,
       if (player->push_delay == 0)
        player->push_delay = FrameCounter;
       if (!FrameReached(&player->push_delay, player->push_delay_value) &&
-         !tape.playing)
+         !tape.playing && element != EL_SPRING)
        return MF_NO_ACTION;
 
       RemoveField(x, y);
       Feld[x+dx][y+dy] = element;
 
-      player->push_delay_value = 2+RND(8);
+      if (element == EL_SPRING)
+      {
+       Feld[x+dx][y+dy] = EL_SPRING_MOVING;
+       MovDir[x+dx][y+dy] = move_direction;
+      }
+
+      player->push_delay_value = (element == EL_SPRING ? 0 : 2 + RND(8));
 
       DrawLevelField(x+dx, y+dy);
-      if (element == EL_FELSBROCKEN)
+      if (element == EL_FELSBROCKEN || element == EL_BD_ROCK)
        PlaySoundLevel(x+dx, y+dy, SND_PUSCH);
       else if (element == EL_KOKOSNUSS)
        PlaySoundLevel(x+dx, y+dy, SND_KNURK);
@@ -5696,7 +5746,6 @@ int DigField(struct PlayerInfo *player,
     case EL_SONDE:
     case EL_SP_DISK_YELLOW:
     case EL_BALLOON:
-    case EL_SPRING:
       if (mode == DF_SNAP)
        return MF_NO_ACTION;