- 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;
- }
- }
-
- /* correct custom element values (fix invalid values for all versions) */
- if (1)
- {
- for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
- {
- 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 (change->trigger_player == CH_PLAYER_NONE)
- change->trigger_player = CH_PLAYER_ANY;
-
- if (change->trigger_side == CH_SIDE_NONE)
- change->trigger_side = CH_SIDE_ANY;
- }
- }
- }
-
- /* 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++)
- {
- int element = EL_CUSTOM_START + i;
-
- if (EXPLODES_1X1_OLD(element))
- element_info[element].explosion_type = EXPLODES_1X1;
-
- SET_PROPERTY(element, EP_CAN_EXPLODE, (EXPLODES_BY_FIRE(element) ||
- EXPLODES_SMASHED(element) ||
- EXPLODES_IMPACT(element)));
- }
- }
-
- /* 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;
- }
- }
- }
-
- /* 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->game_version);
-
- /* initialize element properties for level editor etc. */
- InitElementPropertiesEngine(level->game_version);
- InitElementPropertiesAfterLoading(level->game_version);
- InitElementPropertiesGfxElement();
-}
-
-static void LoadLevel_InitPlayfield(struct LevelInfo *level, char *filename)
-{
- int x, y;
-
- /* 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);
-
- /* copy elements to runtime playfield array */
- for (x = 0; x < MAX_LEV_FIELDX; x++)
- for (y = 0; y < MAX_LEV_FIELDY; y++)
- Feld[x][y] = level->field[x][y];
-
- /* initialize level size variables for faster access */
- lev_fieldx = level->fieldx;
- lev_fieldy = level->fieldy;
-
- /* determine border element for this level */
- if (level->file_info.type == LEVEL_FILE_TYPE_DC)
- BorderElement = EL_EMPTY; /* (in editor, SetBorderElement() is used) */
- else
- SetBorderElement();
-}
-
-static void LoadLevel_InitNativeEngines(struct LevelInfo *level,char *filename)
-{
- struct LevelFileInfo *level_file_info = &level->file_info;
-
- if (level_file_info->type == LEVEL_FILE_TYPE_RND)
- CopyNativeLevel_RND_to_Native(level);
-}
-
-void LoadLevelTemplate(int nr)
-{
- char *filename;
-
- setLevelFileInfo(&level_template.file_info, nr);
- filename = level_template.file_info.filename;
-
- LoadLevelFromFileInfo(&level_template, &level_template.file_info, FALSE);
-
- LoadLevel_InitVersion(&level_template, filename);
- LoadLevel_InitElements(&level_template, filename);
-
- ActivateLevelTemplate();
-}
-
-void LoadLevel(int nr)
-{
- char *filename;
-
- setLevelFileInfo(&level.file_info, nr);
- filename = level.file_info.filename;
-
- LoadLevelFromFileInfo(&level, &level.file_info, FALSE);
-
- if (level.use_custom_template)
- LoadLevelTemplate(-1);
-
- LoadLevel_InitVersion(&level, filename);
- LoadLevel_InitElements(&level, filename);
- LoadLevel_InitPlayfield(&level, filename);
-
- LoadLevel_InitNativeEngines(&level, filename);
-}
-
-void LoadLevelInfoOnly(int nr)
-{
-#if 0
- char *filename;
-#endif
-
- setLevelFileInfo(&level.file_info, nr);
-#if 0
- filename = level.file_info.filename;
-#endif
-
- LoadLevelFromFileInfo(&level, &level.file_info, TRUE);
-}
-
-static int SaveLevel_VERS(FILE *file, struct LevelInfo *level)
-{
- int chunk_size = 0;
-
- chunk_size += putFileVersion(file, level->file_version);
- chunk_size += putFileVersion(file, level->game_version);
-
- return chunk_size;
-}
-
-static int SaveLevel_DATE(FILE *file, struct LevelInfo *level)
-{
- int chunk_size = 0;
-
- chunk_size += putFile16BitBE(file, level->creation_date.year);
- chunk_size += putFile8Bit(file, level->creation_date.month);
- chunk_size += putFile8Bit(file, level->creation_date.day);
-
- return chunk_size;
-}
-
-#if 0
-static void SaveLevel_HEAD(FILE *file, struct LevelInfo *level)
-{
- int i, x, y;
-
- putFile8Bit(file, level->fieldx);
- putFile8Bit(file, level->fieldy);
-
- putFile16BitBE(file, level->time);
- putFile16BitBE(file, level->gems_needed);
-
- for (i = 0; i < MAX_LEVEL_NAME_LEN; i++)
- putFile8Bit(file, level->name[i]);
-
- for (i = 0; i < LEVEL_SCORE_ELEMENTS; i++)
- putFile8Bit(file, level->score[i]);
-
- for (i = 0; i < STD_ELEMENT_CONTENTS; i++)
- 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]));
- putFile8Bit(file, level->amoeba_speed);
- putFile8Bit(file, level->time_magic_wall);
- putFile8Bit(file, level->time_wheel);
- putFile8Bit(file, (level->encoding_16bit_amoeba ? EL_EMPTY :
- level->amoeba_content));
- putFile8Bit(file, (level->initial_player_stepsize == STEPSIZE_FAST ? 1 : 0));
- putFile8Bit(file, (level->initial_gravity ? 1 : 0));
- putFile8Bit(file, (level->encoding_16bit_field ? 1 : 0));
- putFile8Bit(file, (level->em_slippery_gems ? 1 : 0));
-
- putFile8Bit(file, (level->use_custom_template ? 1 : 0));
-
- putFile8Bit(file, (level->block_last_field ? 1 : 0));
- putFile8Bit(file, (level->sp_block_last_field ? 1 : 0));
- putFile32BitBE(file, level->can_move_into_acid_bits);
- putFile8Bit(file, level->dont_collide_with_bits);
-
- putFile8Bit(file, (level->use_spring_bug ? 1 : 0));
- putFile8Bit(file, (level->use_step_counter ? 1 : 0));
-
- putFile8Bit(file, (level->instant_relocation ? 1 : 0));
- putFile8Bit(file, (level->can_pass_to_walkable ? 1 : 0));
- putFile8Bit(file, (level->grow_into_diggable ? 1 : 0));
-
- putFile8Bit(file, level->game_engine_type);
-
- WriteUnusedBytesToFile(file, LEVEL_CHUNK_HEAD_UNUSED);
-}
-#endif
-
-static int SaveLevel_NAME(FILE *file, struct LevelInfo *level)
-{
- int chunk_size = 0;
- int i;
-
- for (i = 0; i < MAX_LEVEL_NAME_LEN; i++)
- chunk_size += putFile8Bit(file, level->name[i]);
-
- return chunk_size;
-}
-
-static int SaveLevel_AUTH(FILE *file, struct LevelInfo *level)
-{
- int chunk_size = 0;
- int i;
-
- for (i = 0; i < MAX_LEVEL_AUTHOR_LEN; i++)
- chunk_size += putFile8Bit(file, level->author[i]);
-
- return chunk_size;
-}
-
-#if 0
-static int SaveLevel_BODY(FILE *file, struct LevelInfo *level)
-{
- int chunk_size = 0;
- int x, y;
-
- for (y = 0; y < level->fieldy; y++)
- for (x = 0; x < level->fieldx; x++)
- if (level->encoding_16bit_field)
- chunk_size += putFile16BitBE(file, level->field[x][y]);
- else
- chunk_size += putFile8Bit(file, level->field[x][y]);
-
- return chunk_size;
-}
-#endif
-
-static int SaveLevel_BODY(FILE *file, struct LevelInfo *level)
-{
- int chunk_size = 0;
- int x, y;
-
- for (y = 0; y < level->fieldy; y++)
- for (x = 0; x < level->fieldx; x++)
- chunk_size += putFile16BitBE(file, level->field[x][y]);
-
- return chunk_size;
-}
-
-#if 0
-static void SaveLevel_CONT(FILE *file, struct LevelInfo *level)
-{
- int i, x, y;
-
- putFile8Bit(file, EL_YAMYAM);
- putFile8Bit(file, level->num_yamyam_contents);
- putFile8Bit(file, 0);
- putFile8Bit(file, 0);
-
- for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
- 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]);
- else
- putFile8Bit(file, level->yamyam_content[i].e[x][y]);
-}
-#endif
-
-#if 0
-static void SaveLevel_CNT2(FILE *file, struct LevelInfo *level, int element)
-{
- int i, x, y;
- int num_contents, content_xsize, content_ysize;
- int content_array[MAX_ELEMENT_CONTENTS][3][3];
-
- if (element == EL_YAMYAM)
- {
- num_contents = level->num_yamyam_contents;
- content_xsize = 3;
- content_ysize = 3;
-
- 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];
- }
- else if (element == EL_BD_AMOEBA)
- {
- num_contents = 1;
- content_xsize = 1;
- content_ysize = 1;
-
- 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] = EL_EMPTY;
- content_array[0][0][0] = level->amoeba_content;
- }
- else
- {
- /* chunk header already written -- write empty chunk data */
- WriteUnusedBytesToFile(file, LEVEL_CHUNK_CNT2_SIZE);
-
- Error(ERR_WARN, "cannot save content for element '%d'", element);
- return;
- }
-
- putFile16BitBE(file, element);
- putFile8Bit(file, num_contents);
- putFile8Bit(file, content_xsize);
- putFile8Bit(file, content_ysize);
-
- WriteUnusedBytesToFile(file, LEVEL_CHUNK_CNT2_UNUSED);
-
- for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
- for (y = 0; y < 3; y++)
- for (x = 0; x < 3; x++)
- putFile16BitBE(file, content_array[i][x][y]);
-}
-#endif
-
-#if 0
-static int SaveLevel_CNT3(FILE *file, struct LevelInfo *level, int element)
-{
- int envelope_nr = element - EL_ENVELOPE_1;
- int envelope_len = strlen(level->envelope_text[envelope_nr]) + 1;
- int chunk_size = 0;
- int i;
-
- chunk_size += putFile16BitBE(file, element);
- chunk_size += putFile16BitBE(file, envelope_len);
- chunk_size += putFile8Bit(file, level->envelope_xsize[envelope_nr]);
- chunk_size += putFile8Bit(file, level->envelope_ysize[envelope_nr]);
-
- WriteUnusedBytesToFile(file, LEVEL_CHUNK_CNT3_UNUSED);
- chunk_size += LEVEL_CHUNK_CNT3_UNUSED;
-
- for (i = 0; i < envelope_len; i++)
- chunk_size += putFile8Bit(file, level->envelope_text[envelope_nr][i]);
-
- return chunk_size;
-}
-#endif
-
-#if 0
-static void SaveLevel_CUS1(FILE *file, struct LevelInfo *level,
- int num_changed_custom_elements)
-{
- int i, check = 0;
-
- putFile16BitBE(file, num_changed_custom_elements);
-
- for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
- {
- int element = EL_CUSTOM_START + i;
-
- struct ElementInfo *ei = &element_info[element];
-
- if (ei->properties[EP_BITFIELD_BASE_NR] != EP_BITMASK_DEFAULT)
- {
- if (check < num_changed_custom_elements)
- {
- putFile16BitBE(file, element);
- putFile32BitBE(file, ei->properties[EP_BITFIELD_BASE_NR]);
- }
-
- check++;
- }
- }
-
- if (check != num_changed_custom_elements) /* should not happen */
- Error(ERR_WARN, "inconsistent number of custom element properties");
-}
-#endif
-
-#if 0
-static void SaveLevel_CUS2(FILE *file, struct LevelInfo *level,
- int num_changed_custom_elements)
-{
- int i, check = 0;
-
- putFile16BitBE(file, num_changed_custom_elements);
-
- for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
- {
- int element = EL_CUSTOM_START + i;
-
- if (element_info[element].change->target_element != EL_EMPTY_SPACE)
- {
- if (check < num_changed_custom_elements)
- {
- putFile16BitBE(file, element);
- putFile16BitBE(file, element_info[element].change->target_element);
- }
-
- check++;
- }
- }
-
- if (check != num_changed_custom_elements) /* should not happen */
- Error(ERR_WARN, "inconsistent number of custom target elements");
-}
-#endif
-
-#if 0
-static void SaveLevel_CUS3(FILE *file, struct LevelInfo *level,
- int num_changed_custom_elements)
-{
- int i, j, x, y, check = 0;
-
- putFile16BitBE(file, num_changed_custom_elements);
-
- 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 (check < num_changed_custom_elements)
- {
- putFile16BitBE(file, element);
-
- for (j = 0; j < MAX_ELEMENT_NAME_LEN; j++)
- putFile8Bit(file, ei->description[j]);
-
- putFile32BitBE(file, ei->properties[EP_BITFIELD_BASE_NR]);
-
- /* some free bytes for future properties and padding */
- WriteUnusedBytesToFile(file, 7);
-
- putFile8Bit(file, ei->use_gfx_element);
- putFile16BitBE(file, ei->gfx_element_initial);
-
- putFile8Bit(file, ei->collect_score_initial);
- putFile8Bit(file, ei->collect_count_initial);
-
- 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, ei->move_pattern);
- putFile8Bit(file, ei->move_direction_initial);
- putFile8Bit(file, ei->move_stepsize);
-
- for (y = 0; y < 3; y++)
- for (x = 0; x < 3; x++)
- putFile16BitBE(file, ei->content.e[x][y]);
-
- putFile32BitBE(file, ei->change->events);
-
- putFile16BitBE(file, ei->change->target_element);
-
- putFile16BitBE(file, ei->change->delay_fixed);
- putFile16BitBE(file, ei->change->delay_random);
- putFile16BitBE(file, ei->change->delay_frames);
-
- putFile16BitBE(file, ei->change->initial_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, ei->change->random_percentage);
- putFile8Bit(file, ei->change->replace_when);
-
- for (y = 0; y < 3; y++)
- for (x = 0; x < 3; x++)
- putFile16BitBE(file, ei->change->content.e[x][y]);
-
- putFile8Bit(file, ei->slippery_type);
-
- /* some free bytes for future properties and padding */
- WriteUnusedBytesToFile(file, LEVEL_CPART_CUS3_UNUSED);
- }
-
- check++;
- }
- }
-
- if (check != num_changed_custom_elements) /* should not happen */
- Error(ERR_WARN, "inconsistent number of custom element properties");
-}
-#endif
-
-#if 0
-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++)
- putFile8Bit(file, ei->description[i]);
-
- putFile32BitBE(file, ei->properties[EP_BITFIELD_BASE_NR]);
-
- WriteUnusedBytesToFile(file, 4); /* reserved for more base properties */
-
- 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);
-
- putFile8Bit(file, ei->use_gfx_element);
- putFile16BitBE(file, ei->gfx_element_initial);
-
- putFile8Bit(file, ei->collect_score_initial);
- putFile8Bit(file, ei->collect_count_initial);
-
- putFile8Bit(file, ei->drop_delay_fixed);
- putFile8Bit(file, ei->push_delay_fixed);
- putFile8Bit(file, ei->drop_delay_random);
- putFile8Bit(file, ei->push_delay_random);
- putFile16BitBE(file, ei->move_delay_fixed);
- putFile16BitBE(file, ei->move_delay_random);
-
- /* bits 0 - 15 of "move_pattern" ... */
- putFile16BitBE(file, ei->move_pattern & 0xffff);
- putFile8Bit(file, ei->move_direction_initial);
- putFile8Bit(file, ei->move_stepsize);
-
- putFile8Bit(file, ei->slippery_type);
-
- for (y = 0; y < 3; y++)
- for (x = 0; x < 3; x++)
- putFile16BitBE(file, ei->content.e[x][y]);
-
- putFile16BitBE(file, ei->move_enter_element);
- putFile16BitBE(file, ei->move_leave_element);
- putFile8Bit(file, ei->move_leave_type);
-
- /* ... bits 16 - 31 of "move_pattern" (not nice, but downward compatible) */
- putFile16BitBE(file, (ei->move_pattern >> 16) & 0xffff);
-
- putFile8Bit(file, ei->access_direction);
-
- putFile8Bit(file, ei->explosion_delay);
- putFile8Bit(file, ei->ignition_delay);
- putFile8Bit(file, ei->explosion_type);
-
- /* some free bytes for future custom property values and padding */
- WriteUnusedBytesToFile(file, 1);
-
- /* ---------- change page property values (48 bytes) --------------------- */
-
- for (i = 0; i < ei->num_change_pages; i++)
- {
- struct ElementChangeInfo *change = &ei->change_page[i];
- unsigned int event_bits;
-
- /* bits 0 - 31 of "has_event[]" ... */
- event_bits = 0;
- for (j = 0; j < MIN(NUM_CHANGE_EVENTS, 32); j++)
- if (change->has_event[j])
- event_bits |= (1 << j);
- putFile32BitBE(file, event_bits);
-
- putFile16BitBE(file, change->target_element);
-
- putFile16BitBE(file, change->delay_fixed);
- putFile16BitBE(file, change->delay_random);
- putFile16BitBE(file, change->delay_frames);
-
- putFile16BitBE(file, change->initial_trigger_element);
-
- putFile8Bit(file, change->explode);
- putFile8Bit(file, change->use_target_content);
- putFile8Bit(file, change->only_if_complete);
- putFile8Bit(file, change->use_random_replace);
-
- putFile8Bit(file, change->random_percentage);
- putFile8Bit(file, change->replace_when);
-
- for (y = 0; y < 3; y++)
- for (x = 0; x < 3; x++)
- putFile16BitBE(file, change->target_content.e[x][y]);
-
- putFile8Bit(file, change->can_change);
-
- putFile8Bit(file, change->trigger_side);
-
- 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);
-
- /* ... 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);
- }
-}
-#endif
-
-#if 0
-static void SaveLevel_GRP1(FILE *file, struct LevelInfo *level, int element)
-{
- struct ElementInfo *ei = &element_info[element];
- struct ElementGroupInfo *group = ei->group;
- int i;
-
- putFile16BitBE(file, element);
-
- for (i = 0; i < MAX_ELEMENT_NAME_LEN; i++)
- putFile8Bit(file, ei->description[i]);
-
- putFile8Bit(file, group->num_elements);
-
- putFile8Bit(file, ei->use_gfx_element);
- putFile16BitBE(file, ei->gfx_element_initial);
-
- putFile8Bit(file, group->choice_mode);
-
- /* some free bytes for future values and padding */
- WriteUnusedBytesToFile(file, 3);
-
- for (i = 0; i < MAX_ELEMENTS_IN_GROUP; i++)
- putFile16BitBE(file, group->element[i]);
-}
-#endif
-
-static int SaveLevel_MicroChunk(FILE *file, struct LevelFileConfigInfo *entry,
- boolean write_element)
-{
- int save_type = entry->save_type;
- int data_type = entry->data_type;
- int conf_type = entry->conf_type;
- int byte_mask = conf_type & CONF_MASK_BYTES;
- int element = entry->element;
- int default_value = entry->default_value;
- int num_bytes = 0;
- boolean modified = FALSE;
-
- if (byte_mask != CONF_MASK_MULTI_BYTES)