X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fgame.c;h=f359a2cbdfb406c6bf018873c7b14c5901397dfc;hp=3255b4280abc8bc74978e66cd36df44bb07fea33;hb=4848f0bcd25bee8a7a4e48ae7d2a670bbc4e278d;hpb=cea784bc644569bd9c155de02846dfba9ace036b diff --git a/src/game.c b/src/game.c index 3255b428..f359a2cb 100644 --- a/src/game.c +++ b/src/game.c @@ -81,7 +81,7 @@ #define EX_TYPE_DYNA (1 << 4) #define EX_TYPE_SINGLE_TILE (EX_TYPE_CENTER | EX_TYPE_BORDER) -#define PANEL_OFF() (local_player->LevelSolved_PanelOff) +#define PANEL_OFF() (game.panel.active == FALSE) #define PANEL_DEACTIVATED(p) ((p)->x < 0 || (p)->y < 0 || PANEL_OFF()) #define PANEL_XPOS(p) (DX + ALIGNED_TEXT_XPOS(p)) #define PANEL_YPOS(p) (DY + ALIGNED_TEXT_YPOS(p)) @@ -3525,7 +3525,6 @@ void InitGame(void) player->LevelSolved_GameWon = FALSE; player->LevelSolved_GameEnd = FALSE; - player->LevelSolved_PanelOff = FALSE; player->LevelSolved_SaveTape = FALSE; player->LevelSolved_SaveScore = FALSE; @@ -3559,6 +3558,8 @@ void InitGame(void) AllPlayersGone = FALSE; + game.panel.active = TRUE; + game.no_time_limit = (level.time == 0); game.yamyam_content_nr = 0; @@ -3595,7 +3596,7 @@ void InitGame(void) SCAN_PLAYFIELD(x, y) { - Feld[x][y] = level.field[x][y]; + Feld[x][y] = Last[x][y] = level.field[x][y]; MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0; ChangeDelay[x][y] = 0; ChangePage[x][y] = -1; @@ -4195,6 +4196,7 @@ void InitGame(void) game.restart_level = FALSE; game.restart_game_message = NULL; + game.request_active = FALSE; if (level.game_engine_type == GAME_ENGINE_TYPE_MM) InitGameActions_MM(); @@ -4653,7 +4655,7 @@ void GameWon(void) return; } - local_player->LevelSolved_PanelOff = TRUE; + game.panel.active = FALSE; if (game_over_delay_3 > 0) { @@ -4667,6 +4669,8 @@ void GameWon(void) void GameEnd(void) { + /* used instead of "level_nr" (needed for network games) */ + int last_level_nr = levelset.level_nr; int hi_pos; local_player->LevelSolved_GameEnd = TRUE; @@ -4723,16 +4727,16 @@ void GameEnd(void) } } - /* used instead of last "level_nr" (for network games) */ - hi_pos = NewHiScore(levelset.level_nr); + hi_pos = NewHiScore(last_level_nr); if (hi_pos >= 0 && !setup.skip_scores_after_game) { SetGameStatus(GAME_MODE_SCORES); - DrawHallOfFame(levelset.level_nr, hi_pos); + DrawHallOfFame(last_level_nr, hi_pos); } else if (setup.auto_play_next_level && setup.increment_levels && + last_level_nr < leveldir_current->last_level && !network_playing) { StartGameActions(network.enabled, setup.autorecord, level.random_seed); @@ -8929,13 +8933,28 @@ static void Life(int ax, int ay) if (!IN_LEV_FIELD(x, y) || (x == xx && y == yy)) continue; - if (((Feld[x][y] == element || - (element == EL_GAME_OF_LIFE && IS_PLAYER(x, y))) && - !Stop[x][y]) || - (IS_FREE(x, y) && Stop[x][y])) + boolean is_player_cell = (element == EL_GAME_OF_LIFE && IS_PLAYER(x, y)); + boolean is_neighbour = FALSE; + + if (level.use_life_bugs) + is_neighbour = + (((Feld[x][y] == element || is_player_cell) && !Stop[x][y]) || + (IS_FREE(x, y) && Stop[x][y])); + else + is_neighbour = + (Last[x][y] == element || is_player_cell); + + if (is_neighbour) num_neighbours++; } + boolean is_free = FALSE; + + if (level.use_life_bugs) + is_free = (IS_FREE(xx, yy)); + else + is_free = (IS_FREE(xx, yy) && Last[xx][yy] == EL_EMPTY); + if (xx == ax && yy == ay) /* field in the middle */ { if (num_neighbours < life_parameter[0] || @@ -8948,7 +8967,7 @@ static void Life(int ax, int ay) changed = TRUE; } } - else if (IS_FREE(xx, yy) || CAN_GROW_INTO(Feld[xx][yy])) + else if (is_free || CAN_GROW_INTO(Feld[xx][yy])) { /* free border field */ if (num_neighbours >= life_parameter[2] && num_neighbours <= life_parameter[3]) @@ -11064,11 +11083,8 @@ static void SetTapeActionFromMouseAction(byte *tape_action, tape_action[TAPE_ACTION_BUTTON] = mouse_action->button; } -static void CheckLevelTime(void) +static void CheckLevelSolved(void) { - int i; - - /* !!! SAME CODE AS IN "GameActions()" -- FIX THIS !!! */ if (level.game_engine_type == GAME_ENGINE_TYPE_EM) { if (level.native_em_level->lev->home == 0) /* all players at home */ @@ -11116,6 +11132,11 @@ static void CheckLevelTime(void) if (game_mm.game_over) /* game lost */ AllPlayersGone = TRUE; } +} + +static void CheckLevelTime(void) +{ + int i; if (TimeFrames >= FRAMES_PER_SECOND) { @@ -11280,54 +11301,7 @@ static void GameActionsExt(void) if (game.restart_level) StartGameActions(network.enabled, setup.autorecord, level.random_seed); - /* !!! SAME CODE AS IN "CheckLevelTime()" -- FIX THIS !!! */ - if (level.game_engine_type == GAME_ENGINE_TYPE_EM) - { - if (level.native_em_level->lev->home == 0) /* all players at home */ - { - PlayerWins(local_player); - - AllPlayersGone = TRUE; - - level.native_em_level->lev->home = -1; - } - - 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 */ - AllPlayersGone = TRUE; - } - else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) - { - if (game_sp.LevelSolved && - !game_sp.GameOver) /* game won */ - { - PlayerWins(local_player); - - game_sp.GameOver = TRUE; - - AllPlayersGone = TRUE; - } - - if (game_sp.GameOver) /* game lost */ - AllPlayersGone = TRUE; - } - else if (level.game_engine_type == GAME_ENGINE_TYPE_MM) - { - if (game_mm.level_solved && - !game_mm.game_over) /* game won */ - { - PlayerWins(local_player); - - game_mm.game_over = TRUE; - - AllPlayersGone = TRUE; - } - - if (game_mm.game_over) /* game lost */ - AllPlayersGone = TRUE; - } + CheckLevelSolved(); if (local_player->LevelSolved && !local_player->LevelSolved_GameEnd) GameWon(); @@ -11372,7 +11346,8 @@ static void GameActionsExt(void) if (game_status != GAME_MODE_PLAYING) return; - if (!network_player_action_received) + /* check if network player actions still missing and game still running */ + if (!network_player_action_received && !checkGameEnded()) return; /* failed to get network player actions in time */ /* do not yet reset "network_player_action_received" (for tape.pausing) */ @@ -11412,7 +11387,7 @@ static void GameActionsExt(void) stored_player[i].effective_action = stored_player[i].action; } - if (network_playing) + if (network_playing && !checkGameEnded()) SendToServer_MovePlayer(summarized_player_action); // summarize all actions at local players mapped input device position @@ -11526,6 +11501,7 @@ static void GameActionsExt(void) BlitScreenToBitmap(backbuffer); + CheckLevelSolved(); CheckLevelTime(); AdvanceFrameAndPlayerCounters(-1); /* advance counters for all players */ @@ -11733,6 +11709,8 @@ void GameActions_RND(void) SCAN_PLAYFIELD(x, y) { + Last[x][y] = Feld[x][y]; + ChangeCount[x][y] = 0; ChangeEvent[x][y] = -1; @@ -14960,7 +14938,10 @@ void RequestRestartGame(char *message) { game.restart_game_message = NULL; - if (Request(message, REQ_ASK | REQ_STAY_CLOSED)) + boolean has_started_game = hasStartedNetworkGame(); + int request_mode = (has_started_game ? REQ_ASK : REQ_CONFIRM); + + if (Request(message, request_mode | REQ_STAY_CLOSED) && has_started_game) { StartGameActions(network.enabled, setup.autorecord, level.random_seed); } @@ -14972,6 +14953,66 @@ void RequestRestartGame(char *message) } } +void CheckGameOver(void) +{ + static boolean last_game_over = FALSE; + static int game_over_delay = 0; + int game_over_delay_value = 50; + boolean game_over = checkGameFailed(); + + /* do not handle game over if request dialog is already active */ + if (game.request_active) + return; + + if (!game_over) + { + last_game_over = FALSE; + game_over_delay = game_over_delay_value; + + return; + } + + if (game_over_delay > 0) + { + game_over_delay--; + + return; + } + + if (last_game_over != game_over) + game.restart_game_message = (hasStartedNetworkGame() ? + "Game over! Play it again?" : + "Game over!"); + + last_game_over = game_over; +} + +boolean checkGameSolved(void) +{ + /* set for all game engines if level was solved */ + return local_player->LevelSolved_GameEnd; +} + +boolean checkGameFailed(void) +{ + if (!AllPlayersGone) + return FALSE; + + if (level.game_engine_type == GAME_ENGINE_TYPE_EM) + return (level.native_em_level->lev->home > 0); + else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) + return (game_sp.GameOver && !game_sp.LevelSolved); + 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); +} + +boolean checkGameEnded(void) +{ + return (checkGameSolved() || checkGameFailed()); +} + /* ------------------------------------------------------------------------- */ /* random generator functions */