rnd-20051231-1-src
[rocksndiamonds.git] / src / init.c
index f9dd0c1338bb8933f5bfeb18eb8bd7e2877ae277..b4b78259e4db2b48151bad954c48574df729b3c2 100644 (file)
@@ -109,6 +109,14 @@ inline void InitElementSmallImagesScaledUp(int graphic)
 
 void InitElementSmallImages()
 {
+  static int special_graphics[] =
+  {
+    IMG_EDITOR_ELEMENT_BORDER,
+    IMG_EDITOR_ELEMENT_BORDER_INPUT,
+    IMG_EDITOR_CASCADE_LIST,
+    IMG_EDITOR_CASCADE_LIST_ACTIVE,
+    -1
+  };
   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
   int num_property_mappings = getImageListPropertyMappingSize();
   int i;
@@ -124,6 +132,10 @@ void InitElementSmallImages()
   /* initialize images from dynamic configuration (may be elements or other) */
   for (i = 0; i < num_property_mappings; i++)
     InitElementSmallImagesScaledUp(property_mapping[i].artwork_index);
+
+  /* initialize special images from above list (non-element images) */
+  for (i = 0; special_graphics[i] > -1; i++)
+    InitElementSmallImagesScaledUp(special_graphics[i]);
 }
 
 #if 1
@@ -451,6 +463,17 @@ void InitElementGraphicInfo()
   element_info[EL_AMOEBA_TO_DIAMOND].graphic[ACTION_DEFAULT] = IMG_AMOEBA_DEAD;
 #endif
 
+#if 1
+  /* set hardcoded definitions for some internal elements without graphic */
+  for (i = 0; i < MAX_NUM_ELEMENTS; i++)
+  {
+    if (IS_EDITOR_CASCADE_INACTIVE(i))
+      element_info[i].graphic[ACTION_DEFAULT] = IMG_EDITOR_CASCADE_LIST;
+    else if (IS_EDITOR_CASCADE_ACTIVE(i))
+      element_info[i].graphic[ACTION_DEFAULT] = IMG_EDITOR_CASCADE_LIST_ACTIVE;
+  }
+#endif
+
   /* now set all undefined/invalid graphics to -1 to set to default after it */
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
   {
@@ -785,16 +808,23 @@ void InitElementSpecialGraphicInfo()
          element_info[i].graphic[ACTION_DEFAULT];
 }
 
-static int get_element_from_token(char *token)
+static int get_graphic_parameter_value(char *value_raw, char *suffix, int type)
 {
   int i;
   int x = 0;
 
+  if (type != TYPE_TOKEN)
+    return get_parameter_value(value_raw, suffix, type);
+
+  if (strcmp(value_raw, ARG_UNDEFINED) == 0)
+    return ARG_UNDEFINED_VALUE;
+
+  /* !!! OPTIMIZE THIS BY USING HASH !!! */
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
-    if (strcmp(element_info[i].token_name, token) == 0)
+    if (strcmp(element_info[i].token_name, value_raw) == 0)
       return i;
 
-#if 1
+  /* !!! OPTIMIZE THIS BY USING HASH !!! */
   for (i = 0; image_config[i].token != NULL; i++)
   {
     int len_config_value = strlen(image_config[i].value);
@@ -804,12 +834,11 @@ static int get_element_from_token(char *token)
        strcmp(image_config[i].value, UNDEFINED_FILENAME) != 0)
       continue;
 
-    if (strcmp(image_config[i].token, token) == 0)
+    if (strcmp(image_config[i].token, value_raw) == 0)
       return x;
 
     x++;
   }
-#endif
 
   return -1;
 }
@@ -830,39 +859,25 @@ static int get_scaled_graphic_height(int graphic)
   return original_height * scale_up_factor;
 }
 
