rnd-20051217-1-src
[rocksndiamonds.git] / src / files.c
index 473a73926cbcaa9f24502582db6844c9746b786a..4cf2a857ea8246c32f98c681ecbfb40866c14498 100644 (file)
 
 #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)
+#define LEVEL_CHUNK_CUS4_SIZE(x) (96 + (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_MAGIC_BALL,                 CONF_VALUE_INTEGER_1,
+    &li.ball_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_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
+  },
+
+  /* ---------- multi-byte values ------------------------------------------ */
+  {
+    EL_EMC_MAGIC_BALL,                 CONF_VALUE_CONTENT_8,
+    &li.ball_content,                  EL_EMPTY
+  },
+
+  {
+    -1,                                        -1,
+    NULL,                              -1
+  },
+};
+
 static struct
 {
   int filetype;
@@ -71,6 +238,40 @@ 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);
@@ -88,11 +289,12 @@ void setElementChangePages(struct ElementInfo *ei, int change_pages)
 
 void setElementChangeInfoToDefaults(struct ElementChangeInfo *change)
 {
-  int x, y;
+  int i, x, y;
 
   change->can_change = FALSE;
 
-  change->events = CE_BITMASK_DEFAULT;
+  for (i = 0; i < NUM_CHANGE_EVENTS; i++)
+    change->has_event[i] = FALSE;
 
   change->trigger_player = CH_PLAYER_ANY;
   change->trigger_side = CH_SIDE_ANY;
@@ -113,9 +315,14 @@ 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[x][y] = EL_EMPTY_SPACE;
+      change->target_content.e[x][y] = EL_EMPTY_SPACE;
 
   change->direct_action = 0;
   change->other_action = 0;
@@ -130,6 +337,7 @@ 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;
@@ -157,11 +365,23 @@ 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;
@@ -171,31 +391,35 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
 
   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->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->magnify_score = 10;
-  level->slurp_score = 10;
   level->lenses_time = 10;
+  level->magnify_score = 10;
   level->magnify_time = 10;
-  level->wind_direction_initial = MV_NO_MOVING;
-  for (i = 0; i < NUM_MAGIC_BALL_CONTENTS; i++)
+  level->slurp_score = 10;
+  level->wind_direction_initial = MV_NONE;
+#endif
+  level->ball_random = FALSE;
+  level->ball_state_initial = FALSE;
+#if 0
+  for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
     for (x = 0; x < 3; x++)
       for (y = 0; y < 3; y++)
-       level->ball_content[i][x][y] = EL_EMPTY;
+       level->ball_content[i].e[x][y] = EL_EMPTY;
+#endif
   for (i = 0; i < 16; i++)
     level->android_array[i] = FALSE;
 
@@ -223,7 +447,7 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
   for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
     for (x = 0; x < 3; x++)
       for (y = 0; y < 3; y++)
-       level->yamyam_content[i][x][y] =
+       level->yamyam_content[i].e[x][y] =
          (i < STD_ELEMENT_CONTENTS ? EL_ROCK : EL_EMPTY);
 
   level->field[0][0] = EL_PLAYER_1;
@@ -232,79 +456,82 @@ 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(&element_info[element], 1);
-    setElementChangeInfoToDefaults(element_info[element].change);
+    setElementChangePages(ei, 1);
+    setElementChangeInfoToDefaults(ei->change);
 
     if (IS_CUSTOM_ELEMENT(element) ||
        IS_GROUP_ELEMENT(element) ||
        IS_INTERNAL_ELEMENT(element))
     {
       for (j = 0; j < MAX_ELEMENT_NAME_LEN + 1; j++)
-       element_info[element].description[j] = '\0';
+       ei->description[j] = '\0';
 
-      if (element_info[element].custom_description != NULL)
-       strncpy(element_info[element].description,
-               element_info[element].custom_description,MAX_ELEMENT_NAME_LEN);
+      if (ei->custom_description != NULL)
+       strncpy(ei->description, ei->custom_description,MAX_ELEMENT_NAME_LEN);
       else
-       strcpy(element_info[element].description,
-              element_info[element].editor_description);
+       strcpy(ei->description, ei->editor_description);
 
-      element_info[element].use_gfx_element = FALSE;
-      element_info[element].gfx_element = EL_EMPTY_SPACE;
+      ei->use_gfx_element = FALSE;
+      ei->gfx_element = EL_EMPTY_SPACE;
 
-      element_info[element].modified_settings = FALSE;
+      ei->modified_settings = FALSE;
     }
 
     if (IS_CUSTOM_ELEMENT(element) ||
        IS_INTERNAL_ELEMENT(element))
     {
-      element_info[element].access_direction = MV_ALL_DIRECTIONS;
+      ei->access_direction = MV_ALL_DIRECTIONS;
 
-      element_info[element].collect_score = 10;                /* special default */
-      element_info[element].collect_count = 1;         /* special default */
+      ei->collect_score_initial = 10;  /* special default */
+      ei->collect_count_initial = 1;   /* special default */
 
-      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->ce_value_fixed_initial = 0;
+      ei->ce_value_random_initial = 0;
+      ei->use_last_ce_value = FALSE;
 
-      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->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_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_pattern = MV_ALL_DIRECTIONS;
+      ei->move_direction_initial = MV_START_AUTOMATIC;
+      ei->move_stepsize = TILEX / 8;
 
-      element_info[element].slippery_type = SLIPPERY_ANY_RANDOM;
+      ei->move_enter_element = EL_EMPTY_SPACE;
+      ei->move_leave_element = EL_EMPTY_SPACE;
+      ei->move_leave_type = LEAVE_TYPE_UNLIMITED;
 
-      element_info[element].explosion_type = EXPLODES_3X3;
-      element_info[element].explosion_delay = 16;
-      element_info[element].ignition_delay = 8;
+      ei->slippery_type = SLIPPERY_ANY_RANDOM;
+
+      ei->explosion_type = EXPLODES_3X3;
+      ei->explosion_delay = 16;
+      ei->ignition_delay = 8;
 
       for (x = 0; x < 3; x++)
        for (y = 0; y < 3; y++)
-         element_info[element].content[x][y] = EL_EMPTY_SPACE;
+         ei->content.e[x][y] = EL_EMPTY_SPACE;
 
-      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->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].can_explode_by_fire = FALSE;
-      element_info[element].can_explode_smashed = FALSE;
-      element_info[element].can_explode_impact = FALSE;
+      ei->can_explode_by_fire = FALSE;
+      ei->can_explode_smashed = FALSE;
+      ei->can_explode_impact = FALSE;
 
-      element_info[element].current_change_page = 0;
+      ei->current_change_page = 0;
 
       /* start with no properties at all */
       for (j = 0; j < NUM_EP_BITFIELDS; j++)
@@ -317,18 +544,21 @@ 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 (element_info[element].group == NULL)
-       element_info[element].group =
-         checked_malloc(sizeof(struct ElementGroupInfo));
+      if (ei->group == NULL)
+       ei->group = checked_malloc(sizeof(struct ElementGroupInfo));
+
+      group = ei->group;
 
       for (j = 0; j < MAX_ELEMENTS_IN_GROUP; j++)
-       element_info[element].group->element[j] = EL_EMPTY_SPACE;
+       group->element[j] = EL_EMPTY_SPACE;
 
       /* default: only one element in group */
-      element_info[element].group->num_elements = 1;
+      group->num_elements = 1;
 
-      element_info[element].group->choice_mode = ANIM_RANDOM;
+      group->choice_mode = ANIM_RANDOM;
     }
   }
 
