rnd-20030801-1-src
[rocksndiamonds.git] / src / libgame / setup.c
index 1e9a56e2e1917f2f2779fc8c2256a065d42be6bc..47f57cb0152912f466b02b2d1ced52c770b4f508 100644 (file)
@@ -268,6 +268,16 @@ static char *getDefaultMusicDir(char *music_subdir)
   return music_dir;
 }
 
   return music_dir;
 }
 
+static char *getDefaultArtworkDir(int type)
+{
+  return (type == TREE_TYPE_GRAPHICS_DIR ?
+         getDefaultGraphicsDir(GRAPHICS_SUBDIR) :
+         type == TREE_TYPE_SOUNDS_DIR ?
+         getDefaultSoundsDir(SOUNDS_SUBDIR) :
+         type == TREE_TYPE_MUSIC_DIR ?
+         getDefaultMusicDir(MUSIC_SUBDIR) : "");
+}
+
 static char *getUserGraphicsDir()
 {
   static char *usergraphics_dir = NULL;
 static char *getUserGraphicsDir()
 {
   static char *usergraphics_dir = NULL;
@@ -328,13 +338,29 @@ void setLevelArtworkDir(TreeInfo *ti)
      ti->type == TREE_TYPE_SOUNDS_DIR   ? leveldir_current->sounds_set :
      leveldir_current->music_set);
 
      ti->type == TREE_TYPE_SOUNDS_DIR   ? leveldir_current->sounds_set :
      leveldir_current->music_set);
 
-  if ((level_artwork = getTreeInfoFromIdentifier(ti, artwork_set)) == NULL)
-    return;
-
   if (*artwork_path_ptr != NULL)
     free(*artwork_path_ptr);
 
   if (*artwork_path_ptr != NULL)
     free(*artwork_path_ptr);
 
-  *artwork_path_ptr = getStringCopy(getSetupArtworkDir(level_artwork));
+  if ((level_artwork = getTreeInfoFromIdentifier(ti, artwork_set)))
+    *artwork_path_ptr = getStringCopy(getSetupArtworkDir(level_artwork));
+  else
+  {
+    /* No (or non-existing) artwork configured in "levelinfo.conf". This would
+       normally result in using the artwork configured in the setup menu. But
+       if an artwork subdirectory exists (which might contain custom artwork
+       or an artwork configuration file), this level artwork must be treated
+       as relative to the default "classic" artwork, not to the artwork that
+       is currently configured in the setup menu. */
+
+    char *dir = getPath2(getCurrentLevelDir(), ARTWORK_DIRECTORY(ti->type));
+
+    if (fileExists(dir))
+      *artwork_path_ptr = getStringCopy(getDefaultArtworkDir(ti->type));
+    else
+      *artwork_path_ptr = getStringCopy(UNDEFINED_FILENAME);
+
+    free(dir);
+  }
 }
 
 static char *getLevelArtworkDir(int type)
 }
 
 static char *getLevelArtworkDir(int type)
@@ -361,7 +387,11 @@ char *getLevelFilename(int nr)
   if (filename != NULL)
     free(filename);
 
   if (filename != NULL)
     free(filename);
 
-  sprintf(basename, "%03d.%s", nr, LEVELFILE_EXTENSION);
+  if (nr < 0)
+    sprintf(basename, "template.%s", LEVELFILE_EXTENSION);
+  else
+    sprintf(basename, "%03d.%s", nr, LEVELFILE_EXTENSION);
+
   filename = getPath2(getCurrentLevelDir(), basename);
 
   return filename;
   filename = getPath2(getCurrentLevelDir(), basename);
 
   return filename;
