rnd-20040611-1-src
[rocksndiamonds.git] / src / game.c
index 13089ad43e1b2f21a018cef525fae6b8c47d893b..6de0372ce71aba949569874c821db12d8707d7a9 100644 (file)
@@ -27,6 +27,9 @@
 /* EXPERIMENTAL STUFF */
 #define USE_NEW_AMOEBA_CODE    FALSE
 
+/* EXPERIMENTAL STUFF */
+#define USE_NEW_MOVEMENT       FALSE
+
 /* for DigField() */
 #define DF_NO_PUSH             0
 #define DF_DIG                 1
@@ -612,31 +615,39 @@ struct
 }
 access_direction_list[] =
 {
-  { EL_TUBE_ANY,               MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN },
-  { EL_TUBE_VERTICAL,                               MV_UP | MV_DOWN },
-  { EL_TUBE_HORIZONTAL,                MV_LEFT | MV_RIGHT                   },
-  { EL_TUBE_VERTICAL_LEFT,     MV_LEFT |            MV_UP | MV_DOWN },
-  { EL_TUBE_VERTICAL_RIGHT,              MV_RIGHT | MV_UP | MV_DOWN },
-  { EL_TUBE_HORIZONTAL_UP,     MV_LEFT | MV_RIGHT | MV_UP           },
-  { EL_TUBE_HORIZONTAL_DOWN,   MV_LEFT | MV_RIGHT |         MV_DOWN },
-  { EL_TUBE_LEFT_UP,           MV_LEFT |            MV_UP           },
-  { EL_TUBE_LEFT_DOWN,         MV_LEFT |                    MV_DOWN },
-  { EL_TUBE_RIGHT_UP,                    MV_RIGHT | MV_UP           },
-  { EL_TUBE_RIGHT_DOWN,                          MV_RIGHT |         MV_DOWN },
-
-  { EL_SP_PORT_LEFT,                     MV_RIGHT                   },
-  { EL_SP_PORT_RIGHT,          MV_LEFT                              },
-  { EL_SP_PORT_UP,                                          MV_DOWN },
-  { EL_SP_PORT_DOWN,                                MV_UP           },
-  { EL_SP_PORT_HORIZONTAL,     MV_LEFT | MV_RIGHT                   },
-  { EL_SP_PORT_VERTICAL,                            MV_UP | MV_DOWN },
-  { EL_SP_PORT_ANY,            MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN },
-  { EL_SP_GRAVITY_PORT_LEFT,             MV_RIGHT                   },
-  { EL_SP_GRAVITY_PORT_RIGHT,  MV_LEFT                              },
-  { EL_SP_GRAVITY_PORT_UP,                                  MV_DOWN },
-  { EL_SP_GRAVITY_PORT_DOWN,                        MV_UP           },
-
-  { EL_UNDEFINED,              MV_NO_MOVING                         }
+  { EL_TUBE_ANY,                       MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN },
+  { EL_TUBE_VERTICAL,                                       MV_UP | MV_DOWN },
+  { EL_TUBE_HORIZONTAL,                        MV_LEFT | MV_RIGHT                   },
+  { EL_TUBE_VERTICAL_LEFT,             MV_LEFT |            MV_UP | MV_DOWN },
+  { EL_TUBE_VERTICAL_RIGHT,                      MV_RIGHT | MV_UP | MV_DOWN },
+  { EL_TUBE_HORIZONTAL_UP,             MV_LEFT | MV_RIGHT | MV_UP           },
+  { EL_TUBE_HORIZONTAL_DOWN,           MV_LEFT | MV_RIGHT |         MV_DOWN },
+  { EL_TUBE_LEFT_UP,                   MV_LEFT |            MV_UP           },
+  { EL_TUBE_LEFT_DOWN,                 MV_LEFT |                    MV_DOWN },
+  { EL_TUBE_RIGHT_UP,                            MV_RIGHT | MV_UP           },
+  { EL_TUBE_RIGHT_DOWN,                                  MV_RIGHT |         MV_DOWN },
+
+  { EL_SP_PORT_LEFT,                             MV_RIGHT                   },
+  { EL_SP_PORT_RIGHT,                  MV_LEFT                              },
+  { EL_SP_PORT_UP,                                                  MV_DOWN },
+  { EL_SP_PORT_DOWN,                                        MV_UP           },
+  { EL_SP_PORT_HORIZONTAL,             MV_LEFT | MV_RIGHT                   },
+  { EL_SP_PORT_VERTICAL,                                    MV_UP | MV_DOWN },
+  { EL_SP_PORT_ANY,                    MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN },
+  { EL_SP_GRAVITY_PORT_LEFT,                     MV_RIGHT                   },
+  { EL_SP_GRAVITY_PORT_RIGHT,          MV_LEFT                              },
+  { EL_SP_GRAVITY_PORT_UP,                                          MV_DOWN },
+  { EL_SP_GRAVITY_PORT_DOWN,                                MV_UP           },
+  { EL_SP_GRAVITY_ON_PORT_LEFT,                          MV_RIGHT                   },
+  { EL_SP_GRAVITY_ON_PORT_RIGHT,       MV_LEFT                              },
+  { EL_SP_GRAVITY_ON_PORT_UP,                                       MV_DOWN },
+  { EL_SP_GRAVITY_ON_PORT_DOWN,                                     MV_UP           },
+  { EL_SP_GRAVITY_OFF_PORT_LEFT,                 MV_RIGHT                   },
+  { EL_SP_GRAVITY_OFF_PORT_RIGHT,      MV_LEFT                              },
+  { EL_SP_GRAVITY_OFF_PORT_UP,                                      MV_DOWN },
+  { EL_SP_GRAVITY_OFF_PORT_DOWN,                            MV_UP           },
+
+  { EL_UNDEFINED,                      MV_NO_MOVING                         }
 };
 
 static unsigned long trigger_events[MAX_NUM_ELEMENTS];
