+ if (!stored_player[i].active)
+ continue;
+
+ if (!IN_VIS_FIELD(SCREENX(jx), SCREENY(jy)))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void ScrollLevel(int dx, int dy)
+{
+ int softscroll_offset = (setup.soft_scrolling ? TILEX : 0);
+ int x, y;
+
+ BlitBitmap(drawto_field, drawto_field,
+ FX + TILEX * (dx == -1) - softscroll_offset,
+ FY + TILEY * (dy == -1) - softscroll_offset,
+ SXSIZE - TILEX * (dx!=0) + 2 * softscroll_offset,
+ SYSIZE - TILEY * (dy!=0) + 2 * softscroll_offset,
+ FX + TILEX * (dx == 1) - softscroll_offset,
+ FY + TILEY * (dy == 1) - softscroll_offset);
+
+ if (dx)
+ {
+ x = (dx == 1 ? BX1 : BX2);
+ for (y = BY1; y <= BY2; y++)
+ DrawScreenField(x, y);
+ }
+
+ if (dy)
+ {
+ y = (dy == 1 ? BY1 : BY2);
+ for (x = BX1; x <= BX2; x++)
+ DrawScreenField(x, y);
+ }
+
+ redraw_mask |= REDRAW_FIELD;
+}
+
+#if 0
+static boolean canEnterSupaplexPort(int x, int y, int dx, int dy)
+{
+ int nextx = x + dx, nexty = y + dy;
+ int element = Feld[x][y];
+
+ if ((dx == -1 &&
+ element != EL_SP_PORT_LEFT &&
+ element != EL_SP_GRAVITY_PORT_LEFT &&
+ element != EL_SP_PORT_HORIZONTAL &&
+ element != EL_SP_PORT_ANY) ||
+ (dx == +1 &&
+ element != EL_SP_PORT_RIGHT &&
+ element != EL_SP_GRAVITY_PORT_RIGHT &&
+ element != EL_SP_PORT_HORIZONTAL &&
+ element != EL_SP_PORT_ANY) ||
+ (dy == -1 &&
+ element != EL_SP_PORT_UP &&
+ element != EL_SP_GRAVITY_PORT_UP &&
+ element != EL_SP_PORT_VERTICAL &&
+ element != EL_SP_PORT_ANY) ||
+ (dy == +1 &&
+ element != EL_SP_PORT_DOWN &&
+ element != EL_SP_GRAVITY_PORT_DOWN &&
+ element != EL_SP_PORT_VERTICAL &&
+ element != EL_SP_PORT_ANY) ||
+ !IN_LEV_FIELD(nextx, nexty) ||
+ !IS_FREE(nextx, nexty))
+ return FALSE;
+
+ return TRUE;
+}
+#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) ||
+#if USE_NEW_BLOCK_STYLE
+#if USE_GRAVITY_BUGFIX_OLD
+ Feld[jx][jy + 1] == EL_PLAYER_IS_LEAVING ||
+#endif
+#endif
+ (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);
+ 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 newx = x + dx;
+ int newy = y + dy;
+#if 0
+ int nextx = newx + dx;
+ int nexty = newy + dy;
+#endif
+
+#if 1
+ return (IN_LEV_FIELD(newx, newy) && !IS_FREE_OR_PLAYER(newx, newy) &&
+ IS_GRAVITY_REACHABLE(Feld[newx][newy]) &&
+#if 0
+ (!IS_SP_PORT(Feld[newx][newy]) || move_dir == MV_UP) &&
+#endif
+ (IS_DIGGABLE(Feld[newx][newy]) ||
+ IS_WALKABLE_FROM(Feld[newx][newy], opposite_dir) ||
+ canPassField(newx, newy, move_dir)));
+#else
+#if 1
+ return (IN_LEV_FIELD(newx, newy) && !IS_FREE_OR_PLAYER(newx, newy) &&
+ IS_GRAVITY_REACHABLE(Feld[newx][newy]) &&
+ (IS_DIGGABLE(Feld[newx][newy]) ||
+ IS_WALKABLE_FROM(Feld[newx][newy], opposite_dir) ||
+ canPassField(newx, newy, move_dir)));
+#else
+#if 1
+ return (IN_LEV_FIELD(newx, newy) && !IS_FREE_OR_PLAYER(newx, newy) &&
+ (IS_DIGGABLE_WITH_GRAVITY(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) ||
+ (IS_PASSABLE_FROM(Feld[newx][newy], opposite_dir) &&
+ !CAN_MOVE(Feld[newx][newy]) &&
+ 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)))));
+#endif
+#endif
+#endif
+}
+
+static void CheckGravityMovement(struct PlayerInfo *player)
+{
+ if (game.gravity && !player->programmed_action)
+ {
+#if 1
+ int move_dir_horizontal = player->effective_action & MV_HORIZONTAL;
+ int move_dir_vertical = player->effective_action & MV_VERTICAL;
+#else
+ int move_dir_horizontal = player->action & MV_HORIZONTAL;
+ int move_dir_vertical = player->action & MV_VERTICAL;
+#endif
+
+#if 1
+ boolean player_is_snapping = player->effective_action & JOY_BUTTON_1;
+#else
+ boolean player_is_snapping = player->action & JOY_BUTTON_1;
+#endif
+
+ int jx = player->jx, jy = player->jy;
+
+ boolean player_is_moving_to_valid_field =
+ (!player_is_snapping &&
+ (canMoveToValidFieldWithGravity(jx, jy, move_dir_horizontal) ||
+ canMoveToValidFieldWithGravity(jx, jy, move_dir_vertical)));
+
+#if 0
+ int move_dir =
+ (player->last_move_dir & MV_HORIZONTAL ?
+ (move_dir_vertical ? move_dir_vertical : move_dir_horizontal) :
+ (move_dir_horizontal ? move_dir_horizontal : move_dir_vertical));
+#endif
+
+#if 0
+ 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 new_jx = jx + dx, new_jy = jy + dy;
+ int nextx = new_jx + dx, nexty = new_jy + dy;
+#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) &&
+ (IS_FREE(jx, jy + 1)));
+#endif