X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Ffiles.c;h=93ab6bc8e1b564612179ae24109ec3be17b2684c;hb=ea6e4698905d7440a265e323d03cf13fc323c44b;hp=743624677e149c4aff94d472caa46c9f76568233;hpb=68f0ce90185b6ea19cad62bc6328326bda538951;p=rocksndiamonds.git diff --git a/src/files.c b/src/files.c index 74362467..93ab6bc8 100644 --- a/src/files.c +++ b/src/files.c @@ -40,235 +40,14 @@ #define TAPE_HEADER_SIZE 20 /* size of tape file header */ #define TAPE_HEADER_UNUSED 3 /* unused tape header bytes */ -#define LEVEL_CHUNK_CNT3_SIZE(x) (LEVEL_CHUNK_CNT3_HEADER + (x)) -#define LEVEL_CHUNK_CUS3_SIZE(x) (2 + (x) * LEVEL_CPART_CUS3_SIZE) -#define LEVEL_CHUNK_CUS4_SIZE(x) (96 + (x) * 48) +#define LEVEL_CHUNK_CNT3_SIZE(x) (LEVEL_CHUNK_CNT3_HEADER + (x)) +#define LEVEL_CHUNK_CUS3_SIZE(x) (2 + (x) * LEVEL_CPART_CUS3_SIZE) +#define LEVEL_CHUNK_CUS4_SIZE(x) (48 + 48 + (x) * 48) /* file identifier strings */ -#define LEVEL_COOKIE_TMPL "ROCKSNDIAMONDS_LEVEL_FILE_VERSION_x.x" -#define TAPE_COOKIE_TMPL "ROCKSNDIAMONDS_TAPE_FILE_VERSION_x.x" -#define SCORE_COOKIE "ROCKSNDIAMONDS_SCORE_FILE_VERSION_1.2" - -/* values for "CONF" chunk */ -#define CONF_MASK_1_BYTE 0x00 -#define CONF_MASK_2_BYTE 0x40 -#define CONF_MASK_4_BYTE 0x80 -#define CONF_MASK_MULTI_BYTES 0xc0 - -#define CONF_MASK_BYTES 0xc0 -#define CONF_MASK_TOKEN 0x3f - -#define CONF_LAST_ENTRY (CONF_MASK_1_BYTE | 0) - -#define CONF_VALUE_INTEGER_1 (CONF_MASK_1_BYTE | 1) -#define CONF_VALUE_INTEGER_2 (CONF_MASK_1_BYTE | 2) -#define CONF_VALUE_INTEGER_3 (CONF_MASK_1_BYTE | 3) -#define CONF_VALUE_INTEGER_4 (CONF_MASK_1_BYTE | 4) -#define CONF_VALUE_BOOLEAN_1 (CONF_MASK_1_BYTE | 5) -#define CONF_VALUE_BOOLEAN_2 (CONF_MASK_1_BYTE | 6) -#define CONF_VALUE_BOOLEAN_3 (CONF_MASK_1_BYTE | 7) -#define CONF_VALUE_BOOLEAN_4 (CONF_MASK_1_BYTE | 8) - -#define CONF_VALUE_ELEMENT_1 (CONF_MASK_2_BYTE | 1) -#define CONF_VALUE_ELEMENT_2 (CONF_MASK_2_BYTE | 2) -#define CONF_VALUE_ELEMENT_3 (CONF_MASK_2_BYTE | 3) -#define CONF_VALUE_ELEMENT_4 (CONF_MASK_2_BYTE | 4) - -#define CONF_VALUE_CONTENT_1 (CONF_MASK_MULTI_BYTES | 1) -#define CONF_VALUE_CONTENT_8 (CONF_MASK_MULTI_BYTES | 2) - -#define CONF_VALUE_INTEGER(x) ((x) >= CONF_VALUE_INTEGER_1 && \ - (x) <= CONF_VALUE_INTEGER_4) - -#define CONF_VALUE_BOOLEAN(x) ((x) >= CONF_VALUE_BOOLEAN_1 && \ - (x) <= CONF_VALUE_BOOLEAN_4) - -#define CONF_VALUE_NUM_BYTES(x) ((x) == CONF_MASK_1_BYTE ? 1 : \ - (x) == CONF_MASK_2_BYTE ? 2 : \ - (x) == CONF_MASK_4_BYTE ? 4 : 0) - -#define CONF_CONTENT_NUM_ELEMENTS (3 * 3) -#define CONF_CONTENT_NUM_BYTES (CONF_CONTENT_NUM_ELEMENTS * 2) - -#define CONF_CONTENT_ELEMENT_POS(c,x,y) ((c) * CONF_CONTENT_NUM_ELEMENTS + \ - (y) * 3 + (x)) -#define CONF_CONTENT_BYTE_POS(c,x,y) (CONF_CONTENT_ELEMENT_POS(c,x,y) * 2) -#define CONF_CONTENT_ELEMENT(b,c,x,y) ((b[CONF_CONTENT_BYTE_POS(c,x,y)] << 8)|\ - (b[CONF_CONTENT_BYTE_POS(c,x,y) + 1])) - -static struct LevelInfo li; - -static struct -{ - int element; - int type; - void *value; - int default_value; -} element_conf[] = -{ - /* ---------- 1-byte values ---------------------------------------------- */ - { - EL_EMC_ANDROID, CONF_VALUE_INTEGER_1, - &li.android_move_time, 10 - }, - { - EL_EMC_ANDROID, CONF_VALUE_INTEGER_2, - &li.android_clone_time, 10 - }, - { - EL_EMC_LENSES, CONF_VALUE_INTEGER_1, - &li.lenses_score, 10 - }, - { - EL_EMC_LENSES, CONF_VALUE_INTEGER_2, - &li.lenses_time, 10 - }, - { - EL_EMC_MAGNIFIER, CONF_VALUE_INTEGER_1, - &li.magnify_score, 10 - }, - { - EL_EMC_MAGNIFIER, CONF_VALUE_INTEGER_2, - &li.magnify_time, 10 - }, - { - EL_ROBOT, CONF_VALUE_INTEGER_1, - &li.slurp_score, 10 - }, - { - EL_GAME_OF_LIFE, CONF_VALUE_INTEGER_1, - &li.game_of_life[0], 2 - }, - { - EL_GAME_OF_LIFE, CONF_VALUE_INTEGER_2, - &li.game_of_life[1], 3 - }, - { - EL_GAME_OF_LIFE, CONF_VALUE_INTEGER_3, - &li.game_of_life[2], 3 - }, - { - EL_GAME_OF_LIFE, CONF_VALUE_INTEGER_4, - &li.game_of_life[3], 3 - }, - { - EL_BIOMAZE, CONF_VALUE_INTEGER_1, - &li.biomaze[0], 2 - }, - { - EL_BIOMAZE, CONF_VALUE_INTEGER_2, - &li.biomaze[1], 3 - }, - { - EL_BIOMAZE, CONF_VALUE_INTEGER_3, - &li.biomaze[2], 3 - }, - { - EL_BIOMAZE, CONF_VALUE_INTEGER_4, - &li.biomaze[3], 3 - }, - { - EL_BALLOON, CONF_VALUE_INTEGER_1, - &li.wind_direction_initial, MV_NONE - }, - { - EL_TIMEGATE_SWITCH, CONF_VALUE_INTEGER_1, - &li.time_timegate, 10 - }, - { - EL_LIGHT_SWITCH_ACTIVE, CONF_VALUE_INTEGER_1, - &li.time_light, 10 - }, - { - EL_SHIELD_NORMAL, CONF_VALUE_INTEGER_1, - &li.shield_normal_time, 10 - }, - { - EL_SHIELD_DEADLY, CONF_VALUE_INTEGER_1, - &li.shield_deadly_time, 10 - }, - { - EL_EXTRA_TIME, CONF_VALUE_INTEGER_1, - &li.extra_time, 10 - }, - { - EL_EXTRA_TIME, CONF_VALUE_INTEGER_2, - &li.extra_time_score, 10 - }, - { - EL_TIME_ORB_FULL, CONF_VALUE_INTEGER_1, - &li.time_orb_time, 10 - }, - { - EL_TIME_ORB_FULL, CONF_VALUE_BOOLEAN_1, - &li.use_time_orb_bug, FALSE - }, - { - EL_PLAYER_1, CONF_VALUE_BOOLEAN_1, - &li.block_snap_field, TRUE - }, - { - EL_PLAYER_1, CONF_VALUE_BOOLEAN_2, - &li.use_start_element[0], FALSE - }, - { - EL_PLAYER_2, CONF_VALUE_BOOLEAN_2, - &li.use_start_element[1], FALSE - }, - { - EL_PLAYER_3, CONF_VALUE_BOOLEAN_2, - &li.use_start_element[2], FALSE - }, - { - EL_PLAYER_4, CONF_VALUE_BOOLEAN_2, - &li.use_start_element[3], FALSE - }, - { - EL_EMC_MAGIC_BALL, CONF_VALUE_INTEGER_1, - &li.ball_time, 10 - }, - { - EL_EMC_MAGIC_BALL, CONF_VALUE_INTEGER_2, - &li.num_ball_contents, 8 - }, - { - EL_EMC_MAGIC_BALL, CONF_VALUE_BOOLEAN_1, - &li.ball_random, FALSE - }, - { - EL_EMC_MAGIC_BALL, CONF_VALUE_BOOLEAN_2, - &li.ball_state_initial, FALSE - }, - - /* ---------- 2-byte values ---------------------------------------------- */ - { - EL_PLAYER_1, CONF_VALUE_ELEMENT_1, - &li.start_element[0], EL_PLAYER_1 - }, - { - EL_PLAYER_2, CONF_VALUE_ELEMENT_1, - &li.start_element[1], EL_PLAYER_2 - }, - { - EL_PLAYER_3, CONF_VALUE_ELEMENT_1, - &li.start_element[2], EL_PLAYER_3 - }, - { - EL_PLAYER_4, CONF_VALUE_ELEMENT_1, - &li.start_element[3], EL_PLAYER_4 - }, - - /* ---------- multi-byte values ------------------------------------------ */ - { - EL_EMC_MAGIC_BALL, CONF_VALUE_CONTENT_8, - &li.ball_content, EL_EMPTY - }, - - { - -1, -1, - NULL, -1 - }, -}; +#define LEVEL_COOKIE_TMPL "ROCKSNDIAMONDS_LEVEL_FILE_VERSION_x.x" +#define TAPE_COOKIE_TMPL "ROCKSNDIAMONDS_TAPE_FILE_VERSION_x.x" +#define SCORE_COOKIE "ROCKSNDIAMONDS_SCORE_FILE_VERSION_1.2" static struct { @@ -292,40 +71,6 @@ filetype_id_list[] = /* level file functions */ /* ========================================================================= */ -static void setLevelInfoToDefaultsFromConfigList(struct LevelInfo *level) -{ - int i; - - li = *level; /* copy level information into temporary buffer */ - - for (i = 0; element_conf[i].element != -1; i++) - { - int default_value = element_conf[i].default_value; - int type = element_conf[i].type; - int bytes = type & CONF_MASK_BYTES; - - if (bytes != CONF_MASK_MULTI_BYTES) - { - if (CONF_VALUE_BOOLEAN(type)) - *(boolean *)(element_conf[i].value) = default_value; - else - *(int *) (element_conf[i].value) = default_value; - } - else if (type == CONF_VALUE_CONTENT_8) - { - struct Content *content = (struct Content *)(element_conf[i].value); - int c, x, y; - - for (c = 0; c < MAX_ELEMENT_CONTENTS; c++) - for (y = 0; y < 3; y++) - for (x = 0; x < 3; x++) - content[c].e[x][y] = default_value; - } - } - - *level = li; /* copy temporary buffer back to level information */ -} - void setElementChangePages(struct ElementInfo *ei, int change_pages) { int change_page_size = sizeof(struct ElementChangeInfo); @@ -358,7 +103,7 @@ void setElementChangeInfoToDefaults(struct ElementChangeInfo *change) change->delay_fixed = 0; change->delay_random = 0; - change->delay_frames = FRAMES_PER_SECOND; + change->delay_frames = 1; change->trigger_element = EL_EMPTY_SPACE; @@ -369,14 +114,9 @@ void setElementChangeInfoToDefaults(struct ElementChangeInfo *change) change->random_percentage = 100; change->replace_when = CP_WHEN_EMPTY; - change->has_action = FALSE; - change->action_type = CA_NO_ACTION; - change->action_mode = CA_MODE_UNDEFINED; - change->action_arg = CA_ARG_UNDEFINED; - for (x = 0; x < 3; x++) for (y = 0; y < 3; y++) - change->target_content.e[x][y] = EL_EMPTY_SPACE; + change->target_content[x][y] = EL_EMPTY_SPACE; change->direct_action = 0; change->other_action = 0; @@ -391,7 +131,6 @@ static void setLevelInfoToDefaults(struct LevelInfo *level) static boolean clipboard_elements_initialized = FALSE; int i, j, x, y; - setLevelInfoToDefaultsFromConfigList(level); setLevelInfoToDefaults_EM(); level->native_em_level = &native_em_level; @@ -419,23 +158,11 @@ static void setLevelInfoToDefaults(struct LevelInfo *level) level->time_magic_wall = 10; level->time_wheel = 10; -#if 0 level->time_light = 10; level->time_timegate = 10; -#endif level->amoeba_content = EL_DIAMOND; - level->game_of_life[0] = 2; - level->game_of_life[1] = 3; - level->game_of_life[2] = 3; - level->game_of_life[3] = 3; - - level->biomaze[0] = 2; - level->biomaze[1] = 3; - level->biomaze[2] = 3; - level->biomaze[3] = 3; - level->double_speed = FALSE; level->initial_gravity = FALSE; level->em_slippery_gems = FALSE; @@ -443,37 +170,36 @@ static void setLevelInfoToDefaults(struct LevelInfo *level) level->can_pass_to_walkable = FALSE; level->grow_into_diggable = TRUE; - level->block_snap_field = TRUE; - level->block_last_field = FALSE; /* EM does not block by default */ level->sp_block_last_field = TRUE; /* SP blocks the last field */ +#if 0 /* !!! THIS IS NOT A LEVEL SETTING => LOGIC MOVED TO "game.c" !!! */ + level->block_delay = 8; /* when blocking, block 8 frames */ + level->sp_block_delay = 9; /* SP indeed blocks 9 frames, not 8 */ +#endif + level->can_move_into_acid_bits = ~0; /* everything can move into acid */ level->dont_collide_with_bits = ~0; /* always deadly when colliding */ level->use_spring_bug = FALSE; - level->use_time_orb_bug = FALSE; - level->use_step_counter = FALSE; /* values for the new EMC elements */ -#if 0 level->android_move_time = 10; level->android_clone_time = 10; + level->ball_random = FALSE; + level->ball_state_initial = FALSE; level->ball_time = 10; level->lenses_score = 10; - level->lenses_time = 10; level->magnify_score = 10; - level->magnify_time = 10; level->slurp_score = 10; - level->wind_direction_initial = MV_NONE; - level->ball_random = FALSE; - level->ball_state_initial = FALSE; - for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) + level->lenses_time = 10; + level->magnify_time = 10; + level->wind_direction_initial = MV_NO_MOVING; + for (i = 0; i < NUM_MAGIC_BALL_CONTENTS; i++) for (x = 0; x < 3; x++) for (y = 0; y < 3; y++) - level->ball_content[i].e[x][y] = EL_EMPTY; -#endif + level->ball_content[i][x][y] = EL_EMPTY; for (i = 0; i < 16; i++) level->android_array[i] = FALSE; @@ -495,13 +221,13 @@ static void setLevelInfoToDefaults(struct LevelInfo *level) } for (i = 0; i < LEVEL_SCORE_ELEMENTS; i++) - level->score[i] = (i == SC_TIME_BONUS ? 1 : 10); + level->score[i] = 10; level->num_yamyam_contents = STD_ELEMENT_CONTENTS; for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) for (x = 0; x < 3; x++) for (y = 0; y < 3; y++) - level->yamyam_content[i].e[x][y] = + level->yamyam_content[i][x][y] = (i < STD_ELEMENT_CONTENTS ? EL_ROCK : EL_EMPTY); level->field[0][0] = EL_PLAYER_1; @@ -510,82 +236,79 @@ static void setLevelInfoToDefaults(struct LevelInfo *level) for (i = 0; i < MAX_NUM_ELEMENTS; i++) { int element = i; - struct ElementInfo *ei = &element_info[element]; /* never initialize clipboard elements after the very first time */ if (IS_CLIPBOARD_ELEMENT(element) && clipboard_elements_initialized) continue; - setElementChangePages(ei, 1); - setElementChangeInfoToDefaults(ei->change); + setElementChangePages(&element_info[element], 1); + setElementChangeInfoToDefaults(element_info[element].change); if (IS_CUSTOM_ELEMENT(element) || IS_GROUP_ELEMENT(element) || IS_INTERNAL_ELEMENT(element)) { for (j = 0; j < MAX_ELEMENT_NAME_LEN + 1; j++) - ei->description[j] = '\0'; + element_info[element].description[j] = '\0'; - if (ei->custom_description != NULL) - strncpy(ei->description, ei->custom_description,MAX_ELEMENT_NAME_LEN); + if (element_info[element].custom_description != NULL) + strncpy(element_info[element].description, + element_info[element].custom_description,MAX_ELEMENT_NAME_LEN); else - strcpy(ei->description, ei->editor_description); + strcpy(element_info[element].description, + element_info[element].editor_description); - ei->use_gfx_element = FALSE; - ei->gfx_element = EL_EMPTY_SPACE; + element_info[element].use_gfx_element = FALSE; + element_info[element].gfx_element = EL_EMPTY_SPACE; - ei->modified_settings = FALSE; + element_info[element].modified_settings = FALSE; } if (IS_CUSTOM_ELEMENT(element) || IS_INTERNAL_ELEMENT(element)) { - ei->access_direction = MV_ALL_DIRECTIONS; + element_info[element].access_direction = MV_ALL_DIRECTIONS; - ei->collect_score_initial = 10; /* special default */ - ei->collect_count_initial = 1; /* special default */ + element_info[element].collect_score = 10; /* special default */ + element_info[element].collect_count = 1; /* special default */ - ei->ce_value_fixed_initial = 0; - ei->ce_value_random_initial = 0; - ei->use_last_ce_value = FALSE; + element_info[element].push_delay_fixed = -1; /* initialize later */ + element_info[element].push_delay_random = -1; /* initialize later */ + element_info[element].drop_delay_fixed = 0; + element_info[element].drop_delay_random = 0; + element_info[element].move_delay_fixed = 0; + element_info[element].move_delay_random = 0; - ei->push_delay_fixed = -1; /* initialize later */ - ei->push_delay_random = -1; /* initialize later */ - ei->drop_delay_fixed = 0; - ei->drop_delay_random = 0; - ei->move_delay_fixed = 0; - ei->move_delay_random = 0; + element_info[element].move_pattern = MV_ALL_DIRECTIONS; + element_info[element].move_direction_initial = MV_START_AUTOMATIC; + element_info[element].move_stepsize = TILEX / 8; - ei->move_pattern = MV_ALL_DIRECTIONS; - ei->move_direction_initial = MV_START_AUTOMATIC; - ei->move_stepsize = TILEX / 8; + element_info[element].move_enter_element = EL_EMPTY_SPACE; + element_info[element].move_leave_element = EL_EMPTY_SPACE; + element_info[element].move_leave_type = LEAVE_TYPE_UNLIMITED; - ei->move_enter_element = EL_EMPTY_SPACE; - ei->move_leave_element = EL_EMPTY_SPACE; - ei->move_leave_type = LEAVE_TYPE_UNLIMITED; + element_info[element].slippery_type = SLIPPERY_ANY_RANDOM; - ei->slippery_type = SLIPPERY_ANY_RANDOM; - - ei->explosion_type = EXPLODES_3X3; - ei->explosion_delay = 16; - ei->ignition_delay = 8; + element_info[element].explosion_type = EXPLODES_3X3; + element_info[element].explosion_delay = 16; + element_info[element].ignition_delay = 8; for (x = 0; x < 3; x++) for (y = 0; y < 3; y++) - ei->content.e[x][y] = EL_EMPTY_SPACE; + element_info[element].content[x][y] = EL_EMPTY_SPACE; - ei->access_type = 0; - ei->access_layer = 0; - ei->access_protected = 0; - ei->walk_to_action = 0; - ei->smash_targets = 0; - ei->deadliness = 0; + element_info[element].access_type = 0; + element_info[element].access_layer = 0; + element_info[element].access_protected = 0; + element_info[element].walk_to_action = 0; + element_info[element].smash_targets = 0; + element_info[element].deadliness = 0; - ei->can_explode_by_fire = FALSE; - ei->can_explode_smashed = FALSE; - ei->can_explode_impact = FALSE; + element_info[element].can_explode_by_fire = FALSE; + element_info[element].can_explode_smashed = FALSE; + element_info[element].can_explode_impact = FALSE; - ei->current_change_page = 0; + element_info[element].current_change_page = 0; /* start with no properties at all */ for (j = 0; j < NUM_EP_BITFIELDS; j++) @@ -598,21 +321,18 @@ static void setLevelInfoToDefaults(struct LevelInfo *level) if (IS_GROUP_ELEMENT(element) || IS_INTERNAL_ELEMENT(element)) { - struct ElementGroupInfo *group; - /* initialize memory for list of elements in group */ - if (ei->group == NULL) - ei->group = checked_malloc(sizeof(struct ElementGroupInfo)); - - group = ei->group; + if (element_info[element].group == NULL) + element_info[element].group = + checked_malloc(sizeof(struct ElementGroupInfo)); for (j = 0; j < MAX_ELEMENTS_IN_GROUP; j++) - group->element[j] = EL_EMPTY_SPACE; + element_info[element].group->element[j] = EL_EMPTY_SPACE; /* default: only one element in group */ - group->num_elements = 1; + element_info[element].group->num_elements = 1; - group->choice_mode = ANIM_RANDOM; + element_info[element].group->choice_mode = ANIM_RANDOM; } } @@ -844,6 +564,48 @@ static int getFiletypeFromID(char *filetype_id) return filetype; } +#if 0 +static void OLD_determineLevelFileInfo_Filename(struct LevelFileInfo *lfi) +{ + /* special case: level number is negative => check for level template file */ + if (lfi->nr < 0) + { + setLevelFileInfo_SingleLevelFilename(lfi, LEVEL_FILE_TYPE_RND); + + return; + } + + if (leveldir_current->level_filename != NULL) + { + int filetype = getFiletypeFromID(leveldir_current->level_filetype); + + /* check for file name/pattern specified in "levelinfo.conf" */ + setLevelFileInfo_SingleLevelFilename(lfi, filetype); + + if (fileExists(lfi->filename)) + return; + } + + /* check for native Rocks'n'Diamonds level file */ + setLevelFileInfo_SingleLevelFilename(lfi, LEVEL_FILE_TYPE_RND); + if (fileExists(lfi->filename)) + return; + + /* check for classic Emerald Mine level file */ + setLevelFileInfo_SingleLevelFilename(lfi, LEVEL_FILE_TYPE_EM); + if (fileExists(lfi->filename)) + return; + + /* check for various packed level file formats */ + setLevelFileInfo_PackedLevelFilename(lfi, LEVEL_FILE_TYPE_UNKNOWN); + if (fileExists(lfi->filename)) + return; + + /* no known level file found -- try to use default values */ + setLevelFileInfo_SingleLevelFilename(lfi, LEVEL_FILE_TYPE_UNKNOWN); +} +#endif + static void determineLevelFileInfo_Filename(struct LevelFileInfo *lfi) { int nr = lfi->nr; @@ -922,6 +684,7 @@ 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 */ @@ -933,6 +696,24 @@ static void setLevelFileInfo(struct LevelFileInfo *level_file_info, int nr) determineLevelFileInfo_Filetype(level_file_info); } +#else + +static struct LevelFileInfo *getLevelFileInfo(int nr) +{ + static struct LevelFileInfo level_file_info; + + /* 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); + + return &level_file_info; +} +#endif + /* ------------------------------------------------------------------------- */ /* functions for loading R'n'D level */ /* ------------------------------------------------------------------------- */ @@ -941,6 +722,7 @@ int getMappedElement(int element) { /* remap some (historic, now obsolete) elements */ +#if 1 switch (element) { case EL_PLAYER_OBSOLETE: @@ -983,6 +765,18 @@ int getMappedElement(int element) } break; } +#else + if (element >= NUM_FILE_ELEMENTS) + { + Error(ERR_WARN, "invalid level element %d", element); + + element = EL_UNKNOWN; + } + else if (element == EL_PLAYER_OBSOLETE) + element = EL_PLAYER_1; + else if (element == EL_KEY_OBSOLETE) + element = EL_KEY_1; +#endif return element; } @@ -1042,7 +836,7 @@ static int LoadLevel_HEAD(FILE *file, int chunk_size, struct LevelInfo *level) for (i = 0; i < STD_ELEMENT_CONTENTS; i++) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - level->yamyam_content[i].e[x][y] = getMappedElement(getFile8Bit(file)); + level->yamyam_content[i][x][y] = getMappedElement(getFile8Bit(file)); level->amoeba_speed = getFile8Bit(file); level->time_magic_wall = getFile8Bit(file); @@ -1146,7 +940,7 @@ static int LoadLevel_CONT(FILE *file, int chunk_size, struct LevelInfo *level) for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - level->yamyam_content[i].e[x][y] = + level->yamyam_content[i][x][y] = getMappedElement(level->encoding_16bit_field ? getFile16BitBE(file) : getFile8Bit(file)); return chunk_size; @@ -1182,7 +976,7 @@ static int LoadLevel_CNT2(FILE *file, int chunk_size, struct LevelInfo *level) for (i = 0; i < num_contents; i++) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - level->yamyam_content[i].e[x][y] = content_array[i][x][y]; + level->yamyam_content[i][x][y] = content_array[i][x][y]; } else if (element == EL_BD_AMOEBA) { @@ -1297,7 +1091,6 @@ static int LoadLevel_CUS3(FILE *file, int chunk_size, struct LevelInfo *level) for (i = 0; i < num_changed_custom_elements; i++) { int element = getFile16BitBE(file); - struct ElementInfo *ei = &element_info[element]; unsigned long event_bits; if (!IS_CUSTOM_ELEMENT(element)) @@ -1308,66 +1101,70 @@ static int LoadLevel_CUS3(FILE *file, int chunk_size, struct LevelInfo *level) } for (j = 0; j < MAX_ELEMENT_NAME_LEN; j++) - ei->description[j] = getFile8Bit(file); - ei->description[MAX_ELEMENT_NAME_LEN] = 0; + element_info[element].description[j] = getFile8Bit(file); + element_info[element].description[MAX_ELEMENT_NAME_LEN] = 0; Properties[element][EP_BITFIELD_BASE] = getFile32BitBE(file); /* some free bytes for future properties and padding */ ReadUnusedBytesFromFile(file, 7); - ei->use_gfx_element = getFile8Bit(file); - ei->gfx_element = getMappedElement(getFile16BitBE(file)); + element_info[element].use_gfx_element = getFile8Bit(file); + element_info[element].gfx_element = + getMappedElement(getFile16BitBE(file)); - ei->collect_score_initial = getFile8Bit(file); - ei->collect_count_initial = getFile8Bit(file); + element_info[element].collect_score = getFile8Bit(file); + element_info[element].collect_count = getFile8Bit(file); - ei->push_delay_fixed = getFile16BitBE(file); - ei->push_delay_random = getFile16BitBE(file); - ei->move_delay_fixed = getFile16BitBE(file); - ei->move_delay_random = getFile16BitBE(file); + element_info[element].push_delay_fixed = getFile16BitBE(file); + element_info[element].push_delay_random = getFile16BitBE(file); + element_info[element].move_delay_fixed = getFile16BitBE(file); + element_info[element].move_delay_random = getFile16BitBE(file); - ei->move_pattern = getFile16BitBE(file); - ei->move_direction_initial = getFile8Bit(file); - ei->move_stepsize = getFile8Bit(file); + element_info[element].move_pattern = getFile16BitBE(file); + element_info[element].move_direction_initial = getFile8Bit(file); + element_info[element].move_stepsize = getFile8Bit(file); for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - ei->content.e[x][y] = getMappedElement(getFile16BitBE(file)); + element_info[element].content[x][y] = + getMappedElement(getFile16BitBE(file)); event_bits = getFile32BitBE(file); for (j = 0; j < NUM_CHANGE_EVENTS; j++) if (event_bits & (1 << j)) - ei->change->has_event[j] = TRUE; + element_info[element].change->has_event[j] = TRUE; - ei->change->target_element = getMappedElement(getFile16BitBE(file)); + element_info[element].change->target_element = + getMappedElement(getFile16BitBE(file)); - ei->change->delay_fixed = getFile16BitBE(file); - ei->change->delay_random = getFile16BitBE(file); - ei->change->delay_frames = getFile16BitBE(file); + element_info[element].change->delay_fixed = getFile16BitBE(file); + element_info[element].change->delay_random = getFile16BitBE(file); + element_info[element].change->delay_frames = getFile16BitBE(file); - ei->change->trigger_element = getMappedElement(getFile16BitBE(file)); + element_info[element].change->trigger_element = + getMappedElement(getFile16BitBE(file)); - ei->change->explode = getFile8Bit(file); - ei->change->use_target_content = getFile8Bit(file); - ei->change->only_if_complete = getFile8Bit(file); - ei->change->use_random_replace = getFile8Bit(file); + element_info[element].change->explode = getFile8Bit(file); + element_info[element].change->use_target_content = getFile8Bit(file); + element_info[element].change->only_if_complete = getFile8Bit(file); + element_info[element].change->use_random_replace = getFile8Bit(file); - ei->change->random_percentage = getFile8Bit(file); - ei->change->replace_when = getFile8Bit(file); + element_info[element].change->random_percentage = getFile8Bit(file); + element_info[element].change->replace_when = getFile8Bit(file); for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - ei->change->target_content.e[x][y] = + element_info[element].change->target_content[x][y] = getMappedElement(getFile16BitBE(file)); - ei->slippery_type = getFile8Bit(file); + element_info[element].slippery_type = getFile8Bit(file); /* some free bytes for future properties and padding */ ReadUnusedBytesFromFile(file, LEVEL_CPART_CUS3_UNUSED); /* mark that this custom element has been modified */ - ei->modified_settings = TRUE; + element_info[element].modified_settings = TRUE; } return chunk_size; @@ -1380,8 +1177,6 @@ static int LoadLevel_CUS4(FILE *file, int chunk_size, struct LevelInfo *level) int element; int i, j, x, y; - /* ---------- custom element base property values (96 bytes) ------------- */ - element = getFile16BitBE(file); if (!IS_CUSTOM_ELEMENT(element)) @@ -1403,22 +1198,23 @@ static int LoadLevel_CUS4(FILE *file, int chunk_size, struct LevelInfo *level) ei->num_change_pages = getFile8Bit(file); + /* some free bytes for future base property values and padding */ + ReadUnusedBytesFromFile(file, 5); + chunk_size_expected = LEVEL_CHUNK_CUS4_SIZE(ei->num_change_pages); if (chunk_size_expected != chunk_size) { - ReadUnusedBytesFromFile(file, chunk_size - 43); + ReadUnusedBytesFromFile(file, chunk_size - 48); return chunk_size_expected; } - ei->ce_value_fixed_initial = getFile16BitBE(file); - ei->ce_value_random_initial = getFile16BitBE(file); - ei->use_last_ce_value = getFile8Bit(file); + /* read custom property values */ ei->use_gfx_element = getFile8Bit(file); ei->gfx_element = getMappedElement(getFile16BitBE(file)); - ei->collect_score_initial = getFile8Bit(file); - ei->collect_count_initial = getFile8Bit(file); + ei->collect_score = getFile8Bit(file); + ei->collect_count = getFile8Bit(file); ei->drop_delay_fixed = getFile8Bit(file); ei->push_delay_fixed = getFile8Bit(file); @@ -1436,7 +1232,7 @@ static int LoadLevel_CUS4(FILE *file, int chunk_size, struct LevelInfo *level) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - ei->content.e[x][y] = getMappedElement(getFile16BitBE(file)); + ei->content[x][y] = getMappedElement(getFile16BitBE(file)); ei->move_enter_element = getMappedElement(getFile16BitBE(file)); ei->move_leave_element = getMappedElement(getFile16BitBE(file)); @@ -1454,7 +1250,7 @@ static int LoadLevel_CUS4(FILE *file, int chunk_size, struct LevelInfo *level) /* some free bytes for future custom property values and padding */ ReadUnusedBytesFromFile(file, 1); - /* ---------- change page property values (48 bytes) --------------------- */ + /* read change property values */ setElementChangePages(ei, ei->num_change_pages); @@ -1466,9 +1262,8 @@ static int LoadLevel_CUS4(FILE *file, int chunk_size, struct LevelInfo *level) /* always start with reliable default values */ setElementChangeInfoToDefaults(change); - /* bits 0 - 31 of "has_event[]" ... */ event_bits = getFile32BitBE(file); - for (j = 0; j < MIN(NUM_CHANGE_EVENTS, 32); j++) + for (j = 0; j < NUM_CHANGE_EVENTS; j++) if (event_bits & (1 << j)) change->has_event[j] = TRUE; @@ -1490,28 +1285,27 @@ static int LoadLevel_CUS4(FILE *file, int chunk_size, struct LevelInfo *level) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - change->target_content.e[x][y]= getMappedElement(getFile16BitBE(file)); + change->target_content[x][y] = getMappedElement(getFile16BitBE(file)); change->can_change = getFile8Bit(file); change->trigger_side = getFile8Bit(file); +#if 1 change->trigger_player = getFile8Bit(file); change->trigger_page = getFile8Bit(file); change->trigger_page = (change->trigger_page == CH_PAGE_ANY_FILE ? CH_PAGE_ANY : (1 << change->trigger_page)); - change->has_action = getFile8Bit(file); - change->action_type = getFile8Bit(file); - change->action_mode = getFile8Bit(file); - change->action_arg = getFile16BitBE(file); + /* some free bytes for future change property values and padding */ + ReadUnusedBytesFromFile(file, 6); - /* ... bits 32 - 39 of "has_event[]" (not nice, but downward compatible) */ - event_bits = getFile8Bit(file); - for (j = 32; j < NUM_CHANGE_EVENTS; j++) - if (event_bits & (1 << (j - 32))) - change->has_event[j] = TRUE; +#else + + /* some free bytes for future change property values and padding */ + ReadUnusedBytesFromFile(file, 8); +#endif } /* mark this custom element as modified */ @@ -1564,96 +1358,6 @@ static int LoadLevel_GRP1(FILE *file, int chunk_size, struct LevelInfo *level) return chunk_size; } -static int LoadLevel_CONF(FILE *file, int chunk_size, struct LevelInfo *level) -{ - int real_chunk_size = 0; - int i; - - while (!feof(file)) - { - int element = getFile16BitBE(file); - int type = getFile8Bit(file); - int bytes = type & CONF_MASK_BYTES; - boolean element_found = FALSE; - - real_chunk_size += 3; - - li = *level; /* copy level information into temporary buffer */ - - if (bytes == CONF_MASK_MULTI_BYTES) - { - int num_bytes = getFile16BitBE(file); - byte *buffer = checked_malloc(num_bytes); - - ReadBytesFromFile(file, buffer, num_bytes); - - for (i = 0; element_conf[i].element != -1; i++) - { - if (element_conf[i].element == element && - element_conf[i].type == type) - { - element_found = TRUE; - - if (type == CONF_VALUE_CONTENT_8) - { - struct Content *content= (struct Content *)(element_conf[i].value); - int num_contents = num_bytes / CONF_CONTENT_NUM_BYTES; - int c, x, y; - - for (c = 0; c < num_contents; c++) - for (y = 0; y < 3; y++) - for (x = 0; x < 3; x++) - content[c].e[x][y] = - getMappedElement(CONF_CONTENT_ELEMENT(buffer, c, x, y)); - } - else - element_found = FALSE; - - break; - } - } - - checked_free(buffer); - - real_chunk_size += 2 + num_bytes; - } - else - { - int value = (bytes == CONF_MASK_1_BYTE ? getFile8Bit (file) : - bytes == CONF_MASK_2_BYTE ? getFile16BitBE(file) : - bytes == CONF_MASK_4_BYTE ? getFile32BitBE(file) : 0); - - for (i = 0; element_conf[i].element != -1; i++) - { - if (element_conf[i].element == element && - element_conf[i].type == type) - { - if (CONF_VALUE_BOOLEAN(type)) - *(boolean *)(element_conf[i].value) = value; - else - *(int *) (element_conf[i].value) = value; - - element_found = TRUE; - - break; - } - } - - real_chunk_size += CONF_VALUE_NUM_BYTES(bytes); - } - - *level = li; /* copy temporary buffer back to level information */ - - if (!element_found) - Error(ERR_WARN, "cannot load CONF value for element %d", element); - - if (type == CONF_LAST_ENTRY || real_chunk_size >= chunk_size) - break; - } - - return real_chunk_size; -} - static void LoadLevelFromFileInfo_RND(struct LevelInfo *level, struct LevelFileInfo *level_file_info) { @@ -1745,8 +1449,6 @@ static void LoadLevelFromFileInfo_RND(struct LevelInfo *level, { "CUS3", -1, LoadLevel_CUS3 }, { "CUS4", -1, LoadLevel_CUS4 }, { "GRP1", -1, LoadLevel_GRP1 }, - { "CONF", -1, LoadLevel_CONF }, - { NULL, 0, NULL } }; @@ -2189,7 +1891,7 @@ static void OLD_LoadLevelFromFileInfo_EM(struct LevelInfo *level, for (i = 0; i < level->num_yamyam_contents; i++) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - level->yamyam_content[i].e[x][y] = + level->yamyam_content[i][x][y] = map_em_element_yam(header[i * 9 + y * 3 + x]); level->amoeba_speed = (header[52] * 256 + header[53]) % 256; @@ -2216,7 +1918,7 @@ static void OLD_LoadLevelFromFileInfo_EM(struct LevelInfo *level, level->field[x][y] = EL_PLAYER_2; } -#endif +#else void CopyNativeLevel_RND_to_EM(struct LevelInfo *level) { @@ -2258,7 +1960,7 @@ void CopyNativeLevel_RND_to_EM(struct LevelInfo *level) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) lev->eater_array[i][y * 3 + x] = - map_element_RND_to_EM(level->yamyam_content[i].e[x][y]); + map_element_RND_to_EM(level->yamyam_content[i][x][y]); lev->amoeba_time = level->amoeba_speed; lev->wonderwall_time_initial = level->time_magic_wall; @@ -2269,7 +1971,6 @@ void CopyNativeLevel_RND_to_EM(struct LevelInfo *level) lev->ball_random = level->ball_random; lev->ball_state_initial = level->ball_state_initial; lev->ball_time = level->ball_time; - lev->num_ball_arrays = level->num_ball_contents; lev->lenses_score = level->lenses_score; lev->magnify_score = level->magnify_score; @@ -2277,17 +1978,13 @@ void CopyNativeLevel_RND_to_EM(struct LevelInfo *level) lev->lenses_time = level->lenses_time; lev->magnify_time = level->magnify_time; + lev->wind_direction_initial = level->wind_direction_initial; - lev->wind_direction_initial = - map_direction_RND_to_EM(level->wind_direction_initial); - lev->wind_cnt_initial = (level->wind_direction_initial != MV_NONE ? - lev->wind_time : 0); - - for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) + for (i = 0; i < NUM_MAGIC_BALL_CONTENTS; i++) for (j = 0; j < 8; j++) lev->ball_array[i][j] = map_element_RND_to_EM(level-> - ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]]); + ball_content[i][ball_xy[j][0]][ball_xy[j][1]]); for (i = 0; i < 16; i++) lev->android_array[i] = FALSE; /* !!! YET TO COME !!! */ @@ -2375,7 +2072,7 @@ void CopyNativeLevel_EM_to_RND(struct LevelInfo *level) for (i = 0; i < level->num_yamyam_contents; i++) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - level->yamyam_content[i].e[x][y] = + level->yamyam_content[i][x][y] = map_element_EM_to_RND(lev->eater_array[i][y * 3 + x]); level->amoeba_speed = lev->amoeba_time; @@ -2387,7 +2084,6 @@ void CopyNativeLevel_EM_to_RND(struct LevelInfo *level) level->ball_random = lev->ball_random; level->ball_state_initial = lev->ball_state_initial; level->ball_time = lev->ball_time; - level->num_ball_contents = lev->num_ball_arrays; level->lenses_score = lev->lenses_score; level->magnify_score = lev->magnify_score; @@ -2395,13 +2091,11 @@ void CopyNativeLevel_EM_to_RND(struct LevelInfo *level) level->lenses_time = lev->lenses_time; level->magnify_time = lev->magnify_time; + level->wind_direction_initial = lev->wind_direction_initial; - level->wind_direction_initial = - map_direction_EM_to_RND(lev->wind_direction_initial); - - for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) + for (i = 0; i < NUM_MAGIC_BALL_CONTENTS; i++) for (j = 0; j < 8; j++) - level->ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]] = + level->ball_content[i][ball_xy[j][0]][ball_xy[j][1]] = map_element_EM_to_RND(lev->ball_array[i][j]); for (i = 0; i < 16; i++) @@ -2434,6 +2128,8 @@ static void LoadLevelFromFileInfo_EM(struct LevelInfo *level, level->no_valid_file = TRUE; } +#endif + void CopyNativeLevel_RND_to_Native(struct LevelInfo *level) { if (level->game_engine_type == GAME_ENGINE_TYPE_EM) @@ -2605,7 +2301,7 @@ static void LoadLevelFromFileStream_SP(FILE *file, struct LevelInfo *level, for (i = 0; i < level->num_yamyam_contents; i++) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - level->yamyam_content[i].e[x][y] = EL_EMPTY; + level->yamyam_content[i][x][y] = EL_EMPTY; } static void LoadLevelFromFileInfo_SP(struct LevelInfo *level, @@ -2849,107 +2545,157 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename) if (leveldir_current == NULL) /* only when dumping level */ return; - if (leveldir_current->latest_engine) +#if 0 + printf("::: sort_priority: %d\n", leveldir_current->sort_priority); +#endif + + /* determine correct game engine version of current level */ +#if 1 + if (!leveldir_current->latest_engine) +#else + if (IS_LEVELCLASS_CONTRIB(leveldir_current) || + IS_LEVELCLASS_PRIVATE(leveldir_current) || + IS_LEVELCLASS_UNDEFINED(leveldir_current)) +#endif { - /* ---------- use latest game engine ----------------------------------- */ +#if 0 + printf("\n::: This level is private or contributed: '%s'\n", filename); +#endif - /* For all levels which are forced to use the latest game engine version - (normally all but user contributed, private and undefined levels), set - the game engine version to the actual version; this allows for actual - corrections in the game engine to take effect for existing, converted - levels (from "classic" or other existing games) to make the emulation - of the corresponding game more accurate, while (hopefully) not breaking - existing levels created from other players. */ +#if 0 + printf("\n::: Use the stored game engine version for this level\n"); +#endif - level->game_version = GAME_VERSION_ACTUAL; + /* For all levels which are not forced to use the latest game engine + version (normally user contributed, private and undefined levels), + use the version of the game engine the levels were created for. - /* Set special EM style gems behaviour: EM style gems slip down from - normal, steel and growing wall. As this is a more fundamental change, - it seems better to set the default behaviour to "off" (as it is more - natural) and make it configurable in the level editor (as a property - of gem style elements). Already existing converted levels (neither - private nor contributed levels) are changed to the new behaviour. */ + Since 2.0.1, the game engine version is now directly stored + in the level file (chunk "VERS"), so there is no need anymore + to set the game version from the file version (except for old, + pre-2.0 levels, where the game version is still taken from the + file format version used to store the level -- see above). */ - if (level->file_version < FILE_VERSION_2_0) +#if 1 + /* player was faster than enemies in 1.0.0 and before */ + if (level->file_version == FILE_VERSION_1_0) + level->double_speed = TRUE; +#else + /* do some special adjustments to support older level versions */ + if (level->file_version == FILE_VERSION_1_0) + { + Error(ERR_WARN, "level file '%s' has version number 1.0", filename); + Error(ERR_WARN, "using high speed movement for player"); + + /* player was faster than monsters in (pre-)1.0 levels */ + level->double_speed = TRUE; + } +#endif + + /* default behaviour for EM style gems was "slippery" only in 2.0.1 */ + if (level->game_version == VERSION_IDENT(2,0,1,0)) level->em_slippery_gems = TRUE; - return; - } + /* 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; - /* ---------- use game engine the level was created with ----------------- */ + /* only few elements were able to actively move into acid before 3.1.0 */ + /* trigger settings did not exist before 3.1.0; set to default "any" */ + if (level->game_version < VERSION_IDENT(3,1,0,0)) + { + int i, j; - /* For all levels which are not forced to use the latest game engine - version (normally user contributed, private and undefined levels), - use the version of the game engine the levels were created for. + /* correct "can move into acid" settings (all zero in old levels) */ - Since 2.0.1, the game engine version is now directly stored - in the level file (chunk "VERS"), so there is no need anymore - to set the game version from the file version (except for old, - pre-2.0 levels, where the game version is still taken from the - file format version used to store the level -- see above). */ + level->can_move_into_acid_bits = 0; /* nothing can move into acid */ + level->dont_collide_with_bits = 0; /* nothing is deadly when colliding */ - /* player was faster than enemies in 1.0.0 and before */ - if (level->file_version == FILE_VERSION_1_0) - level->double_speed = TRUE; + setMoveIntoAcidProperty(level, EL_ROBOT, TRUE); + setMoveIntoAcidProperty(level, EL_SATELLITE, TRUE); + setMoveIntoAcidProperty(level, EL_PENGUIN, TRUE); + setMoveIntoAcidProperty(level, EL_BALLOON, TRUE); - /* default behaviour for EM style gems was "slippery" only in 2.0.1 */ - if (level->game_version == VERSION_IDENT(2,0,1,0)) - level->em_slippery_gems = TRUE; + for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) + SET_PROPERTY(EL_CUSTOM_START + i, EP_CAN_MOVE_INTO_ACID, 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; + /* correct trigger settings (stored as zero == "none" in old levels) */ - if (level->game_version < VERSION_IDENT(3,2,0,5)) - { - /* time orb caused limited time in endless time levels before 3.2.0-5 */ - level->use_time_orb_bug = TRUE; + for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) + { + int element = EL_CUSTOM_START + i; + struct ElementInfo *ei = &element_info[element]; - /* default behaviour for snapping was "no snap delay" before 3.2.0-5 */ - level->block_snap_field = FALSE; + for (j = 0; j < ei->num_change_pages; j++) + { + struct ElementChangeInfo *change = &ei->change_page[j]; - /* extra time score was same value as time left score before 3.2.0-5 */ - level->extra_time_score = level->score[SC_TIME_BONUS]; + change->trigger_player = CH_PLAYER_ANY; + change->trigger_page = CH_PAGE_ANY; + } + } + } - /* time bonus score was given for 10 s instead of 1 s before 3.2.0-5 */ - level->score[SC_TIME_BONUS] /= 10; - } +#if 0 /* !!! MOVED TO "game.c", BECAUSE CAN CHANGE INSIDE LEVEL EDITOR !!! */ +#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 - /* only few elements were able to actively move into acid before 3.1.0 */ - /* trigger settings did not exist before 3.1.0; set to default "any" */ - if (level->game_version < VERSION_IDENT(3,1,0,0)) - { - int i, j; + /* 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); - /* correct "can move into acid" settings (all zero in old levels) */ + level->block_last_field = TRUE; + level->sp_block_last_field = TRUE; + } +#endif +#endif - level->can_move_into_acid_bits = 0; /* nothing can move into acid */ - level->dont_collide_with_bits = 0; /* nothing is deadly when colliding */ + } + else /* always use the latest game engine version */ + { +#if 0 + printf("\n::: ALWAYS USE LATEST ENGINE FOR THIS LEVEL: [%d] '%s'\n", + leveldir_current->sort_priority, filename); +#endif - setMoveIntoAcidProperty(level, EL_ROBOT, TRUE); - setMoveIntoAcidProperty(level, EL_SATELLITE, TRUE); - setMoveIntoAcidProperty(level, EL_PENGUIN, TRUE); - setMoveIntoAcidProperty(level, EL_BALLOON, TRUE); +#if 0 + printf("\n::: Use latest game engine version for this level.\n"); +#endif - for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) - SET_PROPERTY(EL_CUSTOM_START + i, EP_CAN_MOVE_INTO_ACID, TRUE); + /* For all levels which are forced to use the latest game engine version + (normally all but user contributed, private and undefined levels), set + the game engine version to the actual version; this allows for actual + corrections in the game engine to take effect for existing, converted + levels (from "classic" or other existing games) to make the emulation + of the corresponding game more accurate, while (hopefully) not breaking + existing levels created from other players. */ - /* correct trigger settings (stored as zero == "none" in old levels) */ +#if 0 + printf("::: changing engine from %d to %d\n", + level->game_version, GAME_VERSION_ACTUAL); +#endif - for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) - { - int element = EL_CUSTOM_START + i; - struct ElementInfo *ei = &element_info[element]; + level->game_version = GAME_VERSION_ACTUAL; - for (j = 0; j < ei->num_change_pages; j++) - { - struct ElementChangeInfo *change = &ei->change_page[j]; + /* Set special EM style gems behaviour: EM style gems slip down from + normal, steel and growing wall. As this is a more fundamental change, + it seems better to set the default behaviour to "off" (as it is more + natural) and make it configurable in the level editor (as a property + of gem style elements). Already existing converted levels (neither + private nor contributed levels) are changed to the new behaviour. */ - change->trigger_player = CH_PLAYER_ANY; - change->trigger_page = CH_PAGE_ANY; - } - } + if (level->file_version < FILE_VERSION_2_0) + level->em_slippery_gems = TRUE; } + +#if 0 + printf("::: => %d\n", level->game_version); +#endif } static void LoadLevel_InitElements(struct LevelInfo *level, char *filename) @@ -2957,8 +2703,7 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename) int i, j, x, y; /* map custom element change events that have changed in newer versions - (these following values were accidentally changed in version 3.0.1) - (this seems to be needed only for 'ab_levelset3' and 'ab_levelset4') */ + (these following values were accidentally changed in version 3.0.1) */ if (level->game_version <= VERSION_IDENT(3,0,0,0)) { for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) @@ -2966,7 +2711,7 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename) int element = EL_CUSTOM_START + i; /* order of checking and copying events to be mapped is important */ - for (j = CE_BY_OTHER_ACTION; j >= CE_VALUE_GETS_ZERO; j--) + for (j = CE_BY_OTHER_ACTION; j >= CE_BY_PLAYER_OBSOLETE; j--) { if (HAS_CHANGE_EVENT(element, j - 2)) { @@ -2987,63 +2732,50 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename) } } - /* initialize "can_change" field for old levels with only one change page */ - if (level->game_version <= VERSION_IDENT(3,0,2,0)) + /* some custom element change events get mapped since version 3.0.3 */ + for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) { - for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) + int element = EL_CUSTOM_START + i; + + if (HAS_CHANGE_EVENT(element, CE_BY_PLAYER_OBSOLETE) || + HAS_CHANGE_EVENT(element, CE_BY_COLLISION_OBSOLETE)) { - int element = EL_CUSTOM_START + i; + SET_CHANGE_EVENT(element, CE_BY_PLAYER_OBSOLETE, FALSE); + SET_CHANGE_EVENT(element, CE_BY_COLLISION_OBSOLETE, FALSE); - if (CAN_CHANGE(element)) - element_info[element].change->can_change = TRUE; + SET_CHANGE_EVENT(element, CE_BY_DIRECT_ACTION, TRUE); } } - /* correct custom element values (for old levels without these options) */ - if (level->game_version < VERSION_IDENT(3,1,1,0)) + /* initialize "can_change" field for old levels with only one change page */ + if (level->game_version <= VERSION_IDENT(3,0,2,0)) { for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) { int element = EL_CUSTOM_START + i; - struct ElementInfo *ei = &element_info[element]; - - if (ei->access_direction == MV_NO_DIRECTION) - ei->access_direction = MV_ALL_DIRECTIONS; - -#if 0 - for (j = 0; j < ei->num_change_pages; j++) - { - struct ElementChangeInfo *change = &ei->change_page[j]; - if (change->trigger_side == CH_SIDE_NONE) - change->trigger_side = CH_SIDE_ANY; - } -#endif + if (CAN_CHANGE(element)) + element_info[element].change->can_change = TRUE; } } -#if 1 - /* correct custom element values (fix invalid values for all versions) */ - if (1) + /* correct custom element values (for old levels without these options) */ + for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) { - for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) - { - int element = EL_CUSTOM_START + i; - struct ElementInfo *ei = &element_info[element]; + int element = EL_CUSTOM_START + i; + struct ElementInfo *ei = &element_info[element]; - for (j = 0; j < ei->num_change_pages; j++) - { - struct ElementChangeInfo *change = &ei->change_page[j]; + if (ei->access_direction == MV_NO_MOVING) + ei->access_direction = MV_ALL_DIRECTIONS; - if (change->trigger_player == CH_PLAYER_NONE) - change->trigger_player = CH_PLAYER_ANY; + for (j = 0; j < ei->num_change_pages; j++) + { + struct ElementChangeInfo *change = &ei->change_page[j]; - if (change->trigger_side == CH_SIDE_NONE) - change->trigger_side = CH_SIDE_ANY; - } + if (change->trigger_side == CH_SIDE_NONE) + change->trigger_side = CH_SIDE_ANY; } } -#endif /* initialize "can_explode" field for old levels which did not store this */ /* !!! CHECK THIS -- "<= 3,1,0,0" IS PROBABLY WRONG !!! */ @@ -3078,14 +2810,39 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename) } } +#if 0 + /* set default push delay values (corrected since version 3.0.7-1) */ + if (level->game_version < VERSION_IDENT(3,0,7,1)) + { + game.default_push_delay_fixed = 2; + game.default_push_delay_random = 8; + } + else + { + game.default_push_delay_fixed = 8; + game.default_push_delay_random = 8; + } + + /* set uninitialized push delay values of custom elements in older levels */ + for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) + { + int element = EL_CUSTOM_START + i; + + if (element_info[element].push_delay_fixed == -1) + element_info[element].push_delay_fixed = game.default_push_delay_fixed; + if (element_info[element].push_delay_random == -1) + element_info[element].push_delay_random = game.default_push_delay_random; + } +#endif + /* map elements that have changed in newer versions */ level->amoeba_content = getMappedElementByVersion(level->amoeba_content, level->game_version); for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) for (x = 0; x < 3; x++) for (y = 0; y < 3; y++) - level->yamyam_content[i].e[x][y] = - getMappedElementByVersion(level->yamyam_content[i].e[x][y], + level->yamyam_content[i][x][y] = + getMappedElementByVersion(level->yamyam_content[i][x][y], level->game_version); /* initialize element properties for level editor etc. */ @@ -3098,9 +2855,37 @@ static void LoadLevel_InitPlayfield(struct LevelInfo *level, char *filename) /* map elements that have changed in newer versions */ for (y = 0; y < level->fieldy; y++) + { for (x = 0; x < level->fieldx; x++) - level->field[x][y] = getMappedElementByVersion(level->field[x][y], - level->game_version); + { + int element = level->field[x][y]; + +#if 1 + element = getMappedElementByVersion(element, level->game_version); +#else + if (level->game_version <= VERSION_IDENT(2,2,0,0)) + { + /* map game font elements */ + element = (element == EL_CHAR('[') ? EL_CHAR_AUMLAUT : + element == EL_CHAR('\\') ? EL_CHAR_OUMLAUT : + element == EL_CHAR(']') ? EL_CHAR_UUMLAUT : + element == EL_CHAR('^') ? EL_CHAR_COPYRIGHT : element); + } + + if (level->game_version < VERSION_IDENT(3,0,0,0)) + { + /* map Supaplex gravity tube elements */ + element = (element == EL_SP_GRAVITY_PORT_LEFT ? EL_SP_PORT_LEFT : + element == EL_SP_GRAVITY_PORT_RIGHT ? EL_SP_PORT_RIGHT : + element == EL_SP_GRAVITY_PORT_UP ? EL_SP_PORT_UP : + element == EL_SP_GRAVITY_PORT_DOWN ? EL_SP_PORT_DOWN : + element); + } +#endif + + level->field[x][y] = element; + } + } /* copy elements to runtime playfield array */ for (x = 0; x < MAX_LEV_FIELDX; x++) @@ -3117,6 +2902,7 @@ static void LoadLevel_InitPlayfield(struct LevelInfo *level, char *filename) void LoadLevelTemplate(int nr) { +#if 1 char *filename; setLevelFileInfo(&level_template.file_info, nr); @@ -3124,14 +2910,34 @@ void LoadLevelTemplate(int nr) LoadLevelFromFileInfo(&level_template, &level_template.file_info); +#else + +#if 1 + struct LevelFileInfo *level_file_info = getLevelFileInfo(nr); + char *filename = level_file_info->filename; + + LoadLevelFromFileInfo(&level_template, level_file_info); +#else + char *filename = getDefaultLevelFilename(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); @@ -3139,12 +2945,30 @@ void LoadLevel(int nr) LoadLevelFromFileInfo(&level, &level.file_info); +#else + +#if 1 + struct LevelFileInfo *level_file_info = getLevelFileInfo(nr); + char *filename = level_file_info->filename; + + LoadLevelFromFileInfo(&level, level_file_info); +#else + char *filename = getLevelFilename(nr); + + LoadLevelFromFilename_RND(&level, filename); +#endif +#endif + if (level.use_custom_template) LoadLevelTemplate(-1); +#if 1 LoadLevel_InitVersion(&level, filename); LoadLevel_InitElements(&level, filename); LoadLevel_InitPlayfield(&level, filename); +#else + LoadLevel_InitLevel(&level, filename); +#endif } static void SaveLevel_VERS(FILE *file, struct LevelInfo *level) @@ -3173,7 +2997,7 @@ static void SaveLevel_HEAD(FILE *file, struct LevelInfo *level) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) putFile8Bit(file, (level->encoding_16bit_yamyam ? EL_EMPTY : - level->yamyam_content[i].e[x][y])); + level->yamyam_content[i][x][y])); putFile8Bit(file, level->amoeba_speed); putFile8Bit(file, level->time_magic_wall); putFile8Bit(file, level->time_wheel); @@ -3237,9 +3061,9 @@ static void SaveLevel_CONT(FILE *file, struct LevelInfo *level) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) if (level->encoding_16bit_field) - putFile16BitBE(file, level->yamyam_content[i].e[x][y]); + putFile16BitBE(file, level->yamyam_content[i][x][y]); else - putFile8Bit(file, level->yamyam_content[i].e[x][y]); + putFile8Bit(file, level->yamyam_content[i][x][y]); } #endif @@ -3258,7 +3082,7 @@ static void SaveLevel_CNT2(FILE *file, struct LevelInfo *level, int element) for (i = 0; i < MAX_ELEMENT_CONTENTS; i++) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - content_array[i][x][y] = level->yamyam_content[i].e[x][y]; + content_array[i][x][y] = level->yamyam_content[i][x][y]; } else if (element == EL_BD_AMOEBA) { @@ -3380,64 +3204,63 @@ static void SaveLevel_CUS3(FILE *file, struct LevelInfo *level, for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) { int element = EL_CUSTOM_START + i; - struct ElementInfo *ei = &element_info[element]; - if (ei->modified_settings) + if (element_info[element].modified_settings) { if (check < num_changed_custom_elements) { putFile16BitBE(file, element); for (j = 0; j < MAX_ELEMENT_NAME_LEN; j++) - putFile8Bit(file, ei->description[j]); + putFile8Bit(file, element_info[element].description[j]); putFile32BitBE(file, Properties[element][EP_BITFIELD_BASE]); /* some free bytes for future properties and padding */ WriteUnusedBytesToFile(file, 7); - putFile8Bit(file, ei->use_gfx_element); - putFile16BitBE(file, ei->gfx_element); + putFile8Bit(file, element_info[element].use_gfx_element); + putFile16BitBE(file, element_info[element].gfx_element); - putFile8Bit(file, ei->collect_score_initial); - putFile8Bit(file, ei->collect_count_initial); + putFile8Bit(file, element_info[element].collect_score); + putFile8Bit(file, element_info[element].collect_count); - putFile16BitBE(file, ei->push_delay_fixed); - putFile16BitBE(file, ei->push_delay_random); - putFile16BitBE(file, ei->move_delay_fixed); - putFile16BitBE(file, ei->move_delay_random); + putFile16BitBE(file, element_info[element].push_delay_fixed); + putFile16BitBE(file, element_info[element].push_delay_random); + putFile16BitBE(file, element_info[element].move_delay_fixed); + putFile16BitBE(file, element_info[element].move_delay_random); - putFile16BitBE(file, ei->move_pattern); - putFile8Bit(file, ei->move_direction_initial); - putFile8Bit(file, ei->move_stepsize); + putFile16BitBE(file, element_info[element].move_pattern); + putFile8Bit(file, element_info[element].move_direction_initial); + putFile8Bit(file, element_info[element].move_stepsize); for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - putFile16BitBE(file, ei->content.e[x][y]); + putFile16BitBE(file, element_info[element].content[x][y]); - putFile32BitBE(file, ei->change->events); + putFile32BitBE(file, element_info[element].change->events); - putFile16BitBE(file, ei->change->target_element); + putFile16BitBE(file, element_info[element].change->target_element); - putFile16BitBE(file, ei->change->delay_fixed); - putFile16BitBE(file, ei->change->delay_random); - putFile16BitBE(file, ei->change->delay_frames); + putFile16BitBE(file, element_info[element].change->delay_fixed); + putFile16BitBE(file, element_info[element].change->delay_random); + putFile16BitBE(file, element_info[element].change->delay_frames); - putFile16BitBE(file, ei->change->trigger_element); + putFile16BitBE(file, element_info[element].change->trigger_element); - putFile8Bit(file, ei->change->explode); - putFile8Bit(file, ei->change->use_target_content); - putFile8Bit(file, ei->change->only_if_complete); - putFile8Bit(file, ei->change->use_random_replace); + putFile8Bit(file, element_info[element].change->explode); + putFile8Bit(file, element_info[element].change->use_target_content); + putFile8Bit(file, element_info[element].change->only_if_complete); + putFile8Bit(file, element_info[element].change->use_random_replace); - putFile8Bit(file, ei->change->random_percentage); - putFile8Bit(file, ei->change->replace_when); + putFile8Bit(file, element_info[element].change->random_percentage); + putFile8Bit(file, element_info[element].change->replace_when); for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - putFile16BitBE(file, ei->change->content.e[x][y]); + putFile16BitBE(file, element_info[element].change->content[x][y]); - putFile8Bit(file, ei->slippery_type); + putFile8Bit(file, element_info[element].slippery_type); /* some free bytes for future properties and padding */ WriteUnusedBytesToFile(file, LEVEL_CPART_CUS3_UNUSED); @@ -3457,8 +3280,6 @@ static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element) struct ElementInfo *ei = &element_info[element]; int i, j, x, y; - /* ---------- custom element base property values (96 bytes) ------------- */ - putFile16BitBE(file, element); for (i = 0; i < MAX_ELEMENT_NAME_LEN; i++) @@ -3469,15 +3290,16 @@ static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element) putFile8Bit(file, ei->num_change_pages); - putFile16BitBE(file, ei->ce_value_fixed_initial); - putFile16BitBE(file, ei->ce_value_random_initial); - putFile8Bit(file, ei->use_last_ce_value); + /* some free bytes for future base property values and padding */ + WriteUnusedBytesToFile(file, 5); + + /* write custom property values */ putFile8Bit(file, ei->use_gfx_element); putFile16BitBE(file, ei->gfx_element); - putFile8Bit(file, ei->collect_score_initial); - putFile8Bit(file, ei->collect_count_initial); + putFile8Bit(file, ei->collect_score); + putFile8Bit(file, ei->collect_count); putFile8Bit(file, ei->drop_delay_fixed); putFile8Bit(file, ei->push_delay_fixed); @@ -3495,7 +3317,7 @@ static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - putFile16BitBE(file, ei->content.e[x][y]); + putFile16BitBE(file, ei->content[x][y]); putFile16BitBE(file, ei->move_enter_element); putFile16BitBE(file, ei->move_leave_element); @@ -3513,18 +3335,17 @@ static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element) /* some free bytes for future custom property values and padding */ WriteUnusedBytesToFile(file, 1); - /* ---------- change page property values (48 bytes) --------------------- */ + /* write change property values */ for (i = 0; i < ei->num_change_pages; i++) { struct ElementChangeInfo *change = &ei->change_page[i]; - unsigned long event_bits; + unsigned long event_bits = 0; - /* bits 0 - 31 of "has_event[]" ... */ - event_bits = 0; - for (j = 0; j < MIN(NUM_CHANGE_EVENTS, 32); j++) + for (j = 0; j < NUM_CHANGE_EVENTS; j++) if (change->has_event[j]) event_bits |= (1 << j); + putFile32BitBE(file, event_bits); putFile16BitBE(file, change->target_element); @@ -3545,27 +3366,25 @@ static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - putFile16BitBE(file, change->target_content.e[x][y]); + putFile16BitBE(file, change->target_content[x][y]); putFile8Bit(file, change->can_change); putFile8Bit(file, change->trigger_side); +#if 1 putFile8Bit(file, change->trigger_player); putFile8Bit(file, (change->trigger_page == CH_PAGE_ANY ? CH_PAGE_ANY_FILE : log_2(change->trigger_page))); - putFile8Bit(file, change->has_action); - putFile8Bit(file, change->action_type); - putFile8Bit(file, change->action_mode); - putFile16BitBE(file, change->action_arg); + /* some free bytes for future change property values and padding */ + WriteUnusedBytesToFile(file, 6); - /* ... bits 32 - 39 of "has_event[]" (not nice, but downward compatible) */ - event_bits = 0; - for (j = 32; j < NUM_CHANGE_EVENTS; j++) - if (change->has_event[j]) - event_bits |= (1 << (j - 32)); - putFile8Bit(file, event_bits); +#else + + /* some free bytes for future change property values and padding */ + WriteUnusedBytesToFile(file, 8); +#endif } } @@ -3594,93 +3413,9 @@ static void SaveLevel_GRP1(FILE *file, struct LevelInfo *level, int element) putFile16BitBE(file, group->element[i]); } -static int SaveLevel_CONF_Value(FILE *file, int pos) -{ - int default_value = element_conf[pos].default_value; - int element = element_conf[pos].element; - int type = element_conf[pos].type; - int bytes = type & CONF_MASK_BYTES; - void *value_ptr = element_conf[pos].value; - int value = (CONF_VALUE_BOOLEAN(type) ? *(boolean *)value_ptr : - *(int *)value_ptr); - int num_bytes = 0; - boolean modified = FALSE; - - /* check if any settings have been modified before saving them */ - if (value != default_value) - modified = TRUE; - - if (!modified) /* do not save unmodified default settings */ - return 0; - - if (bytes == CONF_MASK_MULTI_BYTES) - Error(ERR_EXIT, "SaveLevel_CONF_Value: cannot save multi-byte values"); - - num_bytes += putFile16BitBE(file, element); - num_bytes += putFile8Bit(file, type); - num_bytes += (bytes == CONF_MASK_1_BYTE ? putFile8Bit (file, value) : - bytes == CONF_MASK_2_BYTE ? putFile16BitBE(file, value) : - bytes == CONF_MASK_4_BYTE ? putFile32BitBE(file, value) : 0); - - return num_bytes; -} - -static int SaveLevel_CONF_Content(FILE *file, int pos, int num_contents) -{ - struct Content *content = (struct Content *)(element_conf[pos].value); - int default_value = element_conf[pos].default_value; - int element = element_conf[pos].element; - int type = element_conf[pos].type; - int num_bytes = 0; - boolean modified = FALSE; - int i, x, y; - - /* check if any settings have been modified before saving them */ - for (i = 0; i < num_contents; i++) - for (y = 0; y < 3; y++) - for (x = 0; x < 3; x++) - if (content[i].e[x][y] != default_value) - modified = TRUE; - - if (!modified) /* do not save unmodified default settings */ - return 0; - - num_bytes += putFile16BitBE(file, element); - num_bytes += putFile8Bit(file, type); - num_bytes += putFile16BitBE(file, num_contents * CONF_CONTENT_NUM_BYTES); - - for (i = 0; i < num_contents; i++) - for (y = 0; y < 3; y++) - for (x = 0; x < 3; x++) - num_bytes += putFile16BitBE(file, content[i].e[x][y]); - - return num_bytes; -} - -static int SaveLevel_CONF(FILE *file, struct LevelInfo *level) -{ - int chunk_size = 0; - int i; - - li = *level; /* copy level information into temporary buffer */ - - for (i = 0; element_conf[i].element != -1; i++) - { - int type = element_conf[i].type; - int bytes = type & CONF_MASK_BYTES; - - if (bytes != CONF_MASK_MULTI_BYTES) - chunk_size += SaveLevel_CONF_Value(file, i); - else if (type == CONF_VALUE_CONTENT_8) - chunk_size += SaveLevel_CONF_Content(file, i, MAX_ELEMENT_CONTENTS); - } - - return chunk_size; -} - static void SaveLevelFromFilename(struct LevelInfo *level, char *filename) { - int body_chunk_size, conf_chunk_size; + int body_chunk_size; int i, x, y; FILE *file; @@ -3705,7 +3440,7 @@ static void SaveLevelFromFilename(struct LevelInfo *level, char *filename) for (i = 0; i < level->num_yamyam_contents; i++) for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) - if (level->yamyam_content[i].e[x][y] > 255) + if (level->yamyam_content[i][x][y] > 255) level->encoding_16bit_yamyam = TRUE; /* check amoeba content for 16-bit elements */ @@ -3789,15 +3524,6 @@ static void SaveLevelFromFilename(struct LevelInfo *level, char *filename) } } - conf_chunk_size = SaveLevel_CONF(NULL, level); /* get chunk size */ - - /* check for non-default configuration settings to be saved in CONF chunk */ - if (conf_chunk_size > 0) - { - putFileChunkBE(file, "CONF", conf_chunk_size); - SaveLevel_CONF(file, level); - } - fclose(file); SetFilePermissions(filename, PERMS_PRIVATE); @@ -3974,7 +3700,7 @@ static int LoadTape_BODY(FILE *file, int chunk_size, struct TapeInfo *tape) for (j = 0; j < MAX_PLAYERS; j++) { - tape->pos[i].action[j] = MV_NONE; + tape->pos[i].action[j] = MV_NO_MOVING; if (tape->player_participates[j]) tape->pos[i].action[j] = getFile8Bit(file); @@ -4021,7 +3747,7 @@ static int LoadTape_BODY(FILE *file, int chunk_size, struct TapeInfo *tape) /* delay part */ for (j = 0; j < MAX_PLAYERS; j++) - tape->pos[i].action[j] = MV_NONE; + tape->pos[i].action[j] = MV_NO_MOVING; tape->pos[i].delay--; i++; @@ -4053,6 +3779,10 @@ void LoadTapeFromFilename(char *filename) { tape.no_valid_file = TRUE; +#if 0 + Error(ERR_WARN, "cannot read tape '%s' -- using empty tape", filename); +#endif + return; } @@ -4307,12 +4037,21 @@ void DumpTape(struct TapeInfo *tape) { int i, j; +#if 1 if (tape->no_valid_file) { Error(ERR_WARN, "cannot dump -- no valid tape file found"); return; } +#else + if (TAPE_IS_EMPTY(*tape)) + { + Error(ERR_WARN, "no tape available for level %d", tape->level_nr); + + return; + } +#endif printf_line("-", 79); printf("Tape of Level %03d (file version %08d, game version %08d)\n", @@ -5018,6 +4757,7 @@ void LoadUserDefinedEditorElementList(int **elements, int *num_elements) freeSetupFileHash(element_hash); #if 0 + /* TEST-ONLY */ for (i = 0; i < *num_elements; i++) printf("editor: element '%s' [%d]\n", element_info[(*elements)[i]].token_name, (*elements)[i]); @@ -5182,10 +4922,18 @@ void LoadMusicInfo() new = &music_file_info; +#if 0 + printf("::: num_music == %d\n", num_music); +#endif + for (i = 0; i < num_music; i++) { music = getMusicListEntry(i); +#if 0 + printf("::: %d [%08x]\n", i, music->filename); +#endif + if (music->filename == NULL) continue; @@ -5284,6 +5032,7 @@ void LoadMusicInfo() } #if 0 + /* TEST-ONLY */ for (next = music_file_info; next != NULL; next = next->next) printf("::: title == '%s'\n", next->title); #endif @@ -5524,6 +5273,7 @@ void LoadHelpAnimInfo() freeSetupFileHash(direction_hash); #if 0 + /* TEST ONLY */ for (i = 0; i < num_list_entries; i++) printf("::: %d, %d, %d => %d\n", helpanim_info[i].element, @@ -5559,6 +5309,7 @@ void LoadHelpTextInfo() } #if 0 + /* TEST ONLY */ BEGIN_HASH_ITERATION(helptext_info, itr) { printf("::: '%s' => '%s'\n",