-static void set_graphic_parameters(int graphic, int graphic_copy_from)
+static void set_graphic_parameters(int graphic)
 {
-  struct FileInfo *image = getImageListEntryFromImageID(graphic_copy_from);
+  struct FileInfo *image = getImageListEntryFromImageID(graphic);
   char **parameter_raw = image->parameter;
-  Bitmap *src_bitmap = getBitmapFromImageID(graphic_copy_from);
+  Bitmap *src_bitmap = getBitmapFromImageID(graphic);
   int parameter[NUM_GFX_ARGS];
   int anim_frames_per_row = 1, anim_frames_per_col = 1;
   int anim_frames_per_line = 1;
   int i;
 
-#if 1
-  if (graphic != graphic_copy_from)
-  {
-    graphic_info[graphic] = graphic_info[graphic_copy_from];
-
-    return;
-  }
-#endif
-
   /* if fallback to default artwork is done, also use the default parameters */
   if (image->fallback_to_default)
     parameter_raw = image->default_parameter;
 
   /* get integer values from string parameters */
   for (i = 0; i < NUM_GFX_ARGS; i++)
-  {
-    parameter[i] =
-      get_parameter_value(image_config_suffix[i].token, parameter_raw[i],
-                         image_config_suffix[i].type);
-
-    if (image_config_suffix[i].type == TYPE_TOKEN)
-      parameter[i] = get_element_from_token(parameter_raw[i]);
-  }
+    parameter[i] = get_graphic_parameter_value(parameter_raw[i],
+                                              image_config_suffix[i].token,
+                                              image_config_suffix[i].type);
 
   graphic_info[graphic].bitmap = src_bitmap;
 
@@ -1046,25 +1061,48 @@ static void set_graphic_parameters(int graphic, int graphic_copy_from)
   /* this is only used for drawing envelope graphics */
   graphic_info[graphic].draw_masked = parameter[GFX_ARG_DRAW_MASKED];
 
-#if 1
   /* optional graphic for cloning all graphics settings */
   if (parameter[GFX_ARG_CLONE_FROM] != ARG_UNDEFINED_VALUE)
     graphic_info[graphic].clone_from = parameter[GFX_ARG_CLONE_FROM];
-#else
-  /* optional graphic for cloning all graphics settings */
-  if (parameter[GFX_ARG_CLONE_FROM] != ARG_UNDEFINED_VALUE)
+}
+
+static void set_cloned_graphic_parameters(int graphic)
+{
+  int fallback_graphic = IMG_CHAR_EXCLAM;
+  int max_num_images = getImageListSize();
+  int clone_graphic = graphic_info[graphic].clone_from;
+  int num_references_followed = 1;
+
+  while (graphic_info[clone_graphic].clone_from != -1 &&
+        num_references_followed < max_num_images)
   {
-    if (parameter[GFX_ARG_CLONE_FROM] != -1)
-    {
-      int clone_graphic = parameter[GFX_ARG_CLONE_FROM];
+    clone_graphic = graphic_info[clone_graphic].clone_from;
 
-      graphic_info[graphic] = graphic_info[clone_graphic];
-      graphic_info[graphic].clone_from = clone_graphic;
+    num_references_followed++;
+  }
 
-      printf("::: %d -> %d\n", graphic, clone_graphic);
-    }
+  if (num_references_followed >= max_num_images)
+  {
+    Error(ERR_RETURN_LINE, "-");
+    Error(ERR_RETURN, "warning: error found in config file:");
+    Error(ERR_RETURN, "- config file: '%s'", getImageConfigFilename());
+    Error(ERR_RETURN, "- config token: '%s'", getTokenFromImageID(graphic));
+    Error(ERR_RETURN, "error: loop discovered when resolving cloned graphics");
+    Error(ERR_RETURN, "custom graphic rejected for this element/action");
+
+    if (graphic == fallback_graphic)
+      Error(ERR_EXIT, "fatal error: no fallback graphic available");
+
+    Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
+    Error(ERR_RETURN_LINE, "-");
+
+    graphic_info[graphic] = graphic_info[fallback_graphic];
+  }
+  else
+  {
+    graphic_info[graphic] = graphic_info[clone_graphic];
+    graphic_info[graphic].clone_from = clone_graphic;
   }
-#endif
 }
 
 static void InitGraphicInfo()
@@ -1101,53 +1139,14 @@ static void InitGraphicInfo()
   }
 #endif
 
-#if 1
   /* first set all graphic paramaters ... */
   for (i = 0; i < num_images; i++)
-  {
-    set_graphic_parameters(i, i);
-  }
+    set_graphic_parameters(i);
 
   /* ... then copy these parameters for cloned graphics */
   for (i = 0; i < num_images; i++)