@@ -5285,6 +5296,11 @@ void StartMoving(int x, int y)
 
       CheckCollision[x][y] = 0;
 
+#if 0
+      if (IS_PLAYER(x, y + 1))
+       printf("::: we ARE now killing the player [%d]\n", FrameCounter);
+#endif
+
       Impact(x, y);
     }
     else if (IS_FREE(x, y + 1) && element == EL_SPRING && level.use_spring_bug)
@@ -6360,9 +6376,24 @@ void ContinueMoving(int x, int y)
   else if (element == EL_PENGUIN)
     TestIfFriendTouchesBadThing(newx, newy);
 
+#if USE_NEW_MOVEMENT
+#if 0
+  if (CAN_FALL(element) && direction == MV_DOWN &&
+      (newy == lev_fieldy - 1 || !IS_FREE(x, newy + 1)) &&
+      IS_PLAYER(x, newy + 1))
+    printf("::: we would now kill the player [%d]\n", FrameCounter);
+#endif
+
+  /* give the player one last chance (one more frame) to move away */
+  if (CAN_FALL(element) && direction == MV_DOWN &&
+      (newy == lev_fieldy - 1 || !IS_FREE(x, newy + 1)) &&
+      !IS_PLAYER(x, newy + 1))
+    Impact(x, newy);
+#else
   if (CAN_FALL(element) && direction == MV_DOWN &&
       (newy == lev_fieldy - 1 || !IS_FREE(x, newy + 1)))
     Impact(x, newy);
+#endif
 
 #if 1
   if (pushed_by_player)
@@ -7433,6 +7464,11 @@ static void ChangeElementNowExt(int x, int y, int target_element)
   if (IS_PLAYER(x, y) && !PLAYER_EXPLOSION_PROTECTED(x, y) &&
       IS_ACCESSIBLE(Feld[x][y]) && !IS_ACCESSIBLE(target_element))
   {
+#if 0
+    printf("::: BOOOM! [%d, '%s']\n", target_element,
+          element_info[target_element].token_name);
+#endif
+
     Bang(x, y);
     return;
   }
@@ -7610,6 +7646,7 @@ static boolean ChangeElementNow(int x, int y, int element, int page)
 #endif
 
 #endif
+
       is_walkable     = (is_empty || IS_WALKABLE(e));
       is_diggable     = (is_empty || IS_DIGGABLE(e));
       is_collectible  = (is_empty || IS_COLLECTIBLE(e));
@@ -7617,12 +7654,13 @@ static boolean ChangeElementNow(int x, int y, int element, int page)
       is_removable    = (is_diggable || is_collectible);
 
       can_replace[xx][yy] =
