rnd-20040325-1-src
authorHolger Schemel <info@artsoft.org>
Thu, 25 Mar 2004 09:01:43 +0000 (10:01 +0100)
committerHolger Schemel <info@artsoft.org>
Sat, 30 Aug 2014 08:46:38 +0000 (10:46 +0200)
* fixed bug with movable elements not moving after left behind by CEs

ChangeLog
src/conftime.h
src/editor.c
src/files.c
src/game.c
src/main.h

index 4ebfd87505f24b99ef40775c11769d642f194853..dcea920b159bdfd31e3e4baa205ed1ea80123f7a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
+2004-03-24
+       * fixed bug with movable elements not moving after left behind by CEs
+
 2004-03-23
-       * bug fixed with movable elements not moving anymore after falling down
+       * fixed bug with movable elements not moving anymore after falling down
 
 2004-03-22
        * fixed another bug with custom elements digging and leaving elements
index 1565dc42e54bfd3b5801ef567f41e1e9a383a0c6..999c4b9f15feec49cf4f0c8b9f445a0368ecaa60 100644 (file)
@@ -1 +1 @@
-#define COMPILE_DATE_STRING "[2004-03-24 11:12]"
+#define COMPILE_DATE_STRING "[2004-03-25 03:08]"
index 60e64be0be99ad3d2329448506283e48b7f757d3..97904719c9a2df1d74229853f6a667a834835a0e 100644 (file)
 #define GADGET_ID_BLOCK_LAST_FIELD     (GADGET_ID_CHECKBUTTON_FIRST + 8)
 #define GADGET_ID_SP_BLOCK_LAST_FIELD  (GADGET_ID_CHECKBUTTON_FIRST + 9)
 #define GADGET_ID_INSTANT_RELOCATION   (GADGET_ID_CHECKBUTTON_FIRST + 10)