-  {
     if (graphic_info[i].clone_from != -1)
-    {
-      int clone_graphic = graphic_info[i].clone_from;
-
-      if (graphic_info[clone_graphic].clone_from != -1)
-      {
-       Error(ERR_RETURN_LINE, "-");
-       Error(ERR_RETURN, "warning: error found in config file:");
-       Error(ERR_RETURN, "- config file: '%s'", getImageConfigFilename());
-       Error(ERR_RETURN, "- config token: '%s'", getTokenFromImageID(i));
-       Error(ERR_RETURN,
-             "error: cannot clone from already cloned graphic '%s'",
-             getTokenFromImageID(clone_graphic));
-       Error(ERR_RETURN, "custom graphic rejected for this element/action");
-
-       if (i == fallback_graphic)
-         Error(ERR_EXIT, "fatal error: no fallback graphic available");
-
-       Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
-       Error(ERR_RETURN_LINE, "-");
-
-       set_graphic_parameters(i, fallback_graphic);
-      }
-      else
-      {
-       graphic_info[i] = graphic_info[clone_graphic];
-       graphic_info[i].clone_from = clone_graphic;
-
-#if 0
-       printf("::: graphic %d ['%s'] is cloned from %d ['%s']\n",
-              i, getTokenFromImageID(i),
-              clone_graphic, getTokenFromImageID(clone_graphic));
-#endif
-      }
-    }
-  }
-#endif
+      set_cloned_graphic_parameters(i);
 
   for (i = 0; i < num_images; i++)
   {
@@ -1156,46 +1155,20 @@ static void InitGraphicInfo()
     int first_frame, last_frame;
     int src_bitmap_width, src_bitmap_height;
 
-#if 0
-    printf("::: image # %d: '%s' ['%s']\n",
-          i, image->token, getTokenFromImageID(i));
-#endif
-
-#if 0
-    set_graphic_parameters(i, i);
-#endif
-
     /* now check if no animation frames are outside of the loaded image */
 
-#if 0
-    if (graphic_info[i].bitmap == NULL)
-      Error(ERR_WARN, "no bitmap for graphic %d ['%s']",
-           i, getTokenFromImageID(i));
-#endif
-
     if (graphic_info[i].bitmap == NULL)
       continue;                /* skip check for optional images that are undefined */
 
-#if 1
     /* get final bitmap size (with scaling, but without small images) */
     src_bitmap_width  = graphic_info[i].src_image_width;
     src_bitmap_height = graphic_info[i].src_image_height;
-#else
-    /* get final bitmap size (with scaling, but without small images) */
-    src_bitmap_width  = get_scaled_graphic_width(i);
-    src_bitmap_height = get_scaled_graphic_height(i);
 
-    if (graphic_info[i].clone_from != -1)
-    {
-      int clone_graphic = graphic_info[i].clone_from;
-
-      src_bitmap_width  = get_scaled_graphic_width(clone_graphic);
-      src_bitmap_height = get_scaled_graphic_height(clone_graphic);
-    }
-#endif
+    /* check if first animation frame is inside specified bitmap */
 
     first_frame = 0;
     getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
+
     if (src_x < 0 || src_y < 0 ||
        src_x + TILEX > src_bitmap_width ||
        src_y + TILEY > src_bitmap_height)
@@ -1216,11 +1189,14 @@ static void InitGraphicInfo()
       Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
       Error(ERR_RETURN_LINE, "-");
 
-      set_graphic_parameters(i, fallback_graphic);
+      graphic_info[i] = graphic_info[fallback_graphic];
     }
 
+    /* check if last animation frame is inside specified bitmap */
+
     last_frame = graphic_info[i].anim_frames - 1;
     getGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y);
+
     if (src_x < 0 || src_y < 0 ||
        src_x + TILEX > src_bitmap_width ||
        src_y + TILEY > src_bitmap_height)
@@ -1241,7 +1217,7 @@ static void InitGraphicInfo()
       Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
       Error(ERR_RETURN_LINE, "-");
 
-      set_graphic_parameters(i, fallback_graphic);
+      graphic_info[i] = graphic_info[fallback_graphic];
     }
 
 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
@@ -1431,7 +1407,8 @@ static void set_sound_parameters(int sound, char **parameter_raw)
   /* get integer values from string parameters */
   for (i = 0; i < NUM_SND_ARGS; i++)
     parameter[i] =
