rnd-20031019-3-src
[rocksndiamonds.git] / src / files.c
index ef7fa51f4792121c18f8290f180e698e75eacc57..61bd1af81bc931728934b5d0e0788ab1e611ac04 100644 (file)
@@ -34,8 +34,6 @@
 #define LEVEL_CHUNK_CNT3_UNUSED        10      /* unused CNT3 chunk bytes    */
 #define LEVEL_CPART_CUS3_SIZE  134     /* size of CUS3 chunk part    */
 #define LEVEL_CPART_CUS3_UNUSED        15      /* unused CUS3 bytes / part   */
-#define LEVEL_CPART_CUS4_SIZE  ???     /* size of CUS4 chunk part    */
-#define LEVEL_CPART_CUS4_UNUSED        ???     /* unused CUS4 bytes / part   */
 #define TAPE_HEADER_SIZE       20      /* size of tape file header   */
 #define TAPE_HEADER_UNUSED     3       /* unused tape header bytes   */
 
@@ -80,7 +78,7 @@ void setElementChangeInfoToDefaults(struct ElementChangeInfo *change)
 
   change->delay_fixed = 0;
   change->delay_random = 0;
-  change->delay_frames = -1;   /* later set to reliable default value */
+  change->delay_frames = 1;
 
   change->trigger_element = EL_EMPTY_SPACE;
 
@@ -88,7 +86,7 @@ void setElementChangeInfoToDefaults(struct ElementChangeInfo *change)
   change->use_content = FALSE;
   change->only_complete = FALSE;
   change->use_random_change = FALSE;
-  change->random = 0;
+  change->random = 100;
   change->power = CP_NON_DESTRUCTIVE;
 
   for(x=0; x<3; x++)
@@ -130,7 +128,7 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
   level->time_timegate = 10;
   level->amoeba_content = EL_DIAMOND;
   level->double_speed = FALSE;
-  level->gravity = FALSE;
+  level->initial_gravity = FALSE;
   level->em_slippery_gems = FALSE;
 
   level->use_custom_template = FALSE;
@@ -188,8 +186,8 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
     element_info[element].collect_score = 10;          /* special default */
     element_info[element].collect_count = 1;           /* special default */
 
-    element_info[element].push_delay_fixed = 2;                /* special default */
-    element_info[element].push_delay_random = 8;       /* special default */
+    element_info[element].push_delay_fixed = -1;       /* initialize later */
+    element_info[element].push_delay_random = -1;      /* initialize later */
     element_info[element].move_delay_fixed = 0;
     element_info[element].move_delay_random = 0;
 
@@ -374,7 +372,7 @@ static int LoadLevel_HEAD(FILE *file, int chunk_size, struct LevelInfo *level)
   level->time_wheel            = getFile8Bit(file);
   level->amoeba_content                = checkLevelElement(getFile8Bit(file));
   level->double_speed          = (getFile8Bit(file) == 1 ? TRUE : FALSE);
-  level->gravity               = (getFile8Bit(file) == 1 ? TRUE : FALSE);
+  level->initial_gravity       = (getFile8Bit(file) == 1 ? TRUE : FALSE);
   level->encoding_16bit_field  = (getFile8Bit(file) == 1 ? TRUE : FALSE);
   level->em_slippery_gems      = (getFile8Bit(file) == 1 ? TRUE : FALSE);
 
@@ -782,8 +780,13 @@ static int LoadLevel_CUS4(FILE *file, int chunk_size, struct LevelInfo *level)
 
     change->can_change = getFile8Bit(file);
 
+    change->sides = getFile8Bit(file);
+
+    if (change->sides == CH_SIDE_NONE) /* correct empty sides field */
+      change->sides = CH_SIDE_ANY;
+
     /* some free bytes for future change property values and padding */
-    ReadUnusedBytesFromFile(file, 9);
+    ReadUnusedBytesFromFile(file, 8);
   }
 
   /* mark this custom element as modified */
@@ -922,8 +925,6 @@ void LoadLevelFromFilename(struct LevelInfo *level, char *filename)
   fclose(file);
 }
 
-#if 1
-
 static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename)
 {
   if (leveldir_current == NULL)                /* only when dumping level */
@@ -1048,122 +1049,36 @@ static void LoadLevel_InitElements(struct LevelInfo *level, char *filename)
     }
   }
 