@@ -560,48 +790,6 @@ 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;
@@ -680,7 +868,6 @@ 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 */
@@ -692,24 +879,6 @@ 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                                         */
 /* ------------------------------------------------------------------------- */
@@ -718,7 +887,6 @@ int getMappedElement(int element)
 {
   /* remap some (historic, now obsolete) elements */
 
-#if 1
   switch (element)
   {
     case EL_PLAYER_OBSOLETE:
@@ -761,18 +929,6 @@ 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;
 }
@@ -832,7 +988,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][x][y] = getMappedElement(getFile8Bit(file));
+       level->yamyam_content[i].e[x][y] = getMappedElement(getFile8Bit(file));
 
   level->amoeba_speed          = getFile8Bit(file);
   level->time_magic_wall       = getFile8Bit(file);
@@ -936,7 +1092,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][x][y] =
+       level->yamyam_content[i].e[x][y] =
          getMappedElement(level->encoding_16bit_field ?
                           getFile16BitBE(file) : getFile8Bit(file));
   return chunk_size;
@@ -972,7 +1128,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][x][y] = content_array[i][x][y];
+         level->yamyam_content[i].e[x][y] = content_array[i][x][y];
   }
   else if (element == EL_BD_AMOEBA)
   {
@@ -1087,6 +1243,8 @@ 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))
     {
@@ -1096,67 +1254,66 @@ static int LoadLevel_CUS3(FILE *file, int chunk_size, struct LevelInfo *level)
     }
 
     for (j = 0; j < MAX_ELEMENT_NAME_LEN; j++)