-#define GADGET_ID_CAN_FALL_INTO_ACID   (GADGET_ID_CHECKBUTTON_FIRST + 11)
-#define GADGET_ID_CAN_MOVE_INTO_ACID   (GADGET_ID_CHECKBUTTON_FIRST + 12)
-#define GADGET_ID_DONT_COLLIDE_WITH    (GADGET_ID_CHECKBUTTON_FIRST + 13)
-#define GADGET_ID_CUSTOM_EXPLODE_RESULT        (GADGET_ID_CHECKBUTTON_FIRST + 14)
-#define GADGET_ID_CUSTOM_EXPLODE_FIRE  (GADGET_ID_CHECKBUTTON_FIRST + 15)
-#define GADGET_ID_CUSTOM_EXPLODE_SMASH (GADGET_ID_CHECKBUTTON_FIRST + 16)
-#define GADGET_ID_CUSTOM_EXPLODE_IMPACT        (GADGET_ID_CHECKBUTTON_FIRST + 17)
-#define GADGET_ID_CUSTOM_WALK_TO_OBJECT        (GADGET_ID_CHECKBUTTON_FIRST + 18)
-#define GADGET_ID_CUSTOM_DEADLY                (GADGET_ID_CHECKBUTTON_FIRST + 19)
-#define GADGET_ID_CUSTOM_CAN_MOVE      (GADGET_ID_CHECKBUTTON_FIRST + 20)
-#define GADGET_ID_CUSTOM_CAN_FALL      (GADGET_ID_CHECKBUTTON_FIRST + 21)
-#define GADGET_ID_CUSTOM_CAN_SMASH     (GADGET_ID_CHECKBUTTON_FIRST + 22)
-#define GADGET_ID_CUSTOM_SLIPPERY      (GADGET_ID_CHECKBUTTON_FIRST + 23)
-#define GADGET_ID_CUSTOM_ACCESSIBLE    (GADGET_ID_CHECKBUTTON_FIRST + 24)
-#define GADGET_ID_CUSTOM_USE_GRAPHIC   (GADGET_ID_CHECKBUTTON_FIRST + 25)
-#define GADGET_ID_CUSTOM_USE_TEMPLATE  (GADGET_ID_CHECKBUTTON_FIRST + 26)
-#define GADGET_ID_CUSTOM_CAN_CHANGE    (GADGET_ID_CHECKBUTTON_FIRST + 27)
-#define GADGET_ID_CHANGE_USE_CONTENT   (GADGET_ID_CHECKBUTTON_FIRST + 28)
-#define GADGET_ID_CHANGE_USE_EXPLOSION (GADGET_ID_CHECKBUTTON_FIRST + 29)
-#define GADGET_ID_CHANGE_ONLY_COMPLETE (GADGET_ID_CHECKBUTTON_FIRST + 30)
-#define GADGET_ID_CHANGE_USE_RANDOM    (GADGET_ID_CHECKBUTTON_FIRST + 31)
-#define GADGET_ID_CHANGE_DELAY         (GADGET_ID_CHECKBUTTON_FIRST + 32)
-#define GADGET_ID_CHANGE_BY_DIRECT_ACT (GADGET_ID_CHECKBUTTON_FIRST + 33)
-#define GADGET_ID_CHANGE_BY_OTHER_ACT  (GADGET_ID_CHECKBUTTON_FIRST + 34)
+#define GADGET_ID_CAN_PASS_TO_WALKABLE (GADGET_ID_CHECKBUTTON_FIRST + 11)
+#define GADGET_ID_CAN_FALL_INTO_ACID   (GADGET_ID_CHECKBUTTON_FIRST + 12)
+#define GADGET_ID_CAN_MOVE_INTO_ACID   (GADGET_ID_CHECKBUTTON_FIRST + 13)
+#define GADGET_ID_DONT_COLLIDE_WITH    (GADGET_ID_CHECKBUTTON_FIRST + 14)
+#define GADGET_ID_CUSTOM_EXPLODE_RESULT        (GADGET_ID_CHECKBUTTON_FIRST + 15)
+#define GADGET_ID_CUSTOM_EXPLODE_FIRE  (GADGET_ID_CHECKBUTTON_FIRST + 16)
+#define GADGET_ID_CUSTOM_EXPLODE_SMASH (GADGET_ID_CHECKBUTTON_FIRST + 17)
+#define GADGET_ID_CUSTOM_EXPLODE_IMPACT        (GADGET_ID_CHECKBUTTON_FIRST + 18)
+#define GADGET_ID_CUSTOM_WALK_TO_OBJECT        (GADGET_ID_CHECKBUTTON_FIRST + 19)
+#define GADGET_ID_CUSTOM_DEADLY                (GADGET_ID_CHECKBUTTON_FIRST + 20)
+#define GADGET_ID_CUSTOM_CAN_MOVE      (GADGET_ID_CHECKBUTTON_FIRST + 21)
+#define GADGET_ID_CUSTOM_CAN_FALL      (GADGET_ID_CHECKBUTTON_FIRST + 22)
+#define GADGET_ID_CUSTOM_CAN_SMASH     (GADGET_ID_CHECKBUTTON_FIRST + 23)
+#define GADGET_ID_CUSTOM_SLIPPERY      (GADGET_ID_CHECKBUTTON_FIRST + 24)
+#define GADGET_ID_CUSTOM_ACCESSIBLE    (GADGET_ID_CHECKBUTTON_FIRST + 25)
+#define GADGET_ID_CUSTOM_USE_GRAPHIC   (GADGET_ID_CHECKBUTTON_FIRST + 26)
+#define GADGET_ID_CUSTOM_USE_TEMPLATE  (GADGET_ID_CHECKBUTTON_FIRST + 27)
+#define GADGET_ID_CUSTOM_CAN_CHANGE    (GADGET_ID_CHECKBUTTON_FIRST + 28)
+#define GADGET_ID_CHANGE_USE_CONTENT   (GADGET_ID_CHECKBUTTON_FIRST + 29)
+#define GADGET_ID_CHANGE_USE_EXPLOSION (GADGET_ID_CHECKBUTTON_FIRST + 30)
+#define GADGET_ID_CHANGE_ONLY_COMPLETE (GADGET_ID_CHECKBUTTON_FIRST + 31)
+#define GADGET_ID_CHANGE_USE_RANDOM    (GADGET_ID_CHECKBUTTON_FIRST + 32)
+#define GADGET_ID_CHANGE_DELAY         (GADGET_ID_CHECKBUTTON_FIRST + 33)
+#define GADGET_ID_CHANGE_BY_DIRECT_ACT (GADGET_ID_CHECKBUTTON_FIRST + 34)
+#define GADGET_ID_CHANGE_BY_OTHER_ACT  (GADGET_ID_CHECKBUTTON_FIRST + 35)
 
 /* gadgets for buttons in element list */
