return element;
}
+static void IncrementPlayerSokobanFieldsNeeded(struct PlayerInfo *player)
+{
+ if (level.sb_fields_needed)
+ player->sokoban_fields_still_needed++;
+}
+
+static void IncrementPlayerSokobanObjectsNeeded(struct PlayerInfo *player)
+{
+ if (level.sb_objects_needed)
+ player->sokoban_objects_still_needed++;
+}
+
+static void DecrementPlayerSokobanFieldsNeeded(struct PlayerInfo *player)
+{
+ if (player->sokoban_fields_still_needed > 0)
+ player->sokoban_fields_still_needed--;
+}
+
+static void DecrementPlayerSokobanObjectsNeeded(struct PlayerInfo *player)
+{
+ if (player->sokoban_objects_still_needed > 0)
+ player->sokoban_objects_still_needed--;
+}
+
static void InitPlayerField(int x, int y, int element, boolean init_game)
{
if (element == EL_SP_MURPHY)
break;
case EL_SOKOBAN_FIELD_EMPTY:
- local_player->sokobanfields_still_needed++;
+ IncrementPlayerSokobanFieldsNeeded(local_player);
+ break;
+
+ case EL_SOKOBAN_OBJECT:
+ IncrementPlayerSokobanObjectsNeeded(local_player);
break;
case EL_STONEBLOCK:
game_mm.kettles_still_needed > 0 ||
game_mm.lights_still_needed > 0 :
local_player->gems_still_needed > 0 ||
- local_player->sokobanfields_still_needed > 0 ||
+ local_player->sokoban_fields_still_needed > 0 ||
+ local_player->sokoban_objects_still_needed > 0 ||
local_player->lights_still_needed > 0);
int health = (local_player->LevelSolved ?
local_player->LevelSolved_CountingHealth :
local_player->friends_still_needed;
game_panel_controls[GAME_PANEL_SOKOBAN_OBJECTS].value =
- local_player->sokobanfields_still_needed;
+ local_player->sokoban_objects_still_needed;
game_panel_controls[GAME_PANEL_SOKOBAN_FIELDS].value =
- local_player->sokobanfields_still_needed;
+ local_player->sokoban_fields_still_needed;
game_panel_controls[GAME_PANEL_ROBOT_WHEEL].value =
(game.robot_wheel_active ? EL_ROBOT_WHEEL_ACTIVE : EL_ROBOT_WHEEL);
player->health_final = MAX_HEALTH;
player->gems_still_needed = level.gems_needed;
- player->sokobanfields_still_needed = 0;
+ player->sokoban_fields_still_needed = 0;
+ player->sokoban_objects_still_needed = 0;
player->lights_still_needed = 0;
player->players_still_needed = 0;
player->friends_still_needed = 0;
static void CheckExit(int x, int y)
{
if (local_player->gems_still_needed > 0 ||
- local_player->sokobanfields_still_needed > 0 ||
+ local_player->sokoban_fields_still_needed > 0 ||
+ local_player->sokoban_objects_still_needed > 0 ||
local_player->lights_still_needed > 0)
{
int element = Feld[x][y];
static void CheckExitEM(int x, int y)
{
if (local_player->gems_still_needed > 0 ||
- local_player->sokobanfields_still_needed > 0 ||
+ local_player->sokoban_fields_still_needed > 0 ||
+ local_player->sokoban_objects_still_needed > 0 ||
local_player->lights_still_needed > 0)
{
int element = Feld[x][y];
static void CheckExitSteel(int x, int y)
{
if (local_player->gems_still_needed > 0 ||
- local_player->sokobanfields_still_needed > 0 ||
+ local_player->sokoban_fields_still_needed > 0 ||
+ local_player->sokoban_objects_still_needed > 0 ||
local_player->lights_still_needed > 0)
{
int element = Feld[x][y];
static void CheckExitSteelEM(int x, int y)
{
if (local_player->gems_still_needed > 0 ||
- local_player->sokobanfields_still_needed > 0 ||
+ local_player->sokoban_fields_still_needed > 0 ||
+ local_player->sokoban_objects_still_needed > 0 ||
local_player->lights_still_needed > 0)
{
int element = Feld[x][y];
{
if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
{
- if (level.native_em_level->lev->home == 0) // all players at home
+ if (game_em.level_solved &&
+ !game_em.game_over) // game won
{
PlayerWins(local_player);
- AllPlayersGone = TRUE;
+ game_em.game_over = TRUE;
- level.native_em_level->lev->home = -1;
+ AllPlayersGone = TRUE;
}
- if (level.native_em_level->ply[0]->alive == 0 &&
- level.native_em_level->ply[1]->alive == 0 &&
- level.native_em_level->ply[2]->alive == 0 &&
- level.native_em_level->ply[3]->alive == 0) // all dead
+ if (game_em.game_over) // game lost
AllPlayersGone = TRUE;
}
else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
{
- if (game_sp.LevelSolved &&
- !game_sp.GameOver) // game won
+ if (game_sp.level_solved &&
+ !game_sp.game_over) // game won
{
PlayerWins(local_player);
- game_sp.GameOver = TRUE;
+ game_sp.game_over = TRUE;
AllPlayersGone = TRUE;
}
- if (game_sp.GameOver) // game lost
+ if (game_sp.game_over) // game lost
AllPlayersGone = TRUE;
}
else if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
if (IS_SB_ELEMENT(element))
{
+ boolean sokoban_task_solved = FALSE;
+
if (element == EL_SOKOBAN_FIELD_FULL)
{
Back[x][y] = EL_SOKOBAN_FIELD_EMPTY;
- local_player->sokobanfields_still_needed++;
+
+ IncrementPlayerSokobanFieldsNeeded(local_player);
+ IncrementPlayerSokobanObjectsNeeded(local_player);
}
if (Feld[nextx][nexty] == EL_SOKOBAN_FIELD_EMPTY)
{
Back[nextx][nexty] = EL_SOKOBAN_FIELD_EMPTY;
- local_player->sokobanfields_still_needed--;
+
+ DecrementPlayerSokobanFieldsNeeded(local_player);
+ DecrementPlayerSokobanObjectsNeeded(local_player);
+
+ // sokoban object was pushed from empty field to sokoban field
+ if (Back[x][y] == EL_EMPTY)
+ sokoban_task_solved = TRUE;
}
Feld[x][y] = EL_SOKOBAN_OBJECT;
PlayLevelSoundElementAction(nextx, nexty, EL_SOKOBAN_FIELD_EMPTY,
ACTION_FILLING);
- if (local_player->sokobanfields_still_needed == 0 &&
+ if (sokoban_task_solved &&
+ local_player->sokoban_fields_still_needed == 0 &&
+ local_player->sokoban_objects_still_needed == 0 &&
(game.emulation == EMU_SOKOBAN || level.auto_exit_sokoban))
{
local_player->players_still_needed = 0;
return FALSE;
if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
- return (level.native_em_level->lev->home > 0);
+ return (game_em.game_over && !game_em.level_solved);
else if (level.game_engine_type == GAME_ENGINE_TYPE_SP)
- return (game_sp.GameOver && !game_sp.LevelSolved);
+ return (game_sp.game_over && !game_sp.level_solved);
else if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
return (game_mm.game_over && !game_mm.level_solved);
else // GAME_ENGINE_TYPE_RND