@@ -449,23 +479,56 @@ char *getCustomImageFilename(char *basename)
 
   if (!setup.override_level_graphics)
   {
 
   if (!setup.override_level_graphics)
   {
+#if 0
     /* 1st try: look for special artwork configured in level series config */
     filename = getPath2(getLevelArtworkDir(TREE_TYPE_GRAPHICS_DIR), basename);
     /* 1st try: look for special artwork configured in level series config */
     filename = getPath2(getLevelArtworkDir(TREE_TYPE_GRAPHICS_DIR), basename);
+#if 0
+    if (strcmp(basename, "RocksScreen.pcx") == 0)
+      printf("::: trying 1 '%s' ...\n", filename);
+#endif
     if (fileExists(filename))
       return filename;
 
     free(filename);
     if (fileExists(filename))
       return filename;
 
     free(filename);
+#endif
 
     /* 2nd try: look for special artwork in current level series directory */
     filename = getPath3(getCurrentLevelDir(), GRAPHICS_DIRECTORY, basename);
 
     /* 2nd try: look for special artwork in current level series directory */
     filename = getPath3(getCurrentLevelDir(), GRAPHICS_DIRECTORY, basename);
+#if 0
+    /*
+    if (strcmp(basename, "RocksScreen.pcx") == 0)
+    */
+      printf("::: trying 2 '%s' ...\n", filename);
+#endif
+    if (fileExists(filename))
+      return filename;
+
+    free(filename);
+
+#if 1
+    /* 1st try: look for special artwork configured in level series config */
+    filename = getPath2(getLevelArtworkDir(TREE_TYPE_GRAPHICS_DIR), basename);
+#if 0
+    /*
+    if (strcmp(basename, "RocksScreen.pcx") == 0)
+    */
+      printf("::: trying 2.1 '%s' ...\n", filename);
+#endif
     if (fileExists(filename))
       return filename;
 
     free(filename);
     if (fileExists(filename))
       return filename;
 
     free(filename);
+#endif
   }
 
   /* 3rd try: look for special artwork in configured artwork directory */
   filename = getPath2(getSetupArtworkDir(artwork.gfx_current), basename);
   }
 
   /* 3rd try: look for special artwork in configured artwork directory */
   filename = getPath2(getSetupArtworkDir(artwork.gfx_current), basename);
+#if 0
+  /*
+  if (strcmp(basename, "RocksScreen.pcx") == 0)
+  */
+    printf("::: trying 3 '%s' ...\n", filename);
+#endif
   if (fileExists(filename))
     return filename;
 
   if (fileExists(filename))
     return filename;
 
@@ -473,6 +536,10 @@ char *getCustomImageFilename(char *basename)
 
   /* 4th try: look for default artwork in new default artwork directory */
   filename = getPath2(getDefaultGraphicsDir(GRAPHICS_SUBDIR), basename);
 
   /* 4th try: look for default artwork in new default artwork directory */
   filename = getPath2(getDefaultGraphicsDir(GRAPHICS_SUBDIR), basename);
+#if 0
+  if (strcmp(basename, "RocksScreen.pcx") == 0)
+    printf("::: trying 4 '%s' ...\n", filename);
+#endif
   if (fileExists(filename))
     return filename;
 
   if (fileExists(filename))
     return filename;
 
@@ -480,6 +547,10 @@ char *getCustomImageFilename(char *basename)
 
   /* 5th try: look for default artwork in old default artwork directory */
   filename = getPath2(options.graphics_directory, basename);
 
   /* 5th try: look for default artwork in old default artwork directory */
   filename = getPath2(options.graphics_directory, basename);
+#if 0
+  if (strcmp(basename, "RocksScreen.pcx") == 0)
+    printf("::: trying 5 '%s' ...\n", filename);
+#endif
   if (fileExists(filename))
     return filename;
 
   if (fileExists(filename))
     return filename;
 
@@ -495,12 +566,14 @@ char *getCustomSoundFilename(char *basename)
 
   if (!setup.override_level_sounds)
   {
 
   if (!setup.override_level_sounds)
   {
+#if 0
     /* 1st try: look for special artwork configured in level series config */
     filename = getPath2(getLevelArtworkDir(TREE_TYPE_SOUNDS_DIR), basename);
     if (fileExists(filename))
       return filename;
 
     free(filename);
     /* 1st try: look for special artwork configured in level series config */
     filename = getPath2(getLevelArtworkDir(TREE_TYPE_SOUNDS_DIR), basename);
     if (fileExists(filename))
       return filename;
 
     free(filename);
+#endif
 
     /* 2nd try: look for special artwork in current level series directory */
     filename = getPath3(getCurrentLevelDir(), SOUNDS_DIRECTORY, basename);
 
     /* 2nd try: look for special artwork in current level series directory */
     filename = getPath3(getCurrentLevelDir(), SOUNDS_DIRECTORY, basename);
@@ -508,6 +581,15 @@ char *getCustomSoundFilename(char *basename)
       return filename;
 
     free(filename);
       return filename;
 
     free(filename);
+
+#if 1
+    /* 1st try: look for special artwork configured in level series config */
+    filename = getPath2(getLevelArtworkDir(TREE_TYPE_SOUNDS_DIR), basename);
+    if (fileExists(filename))
+      return filename;
+
+    free(filename);
+#endif
   }
 
   /* 3rd try: look for special artwork in configured artwork directory */
   }
 
   /* 3rd try: look for special artwork in configured artwork directory */