-      element_info[element].description[j] = getFile8Bit(file);
-    element_info[element].description[MAX_ELEMENT_NAME_LEN] = 0;
+      ei->description[j] = getFile8Bit(file);
+    ei->description[MAX_ELEMENT_NAME_LEN] = 0;
 
     Properties[element][EP_BITFIELD_BASE] = getFile32BitBE(file);
 
     /* some free bytes for future properties and padding */
     ReadUnusedBytesFromFile(file, 7);
 
-    element_info[element].use_gfx_element = getFile8Bit(file);
-    element_info[element].gfx_element =
-      getMappedElement(getFile16BitBE(file));
+    ei->use_gfx_element = getFile8Bit(file);
+    ei->gfx_element = getMappedElement(getFile16BitBE(file));
 
-    element_info[element].collect_score = getFile8Bit(file);
-    element_info[element].collect_count = getFile8Bit(file);
+    ei->collect_score_initial = getFile8Bit(file);
+    ei->collect_count_initial = getFile8Bit(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->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].move_pattern = getFile16BitBE(file);
-    element_info[element].move_direction_initial = getFile8Bit(file);
-    element_info[element].move_stepsize = getFile8Bit(file);
+    ei->move_pattern = getFile16BitBE(file);
+    ei->move_direction_initial = getFile8Bit(file);
+    ei->move_stepsize = getFile8Bit(file);
 
     for (y = 0; y < 3; y++)
       for (x = 0; x < 3; x++)
-       element_info[element].content[x][y] =
-         getMappedElement(getFile16BitBE(file));
+       ei->content.e[x][y] = getMappedElement(getFile16BitBE(file));
 
