&li.score[SC_TIME_BONUS], 1
},
+ {
+ -1, -1,
+ TYPE_BOOLEAN, CONF_VALUE_8_BIT(9),
+ &li.auto_exit_sokoban, FALSE
+ },
+
{
-1, -1,
-1, -1,
date.month = now->tm_mon + 1;
date.day = now->tm_mday;
+ date.src = DATE_SRC_CLOCK;
+
return date;
}
change->post_change_function = NULL;
}
-static void setLevelInfoToDefaults(struct LevelInfo *level)
+#if 1
+
+static void setLevelInfoToDefaults_Level(struct LevelInfo *level)
+{
+ int i, x, y;
+
+ li = *level; /* copy level data into temporary buffer */
+ setConfigToDefaultsFromConfigList(chunk_config_INFO);
+ *level = li; /* copy temporary buffer back to level data */
+
+ setLevelInfoToDefaults_EM();
+ setLevelInfoToDefaults_SP();
+
+ level->native_em_level = &native_em_level;
+ level->native_sp_level = &native_sp_level;
+
+ level->file_version = FILE_VERSION_ACTUAL;
+ level->game_version = GAME_VERSION_ACTUAL;
+
+ level->creation_date = getCurrentDate();
+
+ level->encoding_16bit_field = TRUE;
+ level->encoding_16bit_yamyam = TRUE;
+ level->encoding_16bit_amoeba = TRUE;
+
+ for (x = 0; x < MAX_LEV_FIELDX; x++)
+ for (y = 0; y < MAX_LEV_FIELDY; y++)
+ level->field[x][y] = EL_SAND;
+
+ for (i = 0; i < MAX_LEVEL_NAME_LEN; i++)
+ level->name[i] = '\0';
+ for (i = 0; i < MAX_LEVEL_AUTHOR_LEN; i++)
+ level->author[i] = '\0';
+
+ strcpy(level->name, NAMELESS_LEVEL_NAME);
+ strcpy(level->author, ANONYMOUS_NAME);
+
+ level->field[0][0] = EL_PLAYER_1;
+ level->field[STD_LEV_FIELDX - 1][STD_LEV_FIELDY - 1] = EL_EXIT_CLOSED;
+
+ BorderElement = EL_STEELWALL;
+
+ /* set all bug compatibility flags to "false" => do not emulate this bug */
+ level->use_action_after_change_bug = FALSE;
+
+ if (leveldir_current)
+ {
+ /* try to determine better author name than 'anonymous' */
+ if (!strEqual(leveldir_current->author, ANONYMOUS_NAME))
+ {
+ strncpy(level->author, leveldir_current->author, MAX_LEVEL_AUTHOR_LEN);
+ level->author[MAX_LEVEL_AUTHOR_LEN] = '\0';
+ }
+ else
+ {
+ switch (LEVELCLASS(leveldir_current))
+ {
+ case LEVELCLASS_TUTORIAL:
+ strcpy(level->author, PROGRAM_AUTHOR_STRING);
+ break;
+
+ case LEVELCLASS_CONTRIB:
+ strncpy(level->author, leveldir_current->name, MAX_LEVEL_AUTHOR_LEN);
+ level->author[MAX_LEVEL_AUTHOR_LEN] = '\0';
+ break;
+
+ case LEVELCLASS_PRIVATE:
+ strncpy(level->author, getRealName(), MAX_LEVEL_AUTHOR_LEN);
+ level->author[MAX_LEVEL_AUTHOR_LEN] = '\0';
+ break;
+
+ default:
+ /* keep default value */
+ break;
+ }
+ }
+ }
+}
+
+static void setLevelInfoToDefaults_Elements(struct LevelInfo *level)
+{
+ static boolean clipboard_elements_initialized = FALSE;
+ int i;
+
+ InitElementPropertiesStatic();
+
+ li = *level; /* copy level data into temporary buffer */
+ setConfigToDefaultsFromConfigList(chunk_config_ELEM);
+ *level = li; /* copy temporary buffer back to level data */
+
+ for (i = 0; i < MAX_NUM_ELEMENTS; i++)
+ {
+ int element = i;
+ struct ElementInfo *ei = &element_info[element];
+
+ /* never initialize clipboard elements after the very first time */
+ /* (to be able to use clipboard elements between several levels) */
+ if (IS_CLIPBOARD_ELEMENT(element) && clipboard_elements_initialized)
+ continue;
+
+ if (IS_ENVELOPE(element))
+ {
+ int envelope_nr = element - EL_ENVELOPE_1;
+
+ setConfigToDefaultsFromConfigList(chunk_config_NOTE);
+
+ level->envelope[envelope_nr] = xx_envelope;
+ }
+
+ if (IS_CUSTOM_ELEMENT(element) ||
+ IS_GROUP_ELEMENT(element) ||
+ IS_INTERNAL_ELEMENT(element))
+ {
+ xx_ei = *ei; /* copy element data into temporary buffer */
+
+ setConfigToDefaultsFromConfigList(chunk_config_CUSX_base);
+
+ *ei = xx_ei;
+ }
+
+ setElementChangePages(ei, 1);
+ setElementChangeInfoToDefaults(ei->change);
+
+ if (IS_CUSTOM_ELEMENT(element) ||
+ IS_GROUP_ELEMENT(element) ||
+ IS_INTERNAL_ELEMENT(element))
+ {
+ setElementDescriptionToDefault(ei);
+
+ ei->modified_settings = FALSE;
+ }
+
+ if (IS_CUSTOM_ELEMENT(element) ||
+ IS_INTERNAL_ELEMENT(element))
+ {
+ /* internal values used in level editor */
+
+ ei->access_type = 0;
+ ei->access_layer = 0;
+ ei->access_protected = 0;
+ ei->walk_to_action = 0;
+ ei->smash_targets = 0;
+ ei->deadliness = 0;
+
+ ei->can_explode_by_fire = FALSE;
+ ei->can_explode_smashed = FALSE;
+ ei->can_explode_impact = FALSE;
+
+ ei->current_change_page = 0;
+ }
+
+ if (IS_GROUP_ELEMENT(element) ||
+ IS_INTERNAL_ELEMENT(element))
+ {
+ struct ElementGroupInfo *group;
+
+ /* initialize memory for list of elements in group */
+ if (ei->group == NULL)
+ ei->group = checked_malloc(sizeof(struct ElementGroupInfo));
+
+ group = ei->group;
+
+ xx_group = *group; /* copy group data into temporary buffer */
+
+ setConfigToDefaultsFromConfigList(chunk_config_GRPX);
+
+ *group = xx_group;
+ }
+ }
+
+ clipboard_elements_initialized = TRUE;
+}
+
+static void setLevelInfoToDefaults(struct LevelInfo *level,
+ boolean level_info_only)
+{
+ setLevelInfoToDefaults_Level(level);
+
+ if (!level_info_only)
+ setLevelInfoToDefaults_Elements(level);
+
+ level->no_valid_file = FALSE;
+
+ level->changed = FALSE;
+}
+
+#else
+
+static void setLevelInfoToDefaults(struct LevelInfo *level,
+ boolean level_info_only)
{
static boolean clipboard_elements_initialized = FALSE;
int i, x, y;
+ if (level_info_only)
+ return;
+
InitElementPropertiesStatic();
li = *level; /* copy level data into temporary buffer */
/* set all bug compatibility flags to "false" => do not emulate this bug */
level->use_action_after_change_bug = FALSE;
- if (leveldir_current == NULL) /* only when dumping level */
- return;
-
- /* try to determine better author name than 'anonymous' */
- if (!strEqual(leveldir_current->author, ANONYMOUS_NAME))
- {
- strncpy(level->author, leveldir_current->author, MAX_LEVEL_AUTHOR_LEN);
- level->author[MAX_LEVEL_AUTHOR_LEN] = '\0';
- }
- else
+ if (leveldir_current)
{
- switch (LEVELCLASS(leveldir_current))
+ /* try to determine better author name than 'anonymous' */
+ if (!strEqual(leveldir_current->author, ANONYMOUS_NAME))
{
- case LEVELCLASS_TUTORIAL:
- strcpy(level->author, PROGRAM_AUTHOR_STRING);
- break;
-
- case LEVELCLASS_CONTRIB:
- strncpy(level->author, leveldir_current->name, MAX_LEVEL_AUTHOR_LEN);
- level->author[MAX_LEVEL_AUTHOR_LEN] = '\0';
- break;
-
- case LEVELCLASS_PRIVATE:
- strncpy(level->author, getRealName(), MAX_LEVEL_AUTHOR_LEN);
- level->author[MAX_LEVEL_AUTHOR_LEN] = '\0';
- break;
-
- default:
- /* keep default value */
- break;
+ strncpy(level->author, leveldir_current->author, MAX_LEVEL_AUTHOR_LEN);
+ level->author[MAX_LEVEL_AUTHOR_LEN] = '\0';
+ }
+ else
+ {
+ switch (LEVELCLASS(leveldir_current))
+ {
+ case LEVELCLASS_TUTORIAL:
+ strcpy(level->author, PROGRAM_AUTHOR_STRING);
+ break;
+
+ case LEVELCLASS_CONTRIB:
+ strncpy(level->author, leveldir_current->name, MAX_LEVEL_AUTHOR_LEN);
+ level->author[MAX_LEVEL_AUTHOR_LEN] = '\0';
+ break;
+
+ case LEVELCLASS_PRIVATE:
+ strncpy(level->author, getRealName(), MAX_LEVEL_AUTHOR_LEN);
+ level->author[MAX_LEVEL_AUTHOR_LEN] = '\0';
+ break;
+
+ default:
+ /* keep default value */
+ break;
+ }
}
}
}
+#endif
+
static void setFileInfoToDefaults(struct LevelFileInfo *level_file_info)
{
level_file_info->nr = 0;
return (getFileTypeFromBasename(basename) != LEVEL_FILE_TYPE_UNKNOWN);
}
-static char *getSingleLevelBasename(int nr)
+static char *getSingleLevelBasenameExt(int nr, char *extension)
{
static char basename[MAX_FILENAME_LEN];
if (nr < 0)
- sprintf(basename, "template.%s", LEVELFILE_EXTENSION);
+ sprintf(basename, "template.%s", extension);
else
- sprintf(basename, "%03d.%s", nr, LEVELFILE_EXTENSION);
+ sprintf(basename, "%03d.%s", nr, extension);
return basename;
}
+static char *getSingleLevelBasename(int nr)
+{
+ return getSingleLevelBasenameExt(nr, LEVELFILE_EXTENSION);
+}
+
static char *getPackedLevelBasename(int type)
{
static char basename[MAX_FILENAME_LEN];
level->creation_date.month = getFile8Bit(file);
level->creation_date.day = getFile8Bit(file);
+ level->creation_date.src = DATE_SRC_LEVELFILE;
+
return chunk_size;
}
{
int i, x, y;
int element;
- int num_contents, content_xsize, content_ysize;
+ int num_contents;
+#if 0
+ int content_xsize, content_ysize;
+#endif
int content_array[MAX_ELEMENT_CONTENTS][3][3];
element = getMappedElement(getFile16BitBE(file));
num_contents = getFile8Bit(file);
+#if 1
+ getFile8Bit(file); /* content x size (unused) */
+ getFile8Bit(file); /* content y size (unused) */
+#else
content_xsize = getFile8Bit(file);
content_ysize = getFile8Bit(file);
+#endif
ReadUnusedBytesFromFile(file, LEVEL_CHUNK_CNT2_UNUSED);
}
static void LoadLevelFromFileInfo_RND(struct LevelInfo *level,
- struct LevelFileInfo *level_file_info)
+ struct LevelFileInfo *level_file_info,
+ boolean level_info_only)
{
char *filename = level_file_info->filename;
char cookie[MAX_LINE_LEN];
level->no_valid_file = TRUE;
#if 1
- Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
+ if (!level_info_only)
+ Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
#else
if (level != &level_template)
Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
else /* check for pre-2.0 file format with cookie string */
{
strcpy(cookie, chunk_name);
- fgets(&cookie[4], MAX_LINE_LEN - 4, file);
+ if (fgets(&cookie[4], MAX_LINE_LEN - 4, file) == NULL)
+ cookie[4] = '\0';
if (strlen(cookie) > 0 && cookie[strlen(cookie) - 1] == '\n')
cookie[strlen(cookie) - 1] = '\0';
}
static void LoadLevelFromFileInfo_SP(struct LevelInfo *level,
- struct LevelFileInfo *level_file_info)
+ struct LevelFileInfo *level_file_info,
+ boolean level_info_only)
{
char *filename = level_file_info->filename;
FILE *file;
{
level->no_valid_file = TRUE;
- Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
+ if (!level_info_only)
+ Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
return;
}
level_sp->height = level->fieldy;
for (x = 0; x < level->fieldx; x++)
- {
for (y = 0; y < level->fieldy; y++)
- {
- int element_old = level->field[x][y];
- int element_new;
-
- if (element_old >= EL_SP_START &&
- element_old <= EL_SP_END)
- element_new = element_old - EL_SP_START;
- else if (element_old == EL_EMPTY_SPACE)
- element_new = 0x00;
- else if (element_old == EL_INVISIBLE_WALL)
- element_new = 0x28;
- else
- element_new = 0x20; /* map unknown elements to yellow "hardware" */
-
- level_sp->playfield[x][y] = element_new;
- }
- }
+ level_sp->playfield[x][y] = map_element_RND_to_SP(level->field[x][y]);
header->InitialGravity = (level->initial_player_gravity[0] ? 1 : 0);
for (y = 0; y < level->fieldy; y++)
{
int element_old = level_sp->playfield[x][y];
- int element_new;
+ int element_new = getMappedElement(map_element_SP_to_RND(element_old));
- if (element_old <= 0x27)
- element_new = getMappedElement(EL_SP_START + element_old);
- else if (element_old == 0x28)
- element_new = EL_INVISIBLE_WALL;
- else
- {
+ if (element_new == EL_UNKNOWN)
Error(ERR_WARN, "invalid element %d at position %d, %d",
element_old, x, y);
- element_new = EL_UNKNOWN;
- }
-
level->field[x][y] = element_new;
}
}
level->yamyam_content[i].e[x][y] = EL_EMPTY;
}
+static void CopyNativeTape_RND_to_SP(struct LevelInfo *level)
+{
+ struct LevelInfo_SP *level_sp = level->native_sp_level;
+ struct DemoInfo_SP *demo = &level_sp->demo;
+ int i, j;
+
+ /* always start with reliable default values */
+ demo->is_available = FALSE;
+ demo->length = 0;
+
+ if (TAPE_IS_EMPTY(tape))
+ return;
+
+ demo->level_nr = tape.level_nr; /* (currently not used) */
+
+ level_sp->header.DemoRandomSeed = tape.random_seed;
+
+ demo->length = 0;
+ for (i = 0; i < tape.length; i++)
+ {
+ int demo_action = map_key_RND_to_SP(tape.pos[i].action[0]);
+ int demo_repeat = tape.pos[i].delay;
+
+ for (j = 0; j < demo_repeat / 16; j++)
+ demo->data[demo->length++] = 0xf0 | demo_action;
+
+ if (demo_repeat % 16)
+ demo->data[demo->length++] = ((demo_repeat % 16 - 1) << 4) | demo_action;
+ }
+
+ demo->data[demo->length++] = 0xff;
+
+ demo->is_available = TRUE;
+}
+
static void setTapeInfoToDefaults();
static void CopyNativeTape_SP_to_RND(struct LevelInfo *level)
{
struct LevelInfo_SP *level_sp = level->native_sp_level;
struct DemoInfo_SP *demo = &level_sp->demo;
+ char *filename = level->file_info.filename;
int i;
/* always start with reliable default values */
setTapeInfoToDefaults();
+ if (!demo->is_available)
+ return;
+
tape.level_nr = demo->level_nr; /* (currently not used) */
tape.length = demo->length - 1; /* without "end of demo" byte */
tape.random_seed = level_sp->header.DemoRandomSeed;
- // tape.date = <SET FROM FILE DATE OF *.SP FILE>
+ TapeSetDateFromEpochSeconds(getFileTimestampEpochSeconds(filename));
for (i = 0; i < demo->length - 1; i++)
{
}
static void LoadLevelFromFileInfo_DC(struct LevelInfo *level,
- struct LevelFileInfo *level_file_info)
+ struct LevelFileInfo *level_file_info,
+ boolean level_info_only)
{
char *filename = level_file_info->filename;
FILE *file;
{
level->no_valid_file = TRUE;
- Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
+ if (!level_info_only)
+ Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
return;
}
if (level_file_info->packed)
{
/* read "magic bytes" from start of file */
- fgets(magic_bytes, num_magic_bytes + 1, file);
+ if (fgets(magic_bytes, num_magic_bytes + 1, file) == NULL)
+ magic_bytes[0] = '\0';
/* check "magic bytes" for correct file format */
if (!strPrefix(magic_bytes, "DC2"))
{
level->no_valid_file = TRUE;
- Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
+ if (!level_info_only)
+ Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
return;
}
}
static void LoadLevelFromFileInfo_SB(struct LevelInfo *level,
- struct LevelFileInfo *level_file_info)
+ struct LevelFileInfo *level_file_info,
+ boolean level_info_only)
{
char *filename = level_file_info->filename;
char line[MAX_LINE_LEN], line_raw[MAX_LINE_LEN], previous_line[MAX_LINE_LEN];
boolean load_xsb_to_ces = check_special_flags("load_xsb_to_ces");
int file_level_nr = 0;
int line_nr = 0;
- int x, y;
+ int x = 0, y = 0; /* initialized to make compilers happy */
#if 0
printf("::: looking for level number %d [%d]\n",
{
level->no_valid_file = TRUE;
- Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
+ if (!level_info_only)
+ Error(ERR_WARN, "cannot read level '%s' -- using empty level", filename);
return;
}
/* ------------------------------------------------------------------------- */
static void LoadLevelFromFileInfo_EM(struct LevelInfo *level,
- struct LevelFileInfo *level_file_info)
+ struct LevelFileInfo *level_file_info,
+ boolean level_info_only)
{
- if (!LoadNativeLevel_EM(level_file_info->filename))
+ if (!LoadNativeLevel_EM(level_file_info->filename, level_info_only))
level->no_valid_file = TRUE;
}
static void LoadLevelFromFileInfo_SP(struct LevelInfo *level,
- struct LevelFileInfo *level_file_info)
+ struct LevelFileInfo *level_file_info,
+ boolean level_info_only)
{
int pos = 0;
if (level_file_info->packed)
pos = level_file_info->nr - leveldir_current->first_level;
- if (!LoadNativeLevel_SP(level_file_info->filename, pos))
+ if (!LoadNativeLevel_SP(level_file_info->filename, pos, level_info_only))
level->no_valid_file = TRUE;
}
CopyNativeLevel_SP_to_RND(level);
}
+void SaveNativeLevel(struct LevelInfo *level)
+{
+ if (level->game_engine_type == GAME_ENGINE_TYPE_SP)
+ {
+ char *basename = getSingleLevelBasenameExt(level->file_info.nr, "sp");
+ char *filename = getLevelFilenameFromBasename(basename);
+
+ CopyNativeLevel_RND_to_SP(level);
+ CopyNativeTape_RND_to_SP(level);
+
+ SaveNativeLevel_SP(filename);
+ }
+}
+
/* ------------------------------------------------------------------------- */
/* functions for loading generic level */
/* ------------------------------------------------------------------------- */
-void LoadLevelFromFileInfo(struct LevelInfo *level,
- struct LevelFileInfo *level_file_info)
+static void LoadLevelFromFileInfo(struct LevelInfo *level,
+ struct LevelFileInfo *level_file_info,
+ boolean level_info_only)
{
/* always start with reliable default values */
- setLevelInfoToDefaults(level);
+ setLevelInfoToDefaults(level, level_info_only);
switch (level_file_info->type)
{
case LEVEL_FILE_TYPE_RND:
- LoadLevelFromFileInfo_RND(level, level_file_info);
+ LoadLevelFromFileInfo_RND(level, level_file_info, level_info_only);
break;
case LEVEL_FILE_TYPE_EM:
- LoadLevelFromFileInfo_EM(level, level_file_info);
+ LoadLevelFromFileInfo_EM(level, level_file_info, level_info_only);
level->game_engine_type = GAME_ENGINE_TYPE_EM;
break;
case LEVEL_FILE_TYPE_SP:
- LoadLevelFromFileInfo_SP(level, level_file_info);
+ LoadLevelFromFileInfo_SP(level, level_file_info, level_info_only);
level->game_engine_type = GAME_ENGINE_TYPE_SP;
break;
case LEVEL_FILE_TYPE_DC:
- LoadLevelFromFileInfo_DC(level, level_file_info);
+ LoadLevelFromFileInfo_DC(level, level_file_info, level_info_only);
break;
case LEVEL_FILE_TYPE_SB:
- LoadLevelFromFileInfo_SB(level, level_file_info);
+ LoadLevelFromFileInfo_SB(level, level_file_info, level_info_only);
break;
default:
- LoadLevelFromFileInfo_RND(level, level_file_info);
+ LoadLevelFromFileInfo_RND(level, level_file_info, level_info_only);
break;
}
/* if level file is invalid, restore level structure to default values */
if (level->no_valid_file)
- setLevelInfoToDefaults(level);
+ {
+ setLevelInfoToDefaults(level, level_info_only);
+
+ level->no_valid_file = TRUE; /* but keep "no valid file" flag */
+ }
if (level->game_engine_type == GAME_ENGINE_TYPE_UNKNOWN)
level->game_engine_type = GAME_ENGINE_TYPE_RND;
level_file_info.type = LEVEL_FILE_TYPE_RND; /* no others supported yet */
level_file_info.filename = filename;
- LoadLevelFromFileInfo(level, &level_file_info);
+ LoadLevelFromFileInfo(level, &level_file_info, FALSE);
}
static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename)
setLevelFileInfo(&level_template.file_info, nr);
filename = level_template.file_info.filename;
- LoadLevelFromFileInfo(&level_template, &level_template.file_info);
+ LoadLevelFromFileInfo(&level_template, &level_template.file_info, FALSE);
LoadLevel_InitVersion(&level_template, filename);
LoadLevel_InitElements(&level_template, filename);
setLevelFileInfo(&level.file_info, nr);
filename = level.file_info.filename;
- LoadLevelFromFileInfo(&level, &level.file_info);
+ LoadLevelFromFileInfo(&level, &level.file_info, FALSE);
if (level.use_custom_template)
LoadLevelTemplate(-1);
LoadLevel_InitNativeEngines(&level, filename);
}
+void LoadLevelInfoOnly(int nr)
+{
+#if 0
+ char *filename;
+#endif
+
+ setLevelFileInfo(&level.file_info, nr);
+#if 0
+ filename = level.file_info.filename;
+#endif
+
+ LoadLevelFromFileInfo(&level, &level.file_info, TRUE);
+}
+
static int SaveLevel_VERS(FILE *file, struct LevelInfo *level)
{
int chunk_size = 0;
return chunk_size;
}
+void LoadTape_SokobanSolution(char *filename)
+{
+ FILE *file;
+ int move_delay = TILESIZE / level.initial_player_stepsize[0];
+
+ if (!(file = fopen(filename, MODE_READ)))
+ {
+ tape.no_valid_file = TRUE;
+
+ return;
+ }
+
+ while (!feof(file))
+ {
+ unsigned char c = fgetc(file);
+
+ if (feof(file))
+ break;
+
+ switch (c)
+ {
+ case 'u':
+ case 'U':
+ tape.pos[tape.length].action[0] = MV_UP;
+ tape.pos[tape.length].delay = move_delay + (c < 'a' ? 2 : 0);
+ tape.length++;
+ break;
+
+ case 'd':
+ case 'D':
+ tape.pos[tape.length].action[0] = MV_DOWN;
+ tape.pos[tape.length].delay = move_delay + (c < 'a' ? 2 : 0);
+ tape.length++;
+ break;
+
+ case 'l':
+ case 'L':
+ tape.pos[tape.length].action[0] = MV_LEFT;
+ tape.pos[tape.length].delay = move_delay + (c < 'a' ? 2 : 0);
+ tape.length++;
+ break;
+
+ case 'r':
+ case 'R':
+ tape.pos[tape.length].action[0] = MV_RIGHT;
+ tape.pos[tape.length].delay = move_delay + (c < 'a' ? 2 : 0);
+ tape.length++;
+ break;
+
+ case '\n':
+ case '\r':
+ case '\t':
+ case ' ':
+ /* ignore white-space characters */
+ break;
+
+ default:
+ tape.no_valid_file = TRUE;
+
+ Error(ERR_WARN, "unsupported Sokoban solution file '%s' ['%d']", filename, c);
+
+ break;
+ }
+ }
+
+ fclose(file);
+
+ if (tape.no_valid_file)
+ return;
+
+ tape.length_seconds = GetTapeLength();
+}
+
void LoadTapeFromFilename(char *filename)
{
char cookie[MAX_LINE_LEN];
/* always start with reliable default values */
setTapeInfoToDefaults();
+ if (strSuffix(filename, ".sln"))
+ {
+ LoadTape_SokobanSolution(filename);
+
+ return;
+ }
+
if (!(file = fopen(filename, MODE_READ)))
{
tape.no_valid_file = TRUE;
else /* check for pre-2.0 file format with cookie string */
{
strcpy(cookie, chunk_name);
- fgets(&cookie[4], MAX_LINE_LEN - 4, file);
+ if (fgets(&cookie[4], MAX_LINE_LEN - 4, file) == NULL)
+ cookie[4] = '\0';
if (strlen(cookie) > 0 && cookie[strlen(cookie) - 1] == '\n')
cookie[strlen(cookie) - 1] = '\0';
Error(ERR_WARN, "unsupported version of tape file '%s'", filename);
fclose(file);
+
return;
}
return;
/* check file identifier */
- fgets(cookie, MAX_LINE_LEN, file);
+ if (fgets(cookie, MAX_LINE_LEN, file) == NULL)
+ cookie[0] = '\0';
if (strlen(cookie) > 0 && cookie[strlen(cookie) - 1] == '\n')
cookie[strlen(cookie) - 1] = '\0';
for (i = 0; i < MAX_SCORE_ENTRIES; i++)
{
- fscanf(file, "%d", &highscore[i].Score);
- fgets(line, MAX_LINE_LEN, file);
+ if (fscanf(file, "%d", &highscore[i].Score) == EOF)
+ Error(ERR_WARN, "fscanf() failed; %s", strerror(errno));
+ if (fgets(line, MAX_LINE_LEN, file) == NULL)
+ line[0] = '\0';
- if (line[strlen(line) - 1] == '\n')
+ if (strlen(line) > 0 && line[strlen(line) - 1] == '\n')
line[strlen(line) - 1] = '\0';
for (line_ptr = line; *line_ptr; line_ptr++)
#define SETUP_TOKEN_PREFER_AGA_GRAPHICS 23
#define SETUP_TOKEN_GAME_FRAME_DELAY 24
#define SETUP_TOKEN_SP_SHOW_BORDER_ELEMENTS 25
-#define SETUP_TOKEN_GRAPHICS_SET 26
-#define SETUP_TOKEN_SOUNDS_SET 27
-#define SETUP_TOKEN_MUSIC_SET 28
-#define SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS 29
-#define SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS 30
-#define SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC 31
-
-#define NUM_GLOBAL_SETUP_TOKENS 32
+#define SETUP_TOKEN_SMALL_GAME_GRAPHICS 26
+#define SETUP_TOKEN_GRAPHICS_SET 27
+#define SETUP_TOKEN_SOUNDS_SET 28
+#define SETUP_TOKEN_MUSIC_SET 29
+#define SETUP_TOKEN_OVERRIDE_LEVEL_GRAPHICS 30
+#define SETUP_TOKEN_OVERRIDE_LEVEL_SOUNDS 31
+#define SETUP_TOKEN_OVERRIDE_LEVEL_MUSIC 32
+#define SETUP_TOKEN_VOLUME_SIMPLE 33
+#define SETUP_TOKEN_VOLUME_LOOPS 34
+#define SETUP_TOKEN_VOLUME_MUSIC 35
+
+#define NUM_GLOBAL_SETUP_TOKENS 36
/* editor setup */
#define SETUP_TOKEN_EDITOR_EL_BOULDERDASH 0
#define SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_3 5
#define SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_4 6
#define SETUP_TOKEN_SHORTCUT_FOCUS_PLAYER_ALL 7
-
-#define NUM_SHORTCUT_SETUP_TOKENS 8
+#define SETUP_TOKEN_SHORTCUT_TAPE_EJECT 8
+#define SETUP_TOKEN_SHORTCUT_TAPE_EXTRA 9
+#define SETUP_TOKEN_SHORTCUT_TAPE_STOP 10
+#define SETUP_TOKEN_SHORTCUT_TAPE_PAUSE 11
+#define SETUP_TOKEN_SHORTCUT_TAPE_RECORD 12
+#define SETUP_TOKEN_SHORTCUT_TAPE_PLAY 13
+#define SETUP_TOKEN_SHORTCUT_SOUND_SIMPLE 14
+#define SETUP_TOKEN_SHORTCUT_SOUND_LOOPS 15
+#define SETUP_TOKEN_SHORTCUT_SOUND_MUSIC 16
+#define SETUP_TOKEN_SHORTCUT_SNAP_LEFT 17
+#define SETUP_TOKEN_SHORTCUT_SNAP_RIGHT 18
+#define SETUP_TOKEN_SHORTCUT_SNAP_UP 19
+#define SETUP_TOKEN_SHORTCUT_SNAP_DOWN 20
+
+#define NUM_SHORTCUT_SETUP_TOKENS 21
/* player setup */
#define SETUP_TOKEN_PLAYER_USE_JOYSTICK 0
{ TYPE_SWITCH, &si.prefer_aga_graphics, "prefer_aga_graphics" },
{ TYPE_INTEGER,&si.game_frame_delay, "game_frame_delay" },
{ TYPE_SWITCH, &si.sp_show_border_elements, "sp_show_border_elements" },
+ { TYPE_SWITCH, &si.small_game_graphics, "small_game_graphics" },
{ TYPE_STRING, &si.graphics_set, "graphics_set" },
{ TYPE_STRING, &si.sounds_set, "sounds_set" },
{ TYPE_STRING, &si.music_set, "music_set" },
{ TYPE_SWITCH3,&si.override_level_graphics, "override_level_graphics" },
{ TYPE_SWITCH3,&si.override_level_sounds, "override_level_sounds" },
{ TYPE_SWITCH3,&si.override_level_music, "override_level_music" },
+ { TYPE_INTEGER,&si.volume_simple, "volume_simple" },
+ { TYPE_INTEGER,&si.volume_loops, "volume_loops" },
+ { TYPE_INTEGER,&si.volume_music, "volume_music" },
};
static boolean not_used = FALSE;
{ TYPE_KEY_X11, &ssi.focus_player[2], "shortcut.focus_player_3" },
{ TYPE_KEY_X11, &ssi.focus_player[3], "shortcut.focus_player_4" },
{ TYPE_KEY_X11, &ssi.focus_player_all,"shortcut.focus_player_all" },
+ { TYPE_KEY_X11, &ssi.tape_eject, "shortcut.tape_eject" },
+ { TYPE_KEY_X11, &ssi.tape_extra, "shortcut.tape_extra" },
+ { TYPE_KEY_X11, &ssi.tape_stop, "shortcut.tape_stop" },
+ { TYPE_KEY_X11, &ssi.tape_pause, "shortcut.tape_pause" },
+ { TYPE_KEY_X11, &ssi.tape_record, "shortcut.tape_record" },
+ { TYPE_KEY_X11, &ssi.tape_play, "shortcut.tape_play" },
+ { TYPE_KEY_X11, &ssi.sound_simple, "shortcut.sound_simple" },
+ { TYPE_KEY_X11, &ssi.sound_loops, "shortcut.sound_loops" },
+ { TYPE_KEY_X11, &ssi.sound_music, "shortcut.sound_music" },
+ { TYPE_KEY_X11, &ssi.snap_left, "shortcut.snap_left" },
+ { TYPE_KEY_X11, &ssi.snap_right, "shortcut.snap_right" },
+ { TYPE_KEY_X11, &ssi.snap_up, "shortcut.snap_up" },
+ { TYPE_KEY_X11, &ssi.snap_down, "shortcut.snap_down" },
};
static struct TokenInfo player_setup_tokens[] =
si->prefer_aga_graphics = TRUE;
si->game_frame_delay = GAME_FRAME_DELAY;
si->sp_show_border_elements = FALSE;
+ si->small_game_graphics = FALSE;
si->graphics_set = getStringCopy(GFX_DEFAULT_SUBDIR);
si->sounds_set = getStringCopy(SND_DEFAULT_SUBDIR);
si->override_level_sounds = FALSE;
si->override_level_music = FALSE;
+ si->volume_simple = 100; /* percent */
+ si->volume_loops = 100; /* percent */
+ si->volume_music = 100; /* percent */
+
si->editor.el_boulderdash = TRUE;
si->editor.el_emerald_mine = TRUE;
si->editor.el_emerald_mine_club = TRUE;
si->shortcut.focus_player[3] = DEFAULT_KEY_FOCUS_PLAYER_4;
si->shortcut.focus_player_all = DEFAULT_KEY_FOCUS_PLAYER_ALL;
+ si->shortcut.tape_eject = DEFAULT_KEY_TAPE_EJECT;
+ si->shortcut.tape_extra = DEFAULT_KEY_TAPE_EXTRA;
+ si->shortcut.tape_stop = DEFAULT_KEY_TAPE_STOP;
+ si->shortcut.tape_pause = DEFAULT_KEY_TAPE_PAUSE;
+ si->shortcut.tape_record = DEFAULT_KEY_TAPE_RECORD;
+ si->shortcut.tape_play = DEFAULT_KEY_TAPE_PLAY;
+
+ si->shortcut.sound_simple = DEFAULT_KEY_SOUND_SIMPLE;
+ si->shortcut.sound_loops = DEFAULT_KEY_SOUND_LOOPS;
+ si->shortcut.sound_music = DEFAULT_KEY_SOUND_MUSIC;
+
+ si->shortcut.snap_left = DEFAULT_KEY_SNAP_LEFT;
+ si->shortcut.snap_right = DEFAULT_KEY_SNAP_RIGHT;
+ si->shortcut.snap_up = DEFAULT_KEY_SNAP_UP;
+ si->shortcut.snap_down = DEFAULT_KEY_SNAP_DOWN;
+
for (i = 0; i < MAX_PLAYERS; i++)
{
si->input[i].use_joystick = FALSE;
si->options.verbose = FALSE;
#if defined(CREATE_SPECIAL_EDITION_RND_JUE)
+ si->toons = FALSE;
si->handicap = FALSE;
si->fullscreen = TRUE;
si->override_level_graphics = AUTO;
{
/* just to make things nicer :) */
if (i == SETUP_TOKEN_PLAYER_NAME + 1 ||
- i == SETUP_TOKEN_GRAPHICS_SET)
+ i == SETUP_TOKEN_GRAPHICS_SET ||
+ i == SETUP_TOKEN_VOLUME_SIMPLE)
fprintf(file, "\n");
fprintf(file, "%s\n", getSetupLine(global_setup_tokens, "", i));
menu.enter_screen[i] = menu.enter_screen[GFX_SPECIAL_ARG_DEFAULT];
menu.leave_screen[i] = menu.leave_screen[GFX_SPECIAL_ARG_DEFAULT];
}
+
+ /* special case: initialize "ARG_DEFAULT" values in static default config */
+ /* (eg, init "viewport.door_1.MAIN.xyz" from "viewport.door_1.xyz") */
+ for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
+ {
+ viewport.playfield[i] = viewport.playfield[GFX_SPECIAL_ARG_DEFAULT];
+ viewport.door_1[i] = viewport.door_1[GFX_SPECIAL_ARG_DEFAULT];
+ if (i != GFX_SPECIAL_ARG_EDITOR) /* editor value already initialized */
+ viewport.door_2[i] = viewport.door_2[GFX_SPECIAL_ARG_DEFAULT];
+ }
}
static void InitMenuDesignSettings_SpecialPostProcessing()
value_6);
}
+ /* special case: initialize with default values that may be overwritten */
+ /* (eg, init "viewport.door_1.MAIN.xyz" from "viewport.door_1.xyz") */
+ for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
+ {
+ char *token_1 = "viewport.playfield.x";
+ char *token_2 = "viewport.playfield.y";
+ char *token_3 = "viewport.playfield.width";
+ char *token_4 = "viewport.playfield.height";
+ char *token_5 = "viewport.playfield.border_size";
+ char *token_6 = "viewport.door_1.x";
+ char *token_7 = "viewport.door_1.y";
+ char *token_8 = "viewport.door_2.x";
+ char *token_9 = "viewport.door_2.y";
+ char *value_1 = getHashEntry(setup_file_hash, token_1);
+ char *value_2 = getHashEntry(setup_file_hash, token_2);
+ char *value_3 = getHashEntry(setup_file_hash, token_3);
+ char *value_4 = getHashEntry(setup_file_hash, token_4);
+ char *value_5 = getHashEntry(setup_file_hash, token_5);
+ char *value_6 = getHashEntry(setup_file_hash, token_6);
+ char *value_7 = getHashEntry(setup_file_hash, token_7);
+ char *value_8 = getHashEntry(setup_file_hash, token_8);
+ char *value_9 = getHashEntry(setup_file_hash, token_9);
+
+ if (value_1 != NULL)
+ viewport.playfield[i].x = get_token_parameter_value(token_1, value_1);
+ if (value_2 != NULL)
+ viewport.playfield[i].y = get_token_parameter_value(token_2, value_2);
+ if (value_3 != NULL)
+ viewport.playfield[i].width = get_token_parameter_value(token_3, value_3);
+ if (value_4 != NULL)
+ viewport.playfield[i].height = get_token_parameter_value(token_4,value_4);
+ if (value_5 != NULL)
+ viewport.playfield[i].border_size = get_token_parameter_value(token_5,
+ value_5);
+ if (value_6 != NULL)
+ viewport.door_1[i].x = get_token_parameter_value(token_6, value_6);
+ if (value_7 != NULL)
+ viewport.door_1[i].y = get_token_parameter_value(token_7, value_7);
+ if (value_8 != NULL)
+ viewport.door_2[i].x = get_token_parameter_value(token_8, value_8);
+ if (value_9 != NULL)
+ viewport.door_2[i].y = get_token_parameter_value(token_9, value_9);
+ }
+
/* special case: initialize with default values that may be overwritten */
/* (e.g., init "titlemessage_1.fade_mode" from "[titlemessage].fade_mode") */
for (i = 0; titlemessage_arrays[i].array != NULL; i++)
if (!music_info_listed(music_file_info, music->filename))
{
*new = get_music_file_info(music->filename, i);
+#if 0
+ if (*new != NULL)
+ printf(":1: adding '%s' ['%s'] ...\n", (*new)->title, music->filename);
+#endif
if (*new != NULL)
new = &(*new)->next;
}
if (!music_info_listed(music_file_info, basename))
{
*new = get_music_file_info(basename, MAP_NOCONF_MUSIC(num_music_noconf));
+#if 0
+ if (*new != NULL)
+ printf(":2: adding '%s' ['%s'] ...\n", (*new)->title, basename);
+#endif
if (*new != NULL)
new = &(*new)->next;
}
filename1 = getPath2(global.create_images_dir, basename1);
filename2 = getPath2(global.create_images_dir, basename2);
- getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
- BlitBitmap(src_bitmap, bitmap1, src_x, src_y, TILEX, TILEY, 0, 0);
+ getFixedGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
+ BlitBitmap(src_bitmap, bitmap1, src_x, src_y, TILEX, TILEY,
+ 0, 0);
if (SDL_SaveBMP(bitmap1->surface, filename1) != 0)
Error(ERR_EXIT, "cannot save level sketch image file '%s'", filename1);
TILEY * (NUM_CUSTOM_ELEMENTS + NUM_GROUP_ELEMENTS) / 16,
DEFAULT_DEPTH);
- getGraphicSource(dummy_graphic, 0, &src_bitmap, &src_x, &src_y);
+ getFixedGraphicSource(dummy_graphic, 0, &src_bitmap, &src_x, &src_y);
for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
{
BlitBitmap(src_bitmap, bitmap, 0, 0, TILEX, TILEY,
TILEX * x, TILEY * y + yoffset_ce);
- BlitBitmap(src_bitmap, bitmap, 0, TILEY, TILEX, TILEY,
- TILEX * x + TILEX * 16, TILEY * y + yoffset_ce);
+ BlitBitmap(src_bitmap, bitmap, 0, TILEY,
+ TILEX, TILEY,
+ TILEX * x + TILEX * 16,
+ TILEY * y + yoffset_ce);
for (j = 2; j >= 0; j--)
{
int c = ii % 10;
- BlitBitmap(src_bitmap, bitmap, TILEX + c * 7, 0, 6, 10,
+ BlitBitmap(src_bitmap, bitmap,
+ TILEX + c * 7, 0, 6, 10,
TILEX * x + 6 + j * 7,
TILEY * y + 11 + yoffset_ce);
- BlitBitmap(src_bitmap, bitmap, TILEX + c * 8, TILEY, 6, 10,
+ BlitBitmap(src_bitmap, bitmap,
+ TILEX + c * 8, TILEY, 6, 10,
TILEX * 16 + TILEX * x + 6 + j * 8,
TILEY * y + 10 + yoffset_ce);
BlitBitmap(src_bitmap, bitmap, 0, 0, TILEX, TILEY,
TILEX * x, TILEY * y + yoffset_ge);
- BlitBitmap(src_bitmap, bitmap, 0, TILEY, TILEX, TILEY,
- TILEX * x + TILEX * 16, TILEY * y + yoffset_ge);
+ BlitBitmap(src_bitmap, bitmap, 0, TILEY,
+ TILEX, TILEY,
+ TILEX * x + TILEX * 16,
+ TILEY * y + yoffset_ge);
for (j = 1; j >= 0; j--)
{
TILEX * x + 6 + j * 10,
TILEY * y + 11 + yoffset_ge);
- BlitBitmap(src_bitmap, bitmap, TILEX + c * 8, TILEY + 12, 6, 10,
+ BlitBitmap(src_bitmap, bitmap,
+ TILEX + c * 8, TILEY + 12, 6, 10,
TILEX * 16 + TILEX * x + 10 + j * 8,
TILEY * y + 10 + yoffset_ge);