X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=98751de41aaeca52086e4695ff2c67da64730a98;hb=c74a890afba46c41f6ba6ef691bc89da0dd0135c;hp=1843274873a34c4b8778dcd982ea540681b63016;hpb=f772f882546ab982dc61074f298d6115c9909f32;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index 18432748..98751de4 100644 --- a/src/game.c +++ b/src/game.c @@ -333,6 +333,32 @@ static void PlayLevelMusic(); static void MapGameButtons(); static void HandleGameButtons(struct GadgetInfo *); +int AmoebeNachbarNr(int, int); +void AmoebeUmwandeln(int, int); +void ContinueMoving(int, int); +void Bang(int, int); +void InitMovDir(int, int); +void InitAmoebaNr(int, int); +int NewHiScore(void); + +void TestIfGoodThingHitsBadThing(int, int, int); +void TestIfBadThingHitsGoodThing(int, int, int); +void TestIfPlayerTouchesBadThing(int, int); +void TestIfPlayerRunsIntoBadThing(int, int, int); +void TestIfBadThingTouchesPlayer(int, int); +void TestIfBadThingRunsIntoPlayer(int, int, int); +void TestIfFriendTouchesBadThing(int, int); +void TestIfBadThingTouchesFriend(int, int); +void TestIfBadThingTouchesOtherBadThing(int, int); + +void KillPlayer(struct PlayerInfo *); +void BuryPlayer(struct PlayerInfo *); +void RemovePlayer(struct PlayerInfo *); + +boolean SnapField(struct PlayerInfo *, int, int); +boolean DropElement(struct PlayerInfo *); + + static struct GadgetInfo *game_gadget[NUM_GAME_BUTTONS]; @@ -690,6 +716,18 @@ static int playfield_scan_delta_y = 1; (x) >= 0 && (x) <= lev_fieldx - 1; \ (x) += playfield_scan_delta_x) \ +#ifdef DEBUG +void DEBUG_SetMaximumDynamite() +{ + int i; + + for (i = 0; i < MAX_INVENTORY_SIZE; i++) + if (local_player->inventory_size < MAX_INVENTORY_SIZE) + local_player->inventory_element[local_player->inventory_size++] = + EL_DYNAMITE; +} +#endif + static void InitPlayfieldScanModeVars() { if (game.use_reverse_scan_direction) @@ -8847,10 +8885,12 @@ static void SetPlayerWaiting(struct PlayerInfo *player, boolean is_waiting) /* special case for sleeping Murphy when leaning against non-free tile */ if (!IN_LEV_FIELD(player->jx - 1, player->jy) || - Feld[player->jx - 1][player->jy] != EL_EMPTY) + (Feld[player->jx - 1][player->jy] != EL_EMPTY && + !IS_MOVING(player->jx - 1, player->jy))) move_dir = MV_LEFT; else if (!IN_LEV_FIELD(player->jx + 1, player->jy) || - Feld[player->jx + 1][player->jy] != EL_EMPTY) + (Feld[player->jx + 1][player->jy] != EL_EMPTY && + !IS_MOVING(player->jx + 1, player->jy))) move_dir = MV_RIGHT; else player->is_sleeping = FALSE; @@ -9011,6 +9051,79 @@ static byte PlayerActions(struct PlayerInfo *player, byte player_action) } } +static void CheckLevelTime() +{ + int i; + + if (level.game_engine_type == GAME_ENGINE_TYPE_EM) + { + if (level.native_em_level->lev->home == 0) /* all players at home */ + { + local_player->LevelSolved = TRUE; + 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; + } + + if (TimeFrames >= FRAMES_PER_SECOND) + { + TimeFrames = 0; + TapeTime++; + + for (i = 0; i < MAX_PLAYERS; i++) + { + struct PlayerInfo *player = &stored_player[i]; + + if (SHIELD_ON(player)) + { + player->shield_normal_time_left--; + + if (player->shield_deadly_time_left > 0) + player->shield_deadly_time_left--; + } + } + + if (!level.use_step_counter) + { + TimePlayed++; + + if (TimeLeft > 0) + { + TimeLeft--; + + if (TimeLeft <= 10 && setup.time_limit) + PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MIDDLE); + + DrawGameValue_Time(TimeLeft); + + if (!TimeLeft && setup.time_limit) + { + if (level.game_engine_type == GAME_ENGINE_TYPE_EM) + level.native_em_level->lev->killed_out_of_time = TRUE; + else + for (i = 0; i < MAX_PLAYERS; i++) + KillPlayer(&stored_player[i]); + } + } + else if (level.time == 0 && !AllPlayersGone) /* level w/o time limit */ + DrawGameValue_Time(TimePlayed); + + level.native_em_level->lev->time = + (level.time == 0 ? TimePlayed : TimeLeft); + } + + if (tape.recording || tape.playing) + DrawVideoDisplay(VIDEO_STATE_TIME_ON, TapeTime); + } +} + void AdvanceFrameAndPlayerCounters(int player_nr) { int i; @@ -9062,106 +9175,86 @@ void AdvanceFrameAndPlayerCounters(int player_nr) } } -void GameActions() +void StartGameActions(boolean init_network_game, boolean record_tape, + long random_seed) { - static unsigned long game_frame_delay = 0; - unsigned long game_frame_delay_value; - int magic_wall_x = 0, magic_wall_y = 0; - int i, x, y, element, graphic; - byte *recorded_player_action; - byte summarized_player_action = 0; - byte tape_action[MAX_PLAYERS]; +#if 1 + unsigned long new_random_seed = InitRND(random_seed); - if (game_status != GAME_MODE_PLAYING) - return; + if (record_tape) + TapeStartRecording(new_random_seed); +#else + if (record_tape) + TapeStartRecording(random_seed); +#endif - game_frame_delay_value = - (tape.playing && tape.fast_forward ? FfwdFrameDelay : GameFrameDelay); +#if defined(NETWORK_AVALIABLE) + if (init_network_game) + { + SendToServer_StartPlaying(); - if (tape.playing && tape.warp_forward && !tape.pausing) - game_frame_delay_value = 0; + return; + } +#endif - /* ---------- main game synchronization point ---------- */ + StopAnimation(); - WaitUntilDelayReached(&game_frame_delay, game_frame_delay_value); + game_status = GAME_MODE_PLAYING; - InitPlayfieldScanModeVars(); +#if 0 + InitRND(random_seed); +#endif - if (game.set_centered_player) - { - boolean all_players_fit_to_screen = checkIfAllPlayersFitToScreen_RND(); + InitGame(); +} - /* switching to "all players" only possible if all players fit to screen */ - if (game.centered_player_nr_next == -1 && !all_players_fit_to_screen) - { - game.centered_player_nr_next = game.centered_player_nr; - game.set_centered_player = FALSE; - } +void GameActions() +{ + static unsigned long game_frame_delay = 0; + unsigned long game_frame_delay_value; + byte *recorded_player_action; + byte summarized_player_action = 0; + byte tape_action[MAX_PLAYERS]; + int i; - /* do not switch focus to non-existing (or non-active) player */ - if (game.centered_player_nr_next >= 0 && - !stored_player[game.centered_player_nr_next].active) - { - game.centered_player_nr_next = game.centered_player_nr; - game.set_centered_player = FALSE; - } - } + if (game.restart_level) + StartGameActions(options.network, setup.autorecord, NEW_RANDOMIZE); - if (game.set_centered_player && - ScreenMovPos == 0) /* screen currently aligned at tile position */ + if (level.game_engine_type == GAME_ENGINE_TYPE_EM) { -#if 0 - struct PlayerInfo *player; - int player_nr = game.centered_player_nr_next; -#endif - int sx, sy; - - if (game.centered_player_nr_next == -1) - { - setScreenCenteredToAllPlayers(&sx, &sy); - } - else + if (level.native_em_level->lev->home == 0) /* all players at home */ { - sx = stored_player[game.centered_player_nr_next].jx; - sy = stored_player[game.centered_player_nr_next].jy; + local_player->LevelSolved = TRUE; + AllPlayersGone = TRUE; + + level.native_em_level->lev->home = -1; } -#if 0 - player = &stored_player[player_nr]; + 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; + } - if (!player->active) - game.centered_player_nr_next = game.centered_player_nr; + if (local_player->LevelSolved) + GameWon(); - sx = player->jx; - sy = player->jy; -#endif + if (AllPlayersGone && !TAPE_IS_STOPPED(tape)) + TapeStop(); -#if 0 - if (game.centered_player_nr != game.centered_player_nr_next) -#endif - { -#if 1 - DrawRelocateScreen(sx, sy, MV_NONE, TRUE, setup.quick_switch); -#else - DrawRelocatePlayer(player, setup.quick_switch); -#endif + if (game_status != GAME_MODE_PLAYING) /* status might have changed */ + return; - game.centered_player_nr = game.centered_player_nr_next; - } + game_frame_delay_value = + (tape.playing && tape.fast_forward ? FfwdFrameDelay : GameFrameDelay); - game.set_centered_player = FALSE; - } + if (tape.playing && tape.warp_forward && !tape.pausing) + game_frame_delay_value = 0; -#if USE_ONE_MORE_CHANGE_PER_FRAME - if (game.engine_version >= VERSION_IDENT(3,2,0,7)) - { - SCAN_PLAYFIELD(x, y) - { - ChangeCount[x][y] = 0; - ChangeEvent[x][y] = -1; - } - } -#endif + /* ---------- main game synchronization point ---------- */ + + WaitUntilDelayReached(&game_frame_delay, game_frame_delay_value); if (network_playing && !network_player_action_received) { @@ -9185,11 +9278,11 @@ void GameActions() recorded_player_action = (tape.playing ? TapePlayAction() : NULL); -#if 1 - /* !!! CHECK THIS (tape.pausing is always FALSE here!) !!! */ - if (recorded_player_action == NULL && tape.pausing) - return; -#endif + if (tape.set_centered_player) + { + game.centered_player_nr_next = tape.centered_player_nr_next; + game.set_centered_player = TRUE; + } for (i = 0; i < MAX_PLAYERS; i++) { @@ -9207,6 +9300,13 @@ void GameActions() if (!options.network && !setup.team_mode) local_player->effective_action = summarized_player_action; + if (setup.team_mode && setup.input_on_focus && game.centered_player_nr != -1) + { + for (i = 0; i < MAX_PLAYERS; i++) + stored_player[i].effective_action = + (i == game.centered_player_nr ? summarized_player_action : 0); + } + if (recorded_player_action != NULL) for (i = 0; i < MAX_PLAYERS; i++) stored_player[i].effective_action = recorded_player_action[i]; @@ -9215,14 +9315,102 @@ void GameActions() { tape_action[i] = stored_player[i].effective_action; + /* (this can only happen in the R'n'D game engine) */ if (tape.recording && tape_action[i] && !tape.player_participates[i]) tape.player_participates[i] = TRUE; /* player just appeared from CE */ } - /* only save actions from input devices, but not programmed actions */ + /* only record actions from input devices, but not programmed actions */ if (tape.recording) TapeRecordAction(tape_action); + if (level.game_engine_type == GAME_ENGINE_TYPE_EM) + { + GameActions_EM_Main(); + } + else + { + GameActions_RND(); + } +} + +void GameActions_EM_Main() +{ + byte effective_action[MAX_PLAYERS]; + boolean warp_mode = (tape.playing && tape.warp_forward && !tape.pausing); + int i; + + for (i = 0; i < MAX_PLAYERS; i++) + effective_action[i] = stored_player[i].effective_action; + + GameActions_EM(effective_action, warp_mode); + + CheckLevelTime(); + + AdvanceFrameAndPlayerCounters(-1); /* advance counters for all players */ +} + +void GameActions_RND() +{ + int magic_wall_x = 0, magic_wall_y = 0; + int i, x, y, element, graphic; + + InitPlayfieldScanModeVars(); + +#if USE_ONE_MORE_CHANGE_PER_FRAME + if (game.engine_version >= VERSION_IDENT(3,2,0,7)) + { + SCAN_PLAYFIELD(x, y) + { + ChangeCount[x][y] = 0; + ChangeEvent[x][y] = -1; + } + } +#endif + +#if 1 + if (game.set_centered_player) + { + boolean all_players_fit_to_screen = checkIfAllPlayersFitToScreen_RND(); + + /* switching to "all players" only possible if all players fit to screen */ + if (game.centered_player_nr_next == -1 && !all_players_fit_to_screen) + { + game.centered_player_nr_next = game.centered_player_nr; + game.set_centered_player = FALSE; + } + + /* do not switch focus to non-existing (or non-active) player */ + if (game.centered_player_nr_next >= 0 && + !stored_player[game.centered_player_nr_next].active) + { + game.centered_player_nr_next = game.centered_player_nr; + game.set_centered_player = FALSE; + } + } + + if (game.set_centered_player && + ScreenMovPos == 0) /* screen currently aligned at tile position */ + { + int sx, sy; + + if (game.centered_player_nr_next == -1) + { + setScreenCenteredToAllPlayers(&sx, &sy); + } + else + { + sx = stored_player[game.centered_player_nr_next].jx; + sy = stored_player[game.centered_player_nr_next].jy; + } + + DrawRelocateScreen(sx, sy, MV_NONE, TRUE, setup.quick_switch); + + game.centered_player_nr = game.centered_player_nr_next; + game.set_centered_player = FALSE; + } +#endif + for (i = 0; i < MAX_PLAYERS; i++) { int actual_player_action = stored_player[i].effective_action; @@ -9701,48 +9889,7 @@ void GameActions() } } - if (TimeFrames >= FRAMES_PER_SECOND) - { - TimeFrames = 0; - TapeTime++; - - for (i = 0; i < MAX_PLAYERS; i++) - { - struct PlayerInfo *player = &stored_player[i]; - - if (SHIELD_ON(player)) - { - player->shield_normal_time_left--; - - if (player->shield_deadly_time_left > 0) - player->shield_deadly_time_left--; - } - } - - if (!level.use_step_counter) - { - TimePlayed++; - - if (TimeLeft > 0) - { - TimeLeft--; - - if (TimeLeft <= 10 && setup.time_limit) - PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MIDDLE); - - DrawGameValue_Time(TimeLeft); - - if (!TimeLeft && setup.time_limit) - for (i = 0; i < MAX_PLAYERS; i++) - KillPlayer(&stored_player[i]); - } - else if (level.time == 0 && !AllPlayersGone) /* level w/o time limit */ - DrawGameValue_Time(TimePlayed); - } - - if (tape.recording || tape.playing) - DrawVideoDisplay(VIDEO_STATE_TIME_ON, TapeTime); - } + CheckLevelTime(); DrawAllPlayers(); PlayAllPlayersSound();