-#define GADGET_ID_ELEMENTLIST_FIRST    (GADGET_ID_CHECKBUTTON_FIRST + 35)
+#define GADGET_ID_ELEMENTLIST_FIRST    (GADGET_ID_CHECKBUTTON_FIRST + 36)
 #define GADGET_ID_ELEMENTLIST_LAST     (GADGET_ID_ELEMENTLIST_FIRST +  \
                                        ED_NUM_ELEMENTLIST_BUTTONS - 1)
 
 #define ED_CHECKBUTTON_ID_BLOCK_LAST_FIELD     6
 #define ED_CHECKBUTTON_ID_SP_BLOCK_LAST_FIELD  7
 #define ED_CHECKBUTTON_ID_INSTANT_RELOCATION   8
-#define ED_CHECKBUTTON_ID_CAN_FALL_INTO_ACID   9
-#define ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID   10
-#define ED_CHECKBUTTON_ID_DONT_COLLIDE_WITH    11
-#define ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC   12
-#define ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE  13
-#define ED_CHECKBUTTON_ID_CUSTOM_ACCESSIBLE    14
-#define ED_CHECKBUTTON_ID_CUSTOM_WALK_TO_OBJECT        15
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_MOVE      16
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_FALL      17
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_SMASH     18
-#define ED_CHECKBUTTON_ID_CUSTOM_SLIPPERY      19
-#define ED_CHECKBUTTON_ID_CUSTOM_DEADLY                20
-#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_RESULT        21
-#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_FIRE  22
-#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_SMASH 23
-#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_IMPACT        24
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_CHANGE    25
-#define ED_CHECKBUTTON_ID_CHANGE_DELAY         26
-#define ED_CHECKBUTTON_ID_CHANGE_BY_DIRECT_ACT 27
-#define ED_CHECKBUTTON_ID_CHANGE_BY_OTHER_ACT  28
-#define ED_CHECKBUTTON_ID_CHANGE_USE_EXPLOSION 29
-#define ED_CHECKBUTTON_ID_CHANGE_USE_CONTENT   30
-#define ED_CHECKBUTTON_ID_CHANGE_ONLY_COMPLETE 31
-#define ED_CHECKBUTTON_ID_CHANGE_USE_RANDOM    32
-
-#define ED_NUM_CHECKBUTTONS                    33
+#define ED_CHECKBUTTON_ID_CAN_PASS_TO_WALKABLE 9
+#define ED_CHECKBUTTON_ID_CAN_FALL_INTO_ACID   10
+#define ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID   11
+#define ED_CHECKBUTTON_ID_DONT_COLLIDE_WITH    12
+#define ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC   13
+#define ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE  14
+#define ED_CHECKBUTTON_ID_CUSTOM_ACCESSIBLE    15
+#define ED_CHECKBUTTON_ID_CUSTOM_WALK_TO_OBJECT        16
+#define ED_CHECKBUTTON_ID_CUSTOM_CAN_MOVE      17
+#define ED_CHECKBUTTON_ID_CUSTOM_CAN_FALL      18
+#define ED_CHECKBUTTON_ID_CUSTOM_CAN_SMASH     19
+#define ED_CHECKBUTTON_ID_CUSTOM_SLIPPERY      20
+#define ED_CHECKBUTTON_ID_CUSTOM_DEADLY                21
+#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_RESULT        22
+#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_FIRE  23
+#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_SMASH 24
+#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_IMPACT        25
+#define ED_CHECKBUTTON_ID_CUSTOM_CAN_CHANGE    26
+#define ED_CHECKBUTTON_ID_CHANGE_DELAY         27
+#define ED_CHECKBUTTON_ID_CHANGE_BY_DIRECT_ACT 28
+#define ED_CHECKBUTTON_ID_CHANGE_BY_OTHER_ACT  29
+#define ED_CHECKBUTTON_ID_CHANGE_USE_EXPLOSION 30
+#define ED_CHECKBUTTON_ID_CHANGE_USE_CONTENT   31
+#define ED_CHECKBUTTON_ID_CHANGE_ONLY_COMPLETE 32
+#define ED_CHECKBUTTON_ID_CHANGE_USE_RANDOM    33
+
+#define ED_NUM_CHECKBUTTONS                    34
 
 #define ED_CHECKBUTTON_ID_LEVEL_FIRST  ED_CHECKBUTTON_ID_DOUBLE_SPEED
 #define ED_CHECKBUTTON_ID_LEVEL_LAST   ED_CHECKBUTTON_ID_RANDOM_RESTRICTED