-      get_parameter_value(sound_config_suffix[i].token, parameter_raw[i],
+      get_parameter_value(parameter_raw[i],
+                         sound_config_suffix[i].token,
                          sound_config_suffix[i].type);
 
   /* explicit loop mode setting in configuration overrides default value */
@@ -1608,7 +1585,8 @@ static void set_music_parameters(int music, char **parameter_raw)
   /* get integer values from string parameters */
   for (i = 0; i < NUM_MUS_ARGS; i++)
     parameter[i] =
-      get_parameter_value(music_config_suffix[i].token, parameter_raw[i],
+      get_parameter_value(parameter_raw[i],
+                         music_config_suffix[i].token,
                          music_config_suffix[i].type);
 
   /* explicit loop mode setting in configuration overrides default value */
@@ -1995,6 +1973,10 @@ void InitElementPropertiesStatic()
     EL_GATE_2_GRAY,
     EL_GATE_3_GRAY,
     EL_GATE_4_GRAY,
+    EL_GATE_1_GRAY_ACTIVE,
+    EL_GATE_2_GRAY_ACTIVE,
+    EL_GATE_3_GRAY_ACTIVE,
+    EL_GATE_4_GRAY_ACTIVE,
     EL_EM_GATE_1,
     EL_EM_GATE_2,
     EL_EM_GATE_3,
@@ -2003,6 +1985,10 @@ void InitElementPropertiesStatic()
     EL_EM_GATE_2_GRAY,
     EL_EM_GATE_3_GRAY,
     EL_EM_GATE_4_GRAY,
+    EL_EM_GATE_1_GRAY_ACTIVE,
+    EL_EM_GATE_2_GRAY_ACTIVE,
+    EL_EM_GATE_3_GRAY_ACTIVE,
+    EL_EM_GATE_4_GRAY_ACTIVE,
     EL_EMC_GATE_5,
     EL_EMC_GATE_6,
     EL_EMC_GATE_7,
@@ -2011,6 +1997,10 @@ void InitElementPropertiesStatic()
     EL_EMC_GATE_6_GRAY,
     EL_EMC_GATE_7_GRAY,
     EL_EMC_GATE_8_GRAY,
+    EL_EMC_GATE_5_GRAY_ACTIVE,
+    EL_EMC_GATE_6_GRAY_ACTIVE,
+    EL_EMC_GATE_7_GRAY_ACTIVE,
+    EL_EMC_GATE_8_GRAY_ACTIVE,
     EL_SWITCHGATE_OPEN,
     EL_SWITCHGATE_OPENING,
     EL_SWITCHGATE_CLOSED,
@@ -2255,6 +2245,10 @@ void InitElementPropertiesStatic()
     EL_GATE_2_GRAY,
     EL_GATE_3_GRAY,
     EL_GATE_4_GRAY,
+    EL_GATE_1_GRAY_ACTIVE,
+    EL_GATE_2_GRAY_ACTIVE,
+    EL_GATE_3_GRAY_ACTIVE,
+    EL_GATE_4_GRAY_ACTIVE,
     EL_PENGUIN,
     EL_PIG,
     EL_DRAGON,
@@ -2292,6 +2286,10 @@ void InitElementPropertiesStatic()
     EL_EM_GATE_2_GRAY,
     EL_EM_GATE_3_GRAY,
     EL_EM_GATE_4_GRAY,
+    EL_EM_GATE_1_GRAY_ACTIVE,
+    EL_EM_GATE_2_GRAY_ACTIVE,
+    EL_EM_GATE_3_GRAY_ACTIVE,
+    EL_EM_GATE_4_GRAY_ACTIVE,
     EL_EMC_GATE_5,
     EL_EMC_GATE_6,
     EL_EMC_GATE_7,
@@ -2300,6 +2298,10 @@ void InitElementPropertiesStatic()
     EL_EMC_GATE_6_GRAY,
     EL_EMC_GATE_7_GRAY,
     EL_EMC_GATE_8_GRAY,
+    EL_EMC_GATE_5_GRAY_ACTIVE,
+    EL_EMC_GATE_6_GRAY_ACTIVE,
+    EL_EMC_GATE_7_GRAY_ACTIVE,
+    EL_EMC_GATE_8_GRAY_ACTIVE,
     EL_SWITCHGATE_OPEN,
     EL_TIMEGATE_OPEN,
     -1
@@ -2393,6 +2395,10 @@ void InitElementPropertiesStatic()
     EL_EM_GATE_2_GRAY,
     EL_EM_GATE_3_GRAY,
     EL_EM_GATE_4_GRAY,
+    EL_EM_GATE_1_GRAY_ACTIVE,
+    EL_EM_GATE_2_GRAY_ACTIVE,
+    EL_EM_GATE_3_GRAY_ACTIVE,
+    EL_EM_GATE_4_GRAY_ACTIVE,
     EL_EMC_GATE_5,
     EL_EMC_GATE_6,
     EL_EMC_GATE_7,
@@ -2401,6 +2407,10 @@ void InitElementPropertiesStatic()
     EL_EMC_GATE_6_GRAY,
     EL_EMC_GATE_7_GRAY,
     EL_EMC_GATE_8_GRAY,
+    EL_EMC_GATE_5_GRAY_ACTIVE,
+    EL_EMC_GATE_6_GRAY_ACTIVE,
+    EL_EMC_GATE_7_GRAY_ACTIVE,
+    EL_EMC_GATE_8_GRAY_ACTIVE,
     EL_SWITCHGATE_OPEN,
     EL_TIMEGATE_OPEN,
 
@@ -2549,6 +2559,7 @@ void InitElementPropertiesStatic()
     EL_BALLOON_SWITCH_UP,
     EL_BALLOON_SWITCH_DOWN,
     EL_BALLOON_SWITCH_ANY,
+    EL_BALLOON_SWITCH_NONE,
     EL_LAMP,
     EL_TIME_ORB_FULL,
     EL_EMC_MAGIC_BALL_SWITCH,
@@ -2751,6 +2762,10 @@ void InitElementPropertiesStatic()
     EL_GATE_2_GRAY,
     EL_GATE_3_GRAY,
     EL_GATE_4_GRAY,
+    EL_GATE_1_GRAY_ACTIVE,
+    EL_GATE_2_GRAY_ACTIVE,
+    EL_GATE_3_GRAY_ACTIVE,
+    EL_GATE_4_GRAY_ACTIVE,
     EL_EM_GATE_1,
     EL_EM_GATE_2,
     EL_EM_GATE_3,
@@ -2759,6 +2774,10 @@ void InitElementPropertiesStatic()
     EL_EM_GATE_2_GRAY,
     EL_EM_GATE_3_GRAY,
     EL_EM_GATE_4_GRAY,
+    EL_EM_GATE_1_GRAY_ACTIVE,
+    EL_EM_GATE_2_GRAY_ACTIVE,
+    EL_EM_GATE_3_GRAY_ACTIVE,
+    EL_EM_GATE_4_GRAY_ACTIVE,
     EL_EXIT_CLOSED,
     EL_EXIT_OPENING,
     EL_EXIT_OPEN,
@@ -2935,6 +2954,10 @@ void InitElementPropertiesStatic()
     EL_GATE_2_GRAY,
     EL_GATE_3_GRAY,
     EL_GATE_4_GRAY,
+    EL_GATE_1_GRAY_ACTIVE,
+    EL_GATE_2_GRAY_ACTIVE,
+    EL_GATE_3_GRAY_ACTIVE,
+    EL_GATE_4_GRAY_ACTIVE,
     EL_EM_GATE_1,
     EL_EM_GATE_2,
     EL_EM_GATE_3,
@@ -2943,6 +2966,10 @@ void InitElementPropertiesStatic()
     EL_EM_GATE_2_GRAY,
     EL_EM_GATE_3_GRAY,
     EL_EM_GATE_4_GRAY,
+    EL_EM_GATE_1_GRAY_ACTIVE,
+    EL_EM_GATE_2_GRAY_ACTIVE,
+    EL_EM_GATE_3_GRAY_ACTIVE,
+    EL_EM_GATE_4_GRAY_ACTIVE,
     EL_SWITCHGATE_OPEN,
     EL_SWITCHGATE_OPENING,
     EL_SWITCHGATE_CLOSED,
@@ -3058,6 +3085,10 @@ void InitElementPropertiesStatic()
     EL_GATE_2_GRAY,
     EL_GATE_3_GRAY,
     EL_GATE_4_GRAY,
+    EL_GATE_1_GRAY_ACTIVE,
+    EL_GATE_2_GRAY_ACTIVE,
+    EL_GATE_3_GRAY_ACTIVE,
+    EL_GATE_4_GRAY_ACTIVE,
     EL_EM_GATE_1,
     EL_EM_GATE_2,
     EL_EM_GATE_3,
@@ -3066,6 +3097,10 @@ void InitElementPropertiesStatic()
     EL_EM_GATE_2_GRAY,
     EL_EM_GATE_3_GRAY,
     EL_EM_GATE_4_GRAY,
+    EL_EM_GATE_1_GRAY_ACTIVE,
+    EL_EM_GATE_2_GRAY_ACTIVE,
+    EL_EM_GATE_3_GRAY_ACTIVE,
+    EL_EM_GATE_4_GRAY_ACTIVE,
     EL_EMC_GATE_5,
     EL_EMC_GATE_6,
     EL_EMC_GATE_7,
@@ -3074,6 +3109,10 @@ void InitElementPropertiesStatic()
     EL_EMC_GATE_6_GRAY,
     EL_EMC_GATE_7_GRAY,
     EL_EMC_GATE_8_GRAY,
+    EL_EMC_GATE_5_GRAY_ACTIVE,
+    EL_EMC_GATE_6_GRAY_ACTIVE,
+    EL_EMC_GATE_7_GRAY_ACTIVE,
+    EL_EMC_GATE_8_GRAY_ACTIVE,
     -1
   };
 
@@ -3103,6 +3142,7 @@ void InitElementPropertiesStatic()
     EL_AMOEBA_DRY,
     EL_AMOEBA_FULL,
     EL_BD_AMOEBA,
+    EL_EMC_MAGIC_BALL,
     -1
   };
 