@@ -547,6 +629,18 @@ char *getCustomArtworkConfigFilename(int type)
   return getCustomArtworkFilename(ARTWORKINFO_FILENAME(type), type);
 }
 
   return getCustomArtworkFilename(ARTWORKINFO_FILENAME(type), type);
 }
 
+char *getCustomArtworkLevelConfigFilename(int type)
+{
+  static char *filename = NULL;
+
+  if (filename != NULL)
+    free(filename);
+
+  filename = getPath2(getLevelArtworkDir(type), ARTWORKINFO_FILENAME(type));
+
+  return filename;
+}
+
 char *getCustomMusicDirectory(void)
 {
   static char *directory = NULL;
 char *getCustomMusicDirectory(void)
 {
   static char *directory = NULL;
@@ -556,12 +650,14 @@ char *getCustomMusicDirectory(void)
 
   if (!setup.override_level_music)
   {
 
   if (!setup.override_level_music)
   {
+#if 0
     /* 1st try: look for special artwork configured in level series config */
     directory = getStringCopy(getLevelArtworkDir(TREE_TYPE_MUSIC_DIR));
     if (fileExists(directory))
       return directory;
 
     free(directory);
     /* 1st try: look for special artwork configured in level series config */
     directory = getStringCopy(getLevelArtworkDir(TREE_TYPE_MUSIC_DIR));
     if (fileExists(directory))
       return directory;
 
     free(directory);
+#endif
 
     /* 2nd try: look for special artwork in current level series directory */
     directory = getPath2(getCurrentLevelDir(), MUSIC_DIRECTORY);
 
     /* 2nd try: look for special artwork in current level series directory */
     directory = getPath2(getCurrentLevelDir(), MUSIC_DIRECTORY);
@@ -569,6 +665,15 @@ char *getCustomMusicDirectory(void)
       return directory;
 
     free(directory);
       return directory;
 
     free(directory);
+
+#if 1
+    /* 1st try: look for special artwork configured in level series config */
+    directory = getStringCopy(getLevelArtworkDir(TREE_TYPE_MUSIC_DIR));
+    if (fileExists(directory))
+      return directory;
+
+    free(directory);
+#endif
   }
 
   /* 3rd try: look for special artwork in configured artwork directory */
   }
 
   /* 3rd try: look for special artwork in configured artwork directory */
@@ -1040,6 +1145,18 @@ char *getFormattedSetupEntry(char *token, char *value)
   return entry;
 }
 
   return entry;
 }
 
+SetupFileList *newSetupFileList(char *token, char *value)
+{
+  SetupFileList *new = checked_malloc(sizeof(SetupFileList));
+
+  new->token = getStringCopy(token);
+  new->value = getStringCopy(value);
+
+  new->next = NULL;
+
+  return new;
+}
+
 void freeSetupFileList(SetupFileList *list)
 {
   if (list == NULL)
 void freeSetupFileList(SetupFileList *list)
 {
   if (list == NULL)
@@ -1054,18 +1171,6 @@ void freeSetupFileList(SetupFileList *list)
   free(list);
 }
 
   free(list);
 }
 
