rnd-20030726-1-src
[rocksndiamonds.git] / src / libgame / setup.c
index 1e9a56e2e1917f2f2779fc8c2256a065d42be6bc..574d37e84262217730ba644439c0a8e38907b255 100644 (file)
@@ -268,6 +268,16 @@ static char *getDefaultMusicDir(char *music_subdir)
   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;
@@ -328,13 +338,29 @@ void setLevelArtworkDir(TreeInfo *ti)
      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);
 
-  *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)
@@ -361,7 +387,11 @@ char *getLevelFilename(int nr)
   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;
@@ -449,23 +479,50 @@ char *getCustomImageFilename(char *basename)
 
   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);
+#if 0
+    if (strcmp(basename, "RocksScreen.pcx") == 0)
+      printf("::: trying 1 '%s' ...\n", filename);
+#endif
     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);
+#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);
+#endif
   }
 
   /* 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;
 
@@ -473,6 +530,10 @@ char *getCustomImageFilename(char *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;
 
@@ -480,6 +541,10 @@ char *getCustomImageFilename(char *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;
 
@@ -495,12 +560,14 @@ char *getCustomSoundFilename(char *basename)
 
   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);
+#endif
 
     /* 2nd try: look for special artwork in current level series directory */
     filename = getPath3(getCurrentLevelDir(), SOUNDS_DIRECTORY, basename);
@@ -508,6 +575,15 @@ char *getCustomSoundFilename(char *basename)
       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 */
@@ -547,6 +623,18 @@ char *getCustomArtworkConfigFilename(int 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;
@@ -556,12 +644,14 @@ char *getCustomMusicDirectory(void)
 
   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);
+#endif
 
     /* 2nd try: look for special artwork in current level series directory */
     directory = getPath2(getCurrentLevelDir(), MUSIC_DIRECTORY);
@@ -569,6 +659,15 @@ char *getCustomMusicDirectory(void)
       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 */
@@ -1040,6 +1139,18 @@ char *getFormattedSetupEntry(char *token, char *value)
   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)
@@ -1054,18 +1165,6 @@ void freeSetupFileList(SetupFileList *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)
@@ -1125,11 +1224,19 @@ static unsigned int get_hash_from_key(void *key)
   /*
     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.
+
+    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;
@@ -1147,15 +1254,6 @@ static int keys_are_equal(void *key1, void *key2)
   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 =
@@ -1164,6 +1262,14 @@ SetupFileHash *newSetupFileHash()
   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)
@@ -1191,26 +1297,6 @@ void setHashEntry(SetupFileHash *hash, char *token, char *value)
 #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));
@@ -2381,6 +2467,7 @@ static void checkSeriesInfo()
 
       levelnum_value = atoi(levelnum_str);
 
+#if 0
       if (levelnum_value < leveldir_current->first_level)
       {
        Error(ERR_WARN, "additional level %d found", levelnum_value);
@@ -2391,6 +2478,7 @@ static void checkSeriesInfo()
        Error(ERR_WARN, "additional level %d found", levelnum_value);
        leveldir_current->last_level = levelnum_value;
       }
+#endif
     }
   }