@@ -1980,6 +1982,13 @@ static struct
     NULL,
     "no scrolling when relocating",    "player gets relocated without delay"
   },
+  {
+    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(3),
+    GADGET_ID_CAN_PASS_TO_WALKABLE,    GADGET_ID_NONE,
+    &level.can_pass_to_walkable,
+    NULL,
+    "can pass to walkable element",    "player can pass to empty or walkable"
+  },
   {
     ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(0),
     GADGET_ID_CAN_FALL_INTO_ACID,      GADGET_ID_NONE,
@@ -6997,6 +7006,7 @@ static void DrawPropertiesConfig()
                         ED_CHECKBUTTON_ID_SP_BLOCK_LAST_FIELD :
                         ED_CHECKBUTTON_ID_BLOCK_LAST_FIELD);
     MapCheckbuttonGadget(ED_CHECKBUTTON_ID_INSTANT_RELOCATION);
+    MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CAN_PASS_TO_WALKABLE);
   }
 
   if (IS_GEM(properties_element))
index cfce89f8b639a74d7d16f5d8fb8a6d4a1fff3de1..f44c2ca39afcff12d64029235bc0f65cfabff2d5 100644 (file)
@@ -29,7 +29,7 @@
 #define CHUNK_SIZE_NONE                -1      /* do not write chunk size    */
 #define FILE_VERS_CHUNK_SIZE   8       /* size of file version chunk */
 #define LEVEL_HEADER_SIZE      80      /* size of level file header  */
-#define LEVEL_HEADER_UNUSED    3       /* unused level header bytes  */
+#define LEVEL_HEADER_UNUSED    2       /* unused level header bytes  */
 #define LEVEL_CHUNK_CNT2_SIZE  160     /* size of level CNT2 chunk   */
 #define LEVEL_CHUNK_CNT2_UNUSED        11      /* unused CNT2 chunk bytes    */
 #define LEVEL_CHUNK_CNT3_HEADER        16      /* size of level CNT3 header  */
@@ -162,6 +162,7 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
   level->block_last_field = FALSE;
   level->sp_block_last_field = TRUE;
   level->instant_relocation = FALSE;
+  level->can_pass_to_walkable = FALSE;
 
   level->can_move_into_acid_bits = ~0; /* everything can move into acid */
   level->dont_collide_with_bits = ~0;  /* always deadly when colliding  */
@@ -703,6 +704,7 @@ static int LoadLevel_HEAD(FILE *file, int chunk_size, struct LevelInfo *level)
   level->use_step_counter      = (getFile8Bit(file) == 1 ? TRUE : FALSE);
 
   level->instant_relocation    = (getFile8Bit(file) == 1 ? TRUE : FALSE);