-SetupFileList *newSetupFileList(char *token, char *value)
-{
-  SetupFileList *new = checked_malloc(sizeof(SetupFileList));
-
-  new->token = getStringCopy(token);
-  new->value = getStringCopy(value);
-
-  new->next = NULL;
-
-  return new;
-}
-
 char *getListEntry(SetupFileList *list, char *token)
 {
   if (list == NULL)
 char *getListEntry(SetupFileList *list, char *token)
 {
   if (list == NULL)
@@ -1125,11 +1230,19 @@ static unsigned int get_hash_from_key(void *key)
   /*
     djb2
 
   /*
     djb2
 
-    this algorithm (k=33) was first reported by dan bernstein many years ago in
-    comp.lang.c. another version of this algorithm (now favored by bernstein)
-    uses xor: hash(i) = hash(i - 1) * 33 ^ str[i]; the magic of number 33 (why
+    This algorithm (k=33) was first reported by Dan Bernstein many years ago in
+    'comp.lang.c'. Another version of this algorithm (now favored by Bernstein)
+    uses XOR: hash(i) = hash(i - 1) * 33 ^ str[i]; the magic of number 33 (why
     it works better than many other constants, prime or not) has never been
     adequately explained.
     it works better than many other constants, prime or not) has never been
     adequately explained.
+
+    If you just want to have a good hash function, and cannot wait, djb2
+    is one of the best string hash functions i know. It has excellent
+    distribution and speed on many different sets of keys and table sizes.
+    You are not likely to do better with one of the "well known" functions
+    such as PJW, K&R, etc.
+
+    Ozan (oz) Yigit [http://www.cs.yorku.ca/~oz/hash.html]
   */
 
   char *str = (char *)key;
   */
 
   char *str = (char *)key;
@@ -1147,15 +1260,6 @@ static int keys_are_equal(void *key1, void *key2)
   return (strcmp((char *)key1, (char *)key2) == 0);
 }
 
   return (strcmp((char *)key1, (char *)key2) == 0);
 }
 
-void freeSetupFileHash(SetupFileHash *hash)
-{
-  if (hash == NULL)
-    return;
-
-  hashtable_destroy(hash, 1);  /* 1 == also free values */
-  free(hash);
-}
-
 SetupFileHash *newSetupFileHash()
 {
   SetupFileHash *new_hash =
 SetupFileHash *newSetupFileHash()
 {
   SetupFileHash *new_hash =
@@ -1164,6 +1268,14 @@ SetupFileHash *newSetupFileHash()
   return new_hash;
 }
 
   return new_hash;
 }
 
