+ game.restart_level = FALSE;
+}
+
+void UpdateEngineValues(int actual_scroll_x, int actual_scroll_y)
+{
+ /* this is used for non-R'n'D game engines to update certain engine values */
+
+ /* needed to determine if sounds are played within the visible screen area */
+ scroll_x = actual_scroll_x;
+ scroll_y = actual_scroll_y;
+}
+
+void InitMovDir(int x, int y)
+{
+ int i, element = Feld[x][y];
+ static int xy[4][2] =
+ {
+ { 0, +1 },
+ { +1, 0 },
+ { 0, -1 },
+ { -1, 0 }
+ };
+ static int direction[3][4] =
+ {
+ { MV_RIGHT, MV_UP, MV_LEFT, MV_DOWN },
+ { MV_LEFT, MV_DOWN, MV_RIGHT, MV_UP },
+ { MV_LEFT, MV_RIGHT, MV_UP, MV_DOWN }
+ };
+
+ switch (element)
+ {
+ case EL_BUG_RIGHT:
+ case EL_BUG_UP:
+ case EL_BUG_LEFT:
+ case EL_BUG_DOWN:
+ Feld[x][y] = EL_BUG;
+ MovDir[x][y] = direction[0][element - EL_BUG_RIGHT];
+ break;
+
+ case EL_SPACESHIP_RIGHT:
+ case EL_SPACESHIP_UP:
+ case EL_SPACESHIP_LEFT:
+ case EL_SPACESHIP_DOWN:
+ Feld[x][y] = EL_SPACESHIP;
+ MovDir[x][y] = direction[0][element - EL_SPACESHIP_RIGHT];
+ break;
+
+ case EL_BD_BUTTERFLY_RIGHT:
+ case EL_BD_BUTTERFLY_UP:
+ case EL_BD_BUTTERFLY_LEFT:
+ case EL_BD_BUTTERFLY_DOWN:
+ Feld[x][y] = EL_BD_BUTTERFLY;
+ MovDir[x][y] = direction[0][element - EL_BD_BUTTERFLY_RIGHT];
+ break;
+
+ case EL_BD_FIREFLY_RIGHT:
+ case EL_BD_FIREFLY_UP:
+ case EL_BD_FIREFLY_LEFT:
+ case EL_BD_FIREFLY_DOWN:
+ Feld[x][y] = EL_BD_FIREFLY;
+ MovDir[x][y] = direction[0][element - EL_BD_FIREFLY_RIGHT];
+ break;
+
+ case EL_PACMAN_RIGHT:
+ case EL_PACMAN_UP:
+ case EL_PACMAN_LEFT:
+ case EL_PACMAN_DOWN:
+ Feld[x][y] = EL_PACMAN;
+ MovDir[x][y] = direction[0][element - EL_PACMAN_RIGHT];
+ break;
+
+ case EL_YAMYAM_LEFT:
+ case EL_YAMYAM_RIGHT:
+ case EL_YAMYAM_UP:
+ case EL_YAMYAM_DOWN:
+ Feld[x][y] = EL_YAMYAM;
+ MovDir[x][y] = direction[2][element - EL_YAMYAM_LEFT];
+ break;
+
+ case EL_SP_SNIKSNAK:
+ MovDir[x][y] = MV_UP;
+ break;
+
+ case EL_SP_ELECTRON:
+ MovDir[x][y] = MV_LEFT;
+ break;
+
+ case EL_MOLE_LEFT:
+ case EL_MOLE_RIGHT:
+ case EL_MOLE_UP:
+ case EL_MOLE_DOWN:
+ Feld[x][y] = EL_MOLE;
+ MovDir[x][y] = direction[2][element - EL_MOLE_LEFT];
+ break;
+
+ default:
+ if (IS_CUSTOM_ELEMENT(element))
+ {
+ 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_START_PREVIOUS)
+ {
+ if (MovDir[x][y] != MV_NONE)
+ return;
+
+ move_direction_initial = MV_START_AUTOMATIC;
+ }
+
+ if (move_direction_initial == MV_START_RANDOM)
+ MovDir[x][y] = 1 << RND(4);
+ else if (move_direction_initial & MV_ANY_DIRECTION)
+ MovDir[x][y] = move_direction_initial;
+ else if (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 (move_pattern == MV_HORIZONTAL)
+ MovDir[x][y] = (RND(2) ? MV_LEFT : MV_RIGHT);
+ else if (move_pattern == MV_VERTICAL)
+ MovDir[x][y] = (RND(2) ? MV_UP : MV_DOWN);
+ else if (move_pattern & MV_ANY_DIRECTION)
+ MovDir[x][y] = element_info[element].move_pattern;
+ else if (move_pattern == MV_ALONG_LEFT_SIDE ||
+ move_pattern == MV_ALONG_RIGHT_SIDE)
+ {
+ /* use random direction as default start direction */
+ if (game.engine_version >= VERSION_IDENT(3,1,0,0))
+ MovDir[x][y] = 1 << RND(4);
+
+ for (i = 0; i < NUM_DIRECTIONS; i++)
+ {
+ int x1 = x + xy[i][0];
+ int y1 = y + xy[i][1];
+
+ if (!IN_LEV_FIELD(x1, y1) || !IS_FREE(x1, y1))
+ {
+ if (move_pattern == MV_ALONG_RIGHT_SIDE)
+ MovDir[x][y] = direction[0][i];
+ else
+ MovDir[x][y] = direction[1][i];
+
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ MovDir[x][y] = 1 << RND(4);
+
+ if (element != EL_BUG &&
+ element != EL_SPACESHIP &&
+ element != EL_BD_BUTTERFLY &&
+ element != EL_BD_FIREFLY)
+ break;
+
+ for (i = 0; i < NUM_DIRECTIONS; i++)
+ {
+ int x1 = x + xy[i][0];
+ int y1 = y + xy[i][1];
+
+ if (!IN_LEV_FIELD(x1, y1) || !IS_FREE(x1, y1))
+ {
+ if (element == EL_BUG || element == EL_BD_BUTTERFLY)
+ {
+ MovDir[x][y] = direction[0][i];
+ break;
+ }
+ else if (element == EL_SPACESHIP || element == EL_BD_FIREFLY ||
+ element == EL_SP_SNIKSNAK || element == EL_SP_ELECTRON)
+ {
+ MovDir[x][y] = direction[1][i];
+ break;
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ GfxDir[x][y] = MovDir[x][y];
+}
+
+void InitAmoebaNr(int x, int y)
+{
+ int i;
+ int group_nr = AmoebeNachbarNr(x, y);
+
+ if (group_nr == 0)
+ {
+ for (i = 1; i < MAX_NUM_AMOEBA; i++)
+ {
+ if (AmoebaCnt[i] == 0)
+ {
+ group_nr = i;
+ break;
+ }
+ }
+ }
+
+ AmoebaNr[x][y] = group_nr;
+ AmoebaCnt[group_nr]++;
+ AmoebaCnt2[group_nr]++;
+}
+
+static void PlayerWins(struct PlayerInfo *player)
+{
+ player->LevelSolved = TRUE;
+ player->GameOver = TRUE;
+
+ player->score_final = (level.game_engine_type == GAME_ENGINE_TYPE_EM ?
+ level.native_em_level->lev->score : player->score);
+}
+
+void GameWon()
+{
+ static int time, time_final;
+ static int score, score_final;
+ static int game_over_delay_1 = 0;
+ static int game_over_delay_2 = 0;
+ int game_over_delay_value_1 = 50;
+ int game_over_delay_value_2 = 50;
+
+ if (!local_player->LevelSolved_GameWon)
+ {
+ int i;
+
+ /* do not start end game actions before the player stops moving (to exit) */
+ if (local_player->MovPos)
+ return;
+
+ local_player->LevelSolved_GameWon = TRUE;
+ local_player->LevelSolved_SaveTape = tape.recording;
+ local_player->LevelSolved_SaveScore = !tape.playing;
+
+ if (tape.auto_play) /* tape might already be stopped here */
+ tape.auto_play_level_solved = TRUE;
+
+#if 1
+ TapeStop();
+#endif
+
+ game_over_delay_1 = game_over_delay_value_1;
+ game_over_delay_2 = game_over_delay_value_2;
+
+ time = time_final = (level.time == 0 ? TimePlayed : TimeLeft);
+ score = score_final = local_player->score_final;
+
+ if (TimeLeft > 0)
+ {
+ time_final = 0;
+ score_final += TimeLeft * level.score[SC_TIME_BONUS];
+ }
+ else if (level.time == 0 && TimePlayed < 999)
+ {
+ time_final = 999;
+ score_final += (999 - TimePlayed) * level.score[SC_TIME_BONUS];
+ }
+
+ local_player->score_final = score_final;
+
+ if (level_editor_test_game)
+ {
+ time = time_final;
+ score = score_final;
+
+#if 1
+ game_control_value[GAME_CONTROL_TIME] = time;
+ game_control_value[GAME_CONTROL_SCORE] = score;
+
+ DisplayGameControlValues();
+#else
+ DrawGameValue_Time(time);
+ DrawGameValue_Score(score);
+#endif
+ }
+
+ if (level.game_engine_type == GAME_ENGINE_TYPE_RND)
+ {
+ if (ExitX >= 0 && ExitY >= 0) /* local player has left the level */
+ {
+ /* close exit door after last player */
+ if ((AllPlayersGone &&
+ (Feld[ExitX][ExitY] == EL_EXIT_OPEN ||
+ Feld[ExitX][ExitY] == EL_SP_EXIT_OPEN ||
+ Feld[ExitX][ExitY] == EL_STEEL_EXIT_OPEN)) ||
+ Feld[ExitX][ExitY] == EL_EM_EXIT_OPEN ||
+ Feld[ExitX][ExitY] == EL_EM_STEEL_EXIT_OPEN)
+ {
+ int element = Feld[ExitX][ExitY];
+
+#if 0
+ if (element == EL_EM_EXIT_OPEN ||
+ element == EL_EM_STEEL_EXIT_OPEN)
+ {
+ Bang(ExitX, ExitY);
+ }
+ else
+#endif
+ {
+ Feld[ExitX][ExitY] =
+ (element == EL_EXIT_OPEN ? EL_EXIT_CLOSING :
+ element == EL_EM_EXIT_OPEN ? EL_EM_EXIT_CLOSING :
+ element == EL_SP_EXIT_OPEN ? EL_SP_EXIT_CLOSING:
+ element == EL_STEEL_EXIT_OPEN ? EL_STEEL_EXIT_CLOSING:
+ EL_EM_STEEL_EXIT_CLOSING);
+
+ PlayLevelSoundElementAction(ExitX, ExitY, element, ACTION_CLOSING);
+ }
+ }
+
+ /* player disappears */
+ DrawLevelField(ExitX, ExitY);
+ }
+
+ for (i = 0; i < MAX_PLAYERS; i++)
+ {
+ struct PlayerInfo *player = &stored_player[i];
+
+ if (player->present)
+ {
+ RemovePlayer(player);
+
+ /* player disappears */
+ DrawLevelField(player->jx, player->jy);
+ }
+ }
+ }
+
+ PlaySound(SND_GAME_WINNING);
+ }
+
+ if (game_over_delay_1 > 0)
+ {
+ game_over_delay_1--;
+
+ return;
+ }
+
+ if (time != time_final)
+ {
+ int time_to_go = ABS(time_final - time);
+ int time_count_dir = (time < time_final ? +1 : -1);
+ int time_count_steps = (time_to_go > 100 && time_to_go % 10 == 0 ? 10 : 1);
+
+ time += time_count_steps * time_count_dir;
+ score += time_count_steps * level.score[SC_TIME_BONUS];
+
+#if 1
+ game_control_value[GAME_CONTROL_TIME] = time;
+ game_control_value[GAME_CONTROL_SCORE] = score;
+
+ DisplayGameControlValues();
+#else
+ DrawGameValue_Time(time);
+ DrawGameValue_Score(score);
+#endif
+
+ if (time == time_final)
+ StopSound(SND_GAME_LEVELTIME_BONUS);
+ else if (setup.sound_loops)
+ PlaySoundLoop(SND_GAME_LEVELTIME_BONUS);
+ else
+ PlaySound(SND_GAME_LEVELTIME_BONUS);
+
+ return;
+ }
+
+ local_player->LevelSolved_PanelOff = TRUE;
+
+ if (game_over_delay_2 > 0)
+ {
+ game_over_delay_2--;
+
+ return;
+ }
+
+#if 1
+ GameEnd();
+#endif
+}
+
+void GameEnd()
+{
+ int hi_pos;
+ boolean raise_level = FALSE;
+
+ local_player->LevelSolved_GameEnd = TRUE;
+
+ CloseDoor(DOOR_CLOSE_1);
+
+ if (local_player->LevelSolved_SaveTape)
+ {
+#if 0
+ TapeStop();
+#endif
+
+#if 1
+ SaveTapeChecked(tape.level_nr); /* ask to save tape */
+#else
+ SaveTape(tape.level_nr); /* ask to save tape */
+#endif
+ }
+
+ if (level_editor_test_game)
+ {
+ game_status = GAME_MODE_MAIN;
+
+#if 1
+ DrawAndFadeInMainMenu(REDRAW_FIELD);
+#else
+ DrawMainMenu();
+#endif
+
+ return;
+ }
+
+ if (!local_player->LevelSolved_SaveScore)
+ {
+#if 1
+ FadeOut(REDRAW_FIELD);
+#endif
+
+ game_status = GAME_MODE_MAIN;
+
+ DrawAndFadeInMainMenu(REDRAW_FIELD);
+
+ return;
+ }
+
+ if (level_nr == leveldir_current->handicap_level)
+ {
+ leveldir_current->handicap_level++;
+ SaveLevelSetup_SeriesInfo();
+ }
+
+ if (level_nr < leveldir_current->last_level)
+ raise_level = TRUE; /* advance to next level */
+
+ if ((hi_pos = NewHiScore()) >= 0)
+ {
+ game_status = GAME_MODE_SCORES;
+
+ DrawHallOfFame(hi_pos);
+
+ if (raise_level)
+ {
+ level_nr++;
+ TapeErase();
+ }
+ }
+ else
+ {
+#if 1
+ FadeOut(REDRAW_FIELD);
+#endif
+
+ game_status = GAME_MODE_MAIN;
+
+ if (raise_level)
+ {
+ level_nr++;
+ TapeErase();
+ }
+
+ DrawAndFadeInMainMenu(REDRAW_FIELD);
+ }
+}
+
+int NewHiScore()
+{
+ int k, l;
+ int position = -1;
+
+ LoadScore(level_nr);
+
+ if (strEqual(setup.player_name, EMPTY_PLAYER_NAME) ||
+ local_player->score_final < highscore[MAX_SCORE_ENTRIES - 1].Score)
+ return -1;
+
+ for (k = 0; k < MAX_SCORE_ENTRIES; k++)
+ {
+ if (local_player->score_final > highscore[k].Score)
+ {
+ /* player has made it to the hall of fame */
+
+ if (k < MAX_SCORE_ENTRIES - 1)
+ {
+ int m = MAX_SCORE_ENTRIES - 1;
+
+#ifdef ONE_PER_NAME
+ for (l = k; l < MAX_SCORE_ENTRIES; l++)
+ if (strEqual(setup.player_name, highscore[l].Name))
+ m = l;
+ if (m == k) /* player's new highscore overwrites his old one */
+ goto put_into_list;
+#endif
+
+ for (l = m; l > k; l--)
+ {
+ strcpy(highscore[l].Name, highscore[l - 1].Name);
+ highscore[l].Score = highscore[l - 1].Score;
+ }
+ }
+
+#ifdef ONE_PER_NAME
+ put_into_list:
+#endif
+ strncpy(highscore[k].Name, setup.player_name, MAX_PLAYER_NAME_LEN);
+ highscore[k].Name[MAX_PLAYER_NAME_LEN] = '\0';
+ highscore[k].Score = local_player->score_final;
+ position = k;
+ break;
+ }
+
+#ifdef ONE_PER_NAME
+ else if (!strncmp(setup.player_name, highscore[k].Name,
+ MAX_PLAYER_NAME_LEN))
+ break; /* player already there with a higher score */
+#endif
+
+ }
+
+ if (position >= 0)
+ SaveScore(level_nr);
+
+ return position;
+}
+
+inline static int getElementMoveStepsizeExt(int x, int y, int direction)
+{
+ int element = Feld[x][y];
+ int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
+ int dy = (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0);
+ int horiz_move = (dx != 0);
+ int sign = (horiz_move ? dx : dy);
+ int step = sign * element_info[element].move_stepsize;
+
+ /* special values for move stepsize for spring and things on conveyor belt */
+ if (horiz_move)
+ {
+ if (CAN_FALL(element) &&
+ y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1]))
+ step = sign * MOVE_STEPSIZE_NORMAL / 2;
+ else if (element == EL_SPRING)
+ step = sign * MOVE_STEPSIZE_NORMAL * 2;
+ }
+
+ return step;
+}
+
+inline static int getElementMoveStepsize(int x, int y)
+{
+ return getElementMoveStepsizeExt(x, y, MovDir[x][y]);
+}
+
+void InitPlayerGfxAnimation(struct PlayerInfo *player, int action, int dir)
+{
+ if (player->GfxAction != action || player->GfxDir != dir)
+ {
+#if 0
+ printf("Player frame reset! (%d => %d, %d => %d)\n",
+ player->GfxAction, action, player->GfxDir, dir);
+#endif
+
+ player->GfxAction = action;
+ player->GfxDir = dir;
+ player->Frame = 0;
+ player->StepFrame = 0;
+ }
+}
+
+#if USE_GFX_RESET_GFX_ANIMATION
+static void ResetGfxFrame(int x, int y, boolean redraw)
+{
+ int element = Feld[x][y];
+ int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
+ int last_gfx_frame = GfxFrame[x][y];
+
+ if (graphic_info[graphic].anim_global_sync)
+ GfxFrame[x][y] = FrameCounter;
+ else if (ANIM_MODE(graphic) == ANIM_CE_VALUE)
+ GfxFrame[x][y] = CustomValue[x][y];
+ else if (ANIM_MODE(graphic) == ANIM_CE_SCORE)
+ GfxFrame[x][y] = element_info[element].collect_score;
+ else if (ANIM_MODE(graphic) == ANIM_CE_DELAY)
+ GfxFrame[x][y] = ChangeDelay[x][y];
+
+ if (redraw && GfxFrame[x][y] != last_gfx_frame)
+ DrawLevelGraphicAnimation(x, y, graphic);
+}
+#endif
+
+static void ResetGfxAnimation(int x, int y)
+{
+ GfxAction[x][y] = ACTION_DEFAULT;
+ GfxDir[x][y] = MovDir[x][y];
+ GfxFrame[x][y] = 0;
+
+#if USE_GFX_RESET_GFX_ANIMATION
+ ResetGfxFrame(x, y, FALSE);
+#endif
+}
+
+static void ResetRandomAnimationValue(int x, int y)
+{
+ GfxRandom[x][y] = INIT_GFX_RANDOM();
+}
+
+void InitMovingField(int x, int y, int direction)
+{
+ int element = Feld[x][y];
+ int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
+ int dy = (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0);
+ int newx = x + dx;
+ int newy = y + dy;
+ boolean is_moving_before, is_moving_after;
+#if 0
+ boolean continues_moving = (WasJustMoving[x][y] && direction == MovDir[x][y]);
+#endif
+
+ /* check if element was/is moving or being moved before/after mode change */
+#if 1
+#if 1
+ is_moving_before = (WasJustMoving[x][y] != 0);
+#else
+ /* (!!! this does not work -- WasJustMoving is NOT a boolean value !!!) */
+ is_moving_before = WasJustMoving[x][y];
+#endif
+#else
+ is_moving_before = (getElementMoveStepsizeExt(x, y, MovDir[x][y]) != 0);
+#endif
+ is_moving_after = (getElementMoveStepsizeExt(x, y, direction) != 0);
+
+ /* reset animation only for moving elements which change direction of moving
+ or which just started or stopped moving
+ (else CEs with property "can move" / "not moving" are reset each frame) */
+#if USE_GFX_RESET_ONLY_WHEN_MOVING
+#if 1
+ if (is_moving_before != is_moving_after ||
+ direction != MovDir[x][y])
+ ResetGfxAnimation(x, y);
+#else
+ if ((is_moving_before || is_moving_after) && !continues_moving)
+ ResetGfxAnimation(x, y);
+#endif
+#else
+ if (!continues_moving)
+ ResetGfxAnimation(x, y);
+#endif
+
+ MovDir[x][y] = direction;
+ GfxDir[x][y] = direction;
+
+#if USE_GFX_RESET_ONLY_WHEN_MOVING
+ GfxAction[x][y] = (!is_moving_after ? ACTION_WAITING :
+ direction == MV_DOWN && CAN_FALL(element) ?
+ ACTION_FALLING : ACTION_MOVING);
+#else
+ GfxAction[x][y] = (direction == MV_DOWN && CAN_FALL(element) ?
+ ACTION_FALLING : ACTION_MOVING);
+#endif
+
+ /* this is needed for CEs with property "can move" / "not moving" */
+
+ if (is_moving_after)
+ {
+ if (Feld[newx][newy] == EL_EMPTY)
+ Feld[newx][newy] = EL_BLOCKED;
+
+ MovDir[newx][newy] = MovDir[x][y];
+
+#if USE_NEW_CUSTOM_VALUE
+ CustomValue[newx][newy] = CustomValue[x][y];
+#endif
+
+ GfxFrame[newx][newy] = GfxFrame[x][y];
+ GfxRandom[newx][newy] = GfxRandom[x][y];
+ GfxAction[newx][newy] = GfxAction[x][y];
+ GfxDir[newx][newy] = GfxDir[x][y];
+ }
+}
+
+void Moving2Blocked(int x, int y, int *goes_to_x, int *goes_to_y)
+{
+ int direction = MovDir[x][y];
+ int newx = x + (direction & MV_LEFT ? -1 : direction & MV_RIGHT ? +1 : 0);
+ int newy = y + (direction & MV_UP ? -1 : direction & MV_DOWN ? +1 : 0);
+
+ *goes_to_x = newx;
+ *goes_to_y = newy;
+}
+
+void Blocked2Moving(int x, int y, int *comes_from_x, int *comes_from_y)
+{
+ int oldx = x, oldy = y;
+ int direction = MovDir[x][y];
+
+ if (direction == MV_LEFT)
+ oldx++;
+ else if (direction == MV_RIGHT)
+ oldx--;
+ else if (direction == MV_UP)
+ oldy++;
+ else if (direction == MV_DOWN)
+ oldy--;
+
+ *comes_from_x = oldx;
+ *comes_from_y = oldy;
+}
+
+int MovingOrBlocked2Element(int x, int y)
+{
+ int element = Feld[x][y];
+
+ if (element == EL_BLOCKED)
+ {
+ int oldx, oldy;
+
+ Blocked2Moving(x, y, &oldx, &oldy);
+ return Feld[oldx][oldy];
+ }
+ else
+ return element;
+}
+
+static int MovingOrBlocked2ElementIfNotLeaving(int x, int y)
+{
+ /* like MovingOrBlocked2Element(), but if element is moving
+ and (x,y) is the field the moving element is just leaving,
+ return EL_BLOCKED instead of the element value */
+ int element = Feld[x][y];
+
+ if (IS_MOVING(x, y))
+ {
+ if (element == EL_BLOCKED)
+ {
+ int oldx, oldy;
+
+ Blocked2Moving(x, y, &oldx, &oldy);
+ return Feld[oldx][oldy];
+ }
+ else
+ return EL_BLOCKED;
+ }
+ else
+ return element;
+}
+
+static void RemoveField(int x, int y)
+{
+ Feld[x][y] = EL_EMPTY;
+
+ MovPos[x][y] = 0;
+ MovDir[x][y] = 0;
+ MovDelay[x][y] = 0;
+
+#if USE_NEW_CUSTOM_VALUE
+ CustomValue[x][y] = 0;
+#endif
+
+ AmoebaNr[x][y] = 0;
+ ChangeDelay[x][y] = 0;
+ ChangePage[x][y] = -1;
+ Pushed[x][y] = FALSE;
+
+#if 0
+ ExplodeField[x][y] = EX_TYPE_NONE;
+#endif
+
+ GfxElement[x][y] = EL_UNDEFINED;
+ GfxAction[x][y] = ACTION_DEFAULT;
+ GfxDir[x][y] = MV_NONE;
+}
+
+void RemoveMovingField(int x, int y)
+{
+ int oldx = x, oldy = y, newx = x, newy = y;
+ int element = Feld[x][y];
+ int next_element = EL_UNDEFINED;
+
+ if (element != EL_BLOCKED && !IS_MOVING(x, y))
+ return;
+
+ if (IS_MOVING(x, y))
+ {
+ Moving2Blocked(x, y, &newx, &newy);
+
+ if (Feld[newx][newy] != EL_BLOCKED)
+ {
+ /* element is moving, but target field is not free (blocked), but
+ already occupied by something different (example: acid pool);
+ in this case, only remove the moving field, but not the target */
+
+ RemoveField(oldx, oldy);
+
+ Store[oldx][oldy] = Store2[oldx][oldy] = 0;
+
+ DrawLevelField(oldx, oldy);
+
+ return;
+ }
+ }
+ else if (element == EL_BLOCKED)
+ {
+ Blocked2Moving(x, y, &oldx, &oldy);
+ if (!IS_MOVING(oldx, oldy))
+ return;
+ }
+
+ if (element == EL_BLOCKED &&
+ (Feld[oldx][oldy] == EL_QUICKSAND_EMPTYING ||
+ Feld[oldx][oldy] == EL_QUICKSAND_FAST_EMPTYING ||
+ Feld[oldx][oldy] == EL_MAGIC_WALL_EMPTYING ||
+ Feld[oldx][oldy] == EL_BD_MAGIC_WALL_EMPTYING ||
+ Feld[oldx][oldy] == EL_DC_MAGIC_WALL_EMPTYING ||
+ Feld[oldx][oldy] == EL_AMOEBA_DROPPING))
+ next_element = get_next_element(Feld[oldx][oldy]);
+
+ RemoveField(oldx, oldy);
+ RemoveField(newx, newy);
+
+ Store[oldx][oldy] = Store2[oldx][oldy] = 0;
+
+ if (next_element != EL_UNDEFINED)
+ Feld[oldx][oldy] = next_element;