+  level->can_pass_to_walkable  = (getFile8Bit(file) == 1 ? TRUE : FALSE);
 
   ReadUnusedBytesFromFile(file, LEVEL_HEADER_UNUSED);
 
@@ -2441,6 +2443,7 @@ static void SaveLevel_HEAD(FILE *file, struct LevelInfo *level)
   putFile8Bit(file, (level->use_step_counter ? 1 : 0));
 
   putFile8Bit(file, (level->instant_relocation ? 1 : 0));
+  putFile8Bit(file, (level->can_pass_to_walkable ? 1 : 0));
 
   WriteUnusedBytesToFile(file, LEVEL_HEADER_UNUSED);
 }
index 6e8c99afe00b802289370fd0c1c12c3ecd3ff7ce..05460294a81d05a35f0e58af40cb809d06c09333 100644 (file)
@@ -1486,6 +1486,7 @@ void InitGame()
 
     player->is_waiting = FALSE;
     player->is_moving = FALSE;
+    player->is_auto_moving = FALSE;
     player->is_digging = FALSE;
     player->is_snapping = FALSE;
     player->is_collecting = FALSE;
@@ -5800,6 +5801,7 @@ void StartMoving(int x, int y)
 void ContinueMoving(int x, int y)
 {
   int element = Feld[x][y];
+  int stored = Store[x][y];
   struct ElementInfo *ei = &element_info[element];
   int direction = MovDir[x][y];
   int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
@@ -5904,7 +5906,7 @@ void ContinueMoving(int x, int y)
   {
     element = Feld[newx][newy] = EL_ACID;
   }
-#if 1
+#if 0
   else if (IS_CUSTOM_ELEMENT(element) && !IS_PLAYER(x, y) &&
           ei->move_leave_element != EL_EMPTY &&
           (ei->move_leave_type == LEAVE_TYPE_UNLIMITED ||
@@ -5948,6 +5950,22 @@ 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) &&
+      ei->move_leave_element != EL_EMPTY &&
+      (ei->move_leave_type == LEAVE_TYPE_UNLIMITED ||
+       stored != EL_EMPTY))
+  {
+    /* some elements can leave other elements behind after moving */
+
+    Feld[x][y] = ei->move_leave_element;
+    InitField(x, y, FALSE);
+
+    if (GFX_CRUMBLED(Feld[x][y]))
+      DrawLevelFieldCrumbledSandNeighbours(x, y);
+  }
+#endif
+
 #if 0
   /* some elements can leave other elements behind after moving */
   if (IS_CUSTOM_ELEMENT(element) && !IS_PLAYER(x, y) &&
@@ -8617,6 +8635,33 @@ static boolean canEnterSupaplexPort(int x, int y, int dx, int dy)
 }
 #endif
 
+static boolean canFallDown(struct PlayerInfo *player)
+{
+  int jx = player->jx, jy = player->jy;
+
+  return (IN_LEV_FIELD(jx, jy + 1) &&
+         (IS_FREE(jx, jy + 1) ||
+          (Feld[jx][jy + 1] == EL_ACID && player->can_fall_into_acid)) &&
+         IS_WALKABLE_FROM(Feld[jx][jy], MV_DOWN) &&
+         !IS_WALKABLE_INSIDE(Feld[jx][jy]));
+}
+
+static boolean canPassField(int x, int y, int move_dir)
+{
+  int opposite_dir = MV_DIR_OPPOSITE(move_dir);
+  int dx = (move_dir & MV_LEFT ? -1 : move_dir & MV_RIGHT ? +1 : 0);
+  int dy = (move_dir & MV_UP   ? -1 : move_dir & MV_DOWN  ? +1 : 0);
+  int nextx = x + dx;
+  int nexty = y + dy;
+  int element = Feld[x][y];
+
+  return (IS_PASSABLE_FROM(element, opposite_dir) &&
+         !CAN_MOVE(element) &&
+         IN_LEV_FIELD(nextx, nexty) && !IS_PLAYER(nextx, nexty) &&
+         IS_WALKABLE_FROM(Feld[nextx][nexty], move_dir) &&
+         (level.can_pass_to_walkable || IS_FREE(nextx, nexty)));
+}
+
 static boolean canMoveToValidFieldWithGravity(int x, int y, int move_dir)
 {
   int opposite_dir = MV_DIR_OPPOSITE(move_dir);
@@ -8624,10 +8669,17 @@ static boolean canMoveToValidFieldWithGravity(int x, int y, int move_dir)
   int dy = (move_dir & MV_UP   ? -1 : move_dir & MV_DOWN  ? +1 : 0);
   int newx = x + dx;
   int newy = y + dy;
+#if 0
   int nextx = newx + dx;
   int nexty = newy + dy;
-  boolean next_field_must_be_free = TRUE;
+#endif
 
+#if 1
+  return (IN_LEV_FIELD(newx, newy) && !IS_FREE_OR_PLAYER(newx, newy) &&
+         (IS_DIGGABLE(Feld[newx][newy]) ||
+          IS_WALKABLE_FROM(Feld[newx][newy], opposite_dir) ||
+          canPassField(newx, newy, move_dir)));
+#else
   return (IN_LEV_FIELD(newx, newy) && !IS_FREE_OR_PLAYER(newx, newy) &&
          (IS_DIGGABLE(Feld[newx][newy]) ||
           IS_WALKABLE_FROM(Feld[newx][newy], opposite_dir) ||
@@ -8635,7 +8687,8 @@ static boolean canMoveToValidFieldWithGravity(int x, int y, int move_dir)
            !CAN_MOVE(Feld[newx][newy]) &&
            IN_LEV_FIELD(nextx, nexty) && !IS_PLAYER(nextx, nexty) &&
            IS_WALKABLE_FROM(Feld[nextx][nexty], move_dir) &&
-           !(next_field_must_be_free && !IS_FREE(nextx, nexty)))));
+           (level.can_pass_to_walkable || IS_FREE(nextx, nexty)))));
+#endif
 }
 
 static void CheckGravityMovement(struct PlayerInfo *player)
