rnd-20050424-1-src
[rocksndiamonds.git] / src / files.c
index 9ff9a52fbddd7127a6eea81ab833c7b68ef041e3..b1754033ec4d371828e6067a56e79ac23d753cc9 100644 (file)
@@ -428,36 +428,14 @@ static int getFileTypeFromBasename(char *basename)
   return LEVEL_FILE_TYPE_UNKNOWN;
 }
 
-static char *getSingleLevelBasename(int nr, int type)
+static char *getSingleLevelBasename(int nr)
 {
   static char basename[MAX_FILENAME_LEN];
-  char *level_filename = getStringCopy(leveldir_current->level_filename);
 
-  if (level_filename == NULL)
-    level_filename = getStringCat2("%03d.", LEVELFILE_EXTENSION);
+  if (nr < 0)
+    sprintf(basename, "template.%s", LEVELFILE_EXTENSION);
   else
-    type = LEVEL_FILE_TYPE_UNKNOWN;    /* force specified file name/pattern */
-
-  switch (type)
-  {
-    case LEVEL_FILE_TYPE_RND:
-      if (nr < 0)
-       sprintf(basename, "template.%s", LEVELFILE_EXTENSION);
-      else
-       sprintf(basename, "%03d.%s", nr, LEVELFILE_EXTENSION);
-      break;
-
-    case LEVEL_FILE_TYPE_EM:
-      sprintf(basename, "%d", nr);
-      break;
-
-    case LEVEL_FILE_TYPE_UNKNOWN:
-    default:
-      sprintf(basename, level_filename, nr);
-      break;
-  }
-
-  free(level_filename);
+    sprintf(basename, "%03d.%s", nr, LEVELFILE_EXTENSION);
 
   return basename;
 }
@@ -500,9 +478,9 @@ static char *getPackedLevelBasename(int type)
   return basename;
 }
 
-static char *getSingleLevelFilename(int nr, int type)
+static char *getSingleLevelFilename(int nr)
 {
-  return getLevelFilenameFromBasename(getSingleLevelBasename(nr, type));
+  return getLevelFilenameFromBasename(getSingleLevelBasename(nr));
 }
 
 #if 0
@@ -514,9 +492,10 @@ static char *getPackedLevelFilename(int type)
 
 char *getDefaultLevelFilename(int nr)
 {
-  return getSingleLevelFilename(nr, LEVEL_FILE_TYPE_RND);
+  return getSingleLevelFilename(nr);
 }
 
+#if 0
 static void setLevelFileInfo_SingleLevelFilename(struct LevelFileInfo *lfi,
                                                 int type)
 {
@@ -525,6 +504,23 @@ static void setLevelFileInfo_SingleLevelFilename(struct LevelFileInfo *lfi,
   lfi->basename = getSingleLevelBasename(lfi->nr, lfi->type);
   lfi->filename = getLevelFilenameFromBasename(lfi->basename);
 }
+#endif
+
+static void setLevelFileInfo_FormatLevelFilename(struct LevelFileInfo *lfi,
+                                                int type, char *format, ...)
+{
+  static char basename[MAX_FILENAME_LEN];
+  va_list ap;
+
+  va_start(ap, format);
+  vsprintf(basename, format, ap);
+  va_end(ap);
+
+  lfi->type = type;
+  lfi->packed = FALSE;
+  lfi->basename = basename;
+  lfi->filename = getLevelFilenameFromBasename(lfi->basename);
+}
 
 static void setLevelFileInfo_PackedLevelFilename(struct LevelFileInfo *lfi,
                                                 int type)
@@ -564,7 +560,8 @@ static int getFiletypeFromID(char *filetype_id)
   return filetype;
 }
 
-static void determineLevelFileInfo_Filename(struct LevelFileInfo *lfi)
+#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)
@@ -603,6 +600,79 @@ static void determineLevelFileInfo_Filename(struct LevelFileInfo *lfi)
   /* 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;
+
+  /* special case: level number is negative => check for level template file */
+  if (nr < 0)
+  {
+    setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_RND,
+                                        "template.%s", LEVELFILE_EXTENSION);
+
+    /* no fallback if template file not existing */
+    return;
+  }
+
+  /* special case: check for file name/pattern specified in "levelinfo.conf" */
+  if (leveldir_current->level_filename != NULL)
+  {
+    int filetype = getFiletypeFromID(leveldir_current->level_filetype);
+
+    setLevelFileInfo_FormatLevelFilename(lfi, filetype,
+                                        leveldir_current->level_filename, nr);
+    if (fileExists(lfi->filename))
+      return;
+  }
+
+  /* check for native Rocks'n'Diamonds level file */
+  setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_RND,
+                                      "%03d.%s", nr, LEVELFILE_EXTENSION);
+  if (fileExists(lfi->filename))
+    return;
+
+  /* check for Emerald Mine level file (V1) */
+  setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_EM, "a%c%c",
+                                      'a' + (nr / 10) % 26, '0' + nr % 10);
+  if (fileExists(lfi->filename))
+    return;
+  setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_EM, "A%c%c",
+                                      'A' + (nr / 10) % 26, '0' + nr % 10);
+  if (fileExists(lfi->filename))
+    return;
+
+  /* check for Emerald Mine level file (V2 to V5) */
+  setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_EM, "%d", nr);
+  if (fileExists(lfi->filename))
+    return;
+
+  /* check for Emerald Mine level file (V6 / single mode) */
+  setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_EM, "%02ds", nr);
+  if (fileExists(lfi->filename))
+    return;
+  setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_EM, "%02dS", nr);
+  if (fileExists(lfi->filename))
+    return;
+
+  /* check for Emerald Mine level file (V6 / teamwork mode) */
+  setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_EM, "%02dt", nr);
+  if (fileExists(lfi->filename))
+    return;
+  setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_EM, "%02dT", nr);
+  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 -- use default values (and fail later) */
+  setLevelFileInfo_FormatLevelFilename(lfi, LEVEL_FILE_TYPE_RND,
+                                      "%03d.%s", nr, LEVELFILE_EXTENSION);
+}
 
 static void determineLevelFileInfo_Filetype(struct LevelFileInfo *lfi)
 {
@@ -2034,7 +2104,7 @@ void CopyNativeLevel_EM_to_RND(struct LevelInfo *level)
   level->field[ply2->x_initial - 1][ply2->y_initial - 1] = EL_PLAYER_2;
   level->field[ply1->x_initial - 1][ply1->y_initial - 1] = EL_PLAYER_1;
 
-#if 1
+#if 0
   printf("::: native Emerald Mine file version: %d\n", level_em->file_version);
 #endif
 }
