rnd-20040222-1-src
[rocksndiamonds.git] / src / init.c
index 69158a75d27e6a3a7d7f022949d1a80de955630f..40b6417a04d32f6218f0c8efb5862833196ddeb6 100644 (file)
@@ -598,7 +598,7 @@ void InitElementGraphicInfo()
     int default_direction_crumbled[NUM_DIRECTIONS];
 
     if (default_graphic == -1)
-      default_graphic = IMG_CHAR_QUESTION;
+      default_graphic = IMG_UNKNOWN;
     if (default_crumbled == -1)
       default_crumbled = IMG_EMPTY;
 
@@ -732,8 +732,8 @@ void InitElementGraphicInfo()
   if (options.verbose)
   {
     for (i = 0; i < MAX_NUM_ELEMENTS; i++)
-      if (element_info[i].graphic[ACTION_DEFAULT] == IMG_CHAR_QUESTION &&
-         i != EL_CHAR_QUESTION)
+      if (element_info[i].graphic[ACTION_DEFAULT] == IMG_UNKNOWN &&
+         i != EL_UNKNOWN)
        Error(ERR_RETURN, "warning: no graphic for element '%s' (%d)",
              element_info[i].token_name, i);
   }
@@ -1569,6 +1569,92 @@ static void ReinitializeMusic()
   InitGameModeMusicInfo();     /* game mode music mapping */
 }
 
+static int get_special_property_bit(int element, int base_property_bit)
+{
+  static struct
+  {
+    int element;
+    int bit_nr;
+  } pb_can_move_into_acid[] =
+  {
+    { EL_BUG,                  0 },
+    { EL_BUG_LEFT,             0 },
+    { EL_BUG_RIGHT,            0 },
+    { EL_BUG_UP,               0 },
+    { EL_BUG_DOWN,             0 },
+    { EL_SPACESHIP,            0 },
+    { EL_SPACESHIP_LEFT,       0 },
+    { EL_SPACESHIP_RIGHT,      0 },
+    { EL_SPACESHIP_UP,         0 },
+    { EL_SPACESHIP_DOWN,       0 },
+    { EL_BD_BUTTERFLY,         1 },
+    { EL_BD_BUTTERFLY_LEFT,    1 },
+    { EL_BD_BUTTERFLY_RIGHT,   1 },
+    { EL_BD_BUTTERFLY_UP,      1 },
+    { EL_BD_BUTTERFLY_DOWN,    1 },
+    { EL_BD_FIREFLY,           1 },
+    { EL_BD_FIREFLY_LEFT,      1 },
+    { EL_BD_FIREFLY_RIGHT,     1 },
+    { EL_BD_FIREFLY_UP,                1 },
+    { EL_BD_FIREFLY_DOWN,      1 },
+    { EL_YAMYAM,               2 },
+    { EL_DARK_YAMYAM,          2 },
+    { EL_ROBOT,                        3 },
+    { EL_PACMAN,               4 },
+    { EL_PACMAN_LEFT,          4 },
+    { EL_PACMAN_RIGHT,         4 },
+    { EL_PACMAN_UP,            4 },
+    { EL_PACMAN_DOWN,          4 },
+    { EL_MOLE,                 4 },
+    { EL_MOLE_LEFT,            4 },
+    { EL_MOLE_RIGHT,           4 },
+    { EL_MOLE_UP,              4 },
+    { EL_MOLE_DOWN,            4 },
+    { EL_PENGUIN,              5 },
+    { EL_PIG,                  6 },
+    { EL_DRAGON,               6 },
+    { EL_SATELLITE,            7 },
+    { EL_SP_SNIKSNAK,          8 },
+    { EL_SP_ELECTRON,          8 },
+    { EL_BALLOON,              9 },
+
+    { -1,                      0 },
+  };
+  int i;
+
+  if (base_property_bit != EP_CAN_MOVE_INTO_ACID)
+    return -1;
+
+  for (i = 0; pb_can_move_into_acid[i].element != -1; i++)
+    if (pb_can_move_into_acid[i].element == element)
+      return pb_can_move_into_acid[i].bit_nr;
+
+  return -1;
+}
+
+void setMoveIntoAcidProperty(struct LevelInfo *level, int element, boolean set)
+{
+  int bit_nr = get_special_property_bit(element, EP_CAN_MOVE_INTO_ACID);
+
+  if (bit_nr > -1)
+  {
+    level->can_move_into_acid &= ~(1 << bit_nr);
+
+    if (set)
+      level->can_move_into_acid |= (1 << bit_nr);
+  }
+}
+
+boolean getMoveIntoAcidProperty(struct LevelInfo *level, int element)
+{
+  int bit_nr = get_special_property_bit(element, EP_CAN_MOVE_INTO_ACID);
+
+  if (bit_nr > -1)
+    return ((level->can_move_into_acid & (1 << bit_nr)) != 0);
+
+  return FALSE;
+}
+
 void InitElementPropertiesStatic()
 {
   static int ep_diggable[] =
@@ -1945,6 +2031,9 @@ void InitElementPropertiesStatic()
     EL_SP_DISK_YELLOW,
     EL_SP_SNIKSNAK,
     EL_SP_ELECTRON,
+#if 0
+    EL_BLACK_ORB,
+#endif
     -1
   };
 