@@ -3167,6 +3207,10 @@ void InitElementPropertiesStatic()
     EL_GATE_2_GRAY,
     EL_GATE_3_GRAY,
     EL_GATE_4_GRAY,
+    EL_GATE_1_GRAY_ACTIVE,
+    EL_GATE_2_GRAY_ACTIVE,
+    EL_GATE_3_GRAY_ACTIVE,
+    EL_GATE_4_GRAY_ACTIVE,
     EL_EM_GATE_1,
     EL_EM_GATE_2,
     EL_EM_GATE_3,
@@ -3175,6 +3219,10 @@ void InitElementPropertiesStatic()
     EL_EM_GATE_2_GRAY,
     EL_EM_GATE_3_GRAY,
     EL_EM_GATE_4_GRAY,
+    EL_EM_GATE_1_GRAY_ACTIVE,
+    EL_EM_GATE_2_GRAY_ACTIVE,
+    EL_EM_GATE_3_GRAY_ACTIVE,
+    EL_EM_GATE_4_GRAY_ACTIVE,
     EL_EMC_GATE_5,
     EL_EMC_GATE_6,
     EL_EMC_GATE_7,
@@ -3183,6 +3231,10 @@ void InitElementPropertiesStatic()
     EL_EMC_GATE_6_GRAY,
     EL_EMC_GATE_7_GRAY,
     EL_EMC_GATE_8_GRAY,
