added setup option to ask to play again after game is over but not solved
[rocksndiamonds.git] / src / files.c
index efbc26f8cb2797a1784498ae81fedea88e140acf..75e691c36555fdd434af328a817ac5be0c482c99 100644 (file)
@@ -251,6 +251,12 @@ static struct LevelFileConfigInfo chunk_config_INFO[] =
     &li.auto_count_gems,               FALSE
   },
 
+  {
+    -1,                                        -1,
+    TYPE_BOOLEAN,                      CONF_VALUE_8_BIT(11),
+    &li.solved_by_one_player,          FALSE
+  },
+
   {
     -1,                                        -1,
     -1,                                        -1,
@@ -662,6 +668,11 @@ static struct LevelFileConfigInfo chunk_config_ELEM[] =
     TYPE_INTEGER,                      CONF_VALUE_8_BIT(4),
     &li.game_of_life[3],               3
   },
+  {
+    EL_GAME_OF_LIFE,                   -1,
+    TYPE_BOOLEAN,                      CONF_VALUE_8_BIT(5),
+    &li.use_life_bugs,                 FALSE
+  },
 
   {
     EL_BIOMAZE,                                -1,
@@ -1398,7 +1409,7 @@ static boolean check_special_flags(char *flag)
   return FALSE;
 }
 
-static struct DateInfo getCurrentDate()
+static struct DateInfo getCurrentDate(void)
 {
   time_t epoch_seconds = time(NULL);
   struct tm *now = localtime(&epoch_seconds);
@@ -1421,7 +1432,7 @@ static void resetEventFlags(struct ElementChangeInfo *change)
     change->has_event[i] = FALSE;
 }
 