-  /* initialize element properties for level editor etc. */
-  InitElementPropertiesEngine(level->game_version);
-}
-
-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++)
+  /* set default push delay values (corrected since version 3.0.7) */
+  if (level->game_version < VERSION_IDENT(3,0,7))
   {
-    for(x=0; x<level->fieldx; x++)
-    {
-      int element = level->field[x][y];
-
-      if (level->game_version <= VERSION_IDENT(2,2,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))
-      {
-       /* 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);
-      }
-
-      level->field[x][y] = element;
-    }
-  }
-
-  /* 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 */
-  SetBorderElement();
-}
-
-#else
-
-static void LoadLevel_InitLevel(struct LevelInfo *level, char *filename)
-{
-  int i, j, x, y;
-
-  if (leveldir_current == NULL)                /* only when dumping level */
-    return;
-
-  /* determine correct game engine version of current level */
-  if (IS_LEVELCLASS_CONTRIBUTION(leveldir_current) ||
-      IS_LEVELCLASS_USER(leveldir_current))
-  {
-#if 0
-    printf("\n::: This level is private or contributed: '%s'\n", filename);
-#endif
-
-    /* For user contributed and private levels, use the version of
-       the game engine the levels were created for.
-       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). */
-
-    /* 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;
-    }
-
-    /* Default behaviour for EM style gems was "slippery" only in 2.0.1 */
-    if (level->game_version == VERSION_IDENT(2,0,1))
-      level->em_slippery_gems = TRUE;
+    game.default_push_delay_fixed = 2;
+    game.default_push_delay_random = 8;
   }
   else
   {
-#if 0
-    printf("\n::: ALWAYS USE LATEST ENGINE FOR THIS LEVEL: [%d] '%s'\n",
-          leveldir_current->sort_priority, filename);
-#endif
+    game.default_push_delay_fixed = 8;
+    game.default_push_delay_random = 8;
+  }
 
-    /* Always use the latest version of the game engine for all but
-       user contributed and private levels; 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 game emulation more accurate, while (hopefully) not
-       breaking existing levels created from other players. */
+  /* 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;
 
-    level->game_version = GAME_VERSION_ACTUAL;
+    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;
+  }
 
-    /* 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. */
+  /* initialize element properties for level editor etc. */
+  InitElementPropertiesEngine(level->game_version);
+}
 
-    if (level->file_version < FILE_VERSION_2_0)
-      level->em_slippery_gems = TRUE;
-  }
+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++)
@@ -1195,48 +1110,6 @@ static void LoadLevel_InitLevel(struct LevelInfo *level, char *filename)
     }
   }
 
-  /* map custom element change events that have changed in newer versions
-     (these following values have accidentally changed in version 3.0.1) */
-  if (level->game_version <= VERSION_IDENT(3,0,0))
-  {
-    for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
-    {
-      int element = EL_CUSTOM_START + i;
-
-      /* order of checking events to be mapped is important */
-      for (j=CE_BY_OTHER; j >= CE_BY_PLAYER; j--)
-      {
-       if (HAS_CHANGE_EVENT(element, j - 2))
-       {
-         SET_CHANGE_EVENT(element, j - 2, FALSE);
-         SET_CHANGE_EVENT(element, j, TRUE);
-       }
-      }
-
-      /* order of checking events to be mapped is important */
-      for (j=CE_OTHER_GETS_COLLECTED; j >= CE_COLLISION; j--)
-      {
-       if (HAS_CHANGE_EVENT(element, j - 1))
-       {
-         SET_CHANGE_EVENT(element, j - 1, FALSE);
-         SET_CHANGE_EVENT(element, j, TRUE);
-       }
-      }
-    }
-  }
-
-  /* initialize "can_change" field for old levels with only one change page */
-  if (level->game_version <= VERSION_IDENT(3,0,2))
-  {
-    for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
-    {
-      int element = EL_CUSTOM_START + i;
-
-      if (CAN_CHANGE(element))
-       element_info[element].change->can_change = TRUE;
-    }
-  }
-
   /* copy elements to runtime playfield array */
   for(x=0; x<MAX_LEV_FIELDX; x++)
     for(y=0; y<MAX_LEV_FIELDY; y++)
