rnd-20100111-1-src
[rocksndiamonds.git] / src / files.c
index cd288bce594a83cd27d8570348372e2e914d1faf..792d2cddbea28f7bd033fa67061f8d520e26a10a 100644 (file)
@@ -1314,6 +1314,22 @@ filetype_id_list[] =
 /* level file functions                                                      */
 /* ========================================================================= */
 
+static boolean check_special_flags(char *flag)
+{
+#if 0
+  printf("::: '%s', '%s', '%s'\n",
+        flag,
+        options.special_flags,
+        leveldir_current->special_flags);
+#endif
+
+  if (strEqual(options.special_flags, flag) ||
+      strEqual(leveldir_current->special_flags, flag))
+    return TRUE;
+
+  return FALSE;
+}
+
 static struct DateInfo getCurrentDate()
 {
   time_t epoch_seconds = time(NULL);
@@ -1752,9 +1768,38 @@ static void setFileInfoToDefaults(struct LevelFileInfo *level_file_info)
 
 static void ActivateLevelTemplate()
 {
+  int x, y;
+
   /* Currently there is no special action needed to activate the template
      data, because 'element_info' property settings overwrite the original
      level data, while all other variables do not change. */
+
+  /* Exception: 'from_level_template' elements in the original level playfield
+     are overwritten with the corresponding elements at the same position in
+     playfield from the level template. */
+
+  for (x = 0; x < level.fieldx; x++)
+    for (y = 0; y < level.fieldy; y++)
+      if (level.field[x][y] == EL_FROM_LEVEL_TEMPLATE)
+       level.field[x][y] = level_template.field[x][y];
+
+  if (check_special_flags("load_xsb_to_ces"))
+  {
+    short FieldBackup[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+
+    /* backup playfield from individual level */
+    for (x = 0; x < level.fieldx; x++)
+      for (y = 0; y < level.fieldy; y++)
+       FieldBackup[x][y] = level.field[x][y];
+
+    /* set all individual level settings to template level settings */
+    level = level_template;
+
+    /* restore playfield from individual level */
+    for (x = 0; x < level.fieldx; x++)
+      for (y = 0; y < level.fieldy; y++)
+       level.field[x][y] = FieldBackup[x][y];
+  }
 }
 
 static char *getLevelFilenameFromBasename(char *basename)
@@ -4212,7 +4257,7 @@ void CopyNativeLevel_RND_to_SP(struct LevelInfo *level)
   LevelInfoType *header = &level_sp->header;
   int i, x, y;
 
-  level_sp->width = level->fieldx;
+  level_sp->width  = level->fieldx;
   level_sp->height = level->fieldy;
 
   for (x = 0; x < level->fieldx; x++)
@@ -4244,7 +4289,67 @@ void CopyNativeLevel_RND_to_SP(struct LevelInfo *level)
 
   header->InfotronsNeeded = level->gems_needed;
 
-  /* !!! ADD SPECIAL PORT DATABASE STUFF !!! */
+  header->SpecialPortCount = 0;
+
+  for (x = 0; x < level->fieldx; x++) for (y = 0; y < level->fieldy; y++)
+  {
+    boolean gravity_port_found = FALSE;
+    boolean gravity_port_valid = FALSE;
+    int gravity_port_flag;
+    int gravity_port_base_element;
+    int element = level->field[x][y];
+
+    if (element >= EL_SP_GRAVITY_ON_PORT_RIGHT &&
+       element <= EL_SP_GRAVITY_ON_PORT_UP)
+    {
+      gravity_port_found = TRUE;
+      gravity_port_valid = TRUE;
+      gravity_port_flag = 1;
+      gravity_port_base_element = EL_SP_GRAVITY_ON_PORT_RIGHT;
+    }
+    else if (element >= EL_SP_GRAVITY_OFF_PORT_RIGHT &&
+            element <= EL_SP_GRAVITY_OFF_PORT_UP)
+    {
+      gravity_port_found = TRUE;
+      gravity_port_valid = TRUE;
+      gravity_port_flag = 0;
+      gravity_port_base_element = EL_SP_GRAVITY_OFF_PORT_RIGHT;
+    }
+    else if (element >= EL_SP_GRAVITY_PORT_RIGHT &&
+            element <= EL_SP_GRAVITY_PORT_UP)
+    {
+      /* change R'n'D style gravity inverting special port to normal port
+        (there are no gravity inverting ports in native Supaplex engine) */
+
+      gravity_port_found = TRUE;
+      gravity_port_valid = FALSE;
+      gravity_port_base_element = EL_SP_GRAVITY_PORT_RIGHT;
+    }
+
+    if (gravity_port_found)
+    {
+      if (gravity_port_valid &&
+         header->SpecialPortCount < SP_MAX_SPECIAL_PORTS)
+      {
+       SpecialPortType *port = &header->SpecialPort[header->SpecialPortCount];
+
+       port->PortLocation = (y * level->fieldx + x) * 2;
+       port->Gravity = gravity_port_flag;
+
+       element += EL_SP_GRAVITY_PORT_RIGHT - gravity_port_base_element;
+
+       header->SpecialPortCount++;
+      }
+      else
+      {
+       /* change special gravity port to normal port */
+
+       element += EL_SP_PORT_RIGHT - gravity_port_base_element;
+      }
+
+      level_sp->playfield[x][y] = element - EL_SP_START;
+    }
+  }
 }
 
 void CopyNativeLevel_SP_to_RND(struct LevelInfo *level)
@@ -6359,40 +6464,6 @@ static void LoadLevelFromFileInfo_DC(struct LevelInfo *level,
 /* functions for loading SB level                                            */
 /* ------------------------------------------------------------------------- */
 
-#if 1
-
-static boolean check_special_flags(char *flag)
-{
-#if 0
-  printf("::: '%s', '%s', '%s'\n",
-        flag,
-        options.special_flags,
-        leveldir_current->special_flags);
-#endif
-
-  if (strEqual(options.special_flags, flag) ||
-      strEqual(leveldir_current->special_flags, flag))
-    return TRUE;
-
-  return FALSE;
-}
-
-#else
-
-#define SPECIAL_FLAG_LOAD_XSB_TO_CES   (1 << 0)
-
-static unsigned long get_special_flags(char *flags_string)
-{
-  unsigned long flags_value = 0;
-
-  if (strEqual(flags_string, "load_xsb_to_ces"))
-    flags_value = SPECIAL_FLAG_LOAD_XSB_TO_CES;
-
-  return flags_value;
-}
-
-#endif
-
 int getMappedElement_SB(int element_ascii, boolean use_ces)
 {
   static struct
@@ -6410,7 +6481,11 @@ int getMappedElement_SB(int element_ascii, boolean use_ces)
     { '.', EL_SOKOBAN_FIELD_EMPTY,  EL_CUSTOM_5 },  /* goal square */
     { '*', EL_SOKOBAN_FIELD_FULL,   EL_CUSTOM_6 },  /* box on goal square */
     { '+', EL_SOKOBAN_FIELD_PLAYER, EL_CUSTOM_7 },  /* player on goal square */
+#if 0
     { '_', EL_INVISIBLE_STEELWALL,  EL_CUSTOM_8 },  /* floor beyond border */
+#else
+    { '_', EL_INVISIBLE_STEELWALL,  EL_FROM_LEVEL_TEMPLATE },  /* floor beyond border */
+#endif
 
     { 0,   -1,                      -1          },
   };
@@ -6438,11 +6513,7 @@ static void LoadLevelFromFileInfo_SB(struct LevelInfo *level,
   boolean reading_playfield = FALSE;
   boolean got_valid_playfield_line = FALSE;
   boolean invalid_playfield_char = FALSE;
-#if 1
   boolean load_xsb_to_ces = check_special_flags("load_xsb_to_ces");
-#else
-  boolean load_xsb_to_ces = options.special_flags & SPECIAL_FLAG_LOAD_XSB_TO_CES;
-#endif
   int file_level_nr = 0;
   int line_nr = 0;
   int x, y;
@@ -6694,7 +6765,11 @@ static void LoadLevelFromFileInfo_SB(struct LevelInfo *level,
 
   if (load_xsb_to_ces)
   {
+#if 1
+    /* !!! special global settings can now be set in level template !!! */
+#else
     level->initial_player_stepsize[0] = STEPSIZE_SLOW;
+#endif
 
     /* fill smaller playfields with padding "beyond border wall" elements */
     if (level->fieldx < SCR_FIELDX ||