X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fgame.c;h=410fec92a79180a7c5b014b1c95e375750c3c171;hp=0d8c032e84028895eb27bfae62a633ce15c52251;hb=820c0cf7d64247d3f75f9cb10d214cbf988557fe;hpb=64e7c54dce6ea8c063f04198c64c5057d751c928 diff --git a/src/game.c b/src/game.c index 0d8c032e..410fec92 100644 --- a/src/game.c +++ b/src/game.c @@ -1683,6 +1683,30 @@ int GetElementFromGroupElement(int element) return element; } +static void IncrementPlayerSokobanFieldsNeeded(void) +{ + if (level.sb_fields_needed) + local_player->sokoban_fields_still_needed++; +} + +static void IncrementPlayerSokobanObjectsNeeded(void) +{ + if (level.sb_objects_needed) + local_player->sokoban_objects_still_needed++; +} + +static void DecrementPlayerSokobanFieldsNeeded(void) +{ + if (local_player->sokoban_fields_still_needed > 0) + local_player->sokoban_fields_still_needed--; +} + +static void DecrementPlayerSokobanObjectsNeeded(void) +{ + if (local_player->sokoban_objects_still_needed > 0) + local_player->sokoban_objects_still_needed--; +} + static void InitPlayerField(int x, int y, int element, boolean init_game) { if (element == EL_SP_MURPHY) @@ -1792,7 +1816,11 @@ static void InitField(int x, int y, boolean init_game) break; case EL_SOKOBAN_FIELD_EMPTY: - local_player->sokobanfields_still_needed++; + IncrementPlayerSokobanFieldsNeeded(); + break; + + case EL_SOKOBAN_OBJECT: + IncrementPlayerSokobanObjectsNeeded(); break; case EL_STONEBLOCK: @@ -2046,8 +2074,8 @@ static int get_next_dropped_element(struct PlayerInfo *player) static int get_inventory_element_from_pos(struct PlayerInfo *player, int pos) { - /* pos >= 0: get element from bottom of the stack; - pos < 0: get element from top of the stack */ + // pos >= 0: get element from bottom of the stack; + // pos < 0: get element from top of the stack if (pos < 0) { @@ -2179,8 +2207,8 @@ static void UpdatePlayfieldElementCount(void) static void UpdateGameControlValues(void) { int i, k; - int time = (local_player->LevelSolved ? - local_player->LevelSolved_CountingTime : + int time = (game.LevelSolved ? + game.LevelSolved_CountingTime : level.game_engine_type == GAME_ENGINE_TYPE_EM ? level.native_em_level->lev->time : level.game_engine_type == GAME_ENGINE_TYPE_SP ? @@ -2188,8 +2216,8 @@ static void UpdateGameControlValues(void) level.game_engine_type == GAME_ENGINE_TYPE_MM ? game_mm.energy_left : game.no_time_limit ? TimePlayed : TimeLeft); - int score = (local_player->LevelSolved ? - local_player->LevelSolved_CountingScore : + int score = (game.LevelSolved ? + game.LevelSolved_CountingScore : level.game_engine_type == GAME_ENGINE_TYPE_EM ? level.native_em_level->lev->score : level.game_engine_type == GAME_ENGINE_TYPE_SP ? @@ -2212,10 +2240,11 @@ static void UpdateGameControlValues(void) 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 : + int health = (game.LevelSolved ? + game.LevelSolved_CountingHealth : level.game_engine_type == GAME_ENGINE_TYPE_MM ? MM_HEALTH(game_mm.laser_overload_value) : local_player->health); @@ -2381,9 +2410,9 @@ static void UpdateGameControlValues(void) 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); @@ -2780,13 +2809,11 @@ void DrawGameDoorValues(void) } -/* - ============================================================================= - InitGameEngine() - ----------------------------------------------------------------------------- - initialize game engine due to level / tape version number - ============================================================================= -*/ +// ============================================================================ +// InitGameEngine() +// ---------------------------------------------------------------------------- +// initialize game engine due to level / tape version number +// ============================================================================ static void InitGameEngine(void) { @@ -3270,13 +3297,11 @@ static int get_num_special_action(int element, int action_first, } -/* - ============================================================================= - InitGame() - ----------------------------------------------------------------------------- - initialize and start new game - ============================================================================= -*/ +// ============================================================================ +// InitGame() +// ---------------------------------------------------------------------------- +// initialize and start new game +// ============================================================================ #if DEBUG_INIT_PLAYER static void DebugPrintPlayerStatus(char *message) @@ -3393,7 +3418,8 @@ void InitGame(void) 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; @@ -3520,18 +3546,8 @@ void InitGame(void) DigField(player, 0, 0, 0, 0, 0, 0, DF_NO_PUSH); SnapField(player, 0, 0); - player->LevelSolved = FALSE; player->GameOver = FALSE; - player->LevelSolved_GameWon = FALSE; - player->LevelSolved_GameEnd = FALSE; - player->LevelSolved_SaveTape = FALSE; - player->LevelSolved_SaveScore = FALSE; - - player->LevelSolved_CountingTime = 0; - player->LevelSolved_CountingScore = 0; - player->LevelSolved_CountingHealth = 0; - map_player_action[i] = i; } @@ -3558,6 +3574,17 @@ void InitGame(void) AllPlayersGone = FALSE; + game.LevelSolved = FALSE; + + game.LevelSolved_GameWon = FALSE; + game.LevelSolved_GameEnd = FALSE; + game.LevelSolved_SaveTape = FALSE; + game.LevelSolved_SaveScore = FALSE; + + game.LevelSolved_CountingTime = 0; + game.LevelSolved_CountingScore = 0; + game.LevelSolved_CountingHealth = 0; + game.panel.active = TRUE; game.no_time_limit = (level.time == 0); @@ -3724,8 +3751,8 @@ void InitGame(void) } else if (network.enabled) { - /* add team mode players connected over the network (needed for correct - assignment of player figures from level to locally playing players) */ + // add team mode players connected over the network (needed for correct + // assignment of player figures from level to locally playing players) for (i = 0; i < MAX_PLAYERS; i++) if (stored_player[i].connected_network) @@ -3733,8 +3760,8 @@ void InitGame(void) } else if (game.team_mode) { - /* try to guess locally connected team mode players (needed for correct - assignment of player figures from level to locally playing players) */ + // try to guess locally connected team mode players (needed for correct + // assignment of player figures from level to locally playing players) for (i = 0; i < MAX_PLAYERS; i++) if (setup.input[i].use_joystick || @@ -4006,8 +4033,8 @@ void InitGame(void) if (EVEN(SCR_FIELDY) && full_lev_fieldy > SCR_FIELDY) SBY_Upper--; - /* if local player not found, look for custom element that might create - the player (make some assumptions about the right custom element) */ + // if local player not found, look for custom element that might create + // the player (make some assumptions about the right custom element) if (!local_player->present) { int start_x = 0, start_y = 0; @@ -4430,28 +4457,28 @@ void InitAmoebaNr(int x, int y) AmoebaCnt2[group_nr]++; } -static void PlayerWins(struct PlayerInfo *player) +static void LevelSolved(void) { if (level.game_engine_type == GAME_ENGINE_TYPE_RND && local_player->players_still_needed > 0) return; - player->LevelSolved = TRUE; - player->GameOver = TRUE; + game.LevelSolved = TRUE; - player->score_final = (level.game_engine_type == GAME_ENGINE_TYPE_EM ? - level.native_em_level->lev->score : - level.game_engine_type == GAME_ENGINE_TYPE_MM ? - game_mm.score : - player->score); - player->health_final = (level.game_engine_type == GAME_ENGINE_TYPE_MM ? - MM_HEALTH(game_mm.laser_overload_value) : - player->health); + local_player->GameOver = TRUE; - player->LevelSolved_CountingTime = (game.no_time_limit ? TimePlayed : - TimeLeft); - player->LevelSolved_CountingScore = player->score_final; - player->LevelSolved_CountingHealth = player->health_final; + local_player->score_final = (level.game_engine_type == GAME_ENGINE_TYPE_EM ? + level.native_em_level->lev->score : + level.game_engine_type == GAME_ENGINE_TYPE_MM ? + game_mm.score : + local_player->score); + local_player->health_final = (level.game_engine_type == GAME_ENGINE_TYPE_MM ? + MM_HEALTH(game_mm.laser_overload_value) : + local_player->health); + + game.LevelSolved_CountingTime = (game.no_time_limit ? TimePlayed : TimeLeft); + game.LevelSolved_CountingScore = local_player->score_final; + game.LevelSolved_CountingHealth = local_player->health_final; } void GameWon(void) @@ -4467,7 +4494,7 @@ void GameWon(void) int game_over_delay_value_2 = 25; int game_over_delay_value_3 = 50; - if (!local_player->LevelSolved_GameWon) + if (!game.LevelSolved_GameWon) { int i; @@ -4475,9 +4502,9 @@ void GameWon(void) if (local_player->MovPos) return; - local_player->LevelSolved_GameWon = TRUE; - local_player->LevelSolved_SaveTape = tape.recording; - local_player->LevelSolved_SaveScore = !tape.playing; + game.LevelSolved_GameWon = TRUE; + game.LevelSolved_SaveTape = tape.recording; + game.LevelSolved_SaveScore = !tape.playing; if (!tape.playing) { @@ -4533,8 +4560,8 @@ void GameWon(void) time = time_final; score = score_final; - local_player->LevelSolved_CountingTime = time; - local_player->LevelSolved_CountingScore = score; + game.LevelSolved_CountingTime = time; + game.LevelSolved_CountingScore = score; game_panel_controls[GAME_PANEL_TIME].value = time; game_panel_controls[GAME_PANEL_SCORE].value = score; @@ -4605,8 +4632,8 @@ void GameWon(void) time += time_count_steps * time_count_dir; score += time_count_steps * level.score[SC_TIME_BONUS]; - local_player->LevelSolved_CountingTime = time; - local_player->LevelSolved_CountingScore = score; + game.LevelSolved_CountingTime = time; + game.LevelSolved_CountingScore = score; game_panel_controls[GAME_PANEL_TIME].value = time; game_panel_controls[GAME_PANEL_SCORE].value = score; @@ -4637,8 +4664,8 @@ void GameWon(void) health += health_count_dir; score += level.score[SC_TIME_BONUS]; - local_player->LevelSolved_CountingHealth = health; - local_player->LevelSolved_CountingScore = score; + game.LevelSolved_CountingHealth = health; + game.LevelSolved_CountingScore = score; game_panel_controls[GAME_PANEL_HEALTH].value = health; game_panel_controls[GAME_PANEL_SCORE].value = score; @@ -4673,9 +4700,9 @@ void GameEnd(void) int last_level_nr = levelset.level_nr; int hi_pos; - local_player->LevelSolved_GameEnd = TRUE; + game.LevelSolved_GameEnd = TRUE; - if (local_player->LevelSolved_SaveTape) + if (game.LevelSolved_SaveTape) { // make sure that request dialog to save tape does not open door again if (!global.use_envelope_request) @@ -4696,7 +4723,7 @@ void GameEnd(void) return; } - if (!local_player->LevelSolved_SaveScore) + if (!game.LevelSolved_SaveScore) { SetGameStatus(GAME_MODE_MAIN); @@ -4893,9 +4920,9 @@ static void InitMovingField(int x, int y, int direction) is_moving_before = (WasJustMoving[x][y] != 0); 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) */ + // 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 (is_moving_before != is_moving_after || direction != MovDir[x][y]) ResetGfxAnimation(x, y); @@ -4970,9 +4997,9 @@ static int MovingOrBlocked2Element(int x, int y) 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 */ + // 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)) @@ -5026,9 +5053,9 @@ static void RemoveMovingField(int x, int y) 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 */ + // 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); @@ -5493,8 +5520,8 @@ static void Explode(int ex, int ey, int phase, int mode) Store[x][y] = EL_EMPTY; } - /* !!! check this case -- currently needed for rnd_rado_negundo_v, - !!! levels 015 018 019 020 021 022 023 026 027 028 !!! */ + // !!! check this case -- currently needed for rnd_rado_negundo_v, + // !!! levels 015 018 019 020 021 022 023 026 027 028 !!! else if (ELEM_IS_PLAYER(center_element)) Store[x][y] = EL_EMPTY; else if (center_element == EL_YAMYAM) @@ -5502,9 +5529,9 @@ static void Explode(int ex, int ey, int phase, int mode) else if (element_info[center_element].content.e[xx][yy] != EL_EMPTY) Store[x][y] = element_info[center_element].content.e[xx][yy]; #if 1 - /* needed because EL_BD_BUTTERFLY is not defined as "CAN_EXPLODE" - (killing EL_BD_BUTTERFLY with dynamite would result in BD diamond - otherwise) -- FIX THIS !!! */ + // needed because EL_BD_BUTTERFLY is not defined as "CAN_EXPLODE" + // (killing EL_BD_BUTTERFLY with dynamite would result in BD diamond + // otherwise) -- FIX THIS !!! else if (!CAN_EXPLODE(element) && element != EL_BD_BUTTERFLY) Store[x][y] = element_info[element].content.e[1][1]; #else @@ -5580,9 +5607,9 @@ static void Explode(int ex, int ey, int phase, int mode) border_explosion = TRUE; } - /* if an element just explodes due to another explosion (chain-reaction), - do not immediately end the new explosion when it was the last frame of - the explosion (as it would be done in the following "if"-statement!) */ + // if an element just explodes due to another explosion (chain-reaction), + // do not immediately end the new explosion when it was the last frame of + // the explosion (as it would be done in the following "if"-statement!) if (border_explosion && phase == last_phase) return; } @@ -7781,8 +7808,8 @@ static void StartMoving(int x, int y) if (!MovDelay[x][y]) // start new movement phase { - /* all objects that can change their move direction after each step - (YAMYAM, DARK_YAMYAM and PACMAN go straight until they hit a wall */ + // all objects that can change their move direction after each step + // (YAMYAM, DARK_YAMYAM and PACMAN go straight until they hit a wall if (element != EL_YAMYAM && element != EL_DARK_YAMYAM && @@ -7925,7 +7952,7 @@ static void StartMoving(int x, int y) local_player->friends_still_needed--; if (!local_player->friends_still_needed && !local_player->GameOver && AllPlayersGone) - PlayerWins(local_player); + LevelSolved(); return; } @@ -8729,8 +8756,8 @@ static void AmoebaDisappearing(int x, int y) Feld[x][y] = EL_EMPTY; TEST_DrawLevelField(x, y); - /* don't let mole enter this field in this cycle; - (give priority to objects falling to this field from above) */ + // don't let mole enter this field in this cycle; + // (give priority to objects falling to this field from above) Stop[x][y] = TRUE; } } @@ -9057,7 +9084,8 @@ static void ActivateMagicBall(int bx, int by) 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]; @@ -9080,7 +9108,8 @@ static void CheckExit(int x, int 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]; @@ -9103,7 +9132,8 @@ static void CheckExitEM(int x, int 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]; @@ -9126,7 +9156,8 @@ static void CheckExitSteel(int x, int 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]; @@ -9818,7 +9849,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) ExitPlayer(&stored_player[i]); if (AllPlayersGone) - PlayerWins(local_player); + LevelSolved(); break; } @@ -10217,8 +10248,8 @@ static void CreateFieldExt(int x, int y, int element, boolean is_change) TEST_DrawLevelFieldCrumbledNeighbours(x, y); } - /* check if element under the player changes from accessible to unaccessible - (needed for special case of dropping element which then changes) */ + // check if element under the player changes from accessible to unaccessible + // (needed for special case of dropping element which then changes) // (must be checked after creating new element for walkable group elements) if (IS_PLAYER(x, y) && !player_explosion_protected && IS_ACCESSIBLE(old_element) && !IS_ACCESSIBLE(new_element)) @@ -10253,8 +10284,8 @@ static void CreateElementFromChange(int x, int y, int element) { int old_element = Feld[x][y]; - /* prevent changed element from moving in same engine frame - unless both old and new element can either fall or move */ + // prevent changed element from moving in same engine frame + // unless both old and new element can either fall or move if ((!CAN_FALL(old_element) || !CAN_FALL(element)) && (!CAN_MOVE(old_element) || !CAN_MOVE(element))) Stop[x][y] = TRUE; @@ -10507,8 +10538,8 @@ static void HandleElementChange(int x, int y, int page) This can also be seen from the debug output for this test element.) */ - /* when a custom element is about to change (for example by change delay), - do not reset graphic animation when the custom element is moving */ + // when a custom element is about to change (for example by change delay), + // do not reset graphic animation when the custom element is moving if (game.graphics_engine_version < 4 && !IS_MOVING(x, y)) { @@ -10629,9 +10660,9 @@ static boolean CheckTriggeredElementChangeExt(int trigger_x, int trigger_y, { if (change->can_change && !change_done) { - /* if element already changed in this frame, not only prevent - another element change (checked in ChangeElement()), but - also prevent additional element actions for this element */ + // if element already changed in this frame, not only prevent + // another element change (checked in ChangeElement()), but + // also prevent additional element actions for this element if (ChangeCount[x][y] >= game.max_num_changes_per_frame && !level.use_action_after_change_bug) @@ -10644,9 +10675,9 @@ static boolean CheckTriggeredElementChangeExt(int trigger_x, int trigger_y, } else if (change->has_action) { - /* if element already changed in this frame, not only prevent - another element change (checked in ChangeElement()), but - also prevent additional element actions for this element */ + // if element already changed in this frame, not only prevent + // another element change (checked in ChangeElement()), but + // also prevent additional element actions for this element if (ChangeCount[x][y] >= game.max_num_changes_per_frame && !level.use_action_after_change_bug) @@ -11087,34 +11118,32 @@ static void CheckLevelSolved(void) { 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); + LevelSolved(); - 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); + LevelSolved(); - 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) @@ -11122,7 +11151,7 @@ static void CheckLevelSolved(void) if (game_mm.level_solved && !game_mm.game_over) // game won { - PlayerWins(local_player); + LevelSolved(); game_mm.game_over = TRUE; @@ -11156,7 +11185,7 @@ static void CheckLevelTime(void) } } - if (!local_player->LevelSolved && !level.use_step_counter) + if (!game.LevelSolved && !level.use_step_counter) { TimePlayed++; @@ -11303,7 +11332,7 @@ static void GameActionsExt(void) CheckLevelSolved(); - if (local_player->LevelSolved && !local_player->LevelSolved_GameEnd) + if (game.LevelSolved && !game.LevelSolved_GameEnd) GameWon(); if (AllPlayersGone && !TAPE_IS_STOPPED(tape)) @@ -12649,7 +12678,7 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) if ((local_player->friends_still_needed == 0 || IS_SP_ELEMENT(Feld[jx][jy])) && AllPlayersGone) - PlayerWins(local_player); + LevelSolved(); } // this breaks one level: "machine", level 000 @@ -12697,7 +12726,7 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) RemovePlayer(player); } - if (!local_player->LevelSolved && level.use_step_counter) + if (!game.LevelSolved && level.use_step_counter) { int i; @@ -13937,16 +13966,26 @@ static int DigField(struct PlayerInfo *player, 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(); + IncrementPlayerSokobanObjectsNeeded(); } if (Feld[nextx][nexty] == EL_SOKOBAN_FIELD_EMPTY) { Back[nextx][nexty] = EL_SOKOBAN_FIELD_EMPTY; - local_player->sokobanfields_still_needed--; + + DecrementPlayerSokobanFieldsNeeded(); + DecrementPlayerSokobanObjectsNeeded(); + + // 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; @@ -13960,12 +13999,14 @@ static int DigField(struct PlayerInfo *player, 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; - PlayerWins(player); + LevelSolved(); PlayLevelSound(x, y, SND_GAME_SOKOBAN_SOLVING); } @@ -14990,7 +15031,7 @@ void CheckGameOver(void) boolean checkGameSolved(void) { // set for all game engines if level was solved - return local_player->LevelSolved_GameEnd; + return game.LevelSolved_GameEnd; } boolean checkGameFailed(void) @@ -14999,13 +15040,13 @@ boolean checkGameFailed(void) 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 - return (local_player->GameOver && !local_player->LevelSolved); + return (local_player->GameOver && !game.LevelSolved); } boolean checkGameEnded(void)