X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fgame.c;h=fdb77eb3e9e2a139200e2d6d4741f9455b4603e6;hp=41768a54c63e6b97aa0a661a9b522d475a25297f;hb=172a34e8d64ad71e6eee7871803e9faee7669ca3;hpb=10464a20b3b871f7731f5ec6ad2faca814bf6c20 diff --git a/src/game.c b/src/game.c index 41768a54..fdb77eb3 100644 --- a/src/game.c +++ b/src/game.c @@ -1085,8 +1085,8 @@ static void PlayLevelSoundElementAction(int, int, int, int); static void PlayLevelSoundElementActionIfLoop(int, int, int, int); static void PlayLevelSoundActionIfLoop(int, int, int); static void StopLevelSoundActionIfLoop(int, int, int); -static void PlayLevelMusic(); -static void FadeLevelSoundsAndMusic(); +static void PlayLevelMusic(void); +static void FadeLevelSoundsAndMusic(void); static void HandleGameButtons(struct GadgetInfo *); @@ -1096,7 +1096,7 @@ void ContinueMoving(int, int); void Bang(int, int); void InitMovDir(int, int); void InitAmoebaNr(int, int); -int NewHiScore(void); +int NewHiScore(int); void TestIfGoodThingHitsBadThing(int, int, int); void TestIfBadThingHitsGoodThing(int, int, int); @@ -1112,6 +1112,7 @@ void TestIfGoodThingGetsHitByBadThing(int, int, int); void KillPlayer(struct PlayerInfo *); void BuryPlayer(struct PlayerInfo *); void RemovePlayer(struct PlayerInfo *); +void ExitPlayer(struct PlayerInfo *); static int getInvisibleActiveFromInvisibleElement(int); static int getInvisibleFromInvisibleActiveElement(int); @@ -1561,7 +1562,7 @@ static int playfield_scan_delta_y = 1; (x) += playfield_scan_delta_x) #ifdef DEBUG -void DEBUG_SetMaximumDynamite() +void DEBUG_SetMaximumDynamite(void) { int i; @@ -1572,7 +1573,7 @@ void DEBUG_SetMaximumDynamite() } #endif -static void InitPlayfieldScanModeVars() +static void InitPlayfieldScanModeVars(void) { if (game.use_reverse_scan_direction) { @@ -1635,7 +1636,7 @@ static void SetPlayerMoveSpeed(struct PlayerInfo *player, int move_stepsize, } } -void GetPlayerConfig() +void GetPlayerConfig(void) { GameFrameDelay = setup.game_frame_delay; @@ -1731,7 +1732,7 @@ static void InitPlayerField(int x, int y, int element, boolean init_game) if (game.use_block_last_field_bug) player->block_delay_adjustment = (player->block_last_field ? -1 : 1); - if (!options.network || player->connected) + if (!network.enabled || player->connected_network) { player->active = TRUE; @@ -2102,7 +2103,7 @@ int getPlayerInventorySize(int player_nr) return stored_player[player_nr].inventory_size; } -void InitGameControlValues() +static void InitGameControlValues(void) { int i; @@ -2147,7 +2148,7 @@ void InitGameControlValues() sizeof(struct GamePanelOrderInfo), compareGamePanelOrderInfo); } -void UpdatePlayfieldElementCount() +static void UpdatePlayfieldElementCount(void) { boolean use_element_count = FALSE; int i, j, x, y; @@ -2175,7 +2176,7 @@ void UpdatePlayfieldElementCount() element_info[j].element_count; } -void UpdateGameControlValues() +static void UpdateGameControlValues(void) { int i, k; int time = (local_player->LevelSolved ? @@ -2223,7 +2224,8 @@ void UpdateGameControlValues() /* update game panel control values */ - game_panel_controls[GAME_PANEL_LEVEL_NUMBER].value = level_nr; + /* used instead of "level_nr" (for network games) */ + game_panel_controls[GAME_PANEL_LEVEL_NUMBER].value = levelset.level_nr; game_panel_controls[GAME_PANEL_GEMS].value = gems; game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value = 0; @@ -2505,7 +2507,7 @@ void UpdateGameControlValues() } } -void DisplayGameControlValues() +static void DisplayGameControlValues(void) { boolean redraw_panel = FALSE; int i; @@ -2756,7 +2758,7 @@ void DisplayGameControlValues() SetGameStatus(GAME_MODE_PLAYING); } -void UpdateAndDisplayGameControlValues() +void UpdateAndDisplayGameControlValues(void) { if (tape.deactivate_display) return; @@ -2765,12 +2767,14 @@ void UpdateAndDisplayGameControlValues() DisplayGameControlValues(); } -void UpdateGameDoorValues() +#if 0 +static void UpdateGameDoorValues(void) { UpdateGameControlValues(); } +#endif -void DrawGameDoorValues() +void DrawGameDoorValues(void) { DisplayGameControlValues(); } @@ -2784,7 +2788,7 @@ void DrawGameDoorValues() ============================================================================= */ -static void InitGameEngine() +static void InitGameEngine(void) { int i, j, k, l, x, y; @@ -3241,7 +3245,8 @@ static void InitGameEngine() level.time = 0; } -int get_num_special_action(int element, int action_first, int action_last) +static int get_num_special_action(int element, int action_first, + int action_last) { int num_special_action = 0; int i, j; @@ -3273,7 +3278,37 @@ int get_num_special_action(int element, int action_first, int action_last) ============================================================================= */ -void InitGame() +#if DEBUG_INIT_PLAYER +static void DebugPrintPlayerStatus(char *message) +{ + int i; + + if (!options.debug) + return; + + printf("%s:\n", message); + + for (i = 0; i < MAX_PLAYERS; i++) + { + struct PlayerInfo *player = &stored_player[i]; + + printf("- player %d: present == %d, connected == %d [%d/%d], active == %d", + i + 1, + player->present, + player->connected, + player->connected_locally, + player->connected_network, + player->active); + + if (local_player == player) + printf(" (local player)"); + + printf("\n"); + } +} +#endif + +void InitGame(void) { int full_lev_fieldx = lev_fieldx + (BorderElement != EL_EMPTY ? 2 : 0); int full_lev_fieldy = lev_fieldy + (BorderElement != EL_EMPTY ? 2 : 0); @@ -3312,15 +3347,15 @@ void InitGame() ClearField(); - OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW); - DrawCompleteVideoDisplay(); + OpenDoor(GetDoorState() | DOOR_NO_DELAY | DOOR_FORCE_REDRAW); + InitGameEngine(); InitGameControlValues(); /* don't play tapes over network */ - network_playing = (options.network && !tape.playing); + network_playing = (network.enabled && !tape.playing); for (i = 0; i < MAX_PLAYERS; i++) { @@ -3344,10 +3379,12 @@ void InitGame() player->mouse_action.lx = 0; player->mouse_action.ly = 0; player->mouse_action.button = 0; + player->mouse_action.button_hint = 0; player->effective_mouse_action.lx = 0; player->effective_mouse_action.ly = 0; player->effective_mouse_action.button = 0; + player->effective_mouse_action.button_hint = 0; player->score = 0; player->score_final = 0; @@ -3358,6 +3395,7 @@ void InitGame() player->gems_still_needed = level.gems_needed; player->sokobanfields_still_needed = 0; player->lights_still_needed = 0; + player->players_still_needed = 0; player->friends_still_needed = 0; for (j = 0; j < MAX_NUM_KEYS; j++) @@ -3500,11 +3538,9 @@ void InitGame() network_player_action_received = FALSE; -#if defined(NETWORK_AVALIABLE) /* initial null action */ if (network_playing) SendToServer_MovePlayer(MV_NONE); -#endif ZX = ZY = -1; ExitX = ExitY = -1; @@ -3540,19 +3576,9 @@ void InitGame() game.ball_state = level.ball_state_initial; game.ball_content_nr = 0; - game.envelope_active = FALSE; - - /* set focus to local player for network games, else to all players */ - game.centered_player_nr = (network_playing ? local_player->index_nr : -1); - game.centered_player_nr_next = game.centered_player_nr; - game.set_centered_player = FALSE; + game.explosions_delayed = TRUE; - if (network_playing && tape.recording) - { - /* store client dependent player focus when recording network games */ - tape.centered_player_nr_next = game.centered_player_nr_next; - tape.set_centered_player = TRUE; - } + game.envelope_active = FALSE; for (i = 0; i < NUM_BELTS; i++) { @@ -3564,10 +3590,7 @@ void InitGame() AmoebaCnt[i] = AmoebaCnt2[i] = 0; #if DEBUG_INIT_PLAYER - if (options.debug) - { - printf("Player status at level initialization:\n"); - } + DebugPrintPlayerStatus("Player status at level initialization"); #endif SCAN_PLAYFIELD(x, y) @@ -3681,22 +3704,33 @@ void InitGame() game.belt_dir_nr[i] = 3; /* not moving, next moving left */ #if USE_NEW_PLAYER_ASSIGNMENTS - /* !!! SAME AS init.c:InitPlayerInfo() -- FIX THIS !!! */ - /* choose default local player */ - local_player = &stored_player[0]; - for (i = 0; i < MAX_PLAYERS; i++) + { stored_player[i].connected = FALSE; - local_player->connected = TRUE; - /* !!! SAME AS init.c:InitPlayerInfo() -- FIX THIS !!! */ + /* in network game mode, the local player might not be the first player */ + if (stored_player[i].connected_locally) + local_player = &stored_player[i]; + } + + if (!network.enabled) + local_player->connected = TRUE; if (tape.playing) { for (i = 0; i < MAX_PLAYERS; i++) stored_player[i].connected = tape.player_participates[i]; } - else if (game.team_mode && !options.network) + 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) */ + + for (i = 0; i < MAX_PLAYERS; i++) + if (stored_player[i].connected_network) + stored_player[i].connected = TRUE; + } + 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) */ @@ -3708,26 +3742,7 @@ void InitGame() } #if DEBUG_INIT_PLAYER - if (options.debug) - { - printf("Player status after level initialization:\n"); - - for (i = 0; i < MAX_PLAYERS; i++) - { - struct PlayerInfo *player = &stored_player[i]; - - printf("- player %d: present == %d, connected == %d, active == %d", - i + 1, - player->present, - player->connected, - player->active); - - if (local_player == player) - printf(" (local player)"); - - printf("\n"); - } - } + DebugPrintPlayerStatus("Player status after level initialization"); #endif #if DEBUG_INIT_PLAYER @@ -3814,26 +3829,7 @@ void InitGame() } #if DEBUG_INIT_PLAYER - if (options.debug) - { - printf("Player status after player assignment (first stage):\n"); - - for (i = 0; i < MAX_PLAYERS; i++) - { - struct PlayerInfo *player = &stored_player[i]; - - printf("- player %d: present == %d, connected == %d, active == %d", - i + 1, - player->present, - player->connected, - player->active); - - if (local_player == player) - printf(" (local player)"); - - printf("\n"); - } - } + DebugPrintPlayerStatus("Player status after player assignment (first stage)"); #endif #else @@ -3881,6 +3877,18 @@ void InitGame() printf("::: local_player->present == %d\n", local_player->present); #endif + /* set focus to local player for network games, else to all players */ + game.centered_player_nr = (network_playing ? local_player->index_nr : -1); + game.centered_player_nr_next = game.centered_player_nr; + game.set_centered_player = FALSE; + + if (network_playing && tape.recording) + { + /* store client dependent player focus when recording network games */ + tape.centered_player_nr_next = game.centered_player_nr_next; + tape.set_centered_player = TRUE; + } + if (tape.playing) { /* when playing a tape, eliminate all players who do not participate */ @@ -3926,32 +3934,34 @@ void InitGame() } #endif } - else if (!options.network && !game.team_mode) /* && !tape.playing */ + else if (!network.enabled && !game.team_mode) /* && !tape.playing */ { - /* when in single player mode, eliminate all but the first active player */ + /* when in single player mode, eliminate all but the local player */ for (i = 0; i < MAX_PLAYERS; i++) { - if (stored_player[i].active) + struct PlayerInfo *player = &stored_player[i]; + + if (player->active && player != local_player) { - for (j = i + 1; j < MAX_PLAYERS; j++) - { - if (stored_player[j].active) - { - struct PlayerInfo *player = &stored_player[j]; - int jx = player->jx, jy = player->jy; + int jx = player->jx, jy = player->jy; - player->active = FALSE; - player->present = FALSE; + player->active = FALSE; + player->present = FALSE; - StorePlayer[jx][jy] = 0; - Feld[jx][jy] = EL_EMPTY; - } - } + StorePlayer[jx][jy] = 0; + Feld[jx][jy] = EL_EMPTY; } } } + for (i = 0; i < MAX_PLAYERS; i++) + if (stored_player[i].active) + local_player->players_still_needed++; + + if (level.solved_by_one_player) + local_player->players_still_needed = 1; + /* when recording the game, store which players take part in the game */ if (tape.recording) { @@ -3967,26 +3977,7 @@ void InitGame() } #if DEBUG_INIT_PLAYER - if (options.debug) - { - printf("Player status after player assignment (final stage):\n"); - - for (i = 0; i < MAX_PLAYERS; i++) - { - struct PlayerInfo *player = &stored_player[i]; - - printf("- player %d: present == %d, connected == %d, active == %d", - i + 1, - player->present, - player->connected, - player->active); - - if (local_player == player) - printf(" (local player)"); - - printf("\n"); - } - } + DebugPrintPlayerStatus("Player status after player assignment (final stage)"); #endif if (BorderElement == EL_EMPTY) @@ -4183,34 +4174,10 @@ void InitGame() OpenDoor(DOOR_OPEN_ALL); - PlaySound(SND_GAME_STARTING); - - if (setup.sound_music) - PlayLevelMusic(); - KeyboardAutoRepeatOffUnlessAutoplay(); #if DEBUG_INIT_PLAYER - if (options.debug) - { - printf("Player status (final):\n"); - - for (i = 0; i < MAX_PLAYERS; i++) - { - struct PlayerInfo *player = &stored_player[i]; - - printf("- player %d: present == %d, connected == %d, active == %d", - i + 1, - player->present, - player->connected, - player->active); - - if (local_player == player) - printf(" (local player)"); - - printf("\n"); - } - } + DebugPrintPlayerStatus("Player status (final)"); #endif } @@ -4227,11 +4194,20 @@ void InitGame() } game.restart_level = FALSE; + game.restart_game_message = NULL; if (level.game_engine_type == GAME_ENGINE_TYPE_MM) InitGameActions_MM(); SaveEngineSnapshotToListInitial(); + + if (!game.restart_level) + { + PlaySound(SND_GAME_STARTING); + + if (setup.sound_music) + PlayLevelMusic(); + } } void UpdateEngineValues(int actual_scroll_x, int actual_scroll_y, @@ -4454,6 +4430,10 @@ void InitAmoebaNr(int x, int y) static void PlayerWins(struct PlayerInfo *player) { + if (level.game_engine_type == GAME_ENGINE_TYPE_RND && + local_player->players_still_needed > 0) + return; + player->LevelSolved = TRUE; player->GameOver = TRUE; @@ -4472,7 +4452,7 @@ static void PlayerWins(struct PlayerInfo *player) player->LevelSolved_CountingHealth = player->health_final; } -void GameWon() +void GameWon(void) { static int time_count_steps; static int time, time_final; @@ -4576,8 +4556,8 @@ void GameWon() 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); @@ -4685,10 +4665,9 @@ void GameWon() GameEnd(); } -void GameEnd() +void GameEnd(void) { int hi_pos; - boolean raise_level = FALSE; local_player->LevelSolved_GameEnd = TRUE; @@ -4698,7 +4677,7 @@ void GameEnd() if (!global.use_envelope_request) CloseDoor(DOOR_CLOSE_1); - SaveTapeChecked(tape.level_nr); /* ask to save tape */ + SaveTapeChecked_LevelSolved(tape.level_nr); /* ask to save tape */ } /* if no tape is to be saved, close both doors simultaneously */ @@ -4730,36 +4709,43 @@ void GameEnd() } if (setup.increment_levels && - level_nr < leveldir_current->last_level) - raise_level = TRUE; /* advance to next level */ - - if ((hi_pos = NewHiScore()) >= 0) + level_nr < leveldir_current->last_level && + !network_playing) { - SetGameStatus(GAME_MODE_SCORES); - - DrawHallOfFame(hi_pos); + level_nr++; /* advance to next level */ + TapeErase(); /* start with empty tape */ - if (raise_level) + if (setup.auto_play_next_level) { - level_nr++; - TapeErase(); + LoadLevel(level_nr); + + SaveLevelSetup_SeriesInfo(); } } + + /* used instead of last "level_nr" (for network games) */ + hi_pos = NewHiScore(levelset.level_nr); + + if (hi_pos >= 0 && !setup.skip_scores_after_game) + { + SetGameStatus(GAME_MODE_SCORES); + + DrawHallOfFame(levelset.level_nr, hi_pos); + } + else if (setup.auto_play_next_level && setup.increment_levels && + !network_playing) + { + StartGameActions(network.enabled, setup.autorecord, level.random_seed); + } else { SetGameStatus(GAME_MODE_MAIN); - if (raise_level) - { - level_nr++; - TapeErase(); - } - DrawMainMenu(); } } -int NewHiScore() +int NewHiScore(int level_nr) { int k, l; int position = -1; @@ -4890,7 +4876,7 @@ static void ResetRandomAnimationValue(int x, int y) GfxRandom[x][y] = INIT_GFX_RANDOM(); } -void InitMovingField(int x, int y, int direction) +static void InitMovingField(int x, int y, int direction) { int element = Feld[x][y]; int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0); @@ -4963,7 +4949,7 @@ void Blocked2Moving(int x, int y, int *comes_from_x, int *comes_from_y) *comes_from_y = oldy; } -int MovingOrBlocked2Element(int x, int y) +static int MovingOrBlocked2Element(int x, int y) { int element = Feld[x][y]; @@ -5021,7 +5007,7 @@ static void RemoveField(int x, int y) GfxDir[x][y] = MV_NONE; } -void RemoveMovingField(int x, int y) +static void RemoveMovingField(int x, int y) { int oldx = x, oldy = y, newx = x, newy = y; int element = Feld[x][y]; @@ -5102,7 +5088,7 @@ void DrawDynamite(int x, int y) DrawGraphic(sx, sy, graphic, frame); } -void CheckDynamite(int x, int y) +static void CheckDynamite(int x, int y) { if (MovDelay[x][y] != 0) /* dynamite is still waiting to explode */ { @@ -5152,7 +5138,7 @@ static void setMinimalPlayerBoundaries(int *sx1, int *sy1, int *sx2, int *sy2) } } -static boolean checkIfAllPlayersFitToScreen_RND() +static boolean checkIfAllPlayersFitToScreen_RND(void) { int sx1 = 0, sy1 = 0, sx2 = 0, sy2 = 0; @@ -5172,8 +5158,8 @@ static void setScreenCenteredToAllPlayers(int *sx, int *sy) *sy = (sy1 + sy2) / 2; } -void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir, - boolean center_screen, boolean quick_relocation) +static void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir, + boolean center_screen, boolean quick_relocation) { unsigned int frame_delay_value_old = GetVideoFrameDelay(); boolean ffwd_delay = (tape.playing && tape.fast_forward); @@ -5263,7 +5249,7 @@ void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir, SetVideoFrameDelay(frame_delay_value_old); } -void RelocatePlayer(int jx, int jy, int el_player_raw) +static void RelocatePlayer(int jx, int jy, int el_player_raw) { int el_player = GET_PLAYER_ELEMENT(el_player_raw); int player_nr = GET_PLAYER_NR(el_player); @@ -5368,7 +5354,7 @@ void RelocatePlayer(int jx, int jy, int el_player_raw) } } -void Explode(int ex, int ey, int phase, int mode) +static void Explode(int ex, int ey, int phase, int mode) { int x, y; int last_phase; @@ -5671,7 +5657,7 @@ void Explode(int ex, int ey, int phase, int mode) } } -void DynaExplode(int ex, int ey) +static void DynaExplode(int ex, int ey) { int i, j; int dynabomb_element = Feld[ex][ey]; @@ -5796,7 +5782,7 @@ void Bang(int x, int y) CheckTriggeredElementChange(x, y, element, CE_EXPLOSION_OF_X); } -void SplashAcid(int x, int y) +static void SplashAcid(int x, int y) { if (IN_LEV_FIELD(x - 1, y - 1) && IS_FREE(x - 1, y - 1) && (!IN_LEV_FIELD(x - 1, y - 2) || @@ -5811,7 +5797,7 @@ void SplashAcid(int x, int y) PlayLevelSound(x, y, SND_ACID_SPLASHING); } -static void InitBeltMovement() +static void InitBeltMovement(void) { static int belt_base_element[4] = { @@ -6045,7 +6031,7 @@ static int getInvisibleFromInvisibleActiveElement(int element) element); } -static void RedrawAllLightSwitchesAndInvisibleElements() +static void RedrawAllLightSwitchesAndInvisibleElements(void) { int x, y; @@ -6106,7 +6092,7 @@ static void RedrawAllLightSwitchesAndInvisibleElements() } } -static void RedrawAllInvisibleElementsForLenses() +static void RedrawAllInvisibleElementsForLenses(void) { int x, y; @@ -6155,7 +6141,7 @@ static void RedrawAllInvisibleElementsForLenses() } } -static void RedrawAllInvisibleElementsForMagnifier() +static void RedrawAllInvisibleElementsForMagnifier(void) { int x, y; @@ -6248,7 +6234,7 @@ static void ActivateTimegateSwitch(int x, int y) EL_DC_TIMEGATE_SWITCH_ACTIVE); } -void Impact(int x, int y) +static void Impact(int x, int y) { boolean last_line = (y == lev_fieldy - 1); boolean object_hit = FALSE; @@ -7352,7 +7338,7 @@ static boolean JustBeingPushed(int x, int y) return FALSE; } -void StartMoving(int x, int y) +static void StartMoving(int x, int y) { boolean started_moving = FALSE; /* some elements can fall _and_ move */ int element = Feld[x][y]; @@ -8531,7 +8517,7 @@ int AmoebeNachbarNr(int ax, int ay) return group_nr; } -void AmoebenVereinigen(int ax, int ay) +static void AmoebenVereinigen(int ax, int ay) { int i, x, y, xx, yy; int new_group_nr = AmoebaNr[ax][ay]; @@ -8638,7 +8624,7 @@ void AmoebeUmwandeln(int ax, int ay) } } -void AmoebeUmwandelnBD(int ax, int ay, int new_element) +static void AmoebeUmwandelnBD(int ax, int ay, int new_element) { int x, y; int group_nr = AmoebaNr[ax][ay]; @@ -8674,7 +8660,7 @@ void AmoebeUmwandelnBD(int ax, int ay, int new_element) SND_BD_AMOEBA_TURNING_TO_GEM)); } -void AmoebeWaechst(int x, int y) +static void AmoebeWaechst(int x, int y) { static unsigned int sound_delay = 0; static unsigned int sound_delay_value = 0; @@ -8710,7 +8696,7 @@ void AmoebeWaechst(int x, int y) } } -void AmoebaDisappearing(int x, int y) +static void AmoebaDisappearing(int x, int y) { static unsigned int sound_delay = 0; static unsigned int sound_delay_value = 0; @@ -8746,7 +8732,7 @@ void AmoebaDisappearing(int x, int y) } } -void AmoebeAbleger(int ax, int ay) +static void AmoebeAbleger(int ax, int ay) { int i; int element = Feld[ax][ay]; @@ -8901,7 +8887,7 @@ void AmoebeAbleger(int ax, int ay) TEST_DrawLevelField(newax, neway); } -void Life(int ax, int ay) +static void Life(int ax, int ay) { int x1, y1, x2, y2; int life_time = 40; @@ -8930,6 +8916,7 @@ 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 old_element = Feld[xx][yy]; int nachbarn = 0; if (!IN_LEV_FIELD(xx, yy)) @@ -8955,7 +8942,7 @@ void Life(int ax, int ay) nachbarn > 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; @@ -8968,7 +8955,7 @@ void Life(int ax, int ay) { 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; @@ -9048,7 +9035,7 @@ static void ActivateMagicBall(int bx, int by) game.ball_content_nr = (game.ball_content_nr + 1) % level.num_ball_contents; } -void CheckExit(int x, int y) +static void CheckExit(int x, int y) { if (local_player->gems_still_needed > 0 || local_player->sokobanfields_still_needed > 0 || @@ -9071,7 +9058,7 @@ void CheckExit(int x, int y) PlayLevelSoundNearest(x, y, SND_CLASS_EXIT_OPENING); } -void CheckExitEM(int x, int y) +static void CheckExitEM(int x, int y) { if (local_player->gems_still_needed > 0 || local_player->sokobanfields_still_needed > 0 || @@ -9094,7 +9081,7 @@ void CheckExitEM(int x, int y) PlayLevelSoundNearest(x, y, SND_CLASS_EM_EXIT_OPENING); } -void CheckExitSteel(int x, int y) +static void CheckExitSteel(int x, int y) { if (local_player->gems_still_needed > 0 || local_player->sokobanfields_still_needed > 0 || @@ -9117,7 +9104,7 @@ void CheckExitSteel(int x, int y) PlayLevelSoundNearest(x, y, SND_CLASS_STEEL_EXIT_OPENING); } -void CheckExitSteelEM(int x, int y) +static void CheckExitSteelEM(int x, int y) { if (local_player->gems_still_needed > 0 || local_player->sokobanfields_still_needed > 0 || @@ -9140,7 +9127,7 @@ void CheckExitSteelEM(int x, int y) PlayLevelSoundNearest(x, y, SND_CLASS_EM_STEEL_EXIT_OPENING); } -void CheckExitSP(int x, int y) +static void CheckExitSP(int x, int y) { if (local_player->gems_still_needed > 0) { @@ -9161,7 +9148,7 @@ void CheckExitSP(int x, int y) PlayLevelSoundNearest(x, y, SND_CLASS_SP_EXIT_OPENING); } -static void CloseAllOpenTimegates() +static void CloseAllOpenTimegates(void) { int x, y; @@ -9178,7 +9165,7 @@ static void CloseAllOpenTimegates() } } -void DrawTwinkleOnField(int x, int y) +static void DrawTwinkleOnField(int x, int y) { if (!IN_SCR_FIELD(SCREENX(x), SCREENY(y)) || IS_MOVING(x, y)) return; @@ -9205,7 +9192,7 @@ void DrawTwinkleOnField(int x, int y) } } -void MauerWaechst(int x, int y) +static void MauerWaechst(int x, int y) { int delay = 6; @@ -9255,7 +9242,7 @@ void MauerWaechst(int x, int y) } } -void MauerAbleger(int ax, int ay) +static void MauerAbleger(int ax, int ay) { int element = Feld[ax][ay]; int graphic = el2img(element); @@ -9363,7 +9350,7 @@ void MauerAbleger(int ax, int ay) PlayLevelSoundAction(ax, ay, ACTION_GROWING); } -void MauerAblegerStahl(int ax, int ay) +static void MauerAblegerStahl(int ax, int ay) { int element = Feld[ax][ay]; int graphic = el2img(element); @@ -9465,7 +9452,7 @@ void MauerAblegerStahl(int ax, int ay) PlayLevelSoundAction(ax, ay, ACTION_GROWING); } -void CheckForDragon(int x, int y) +static void CheckForDragon(int x, int y) { int i, j; boolean dragon_found = FALSE; @@ -9809,7 +9796,10 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) { for (i = 0; i < MAX_PLAYERS; i++) if (action_arg_player_bits & (1 << i)) - PlayerWins(&stored_player[i]); + ExitPlayer(&stored_player[i]); + + if (AllPlayersGone) + PlayerWins(local_player); break; } @@ -10793,7 +10783,7 @@ static void PlayPlayerSound(struct PlayerInfo *player) } } -static void PlayAllPlayersSound() +static void PlayAllPlayersSound(void) { int i; @@ -11074,7 +11064,7 @@ static void SetTapeActionFromMouseAction(byte *tape_action, tape_action[TAPE_ACTION_BUTTON] = mouse_action->button; } -static void CheckLevelTime() +static void CheckLevelTime(void) { int i; @@ -11246,19 +11236,18 @@ void StartGameActions(boolean init_network_game, boolean record_tape, if (record_tape) TapeStartRecording(new_random_seed); -#if defined(NETWORK_AVALIABLE) if (init_network_game) { + SendToServer_LevelFile(); SendToServer_StartPlaying(); return; } -#endif InitGame(); } -void GameActionsExt() +static void GameActionsExt(void) { #if 0 static unsigned int game_frame_delay = 0; @@ -11289,7 +11278,7 @@ void GameActionsExt() } if (game.restart_level) - StartGameActions(options.network, setup.autorecord, level.random_seed); + StartGameActions(network.enabled, setup.autorecord, level.random_seed); /* !!! SAME CODE AS IN "CheckLevelTime()" -- FIX THIS !!! */ if (level.game_engine_type == GAME_ENGINE_TYPE_EM) @@ -11376,10 +11365,8 @@ void GameActionsExt() { /* try to get network player actions in time */ -#if defined(NETWORK_AVALIABLE) /* last chance to get network player actions without main loop delay */ HandleNetworking(); -#endif /* game was quit by network peer */ if (game_status != GAME_MODE_PLAYING) @@ -11425,14 +11412,12 @@ void GameActionsExt() stored_player[i].effective_action = stored_player[i].action; } -#if defined(NETWORK_AVALIABLE) if (network_playing) SendToServer_MovePlayer(summarized_player_action); -#endif // summarize all actions at local players mapped input device position // (this allows using different input devices in single player mode) - if (!options.network && !game.team_mode) + if (!network.enabled && !game.team_mode) stored_player[map_player_action[local_player->index_nr]].effective_action = summarized_player_action; @@ -11570,7 +11555,7 @@ void GameActionsExt() } } -static void GameActions_CheckSaveEngineSnapshot() +static void GameActions_CheckSaveEngineSnapshot(void) { if (!game.snapshot.save_snapshot) return; @@ -11581,14 +11566,14 @@ static void GameActions_CheckSaveEngineSnapshot() SaveEngineSnapshotToList(); } -void GameActions() +void GameActions(void) { GameActionsExt(); GameActions_CheckSaveEngineSnapshot(); } -void GameActions_EM_Main() +void GameActions_EM_Main(void) { byte effective_action[MAX_PLAYERS]; boolean warp_mode = (tape.playing && tape.warp_forward && !tape.pausing); @@ -11600,7 +11585,7 @@ void GameActions_EM_Main() GameActions_EM(effective_action, warp_mode); } -void GameActions_SP_Main() +void GameActions_SP_Main(void) { byte effective_action[MAX_PLAYERS]; boolean warp_mode = (tape.playing && tape.warp_forward && !tape.pausing); @@ -11620,19 +11605,19 @@ void GameActions_SP_Main() } } -void GameActions_MM_Main() +void GameActions_MM_Main(void) { boolean warp_mode = (tape.playing && tape.warp_forward && !tape.pausing); GameActions_MM(local_player->effective_mouse_action, warp_mode); } -void GameActions_RND_Main() +void GameActions_RND_Main(void) { GameActions_RND(); } -void GameActions_RND() +void GameActions_RND(void) { int magic_wall_x = 0, magic_wall_y = 0; int i, x, y, element, graphic, last_gfx_frame; @@ -12175,7 +12160,7 @@ static boolean AllPlayersInSight(struct PlayerInfo *player, int x, int y) return (max_x - min_x < SCR_FIELDX && max_y - min_y < SCR_FIELDY); } -static boolean AllPlayersInVisibleScreen() +static boolean AllPlayersInVisibleScreen(void) { int i; @@ -12342,7 +12327,7 @@ boolean MovePlayerOneStep(struct PlayerInfo *player, } } - if (!options.network && game.centered_player_nr == -1 && + if (!network.enabled && game.centered_player_nr == -1 && !AllPlayersInSight(player, new_jx, new_jy)) return MP_NO_ACTION; @@ -12529,7 +12514,7 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy) if (scroll_x != old_scroll_x || scroll_y != old_scroll_y) { - if (!options.network && game.centered_player_nr == -1 && + if (!network.enabled && game.centered_player_nr == -1 && !AllPlayersInVisibleScreen()) { scroll_x = old_scroll_x; @@ -12681,12 +12666,12 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) Feld[jx][jy] == EL_SP_EXIT_OPEN || Feld[jx][jy] == EL_SP_EXIT_OPENING) /* <-- special case */ { - DrawPlayer(player); /* needed here only to cleanup last field */ - RemovePlayer(player); + ExitPlayer(player); - if (local_player->friends_still_needed == 0 || - IS_SP_ELEMENT(Feld[jx][jy])) - PlayerWins(player); + if ((local_player->friends_still_needed == 0 || + IS_SP_ELEMENT(Feld[jx][jy])) && + AllPlayersGone) + PlayerWins(local_player); } /* this breaks one level: "machine", level 000 */ @@ -13442,6 +13427,19 @@ void RemovePlayer(struct PlayerInfo *player) ExitY = ZY = jy; } +void ExitPlayer(struct PlayerInfo *player) +{ + DrawPlayer(player); /* needed here only to cleanup last field */ + RemovePlayer(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) { struct ElementInfo *ei = &element_info[element]; @@ -13987,6 +13985,8 @@ static int DigField(struct PlayerInfo *player, if (local_player->sokobanfields_still_needed == 0 && (game.emulation == EMU_SOKOBAN || level.auto_exit_sokoban)) { + local_player->players_still_needed = 0; + PlayerWins(player); PlayLevelSound(x, y, SND_GAME_SOKOBAN_SOLVING); @@ -14469,7 +14469,7 @@ static boolean DropElement(struct PlayerInfo *player) static int *loop_sound_frame = NULL; static int *loop_sound_volume = NULL; -void InitPlayLevelSound() +void InitPlayLevelSound(void) { int num_sounds = getSoundListSize(); @@ -14572,7 +14572,7 @@ static void StopLevelSoundActionIfLoop(int x, int y, int action) StopSound(sound_effect); } -static int getLevelMusicNr() +static int getLevelMusicNr(void) { if (levelset.music[level_nr] != MUS_UNDEFINED) return levelset.music[level_nr]; /* from config file */ @@ -14580,12 +14580,12 @@ static int getLevelMusicNr() return MAP_NOCONF_MUSIC(level_nr); /* from music dir */ } -static void FadeLevelSounds() +static void FadeLevelSounds(void) { FadeSounds(); } -static void FadeLevelMusic() +static void FadeLevelMusic(void) { int music_nr = getLevelMusicNr(); char *curr_music = getCurrentlyPlayingMusicFilename(); @@ -14595,20 +14595,20 @@ static void FadeLevelMusic() FadeMusic(); } -void FadeLevelSoundsAndMusic() +void FadeLevelSoundsAndMusic(void) { FadeLevelSounds(); FadeLevelMusic(); } -static void PlayLevelMusic() +static void PlayLevelMusic(void) { int music_nr = getLevelMusicNr(); char *curr_music = getCurrentlyPlayingMusicFilename(); char *next_music = getMusicInfoEntryFilename(music_nr); if (!strEqual(curr_music, next_music)) - PlayMusic(music_nr); + PlayMusicLoop(music_nr); } void PlayLevelSound_EM(int xx, int yy, int element_em, int sample) @@ -14923,11 +14923,9 @@ void RequestQuitGameExt(boolean skip_request, boolean quick_quit, char *message) if (!skip_request) CloseDoor(DOOR_CLOSE_1); -#if defined(NETWORK_AVALIABLE) - if (options.network) + if (network.enabled) SendToServer_StopPlaying(NETWORK_STOP_BY_PLAYER); else -#endif { if (quick_quit) FadeSkipNextFadeIn(); @@ -14958,6 +14956,22 @@ void RequestQuitGame(boolean ask_if_really_quit) "Do you really want to quit the game?"); } +void RequestRestartGame(char *message) +{ + game.restart_game_message = NULL; + + if (Request(message, REQ_ASK | REQ_STAY_CLOSED)) + { + StartGameActions(network.enabled, setup.autorecord, level.random_seed); + } + else + { + SetGameStatus(GAME_MODE_MAIN); + + DrawMainMenu(); + } +} + /* ------------------------------------------------------------------------- */ /* random generator functions */ @@ -15004,7 +15018,7 @@ static struct EngineSnapshotInfo engine_snapshot_rnd; static char *snapshot_level_identifier = NULL; static int snapshot_level_nr = -1; -static void SaveEngineSnapshotValues_RND() +static void SaveEngineSnapshotValues_RND(void) { static int belt_base_active_element[4] = { @@ -15043,7 +15057,7 @@ static void SaveEngineSnapshotValues_RND() } } -static void LoadEngineSnapshotValues_RND() +static void LoadEngineSnapshotValues_RND(void) { unsigned int num_random_calls = game.num_random_calls; int i, j; @@ -15089,7 +15103,7 @@ static void LoadEngineSnapshotValues_RND() } } -void FreeEngineSnapshotSingle() +void FreeEngineSnapshotSingle(void) { FreeSnapshotSingle(); @@ -15097,12 +15111,12 @@ void FreeEngineSnapshotSingle() snapshot_level_nr = -1; } -void FreeEngineSnapshotList() +void FreeEngineSnapshotList(void) { FreeSnapshotList(); } -ListNode *SaveEngineSnapshotBuffers() +static ListNode *SaveEngineSnapshotBuffers(void) { ListNode *buffers = NULL; @@ -15211,7 +15225,7 @@ ListNode *SaveEngineSnapshotBuffers() return buffers; } -void SaveEngineSnapshotSingle() +void SaveEngineSnapshotSingle(void) { ListNode *buffers = SaveEngineSnapshotBuffers(); @@ -15223,7 +15237,7 @@ void SaveEngineSnapshotSingle() snapshot_level_nr = level_nr; } -boolean CheckSaveEngineSnapshotToList() +boolean CheckSaveEngineSnapshotToList(void) { boolean save_snapshot = ((game.snapshot.mode == SNAPSHOT_MODE_EVERY_STEP) || @@ -15239,7 +15253,7 @@ boolean CheckSaveEngineSnapshotToList() return save_snapshot; } -void SaveEngineSnapshotToList() +void SaveEngineSnapshotToList(void) { if (game.snapshot.mode == SNAPSHOT_MODE_OFF || tape.quick_resume) @@ -15251,14 +15265,14 @@ void SaveEngineSnapshotToList() SaveSnapshotToList(buffers); } -void SaveEngineSnapshotToListInitial() +void SaveEngineSnapshotToListInitial(void) { FreeEngineSnapshotList(); SaveEngineSnapshotToList(); } -void LoadEngineSnapshotValues() +static void LoadEngineSnapshotValues(void) { /* restore special values from snapshot structure */ @@ -15268,38 +15282,38 @@ void LoadEngineSnapshotValues() LoadEngineSnapshotValues_EM(); if (level.game_engine_type == GAME_ENGINE_TYPE_SP) LoadEngineSnapshotValues_SP(); - if (level.game_engine_type == GAME_ENGINE_TYPE_SP) + if (level.game_engine_type == GAME_ENGINE_TYPE_MM) LoadEngineSnapshotValues_MM(); } -void LoadEngineSnapshotSingle() +void LoadEngineSnapshotSingle(void) { LoadSnapshotSingle(); LoadEngineSnapshotValues(); } -void LoadEngineSnapshot_Undo(int steps) +static void LoadEngineSnapshot_Undo(int steps) { LoadSnapshotFromList_Older(steps); LoadEngineSnapshotValues(); } -void LoadEngineSnapshot_Redo(int steps) +static void LoadEngineSnapshot_Redo(int steps) { LoadSnapshotFromList_Newer(steps); LoadEngineSnapshotValues(); } -boolean CheckEngineSnapshotSingle() +boolean CheckEngineSnapshotSingle(void) { return (strEqual(snapshot_level_identifier, leveldir_current->identifier) && snapshot_level_nr == level_nr); } -boolean CheckEngineSnapshotList() +boolean CheckEngineSnapshotList(void) { return CheckSnapshotList(); } @@ -15404,13 +15418,14 @@ static struct } }; -void CreateGameButtons() +void CreateGameButtons(void) { int i; for (i = 0; i < NUM_GAME_BUTTONS; i++) { - struct GraphicInfo *gfx = &graphic_info[gamebutton_info[i].graphic]; + int graphic = gamebutton_info[i].graphic; + struct GraphicInfo *gfx = &graphic_info[graphic]; struct XY *pos = gamebutton_info[i].pos; struct GadgetInfo *gi; int button_type; @@ -15464,6 +15479,7 @@ void CreateGameButtons() } gi = CreateGadget(GDI_CUSTOM_ID, id, + GDI_IMAGE_ID, graphic, GDI_INFO_TEXT, gamebutton_info[i].infotext, GDI_X, base_x + GDI_ACTIVE_POS(pos->x), GDI_Y, base_y + GDI_ACTIVE_POS(pos->y), @@ -15488,7 +15504,7 @@ void CreateGameButtons() } } -void FreeGameButtons() +void FreeGameButtons(void) { int i; @@ -15507,7 +15523,7 @@ static void UnmapGameButtonsAtSamePosition(int id) UnmapGadget(game_gadget[i]); } -static void UnmapGameButtonsAtSamePosition_All() +static void UnmapGameButtonsAtSamePosition_All(void) { if (setup.show_snapshot_buttons) { @@ -15540,7 +15556,7 @@ static void MapGameButtonsAtSamePosition(int id) UnmapGameButtonsAtSamePosition_All(); } -void MapUndoRedoButtons() +void MapUndoRedoButtons(void) { UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_UNDO); UnmapGameButtonsAtSamePosition(GAME_CTRL_ID_REDO); @@ -15551,7 +15567,7 @@ void MapUndoRedoButtons() ModifyGadget(game_gadget[GAME_CTRL_ID_PAUSE2], GDI_CHECKED, TRUE, GDI_END); } -void UnmapUndoRedoButtons() +void UnmapUndoRedoButtons(void) { UnmapGadget(game_gadget[GAME_CTRL_ID_UNDO]); UnmapGadget(game_gadget[GAME_CTRL_ID_REDO]); @@ -15562,7 +15578,7 @@ void UnmapUndoRedoButtons() ModifyGadget(game_gadget[GAME_CTRL_ID_PAUSE2], GDI_CHECKED, FALSE, GDI_END); } -void MapGameButtonsExt(boolean on_tape) +static void MapGameButtonsExt(boolean on_tape) { int i; @@ -15577,7 +15593,7 @@ void MapGameButtonsExt(boolean on_tape) RedrawGameButtons(); } -void UnmapGameButtonsExt(boolean on_tape) +static void UnmapGameButtonsExt(boolean on_tape) { int i; @@ -15586,7 +15602,7 @@ void UnmapGameButtonsExt(boolean on_tape) UnmapGadget(game_gadget[i]); } -void RedrawGameButtonsExt(boolean on_tape) +static void RedrawGameButtonsExt(boolean on_tape) { int i; @@ -15598,7 +15614,7 @@ void RedrawGameButtonsExt(boolean on_tape) redraw_mask &= ~REDRAW_ALL; } -void SetGadgetState(struct GadgetInfo *gi, boolean state) +static void SetGadgetState(struct GadgetInfo *gi, boolean state) { if (gi == NULL) return; @@ -15606,7 +15622,7 @@ void SetGadgetState(struct GadgetInfo *gi, boolean state) gi->checked = state; } -void RedrawSoundButtonGadget(int id) +static void RedrawSoundButtonGadget(int id) { int id2 = (id == SOUND_CTRL_ID_MUSIC ? SOUND_CTRL_ID_PANEL_MUSIC : id == SOUND_CTRL_ID_LOOPS ? SOUND_CTRL_ID_PANEL_LOOPS : @@ -15620,37 +15636,37 @@ void RedrawSoundButtonGadget(int id) RedrawGadget(game_gadget[id2]); } -void MapGameButtons() +void MapGameButtons(void) { MapGameButtonsExt(FALSE); } -void UnmapGameButtons() +void UnmapGameButtons(void) { UnmapGameButtonsExt(FALSE); } -void RedrawGameButtons() +void RedrawGameButtons(void) { RedrawGameButtonsExt(FALSE); } -void MapGameButtonsOnTape() +void MapGameButtonsOnTape(void) { MapGameButtonsExt(TRUE); } -void UnmapGameButtonsOnTape() +void UnmapGameButtonsOnTape(void) { UnmapGameButtonsExt(TRUE); } -void RedrawGameButtonsOnTape() +void RedrawGameButtonsOnTape(void) { RedrawGameButtonsExt(TRUE); } -void GameUndoRedoExt() +static void GameUndoRedoExt(void) { ClearPlayerAction(); @@ -15667,7 +15683,7 @@ void GameUndoRedoExt() BackToFront(); } -void GameUndo(int steps) +static void GameUndo(int steps) { if (!CheckEngineSnapshotList()) return; @@ -15677,7 +15693,7 @@ void GameUndo(int steps) GameUndoRedoExt(); } -void GameRedo(int steps) +static void GameRedo(int steps) { if (!CheckEngineSnapshotList()) return; @@ -15715,14 +15731,12 @@ static void HandleGameButtonsExt(int id, int button) case GAME_CTRL_ID_PAUSE: case GAME_CTRL_ID_PAUSE2: case GAME_CTRL_ID_PANEL_PAUSE: - if (options.network && game_status == GAME_MODE_PLAYING) + if (network.enabled && game_status == GAME_MODE_PLAYING) { -#if defined(NETWORK_AVALIABLE) if (tape.pausing) SendToServer_ContinuePlaying(); else SendToServer_PausePlaying(); -#endif } else TapeTogglePause(TAPE_TOGGLE_MANUAL); @@ -15735,15 +15749,13 @@ static void HandleGameButtonsExt(int id, int button) case GAME_CTRL_ID_PANEL_PLAY: if (game_status == GAME_MODE_MAIN) { - StartGameActions(options.network, setup.autorecord, level.random_seed); + StartGameActions(network.enabled, setup.autorecord, level.random_seed); } else if (tape.pausing) { -#if defined(NETWORK_AVALIABLE) - if (options.network) + if (network.enabled) SendToServer_ContinuePlaying(); else -#endif TapeTogglePause(TAPE_TOGGLE_MANUAL | TAPE_TOGGLE_PLAY_PAUSE); } break;