-    element_info[element].change->events = getFile32BitBE(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->target_element =
-      getMappedElement(getFile16BitBE(file));
+    ei->change->target_element = getMappedElement(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->delay_fixed = getFile16BitBE(file);
+    ei->change->delay_random = getFile16BitBE(file);
+    ei->change->delay_frames = getFile16BitBE(file);
 
-    element_info[element].change->trigger_element =
-      getMappedElement(getFile16BitBE(file));
+    ei->change->trigger_element = getMappedElement(getFile16BitBE(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->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->random_percentage = getFile8Bit(file);
-    element_info[element].change->replace_when = getFile8Bit(file);
+    ei->change->random_percentage = getFile8Bit(file);
+    ei->change->replace_when = getFile8Bit(file);
 
     for (y = 0; y < 3; y++)
       for (x = 0; x < 3; x++)
-       element_info[element].change->target_content[x][y] =
+       ei->change->target_content.e[x][y] =
          getMappedElement(getFile16BitBE(file));
 
-    element_info[element].slippery_type = getFile8Bit(file);
+    ei->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 */
-    element_info[element].modified_settings = TRUE;
+    ei->modified_settings = TRUE;
   }
 
   return chunk_size;
@@ -1167,7 +1324,9 @@ static int LoadLevel_CUS4(FILE *file, int chunk_size, struct LevelInfo *level)
   struct ElementInfo *ei;
   int chunk_size_expected;
   int element;
-  int i, x, y;
+  int i, j, x, y;
+
+  /* ---------- custom element base property values (96 bytes) ------------- */
 
   element = getFile16BitBE(file);
 
@@ -1190,23 +1349,22 @@ 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 - 48);
+    ReadUnusedBytesFromFile(file, chunk_size - 43);
     return chunk_size_expected;
   }
 
-  /* read custom property values */
+  ei->ce_value_fixed_initial = getFile16BitBE(file);
+  ei->ce_value_random_initial = getFile16BitBE(file);
+  ei->use_last_ce_value = getFile8Bit(file);
 
   ei->use_gfx_element = getFile8Bit(file);
   ei->gfx_element = getMappedElement(getFile16BitBE(file));
 
-  ei->collect_score = getFile8Bit(file);
-  ei->collect_count = getFile8Bit(file);
+  ei->collect_score_initial = getFile8Bit(file);
+  ei->collect_count_initial = getFile8Bit(file);
 
   ei->drop_delay_fixed = getFile8Bit(file);
   ei->push_delay_fixed = getFile8Bit(file);
@@ -1224,7 +1382,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[x][y] = getMappedElement(getFile16BitBE(file));
+      ei->content.e[x][y] = getMappedElement(getFile16BitBE(file));
 
   ei->move_enter_element = getMappedElement(getFile16BitBE(file));
   ei->move_leave_element = getMappedElement(getFile16BitBE(file));
@@ -1242,18 +1400,22 @@ 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);
 
-  /* read change property values */
+  /* ---------- change page property values (48 bytes) --------------------- */
 
   setElementChangePages(ei, ei->num_change_pages);
 
   for (i = 0; i < ei->num_change_pages; i++)
   {
     struct ElementChangeInfo *change = &ei->change_page[i];
+    unsigned long event_bits;
 
     /* always start with reliable default values */
     setElementChangeInfoToDefaults(change);
 
-    change->events = getFile32BitBE(file);
+    event_bits = getFile32BitBE(file);
+    for (j = 0; j < NUM_CHANGE_EVENTS; j++)
+      if (event_bits & (1 << j))
+       change->has_event[j] = TRUE;
 
     change->target_element = getMappedElement(getFile16BitBE(file));
 
@@ -1273,27 +1435,25 @@ 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[x][y] = getMappedElement(getFile16BitBE(file));
+       change->target_content.e[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));
 
-    /* some free bytes for future change property values and padding */
-    ReadUnusedBytesFromFile(file, 6);
-
-#else
+    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, 8);
-#endif
+    ReadUnusedBytesFromFile(file, 1);
   }
 
   /* mark this custom element as modified */
@@ -1346,6 +1506,96 @@ 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)
 {
@@ -1437,6 +1687,8 @@ 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 }
     };
 
@@ -1879,7 +2131,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][x][y] =
+       level->yamyam_content[i].e[x][y] =
          map_em_element_yam(header[i * 9 + y * 3 + x]);
 
   level->amoeba_speed          = (header[52] * 256 + header[53]) % 256;
@@ -1906,7 +2158,7 @@ static void OLD_LoadLevelFromFileInfo_EM(struct LevelInfo *level,
   level->field[x][y] = EL_PLAYER_2;
 }
 
-#else
+#endif
 
 void CopyNativeLevel_RND_to_EM(struct LevelInfo *level)
 {
@@ -1948,7 +2200,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][x][y]);
+         map_element_RND_to_EM(level->yamyam_content[i].e[x][y]);
 
   lev->amoeba_time             = level->amoeba_speed;
   lev->wonderwall_time_initial = level->time_magic_wall;