+    EL_EMC_GATE_5_GRAY_ACTIVE,
+    EL_EMC_GATE_6_GRAY_ACTIVE,
+    EL_EMC_GATE_7_GRAY_ACTIVE,
+    EL_EMC_GATE_8_GRAY_ACTIVE,
     EL_DYNAMITE,
     EL_INVISIBLE_STEELWALL,
     EL_INVISIBLE_WALL,
@@ -3321,74 +3373,115 @@ void InitElementPropertiesStatic()
     -1
   };
 
+  static int ep_editor_cascade_active[] =
+  {
+    EL_INTERNAL_CASCADE_BD_ACTIVE,
+    EL_INTERNAL_CASCADE_EM_ACTIVE,
+    EL_INTERNAL_CASCADE_EMC_ACTIVE,
+    EL_INTERNAL_CASCADE_RND_ACTIVE,
+    EL_INTERNAL_CASCADE_SB_ACTIVE,
+    EL_INTERNAL_CASCADE_SP_ACTIVE,
+    EL_INTERNAL_CASCADE_DC_ACTIVE,
+    EL_INTERNAL_CASCADE_DX_ACTIVE,
+    EL_INTERNAL_CASCADE_CHARS_ACTIVE,
+    EL_INTERNAL_CASCADE_CE_ACTIVE,
+    EL_INTERNAL_CASCADE_GE_ACTIVE,
+    EL_INTERNAL_CASCADE_USER_ACTIVE,
+    EL_INTERNAL_CASCADE_GENERIC_ACTIVE,
+    EL_INTERNAL_CASCADE_DYNAMIC_ACTIVE,
+    -1
+  };
+
+  static int ep_editor_cascade_inactive[] =
+  {
+    EL_INTERNAL_CASCADE_BD,
+    EL_INTERNAL_CASCADE_EM,
+    EL_INTERNAL_CASCADE_EMC,
+    EL_INTERNAL_CASCADE_RND,
+    EL_INTERNAL_CASCADE_SB,
+    EL_INTERNAL_CASCADE_SP,
+    EL_INTERNAL_CASCADE_DC,
+    EL_INTERNAL_CASCADE_DX,
+    EL_INTERNAL_CASCADE_CHARS,
+    EL_INTERNAL_CASCADE_CE,
+    EL_INTERNAL_CASCADE_GE,
+    EL_INTERNAL_CASCADE_USER,
+    EL_INTERNAL_CASCADE_GENERIC,
+    EL_INTERNAL_CASCADE_DYNAMIC,
+    -1
+  };
+
   static struct
   {
     int *elements;
     int property;
   } element_properties[] =
   {
-    { ep_diggable,             EP_DIGGABLE             },
-    { ep_collectible_only,     EP_COLLECTIBLE_ONLY     },
-    { ep_dont_run_into,                EP_DONT_RUN_INTO        },
-    { ep_dont_collide_with,    EP_DONT_COLLIDE_WITH    },
-    { ep_dont_touch,           EP_DONT_TOUCH           },
-    { ep_indestructible,       EP_INDESTRUCTIBLE       },
-    { ep_slippery,             EP_SLIPPERY             },
-    { ep_can_change,           EP_CAN_CHANGE           },
-    { ep_can_move,             EP_CAN_MOVE             },
-    { ep_can_fall,             EP_CAN_FALL             },
-    { ep_can_smash_player,     EP_CAN_SMASH_PLAYER     },
-    { ep_can_smash_enemies,    EP_CAN_SMASH_ENEMIES    },
-    { ep_can_smash_everything, EP_CAN_SMASH_EVERYTHING },
-    { ep_explodes_by_fire,     EP_EXPLODES_BY_FIRE     },
-    { ep_explodes_smashed,     EP_EXPLODES_SMASHED     },
-    { ep_explodes_impact,      EP_EXPLODES_IMPACT      },
-    { ep_walkable_over,                EP_WALKABLE_OVER        },
-    { ep_walkable_inside,      EP_WALKABLE_INSIDE      },
-    { ep_walkable_under,       EP_WALKABLE_UNDER       },
-    { ep_passable_over,                EP_PASSABLE_OVER        },
-    { ep_passable_inside,      EP_PASSABLE_INSIDE      },
-    { ep_passable_under,       EP_PASSABLE_UNDER       },
-    { ep_droppable,            EP_DROPPABLE            },
-    { ep_explodes_1x1_old,     EP_EXPLODES_1X1_OLD     },
-    { ep_pushable,             EP_PUSHABLE             },
-    { ep_explodes_cross_old,   EP_EXPLODES_CROSS_OLD   },
-    { ep_protected,            EP_PROTECTED            },
-    { ep_throwable,            EP_THROWABLE            },
-    { ep_can_explode,          EP_CAN_EXPLODE          },
-    { ep_gravity_reachable,    EP_GRAVITY_REACHABLE    },
-
-    { ep_player,               EP_PLAYER               },
-    { ep_can_pass_magic_wall,  EP_CAN_PASS_MAGIC_WALL  },
-    { ep_switchable,           EP_SWITCHABLE           },
-    { ep_bd_element,           EP_BD_ELEMENT           },
-    { ep_sp_element,           EP_SP_ELEMENT           },
-    { ep_sb_element,           EP_SB_ELEMENT           },
-    { ep_gem,                  EP_GEM                  },
-    { ep_food_dark_yamyam,     EP_FOOD_DARK_YAMYAM     },
-    { ep_food_penguin,         EP_FOOD_PENGUIN         },
-    { ep_food_pig,             EP_FOOD_PIG             },
-    { ep_historic_wall,                EP_HISTORIC_WALL        },
-    { ep_historic_solid,       EP_HISTORIC_SOLID       },
-    { ep_classic_enemy,                EP_CLASSIC_ENEMY        },
-    { ep_belt,                 EP_BELT                 },
-    { ep_belt_active,          EP_BELT_ACTIVE          },
-    { ep_belt_switch,          EP_BELT_SWITCH          },
-    { ep_tube,                 EP_TUBE                 },
-    { ep_keygate,              EP_KEYGATE              },
-    { ep_amoeboid,             EP_AMOEBOID             },
-    { ep_amoebalive,           EP_AMOEBALIVE           },
-    { ep_has_content,          EP_HAS_CONTENT          },
-    { ep_can_turn_each_move,   EP_CAN_TURN_EACH_MOVE   },
-    { ep_can_grow,             EP_CAN_GROW             },
-    { ep_active_bomb,          EP_ACTIVE_BOMB          },
-    { ep_inactive,             EP_INACTIVE             },
-
-    { ep_em_slippery_wall,     EP_EM_SLIPPERY_WALL     },
-
-    { ep_gfx_crumbled,         EP_GFX_CRUMBLED         },
-
-    { NULL,                    -1                      }
+    { ep_diggable,                     EP_DIGGABLE                     },
+    { ep_collectible_only,             EP_COLLECTIBLE_ONLY             },
+    { ep_dont_run_into,                        EP_DONT_RUN_INTO                },
+    { ep_dont_collide_with,            EP_DONT_COLLIDE_WITH            },
+    { ep_dont_touch,                   EP_DONT_TOUCH                   },
+    { ep_indestructible,               EP_INDESTRUCTIBLE               },
+    { ep_slippery,                     EP_SLIPPERY                     },
+    { ep_can_change,                   EP_CAN_CHANGE                   },
+    { ep_can_move,                     EP_CAN_MOVE                     },
+    { ep_can_fall,                     EP_CAN_FALL                     },
+    { ep_can_smash_player,             EP_CAN_SMASH_PLAYER             },
+    { ep_can_smash_enemies,            EP_CAN_SMASH_ENEMIES            },
+    { ep_can_smash_everything,         EP_CAN_SMASH_EVERYTHING         },
+    { ep_explodes_by_fire,             EP_EXPLODES_BY_FIRE             },
+    { ep_explodes_smashed,             EP_EXPLODES_SMASHED             },
+    { ep_explodes_impact,              EP_EXPLODES_IMPACT              },
+    { ep_walkable_over,                        EP_WALKABLE_OVER                },
+    { ep_walkable_inside,              EP_WALKABLE_INSIDE              },
+    { ep_walkable_under,               EP_WALKABLE_UNDER               },
+    { ep_passable_over,                        EP_PASSABLE_OVER                },
+    { ep_passable_inside,              EP_PASSABLE_INSIDE              },
+    { ep_passable_under,               EP_PASSABLE_UNDER               },
+    { ep_droppable,                    EP_DROPPABLE                    },
+    { ep_explodes_1x1_old,             EP_EXPLODES_1X1_OLD             },
+    { ep_pushable,                     EP_PUSHABLE                     },
+    { ep_explodes_cross_old,           EP_EXPLODES_CROSS_OLD           },
+    { ep_protected,                    EP_PROTECTED                    },
+    { ep_throwable,                    EP_THROWABLE                    },
+    { ep_can_explode,                  EP_CAN_EXPLODE                  },
+    { ep_gravity_reachable,            EP_GRAVITY_REACHABLE            },
+
+    { ep_player,                       EP_PLAYER                       },
+    { ep_can_pass_magic_wall,          EP_CAN_PASS_MAGIC_WALL          },
+    { ep_switchable,                   EP_SWITCHABLE                   },
+    { ep_bd_element,                   EP_BD_ELEMENT                   },
+    { ep_sp_element,                   EP_SP_ELEMENT                   },
+    { ep_sb_element,                   EP_SB_ELEMENT                   },
+    { ep_gem,                          EP_GEM                          },
+    { ep_food_dark_yamyam,             EP_FOOD_DARK_YAMYAM             },
+    { ep_food_penguin,                 EP_FOOD_PENGUIN                 },
+    { ep_food_pig,                     EP_FOOD_PIG                     },
+    { ep_historic_wall,                        EP_HISTORIC_WALL                },
+    { ep_historic_solid,               EP_HISTORIC_SOLID               },
+    { ep_classic_enemy,                        EP_CLASSIC_ENEMY                },
+    { ep_belt,                         EP_BELT                         },
+    { ep_belt_active,                  EP_BELT_ACTIVE                  },
+    { ep_belt_switch,                  EP_BELT_SWITCH                  },
+    { ep_tube,                         EP_TUBE                         },
+    { ep_keygate,                      EP_KEYGATE                      },
+    { ep_amoeboid,                     EP_AMOEBOID                     },
+    { ep_amoebalive,                   EP_AMOEBALIVE                   },
+    { ep_has_content,                  EP_HAS_CONTENT                  },
+    { ep_can_turn_each_move,           EP_CAN_TURN_EACH_MOVE           },
+    { ep_can_grow,                     EP_CAN_GROW                     },
+    { ep_active_bomb,                  EP_ACTIVE_BOMB                  },
+    { ep_inactive,                     EP_INACTIVE                     },
+
+    { ep_em_slippery_wall,             EP_EM_SLIPPERY_WALL             },
+
+    { ep_gfx_crumbled,                 EP_GFX_CRUMBLED                 },
+
+    { ep_editor_cascade_active,                EP_EDITOR_CASCADE_ACTIVE        },
+    { ep_editor_cascade_inactive,      EP_EDITOR_CASCADE_INACTIVE      },
+
+    { NULL,                            -1                              }
   };
 
   int i, j, k;
@@ -3616,6 +3709,10 @@ void InitElementPropertiesEngine(int engine_version)
     SET_PROPERTY(i, EP_GFX_CRUMBLED,
                 element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
 #endif
+
+    /* ---------- EDITOR_CASCADE ------------------------------------------- */
+    SET_PROPERTY(i, EP_EDITOR_CASCADE, (IS_EDITOR_CASCADE_ACTIVE(i) ||
+                                       IS_EDITOR_CASCADE_INACTIVE(i)));
   }
 
   /* dynamically adjust element properties according to game engine version */
@@ -3774,6 +3871,10 @@ void Execute_Command(char *command)
     printf("# (The entries below are default and therefore commented out.)\n");
     printf("\n");
 
+    /* this is needed to be able to check element list for cascade elements */
+    InitElementPropertiesStatic();
+    InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
+
     PrintEditorElementList();
 
     exit(0);