X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=0dc37771206428ec53ab7a72d6bccf0ea9cee016;hb=b4865a65808ffd72a4f98d09cdb332582e464500;hp=7ce53c5b077581d92118638e15ff81da1a0dfc2f;hpb=943e766434e3043be25c8c11f5aa968304f5164f;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index 7ce53c5b..0dc37771 100644 --- a/src/game.c +++ b/src/game.c @@ -3542,7 +3542,6 @@ void InitGame(void) int fade_mask = REDRAW_FIELD; boolean emulate_bd = TRUE; // unless non-BOULDERDASH elements found - boolean emulate_sb = TRUE; // unless non-SOKOBAN elements found boolean emulate_sp = TRUE; // unless non-SUPAPLEX elements found int initial_move_dir = MV_DOWN; int i, j, x, y; @@ -3886,8 +3885,6 @@ void InitGame(void) { if (emulate_bd && !IS_BD_ELEMENT(Tile[x][y])) emulate_bd = FALSE; - if (emulate_sb && !IS_SB_ELEMENT(Tile[x][y])) - emulate_sb = FALSE; if (emulate_sp && !IS_SP_ELEMENT(Tile[x][y])) emulate_sp = FALSE; @@ -3912,7 +3909,6 @@ void InitGame(void) } game.emulation = (emulate_bd ? EMU_BOULDERDASH : - emulate_sb ? EMU_SOKOBAN : emulate_sp ? EMU_SUPAPLEX : EMU_NONE); // initialize type of slippery elements @@ -4310,7 +4306,7 @@ void InitGame(void) { // check for player created from custom element as single target content = element_info[element].change_page[i].target_element; - is_player = ELEM_IS_PLAYER(content); + is_player = IS_PLAYER_ELEMENT(content); if (is_player && (found_rating < 3 || (found_rating == 3 && element < found_element))) @@ -4328,7 +4324,7 @@ void InitGame(void) { // check for player created from custom element as explosion content content = element_info[element].content.e[xx][yy]; - is_player = ELEM_IS_PLAYER(content); + is_player = IS_PLAYER_ELEMENT(content); if (is_player && (found_rating < 2 || (found_rating == 2 && element < found_element))) @@ -4349,7 +4345,7 @@ void InitGame(void) content = element_info[element].change_page[i].target_content.e[xx][yy]; - is_player = ELEM_IS_PLAYER(content); + is_player = IS_PLAYER_ELEMENT(content); if (is_player && (found_rating < 1 || (found_rating == 1 && element < found_element))) @@ -5025,7 +5021,7 @@ void GameEnd(void) { SetGameStatus(GAME_MODE_SCORES); - DrawHallOfFame(last_level_nr, scores.last_added); + DrawHallOfFame(last_level_nr); } else if (setup.auto_play_next_level && setup.increment_levels && last_level_nr < leveldir_current->last_level && @@ -5041,12 +5037,12 @@ void GameEnd(void) } } -static int addScoreEntry(struct ScoreInfo *list, struct ScoreEntry *new_entry) +static int addScoreEntry(struct ScoreInfo *list, struct ScoreEntry *new_entry, + boolean one_score_entry_per_name) { - boolean one_score_entry_per_name = !program.many_scores_per_name; int i; - if (strEqual(setup.player_name, EMPTY_PLAYER_NAME)) + if (strEqual(new_entry->name, EMPTY_PLAYER_NAME)) return -1; for (i = 0; i < MAX_SCORE_ENTRIES; i++) @@ -5066,7 +5062,9 @@ static int addScoreEntry(struct ScoreInfo *list, struct ScoreEntry *new_entry) entry->time == 0); // prevent adding server score entries if also existing in local score file - if (strEqual(new_entry->tape_basename, entry->tape_basename)) + // (special case: historic score entries have an empty tape basename entry) + if (strEqual(new_entry->tape_basename, entry->tape_basename) && + !strEqual(new_entry->tape_basename, UNDEFINED_FILENAME)) return -1; if (is_better || entry_is_empty) @@ -5081,7 +5079,7 @@ static int addScoreEntry(struct ScoreInfo *list, struct ScoreEntry *new_entry) if (one_score_entry_per_name) { for (l = i; l < MAX_SCORE_ENTRIES; l++) - if (strEqual(list->entry[l].name, setup.player_name)) + if (strEqual(list->entry[l].name, new_entry->name)) m = l; if (m == i) // player's new highscore overwrites his old one @@ -5099,7 +5097,7 @@ static int addScoreEntry(struct ScoreInfo *list, struct ScoreEntry *new_entry) return i; } else if (one_score_entry_per_name && - strEqual(entry->name, setup.player_name)) + strEqual(entry->name, new_entry->name)) { // player already in high score list with better score or time @@ -5113,6 +5111,7 @@ static int addScoreEntry(struct ScoreInfo *list, struct ScoreEntry *new_entry) void NewHighScore(int level_nr) { struct ScoreEntry new_entry = {{ 0 }}; // (prevent warning from GCC bug 53119) + boolean one_per_name = FALSE; strncpy(new_entry.tape_basename, tape.score_tape_basename, MAX_FILENAME_LEN); strncpy(new_entry.name, setup.player_name, MAX_PLAYER_NAME_LEN); @@ -5122,34 +5121,47 @@ void NewHighScore(int level_nr) LoadScore(level_nr); - scores.last_added = addScoreEntry(&scores, &new_entry); + scores.last_added = addScoreEntry(&scores, &new_entry, one_per_name); if (scores.last_added >= 0) { SaveScore(level_nr); - if (game.LevelSolved_SaveTape) - { - SaveScoreTape(level_nr); - SaveServerScore(level_nr); - } + // store last added local score entry (before merging server scores) + scores.last_added_local = scores.last_added; + } + + if (game.LevelSolved_SaveTape) + { + SaveScoreTape(level_nr); + SaveServerScore(level_nr); } } void MergeServerScore(void) { + struct ScoreEntry last_added_entry; + boolean one_per_name = FALSE; int i; + if (scores.last_added >= 0) + last_added_entry = scores.entry[scores.last_added]; + for (i = 0; i < server_scores.num_entries; i++) { - int pos = addScoreEntry(&scores, &server_scores.entry[i]); + int pos = addScoreEntry(&scores, &server_scores.entry[i], one_per_name); if (pos >= 0 && pos <= scores.last_added) scores.last_added++; } if (scores.last_added >= MAX_SCORE_ENTRIES) - scores.last_added = -1; + { + scores.last_added = MAX_SCORE_ENTRIES - 1; + scores.force_last_added = TRUE; + + scores.entry[scores.last_added] = last_added_entry; + } } static int getElementMoveStepsizeExt(int x, int y, int direction) @@ -5672,7 +5684,7 @@ static void RelocatePlayer(int jx, int jy, int el_player_raw) 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 + if (!IS_PLAYER_ELEMENT(element)) // player may be set on walkable element { Tile[jx][jy] = element; // restore previously existing element } @@ -5842,7 +5854,7 @@ static void Explode(int ex, int ey, int phase, int mode) // !!! check this case -- currently needed for rnd_rado_negundo_v, // !!! levels 015 018 019 020 021 022 023 026 027 028 !!! - else if (ELEM_IS_PLAYER(center_element)) + else if (IS_PLAYER_ELEMENT(center_element)) Store[x][y] = EL_EMPTY; else if (center_element == EL_YAMYAM) Store[x][y] = level.yamyam_content[game.yamyam_content_nr].e[xx][yy]; @@ -5982,7 +5994,7 @@ static void Explode(int ex, int ey, int phase, int mode) if (IS_PLAYER(x, y) && !PLAYERINFO(x, y)->present) StorePlayer[x][y] = 0; - if (ELEM_IS_PLAYER(element)) + if (IS_PLAYER_ELEMENT(element)) RelocatePlayer(x, y, element); } else if (IN_SCR_FIELD(SCREENX(x), SCREENY(y))) @@ -8768,7 +8780,7 @@ void ContinueMoving(int x, int y) if (GFX_CRUMBLED(Tile[x][y])) TEST_DrawLevelFieldCrumbledNeighbours(x, y); - if (ELEM_IS_PLAYER(move_leave_element)) + if (IS_PLAYER_ELEMENT(move_leave_element)) RelocatePlayer(x, y, move_leave_element); } @@ -10578,7 +10590,7 @@ static void CreateFieldExt(int x, int y, int element, boolean is_change) int previous_move_direction = MovDir[x][y]; int last_ce_value = CustomValue[x][y]; boolean player_explosion_protected = PLAYER_EXPLOSION_PROTECTED(x, y); - boolean new_element_is_player = ELEM_IS_PLAYER(new_element); + boolean new_element_is_player = IS_PLAYER_ELEMENT(new_element); boolean add_player_onto_element = (new_element_is_player && new_element != EL_SOKOBAN_FIELD_PLAYER && IS_WALKABLE(old_element)); @@ -10754,7 +10766,7 @@ static boolean ChangeElement(int x, int y, int element, int page) (change->replace_when == CP_WHEN_COLLECTIBLE && is_collectible) || (change->replace_when == CP_WHEN_REMOVABLE && is_removable) || (change->replace_when == CP_WHEN_DESTRUCTIBLE && is_destructible)) && - !(IS_PLAYER(ex, ey) && ELEM_IS_PLAYER(content_element))); + !(IS_PLAYER(ex, ey) && IS_PLAYER_ELEMENT(content_element))); if (!can_replace[xx][yy]) complete_replace = FALSE; @@ -10816,6 +10828,10 @@ static boolean ChangeElement(int x, int y, int element, int page) Store[x][y] = EL_EMPTY; } + // special case: element changes to player (and may be kept if walkable) + if (IS_PLAYER_ELEMENT(target_element) && !level.keep_walkable_ce) + CreateElementFromChange(x, y, EL_EMPTY); + CreateElementFromChange(x, y, target_element); PlayLevelSoundElementAction(x, y, element, ACTION_CHANGING); @@ -12157,6 +12173,9 @@ void GameActions_RND(void) TEST_DrawLevelField(x, y); TestFieldAfterSnapping(x, y, element, move_direction, player_index_bit); + + if (IS_ENVELOPE(element)) + local_player->show_envelope = element; } } @@ -14314,7 +14333,10 @@ static int DigField(struct PlayerInfo *player, } else if (IS_ENVELOPE(element)) { - player->show_envelope = element; + boolean wait_for_snapping = (mode == DF_SNAP && level.block_snap_field); + + if (!wait_for_snapping) + player->show_envelope = element; } else if (element == EL_EMC_LENSES) { @@ -14501,7 +14523,7 @@ static int DigField(struct PlayerInfo *player, if (sokoban_task_solved && game.sokoban_fields_still_needed == 0 && game.sokoban_objects_still_needed == 0 && - (game.emulation == EMU_SOKOBAN || level.auto_exit_sokoban)) + level.auto_exit_sokoban) { game.players_still_needed = 0;