@@ -1968,11 +2220,11 @@ void CopyNativeLevel_RND_to_EM(struct LevelInfo *level)
   lev->magnify_time            = level->magnify_time;
   lev->wind_direction_initial  = level->wind_direction_initial;
 
-  for (i = 0; i < NUM_MAGIC_BALL_CONTENTS; i++)
+  for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
     for (j = 0; j < 8; j++)
       lev->ball_array[i][j] =
        map_element_RND_to_EM(level->
-                             ball_content[i][ball_xy[j][0]][ball_xy[j][1]]);
+                             ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]]);
 
   for (i = 0; i < 16; i++)
     lev->android_array[i] = FALSE;     /* !!! YET TO COME !!! */
@@ -2060,7 +2312,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][x][y] =
+       level->yamyam_content[i].e[x][y] =
          map_element_EM_to_RND(lev->eater_array[i][y * 3 + x]);
 
   level->amoeba_speed          = lev->amoeba_time;
@@ -2081,9 +2333,9 @@ void CopyNativeLevel_EM_to_RND(struct LevelInfo *level)
   level->magnify_time          = lev->magnify_time;
   level->wind_direction_initial        = lev->wind_direction_initial;
 
-  for (i = 0; i < NUM_MAGIC_BALL_CONTENTS; i++)
+  for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
     for (j = 0; j < 8; j++)
-      level->ball_content[i][ball_xy[j][0]][ball_xy[j][1]] =
+      level->ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]] =
        map_element_EM_to_RND(lev->ball_array[i][j]);
 
   for (i = 0; i < 16; i++)
@@ -2116,8 +2368,6 @@ 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)
@@ -2289,7 +2539,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][x][y] = EL_EMPTY;
+       level->yamyam_content[i].e[x][y] = EL_EMPTY;
 }
 
 static void LoadLevelFromFileInfo_SP(struct LevelInfo *level,
@@ -2538,22 +2788,8 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename)
 #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
   {
-#if 0
-    printf("\n::: This level is private or contributed: '%s'\n", filename);
-#endif
-
-#if 0
-    printf("\n::: Use the stored game engine version for this level\n");
-#endif
-
     /* 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.
@@ -2564,21 +2800,9 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename)
        pre-2.0 levels, where the game version is still taken from the
        file format version used to store the level -- see above). */
 
-#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))
@@ -2588,11 +2812,18 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename)
     if (level->game_version < VERSION_IDENT(2,2,0,0))
       level->use_spring_bug = TRUE;
 
+    /* time orb caused limited time in endless time levels before 3.1.2 */
+    if (level->game_version < VERSION_IDENT(3,1,2,0))
+      level->use_time_orb_bug = TRUE;
+
     /* 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;
 
+      /* correct "can move into acid" settings (all zero in old levels) */
+
       level->can_move_into_acid_bits = 0; /* nothing can move into acid */
       level->dont_collide_with_bits = 0; /* nothing is deadly when colliding */
 
@@ -2604,6 +2835,8 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename)
       for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
        SET_PROPERTY(EL_CUSTOM_START + i, EP_CAN_MOVE_INTO_ACID, TRUE);
 
