rnd-20040117-2-src
[rocksndiamonds.git] / src / game.c
index 4e6cdf9fd1903ce197d7a2b95537ee7bc62d5457..dfad329ef9c2b2e64d5df8fb4e1a4c6986edd595 100644 (file)
 #define GET_MAX_MOVE_DELAY(e)  (   (element_info[e].move_delay_fixed) + \
                                    (element_info[e].move_delay_random))
 
+#if 1
+#define ELEMENT_CAN_ENTER_FIELD_GENERIC(e, x, y, condition)            \
+               (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) ||                \
+                                       (condition) ||                  \
+                                       (DONT_COLLIDE_WITH(e) &&        \
+                                        IS_PLAYER(x, y) &&             \
+                                        !PLAYER_PROTECTED(x, y))))
+#else
 #define ELEMENT_CAN_ENTER_FIELD_GENERIC(e, x, y, condition)            \
                (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) ||                \
                                        (condition) ||                  \
                                        (DONT_COLLIDE_WITH(e) &&        \
                                         IS_FREE_OR_PLAYER(x, y))))
+#endif
 
 #define ELEMENT_CAN_ENTER_FIELD_GENERIC_2(x, y, condition)             \
                (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) ||                \
@@ -625,6 +634,18 @@ static void InitField(int x, int y, boolean init_game)
       InitPlayerField(x, y, element, init_game);
       break;
 
+    case EL_SOKOBAN_FIELD_PLAYER:
+      element = Feld[x][y] = EL_PLAYER_1;
+      InitField(x, y, init_game);
+
+      element = Feld[x][y] = EL_SOKOBAN_FIELD_EMPTY;
+      InitField(x, y, init_game);
+      break;
+
+    case EL_SOKOBAN_FIELD_EMPTY:
+      local_player->sokobanfields_still_needed++;
+      break;
+
     case EL_STONEBLOCK:
       if (x < lev_fieldx-1 && Feld[x+1][y] == EL_ACID)
        Feld[x][y] = EL_ACID_POOL_TOPLEFT;
@@ -702,10 +723,6 @@ static void InitField(int x, int y, boolean init_game)
       local_player->lights_still_needed++;
       break;
 
-    case EL_SOKOBAN_FIELD_EMPTY:
-      local_player->sokobanfields_still_needed++;
-      break;
-
     case EL_PENGUIN:
       local_player->friends_still_needed++;
       break;
