+ if (kill_x != bad_x || kill_y != bad_y)
+ Bang(bad_x, bad_y);
+}
+
+void KillHero(struct PlayerInfo *player)
+{
+ int jx = player->jx, jy = player->jy;
+
+ if (!player->active)
+ return;
+
+ /* remove accessible field at the player's position */
+ Feld[jx][jy] = EL_EMPTY;
+
+ /* deactivate shield (else Bang()/Explode() would not work right) */
+ player->shield_normal_time_left = 0;
+ player->shield_deadly_time_left = 0;
+
+ Bang(jx, jy);
+ BuryHero(player);
+}
+
+static void KillHeroUnlessProtected(int x, int y)
+{
+ if (!PLAYER_PROTECTED(x, y))
+ KillHero(PLAYERINFO(x, y));
+}
+
+void BuryHero(struct PlayerInfo *player)
+{
+ int jx = player->jx, jy = player->jy;
+
+ if (!player->active)
+ return;
+
+ PlaySoundLevel(jx, jy, SND_CLASS_PLAYER_DYING);
+ PlaySoundLevel(jx, jy, SND_GAME_LOSING);
+
+ player->GameOver = TRUE;
+ RemoveHero(player);
+}
+
+void RemoveHero(struct PlayerInfo *player)
+{
+ int jx = player->jx, jy = player->jy;
+ int i, found = FALSE;
+
+ player->present = FALSE;
+ player->active = FALSE;
+
+ if (!ExplodeField[jx][jy])
+ StorePlayer[jx][jy] = 0;
+
+ for (i=0; i<MAX_PLAYERS; i++)
+ if (stored_player[i].active)
+ found = TRUE;
+
+ if (!found)
+ AllPlayersGone = TRUE;
+
+ ExitX = ZX = jx;
+ ExitY = ZY = jy;
+}
+
+#if 0
+/*
+ checkDiagonalPushing()
+ -----------------------------------------------------------------------------
+ check if diagonal input device direction results in pushing of object
+*/
+
+static boolean checkDiagonalPushing(int x, int y, int real_dx, int real_dy)
+{
+}
+#endif
+
+/*
+ DigField()
+ -----------------------------------------------------------------------------
+ x, y: field next to player (non-diagonal) to try to dig to
+ real_dx, real_dy: direction as read from input device (can be diagonal)
+*/
+
+int DigField(struct PlayerInfo *player,
+ int x, int y, int real_dx, int real_dy, int mode)
+{
+ int jx = player->jx, jy = player->jy;
+ int dx = x - jx, dy = y - jy;
+ int move_direction = (dx == -1 ? MV_LEFT :
+ dx == +1 ? MV_RIGHT :
+ dy == -1 ? MV_UP :
+ dy == +1 ? MV_DOWN : MV_NO_MOVING);
+ int element;
+
+ if (player->MovPos == 0)
+ {
+ player->is_digging = FALSE;
+ player->is_collecting = FALSE;
+ }
+
+ if (player->MovPos == 0)
+ player->Pushing = FALSE;
+
+ if (mode == DF_NO_PUSH)
+ {
+ player->Switching = FALSE;
+ player->push_delay = 0;
+ return MF_NO_ACTION;
+ }
+
+ if (IS_MOVING(x, y) || IS_PLAYER(x, y))
+ return MF_NO_ACTION;
+
+ if (IS_TUBE(Feld[jx][jy]))
+ {
+ int i = 0;
+ int tube_leave_directions[][2] =
+ {
+ { 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 },
+ { -1, MV_LEFT | MV_RIGHT | MV_UP | MV_DOWN }
+ };
+
+ while (tube_leave_directions[i][0] != Feld[jx][jy])
+ {
+ i++;
+ if (tube_leave_directions[i][0] == -1) /* should not happen */
+ break;
+ }
+
+ if (!(tube_leave_directions[i][1] & move_direction))
+ return MF_NO_ACTION; /* tube has no opening in this direction */
+ }
+
+ element = Feld[x][y];
+
+ switch (element)
+ {
+ case EL_EMPTY:
+ case EL_SAND:
+ case EL_INVISIBLE_SAND:
+ case EL_INVISIBLE_SAND_ACTIVE:
+ case EL_TRAP:
+ case EL_SP_BASE:
+ case EL_SP_BUGGY_BASE:
+ case EL_SP_BUGGY_BASE_ACTIVATING:
+ RemoveField(x, y);
+#if 1
+ if (mode != DF_SNAP && element != EL_EMPTY)
+ {
+ GfxElement[x][y] = (CAN_BE_CRUMBLED(element) ? EL_SAND : element);
+ player->is_digging = TRUE;
+ }
+#endif
+ PlaySoundLevelElementAction(x, y, element, ACTION_DIGGING);
+ break;
+
+ case EL_EMERALD:
+ case EL_BD_DIAMOND:
+ case EL_EMERALD_YELLOW:
+ case EL_EMERALD_RED:
+ case EL_EMERALD_PURPLE:
+ case EL_DIAMOND:
+ case EL_SP_INFOTRON:
+ case EL_PEARL:
+ case EL_CRYSTAL:
+ RemoveField(x, y);
+#if 1
+ if (mode != DF_SNAP)
+ {
+ GfxElement[x][y] = element;
+ player->is_collecting = TRUE;
+ }
+#endif
+ local_player->gems_still_needed -= (element == EL_DIAMOND ? 3 :
+ element == EL_PEARL ? 5 :
+ element == EL_CRYSTAL ? 8 : 1);
+ if (local_player->gems_still_needed < 0)
+ local_player->gems_still_needed = 0;
+ RaiseScoreElement(element);
+ DrawText(DX_EMERALDS, DY_EMERALDS,
+ int2str(local_player->gems_still_needed, 3), FONT_TEXT_2);
+ PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING);
+ break;
+
+ case EL_SPEED_PILL:
+ RemoveField(x, y);
+ player->move_delay_value = MOVE_DELAY_HIGH_SPEED;
+ PlaySoundLevel(x, y, SND_SPEED_PILL_COLLECTING);
+ break;
+
+ case EL_ENVELOPE:
+ Feld[x][y] = EL_EMPTY;
+ PlaySoundLevel(x, y, SND_ENVELOPE_COLLECTING);
+ break;
+
+ case EL_EXTRA_TIME:
+ RemoveField(x, y);
+ if (level.time > 0)
+ {
+ TimeLeft += 10;
+ DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_TEXT_2);
+ }
+ PlaySoundStereo(SND_EXTRA_TIME_COLLECTING, SOUND_MIDDLE);
+ break;
+
+ case EL_SHIELD_NORMAL:
+ RemoveField(x, y);
+ player->shield_normal_time_left += 10;
+ PlaySoundLevel(x, y, SND_SHIELD_NORMAL_COLLECTING);
+ break;
+
+ case EL_SHIELD_DEADLY:
+ RemoveField(x, y);
+ player->shield_normal_time_left += 10;
+ player->shield_deadly_time_left += 10;
+ PlaySoundLevel(x, y, SND_SHIELD_DEADLY_COLLECTING);
+ break;
+
+ case EL_DYNAMITE:
+ case EL_SP_DISK_RED:
+ RemoveField(x, y);
+ player->dynamite++;
+ player->use_disk_red_graphic = (element == EL_SP_DISK_RED);
+ RaiseScoreElement(EL_DYNAMITE);
+ DrawText(DX_DYNAMITE, DY_DYNAMITE, int2str(local_player->dynamite, 3),
+ FONT_TEXT_2);
+ PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING);
+ break;
+
+ case EL_DYNABOMB_INCREASE_NUMBER:
+ RemoveField(x, y);
+ player->dynabomb_count++;
+ player->dynabombs_left++;
+ RaiseScoreElement(EL_DYNAMITE);
+ PlaySoundLevel(x, y, SND_DYNABOMB_INCREASE_NUMBER_COLLECTING);
+ break;
+
+ case EL_DYNABOMB_INCREASE_SIZE:
+ RemoveField(x, y);
+ player->dynabomb_size++;
+ RaiseScoreElement(EL_DYNAMITE);
+ PlaySoundLevel(x, y, SND_DYNABOMB_INCREASE_SIZE_COLLECTING);
+ break;
+
+ case EL_DYNABOMB_INCREASE_POWER:
+ RemoveField(x, y);
+ player->dynabomb_xl = TRUE;
+ RaiseScoreElement(EL_DYNAMITE);
+ PlaySoundLevel(x, y, SND_DYNABOMB_INCREASE_POWER_COLLECTING);
+ break;
+
+ case EL_KEY_1:
+ case EL_KEY_2:
+ case EL_KEY_3:
+ case EL_KEY_4:
+ {
+ int key_nr = element - EL_KEY_1;
+ int graphic = el2edimg(element);
+ int element_old, element_new;
+ int num_changes;
+
+ RemoveField(x, y);
+ player->key[key_nr] = TRUE;
+ RaiseScoreElement(element);
+ DrawMiniGraphicExt(drawto, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS,
+ graphic);
+ DrawMiniGraphicExt(window, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS,
+ graphic);
+ PlaySoundLevel(x, y, SND_CLASS_KEY_COLLECTING);
+
+ element_old = EL_GATE_1_CLOSED + key_nr;
+ element_new = EL_GATE_1_OPEN + key_nr;
+ num_changes = ChangeElementOnPlayfield(element_old, element_new);
+ if (num_changes > 0)
+ PlaySoundLevelElementAction(x, y, element_old, ACTION_OPENING);
+
+ element_old = EL_GATE_1_GRAY_CLOSED + key_nr;
+ element_new = EL_GATE_1_GRAY_OPEN + key_nr;
+ num_changes = ChangeElementOnPlayfield(element_old, element_new);
+ if (num_changes > 0)
+ PlaySoundLevelElementAction(x, y, element_old, ACTION_OPENING);
+
+ if (game.engine_version < VERSION_IDENT(2,2,0))
+ {
+ element_old = EL_EM_GATE_1_CLOSED + key_nr;
+ element_new = EL_EM_GATE_1_OPEN + key_nr;
+ num_changes = ChangeElementOnPlayfield(element_old, element_new);
+ if (num_changes > 0)
+ PlaySoundLevelElementAction(x, y, element_old, ACTION_OPENING);
+
+ element_old = EL_EM_GATE_1_GRAY_CLOSED + key_nr;
+ element_new = EL_EM_GATE_1_GRAY_OPEN + key_nr;
+ num_changes = ChangeElementOnPlayfield(element_old, element_new);
+ if (num_changes > 0)
+ PlaySoundLevelElementAction(x, y, element_old, ACTION_OPENING);
+ }
+
+ break;
+ }
+
+ case EL_EM_KEY_1:
+ case EL_EM_KEY_2:
+ case EL_EM_KEY_3:
+ case EL_EM_KEY_4:
+ {
+ int key_nr = element - EL_EM_KEY_1;
+ int graphic = el2edimg(EL_KEY_1 + key_nr);
+ int element_old, element_new;
+ int num_changes;
+
+ RemoveField(x, y);
+ player->key[key_nr] = TRUE;
+ RaiseScoreElement(element);
+ DrawMiniGraphicExt(drawto, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS,
+ graphic);
+ DrawMiniGraphicExt(window, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS,
+ graphic);
+ PlaySoundLevel(x, y, SND_CLASS_KEY_COLLECTING);
+
+ element_old = EL_EM_GATE_1_CLOSED + key_nr;
+ element_new = EL_EM_GATE_1_OPEN + key_nr;
+ num_changes = ChangeElementOnPlayfield(element_old, element_new);
+ if (num_changes > 0)
+ PlaySoundLevelElementAction(x, y, element_old, ACTION_OPENING);
+
+ element_old = EL_EM_GATE_1_GRAY_CLOSED + key_nr;
+ element_new = EL_EM_GATE_1_GRAY_OPEN + key_nr;
+ num_changes = ChangeElementOnPlayfield(element_old, element_new);
+ if (num_changes > 0)
+ PlaySoundLevelElementAction(x, y, element_old, ACTION_OPENING);
+
+ if (game.engine_version < VERSION_IDENT(2,2,0))
+ {
+ element_old = EL_GATE_1_CLOSED + key_nr;
+ element_new = EL_GATE_1_OPEN + key_nr;
+ num_changes = ChangeElementOnPlayfield(element_old, element_new);
+ if (num_changes > 0)
+ PlaySoundLevelElementAction(x, y, element_old, ACTION_OPENING);
+
+ element_old = EL_GATE_1_GRAY_CLOSED + key_nr;
+ element_new = EL_GATE_1_GRAY_OPEN + key_nr;
+ num_changes = ChangeElementOnPlayfield(element_old, element_new);
+ if (num_changes > 0)
+ PlaySoundLevelElementAction(x, y, element_old, ACTION_OPENING);
+ }
+
+ break;
+ }
+
+ case EL_ROBOT_WHEEL:
+ Feld[x][y] = EL_ROBOT_WHEEL_ACTIVE;
+ ZX = x;
+ ZY = y;
+ DrawLevelField(x, y);
+ PlaySoundLevel(x, y, SND_ROBOT_WHEEL_ACTIVATING);
+ return MF_ACTION;
+ break;
+
+ case EL_SP_TERMINAL:
+ {
+ int xx, yy;
+
+ PlaySoundLevel(x, y, SND_SP_TERMINAL_ACTIVATING);
+
+ for (yy=0; yy<lev_fieldy; yy++)
+ {
+ for (xx=0; xx<lev_fieldx; xx++)
+ {
+ if (Feld[xx][yy] == EL_SP_DISK_YELLOW)
+ Bang(xx, yy);
+ else if (Feld[xx][yy] == EL_SP_TERMINAL)
+ Feld[xx][yy] = EL_SP_TERMINAL_ACTIVE;
+ }
+ }
+
+ return MF_ACTION;
+ }
+ break;
+
+ case EL_CONVEYOR_BELT_1_SWITCH_LEFT:
+ case EL_CONVEYOR_BELT_1_SWITCH_MIDDLE:
+ case EL_CONVEYOR_BELT_1_SWITCH_RIGHT:
+ case EL_CONVEYOR_BELT_2_SWITCH_LEFT:
+ case EL_CONVEYOR_BELT_2_SWITCH_MIDDLE:
+ case EL_CONVEYOR_BELT_2_SWITCH_RIGHT:
+ case EL_CONVEYOR_BELT_3_SWITCH_LEFT:
+ case EL_CONVEYOR_BELT_3_SWITCH_MIDDLE:
+ case EL_CONVEYOR_BELT_3_SWITCH_RIGHT:
+ case EL_CONVEYOR_BELT_4_SWITCH_LEFT:
+ case EL_CONVEYOR_BELT_4_SWITCH_MIDDLE:
+ case EL_CONVEYOR_BELT_4_SWITCH_RIGHT:
+ if (!player->Switching)
+ {
+ player->Switching = TRUE;
+ ToggleBeltSwitch(x, y);
+ PlaySoundLevel(x, y, SND_CLASS_CONVEYOR_BELT_SWITCH_ACTIVATING);
+ }
+ return MF_ACTION;
+ break;
+
+ case EL_SWITCHGATE_SWITCH_UP:
+ case EL_SWITCHGATE_SWITCH_DOWN:
+ if (!player->Switching)
+ {
+ player->Switching = TRUE;
+ ToggleSwitchgateSwitch(x, y);
+ PlaySoundLevel(x, y, SND_CLASS_SWITCHGATE_SWITCH_ACTIVATING);
+ }
+ return MF_ACTION;
+ break;