+void freeSetupFileHash(SetupFileHash *hash)
+{
+  if (hash == NULL)
+    return;
+
+  hashtable_destroy(hash, 1);  /* 1 == also free values stored in hash */
+}
+
 char *getHashEntry(SetupFileHash *hash, char *token)
 {
   if (hash == NULL)
 char *getHashEntry(SetupFileHash *hash, char *token)
 {
   if (hash == NULL)
@@ -1191,26 +1303,6 @@ void setHashEntry(SetupFileHash *hash, char *token, char *value)
 #ifdef DEBUG
 static void printSetupFileHash(SetupFileHash *hash)
 {
 #ifdef DEBUG
 static void printSetupFileHash(SetupFileHash *hash)
 {
-#if 0
-  if (hash == NULL)
-    return;
-
-  /* iterator constructor only returns valid iterator for non-empty hash */
-  if (hash != NULL && hashtable_count(hash) > 0)
-  {
-    struct hashtable_itr *itr = hashtable_iterator(hash);
-
-    do
-    {
-      printf("token: '%s'\n", (char *)hashtable_iterator_key(itr));
-      printf("value: '%s'\n", (char *)hashtable_iterator_value(itr));
-    }
-    while (hashtable_iterator_advance(itr));
-
-    free(itr);
-  }
-#endif
-
   BEGIN_HASH_ITERATION(hash, itr)
   {
     printf("token: '%s'\n", HASH_ITERATION_TOKEN(itr));
   BEGIN_HASH_ITERATION(hash, itr)
   {
     printf("token: '%s'\n", HASH_ITERATION_TOKEN(itr));
@@ -2031,16 +2123,25 @@ void LoadArtworkInfo()
   /* before sorting, the first entries will be from the user directory */
   artwork.gfx_current =
     getTreeInfoFromIdentifier(artwork.gfx_first, setup.graphics_set);
   /* before sorting, the first entries will be from the user directory */
   artwork.gfx_current =
     getTreeInfoFromIdentifier(artwork.gfx_first, setup.graphics_set);
+  if (artwork.gfx_current == NULL)
+    artwork.gfx_current =
+      getTreeInfoFromIdentifier(artwork.gfx_first, GRAPHICS_SUBDIR);
   if (artwork.gfx_current == NULL)
     artwork.gfx_current = getFirstValidTreeInfoEntry(artwork.gfx_first);
 
   artwork.snd_current =
     getTreeInfoFromIdentifier(artwork.snd_first, setup.sounds_set);
   if (artwork.gfx_current == NULL)
     artwork.gfx_current = getFirstValidTreeInfoEntry(artwork.gfx_first);
 
   artwork.snd_current =
     getTreeInfoFromIdentifier(artwork.snd_first, setup.sounds_set);
+  if (artwork.snd_current == NULL)
+    artwork.snd_current =
+      getTreeInfoFromIdentifier(artwork.snd_first, SOUNDS_SUBDIR);
   if (artwork.snd_current == NULL)
     artwork.snd_current = getFirstValidTreeInfoEntry(artwork.snd_first);
 
   artwork.mus_current =
     getTreeInfoFromIdentifier(artwork.mus_first, setup.music_set);
   if (artwork.snd_current == NULL)
     artwork.snd_current = getFirstValidTreeInfoEntry(artwork.snd_first);
 
   artwork.mus_current =
     getTreeInfoFromIdentifier(artwork.mus_first, setup.music_set);
+  if (artwork.mus_current == NULL)
+    artwork.mus_current =
+      getTreeInfoFromIdentifier(artwork.mus_first, MUSIC_SUBDIR);
   if (artwork.mus_current == NULL)
     artwork.mus_current = getFirstValidTreeInfoEntry(artwork.mus_first);
 
   if (artwork.mus_current == NULL)
     artwork.mus_current = getFirstValidTreeInfoEntry(artwork.mus_first);
 
@@ -2125,6 +2226,9 @@ void LoadLevelArtworkInfo()
   {
     artwork.gfx_current =
       getTreeInfoFromIdentifier(artwork.gfx_first, setup.graphics_set);
   {
     artwork.gfx_current =
       getTreeInfoFromIdentifier(artwork.gfx_first, setup.graphics_set);
+    if (artwork.gfx_current == NULL)
+      artwork.gfx_current =
+       getTreeInfoFromIdentifier(artwork.gfx_first, GRAPHICS_SUBDIR);
     if (artwork.gfx_current == NULL)
       artwork.gfx_current = getFirstValidTreeInfoEntry(artwork.gfx_first);
   }
     if (artwork.gfx_current == NULL)
       artwork.gfx_current = getFirstValidTreeInfoEntry(artwork.gfx_first);
   }
@@ -2133,6 +2237,9 @@ void LoadLevelArtworkInfo()
   {
     artwork.snd_current =
       getTreeInfoFromIdentifier(artwork.snd_first, setup.sounds_set);
   {
     artwork.snd_current =
       getTreeInfoFromIdentifier(artwork.snd_first, setup.sounds_set);
+    if (artwork.snd_current == NULL)
+      artwork.snd_current =
+       getTreeInfoFromIdentifier(artwork.snd_first, SOUNDS_SUBDIR);
     if (artwork.snd_current == NULL)
       artwork.snd_current = getFirstValidTreeInfoEntry(artwork.snd_first);
   }
     if (artwork.snd_current == NULL)
       artwork.snd_current = getFirstValidTreeInfoEntry(artwork.snd_first);
   }
@@ -2141,6 +2248,9 @@ void LoadLevelArtworkInfo()
   {
     artwork.mus_current =
       getTreeInfoFromIdentifier(artwork.mus_first, setup.music_set);
   {
     artwork.mus_current =
       getTreeInfoFromIdentifier(artwork.mus_first, setup.music_set);
+    if (artwork.mus_current == NULL)
+      artwork.mus_current =
+       getTreeInfoFromIdentifier(artwork.mus_first, MUSIC_SUBDIR);
     if (artwork.mus_current == NULL)
       artwork.mus_current = getFirstValidTreeInfoEntry(artwork.mus_first);
   }
     if (artwork.mus_current == NULL)
       artwork.mus_current = getFirstValidTreeInfoEntry(artwork.mus_first);
   }
@@ -2381,6 +2491,7 @@ static void checkSeriesInfo()
 
       levelnum_value = atoi(levelnum_str);
 
 
       levelnum_value = atoi(levelnum_str);
 
+#if 0
       if (levelnum_value < leveldir_current->first_level)
       {
        Error(ERR_WARN, "additional level %d found", levelnum_value);
       if (levelnum_value < leveldir_current->first_level)
       {
        Error(ERR_WARN, "additional level %d found", levelnum_value);
@@ -2391,6 +2502,7 @@ static void checkSeriesInfo()
        Error(ERR_WARN, "additional level %d found", levelnum_value);
        leveldir_current->last_level = levelnum_value;
       }
        Error(ERR_WARN, "additional level %d found", levelnum_value);
        leveldir_current->last_level = levelnum_value;
       }
+#endif
     }
   }
 
     }
   }