/* file names and filename extensions */
#ifndef MSDOS
#define USERDATA_DIRECTORY ".rocksndiamonds"
+#define LEVELSETUP_DIRECTORY "levelsetup"
#define SETUP_FILENAME "setup.conf"
#define LEVELSETUP_FILENAME "levelsetup.conf"
#define LEVELINFO_FILENAME "levelinfo.conf"
#define SCOREFILE_EXTENSION "score"
#else
#define USERDATA_DIRECTORY "userdata"
+#define LEVELSETUP_DIRECTORY "lvlsetup"
#define SETUP_FILENAME "setup.cnf"
#define LEVELSETUP_FILENAME "lvlsetup.cnf"
#define LEVELINFO_FILENAME "lvlinfo.cnf"
return score_dir;
}
+static char *getLevelSetupDir(char *level_subdir)
+{
+ static char *levelsetup_dir = NULL;
+ char *data_dir = getUserDataDir();
+ char *levelsetup_subdir = LEVELSETUP_DIRECTORY;
+
+ if (levelsetup_dir)
+ free(levelsetup_dir);
+
+ if (strlen(level_subdir) > 0)
+ levelsetup_dir = getPath3(data_dir, levelsetup_subdir, level_subdir);
+ else
+ levelsetup_dir = getPath2(data_dir, levelsetup_subdir);
+
+ return levelsetup_dir;
+}
+
static char *getLevelFilename(int nr)
{
static char *filename = NULL;
}
}
+static void InitLevelSetupDirectory(char *level_subdir)
+{
+ createDirectory(getUserDataDir(), "user data");
+ createDirectory(getLevelSetupDir(""), "main level setup");
+ createDirectory(getLevelSetupDir(level_subdir), "level setup");
+}
+
static void setLevelInfoToDefaults()
{
int i, x, y;
#define TOKEN_STR_FILE_IDENTIFIER "file_identifier"
#define TOKEN_STR_LAST_LEVEL_SERIES "last_level_series"
+#define TOKEN_STR_LAST_PLAYED_LEVEL "last_played_level"
+#define TOKEN_STR_HANDICAP_LEVEL "handicap_level"
#define TOKEN_STR_PLAYER_PREFIX "player_"
#define TOKEN_VALUE_POSITION 30
#define SETUP_TOKEN_SOUND_LOOPS 2
#define SETUP_TOKEN_SOUND_MUSIC 3
#define SETUP_TOKEN_SOUND_SIMPLE 4
+
+#if 0
#define SETUP_TOKEN_TOONS 5
#define SETUP_TOKEN_DOUBLE_BUFFERING 6
-#define SETUP_TOKEN_SCROLL_DELAY 7
-#define SETUP_TOKEN_SOFT_SCROLLING 8
-#define SETUP_TOKEN_FADING 9
-#define SETUP_TOKEN_AUTORECORD 10
-#define SETUP_TOKEN_QUICK_DOORS 11
-#define SETUP_TOKEN_TEAM_MODE 12
+#endif
+
+#define SETUP_TOKEN_SCROLL_DELAY 5
+#define SETUP_TOKEN_SOFT_SCROLLING 6
+#define SETUP_TOKEN_FADING 7
+#define SETUP_TOKEN_AUTORECORD 8
+#define SETUP_TOKEN_QUICK_DOORS 9
+#define SETUP_TOKEN_TEAM_MODE 10
+#define SETUP_TOKEN_HANDICAP 11
+#define SETUP_TOKEN_TIME_LIMIT 12
/* player setup */
#define SETUP_TOKEN_USE_JOYSTICK 13
/* level directory info */
#define LEVELINFO_TOKEN_NAME 29
#define LEVELINFO_TOKEN_NAME_SHORT 30
-#define LEVELINFO_TOKEN_AUTHOR 31
-#define LEVELINFO_TOKEN_IMPORTED_FROM 32
-#define LEVELINFO_TOKEN_LEVELS 33
-#define LEVELINFO_TOKEN_FIRST_LEVEL 34
-#define LEVELINFO_TOKEN_SORT_PRIORITY 35
-#define LEVELINFO_TOKEN_READONLY 36
+#define LEVELINFO_TOKEN_NAME_SORTING 31
+#define LEVELINFO_TOKEN_AUTHOR 32
+#define LEVELINFO_TOKEN_IMPORTED_FROM 33
+#define LEVELINFO_TOKEN_LEVELS 34
+#define LEVELINFO_TOKEN_FIRST_LEVEL 35
+#define LEVELINFO_TOKEN_SORT_PRIORITY 36
+#define LEVELINFO_TOKEN_READONLY 37
#define FIRST_GLOBAL_SETUP_TOKEN SETUP_TOKEN_PLAYER_NAME
-#define LAST_GLOBAL_SETUP_TOKEN SETUP_TOKEN_TEAM_MODE
+#define LAST_GLOBAL_SETUP_TOKEN SETUP_TOKEN_TIME_LIMIT
#define FIRST_PLAYER_SETUP_TOKEN SETUP_TOKEN_USE_JOYSTICK
#define LAST_PLAYER_SETUP_TOKEN SETUP_TOKEN_KEY_BOMB
{ TYPE_SWITCH, &si.sound_loops, "repeating_sound_loops" },
{ TYPE_SWITCH, &si.sound_music, "background_music" },
{ TYPE_SWITCH, &si.sound_simple, "simple_sound_effects" },
+
+#if 0
{ TYPE_SWITCH, &si.toons, "toons" },
{ TYPE_SWITCH, &si.double_buffering, "double_buffering" },
+#endif
+
{ TYPE_SWITCH, &si.scroll_delay, "scroll_delay" },
{ TYPE_SWITCH, &si.soft_scrolling, "soft_scrolling" },
{ TYPE_SWITCH, &si.fading, "screen_fading" },
{ TYPE_SWITCH, &si.autorecord, "automatic_tape_recording" },
{ TYPE_SWITCH, &si.quick_doors, "quick_doors" },
{ TYPE_SWITCH, &si.team_mode, "team_mode" },
+ { TYPE_SWITCH, &si.handicap, "handicap" },
+ { TYPE_SWITCH, &si.time_limit, "time_limit" },
/* player setup */
{ TYPE_BOOLEAN, &sii.use_joystick, ".use_joystick" },
/* level directory info */
{ TYPE_STRING, &ldi.name, "name" },
{ TYPE_STRING, &ldi.name_short, "name_short" },
+ { TYPE_STRING, &ldi.name_sorting, "name_sorting" },
{ TYPE_STRING, &ldi.author, "author" },
{ TYPE_STRING, &ldi.imported_from, "imported_from" },
{ TYPE_INTEGER, &ldi.levels, "levels" },
static void setLevelDirInfoToDefaults(struct LevelDirInfo *ldi)
{
+ ldi->filename = NULL;
ldi->name = getStringCopy(ANONYMOUS_NAME);
ldi->name_short = NULL;
+ ldi->name_sorting = NULL;
ldi->author = getStringCopy(ANONYMOUS_NAME);
ldi->imported_from = NULL;
ldi->levels = 0;
ldi->first_level = 0;
+ ldi->last_level = 0;
ldi->sort_priority = LEVELCLASS_UNDEFINED; /* default: least priority */
ldi->readonly = TRUE;
+ ldi->user_defined = FALSE;
+ ldi->color = 0;
+ ldi->class_desc = NULL;
+ ldi->handicap_level = 0;
}
static void setSetupInfoToDefaults(struct SetupInfo *si)
si->fading = FALSE;
si->autorecord = TRUE;
si->quick_doors = FALSE;
+ si->team_mode = FALSE;
+ si->handicap = TRUE;
+ si->time_limit = TRUE;
for (i=0; i<MAX_PLAYERS; i++)
{
return 0;
}
-int getLastPlayedLevelOfLevelSeries(char *level_series_name)
-{
- char *token_value;
- int level_series_nr = getLevelSeriesNrFromLevelSeriesName(level_series_name);
- int last_level_nr = leveldir[level_series_nr].first_level;
-
- if (!level_series_name)
- return 0;
-
- token_value = getTokenValue(level_setup_list, level_series_name);
-
- if (token_value)
- {
- last_level_nr = atoi(token_value);
-
- if (last_level_nr < leveldir[level_series_nr].first_level)
- last_level_nr = leveldir[level_series_nr].first_level;
- if (last_level_nr > leveldir[level_series_nr].last_level)
- last_level_nr = leveldir[level_series_nr].last_level;
- }
-
- return last_level_nr;
-}
-
static int compareLevelDirInfoEntries(const void *object1, const void *object2)
{
const struct LevelDirInfo *entry1 = object1;
if (entry1->sort_priority == entry2->sort_priority)
{
- char *name1 = getStringToLower(entry1->name_short);
- char *name2 = getStringToLower(entry2->name_short);
+ char *name1 = getStringToLower(entry1->name_sorting);
+ char *name2 = getStringToLower(entry2->name_sorting);
compare_result = strcmp(name1, name2);
if (setup_file_list)
{
+#if 0
+ DrawInitText(dir_entry->d_name, 150, FC_YELLOW);
+#endif
+
checkSetupFileListIdentifier(setup_file_list, LEVELINFO_COOKIE);
setLevelDirInfoToDefaults(&leveldir[current_entry]);
setSetupInfo(i, getTokenValue(setup_file_list, token_info[i].text));
leveldir[current_entry] = ldi;
+#if 1
+ DrawInitText(leveldir[current_entry].name, 150, FC_YELLOW);
+#endif
+
if (leveldir[current_entry].name_short == NULL)
leveldir[current_entry].name_short =
getStringCopy(leveldir[current_entry].name);
+ if (leveldir[current_entry].name_sorting == NULL)
+ leveldir[current_entry].name_sorting =
+ getStringCopy(leveldir[current_entry].name);
+
leveldir[current_entry].filename = getStringCopy(dir_entry->d_name);
leveldir[current_entry].last_level =
leveldir[current_entry].first_level +
leveldir[current_entry].color = LEVELCOLOR(&leveldir[current_entry]);
leveldir[current_entry].class_desc =
getLevelClassDescription(&leveldir[current_entry]);
+#if 0
+ leveldir[current_entry].handicap_level =
+ leveldir[current_entry].first_level; /* default value */
+#else
+ leveldir[current_entry].handicap_level =
+ (leveldir[current_entry].user_defined ?
+ leveldir[current_entry].last_level :
+ leveldir[current_entry].first_level);
+#endif
freeSetupFileList(setup_file_list);
current_entry++;
free(filename);
}
- if (current_entry == MAX_LEVDIR_ENTRIES)
- Error(ERR_WARN, "using %d level directories -- ignoring the rest",
- current_entry);
-
closedir(dir);
- if (current_entry == start_entry)
+ if (current_entry == MAX_LEVDIR_ENTRIES)
+ {
+ Error(ERR_WARN, "maximum of %d level directories reached", current_entry);
+ Error(ERR_WARN, "remaining level directories ignored in directory '%s'",
+ level_directory);
+ }
+ else if (current_entry == start_entry)
Error(ERR_WARN, "cannot find any valid level series in directory '%s'",
level_directory);
num_leveldirs = 0;
leveldir_nr = 0;
+ DrawInitText("Loading level series:", 120, FC_GREEN);
+
num_leveldirs = LoadLevelInfoFromLevelDir(options.level_directory,
num_leveldirs);
num_leveldirs = LoadLevelInfoFromLevelDir(getUserLevelDir(""),
getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER, LEVELINFO_COOKIE));
for (i=FIRST_LEVELINFO_TOKEN; i<=LAST_LEVELINFO_TOKEN; i++)
- if (i != LEVELINFO_TOKEN_NAME_SHORT && i != LEVELINFO_TOKEN_IMPORTED_FROM)
+ if (i != LEVELINFO_TOKEN_NAME_SHORT &&
+ i != LEVELINFO_TOKEN_NAME_SORTING &&
+ i != LEVELINFO_TOKEN_IMPORTED_FROM)
fprintf(file, "%s\n", getSetupLine("", i));
fclose(file);
chmod(filename, SETUP_PERMS);
}
-void LoadLevelSetup()
+void LoadLevelSetup_LastSeries()
{
char *filename;
+ struct SetupFileList *level_setup_list = NULL;
/* always start with reliable default values */
leveldir_nr = 0;
- level_nr = 0;
- filename = getPath2(getSetupDir(), LEVELSETUP_FILENAME);
+ /* ----------------------------------------------------------------------- */
+ /* ~/.rocksndiamonds/levelsetup.conf */
+ /* ----------------------------------------------------------------------- */
- if (level_setup_list)
- freeSetupFileList(level_setup_list);
-
- level_setup_list = loadSetupFileList(filename);
+ filename = getPath2(getSetupDir(), LEVELSETUP_FILENAME);
- if (level_setup_list)
+ if ((level_setup_list = loadSetupFileList(filename)))
{
char *last_level_series =
getTokenValue(level_setup_list, TOKEN_STR_LAST_LEVEL_SERIES);
leveldir_nr = getLevelSeriesNrFromLevelSeriesName(last_level_series);
- level_nr = getLastPlayedLevelOfLevelSeries(last_level_series);
checkSetupFileListIdentifier(level_setup_list, LEVELSETUP_COOKIE);
+
+ freeSetupFileList(level_setup_list);
}
else
- {
- level_setup_list = newSetupFileList(TOKEN_STR_FILE_IDENTIFIER,
- LEVELSETUP_COOKIE);
Error(ERR_WARN, "using default setup values");
- }
free(filename);
}
-void SaveLevelSetup()
+void SaveLevelSetup_LastSeries()
{
char *filename;
- struct SetupFileList *list_entry = level_setup_list;
+ char *level_subdir = leveldir[leveldir_nr].filename;
FILE *file;
- InitUserDataDirectory();
-
- setTokenValue(level_setup_list,
- TOKEN_STR_LAST_LEVEL_SERIES, leveldir[leveldir_nr].filename);
+ /* ----------------------------------------------------------------------- */
+ /* ~/.rocksndiamonds/levelsetup.conf */
+ /* ----------------------------------------------------------------------- */
- setTokenValue(level_setup_list,
- leveldir[leveldir_nr].filename, int2str(level_nr, 0));
+ InitUserDataDirectory();
filename = getPath2(getSetupDir(), LEVELSETUP_FILENAME);
fprintf(file, "%s\n\n", getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER,
LEVELSETUP_COOKIE));
- while (list_entry)
+ fprintf(file, "%s\n", getFormattedSetupEntry(TOKEN_STR_LAST_LEVEL_SERIES,
+ level_subdir));
+
+ fclose(file);
+ free(filename);
+
+ chmod(filename, SETUP_PERMS);
+}
+
+static void checkSeriesInfo(int leveldir_nr)
+{
+ static char *level_directory = NULL;
+ DIR *dir;
+ struct dirent *dir_entry;
+
+ /* check for more levels besides the 'levels' field of 'levelinfo.conf' */
+
+ level_directory = getPath2((leveldir[leveldir_nr].user_defined ?
+ getUserLevelDir("") :
+ options.level_directory),
+ leveldir[leveldir_nr].filename);
+
+ if ((dir = opendir(level_directory)) == NULL)
{
- if (strcmp(list_entry->token, TOKEN_STR_FILE_IDENTIFIER) != 0)
- fprintf(file, "%s\n",
- getFormattedSetupEntry(list_entry->token, list_entry->value));
+ Error(ERR_WARN, "cannot read level directory '%s'", level_directory);
+ return;
+ }
- /* just to make things nicer :) */
- if (strcmp(list_entry->token, TOKEN_STR_LAST_LEVEL_SERIES) == 0)
- fprintf(file, "\n");
+ while ((dir_entry = readdir(dir)) != NULL) /* last directory entry */
+ {
+ if (strlen(dir_entry->d_name) > 4 &&
+ dir_entry->d_name[3] == '.' &&
+ strcmp(&dir_entry->d_name[4], LEVELFILE_EXTENSION) == 0)
+ {
+ char levelnum_str[4];
+ int levelnum_value;
+
+ strncpy(levelnum_str, dir_entry->d_name, 3);
+ levelnum_str[3] = '\0';
+
+ levelnum_value = atoi(levelnum_str);
- list_entry = list_entry->next;
+ if (levelnum_value < leveldir[leveldir_nr].first_level)
+ {
+ Error(ERR_WARN, "additional level %d found", levelnum_value);
+ leveldir[leveldir_nr].first_level = levelnum_value;
+ }
+ else if (levelnum_value > leveldir[leveldir_nr].last_level)
+ {
+ Error(ERR_WARN, "additional level %d found", levelnum_value);
+ leveldir[leveldir_nr].last_level = levelnum_value;
+ }
+ }
}
+ closedir(dir);
+}
+
+void LoadLevelSetup_SeriesInfo(int leveldir_nr)
+{
+ char *filename;
+ struct SetupFileList *level_setup_list = NULL;
+ char *level_subdir = leveldir[leveldir_nr].filename;
+
+ /* always start with reliable default values */
+#if 0
+ level_nr = 0;
+ leveldir[leveldir_nr].handicap_level = 0;
+#else
+ level_nr = leveldir[leveldir_nr].first_level;
+#endif
+
+ checkSeriesInfo(leveldir_nr);
+
+ /* ----------------------------------------------------------------------- */
+ /* ~/.rocksndiamonds/levelsetup/<level series>/levelsetup.conf */
+ /* ----------------------------------------------------------------------- */
+
+ level_subdir = leveldir[leveldir_nr].filename;
+
+ filename = getPath2(getLevelSetupDir(level_subdir), LEVELSETUP_FILENAME);
+
+ if ((level_setup_list = loadSetupFileList(filename)))
+ {
+ char *token_value;
+
+ token_value = getTokenValue(level_setup_list, TOKEN_STR_LAST_PLAYED_LEVEL);
+
+ if (token_value)
+ {
+ level_nr = atoi(token_value);
+
+ if (level_nr < leveldir[leveldir_nr].first_level)
+ level_nr = leveldir[leveldir_nr].first_level;
+ if (level_nr > leveldir[leveldir_nr].last_level)
+ level_nr = leveldir[leveldir_nr].last_level;
+ }
+
+ token_value = getTokenValue(level_setup_list, TOKEN_STR_HANDICAP_LEVEL);
+
+ if (token_value)
+ {
+ int level_nr = atoi(token_value);
+
+ if (level_nr < leveldir[leveldir_nr].first_level)
+ level_nr = leveldir[leveldir_nr].first_level;
+ if (level_nr > leveldir[leveldir_nr].last_level + 1)
+ level_nr = leveldir[leveldir_nr].last_level;
+
+ if (leveldir[leveldir_nr].user_defined)
+ level_nr = leveldir[leveldir_nr].last_level;
+
+ leveldir[leveldir_nr].handicap_level = level_nr;
+ }
+
+ checkSetupFileListIdentifier(level_setup_list, LEVELSETUP_COOKIE);
+
+ freeSetupFileList(level_setup_list);
+ }
+ else
+ Error(ERR_WARN, "using default setup values");
+
+ free(filename);
+}
+
+void SaveLevelSetup_SeriesInfo(int leveldir_nr)
+{
+ char *filename;
+ char *level_subdir = leveldir[leveldir_nr].filename;
+ char *level_nr_str = int2str(level_nr, 0);
+ char *handicap_level_str = int2str(leveldir[leveldir_nr].handicap_level, 0);
+ FILE *file;
+
+ /* ----------------------------------------------------------------------- */
+ /* ~/.rocksndiamonds/levelsetup/<level series>/levelsetup.conf */
+ /* ----------------------------------------------------------------------- */
+
+ InitLevelSetupDirectory(level_subdir);
+
+ filename = getPath2(getLevelSetupDir(level_subdir), LEVELSETUP_FILENAME);
+
+ if (!(file = fopen(filename, "w")))
+ {
+ Error(ERR_WARN, "cannot write setup file '%s'", filename);
+ free(filename);
+ return;
+ }
+
+ fprintf(file, "%s\n\n", getFormattedSetupEntry(TOKEN_STR_FILE_IDENTIFIER,
+ LEVELSETUP_COOKIE));
+ fprintf(file, "%s\n", getFormattedSetupEntry(TOKEN_STR_LAST_PLAYED_LEVEL,
+ level_nr_str));
+ fprintf(file, "%s\n", getFormattedSetupEntry(TOKEN_STR_HANDICAP_LEVEL,
+ handicap_level_str));
+
fclose(file);
free(filename);
}
#ifdef MSDOS
-static boolean initErrorFile()
+void initErrorFile()
{
char *filename;
- FILE *error_file;
InitUserDataDirectory();
filename = getPath2(getUserDataDir(), ERROR_FILENAME);
- error_file = fopen(filename, "w");
+ unlink(filename);
free(filename);
-
- if (error_file == NULL)
- return FALSE;
-
- fclose(error_file);
-
- return TRUE;
}
FILE *openErrorFile()
{
- static boolean first_access = TRUE;
char *filename;
FILE *error_file;
- if (first_access)
- {
- if (!initErrorFile())
- return NULL;
-
- first_access = FALSE;
- }
-
filename = getPath2(getUserDataDir(), ERROR_FILENAME);
error_file = fopen(filename, "a");
free(filename);