X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=f8b9a085891166c4db14cdb306e9546810c87800;hb=013fed105fe1ac6cdd887bac04733a73f66599a3;hp=717ea8d2f263fd0d3ab1d3d99677ac860a469acc;hpb=3da9c6a38081401af8c47d78330a199104f9ad2f;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index 717ea8d2..f8b9a085 100644 --- a/src/game.c +++ b/src/game.c @@ -4228,7 +4228,8 @@ void InitGame() #else for (i = 0; i < MAX_PLAYERS; i++) { - if (stored_player[i].active && !tape.player_participates[i]) + if (stored_player[i].active && + !tape.player_participates[i]) { struct PlayerInfo *player = &stored_player[i]; int jx = player->jx, jy = player->jy; @@ -4467,6 +4468,13 @@ void InitGame() /* blit playfield from scroll buffer to normal back buffer for fading in */ BlitScreenToBitmap_EM(backbuffer); } + else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) + { + InitGameEngine_SP(); + + /* blit playfield from scroll buffer to normal back buffer for fading in */ + BlitScreenToBitmap_SP(backbuffer); + } else { DrawLevel(); @@ -5502,8 +5510,6 @@ void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir, if (quick_relocation) { - int offset = game.scroll_delay_value; - if (!IN_VIS_FIELD(SCREENX(x), SCREENY(y)) || center_screen) { if (!level.shifted_relocation || center_screen) @@ -5544,8 +5550,47 @@ void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir, } else { +#if 1 + if (!level.shifted_relocation || center_screen) + { + /* quick relocation (without scrolling), with centering of screen */ + + scroll_x = (x < SBX_Left + MIDPOSX ? SBX_Left : + x > SBX_Right + MIDPOSX ? SBX_Right : + x - MIDPOSX); + + scroll_y = (y < SBY_Upper + MIDPOSY ? SBY_Upper : + y > SBY_Lower + MIDPOSY ? SBY_Lower : + y - MIDPOSY); + } + else + { + /* quick relocation (without scrolling), but do not center screen */ + + int center_scroll_x = (old_x < SBX_Left + MIDPOSX ? SBX_Left : + old_x > SBX_Right + MIDPOSX ? SBX_Right : + old_x - MIDPOSX); + + int center_scroll_y = (old_y < SBY_Upper + MIDPOSY ? SBY_Upper : + old_y > SBY_Lower + MIDPOSY ? SBY_Lower : + old_y - MIDPOSY); + + int offset_x = x + (scroll_x - center_scroll_x); + int offset_y = y + (scroll_y - center_scroll_y); + + scroll_x = (offset_x < SBX_Left + MIDPOSX ? SBX_Left : + offset_x > SBX_Right + MIDPOSX ? SBX_Right : + offset_x - MIDPOSX); + + scroll_y = (offset_y < SBY_Upper + MIDPOSY ? SBY_Upper : + offset_y > SBY_Lower + MIDPOSY ? SBY_Lower : + offset_y - MIDPOSY); + } +#else /* quick relocation (without scrolling), inside visible screen area */ + int offset = game.scroll_delay_value; + if ((move_dir == MV_LEFT && scroll_x > x - MIDPOSX + offset) || (move_dir == MV_RIGHT && scroll_x < x - MIDPOSX - offset)) scroll_x = x - MIDPOSX + (scroll_x < x - MIDPOSX ? -offset : +offset); @@ -5561,6 +5606,7 @@ void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir, /* don't scroll over playfield boundaries */ if (scroll_y < SBY_Upper || scroll_y > SBY_Lower) scroll_y = (scroll_y < SBY_Upper ? SBY_Upper : SBY_Lower); +#endif } RedrawPlayfield(TRUE, 0,0,0,0); @@ -5726,10 +5772,19 @@ void RelocatePlayer(int jx, int jy, int el_player_raw) Feld[jx][jy] = el_player; InitPlayerField(jx, jy, el_player, TRUE); + /* "InitPlayerField()" above sets Feld[jx][jy] to EL_EMPTY, but it may be + possible that the relocation target field did not contain a player element, + but a walkable element, to which the new player was relocated -- in this + case, restore that (already initialized!) element on the player field */ if (!ELEM_IS_PLAYER(element)) /* player may be set on walkable element */ { - Feld[jx][jy] = element; + Feld[jx][jy] = element; /* restore previously existing element */ +#if 0 + /* !!! do not initialize already initialized element a second time !!! */ + /* (this causes at least problems with "element creation" CE trigger for + already existing elements, and existing Sokoban fields counted twice) */ InitField(jx, jy, FALSE); +#endif } /* only visually relocate centered player */ @@ -11937,7 +11992,16 @@ static byte PlayerActions(struct PlayerInfo *player, byte player_action) if (tape.single_step && tape.recording && !tape.pausing) { +#if 1 + /* as it is called "single step mode", just return to pause mode when the + player stopped moving after one tile (or never starts moving at all) */ + if (!player->is_moving) +#else + /* this is buggy: there are quite some cases where the single step mode + does not return to pause mode (like pushing things that don't move + or simply by trying to run against a wall) */ if (button1 || (dropped && !moved)) +#endif { TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); SnapField(player, 0, 0); /* stop snapping */ @@ -11974,6 +12038,7 @@ static void CheckLevelTime() { 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 */ @@ -11991,6 +12056,21 @@ static void CheckLevelTime() 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_info.LevelSolved && + !game_sp_info.GameOver) /* game won */ + { + PlayerWins(local_player); + + game_sp_info.GameOver = TRUE; + + AllPlayersGone = TRUE; + } + + if (game_sp_info.GameOver) /* game lost */ + AllPlayersGone = TRUE; + } if (TimeFrames >= FRAMES_PER_SECOND) { @@ -12168,6 +12248,7 @@ void GameActions() if (game.restart_level) StartGameActions(options.network, 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 */ @@ -12185,6 +12266,21 @@ void GameActions() 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_info.LevelSolved && + !game_sp_info.GameOver) /* game won */ + { + PlayerWins(local_player); + + game_sp_info.GameOver = TRUE; + + AllPlayersGone = TRUE; + } + + if (game_sp_info.GameOver) /* game lost */ + AllPlayersGone = TRUE; + } if (local_player->LevelSolved && !local_player->LevelSolved_GameEnd) GameWon(); @@ -12246,15 +12342,6 @@ void GameActions() game.set_centered_player = TRUE; } -#if 0 /* USE_NEW_PLAYER_ASSIGNMENTS */ - for (i = 0; i < MAX_PLAYERS; i++) - { - summarized_player_action |= stored_player[i].mapped_action; - - if (!network_playing) - stored_player[i].effective_action = stored_player[i].mapped_action; - } -#else for (i = 0; i < MAX_PLAYERS; i++) { summarized_player_action |= stored_player[i].action; @@ -12262,7 +12349,6 @@ void GameActions() if (!network_playing) stored_player[i].effective_action = stored_player[i].action; } -#endif #if defined(NETWORK_AVALIABLE) if (network_playing) @@ -12279,25 +12365,13 @@ void GameActions() (i == game.centered_player_nr ? summarized_player_action : 0); } -#if 0 /* USE_NEW_PLAYER_ASSIGNMENTS */ - if (recorded_player_action != NULL) - for (i = 0; i < MAX_PLAYERS; i++) - stored_player[i].effective_action = - recorded_player_action[map_player_action[i]]; -#else if (recorded_player_action != NULL) for (i = 0; i < MAX_PLAYERS; i++) - stored_player[i].effective_action = - recorded_player_action[i]; -#endif + stored_player[i].effective_action = recorded_player_action[i]; for (i = 0; i < MAX_PLAYERS; i++) { -#if 0 /* USE_NEW_PLAYER_ASSIGNMENTS */ - tape_action[i] = stored_player[i].action; -#else tape_action[i] = stored_player[i].effective_action; -#endif /* (this can only happen in the R'n'D game engine) */ if (tape.recording && tape_action[i] && !tape.player_participates[i]) @@ -12310,39 +12384,24 @@ void GameActions() #if USE_NEW_PLAYER_ASSIGNMENTS { -#if 0 - - for (i = 0; i < MAX_PLAYERS; i++) - stored_player[i].mapped_action = stored_player[map_player_action[i]].action; - -#else - -#if 1 - byte unmapped_action[MAX_PLAYERS]; - - for (i = 0; i < MAX_PLAYERS; i++) - unmapped_action[i] = stored_player[i].effective_action; + byte mapped_action[MAX_PLAYERS]; for (i = 0; i < MAX_PLAYERS; i++) - stored_player[i].effective_action = unmapped_action[map_player_action[i]]; -#endif + mapped_action[i] = stored_player[map_player_action[i]].effective_action; -#if 0 for (i = 0; i < MAX_PLAYERS; i++) - printf("::: %d: %d [%d]\n", i, stored_player[i].effective_action, - map_player_action[i]); -#endif -#endif + stored_player[i].effective_action = mapped_action[i]; } -#else - for (i = 0; i < MAX_PLAYERS; i++) - stored_player[i].mapped_action = stored_player[i].action; #endif if (level.game_engine_type == GAME_ENGINE_TYPE_EM) { GameActions_EM_Main(); } + else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) + { + GameActions_SP_Main(); + } else { GameActions_RND(); @@ -12365,6 +12424,22 @@ void GameActions_EM_Main() AdvanceFrameAndPlayerCounters(-1); /* advance counters for all players */ } +void GameActions_SP_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_SP(effective_action, warp_mode); + + CheckLevelTime(); + + AdvanceFrameAndPlayerCounters(-1); /* advance counters for all players */ +} + void GameActions_RND() { int magic_wall_x = 0, magic_wall_y = 0; @@ -15323,8 +15398,13 @@ static int DigField(struct PlayerInfo *player, PlayLevelSoundElementAction(nextx, nexty, EL_SOKOBAN_FIELD_EMPTY, ACTION_FILLING); +#if 1 + if (local_player->sokobanfields_still_needed == 0 && + (game.emulation == EMU_SOKOBAN || level.auto_exit_sokoban)) +#else if (local_player->sokobanfields_still_needed == 0 && game.emulation == EMU_SOKOBAN) +#endif { PlayerWins(player);