@@ -1248,13 +1121,8 @@ static void LoadLevel_InitLevel(struct LevelInfo *level, char *filename)
 
   /* determine border element for this level */
   SetBorderElement();
-
-  /* initialize element properties for level editor etc. */
-  InitElementPropertiesEngine(level->game_version);
 }
 
-#endif
-
 void LoadLevelTemplate(int level_nr)
 {
   char *filename = getLevelFilename(level_nr);
@@ -1318,7 +1186,7 @@ static void SaveLevel_HEAD(FILE *file, struct LevelInfo *level)
   putFile8Bit(file, (level->encoding_16bit_amoeba ? EL_EMPTY :
                     level->amoeba_content));
   putFile8Bit(file, (level->double_speed ? 1 : 0));
-  putFile8Bit(file, (level->gravity ? 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));
 
@@ -1649,8 +1517,10 @@ static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element)
 
     putFile8Bit(file, change->can_change);
 
+    putFile8Bit(file, change->sides);
+
     /* some free bytes for future change property values and padding */
-    WriteUnusedBytesToFile(file, 9);
+    WriteUnusedBytesToFile(file, 8);
   }
 }
 
@@ -1791,7 +1661,7 @@ void DumpLevel(struct LevelInfo *level)
   printf("\n");
   printf("Amoeba Speed: %d\n", level->amoeba_speed);
   printf("\n");
-  printf("Gravity:                %s\n", (level->gravity ? "yes" : "no"));
+  printf("Gravity:                %s\n", (level->initial_gravity ? "yes" : "no"));
   printf("Double Speed Movement:  %s\n", (level->double_speed ? "yes" : "no"));
   printf("EM style slippery gems: %s\n", (level->em_slippery_gems ? "yes" : "no"));
 
@@ -2811,20 +2681,6 @@ void LoadCustomElementDescriptions()
   freeSetupFileHash(setup_file_hash);
 }
 
-static int get_special_integer_from_string(char *string_raw)
-{
-  char *string = getStringToLower(string_raw);
-  int value = (strcmp(string, "none")  == 0 ? 0 :
-              strcmp(string, "short") == 0 ? 1 :
-              strcmp(string, "full")  == 0 ? 2 :
-              strcmp(string, "default")  == 0 ? 0 :
-              strcmp(string, "curtain")  == 0 ? 1 : -1);
-
-  free(string);
-
-  return value;
-}
-
 void LoadSpecialMenuDesignSettings()
 {
   char *filename = getCustomArtworkConfigFilename(ARTWORK_TYPE_GRAPHICS);
@@ -2835,15 +2691,9 @@ void LoadSpecialMenuDesignSettings()
   for (i=0; image_config_vars[i].token != NULL; i++)
     for (j=0; image_config[j].token != NULL; j++)
       if (strcmp(image_config_vars[i].token, image_config[j].token) == 0)
-      {
-       if (strcmp(image_config_vars[i].token, "game.envelope.anim_mode") == 0
-           || strcmp(image_config_vars[i].token, "door.anim_mode") == 0)
-         *image_config_vars[i].value =
-           get_special_integer_from_string(image_config[j].value);
-       else
-         *image_config_vars[i].value =
-           get_integer_from_string(image_config[j].value);
-      }
+       *image_config_vars[i].value =
+         get_auto_parameter_value(image_config_vars[i].token,
+                                  image_config[j].value);
 
   if ((setup_file_hash = loadSetupFileHash(filename)) == NULL)
     return;
@@ -2869,13 +2719,8 @@ void LoadSpecialMenuDesignSettings()
     char *value = getHashEntry(setup_file_hash, image_config_vars[i].token);
 
     if (value != NULL)
-    {
-      if (strcmp(image_config_vars[i].token, "game.envelope.anim_mode") == 0
-         || strcmp(image_config_vars[i].token, "door.anim_mode") == 0)
-       *image_config_vars[i].value = get_special_integer_from_string(value);
-      else
-       *image_config_vars[i].value = get_integer_from_string(value);
-    }
+      *image_config_vars[i].value =
+       get_auto_parameter_value(image_config_vars[i].token, value);
   }
 
   freeSetupFileHash(setup_file_hash);