X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fgame.c;h=5bfa71db14d69900b035c2d31a0e60df472027bd;hp=70b9b811d2db47fc18b9944db43215e9b61ff74a;hb=8cae2f011a23232a4233e808fd1092d2871603e6;hpb=30eb586d06bc4d1ee7388dced1c20e530292aa93 diff --git a/src/game.c b/src/game.c index 70b9b811..5bfa71db 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(); @@ -4556,8 +4558,8 @@ void GameWon(void) Feld[ExitX][ExitY] = (element == EL_EXIT_OPEN ? EL_EXIT_CLOSING : - element == EL_EM_EXIT_OPEN ? EL_EM_EXIT_CLOSING : - element == EL_SP_EXIT_OPEN ? EL_SP_EXIT_CLOSING: + element == EL_EM_EXIT_OPEN ? EL_EM_EXIT_CLOSING : + element == EL_SP_EXIT_OPEN ? EL_SP_EXIT_CLOSING: element == EL_STEEL_EXIT_OPEN ? EL_STEEL_EXIT_CLOSING: EL_EM_STEEL_EXIT_CLOSING); @@ -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); @@ -8916,7 +8920,8 @@ static void Life(int ax, int ay) for (y1 = -1; y1 < 2; y1++) for (x1 = -1; x1 < 2; x1++) { int xx = ax+x1, yy = ay+y1; - int nachbarn = 0; + int old_element = Feld[xx][yy]; + int num_neighbours = 0; if (!IN_LEV_FIELD(xx, yy)) continue; @@ -8928,33 +8933,48 @@ 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])) - nachbarn++; + 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 (nachbarn < life_parameter[0] || - nachbarn > life_parameter[1]) + if (num_neighbours < life_parameter[0] || + num_neighbours > life_parameter[1]) { Feld[xx][yy] = EL_EMPTY; - if (!Stop[xx][yy]) + if (Feld[xx][yy] != old_element) TEST_DrawLevelField(xx, yy); Stop[xx][yy] = TRUE; 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 (nachbarn >= life_parameter[2] && - nachbarn <= life_parameter[3]) + if (num_neighbours >= life_parameter[2] && + num_neighbours <= life_parameter[3]) { Feld[xx][yy] = element; MovDelay[xx][yy] = (element == EL_GAME_OF_LIFE ? 0 : life_time-1); - if (!Stop[xx][yy]) + if (Feld[xx][yy] != old_element) TEST_DrawLevelField(xx, yy); Stop[xx][yy] = TRUE; changed = TRUE; @@ -11063,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 */ @@ -11115,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) { @@ -11279,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(); @@ -11525,6 +11500,7 @@ static void GameActionsExt(void) BlitScreenToBitmap(backbuffer); + CheckLevelSolved(); CheckLevelTime(); AdvanceFrameAndPlayerCounters(-1); /* advance counters for all players */ @@ -11732,6 +11708,8 @@ void GameActions_RND(void) SCAN_PLAYFIELD(x, y) { + Last[x][y] = Feld[x][y]; + ChangeCount[x][y] = 0; ChangeEvent[x][y] = -1; @@ -13433,6 +13411,10 @@ void ExitPlayer(struct PlayerInfo *player) if (local_player->players_still_needed > 0) local_player->players_still_needed--; + + /* also set if some players not yet gone, but not needed to solve level */ + if (local_player->players_still_needed == 0) + AllPlayersGone = TRUE; } static void setFieldForSnapping(int x, int y, int element, int direction) @@ -14967,6 +14949,32 @@ void RequestRestartGame(char *message) } } +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 */