@@ -2431,10 +2501,17 @@ void LoadLevelFromFileInfo(struct LevelInfo *level,
       break;
   }
 
+  /* if level file is invalid, restore level structure to default values */
+  if (level->no_valid_file)
+    setLevelInfoToDefaults(level);
+
   if (level->game_engine_type == GAME_ENGINE_TYPE_UNKNOWN)
     level->game_engine_type = GAME_ENGINE_TYPE_RND;
 
-  CopyNativeLevel_Native_to_RND(level);
+  if (level_file_info->type == LEVEL_FILE_TYPE_RND)
+    CopyNativeLevel_RND_to_Native(level);
+  else
+    CopyNativeLevel_Native_to_RND(level);
 }
 
 void LoadLevelFromFilename(struct LevelInfo *level, char *filename)
@@ -4092,17 +4169,18 @@ void SaveScore(int nr)
 #define SETUP_TOKEN_QUICK_DOORS                        10
 #define SETUP_TOKEN_TEAM_MODE                  11
 #define SETUP_TOKEN_HANDICAP                   12
-#define SETUP_TOKEN_TIME_LIMIT                 13
-#define SETUP_TOKEN_FULLSCREEN                 14
-#define SETUP_TOKEN_ASK_ON_ESCAPE              15
-#define SETUP_TOKEN_GRAPHICS_SET               16
-#define SETUP_TOKEN_SOUNDS_SET                 17
-#define SETUP_TOKEN_MUSIC_SET                  18
-#define SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS    19
-#define SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS      20
-#define SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC       21
-
-#define NUM_GLOBAL_SETUP_TOKENS                        22
+#define SETUP_TOKEN_SKIP_LEVELS                        13
+#define SETUP_TOKEN_TIME_LIMIT                 14
+#define SETUP_TOKEN_FULLSCREEN                 15
+#define SETUP_TOKEN_ASK_ON_ESCAPE              16
+#define SETUP_TOKEN_GRAPHICS_SET               17
+#define SETUP_TOKEN_SOUNDS_SET                 18
+#define SETUP_TOKEN_MUSIC_SET                  19
+#define SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS    20
+#define SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS      21
+#define SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC       22
+
+#define NUM_GLOBAL_SETUP_TOKENS                        23
 
 /* editor setup */
 #define SETUP_TOKEN_EDITOR_EL_BOULDERDASH      0
@@ -4182,6 +4260,7 @@ static struct TokenInfo global_setup_tokens[] =
   { TYPE_SWITCH, &si.quick_doors,      "quick_doors"                   },
   { TYPE_SWITCH, &si.team_mode,                "team_mode"                     },
   { TYPE_SWITCH, &si.handicap,         "handicap"                      },
+  { TYPE_SWITCH, &si.skip_levels,      "skip_levels"                   },
   { TYPE_SWITCH, &si.time_limit,       "time_limit"                    },
   { TYPE_SWITCH, &si.fullscreen,       "fullscreen"                    },
   { TYPE_SWITCH, &si.ask_on_escape,    "ask_on_escape"                 },
@@ -4283,6 +4362,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si)
   si->quick_doors = FALSE;
   si->team_mode = FALSE;
   si->handicap = TRUE;
+  si->skip_levels = TRUE;
   si->time_limit = TRUE;
   si->fullscreen = FALSE;
   si->ask_on_escape = TRUE;
@@ -4611,7 +4691,19 @@ void LoadUserDefinedEditorElementList(int **elements, int *num_elements)
   {
     char *value = getHashEntry(element_hash, list->token);
 
-    if (value)
+    if (value == NULL)         /* try to find obsolete token mapping */
+    {
+      char *mapped_token = get_mapped_token(list->token);
+
+      if (mapped_token != NULL)
+      {
+       value = getHashEntry(element_hash, mapped_token);
+
+       free(mapped_token);
+      }
+    }
+
+    if (value != NULL)
     {
       (*elements)[(*num_elements)++] = atoi(value);
     }