-       ((change->replace_when == CP_WHEN_EMPTY        && is_empty) ||
-        (change->replace_when == CP_WHEN_WALKABLE     && is_walkable) ||
-        (change->replace_when == CP_WHEN_DIGGABLE     && is_diggable) ||
-        (change->replace_when == CP_WHEN_COLLECTIBLE  && is_collectible) ||
-        (change->replace_when == CP_WHEN_REMOVABLE    && is_removable) ||
-        (change->replace_when == CP_WHEN_DESTRUCTIBLE && is_destructible));
+       (((change->replace_when == CP_WHEN_EMPTY        && is_empty) ||
+         (change->replace_when == CP_WHEN_WALKABLE     && is_walkable) ||
+         (change->replace_when == CP_WHEN_DIGGABLE     && is_diggable) ||
+         (change->replace_when == CP_WHEN_COLLECTIBLE  && is_collectible) ||
+         (change->replace_when == CP_WHEN_REMOVABLE    && is_removable) ||
+         (change->replace_when == CP_WHEN_DESTRUCTIBLE && is_destructible)) &&
+        !(IS_PLAYER(ex, ey) && ELEM_IS_PLAYER(content_element)));
 
       if (!can_replace[xx][yy])
        complete_replace = FALSE;
@@ -9469,14 +9507,30 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
 #else
 
 #if 1
+
+#if 0
+  printf("::: %d <= %d < %d ?\n", player->move_delay, FrameCounter,
+        player->move_delay + player->move_delay_value);
+#endif
+
   if (!FrameReached(&player->move_delay, player->move_delay_value))
+  {
+#if 0
+    printf("::: can NOT move\n");
+#endif
+
     return FALSE;
+  }
 #else
   if (!FrameReached(&player->move_delay, player->move_delay_value) &&
       !(tape.playing && tape.file_version < FILE_VERSION_2_0))
     return FALSE;
 #endif
 
+#endif
+
+#if 0
+  printf("::: COULD move now\n");
 #endif
 
   /* store if player is automatically moved to next field */
@@ -9608,6 +9662,10 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
 
   if (moved & MF_MOVING)
   {
+#if 0
+    printf("::: REALLY moves now\n");
+#endif
+
     if (old_jx != jx && old_jy == jy)
       player->MovDir = (old_jx < jx ? MV_RIGHT : MV_LEFT);
     else if (old_jx == jx && old_jy != jy)
@@ -9687,6 +9745,15 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
     player->last_move_dir = MV_NO_MOVING;
     */
     player->is_moving = FALSE;
+
+#if USE_NEW_MOVEMENT
+    /* player is ALLOWED to move, but CANNOT move (something blocks his way) */
+    /* ensure that the player is also allowed to move in the next frame */
+    /* (currently, the player is forced to wait eight frames before he can try
+       again!!!) */
+
+    player->move_delay = -1;   /* allow direct movement in the next frame */
+#endif
   }
 
   if (game.engine_version < VERSION_IDENT(3,0,7,0))
@@ -9715,8 +9782,14 @@ void ScrollPlayer(struct PlayerInfo *player, int mode)
     player->actual_frame_counter = FrameCounter;
     player->GfxPos = move_stepsize * (player->MovPos / move_stepsize);
 
+#if USE_NEW_MOVEMENT
+    if (player->block_last_field &&
+       Feld[last_jx][last_jy] == EL_EMPTY)
+      Feld[last_jx][last_jy] = EL_PLAYER_IS_LEAVING;
+#else
     if (Feld[last_jx][last_jy] == EL_EMPTY)
       Feld[last_jx][last_jy] = EL_PLAYER_IS_LEAVING;
+#endif
 
 #if 0
     DrawPlayer(player);
@@ -10036,7 +10109,7 @@ void TestIfElementTouchesCustomElement(int x, int y)
   boolean change_center_element = FALSE;
   int center_element_change_page = 0;
   int center_element = Feld[x][y];     /* should always be non-moving! */
-  int border_trigger_element;
+  int border_trigger_element = EL_UNDEFINED;
   int i, j;
 
   for (i = 0; i < NUM_DIRECTIONS; i++)
@@ -11045,6 +11118,16 @@ int DigField(struct PlayerInfo *player,
              element == EL_SP_GRAVITY_PORT_UP ||
              element == EL_SP_GRAVITY_PORT_DOWN)
            game.gravity = !game.gravity;
+         else if (element == EL_SP_GRAVITY_ON_PORT_LEFT ||
+                  element == EL_SP_GRAVITY_ON_PORT_RIGHT ||
+                  element == EL_SP_GRAVITY_ON_PORT_UP ||
+                  element == EL_SP_GRAVITY_ON_PORT_DOWN)
+           game.gravity = TRUE;
+         else if (element == EL_SP_GRAVITY_OFF_PORT_LEFT ||
+                  element == EL_SP_GRAVITY_OFF_PORT_RIGHT ||
+                  element == EL_SP_GRAVITY_OFF_PORT_UP ||
+                  element == EL_SP_GRAVITY_OFF_PORT_DOWN)
+           game.gravity = FALSE;
        }
 
        /* automatically move to the next field with double speed */