X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Ffiles.c;h=0fd7a18ade6db1691778942d270aee3e8f15ecb7;hb=cee436b68cda95e13abc810235a11ce94bc79c95;hp=a58442ee8217c8ff7413a9fe869f97c81ff71fca;hpb=b399baa8e7bc4cc0cd593ff71f9da95291ba4ccd;p=rocksndiamonds.git diff --git a/src/files.c b/src/files.c index a58442ee..0fd7a18a 100644 --- a/src/files.c +++ b/src/files.c @@ -49,22 +49,6 @@ #define TAPE_COOKIE_TMPL "ROCKSNDIAMONDS_TAPE_FILE_VERSION_x.x" #define SCORE_COOKIE "ROCKSNDIAMONDS_SCORE_FILE_VERSION_1.2" -/* values for level file type identifier */ -#define LEVEL_FILE_TYPE_UNKNOWN 0 -#define LEVEL_FILE_TYPE_RND 1 -#define LEVEL_FILE_TYPE_BD 2 -#define LEVEL_FILE_TYPE_EM 3 -#define LEVEL_FILE_TYPE_SP 4 -#define LEVEL_FILE_TYPE_DX 5 -#define LEVEL_FILE_TYPE_SB 6 -#define LEVEL_FILE_TYPE_DC 7 - -#define LEVEL_FILE_TYPE_RND_PACKED (10 + LEVEL_FILE_TYPE_RND) -#define LEVEL_FILE_TYPE_EM_PACKED (10 + LEVEL_FILE_TYPE_EM) - -#define IS_SINGLE_LEVEL_FILE(x) (x < 10) -#define IS_PACKED_LEVEL_FILE(x) (x > 10) - /* ========================================================================= */ /* level file functions */ @@ -159,14 +143,17 @@ static void setLevelInfoToDefaults(struct LevelInfo *level) level->double_speed = FALSE; level->initial_gravity = FALSE; level->em_slippery_gems = FALSE; - level->block_last_field = FALSE; - level->sp_block_last_field = TRUE; level->instant_relocation = FALSE; level->can_pass_to_walkable = FALSE; level->grow_into_diggable = TRUE; + level->block_last_field = FALSE; /* EM does not block by default */ + level->sp_block_last_field = TRUE; /* SP blocks the last field */ + level->block_delay = 8; /* when blocking, block 8 frames */ + level->sp_block_delay = 9; /* SP indeed blocks 9 frames, not 8 */ + level->can_move_into_acid_bits = ~0; /* everything can move into acid */ - level->dont_collide_with_bits = ~0; /* always deadly when colliding */ + level->dont_collide_with_bits = ~0; /* always deadly when colliding */ level->use_spring_bug = FALSE; level->use_step_counter = FALSE; @@ -310,6 +297,8 @@ static void setLevelInfoToDefaults(struct LevelInfo *level) level->no_valid_file = FALSE; + level->changed = FALSE; + if (leveldir_current == NULL) /* only when dumping level */ return; @@ -546,6 +535,20 @@ static void determineLevelFileInfo_Filetype(struct LevelFileInfo *lfi) lfi->type = getFileTypeFromBasename(lfi->basename); } +#if 1 +static void setLevelFileInfo(struct LevelFileInfo *level_file_info, int nr) +{ + /* always start with reliable default values */ + setFileInfoToDefaults(level_file_info); + + level_file_info->nr = nr; /* set requested level number */ + + determineLevelFileInfo_Filename(level_file_info); + determineLevelFileInfo_Filetype(level_file_info); +} + +#else + static struct LevelFileInfo *getLevelFileInfo(int nr) { static struct LevelFileInfo level_file_info; @@ -560,7 +563,7 @@ static struct LevelFileInfo *getLevelFileInfo(int nr) return &level_file_info; } - +#endif /* ------------------------------------------------------------------------- */ /* functions for loading R'n'D level */ @@ -1888,6 +1891,17 @@ static void LoadLevelFromFileStream_SP(FILE *file, struct LevelInfo *level, level->field[x][y] <= EL_SP_GRAVITY_PORT_UP) level->field[x][y] += EL_SP_PORT_RIGHT - EL_SP_GRAVITY_PORT_RIGHT; + /* auto-determine number of infotrons if it was stored as "0" -- see above */ + if (level->gems_needed == 0) + { + for (y = 0; y < SP_LEVEL_YSIZE; y++) + for (x = 0; x < SP_LEVEL_XSIZE; x++) + if (level->field[x][y] == EL_SP_INFOTRON) + level->gems_needed++; + + level->gems_needed &= 0xff; /* only use low byte -- see above */ + } + level->fieldx = SP_LEVEL_XSIZE; level->fieldy = SP_LEVEL_YSIZE; @@ -2186,9 +2200,11 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename) if (level->game_version == VERSION_IDENT(2,0,1,0)) level->em_slippery_gems = TRUE; + /* springs could be pushed over pits before (pre-release version) 2.2.0 */ if (level->game_version < VERSION_IDENT(2,2,0,0)) level->use_spring_bug = TRUE; + /* only few elements were able to actively move into acid before 3.1.0 */ if (level->game_version < VERSION_IDENT(3,1,0,0)) { int i, j; @@ -2218,8 +2234,25 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename) } } } + +#if 1 /* USE_NEW_BLOCK_STYLE */ + /* blocking the last field when moving was corrected in version 3.1.1 */ + if (level->game_version < VERSION_IDENT(3,1,1,0)) + { +#if 0 + printf("::: %d\n", level->block_last_field); +#endif + + /* even "not blocking" was blocking the last field for one frame */ + level->block_delay = (level->block_last_field ? 7 : 1); + level->sp_block_delay = (level->sp_block_last_field ? 7 : 1); + + level->block_last_field = TRUE; + level->sp_block_last_field = TRUE; + } +#endif } - else + else /* always use the latest game engine version */ { #if 0 printf("\n::: ALWAYS USE LATEST ENGINE FOR THIS LEVEL: [%d] '%s'\n", @@ -2341,6 +2374,7 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename) } /* initialize "can_explode" field for old levels which did not store this */ + /* !!! CHECK THIS -- "<= 3,1,0,0" IS PROBABLY WRONG !!! */ if (level->game_version <= VERSION_IDENT(3,1,0,0)) { for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) @@ -2356,6 +2390,22 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename) } } + /* correct previously hard-coded move delay values for maze runner style */ + if (level->game_version < VERSION_IDENT(3,1,1,0)) + { + for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) + { + int element = EL_CUSTOM_START + i; + + if (element_info[element].move_pattern & MV_MAZE_RUNNER_STYLE) + { + /* previously hard-coded and therefore ignored */ + element_info[element].move_delay_fixed = 9; + element_info[element].move_delay_random = 0; + } + } + } + #if 0 /* set default push delay values (corrected since version 3.0.7-1) */ if (level->game_version < VERSION_IDENT(3,0,7,1)) @@ -2448,6 +2498,16 @@ static void LoadLevel_InitPlayfield(struct LevelInfo *level, char *filename) void LoadLevelTemplate(int nr) { +#if 1 + char *filename; + + setLevelFileInfo(&level_template.file_info, nr); + filename = level_template.file_info.filename; + + LoadLevelFromFileInfo(&level_template, &level_template.file_info); + +#else + #if 1 struct LevelFileInfo *level_file_info = getLevelFileInfo(nr); char *filename = level_file_info->filename; @@ -2458,15 +2518,31 @@ void LoadLevelTemplate(int nr) LoadLevelFromFilename_RND(&level_template, filename); #endif +#endif +#if 1 + LoadLevel_InitVersion(&level_template, filename); + LoadLevel_InitElements(&level_template, filename); +#else LoadLevel_InitVersion(&level, filename); LoadLevel_InitElements(&level, filename); +#endif ActivateLevelTemplate(); } void LoadLevel(int nr) { +#if 1 + char *filename; + + setLevelFileInfo(&level.file_info, nr); + filename = level.file_info.filename; + + LoadLevelFromFileInfo(&level, &level.file_info); + +#else + #if 1 struct LevelFileInfo *level_file_info = getLevelFileInfo(nr); char *filename = level_file_info->filename; @@ -2476,6 +2552,7 @@ void LoadLevel(int nr) char *filename = getLevelFilename(nr); LoadLevelFromFilename_RND(&level, filename); +#endif #endif if (level.use_custom_template) @@ -3568,6 +3645,8 @@ void DumpTape(struct TapeInfo *tape) printf_line("-", 79); printf("Tape of Level %03d (file version %08d, game version %08d)\n", tape->level_nr, tape->file_version, tape->game_version); + printf(" (effective engine version %08d)\n", + tape->engine_version); printf("Level series identifier: '%s'\n", tape->level_identifier); printf_line("-", 79); @@ -4810,3 +4889,117 @@ void LoadHelpTextInfo() END_HASH_ITERATION(hash, itr) #endif } + + +/* ------------------------------------------------------------------------- * + * convert levels + * ------------------------------------------------------------------------- */ + +#define MAX_NUM_CONVERT_LEVELS 1000 + +void ConvertLevels() +{ + static LevelDirTree *convert_leveldir = NULL; + static int convert_level_nr = -1; + static int num_levels_handled = 0; + static int num_levels_converted = 0; + static boolean levels_failed[MAX_NUM_CONVERT_LEVELS]; + int i; + + convert_leveldir = getTreeInfoFromIdentifier(leveldir_first, + global.convert_leveldir); + + if (convert_leveldir == NULL) + Error(ERR_EXIT, "no such level identifier: '%s'", + global.convert_leveldir); + + leveldir_current = convert_leveldir; + + if (global.convert_level_nr != -1) + { + convert_leveldir->first_level = global.convert_level_nr; + convert_leveldir->last_level = global.convert_level_nr; + } + + convert_level_nr = convert_leveldir->first_level; + + printf_line("=", 79); + printf("Converting levels\n"); + printf_line("-", 79); + printf("Level series identifier: '%s'\n", convert_leveldir->identifier); + printf("Level series name: '%s'\n", convert_leveldir->name); + printf("Level series author: '%s'\n", convert_leveldir->author); + printf("Number of levels: %d\n", convert_leveldir->levels); + printf_line("=", 79); + printf("\n"); + + for (i = 0; i < MAX_NUM_CONVERT_LEVELS; i++) + levels_failed[i] = FALSE; + + while (convert_level_nr <= convert_leveldir->last_level) + { + char *level_filename; + boolean new_level; + + level_nr = convert_level_nr++; + + printf("Level %03d: ", level_nr); + + LoadLevel(level_nr); + if (level.no_valid_file) + { + printf("(no level)\n"); + continue; + } + + printf("converting level ... "); + + level_filename = getDefaultLevelFilename(level_nr); + new_level = !fileExists(level_filename); + + if (new_level) + { + SaveLevel(level_nr); + + num_levels_converted++; + + printf("converted.\n"); + } + else + { + if (level_nr >= 0 && level_nr < MAX_NUM_CONVERT_LEVELS) + levels_failed[level_nr] = TRUE; + + printf("NOT CONVERTED -- LEVEL ALREADY EXISTS.\n"); + } + + num_levels_handled++; + } + + printf("\n"); + printf_line("=", 79); + printf("Number of levels handled: %d\n", num_levels_handled); + printf("Number of levels converted: %d (%d%%)\n", num_levels_converted, + (num_levels_handled ? + num_levels_converted * 100 / num_levels_handled : 0)); + printf_line("-", 79); + printf("Summary (for automatic parsing by scripts):\n"); + printf("LEVELDIR '%s', CONVERTED %d/%d (%d%%)", + convert_leveldir->identifier, num_levels_converted, + num_levels_handled, + (num_levels_handled ? + num_levels_converted * 100 / num_levels_handled : 0)); + + if (num_levels_handled != num_levels_converted) + { + printf(", FAILED:"); + for (i = 0; i < MAX_NUM_CONVERT_LEVELS; i++) + if (levels_failed[i]) + printf(" %03d", i); + } + + printf("\n"); + printf_line("=", 79); + + CloseAllAndExit(0); +}