X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=d19831759e264f2419d09ad36316986eefa617ae;hb=123c5a87fa9cf6d9759ed7911d3544f05afdd11c;hp=eb115cb3978c1e6e27da7a57d7a196f9b683b1b2;hpb=79d7ca29718d025ed0b131bf5389685fe9b941c4;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index eb115cb3..d1983175 100644 --- a/src/game.c +++ b/src/game.c @@ -2221,17 +2221,25 @@ void UpdateGameControlValues() local_player->LevelSolved_CountingTime : level.game_engine_type == GAME_ENGINE_TYPE_EM ? level.native_em_level->lev->time : + level.game_engine_type == GAME_ENGINE_TYPE_SP ? + level.native_sp_level->game_sp->time_played : level.time == 0 ? TimePlayed : TimeLeft); int score = (local_player->LevelSolved ? local_player->LevelSolved_CountingScore : level.game_engine_type == GAME_ENGINE_TYPE_EM ? level.native_em_level->lev->score : + level.game_engine_type == GAME_ENGINE_TYPE_SP ? + level.native_sp_level->game_sp->score : local_player->score); int gems = (level.game_engine_type == GAME_ENGINE_TYPE_EM ? level.native_em_level->lev->required : + level.game_engine_type == GAME_ENGINE_TYPE_SP ? + level.native_sp_level->game_sp->infotrons_still_needed : local_player->gems_still_needed); int exit_closed = (level.game_engine_type == GAME_ENGINE_TYPE_EM ? level.native_em_level->lev->required > 0 : + level.game_engine_type == GAME_ENGINE_TYPE_SP ? + level.native_sp_level->game_sp->infotrons_still_needed > 0 : local_player->gems_still_needed > 0 || local_player->sokobanfields_still_needed > 0 || local_player->lights_still_needed > 0); @@ -2253,6 +2261,10 @@ void UpdateGameControlValues() { for (i = 0; i < MAX_PLAYERS; i++) { + /* only one player in Supaplex game engine */ + if (level.game_engine_type == GAME_ENGINE_TYPE_SP && i > 0) + break; + for (k = 0; k < MAX_NUM_KEYS; k++) { if (level.game_engine_type == GAME_ENGINE_TYPE_EM) @@ -2269,6 +2281,9 @@ void UpdateGameControlValues() if (level.game_engine_type == GAME_ENGINE_TYPE_EM) game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value += level.native_em_level->ply[i]->dynamite; + else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) + game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value += + level.native_sp_level->game_sp->red_disk_count; else game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value += stored_player[i].inventory_size; @@ -2301,6 +2316,9 @@ void UpdateGameControlValues() if (level.game_engine_type == GAME_ENGINE_TYPE_EM) game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value += level.native_em_level->ply[player_nr]->dynamite; + else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) + game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value += + level.native_sp_level->game_sp->red_disk_count; else game_panel_controls[GAME_PANEL_INVENTORY_COUNT].value += stored_player[player_nr].inventory_size; @@ -5772,10 +5790,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 */ @@ -11983,7 +12010,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 */ @@ -12020,6 +12056,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 */ @@ -12039,14 +12076,17 @@ static void CheckLevelTime() } else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) { - if (game_sp_info.LevelSolved) /* game won */ + if (game_sp.LevelSolved && + !game_sp.GameOver) /* game won */ { PlayerWins(local_player); + game_sp.GameOver = TRUE; + AllPlayersGone = TRUE; } - if (game_sp_info.GameOver) /* game lost */ + if (game_sp.GameOver) /* game lost */ AllPlayersGone = TRUE; } @@ -12226,6 +12266,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 */ @@ -12243,6 +12284,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.LevelSolved && + !game_sp.GameOver) /* game won */ + { + PlayerWins(local_player); + + game_sp.GameOver = TRUE; + + AllPlayersGone = TRUE; + } + + if (game_sp.GameOver) /* game lost */ + AllPlayersGone = TRUE; + } if (local_player->LevelSolved && !local_player->LevelSolved_GameEnd) GameWon(); @@ -15360,8 +15416,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); @@ -16370,8 +16431,6 @@ unsigned int RND(int max) /* game engine snapshot handling functions */ /* ------------------------------------------------------------------------- */ -#define ARGS_ADDRESS_AND_SIZEOF(x) (&(x)), (sizeof(x)) - struct EngineSnapshotInfo { /* runtime values for custom element collect score */ @@ -16381,32 +16440,14 @@ struct EngineSnapshotInfo int choice_pos[NUM_GROUP_ELEMENTS]; /* runtime values for belt position animations */ - int belt_graphic[4 * NUM_BELT_PARTS]; - int belt_anim_mode[4 * NUM_BELT_PARTS]; -}; - -struct EngineSnapshotNodeInfo -{ - void *buffer_orig; - void *buffer_copy; - int size; + int belt_graphic[4][NUM_BELT_PARTS]; + int belt_anim_mode[4][NUM_BELT_PARTS]; }; static struct EngineSnapshotInfo engine_snapshot_rnd; -static ListNode *engine_snapshot_list = NULL; static char *snapshot_level_identifier = NULL; static int snapshot_level_nr = -1; -void FreeEngineSnapshot() -{ - while (engine_snapshot_list != NULL) - deleteNodeFromList(&engine_snapshot_list, engine_snapshot_list->key, - checked_free); - - setString(&snapshot_level_identifier, NULL); - snapshot_level_nr = -1; -} - static void SaveEngineSnapshotValues_RND() { static int belt_base_active_element[4] = @@ -16440,8 +16481,8 @@ static void SaveEngineSnapshotValues_RND() int graphic = el2img(element); int anim_mode = graphic_info[graphic].anim_mode; - engine_snapshot_rnd.belt_graphic[i * 4 + j] = graphic; - engine_snapshot_rnd.belt_anim_mode[i * 4 + j] = anim_mode; + engine_snapshot_rnd.belt_graphic[i][j] = graphic; + engine_snapshot_rnd.belt_anim_mode[i][j] = anim_mode; } } } @@ -16469,8 +16510,8 @@ static void LoadEngineSnapshotValues_RND() { for (j = 0; j < NUM_BELT_PARTS; j++) { - int graphic = engine_snapshot_rnd.belt_graphic[i * 4 + j]; - int anim_mode = engine_snapshot_rnd.belt_anim_mode[i * 4 + j]; + int graphic = engine_snapshot_rnd.belt_graphic[i][j]; + int anim_mode = engine_snapshot_rnd.belt_anim_mode[i][j]; graphic_info[graphic].anim_mode = anim_mode; } @@ -16492,36 +16533,26 @@ static void LoadEngineSnapshotValues_RND() } } -static void SaveEngineSnapshotBuffer(void *buffer, int size) -{ - struct EngineSnapshotNodeInfo *bi = - checked_calloc(sizeof(struct EngineSnapshotNodeInfo)); - - bi->buffer_orig = buffer; - bi->buffer_copy = checked_malloc(size); - bi->size = size; - - memcpy(bi->buffer_copy, buffer, size); - - addNodeToList(&engine_snapshot_list, NULL, bi); -} - void SaveEngineSnapshot() { - FreeEngineSnapshot(); /* free previous snapshot, if needed */ - - if (level_editor_test_game) /* do not save snapshots from editor */ + /* do not save snapshots from editor */ + if (level_editor_test_game) return; + /* free previous snapshot buffers, if needed */ + FreeEngineSnapshotBuffers(); + /* copy some special values to a structure better suited for the snapshot */ SaveEngineSnapshotValues_RND(); SaveEngineSnapshotValues_EM(); + SaveEngineSnapshotValues_SP(); /* save values stored in special snapshot structure */ SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_rnd)); SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_em)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_sp)); /* save further RND engine values */ @@ -16595,7 +16626,7 @@ void SaveEngineSnapshot() snapshot_level_nr = level_nr; #if 0 - ListNode *node = engine_snapshot_list; + ListNode *node = engine_snapshot_list_rnd; int num_bytes = 0; while (node != NULL) @@ -16609,29 +16640,17 @@ void SaveEngineSnapshot() #endif } -static void LoadEngineSnapshotBuffer(struct EngineSnapshotNodeInfo *bi) -{ - memcpy(bi->buffer_orig, bi->buffer_copy, bi->size); -} - void LoadEngineSnapshot() { - ListNode *node = engine_snapshot_list; + /* restore generically stored snapshot buffers */ - if (engine_snapshot_list == NULL) - return; - - while (node != NULL) - { - LoadEngineSnapshotBuffer((struct EngineSnapshotNodeInfo *)node->content); - - node = node->next; - } + LoadEngineSnapshotBuffers(); /* restore special values from snapshot structure */ LoadEngineSnapshotValues_RND(); LoadEngineSnapshotValues_EM(); + LoadEngineSnapshotValues_SP(); } boolean CheckEngineSnapshot()