+      /* correct trigger settings (stored as zero == "none" in old levels) */
+
       for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
       {
        int element = EL_CUSTOM_START + i;
@@ -2618,35 +2851,9 @@ 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         /* 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
-
-#if 0
-    printf("\n::: Use latest game engine version for this level.\n");
-#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
@@ -2655,11 +2862,6 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename)
        of the corresponding game more accurate, while (hopefully) not breaking
        existing levels created from other players. */
 
-#if 0
-    printf("::: changing engine from %d to %d\n",
-          level->game_version, GAME_VERSION_ACTUAL);
-#endif
-
     level->game_version = GAME_VERSION_ACTUAL;
 
     /* Set special EM style gems behaviour: EM style gems slip down from
@@ -2672,10 +2874,6 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename)
     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)
@@ -2683,7 +2881,8 @@ 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) */
+     (these following values were accidentally changed in version 3.0.1)
+     (this seems to be needed only for 'ab_levelset3' and 'ab_levelset4') */
   if (level->game_version <= VERSION_IDENT(3,0,0,0))
   {
     for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
@@ -2691,7 +2890,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_BY_PLAYER_OBSOLETE; j--)
+      for (j = CE_BY_OTHER_ACTION; j >= CE_VALUE_GETS_ZERO; j--)
       {
        if (HAS_CHANGE_EVENT(element, j - 2))
        {
@@ -2701,7 +2900,7 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename)
       }
 
       /* order of checking and copying events to be mapped is important */
-      for (j = CE_OTHER_GETS_COLLECTED; j >= CE_HITTING_SOMETHING; j--)
+      for (j = CE_PLAYER_COLLECTS_X; j >= CE_HITTING_SOMETHING; j--)
       {
        if (HAS_CHANGE_EVENT(element, j - 1))
        {
@@ -2712,21 +2911,6 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename)
     }
   }
 
-  /* some custom element change events get mapped since version 3.0.3 */
-  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))
-    {
-      SET_CHANGE_EVENT(element, CE_BY_PLAYER_OBSOLETE, FALSE);
-      SET_CHANGE_EVENT(element, CE_BY_COLLISION_OBSOLETE, FALSE);
-
-      SET_CHANGE_EVENT(element, CE_BY_DIRECT_ACTION, TRUE);
-    }
-  }
-
   /* initialize "can_change" field for old levels with only one change page */
   if (level->game_version <= VERSION_IDENT(3,0,2,0))
   {
@@ -2740,22 +2924,50 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename)
   }
 
   /* correct custom element values (for old levels without these options) */
-  for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+  if (level->game_version < VERSION_IDENT(3,1,1,0))
   {
-    int element = EL_CUSTOM_START + i;
-    struct ElementInfo *ei = &element_info[element];
+    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_MOVING)
-      ei->access_direction = MV_ALL_DIRECTIONS;
+      if (ei->access_direction == MV_NO_DIRECTION)
+       ei->access_direction = MV_ALL_DIRECTIONS;
 
-    for (j = 0; j < ei->num_change_pages; j++)
+#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 1
+  /* correct custom element values (fix invalid values for all versions) */
+  if (1)
+  {
+    for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
     {
-      struct ElementChangeInfo *change = &ei->change_page[j];
+      int element = EL_CUSTOM_START + i;
+      struct ElementInfo *ei = &element_info[element];
 
-      if (change->trigger_side == CH_SIDE_NONE)
-       change->trigger_side = CH_SIDE_ANY;
+      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;
+      }
     }
   }
+#endif
 
   /* initialize "can_explode" field for old levels which did not store this */
   /* !!! CHECK THIS -- "<= 3,1,0,0" IS PROBABLY WRONG !!! */
@@ -2790,39 +3002,14 @@ 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][x][y] =
-         getMappedElementByVersion(level->yamyam_content[i][x][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. */
@@ -2835,37 +3022,9 @@ 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++)
-    {
-      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;
-    }
-  }
+      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++)
@@ -2882,7 +3041,6 @@ static void LoadLevel_InitPlayfield(struct LevelInfo *level, char *filename)
 
 void LoadLevelTemplate(int nr)
 {
-#if 1
   char *filename;
 
   setLevelFileInfo(&level_template.file_info, nr);
@@ -2890,34 +3048,14 @@ 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);
@@ -2925,30 +3063,12 @@ 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)
@@ -2977,7 +3097,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][x][y]));
+                          level->yamyam_content[i].e[x][y]));
   putFile8Bit(file, level->amoeba_speed);
   putFile8Bit(file, level->time_magic_wall);
   putFile8Bit(file, level->time_wheel);
@@ -3041,9 +3161,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][x][y]);
+         putFile16BitBE(file, level->yamyam_content[i].e[x][y]);
        else
-         putFile8Bit(file, level->yamyam_content[i][x][y]);
+         putFile8Bit(file, level->yamyam_content[i].e[x][y]);
 }
 #endif
 