@@ -2084,6 +2173,21 @@ void InitElementPropertiesStatic()
     -1
   };
 
+  static int ep_protected[] =
+  {
+    EL_EM_GATE_1,
+    EL_EM_GATE_2,
+    EL_EM_GATE_3,
+    EL_EM_GATE_4,
+    EL_EM_GATE_1_GRAY,
+    EL_EM_GATE_2_GRAY,
+    EL_EM_GATE_3_GRAY,
+    EL_EM_GATE_4_GRAY,
+    EL_SWITCHGATE_OPEN,
+    EL_TIMEGATE_OPEN,
+    -1
+  };
+
   static int ep_player[] =
   {
     EL_PLAYER_1,
@@ -2164,6 +2268,7 @@ void InitElementPropertiesStatic()
     EL_BD_BUTTERFLY_4,
     EL_BD_AMOEBA,
     EL_CHAR_QUESTION,
+    EL_UNKNOWN,
     -1
   };
 
@@ -2856,6 +2961,7 @@ void InitElementPropertiesStatic()
     { ep_can_explode_1x1,      EP_CAN_EXPLODE_1X1      },
     { ep_pushable,             EP_PUSHABLE             },
     { ep_can_explode_dyna,     EP_CAN_EXPLODE_DYNA     },
+    { ep_protected,            EP_PROTECTED            },
 
     { ep_player,               EP_PLAYER               },
     { ep_can_pass_magic_wall,  EP_CAN_PASS_MAGIC_WALL  },
@@ -2915,6 +3021,11 @@ void InitElementPropertiesStatic()
       EL_PACMAN_LEFT,          EL_PACMAN_RIGHT,
       EL_PACMAN_UP,            EL_PACMAN_DOWN
     },
+    {
+      EL_MOLE,
+      EL_MOLE_LEFT,            EL_MOLE_RIGHT,
+      EL_MOLE_UP,              EL_MOLE_DOWN
+    },
     {
       -1,
       -1, -1, -1, -1
@@ -3001,6 +3112,7 @@ void InitElementPropertiesEngine(int engine_version)
     EP_ACTIVE_BOMB,
 
     EP_ACCESSIBLE,
+
     -1
   };
 
@@ -3010,6 +3122,12 @@ void InitElementPropertiesEngine(int engine_version)
   InitElementPropertiesStatic();
 #endif
 
