X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Flibgame%2Fsetup.c;h=102d5fd13d92d0bd7fa1fa0ca494d7ecbe34994b;hb=f857fec3082c785b0dd271b6ad1b7642a2ed4e65;hp=943c063a1ab8d48665feb5701a465d6727feaa96;hpb=28f0f8708f4b4f8c4f39f1b23bc5fc7e0fed7579;p=rocksndiamonds.git diff --git a/src/libgame/setup.c b/src/libgame/setup.c index 943c063a..102d5fd1 100644 --- a/src/libgame/setup.c +++ b/src/libgame/setup.c @@ -21,6 +21,7 @@ #include "joystick.h" #include "text.h" #include "misc.h" +#include "hash.h" /* file names and filename extensions */ #if !defined(PLATFORM_MSDOS) @@ -170,7 +171,7 @@ static char *getTapeDir(char *level_subdir) static char *getScoreDir(char *level_subdir) { static char *score_dir = NULL; - char *data_dir = options.rw_base_directory; + char *data_dir = getCommonDataDir(); char *score_subdir = SCORES_DIRECTORY; if (score_dir) @@ -408,7 +409,7 @@ char *getSetupFilename() static char *getCorrectedImageBasename(char *basename) { - char *result = basename; + char *basename_corrected = basename; #if defined(PLATFORM_MSDOS) if (program.filename_prefix != NULL) @@ -416,20 +417,25 @@ static char *getCorrectedImageBasename(char *basename) int prefix_len = strlen(program.filename_prefix); if (strncmp(basename, program.filename_prefix, prefix_len) == 0) - result = &basename[prefix_len]; - } -#endif + basename_corrected = &basename[prefix_len]; - return result; -} + /* if corrected filename is still longer than standard MS-DOS filename + size (8 characters + 1 dot + 3 characters file extension), shorten + filename by writing file extension after 8th basename character */ + if (strlen(basename_corrected) > 8+1+3) + { + static char *msdos_filename = NULL; -static boolean fileExists(char *filename) -{ -#if 0 - printf("checking file '%s'\n", filename); + if (msdos_filename != NULL) + free(msdos_filename); + + msdos_filename = getStringCopy(basename_corrected); + strncpy(&msdos_filename[8], &basename[strlen(basename) - 1+3], 1+3 + 1); + } + } #endif - return (access(filename, F_OK) == 0); + return basename_corrected; } char *getCustomImageFilename(char *basename) @@ -448,10 +454,14 @@ char *getCustomImageFilename(char *basename) if (fileExists(filename)) return filename; + free(filename); + /* 2nd try: look for special artwork in current level series directory */ filename = getPath3(getCurrentLevelDir(), GRAPHICS_DIRECTORY, basename); if (fileExists(filename)) return filename; + + free(filename); } /* 3rd try: look for special artwork in configured artwork directory */ @@ -459,11 +469,15 @@ char *getCustomImageFilename(char *basename) if (fileExists(filename)) return filename; + free(filename); + /* 4th try: look for default artwork in new default artwork directory */ filename = getPath2(getDefaultGraphicsDir(GRAPHICS_SUBDIR), basename); if (fileExists(filename)) return filename; + free(filename); + /* 5th try: look for default artwork in old default artwork directory */ filename = getPath2(options.graphics_directory, basename); if (fileExists(filename)) @@ -486,10 +500,14 @@ char *getCustomSoundFilename(char *basename) if (fileExists(filename)) return filename; + free(filename); + /* 2nd try: look for special artwork in current level series directory */ filename = getPath3(getCurrentLevelDir(), SOUNDS_DIRECTORY, basename); if (fileExists(filename)) return filename; + + free(filename); } /* 3rd try: look for special artwork in configured artwork directory */ @@ -497,11 +515,15 @@ char *getCustomSoundFilename(char *basename) if (fileExists(filename)) return filename; + free(filename); + /* 4th try: look for default artwork in new default artwork directory */ filename = getPath2(getDefaultSoundsDir(SOUNDS_SUBDIR), basename); if (fileExists(filename)) return filename; + free(filename); + /* 5th try: look for default artwork in old default artwork directory */ filename = getPath2(options.sounds_directory, basename); if (fileExists(filename)) @@ -539,10 +561,14 @@ char *getCustomMusicDirectory(void) if (fileExists(directory)) return directory; + free(directory); + /* 2nd try: look for special artwork in current level series directory */ directory = getPath2(getCurrentLevelDir(), MUSIC_DIRECTORY); if (fileExists(directory)) return directory; + + free(directory); } /* 3rd try: look for special artwork in configured artwork directory */ @@ -550,11 +576,15 @@ char *getCustomMusicDirectory(void) if (fileExists(directory)) return directory; + free(directory); + /* 4th try: look for default artwork in new default artwork directory */ directory = getStringCopy(getDefaultMusicDir(MUSIC_SUBDIR)); if (fileExists(directory)) return directory; + free(directory); + /* 5th try: look for default artwork in old default artwork directory */ directory = getStringCopy(options.music_directory); if (fileExists(directory)) @@ -572,6 +602,7 @@ void InitTapeDirectory(char *level_subdir) void InitScoreDirectory(char *level_subdir) { + createDirectory(getCommonDataDir(), "common data", PERMS_PUBLIC); createDirectory(getScoreDir(NULL), "main score", PERMS_PUBLIC); createDirectory(getScoreDir(level_subdir), "level score", PERMS_PUBLIC); } @@ -847,15 +878,33 @@ char *getUserDataDir(void) { static char *userdata_dir = NULL; - if (!userdata_dir) + if (userdata_dir == NULL) + userdata_dir = getPath2(getHomeDir(), program.userdata_directory); + + return userdata_dir; +} + +char *getCommonDataDir(void) +{ + static char *common_data_dir = NULL; + +#if defined(PLATFORM_WIN32) + if (common_data_dir == NULL) { - char *home_dir = getHomeDir(); - char *data_dir = program.userdata_directory; + char *dir = checked_malloc(MAX_PATH + 1); - userdata_dir = getPath2(home_dir, data_dir); + if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_COMMON_DOCUMENTS, NULL, 0, dir)) + && strcmp(dir, "") != 0) /* empty for Windows 95/98 */ + common_data_dir = getPath2(dir, program.userdata_directory); + else + common_data_dir = options.rw_base_directory; } +#else + if (common_data_dir == NULL) + common_data_dir = options.rw_base_directory; +#endif - return userdata_dir; + return common_data_dir; } char *getSetupDir() @@ -972,158 +1021,206 @@ boolean checkCookieString(const char *cookie, const char *template) } /* ------------------------------------------------------------------------- */ -/* setup file list handling functions */ +/* setup file list and hash handling functions */ /* ------------------------------------------------------------------------- */ -int get_string_integer_value(char *s) +char *getFormattedSetupEntry(char *token, char *value) { - static char *number_text[][3] = - { - { "0", "zero", "null", }, - { "1", "one", "first" }, - { "2", "two", "second" }, - { "3", "three", "third" }, - { "4", "four", "fourth" }, - { "5", "five", "fifth" }, - { "6", "six", "sixth" }, - { "7", "seven", "seventh" }, - { "8", "eight", "eighth" }, - { "9", "nine", "ninth" }, - { "10", "ten", "tenth" }, - { "11", "eleven", "eleventh" }, - { "12", "twelve", "twelfth" }, - }; + int i; + static char entry[MAX_LINE_LEN]; - int i, j; - char *s_lower = getStringToLower(s); - int result = -1; + /* start with the token and some spaces to format output line */ + sprintf(entry, "%s:", token); + for (i=strlen(entry); itoken = getStringCopy(token); + new->value = getStringCopy(value); - free(s_lower); + new->next = NULL; - return result; + return new; } -boolean get_string_boolean_value(char *s) +void freeSetupFileList(SetupFileList *list) { - char *s_lower = getStringToLower(s); - boolean result = FALSE; + if (list == NULL) + return; - if (strcmp(s_lower, "true") == 0 || - strcmp(s_lower, "yes") == 0 || - strcmp(s_lower, "on") == 0 || - get_string_integer_value(s) == 1) - result = TRUE; + if (list->token) + free(list->token); + if (list->value) + free(list->value); + if (list->next) + freeSetupFileList(list->next); + free(list); +} - free(s_lower); +char *getListEntry(SetupFileList *list, char *token) +{ + if (list == NULL) + return NULL; - return result; + if (strcmp(list->token, token) == 0) + return list->value; + else + return getListEntry(list->next, token); } -char *getFormattedSetupEntry(char *token, char *value) +void setListEntry(SetupFileList *list, char *token, char *value) { - int i; - static char entry[MAX_LINE_LEN]; - - /* start with the token and some spaces to format output line */ - sprintf(entry, "%s:", token); - for (i=strlen(entry); itoken, token) == 0) + { + if (list->value) + free(list->value); - return entry; + list->value = getStringCopy(value); + } + else if (list->next == NULL) + list->next = newSetupFileList(token, value); + else + setListEntry(list->next, token, value); } -void freeSetupFileList(struct SetupFileList *setup_file_list) +#ifdef DEBUG +static void printSetupFileList(SetupFileList *list) { - if (!setup_file_list) + if (!list) return; - if (setup_file_list->token) - free(setup_file_list->token); - if (setup_file_list->value) - free(setup_file_list->value); - if (setup_file_list->next) - freeSetupFileList(setup_file_list->next); - free(setup_file_list); + printf("token: '%s'\n", list->token); + printf("value: '%s'\n", list->value); + + printSetupFileList(list->next); } +#endif -static struct SetupFileList *newSetupFileList(char *token, char *value) +#ifdef DEBUG +DEFINE_HASHTABLE_INSERT(insert_hash_entry, char, char); +DEFINE_HASHTABLE_SEARCH(search_hash_entry, char, char); +DEFINE_HASHTABLE_CHANGE(change_hash_entry, char, char); +DEFINE_HASHTABLE_REMOVE(remove_hash_entry, char, char); +#else +#define insert_hash_entry hashtable_insert +#define search_hash_entry hashtable_search +#define change_hash_entry hashtable_change +#define remove_hash_entry hashtable_remove +#endif + +static unsigned int get_hash_from_key(void *key) { - struct SetupFileList *new = checked_malloc(sizeof(struct SetupFileList)); + /* + djb2 - new->token = checked_malloc(strlen(token) + 1); - strcpy(new->token, token); + 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. - new->value = checked_malloc(strlen(value) + 1); - strcpy(new->value, value); + 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. - new->next = NULL; + Ozan (oz) Yigit [http://www.cs.yorku.ca/~oz/hash.html] + */ - return new; + char *str = (char *)key; + unsigned int hash = 5381; + int c; + + while ((c = *str++)) + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + + return hash; } -char *getTokenValue(struct SetupFileList *setup_file_list, char *token) +static int keys_are_equal(void *key1, void *key2) { - if (!setup_file_list) - return NULL; + return (strcmp((char *)key1, (char *)key2) == 0); +} - if (strcmp(setup_file_list->token, token) == 0) - return setup_file_list->value; - else - return getTokenValue(setup_file_list->next, token); +SetupFileHash *newSetupFileHash() +{ + SetupFileHash *new_hash = + create_hashtable(16, 0.75, get_hash_from_key, keys_are_equal); + + return new_hash; } -static void setTokenValue(struct SetupFileList *setup_file_list, - char *token, char *value) +void freeSetupFileHash(SetupFileHash *hash) { - if (!setup_file_list) + if (hash == NULL) return; - if (strcmp(setup_file_list->token, token) == 0) - { - free(setup_file_list->value); - setup_file_list->value = checked_malloc(strlen(value) + 1); - strcpy(setup_file_list->value, value); - } - else if (setup_file_list->next == NULL) - setup_file_list->next = newSetupFileList(token, value); - else - setTokenValue(setup_file_list->next, token, value); + hashtable_destroy(hash, 1); /* 1 == also free values stored in hash */ } -#ifdef DEBUG -static void printSetupFileList(struct SetupFileList *setup_file_list) +char *getHashEntry(SetupFileHash *hash, char *token) { - if (!setup_file_list) + if (hash == NULL) + return NULL; + + return search_hash_entry(hash, token); +} + +void setHashEntry(SetupFileHash *hash, char *token, char *value) +{ + char *value_copy; + + if (hash == NULL) return; - printf("token: '%s'\n", setup_file_list->token); - printf("value: '%s'\n", setup_file_list->value); + value_copy = getStringCopy(value); + + /* change value; if it does not exist, insert it as new */ + if (!change_hash_entry(hash, token, value_copy)) + if (!insert_hash_entry(hash, getStringCopy(token), value_copy)) + Error(ERR_EXIT, "cannot insert into hash -- aborting"); +} - printSetupFileList(setup_file_list->next); +#if 0 +#ifdef DEBUG +static void printSetupFileHash(SetupFileHash *hash) +{ + BEGIN_HASH_ITERATION(hash, itr) + { + printf("token: '%s'\n", HASH_ITERATION_TOKEN(itr)); + printf("value: '%s'\n", HASH_ITERATION_VALUE(itr)); + } + END_HASH_ITERATION(hash, itr) } #endif +#endif -struct SetupFileList *loadSetupFileList(char *filename) +static void *loadSetupFileData(char *filename, boolean use_hash) { int line_len; char line[MAX_LINE_LEN]; char *token, *value, *line_ptr; - struct SetupFileList *setup_file_list = newSetupFileList("", ""); - struct SetupFileList *first_valid_list_entry; - + void *setup_file_data; FILE *file; + if (use_hash) + setup_file_data = newSetupFileHash(); + else + setup_file_data = newSetupFileList("", ""); + if (!(file = fopen(filename, MODE_READ))) { Error(ERR_WARN, "cannot open configuration file '%s'", filename); @@ -1183,47 +1280,57 @@ struct SetupFileList *loadSetupFileList(char *filename) break; if (*token && *value) - setTokenValue(setup_file_list, token, value); + { + if (use_hash) + setHashEntry((SetupFileHash *)setup_file_data, token, value); + else + setListEntry((SetupFileList *)setup_file_data, token, value); + } } fclose(file); - first_valid_list_entry = setup_file_list->next; + if (use_hash) + { + if (hashtable_count((SetupFileHash *)setup_file_data) == 0) + Error(ERR_WARN, "configuration file '%s' is empty", filename); + } + else + { + SetupFileList *setup_file_list = (SetupFileList *)setup_file_data; + SetupFileList *first_valid_list_entry = setup_file_list->next; - /* free empty list header */ - setup_file_list->next = NULL; - freeSetupFileList(setup_file_list); + /* free empty list header */ + setup_file_list->next = NULL; + freeSetupFileList(setup_file_list); + setup_file_data = first_valid_list_entry; - if (first_valid_list_entry == NULL) - Error(ERR_WARN, "configuration file '%s' is empty", filename); + if (first_valid_list_entry == NULL) + Error(ERR_WARN, "configuration file '%s' is empty", filename); + } - return first_valid_list_entry; + return setup_file_data; } -void checkSetupFileListIdentifier(struct SetupFileList *setup_file_list, - char *identifier) +SetupFileList *loadSetupFileList(char *filename) { - if (!setup_file_list) - return; + return (SetupFileList *)loadSetupFileData(filename, FALSE); +} - if (strcmp(setup_file_list->token, TOKEN_STR_FILE_IDENTIFIER) == 0) - { - if (!checkCookieString(setup_file_list->value, identifier)) - { - Error(ERR_WARN, "configuration file has wrong file identifier"); - return; - } - else - return; - } +SetupFileHash *loadSetupFileHash(char *filename) +{ + return (SetupFileHash *)loadSetupFileData(filename, TRUE); +} - if (setup_file_list->next) - checkSetupFileListIdentifier(setup_file_list->next, identifier); - else - { +void checkSetupFileHashIdentifier(SetupFileHash *setup_file_hash, + char *identifier) +{ + char *value = getHashEntry(setup_file_hash, TOKEN_STR_FILE_IDENTIFIER); + + if (value == NULL) Error(ERR_WARN, "configuration file has no file identifier"); - return; - } + else if (!checkCookieString(value, identifier)) + Error(ERR_WARN, "configuration file has wrong file identifier"); } @@ -1373,7 +1480,7 @@ void setSetupInfo(struct TokenInfo *token_info, { case TYPE_BOOLEAN: case TYPE_SWITCH: - *(boolean *)setup_value = get_string_boolean_value(token_value); + *(boolean *)setup_value = get_boolean_from_string(token_value); break; case TYPE_KEY: @@ -1385,7 +1492,7 @@ void setSetupInfo(struct TokenInfo *token_info, break; case TYPE_INTEGER: - *(int *)setup_value = get_string_integer_value(token_value); + *(int *)setup_value = get_integer_from_string(token_value); break; case TYPE_STRING: @@ -1473,11 +1580,11 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first, { char *directory_path = getPath2(level_directory, directory_name); char *filename = getPath2(directory_path, LEVELINFO_FILENAME); - struct SetupFileList *setup_file_list = loadSetupFileList(filename); + SetupFileHash *setup_file_hash = loadSetupFileHash(filename); LevelDirTree *leveldir_new = NULL; int i; - if (setup_file_list == NULL) + if (setup_file_hash == NULL) { Error(ERR_WARN, "ignoring level directory '%s'", directory_path); @@ -1496,13 +1603,13 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first, leveldir_new->filename = getStringCopy(directory_name); - checkSetupFileListIdentifier(setup_file_list, getCookie("LEVELINFO")); + checkSetupFileHashIdentifier(setup_file_hash, getCookie("LEVELINFO")); /* set all structure fields according to the token/value pairs */ ldi = *leveldir_new; for (i=0; iname, ANONYMOUS_NAME) == 0) @@ -1549,7 +1656,7 @@ static boolean LoadLevelInfoFromLevelConf(TreeInfo **node_first, pushTreeInfo(node_first, leveldir_new); - freeSetupFileList(setup_file_list); + freeSetupFileHash(setup_file_hash); if (leveldir_new->level_group) { @@ -1658,14 +1765,14 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first, { char *directory_path = getPath2(base_directory, directory_name); char *filename = getPath2(directory_path, ARTWORKINFO_FILENAME(type)); - struct SetupFileList *setup_file_list = NULL; + SetupFileHash *setup_file_hash = NULL; TreeInfo *artwork_new = NULL; int i; if (access(filename, F_OK) == 0) /* file exists */ - setup_file_list = loadSetupFileList(filename); + setup_file_hash = loadSetupFileHash(filename); - if (setup_file_list == NULL) /* no config file -- look for artwork files */ + if (setup_file_hash == NULL) /* no config file -- look for artwork files */ { DIR *dir; struct dirent *dir_entry; @@ -1708,17 +1815,17 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first, artwork_new->filename = getStringCopy(directory_name); - if (setup_file_list) /* (before defining ".color" and ".class_desc") */ + if (setup_file_hash) /* (before defining ".color" and ".class_desc") */ { #if 0 - checkSetupFileListIdentifier(setup_file_list, getCookie("...")); + checkSetupFileHashIdentifier(setup_file_hash, getCookie("...")); #endif /* set all structure fields according to the token/value pairs */ ldi = *artwork_new; for (i=0; iname, ANONYMOUS_NAME) == 0) @@ -1752,11 +1859,11 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first, artwork_new->user_defined = (artwork_new->basepath == OPTIONS_ARTWORK_DIRECTORY(type) ? FALSE : TRUE); - /* (may use ".sort_priority" from "setup_file_list" above) */ + /* (may use ".sort_priority" from "setup_file_hash" above) */ artwork_new->color = ARTWORKCOLOR(artwork_new); artwork_new->class_desc = getLevelClassDescription(artwork_new); - if (setup_file_list == NULL) /* (after determining ".user_defined") */ + if (setup_file_hash == NULL) /* (after determining ".user_defined") */ { if (artwork_new->name != NULL) free(artwork_new->name); @@ -1791,7 +1898,7 @@ static boolean LoadArtworkInfoFromArtworkConf(TreeInfo **node_first, pushTreeInfo(node_first, artwork_new); - freeSetupFileList(setup_file_list); + freeSetupFileHash(setup_file_hash); free(directory_path); free(filename); @@ -2060,6 +2167,9 @@ static void SaveUserLevelInfo() ldi.first_level = 1; ldi.sort_priority = LEVELCLASS_USER_START; ldi.readonly = FALSE; + ldi.graphics_set = getStringCopy(GRAPHICS_SUBDIR); + ldi.sounds_set = getStringCopy(SOUNDS_SUBDIR); + ldi.music_set = getStringCopy(MUSIC_SUBDIR); fprintf(file, "%s\n\n", getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER, getCookie("LEVELINFO"))); @@ -2162,7 +2272,7 @@ char *getSetupLine(struct TokenInfo *token_info, char *prefix, int token_nr) void LoadLevelSetup_LastSeries() { char *filename; - struct SetupFileList *level_setup_list = NULL; + SetupFileHash *level_setup_hash = NULL; /* always start with reliable default values */ leveldir_current = getFirstValidTreeInfoEntry(leveldir_first); @@ -2173,19 +2283,19 @@ void LoadLevelSetup_LastSeries() filename = getPath2(getSetupDir(), LEVELSETUP_FILENAME); - if ((level_setup_list = loadSetupFileList(filename))) + if ((level_setup_hash = loadSetupFileHash(filename))) { char *last_level_series = - getTokenValue(level_setup_list, TOKEN_STR_LAST_LEVEL_SERIES); + getHashEntry(level_setup_hash, TOKEN_STR_LAST_LEVEL_SERIES); leveldir_current = getTreeInfoFromIdentifier(leveldir_first, last_level_series); if (leveldir_current == NULL) leveldir_current = getFirstValidTreeInfoEntry(leveldir_first); - checkSetupFileListIdentifier(level_setup_list, getCookie("LEVELSETUP")); + checkSetupFileHashIdentifier(level_setup_hash, getCookie("LEVELSETUP")); - freeSetupFileList(level_setup_list); + freeSetupFileHash(level_setup_hash); } else Error(ERR_WARN, "using default setup values"); @@ -2258,6 +2368,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); @@ -2268,6 +2379,7 @@ static void checkSeriesInfo() Error(ERR_WARN, "additional level %d found", levelnum_value); leveldir_current->last_level = levelnum_value; } +#endif } } @@ -2277,7 +2389,7 @@ static void checkSeriesInfo() void LoadLevelSetup_SeriesInfo() { char *filename; - struct SetupFileList *level_setup_list = NULL; + SetupFileHash *level_setup_hash = NULL; char *level_subdir = leveldir_current->filename; /* always start with reliable default values */ @@ -2293,11 +2405,11 @@ void LoadLevelSetup_SeriesInfo() filename = getPath2(getLevelSetupDir(level_subdir), LEVELSETUP_FILENAME); - if ((level_setup_list = loadSetupFileList(filename))) + if ((level_setup_hash = loadSetupFileHash(filename))) { char *token_value; - token_value = getTokenValue(level_setup_list, TOKEN_STR_LAST_PLAYED_LEVEL); + token_value = getHashEntry(level_setup_hash, TOKEN_STR_LAST_PLAYED_LEVEL); if (token_value) { @@ -2309,7 +2421,7 @@ void LoadLevelSetup_SeriesInfo() level_nr = leveldir_current->last_level; } - token_value = getTokenValue(level_setup_list, TOKEN_STR_HANDICAP_LEVEL); + token_value = getHashEntry(level_setup_hash, TOKEN_STR_HANDICAP_LEVEL); if (token_value) { @@ -2326,9 +2438,9 @@ void LoadLevelSetup_SeriesInfo() leveldir_current->handicap_level = level_nr; } - checkSetupFileListIdentifier(level_setup_list, getCookie("LEVELSETUP")); + checkSetupFileHashIdentifier(level_setup_hash, getCookie("LEVELSETUP")); - freeSetupFileList(level_setup_list); + freeSetupFileHash(level_setup_hash); } else Error(ERR_WARN, "using default setup values");