@@ -3062,7 +3182,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][x][y];
+         content_array[i][x][y] = level->yamyam_content[i].e[x][y];
   }
   else if (element == EL_BD_AMOEBA)
   {
@@ -3184,63 +3304,64 @@ 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 (element_info[element].modified_settings)
+    if (ei->modified_settings)
     {
       if (check < num_changed_custom_elements)
       {
        putFile16BitBE(file, element);
 
        for (j = 0; j < MAX_ELEMENT_NAME_LEN; j++)
-         putFile8Bit(file, element_info[element].description[j]);
+         putFile8Bit(file, ei->description[j]);
 
        putFile32BitBE(file, Properties[element][EP_BITFIELD_BASE]);
 
        /* some free bytes for future properties and padding */
        WriteUnusedBytesToFile(file, 7);
 
-       putFile8Bit(file, element_info[element].use_gfx_element);
-       putFile16BitBE(file, element_info[element].gfx_element);
+       putFile8Bit(file, ei->use_gfx_element);
+       putFile16BitBE(file, ei->gfx_element);
 
-       putFile8Bit(file, element_info[element].collect_score);
-       putFile8Bit(file, element_info[element].collect_count);
+       putFile8Bit(file, ei->collect_score_initial);
+       putFile8Bit(file, ei->collect_count_initial);
 
-       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->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].move_pattern);
-       putFile8Bit(file, element_info[element].move_direction_initial);
-       putFile8Bit(file, element_info[element].move_stepsize);
+       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, element_info[element].content[x][y]);
+           putFile16BitBE(file, ei->content.e[x][y]);
 
-       putFile32BitBE(file, element_info[element].change->events);
+       putFile32BitBE(file, ei->change->events);
 
-       putFile16BitBE(file, element_info[element].change->target_element);
+       putFile16BitBE(file, ei->change->target_element);
 
-       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->delay_fixed);
+       putFile16BitBE(file, ei->change->delay_random);
+       putFile16BitBE(file, ei->change->delay_frames);
 
-       putFile16BitBE(file, element_info[element].change->trigger_element);
+       putFile16BitBE(file, ei->change->trigger_element);
 
-       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->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->random_percentage);
-       putFile8Bit(file, element_info[element].change->replace_when);
+       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, element_info[element].change->content[x][y]);
+           putFile16BitBE(file, ei->change->content.e[x][y]);
 
-       putFile8Bit(file, element_info[element].slippery_type);
+       putFile8Bit(file, ei->slippery_type);
 
        /* some free bytes for future properties and padding */
        WriteUnusedBytesToFile(file, LEVEL_CPART_CUS3_UNUSED);
@@ -3258,7 +3379,9 @@ static void SaveLevel_CUS3(FILE *file, struct LevelInfo *level,
 static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element)
 {
   struct ElementInfo *ei = &element_info[element];
-  int i, x, y;
+  int i, j, x, y;
+
+  /* ---------- custom element base property values (96 bytes) ------------- */
 
   putFile16BitBE(file, element);
 
@@ -3270,16 +3393,15 @@ static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element)
 
   putFile8Bit(file, ei->num_change_pages);
 
-  /* some free bytes for future base property values and padding */
-  WriteUnusedBytesToFile(file, 5);
-
-  /* write custom property values */
+  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);
 
-  putFile8Bit(file, ei->collect_score);
-  putFile8Bit(file, ei->collect_count);
+  putFile8Bit(file, ei->collect_score_initial);
+  putFile8Bit(file, ei->collect_count_initial);
 
   putFile8Bit(file, ei->drop_delay_fixed);
   putFile8Bit(file, ei->push_delay_fixed);
@@ -3297,7 +3419,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[x][y]);
+      putFile16BitBE(file, ei->content.e[x][y]);
 
   putFile16BitBE(file, ei->move_enter_element);
   putFile16BitBE(file, ei->move_leave_element);
