rnd-20030419-2-src
[rocksndiamonds.git] / src / game.c
index fb479b0e964d2086a206fd79e217ab23fc2ae3fb..0f4ce58eb9455bbb3bcd9d0231a783da8a3ad5dd 100644 (file)
@@ -723,7 +723,7 @@ void InitGame()
     {
       Feld[x][y] = Ur[x][y];
       MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0;
-      Store[x][y] = Store2[x][y] = StorePlayer[x][y] = 0;
+      Store[x][y] = Store2[x][y] = StorePlayer[x][y] = Back[x][y] = 0;
       AmoebaNr[x][y] = 0;
       JustStopped[x][y] = 0;
       Stop[x][y] = FALSE;
@@ -1378,7 +1378,7 @@ static int MovingOrBlocked2ElementIfNotLeaving(int x, int y)
 static void RemoveField(int x, int y)
 {
   Feld[x][y] = EL_EMPTY;
-  GfxElement[x][y] = EL_EMPTY;
+  GfxElement[x][y] = EL_UNDEFINED;
   MovPos[x][y] = 0;
   MovDir[x][y] = 0;
   MovDelay[x][y] = 0;
@@ -1433,13 +1433,18 @@ void DrawDynamite(int x, int y)
   if (!IN_SCR_FIELD(sx, sy) || IS_PLAYER(x, y))
     return;
 
-  if (Store[x][y])
+  if (IS_WALKABLE_INSIDE(Back[x][y]))
+    return;
+
+  if (Back[x][y])
+    DrawGraphic(sx, sy, el2img(Back[x][y]), 0);
+  else if (Store[x][y])
     DrawGraphic(sx, sy, el2img(Store[x][y]), 0);
 
   frame = getGraphicAnimationFrame(graphic, GfxFrame[x][y]);
 
 #if 1
-  if (Store[x][y])
+  if (Back[x][y] || Store[x][y])
     DrawGraphicThruMask(sx, sy, graphic, frame);
   else
     DrawGraphic(sx, sy, graphic, frame);
@@ -1500,6 +1505,10 @@ void Explode(int ex, int ey, int phase, int mode)
   {
     int center_element = Feld[ex][ey];
 
+    /* remove things displayed in background while burning dynamite */
+    if (!IS_INDESTRUCTIBLE(Back[ex][ey]))
+      Back[ex][ey] = 0;
+
     if (IS_MOVING(ex, ey) || IS_BLOCKED(ex, ey))
     {
       /* put moving element to center field (and let it explode there) */
@@ -1525,8 +1534,16 @@ void Explode(int ex, int ey, int phase, int mode)
        RemoveMovingField(x, y);
       }
 
-      if (IS_INDESTRUCTIBLE(element) || element == EL_FLAMES)
+#if 1
+      if ((IS_INDESTRUCTIBLE(element) &&
+          (game.engine_version < VERSION_IDENT(2,2,0) ||
+           (!IS_WALKABLE_OVER(element) && !IS_WALKABLE_UNDER(element)))) ||
+         element == EL_FLAMES)
        continue;
+#else
+      if (IS_INDESTRUCTIBLE(element) || element == EL_FLAMES)
+        continue;
+#endif
 
       if (IS_PLAYER(x, y) && SHIELD_ON(PLAYERINFO(x, y)))
       {
@@ -1540,9 +1557,26 @@ void Explode(int ex, int ey, int phase, int mode)
        continue;
       }
 
+#if 1
+      /* save walkable background elements while explosion on same tile */
+      if (IS_INDESTRUCTIBLE(element))
+       Back[x][y] = element;
+#endif
+
+      /* ignite explodable elements reached by other explosion */
       if (element == EL_EXPLOSION)
        element = Store2[x][y];
 
+#if 0
+      else if (IS_INDESTRUCTIBLE(Store2[x][y]))        /* hard element under bomb */
+       element = Store2[x][y];
+#endif
+
+#if 0
+      else if (IS_INDESTRUCTIBLE(Store[x][y])) /* hard element under bomb */
+       element = Store[x][y];
+#endif
+
       if (IS_PLAYER(ex, ey) && !PLAYER_PROTECTED(ex, ey))
       {
        switch(StorePlayer[ex][ey])
@@ -1565,6 +1599,18 @@ void Explode(int ex, int ey, int phase, int mode)
        if (game.emulation == EMU_SUPAPLEX)
          Store[x][y] = EL_EMPTY;
       }
+#if 0
+      else if (IS_INDESTRUCTIBLE(Store[x][y]))
+       ;
+#endif
+#if 0
+      else if (IS_INDESTRUCTIBLE(element))
+       Store[x][y] = element;
+#endif
+#if 0
+      else if (IS_INDESTRUCTIBLE(element) && IS_ACCESSIBLE(element))
+       Store[x][y] = element;
+#endif
       else if (center_element == EL_MOLE)
        Store[x][y] = EL_EMERALD_RED;
       else if (center_element == EL_PENGUIN)
@@ -1595,8 +1641,31 @@ void Explode(int ex, int ey, int phase, int mode)
        Store[x][y] = EL_PEARL;
       else if (element == EL_WALL_CRYSTAL)
        Store[x][y] = EL_CRYSTAL;
+#if 1
+#if 0
+#if 0
+      else if (IS_INDESTRUCTIBLE(element) && IS_ACCESSIBLE(element))
+       Store[x][y] = element;
+#else
+      else if (IS_INDESTRUCTIBLE(element))
+       Store[x][y] = element;
+#endif
+#endif
+      else
+       Store[x][y] = EL_EMPTY;
+#else
+
+#if 0
+      else if (IS_PFORTE(element))
+       Store[x][y] = element;
+      else
+       Store[x][y] = EL_EMPTY;
+#else
       else if (!IS_PFORTE(Store[x][y]))
        Store[x][y] = EL_EMPTY;
+#endif
+
+#endif
 
       if (x != ex || y != ey ||
          center_element == EL_AMOEBA_TO_DIAMOND || mode == EX_BORDER)
@@ -1612,7 +1681,7 @@ void Explode(int ex, int ey, int phase, int mode)
       }
 
       Feld[x][y] = EL_EXPLOSION;
-      GfxElement[x][y] = EL_EMPTY;
+      GfxElement[x][y] = EL_UNDEFINED;
       MovDir[x][y] = MovPos[x][y] = 0;
       AmoebaNr[x][y] = 0;
       ExplodePhase[x][y] = 1;
@@ -1666,6 +1735,13 @@ void Explode(int ex, int ey, int phase, int mode)
 
     element = Feld[x][y] = Store[x][y];
     Store[x][y] = Store2[x][y] = 0;
+
+#if 1
+    if (Back[x][y] && IS_INDESTRUCTIBLE(Back[x][y]))
+      element = Feld[x][y] = Back[x][y];
+    Back[x][y] = 0;
+#endif
+
     MovDir[x][y] = MovPos[x][y] = MovDelay[x][y] = 0;
     InitField(x, y, FALSE);
     if (CAN_MOVE(element) || COULD_MOVE(element))
@@ -1686,6 +1762,20 @@ void Explode(int ex, int ey, int phase, int mode)
     if (phase == delay)
       DrawLevelFieldCrumbledSand(x, y);
 
+#if 1
+    if (IS_WALKABLE_OVER(Back[x][y]))
+    {
+      DrawLevelElement(x, y, Back[x][y]);
+      DrawGraphicThruMask(SCREENX(x), SCREENY(y), graphic, frame);
+    }
+    else if (IS_WALKABLE_UNDER(Back[x][y]))
+    {
+      DrawGraphic(SCREENX(x), SCREENY(y), graphic, frame);
+      DrawLevelElementThruMask(x, y, Back[x][y]);
+    }
+    else if (!IS_WALKABLE_INSIDE(Back[x][y]))
+      DrawGraphic(SCREENX(x), SCREENY(y), graphic, frame);
+#else
     if (IS_PFORTE(Store[x][y]))
     {
       DrawLevelElement(x, y, Store[x][y]);
@@ -1693,6 +1783,7 @@ void Explode(int ex, int ey, int phase, int mode)
     }
     else
       DrawGraphic(SCREENX(x), SCREENY(y), graphic, frame);
+#endif
   }
 }
 
@@ -5030,7 +5121,7 @@ static void CheckGravityMovement(struct PlayerInfo *player)
 
     if (field_under_player_is_free &&
        !player_is_moving_to_valid_field &&
-       !IS_WALKABLE_THROUGH(Feld[jx][jy]))
+       !IS_WALKABLE_INSIDE(Feld[jx][jy]))
       player->programmed_action = MV_DOWN;
   }
 }
@@ -5604,8 +5695,13 @@ void KillHero(struct PlayerInfo *player)
   if (!player->active)
     return;
 
+#if 1
+  /* remove accessible field at the player's position */
+  Feld[jx][jy] = EL_EMPTY;
+#else
   if (IS_PFORTE(Feld[jx][jy]))
     Feld[jx][jy] = EL_EMPTY;
+#endif
 
   /* deactivate shield (else Bang()/Explode() would not work right) */
   player->shield_normal_time_left = 0;
@@ -6474,7 +6570,13 @@ boolean PlaceBomb(struct PlayerInfo *player)
     return FALSE;
 
   if (element != EL_EMPTY)
+  {
+#if 0
     Store[jx][jy] = element;
+#else
+    Back[jx][jy] = element;
+#endif
+  }
 
   MovDelay[jx][jy] = 96;