-static void resetEventBits()
+static void resetEventBits(void)
 {
   int i;
 
@@ -1862,7 +1873,7 @@ static void setFileInfoToDefaults(struct LevelFileInfo *level_file_info)
 
 int getMappedElement_SB(int, boolean);
 
-static void ActivateLevelTemplate()
+static void ActivateLevelTemplate(void)
 {
   int x, y;
 
@@ -1915,6 +1926,9 @@ static void ActivateLevelTemplate()
     /* overwrite all individual level settings from template level settings */
     level = level_template;
 
+    /* restore level file info */
+    level.file_info = level_backup.file_info;
+
     /* restore playfield size */
     level.fieldx = level_backup.fieldx;
     level.fieldy = level_backup.fieldy;
@@ -2150,12 +2164,12 @@ static int getFiletypeFromID(char *filetype_id)
   return filetype;
 }
 
-char *getLocalLevelTemplateFilename()
+char *getLocalLevelTemplateFilename(void)
 {
   return getDefaultLevelFilename(-1);
 }
 
-char *getGlobalLevelTemplateFilename()
+char *getGlobalLevelTemplateFilename(void)
 {
   /* global variable "leveldir_current" must be modified in the loop below */
   LevelDirTree *leveldir_current_last = leveldir_current;
@@ -2302,7 +2316,7 @@ static void copyLevelFileInfo(struct LevelFileInfo *lfi_from,
 /* functions for loading R'n'D level                                         */
 /* ------------------------------------------------------------------------- */
 
-int getMappedElement(int element)
+static int getMappedElement(int element)
 {
   /* remap some (historic, now obsolete) elements */
 
@@ -2353,7 +2367,7 @@ int getMappedElement(int element)
   return element;
 }
 
-int getMappedElementByVersion(int element, int game_version)
+static int getMappedElementByVersion(int element, int game_version)
 {
   /* remap some elements due to certain game version */
 
@@ -3475,7 +3489,7 @@ static void LoadLevelFromFileInfo_RND(struct LevelInfo *level,
 /* functions for loading EM level                                            */
 /* ------------------------------------------------------------------------- */
 
-void CopyNativeLevel_RND_to_EM(struct LevelInfo *level)
+static void CopyNativeLevel_RND_to_EM(struct LevelInfo *level)
 {
   static int ball_xy[8][2] =
   {
@@ -3603,7 +3617,7 @@ void CopyNativeLevel_RND_to_EM(struct LevelInfo *level)
   }
 }
 
-void CopyNativeLevel_EM_to_RND(struct LevelInfo *level)
+static void CopyNativeLevel_EM_to_RND(struct LevelInfo *level)
 {
   static int ball_xy[8][2] =
   {
@@ -3704,7 +3718,7 @@ void CopyNativeLevel_EM_to_RND(struct LevelInfo *level)
 /* functions for loading SP level                                            */
 /* ------------------------------------------------------------------------- */
 
-void CopyNativeLevel_RND_to_SP(struct LevelInfo *level)
+static void CopyNativeLevel_RND_to_SP(struct LevelInfo *level)
 {
   struct LevelInfo_SP *level_sp = level->native_sp_level;
   LevelInfoType *header = &level_sp->header;
@@ -3788,7 +3802,7 @@ void CopyNativeLevel_RND_to_SP(struct LevelInfo *level)
   }
 }
 
-void CopyNativeLevel_SP_to_RND(struct LevelInfo *level)
+static void CopyNativeLevel_SP_to_RND(struct LevelInfo *level)
 {
   struct LevelInfo_SP *level_sp = level->native_sp_level;
   LevelInfoType *header = &level_sp->header;
@@ -3948,7 +3962,7 @@ static void CopyNativeTape_RND_to_SP(struct LevelInfo *level)
   demo->is_available = TRUE;
 }
 
-static void setTapeInfoToDefaults();
+static void setTapeInfoToDefaults(void);
 
 static void CopyNativeTape_SP_to_RND(struct LevelInfo *level)
 {
@@ -4001,7 +4015,7 @@ static void CopyNativeTape_SP_to_RND(struct LevelInfo *level)
 /* functions for loading MM level                                            */
 /* ------------------------------------------------------------------------- */
 
-void CopyNativeLevel_RND_to_MM(struct LevelInfo *level)
+static void CopyNativeLevel_RND_to_MM(struct LevelInfo *level)
 {
   struct LevelInfo_MM *level_mm = level->native_mm_level;
   int x, y;
@@ -4038,7 +4052,7 @@ void CopyNativeLevel_RND_to_MM(struct LevelInfo *level)
        level_mm->field[x][y] = map_element_RND_to_MM(level->field[x][y]);
 }
 
-void CopyNativeLevel_MM_to_RND(struct LevelInfo *level)
+static void CopyNativeLevel_MM_to_RND(struct LevelInfo *level)
 {
   struct LevelInfo_MM *level_mm = level->native_mm_level;
   int x, y;
@@ -4084,7 +4098,8 @@ void CopyNativeLevel_MM_to_RND(struct LevelInfo *level)
 
 #define DC_LEVEL_HEADER_SIZE           344
 
-unsigned short getDecodedWord_DC(unsigned short data_encoded, boolean init)
+static unsigned short getDecodedWord_DC(unsigned short data_encoded,
+                                       boolean init)
 {
   static int last_data_encoded;
   static int offset1;
@@ -4123,7 +4138,7 @@ unsigned short getDecodedWord_DC(unsigned short data_encoded, boolean init)
   return data_decoded;
 }
 
-int getMappedElement_DC(int element)
+static int getMappedElement_DC(int element)
 {
   switch (element)
   {
@@ -6299,6 +6314,10 @@ static void LoadLevel_InitVersion(struct LevelInfo *level)
     level->extra_time_score = level->score[SC_TIME_BONUS];
   }
 
+  /* game logic of "game of life" and "biomaze" was buggy before 4.1.1.1 */
+  if (level->game_version < VERSION_IDENT(4,1,1,1))
+    level->use_life_bugs = TRUE;
+
   if (level->game_version < VERSION_IDENT(3,2,0,7))
   {
     /* default behaviour for snapping was "not continuous" before 3.2.0-7 */
@@ -6392,6 +6411,10 @@ static void LoadLevel_InitVersion(struct LevelInfo *level)
   /* EM style elements always chain-exploded in R'n'D engine before 3.2.6 */
   if (level->game_version < VERSION_IDENT(3,2,6,0))
     level->em_explodes_by_fire = TRUE;
+
+  /* levels were solved by the first player entering an exit up to 4.1.0.0 */
+  if (level->game_version <= VERSION_IDENT(4,1,0,0))
+    level->solved_by_one_player = TRUE;
 }
 
 static void LoadLevel_InitStandardElements(struct LevelInfo *level)
@@ -6593,7 +6616,7 @@ static void LoadLevel_InitNativeEngines(struct LevelInfo *level)
     CopyNativeLevel_RND_to_Native(level);
 }
 
-static void LoadLevelTemplate_LoadAndInit()
+static void LoadLevelTemplate_LoadAndInit(void)
 {
   LoadLevelFromFileInfo(&level_template, &level_template.file_info, FALSE);
 
@@ -6617,21 +6640,21 @@ void LoadLevelTemplate(int nr)
   LoadLevelTemplate_LoadAndInit();
 }
 
-static void LoadLevelTemplateFromNetwork(struct LevelFileInfo *lfi_network_template)
+static void LoadNetworkLevelTemplate(struct NetworkLevelInfo *network_level)
 {
-  copyLevelFileInfo(lfi_network_template, &level_template.file_info);
+  copyLevelFileInfo(&network_level->tmpl_info, &level_template.file_info);
 
   LoadLevelTemplate_LoadAndInit();
 }
 
-static void LoadLevel_LoadAndInit(struct LevelFileInfo *lfi_network_template)
+static void LoadLevel_LoadAndInit(struct NetworkLevelInfo *network_level)
 {
   LoadLevelFromFileInfo(&level, &level.file_info, FALSE);
 
   if (level.use_custom_template)
   {
-    if (lfi_network_template != NULL)
-      LoadLevelTemplateFromNetwork(lfi_network_template);
+    if (network_level != NULL)
+      LoadNetworkLevelTemplate(network_level);
     else
       LoadLevelTemplate(-1);
   }
@@ -6645,6 +6668,8 @@ static void LoadLevel_LoadAndInit(struct LevelFileInfo *lfi_network_template)
 
 void LoadLevel(int nr)
 {
+  SetLevelSetInfo(leveldir_current->identifier, nr);
+
   setLevelFileInfo(&level.file_info, nr);
 
   LoadLevel_LoadAndInit(NULL);
@@ -6657,12 +6682,14 @@ void LoadLevelInfoOnly(int nr)
   LoadLevelFromFileInfo(&level, &level.file_info, TRUE);
 }
 
-void LoadLevelFromNetwork(struct LevelFileInfo *lfi_network_level,
-                         struct LevelFileInfo *lfi_network_template)
+void LoadNetworkLevel(struct NetworkLevelInfo *network_level)
 {
-  copyLevelFileInfo(lfi_network_level, &level.file_info);
+  SetLevelSetInfo(network_level->leveldir_identifier,
+                 network_level->file_info.nr);
+
+  copyLevelFileInfo(&network_level->file_info, &level.file_info);
 
-  LoadLevel_LoadAndInit(lfi_network_template);
+  LoadLevel_LoadAndInit(network_level);
 }
 
 static int SaveLevel_VERS(FILE *file, struct LevelInfo *level)
@@ -7497,7 +7524,7 @@ void SaveLevel(int nr)
   SaveLevelFromFilename(&level, filename, FALSE);
 }
 
-void SaveLevelTemplate()
+void SaveLevelTemplate(void)
 {
   char *filename = getLocalLevelTemplateFilename();
 
@@ -7567,7 +7594,7 @@ void DumpLevel(struct LevelInfo *level)
 /* tape file functions                                                       */
 /* ========================================================================= */
 
-static void setTapeInfoToDefaults()
+static void setTapeInfoToDefaults(void)
 {
   int i;
 
@@ -7767,7 +7794,7 @@ static int LoadTape_BODY(File *file, int chunk_size, struct TapeInfo *tape)
   return chunk_size;
 }
 
-void LoadTape_SokobanSolution(char *filename)
+static void LoadTape_SokobanSolution(char *filename)
 {
   File *file;
   int move_delay = TILESIZE / level.initial_player_stepsize[0];
@@ -8335,11 +8362,14 @@ enum
   SETUP_TOKEN_WINDOW_SCALING_PERCENT,
   SETUP_TOKEN_WINDOW_SCALING_QUALITY,
   SETUP_TOKEN_SCREEN_RENDERING_MODE,
+  SETUP_TOKEN_VSYNC_MODE,
   SETUP_TOKEN_ASK_ON_ESCAPE,
   SETUP_TOKEN_ASK_ON_ESCAPE_EDITOR,
+  SETUP_TOKEN_ASK_ON_GAME_OVER,
   SETUP_TOKEN_QUICK_SWITCH,
   SETUP_TOKEN_INPUT_ON_FOCUS,
   SETUP_TOKEN_PREFER_AGA_GRAPHICS,
+  SETUP_TOKEN_GAME_SPEED_EXTENDED,
   SETUP_TOKEN_GAME_FRAME_DELAY,
   SETUP_TOKEN_SP_SHOW_BORDER_ELEMENTS,
   SETUP_TOKEN_SMALL_GAME_GRAPHICS,
@@ -8355,6 +8385,7 @@ enum
   SETUP_TOKEN_VOLUME_MUSIC,
   SETUP_TOKEN_NETWORK_MODE,
   SETUP_TOKEN_NETWORK_PLAYER_NR,
+  SETUP_TOKEN_NETWORK_SERVER_HOSTNAME,
   SETUP_TOKEN_TOUCH_CONTROL_TYPE,
   SETUP_TOKEN_TOUCH_MOVE_DISTANCE,
   SETUP_TOKEN_TOUCH_DROP_DISTANCE,
@@ -8576,11 +8607,14 @@ static struct TokenInfo global_setup_tokens[] =
   { TYPE_INTEGER,&si.window_scaling_percent,  "window_scaling_percent" },
   { TYPE_STRING, &si.window_scaling_quality,  "window_scaling_quality" },
   { TYPE_STRING, &si.screen_rendering_mode,   "screen_rendering_mode"  },
+  { TYPE_STRING, &si.vsync_mode,              "vsync_mode"             },
   { TYPE_SWITCH, &si.ask_on_escape,           "ask_on_escape"          },
   { TYPE_SWITCH, &si.ask_on_escape_editor,    "ask_on_escape_editor"   },
+  { TYPE_SWITCH, &si.ask_on_game_over,        "ask_on_game_over"       },
   { TYPE_SWITCH, &si.quick_switch,            "quick_player_switch"    },
   { TYPE_SWITCH, &si.input_on_focus,          "input_on_focus"         },
   { TYPE_SWITCH, &si.prefer_aga_graphics,     "prefer_aga_graphics"    },
+  { TYPE_SWITCH, &si.game_speed_extended,     "game_speed_extended"    },
   { 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"    },
@@ -8596,6 +8630,7 @@ static struct TokenInfo global_setup_tokens[] =
   { TYPE_INTEGER,&si.volume_music,            "volume_music"           },
   { TYPE_SWITCH, &si.network_mode,            "network_mode"           },
   { TYPE_PLAYER, &si.network_player_nr,       "network_player"         },
+  { TYPE_STRING, &si.network_server_hostname, "network_server_hostname"        },
   { TYPE_STRING, &si.touch.control_type,      "touch.control_type"     },
   { TYPE_INTEGER,&si.touch.move_distance,     "touch.move_distance"    },
   { TYPE_INTEGER,&si.touch.drop_distance,     "touch.drop_distance"    },
@@ -8796,11 +8831,14 @@ static void setSetupInfoToDefaults(struct SetupInfo *si)
   si->window_scaling_percent = STD_WINDOW_SCALING_PERCENT;
   si->window_scaling_quality = getStringCopy(SCALING_QUALITY_DEFAULT);
   si->screen_rendering_mode = getStringCopy(STR_SPECIAL_RENDERING_DEFAULT);
+  si->vsync_mode = getStringCopy(STR_VSYNC_MODE_DEFAULT);
   si->ask_on_escape = TRUE;
   si->ask_on_escape_editor = TRUE;
+  si->ask_on_game_over = TRUE;
   si->quick_switch = FALSE;
   si->input_on_focus = FALSE;
   si->prefer_aga_graphics = TRUE;
+  si->game_speed_extended = FALSE;
   si->game_frame_delay = GAME_FRAME_DELAY;
   si->sp_show_border_elements = FALSE;
   si->small_game_graphics = FALSE;
@@ -8820,6 +8858,7 @@ static void setSetupInfoToDefaults(struct SetupInfo *si)
 
   si->network_mode = FALSE;
   si->network_player_nr = 0;           /* first player */
+  si->network_server_hostname = getStringCopy(STR_NETWORK_AUTO_DETECT);
 
   si->touch.control_type = getStringCopy(TOUCH_CONTROL_DEFAULT);
   si->touch.move_distance = TOUCH_MOVE_DISTANCE_DEFAULT;       /* percent */
@@ -9261,7 +9300,7 @@ void LoadSetupFromFilename(char *filename)
   }
 }
 
-static void LoadSetup_SpecialPostProcessing()
+static void LoadSetup_SpecialPostProcessing(void)
 {
   char *player_name_new;
 
@@ -9282,7 +9321,7 @@ static void LoadSetup_SpecialPostProcessing()
     MIN(MAX(MIN_SCROLL_DELAY, setup.scroll_delay_value), MAX_SCROLL_DELAY);
 }
 
-void LoadSetup()
+void LoadSetup(void)
 {
   char *filename;
 
@@ -9303,7 +9342,7 @@ void LoadSetup()
   LoadSetup_SpecialPostProcessing();
 }
 
-void LoadSetup_AutoSetup()
+void LoadSetup_AutoSetup(void)
 {
   char *filename = getPath2(getSetupDir(), AUTOSETUP_FILENAME);
   SetupFileHash *setup_file_hash = NULL;
@@ -9323,7 +9362,7 @@ void LoadSetup_AutoSetup()
   free(filename);
 }
 
-void LoadSetup_EditorCascade()
+void LoadSetup_EditorCascade(void)
 {
   char *filename = getPath2(getSetupDir(), EDITORCASCADE_FILENAME);
   SetupFileHash *setup_file_hash = NULL;
@@ -9392,7 +9431,7 @@ static void LoadSetup_ReadGameControllerMappings(SetupFileHash *mappings_hash,
   fclose(file);
 }
 
-void SaveSetup()
+void SaveSetup(void)
 {
   char *filename = getSetupFilename();
   FILE *file;
@@ -9505,7 +9544,7 @@ void SaveSetup()
   SetFilePermissions(filename, PERMS_PRIVATE);
 }
 
-void SaveSetup_AutoSetup()
+void SaveSetup_AutoSetup(void)
 {
   char *filename = getPath2(getSetupDir(), AUTOSETUP_FILENAME);
   FILE *file;
@@ -9533,7 +9572,7 @@ void SaveSetup_AutoSetup()
   free(filename);
 }
 
-void SaveSetup_EditorCascade()
+void SaveSetup_EditorCascade(void)
 {
   char *filename = getPath2(getSetupDir(), EDITORCASCADE_FILENAME);
   FILE *file;
@@ -9602,7 +9641,7 @@ void SaveSetup_AddGameControllerMapping(char *mapping)
   free(filename);
 }
 
-void LoadCustomElementDescriptions()
+void LoadCustomElementDescriptions(void)
 {
   char *filename = getCustomArtworkConfigFilename(ARTWORK_TYPE_GRAPHICS);
   SetupFileHash *setup_file_hash;
@@ -9664,7 +9703,7 @@ static int get_token_parameter_value(char *token, char *value_raw)
   return get_parameter_value(value_raw, suffix, TYPE_INTEGER);
 }
 
-void InitMenuDesignSettings_Static()
+void InitMenuDesignSettings_Static(void)
 {
   int i;
 
@@ -9679,7 +9718,7 @@ void InitMenuDesignSettings_Static()
   }
 }
 
-static void InitMenuDesignSettings_SpecialPreProcessing()
+static void InitMenuDesignSettings_SpecialPreProcessing(void)
 {
   int i;
 
@@ -9771,7 +9810,7 @@ static void InitMenuDesignSettings_SpecialPreProcessing()
   }
 }
 
-static void InitMenuDesignSettings_SpecialPostProcessing()
+static void InitMenuDesignSettings_SpecialPostProcessing(void)
 {
   static struct
   {
@@ -9800,7 +9839,7 @@ static void InitMenuDesignSettings_SpecialPostProcessing()
       *game_buttons_xy[i].dst = *game_buttons_xy[i].src;
 }
 
-static void InitMenuDesignSettings_SpecialPostProcessing_AfterGraphics()
+static void InitMenuDesignSettings_SpecialPostProcessing_AfterGraphics(void)
 {
   static struct
   {
@@ -10234,7 +10273,7 @@ static void LoadMenuDesignSettingsFromFilename(char *filename)
   freeSetupFileHash(setup_file_hash);
 }
 
-void LoadMenuDesignSettings()
+void LoadMenuDesignSettings(void)
 {
   char *filename_base = UNDEFINED_FILENAME, *filename_local;
 
@@ -10258,7 +10297,7 @@ void LoadMenuDesignSettings()
   InitMenuDesignSettings_SpecialPostProcessing();
 }
 
-void LoadMenuDesignSettings_AfterGraphics()
+void LoadMenuDesignSettings_AfterGraphics(void)
 {
   InitMenuDesignSettings_SpecialPostProcessing_AfterGraphics();
 }
@@ -10460,7 +10499,7 @@ static boolean sound_info_listed(struct MusicFileInfo *list, char *basename)
   return music_info_listed_ext(list, basename, TRUE);
 }
 
-void LoadMusicInfo()
+void LoadMusicInfo(void)
 {
   char *music_directory = getCustomMusicDirectory();
   int num_music = getMusicListSize();
@@ -10587,8 +10626,8 @@ void LoadMusicInfo()
   }
 }
 
-void add_helpanim_entry(int element, int action, int direction, int delay,
-                       int *num_list_entries)
+static void add_helpanim_entry(int element, int action, int direction,
+                              int delay, int *num_list_entries)
 {
   struct HelpAnimInfo *new_list_entry;
   (*num_list_entries)++;
@@ -10604,7 +10643,7 @@ void add_helpanim_entry(int element, int action, int direction, int delay,
   new_list_entry->delay = delay;
 }
 
-void print_unknown_token(char *filename, char *token, int token_nr)
+static void print_unknown_token(char *filename, char *token, int token_nr)
 {
   if (token_nr == 0)
   {
@@ -10616,13 +10655,13 @@ void print_unknown_token(char *filename, char *token, int token_nr)
   Error(ERR_INFO, "- token: '%s'", token);
 }
 
-void print_unknown_token_end(int token_nr)
+static void print_unknown_token_end(int token_nr)
 {
   if (token_nr > 0)
     Error(ERR_INFO_LINE, "-");
 }
 
-void LoadHelpAnimInfo()
+void LoadHelpAnimInfo(void)
 {
   char *filename = getHelpAnimFilename();
   SetupFileList *setup_file_list = NULL, *list;
@@ -10832,7 +10871,7 @@ void LoadHelpAnimInfo()
 #endif
 }
 
-void LoadHelpTextInfo()
+void LoadHelpTextInfo(void)
 {
   char *filename = getHelpTextFilename();
   int i;
@@ -10874,7 +10913,7 @@ void LoadHelpTextInfo()
 
 #define MAX_NUM_CONVERT_LEVELS         1000
 
-void ConvertLevels()
+void ConvertLevels(void)
 {
   static LevelDirTree *convert_leveldir = NULL;
   static int convert_level_nr = -1;
@@ -10986,7 +11025,7 @@ void ConvertLevels()
 /* create and save images for use in level sketches (raw BMP format)         */
 /* ------------------------------------------------------------------------- */
 
-void CreateLevelSketchImages()
+void CreateLevelSketchImages(void)
 {
 #if defined(TARGET_SDL)
   Bitmap *bitmap1;