@@ -3315,13 +3437,18 @@ static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element)
   /* some free bytes for future custom property values and padding */
   WriteUnusedBytesToFile(file, 1);
 
-  /* write change property values */
+  /* ---------- change page property values (48 bytes) --------------------- */
 
   for (i = 0; i < ei->num_change_pages; i++)
   {
     struct ElementChangeInfo *change = &ei->change_page[i];
+    unsigned long event_bits = 0;
+
+    for (j = 0; j < NUM_CHANGE_EVENTS; j++)
+      if (change->has_event[j])
+       event_bits |= (1 << j);
 
-    putFile32BitBE(file, change->events);
+    putFile32BitBE(file, event_bits);
 
     putFile16BitBE(file, change->target_element);
 
@@ -3341,25 +3468,23 @@ 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[x][y]);
+       putFile16BitBE(file, change->target_content.e[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)));
 
-    /* some free bytes for future change property values and padding */
-    WriteUnusedBytesToFile(file, 6);
-
-#else
+    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, 8);
-#endif
+    WriteUnusedBytesToFile(file, 1);
   }
 }
 
@@ -3388,9 +3513,93 @@ 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;
+  int body_chunk_size, conf_chunk_size;
   int i, x, y;
   FILE *file;
 
@@ -3415,7 +3624,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][x][y] > 255)
+       if (level->yamyam_content[i].e[x][y] > 255)
          level->encoding_16bit_yamyam = TRUE;
 
   /* check amoeba content for 16-bit elements */
@@ -3499,6 +3708,15 @@ 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);
@@ -3670,12 +3888,12 @@ static int LoadTape_BODY(FILE *file, int chunk_size, struct TapeInfo *tape)
 
   for (i = 0; i < tape->length; i++)
   {
-    if (i >= MAX_TAPELEN)
+    if (i >= MAX_TAPE_LEN)
       break;
 
     for (j = 0; j < MAX_PLAYERS; j++)
     {
-      tape->pos[i].action[j] = MV_NO_MOVING;
+      tape->pos[i].action[j] = MV_NONE;
 
       if (tape->player_participates[j])
        tape->pos[i].action[j] = getFile8Bit(file);
@@ -3722,7 +3940,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_NO_MOVING;
+         tape->pos[i].action[j] = MV_NONE;
        tape->pos[i].delay--;
 
        i++;
@@ -3754,10 +3972,6 @@ void LoadTapeFromFilename(char *filename)
   {
     tape.no_valid_file = TRUE;
 
-#if 0
-    Error(ERR_WARN, "cannot read tape '%s' -- using empty tape", filename);
-#endif
-
     return;
   }
 
@@ -3959,7 +4173,7 @@ void SaveTape(int nr)
   InitTapeDirectory(leveldir_current->subdir);
 
   /* if a tape still exists, ask to overwrite it */
-  if (access(filename, F_OK) == 0)
+  if (fileExists(filename))
   {
     new_tape = FALSE;
     if (!Request("Replace old tape ?", REQ_ASK))
@@ -4012,21 +4226,12 @@ 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",
@@ -4038,7 +4243,7 @@ void DumpTape(struct TapeInfo *tape)
 
   for (i = 0; i < tape->length; i++)
   {
-    if (i >= MAX_TAPELEN)
+    if (i >= MAX_TAPE_LEN)
       break;
 
     printf("%03d: ", i);
@@ -4732,7 +4937,6 @@ 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]);
@@ -4897,18 +5101,10 @@ 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;
 
@@ -5007,7 +5203,6 @@ void LoadMusicInfo()
   }
 
 #if 0
-  /* TEST-ONLY */
   for (next = music_file_info; next != NULL; next = next->next)
     printf("::: title == '%s'\n", next->title);
 #endif
@@ -5248,7 +5443,6 @@ 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,
@@ -5284,7 +5478,6 @@ void LoadHelpTextInfo()
   }
 
 #if 0
-  /* TEST ONLY */
   BEGIN_HASH_ITERATION(helptext_info, itr)
   {
     printf("::: '%s' => '%s'\n",