@@ -8657,7 +8710,6 @@ static void CheckGravityMovement(struct PlayerInfo *player)
 
     int jx = player->jx, jy = player->jy;
 
-
     boolean player_is_moving_to_valid_field =
       (!player_is_snapping &&
        (canMoveToValidFieldWithGravity(jx, jy, move_dir_horizontal) ||
@@ -8679,10 +8731,16 @@ static void CheckGravityMovement(struct PlayerInfo *player)
 #endif
 
 #if 1
+
+#if 1
+    boolean player_can_fall_down = canFallDown(player);
+#else
     boolean player_can_fall_down =
       (IN_LEV_FIELD(jx, jy + 1) &&
        (IS_FREE(jx, jy + 1) ||
        (Feld[jx][jy + 1] == EL_ACID && player->can_fall_into_acid)));
+#endif
+
 #else
     boolean player_can_fall_down =
       (IN_LEV_FIELD(jx, jy + 1) &&
@@ -8713,9 +8771,11 @@ static void CheckGravityMovement(struct PlayerInfo *player)
        );
 #endif
 
+#if 0
     boolean player_is_standing_on_valid_field =
       (IS_WALKABLE_INSIDE(Feld[jx][jy]) ||
        (IS_WALKABLE(Feld[jx][jy]) && !ACCESS_FROM(Feld[jx][jy], MV_DOWN)));
+#endif
 
 #if 0
     printf("::: checking gravity NOW [%d, %d, %d] [%d] [%d / %d] ...\n",
@@ -8728,7 +8788,9 @@ static void CheckGravityMovement(struct PlayerInfo *player)
 #endif
 
     if (player_can_fall_down &&
+#if 0
        !player_is_standing_on_valid_field &&
+#endif
        !player_is_moving_to_valid_field)
     {
 #if 0
@@ -8923,6 +8985,9 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy)
 
 #endif
 
+  /* store if player is automatically moved to next field */
+  player->is_auto_moving = (player->programmed_action != MV_NO_MOVING);
+
   /* remove the last programmed player action */
   player->programmed_action = 0;
 
@@ -10308,6 +10373,13 @@ int DigField(struct PlayerInfo *player,
        if (!ACCESS_FROM(element, opposite_direction))
          return MF_NO_ACTION;  /* field not accessible from this direction */
 
+#if 1
+       if (element == EL_EMPTY_SPACE &&
+           game.gravity && !player->is_auto_moving &&
+           canFallDown(player) && move_direction != MV_DOWN)
+         return MF_NO_ACTION;  /* player cannot walk here due to gravity */
+#endif
+
        if (element >= EL_GATE_1 && element <= EL_GATE_4)
        {
          if (!player->key[element - EL_GATE_1])
@@ -10339,12 +10411,15 @@ int DigField(struct PlayerInfo *player,
       }
       else if (IS_PASSABLE(element))
       {
-       boolean next_field_must_be_free = TRUE;
+#if 1
+       if (!canPassField(x, y, move_direction))
+         return MF_NO_ACTION;
+#else
 
 #if 1
        if (!IN_LEV_FIELD(nextx, nexty) || IS_PLAYER(nextx, nexty) ||
            !IS_WALKABLE_FROM(Feld[nextx][nexty], move_direction) ||
-           (next_field_must_be_free && !IS_FREE(nextx, nexty)))
+           (!level.can_pass_to_walkable && !IS_FREE(nextx, nexty)))
          return MF_NO_ACTION;
 #else
        if (!IN_LEV_FIELD(nextx, nexty) || !IS_FREE(nextx, nexty))
@@ -10365,12 +10440,14 @@ int DigField(struct PlayerInfo *player,
          return MF_NO_ACTION;
 #endif
 
-       if (element >= EL_EM_GATE_1 && element <= EL_EM_GATE_4)
+#endif
+
+       if (IS_EM_GATE(element))
        {
          if (!player->key[element - EL_EM_GATE_1])
            return MF_NO_ACTION;
        }
-       else if (element >= EL_EM_GATE_1_GRAY && element <= EL_EM_GATE_4_GRAY)
+       else if (IS_EM_GATE_GRAY(element))
        {
          if (!player->key[element - EL_EM_GATE_1_GRAY])
            return MF_NO_ACTION;
index f2e076fafb4dd0b36e60282c19b76700d7d55ca7..c58dbfbe8ecc81897578a1f1ff66035bd4c78818 100644 (file)
 #define IS_ENVELOPE(e)         ((e) >= EL_ENVELOPE_1 &&                \
                                 (e) <= EL_ENVELOPE_4)
 
+#define IS_EM_GATE(e)          ((e) >= EL_EM_GATE_1 &&                 \
+                                (e) <= EL_EM_GATE_4)
+
+#define IS_EM_GATE_GRAY(e)     ((e) >= EL_EM_GATE_1_GRAY &&            \
+                                (e) <= EL_EM_GATE_4_GRAY)
+
 #define GFX_ELEMENT(e)         (element_info[e].use_gfx_element ?      \
                                 element_info[e].gfx_element : e)
 
@@ -1340,6 +1346,7 @@ struct PlayerInfo
 
   boolean is_waiting;
   boolean is_moving;
+  boolean is_auto_moving;
   boolean is_digging;
   boolean is_snapping;
   boolean is_collecting;
@@ -1453,6 +1460,7 @@ struct LevelInfo
   boolean sp_block_last_field; /* player blocks previous field while moving */
   boolean use_spring_bug;      /* for compatibility with old levels */
   boolean instant_relocation;  /* no visual delay when relocating player */
+  boolean can_pass_to_walkable;        /* player can pass to empty or walkable tile */
 
   /* ('int' instead of 'boolean' because used as selectbox value in editor) */
   int use_step_counter;                /* count steps instead of seconds for level */