-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;
-
-#if 1
- PlaySoundLevelElementAction(jx, jy, player->element_nr, ACTION_DYING);
-#else
- PlaySoundLevel(jx, jy, SND_CLASS_PLAYER_DYING);
-#endif
- 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;
-}
-
-/*
- checkDiagonalPushing()
- -----------------------------------------------------------------------------
- check if diagonal input device direction results in pushing of object
- (by checking if the alternative direction is walkable, diggable, ...)
-*/
-
-static boolean checkDiagonalPushing(struct PlayerInfo *player,
- int x, int y, int real_dx, int real_dy)
-{
- int jx, jy, dx, dy, xx, yy;
-
- if (real_dx == 0 || real_dy == 0) /* no diagonal direction => push */
- return TRUE;
-
- /* diagonal direction: check alternative direction */
- jx = player->jx;
- jy = player->jy;
- dx = x - jx;
- dy = y - jy;
- xx = jx + (dx == 0 ? real_dx : 0);
- yy = jy + (dy == 0 ? real_dy : 0);
-
- return (!IN_LEV_FIELD(xx, yy) || IS_SOLID_FOR_PUSHING(Feld[xx][yy]));
-}
-
-/*
- 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) /* last pushing move finished */
- player->Pushing = FALSE;
-
- if (mode == DF_NO_PUSH) /* player just stopped pushing */
- {
- player->Switching = FALSE;
- player->push_delay = 0;
-
- return MF_NO_ACTION;
- }
-
- if (IS_MOVING(x, y) || IS_PLAYER(x, y))
- {
-#if 0
- if (FrameCounter == 437)
- printf("::: ---> IS_MOVING %d\n", MovDir[x][y]);
-#endif
-
- return MF_NO_ACTION;
- }
-
-#if 0
- if (IS_TUBE(Feld[jx][jy]) || IS_TUBE(Back[jx][jy]))
-#else
- if (IS_TUBE(Feld[jx][jy]) ||
- (IS_TUBE(Back[jx][jy]) && game.engine_version >= VERSION_IDENT(2,2,0)))
-#endif
- {
- int i = 0;
- int tube_element = (IS_TUBE(Feld[jx][jy]) ? Feld[jx][jy] : Back[jx][jy]);
- 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] != tube_element)
- {
- 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];
-
-#if 1
- if (mode == DF_SNAP && !IS_SNAPPABLE(element) &&
- game.engine_version >= VERSION_IDENT(2,2,0))
- return MF_NO_ACTION;
-#endif
-
- switch (element)
- {
-#if 0
- case EL_EMPTY:
- PlaySoundLevelElementAction(x, y, player->element_nr, ACTION_MOVING);
- break;
-#endif
-
-#if 0
- 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 (mode != DF_SNAP && element != EL_EMPTY)
- {
- GfxElement[x][y] = (CAN_BE_CRUMBLED(element) ? EL_SAND : element);
- player->is_digging = TRUE;
- }
-
- PlaySoundLevelElementAction(x, y, element, ACTION_DIGGING);
- break;
-#endif
-
- 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 (mode != DF_SNAP)
- {
- GfxElement[x][y] = element;
- player->is_collecting = TRUE;
- }
-
- 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);
- CheckTriggeredElementChange(element, CE_OTHER_COLLECTING);
- break;
-
- case EL_SPEED_PILL:
- RemoveField(x, y);
- player->move_delay_value = MOVE_DELAY_HIGH_SPEED;
-#if 1
- PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING);
-#else
- PlaySoundLevel(x, y, SND_SPEED_PILL_COLLECTING);
-#endif
- CheckTriggeredElementChange(element, CE_OTHER_COLLECTING);
- break;
-
-#if 0
- case EL_ENVELOPE:
- Feld[x][y] = EL_EMPTY;
-#if 1
- PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING);
-#else
- PlaySoundLevel(x, y, SND_ENVELOPE_COLLECTING);
-#endif
- CheckTriggeredElementChange(element, CE_OTHER_COLLECTING);
- break;
-#endif
-
- case EL_EXTRA_TIME:
- RemoveField(x, y);
- if (level.time > 0)
- {
- TimeLeft += 10;
- DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_TEXT_2);
- }
-#if 1
- PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING);
-#else
- PlaySoundStereo(SND_EXTRA_TIME_COLLECTING, SOUND_MIDDLE);
-#endif
- CheckTriggeredElementChange(element, CE_OTHER_COLLECTING);
- break;
-
- case EL_SHIELD_NORMAL:
- RemoveField(x, y);
- player->shield_normal_time_left += 10;
-#if 1
- PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING);
-#else
- PlaySoundLevel(x, y, SND_SHIELD_NORMAL_COLLECTING);
-#endif
- CheckTriggeredElementChange(element, CE_OTHER_COLLECTING);
- break;
-
- case EL_SHIELD_DEADLY:
- RemoveField(x, y);
- player->shield_normal_time_left += 10;
- player->shield_deadly_time_left += 10;
-#if 1
- PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING);
-#else
- PlaySoundLevel(x, y, SND_SHIELD_DEADLY_COLLECTING);
-#endif
- CheckTriggeredElementChange(element, CE_OTHER_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);
- CheckTriggeredElementChange(element, CE_OTHER_COLLECTING);
- break;
-
- case EL_DYNABOMB_INCREASE_NUMBER:
- RemoveField(x, y);
- player->dynabomb_count++;
- player->dynabombs_left++;
- RaiseScoreElement(EL_DYNAMITE);
-#if 1
- PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING);
-#else
- PlaySoundLevel(x, y, SND_DYNABOMB_INCREASE_NUMBER_COLLECTING);
-#endif
- CheckTriggeredElementChange(element, CE_OTHER_COLLECTING);
- break;
-
- case EL_DYNABOMB_INCREASE_SIZE:
- RemoveField(x, y);
- player->dynabomb_size++;
- RaiseScoreElement(EL_DYNAMITE);
-#if 1
- PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING);
-#else
- PlaySoundLevel(x, y, SND_DYNABOMB_INCREASE_SIZE_COLLECTING);
-#endif
- CheckTriggeredElementChange(element, CE_OTHER_COLLECTING);
- break;
-
- case EL_DYNABOMB_INCREASE_POWER:
- RemoveField(x, y);
- player->dynabomb_xl = TRUE;
- RaiseScoreElement(EL_DYNAMITE);
-#if 1
- PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING);
-#else
- PlaySoundLevel(x, y, SND_DYNABOMB_INCREASE_POWER_COLLECTING);
-#endif
- CheckTriggeredElementChange(element, CE_OTHER_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);
-
- 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);
-#if 1
- PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING);
-#else
- PlaySoundLevel(x, y, SND_CLASS_KEY_COLLECTING);
-#endif
- CheckTriggeredElementChange(element, CE_OTHER_COLLECTING);
- 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);
-
- 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);
-#if 1
- PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING);
-#else
- PlaySoundLevel(x, y, SND_CLASS_KEY_COLLECTING);
-#endif
- CheckTriggeredElementChange(element, CE_OTHER_COLLECTING);
- 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;
-
- case EL_LIGHT_SWITCH:
- case EL_LIGHT_SWITCH_ACTIVE:
- if (!player->Switching)
- {
- player->Switching = TRUE;
- ToggleLightSwitch(x, y);
- PlaySoundLevel(x, y, element == EL_LIGHT_SWITCH ?
- SND_LIGHT_SWITCH_ACTIVATING :
- SND_LIGHT_SWITCH_DEACTIVATING);
- }
- return MF_ACTION;
- break;