@@ -1706,23 +1723,36 @@ void InitMovDir(int x, int y)
     default:
       if (IS_CUSTOM_ELEMENT(element))
       {
-       if (element_info[element].move_direction_initial != MV_NO_MOVING)
-         MovDir[x][y] = element_info[element].move_direction_initial;
-       else if (element_info[element].move_pattern == MV_ALL_DIRECTIONS ||
-                element_info[element].move_pattern == MV_TURNING_LEFT ||
-                element_info[element].move_pattern == MV_TURNING_RIGHT ||
-                element_info[element].move_pattern == MV_TURNING_LEFT_RIGHT ||
-                element_info[element].move_pattern == MV_TURNING_RIGHT_LEFT ||
-                element_info[element].move_pattern == MV_TURNING_RANDOM)
+       struct ElementInfo *ei = &element_info[element];
+       int move_direction_initial = ei->move_direction_initial;
+       int move_pattern = ei->move_pattern;
+
+       if (move_direction_initial == MV_PREVIOUS)
+       {
+         if (MovDir[x][y] != MV_NO_MOVING)
+           return;
+
+         move_direction_initial = MV_AUTOMATIC;
+       }
+
+       if (move_direction_initial & MV_ANY_DIRECTION)
+         MovDir[x][y] = move_direction_initial;
+       else if (move_direction_initial == MV_RANDOM ||
+                move_pattern == MV_ALL_DIRECTIONS ||
+                move_pattern == MV_TURNING_LEFT ||
+                move_pattern == MV_TURNING_RIGHT ||
+                move_pattern == MV_TURNING_LEFT_RIGHT ||
+                move_pattern == MV_TURNING_RIGHT_LEFT ||
+                move_pattern == MV_TURNING_RANDOM)
          MovDir[x][y] = 1 << RND(4);
-       else if (element_info[element].move_pattern == MV_HORIZONTAL)
+       else if (move_pattern == MV_HORIZONTAL)
          MovDir[x][y] = (RND(2) ? MV_LEFT : MV_RIGHT);
-       else if (element_info[element].move_pattern == MV_VERTICAL)
+       else if (move_pattern == MV_VERTICAL)
          MovDir[x][y] = (RND(2) ? MV_UP : MV_DOWN);
-       else if (element_info[element].move_pattern & MV_ANY_DIRECTION)
+       else if (move_pattern & MV_ANY_DIRECTION)
          MovDir[x][y] = element_info[element].move_pattern;
-       else if (element_info[element].move_pattern == MV_ALONG_LEFT_SIDE ||
-                element_info[element].move_pattern == MV_ALONG_RIGHT_SIDE)
+       else if (move_pattern == MV_ALONG_LEFT_SIDE ||
+                move_pattern == MV_ALONG_RIGHT_SIDE)
        {
          for (i = 0; i < 4; i++)
          {
@@ -1731,7 +1761,7 @@ void InitMovDir(int x, int y)
 
            if (!IN_LEV_FIELD(x1, y1) || !IS_FREE(x1, y1))
            {
-             if (element_info[element].move_pattern == MV_ALONG_RIGHT_SIDE)
+             if (move_pattern == MV_ALONG_RIGHT_SIDE)
                MovDir[x][y] = direction[0][i];
              else
                MovDir[x][y] = direction[1][i];
@@ -4685,44 +4715,63 @@ void StartMoving(int x, int y)
       }
     }
 
+#if 1
+
     /*
     else if (move_pattern & MV_MAZE_RUNNER_STYLE && IN_LEV_FIELD(newx, newy))
     */
 
     else if (IS_CUSTOM_ELEMENT(element) &&
-            CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, newx, newy))
-    {
-      int new_element = Feld[newx][newy];
-      int sound;
+            CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, newx, newy)
 
-      /* no element can dig solid indestructible elements */
-      if (IS_INDESTRUCTIBLE(new_element) &&
-         !IS_DIGGABLE(new_element) &&
-         !IS_COLLECTIBLE(new_element))
-       return;
+#if 0
+ &&
+            !IS_FREE(newx, newy)
+#endif
 
-      if (AmoebaNr[newx][newy] &&
-         (new_element == EL_AMOEBA_FULL ||
-          new_element == EL_BD_AMOEBA ||
-          new_element == EL_AMOEBA_GROWING))
-      {
-       AmoebaCnt[AmoebaNr[newx][newy]]--;
-       AmoebaCnt2[AmoebaNr[newx][newy]]--;
-      }
+)
+    {
+#if 0
+      printf("::: '%s' digs '%s' [%d]\n",
+            element_info[element].token_name,
+            element_info[Feld[newx][newy]].token_name,
+            StorePlayer[newx][newy]);
+#endif
 
-      if (IS_MOVING(newx, newy))
-       RemoveMovingField(newx, newy);
-      else
+      if (!IS_FREE(newx, newy))
       {
-       RemoveField(newx, newy);
-       DrawLevelField(newx, newy);
-      }
+       int new_element = Feld[newx][newy];
+       int sound;
 
-      sound = (IS_DIGGABLE(new_element) ? ACTION_DIGGING :
-              IS_COLLECTIBLE(new_element) ? ACTION_COLLECTING :
-              ACTION_BREAKING);
+       /* no element can dig solid indestructible elements */
+       if (IS_INDESTRUCTIBLE(new_element) &&
+           !IS_DIGGABLE(new_element) &&
+           !IS_COLLECTIBLE(new_element))
+         return;
 
-      PlayLevelSoundAction(x, y, sound);
+       if (AmoebaNr[newx][newy] &&
+           (new_element == EL_AMOEBA_FULL ||
+            new_element == EL_BD_AMOEBA ||
+            new_element == EL_AMOEBA_GROWING))
+       {
+         AmoebaCnt[AmoebaNr[newx][newy]]--;
+         AmoebaCnt2[AmoebaNr[newx][newy]]--;
+       }
+
+       if (IS_MOVING(newx, newy))
+         RemoveMovingField(newx, newy);
+       else
+       {
+         RemoveField(newx, newy);
+         DrawLevelField(newx, newy);
+       }
+
+       sound = (IS_DIGGABLE(new_element) ? ACTION_DIGGING :
+                IS_COLLECTIBLE(new_element) ? ACTION_COLLECTING :
+                ACTION_BREAKING);
+
+       PlayLevelSoundAction(x, y, sound);
+      }
 
       if (move_pattern & MV_MAZE_RUNNER_STYLE)
       {
@@ -4730,6 +4779,9 @@ void StartMoving(int x, int y)
        PlayerVisit[x][y] /= 8;         /* expire player visit path */
       }
     }
+
+#endif
+
     else if (element == EL_DRAGON && IN_LEV_FIELD(newx, newy))
     {
       if (!IS_FREE(newx, newy))
@@ -5017,6 +5069,7 @@ void ContinueMoving(int x, int y)
 
   ResetGfxAnimation(x, y);     /* reset animation values for old field */
 
+#if 1
   if (IS_CUSTOM_ELEMENT(element) && !IS_PLAYER(x, y))
   {
     int new_element = element_info[element].move_leave_element;
@@ -5033,6 +5086,7 @@ void ContinueMoving(int x, int y)
        DrawLevelFieldCrumbledSandNeighbours(x, y);
     }
   }
+#endif
 
 #if 0
   /* 2.1.1 (does not work correctly for spring) */
@@ -6085,6 +6139,8 @@ static void ChangeActiveTrap(int x, int y)
 
 static void ChangeElementNowExt(int x, int y, int target_element)
 {
+  int previous_move_direction = MovDir[x][y];
+
   /* check if element under player changes from accessible to unaccessible
      (needed for special case of dropping element which then changes) */
   if (IS_PLAYER(x, y) && !PLAYER_PROTECTED(x, y) &&
@@ -6102,6 +6158,9 @@ static void ChangeElementNowExt(int x, int y, int target_element)
   ResetGfxAnimation(x, y);
   ResetRandomAnimationValue(x, y);
 
+  if (element_info[Feld[x][y]].move_direction_initial == MV_PREVIOUS)
+    MovDir[x][y] = previous_move_direction;
+
   InitField(x, y, FALSE);
   if (CAN_MOVE(Feld[x][y]))
     InitMovDir(x, y);
@@ -9345,7 +9404,7 @@ boolean DropElement(struct PlayerInfo *player)
     int move_stepsize = element_info[new_element].move_stepsize;
     int direction, dx, dy, nextx, nexty;
 
-    if (element_info[new_element].move_direction_initial == MV_NO_MOVING)
+    if (element_info[new_element].move_direction_initial == MV_AUTOMATIC)
       MovDir[jx][jy] = player->MovDir;
 
     direction = MovDir[jx][jy];