+  /* important: after initialization in InitElementPropertiesStatic(), the
+     elements are not again initialized to a default value; therefore all
+     changes have to make sure that they leave the element with a defined
+     property (which means that conditional property changes must be set to
+     a reliable default value before) */
+
   /* set all special, combined or engine dependent element properties */
   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
   {
@@ -3019,8 +3137,7 @@ void InitElementPropertiesEngine(int engine_version)
 #endif
 
     /* ---------- INACTIVE ------------------------------------------------- */
-    if (i >= EL_CHAR_START && i <= EL_CHAR_END)
-      SET_PROPERTY(i, EP_INACTIVE, TRUE);
+    SET_PROPERTY(i, EP_INACTIVE, (i >= EL_CHAR_START && i <= EL_CHAR_END));
 
     /* ---------- WALKABLE, PASSABLE, ACCESSIBLE --------------------------- */
     SET_PROPERTY(i, EP_WALKABLE, (IS_WALKABLE_OVER(i) ||
@@ -3072,6 +3189,12 @@ void InitElementPropertiesEngine(int engine_version)
                                             !IS_DIGGABLE(i) &&
                                             !IS_COLLECTIBLE(i)));
 
+#if 1
+    /* ---------- PROTECTED ------------------------------------------------ */
+    if (IS_ACCESSIBLE_INSIDE(i))
+      SET_PROPERTY(i, EP_PROTECTED, TRUE);
+#endif
+
     /* ---------- DRAGONFIRE_PROOF ----------------------------------------- */
 
     if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
@@ -3086,12 +3209,25 @@ void InitElementPropertiesEngine(int engine_version)
     else if (engine_version < VERSION_IDENT(2,2,0,0))
       SET_PROPERTY(i, EP_EXPLOSION_PROOF, IS_INDESTRUCTIBLE(i));
     else
+#if 1
+      SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
+                                          (!IS_WALKABLE(i) ||
+                                           IS_PROTECTED(i))));
+#else
+#if 1
       SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
                                           !IS_WALKABLE_OVER(i) &&
                                           !IS_WALKABLE_UNDER(i)));
+#else
+      SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
+                                          IS_PROTECTED(i)));
+#endif
+#endif
 
     if (IS_CUSTOM_ELEMENT(i))
     {
+      /* these are additional properties which are initially false when set */
+
       /* ---------- DONT_COLLIDE_WITH / DONT_RUN_INTO ---------------------- */
       if (DONT_TOUCH(i))
        SET_PROPERTY(i, EP_DONT_COLLIDE_WITH, TRUE);
@@ -3120,6 +3256,21 @@ void InitElementPropertiesEngine(int engine_version)
                                         !CAN_EXPLODE_1X1(i) &&
                                         !CAN_EXPLODE_DYNA(i)));
 
+    /* ---------- CAN_EXPLODE_BY_DRAGONFIRE -------------------------------- */
+    SET_PROPERTY(i, EP_CAN_EXPLODE_BY_DRAGONFIRE, CAN_EXPLODE_BY_FIRE(i));
+
+    /* ---------- CAN_EXPLODE_BY_EXPLOSION --------------------------------- */
+    SET_PROPERTY(i, EP_CAN_EXPLODE_BY_EXPLOSION, (CAN_EXPLODE_BY_FIRE(i) ||
+                                                 i == EL_BLACK_ORB));
+
+    /* ---------- COULD_MOVE_INTO_ACID ------------------------------------- */
+    SET_PROPERTY(i, EP_COULD_MOVE_INTO_ACID, ((CAN_MOVE(i) && i != EL_SPRING)||
+                                             IS_CUSTOM_ELEMENT(i)));
+
+    /* ---------- CAN_MOVE_INTO_ACID --------------------------------------- */
+    if (!IS_CUSTOM_ELEMENT(i))
+      SET_PROPERTY(i, EP_CAN_MOVE_INTO_ACID,getMoveIntoAcidProperty(&level,i));
+
     /* ---------- SP_PORT -------------------------------------------------- */
     SET_PROPERTY(i, EP_SP_PORT, (IS_SP_ELEMENT(i) &&
                                 IS_PASSABLE_INSIDE(i)));
@@ -3210,6 +3361,20 @@ void InitElementPropertiesEngine(int engine_version)
     if (element_info[element].push_delay_random == -1)
       element_info[element].push_delay_random = game.default_push_delay_random;
   }
+
+  /* set some other uninitialized values of custom elements in older levels */
+  if (engine_version < VERSION_IDENT(3,0,9,0))
+  {
+    for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+    {
+      int element = EL_CUSTOM_START + i;
+
+      element_info[element].access_direction = MV_ALL_DIRECTIONS;
+
+      element_info[element].explosion_delay = 18;
+      element_info[element].ignition_delay = 8;
+    }
+  }
 #endif
 
   /* this is needed because some graphics depend on element properties */