rnd-20040419-1-src
[rocksndiamonds.git] / src / init.c
index 40b6417a04d32f6218f0c8efb5862833196ddeb6..58595e5bc3448146d15a624f3eac5705e94cdef0 100644 (file)
@@ -440,14 +440,15 @@ void InitElementGraphicInfo()
     int direction    = element_to_graphic[i].direction;
     boolean crumbled = element_to_graphic[i].crumbled;
     int graphic      = element_to_graphic[i].graphic;
+    int base_graphic = el2baseimg(element);
 
     if (graphic_info[graphic].bitmap == NULL)
       continue;
 
     if ((action > -1 || direction > -1 || crumbled == TRUE) &&
-       el2img(element) != -1)
+       base_graphic != -1)
     {
-      boolean base_redefined = getImageListEntry(el2img(element))->redefined;
+      boolean base_redefined = getImageListEntry(base_graphic)->redefined;
       boolean act_dir_redefined = getImageListEntry(graphic)->redefined;
 
       /* if the base graphic ("emerald", for example) has been redefined,
@@ -759,7 +760,8 @@ void InitElementSpecialGraphicInfo()
     int element = element_to_special_graphic[i].element;
     int special = element_to_special_graphic[i].special;
     int graphic = element_to_special_graphic[i].graphic;
-    boolean base_redefined = getImageListEntry(el2img(element))->redefined;
+    int base_graphic = el2baseimg(element);
+    boolean base_redefined = getImageListEntry(base_graphic)->redefined;
     boolean special_redefined = getImageListEntry(graphic)->redefined;
 
     /* if the base graphic ("emerald", for example) has been redefined,
@@ -1569,79 +1571,144 @@ static void ReinitializeMusic()
   InitGameModeMusicInfo();     /* game mode music mapping */
 }
 
-static int get_special_property_bit(int element, int base_property_bit)
+static int get_special_property_bit(int element, int property_bit_nr)
 {
-  static struct
+  struct PropertyBitInfo
   {
     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 },
   };
+
+  static struct PropertyBitInfo pb_can_move_into_acid[] =
+  {
+    /* the player may be able fall into acid when gravity is activated */
+    { EL_PLAYER_1,             0       },
+    { EL_PLAYER_2,             0       },
+    { EL_PLAYER_3,             0       },
+    { EL_PLAYER_4,             0       },
+    { EL_SP_MURPHY,            0       },
+    { EL_SOKOBAN_FIELD_PLAYER, 0       },
+
+    /* all element that can move may be able to also move into acid */
+    { EL_BUG,                  1       },
+    { EL_BUG_LEFT,             1       },
+    { EL_BUG_RIGHT,            1       },
+    { EL_BUG_UP,               1       },
+    { EL_BUG_DOWN,             1       },
+    { EL_SPACESHIP,            2       },
+    { EL_SPACESHIP_LEFT,       2       },
+    { EL_SPACESHIP_RIGHT,      2       },
+    { EL_SPACESHIP_UP,         2       },
+    { EL_SPACESHIP_DOWN,       2       },
+    { EL_BD_BUTTERFLY,         3       },
+    { EL_BD_BUTTERFLY_LEFT,    3       },
+    { EL_BD_BUTTERFLY_RIGHT,   3       },
+    { EL_BD_BUTTERFLY_UP,      3       },
+    { EL_BD_BUTTERFLY_DOWN,    3       },
+    { EL_BD_FIREFLY,           4       },
+    { EL_BD_FIREFLY_LEFT,      4       },
+    { EL_BD_FIREFLY_RIGHT,     4       },
+    { EL_BD_FIREFLY_UP,                4       },
+    { EL_BD_FIREFLY_DOWN,      4       },
+    { EL_YAMYAM,               5       },
+    { EL_DARK_YAMYAM,          6       },
+    { EL_ROBOT,                        7       },
+    { EL_PACMAN,               8       },
+    { EL_PACMAN_LEFT,          8       },
+    { EL_PACMAN_RIGHT,         8       },
+    { EL_PACMAN_UP,            8       },
+    { EL_PACMAN_DOWN,          8       },
+    { EL_MOLE,                 9       },
+    { EL_MOLE_LEFT,            9       },
+    { EL_MOLE_RIGHT,           9       },
+    { EL_MOLE_UP,              9       },
+    { EL_MOLE_DOWN,            9       },
+    { EL_PENGUIN,              10      },
+    { EL_PIG,                  11      },
+    { EL_DRAGON,               12      },
+    { EL_SATELLITE,            13      },
+    { EL_SP_SNIKSNAK,          14      },
+    { EL_SP_ELECTRON,          15      },
+    { EL_BALLOON,              16      },
+    { EL_SPRING,               17      },
+
+    { -1,                      -1      },
+  };
+
+  static struct PropertyBitInfo pb_dont_collide_with[] =
+  {
+    { EL_SP_SNIKSNAK,          0       },
+    { EL_SP_ELECTRON,          1       },
+
+    { -1,                      -1      },
+  };
+
+  static struct
+  {
+    int bit_nr;
+    struct PropertyBitInfo *pb_info;
+  } pb_definition[] =
+  {
+    { EP_CAN_MOVE_INTO_ACID,   pb_can_move_into_acid   },
+    { EP_DONT_COLLIDE_WITH,    pb_dont_collide_with    },
+
+    { -1,                      NULL                    },
+  };
+
+  struct PropertyBitInfo *pb_info = NULL;
   int i;
 
-  if (base_property_bit != EP_CAN_MOVE_INTO_ACID)
+  for (i = 0; pb_definition[i].bit_nr != -1; i++)
+    if (pb_definition[i].bit_nr == property_bit_nr)
+      pb_info = pb_definition[i].pb_info;
+
+  if (pb_info == NULL)
     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;
+  for (i = 0; pb_info[i].element != -1; i++)
+    if (pb_info[i].element == element)
+      return pb_info[i].bit_nr;
 
   return -1;
 }
 
+#if 1
+void setBitfieldProperty(int *bitfield, int property_bit_nr, int element,
+                        boolean property_value)
+{
+  int bit_nr = get_special_property_bit(element, property_bit_nr);
+
+  if (bit_nr > -1)
+  {
+    if (property_value)
+      *bitfield |=  (1 << bit_nr);
+    else
+      *bitfield &= ~(1 << bit_nr);
+  }
+}
+
+boolean getBitfieldProperty(int *bitfield, int property_bit_nr, int element)
+{
+  int bit_nr = get_special_property_bit(element, property_bit_nr);
+
+  if (bit_nr > -1)
+    return ((*bitfield & (1 << bit_nr)) != 0);
+
+  return FALSE;
+}
+
+#else
+
 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);
+    level->can_move_into_acid_bits &= ~(1 << bit_nr);
 
     if (set)
-      level->can_move_into_acid |= (1 << bit_nr);
+      level->can_move_into_acid_bits |= (1 << bit_nr);
   }
 }
 
@@ -1650,10 +1717,11 @@ 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 ((level->can_move_into_acid_bits & (1 << bit_nr)) != 0);
 
   return FALSE;
 }
+#endif
 
 void InitElementPropertiesStatic()
 {
@@ -1668,6 +1736,7 @@ void InitElementPropertiesStatic()
     EL_INVISIBLE_SAND_ACTIVE,
 
     /* !!! currently not diggable, but handled by 'ep_dont_run_into' !!! */
+    /* (if amoeba can grow into anything diggable, maybe keep these out) */
 #if 0
     EL_LANDMINE,
     EL_TRAP_ACTIVE,
@@ -1912,6 +1981,7 @@ void InitElementPropertiesStatic()
 
   static int ep_can_move[] =
   {
+    /* same elements as in 'pb_can_move_into_acid' */
     EL_BUG,
     EL_SPACESHIP,
     EL_BD_BUTTERFLY,
@@ -2168,7 +2238,7 @@ void InitElementPropertiesStatic()
     -1
   };
 
-  static int ep_can_explode_dyna[] =
+  static int ep_can_explode_cross[] =
   {
     -1
   };
@@ -2188,6 +2258,11 @@ void InitElementPropertiesStatic()
     -1
   };
 
+  static int ep_throwable[] =
+  {
+    -1
+  };
+
   static int ep_player[] =
   {
     EL_PLAYER_1,
@@ -2195,6 +2270,8 @@ void InitElementPropertiesStatic()
     EL_PLAYER_3,
     EL_PLAYER_4,
     EL_SP_MURPHY,
+    EL_SOKOBAN_FIELD_PLAYER,
+    EL_TRIGGER_PLAYER,
     -1
   };
 
@@ -2256,6 +2333,9 @@ void InitElementPropertiesStatic()
     EL_EXIT_OPEN,
     EL_STEELWALL,
     EL_PLAYER_1,
+    EL_PLAYER_2,
+    EL_PLAYER_3,
+    EL_PLAYER_4,
     EL_BD_FIREFLY,
     EL_BD_FIREFLY_1,
     EL_BD_FIREFLY_2,
@@ -2339,7 +2419,11 @@ void InitElementPropertiesStatic()
     EL_SOKOBAN_OBJECT,
     EL_SOKOBAN_FIELD_EMPTY,
     EL_SOKOBAN_FIELD_FULL,
+    EL_SOKOBAN_FIELD_PLAYER,
     EL_PLAYER_1,
+    EL_PLAYER_2,
+    EL_PLAYER_3,
+    EL_PLAYER_4,
     EL_INVISIBLE_STEELWALL,
     -1
   };
@@ -2764,6 +2848,24 @@ void InitElementPropertiesStatic()
     -1
   };
 
+  static int ep_can_turn_each_move[] =
+  {
+    /* !!! do something with this one !!! */
+    -1
+  };
+
+  static int ep_can_grow[] =
+  {
+    EL_BD_AMOEBA,
+    EL_AMOEBA_DROP,
+    EL_AMOEBA_WET,
+    EL_AMOEBA_DRY,
+    EL_AMOEBA_FULL,
+    EL_GAME_OF_LIFE,
+    EL_BIOMAZE,
+    -1
+  };
+
   static int ep_active_bomb[] =
   {
     EL_DYNAMITE_ACTIVE,
@@ -2960,8 +3062,9 @@ void InitElementPropertiesStatic()
     { ep_droppable,            EP_DROPPABLE            },
     { ep_can_explode_1x1,      EP_CAN_EXPLODE_1X1      },
     { ep_pushable,             EP_PUSHABLE             },
-    { ep_can_explode_dyna,     EP_CAN_EXPLODE_DYNA     },
+    { ep_can_explode_cross,    EP_CAN_EXPLODE_CROSS    },
     { ep_protected,            EP_PROTECTED            },
+    { ep_throwable,            EP_THROWABLE            },
 
     { ep_player,               EP_PLAYER               },
     { ep_can_pass_magic_wall,  EP_CAN_PASS_MAGIC_WALL  },
@@ -2984,6 +3087,8 @@ void InitElementPropertiesStatic()
     { 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             },
 
@@ -3162,7 +3267,8 @@ void InitElementPropertiesEngine(int engine_version)
 
     /* ---------- COLLECTIBLE ---------------------------------------------- */
     SET_PROPERTY(i, EP_COLLECTIBLE, (IS_COLLECTIBLE_ONLY(i) ||
-                                    IS_DROPPABLE(i)));
+                                    IS_DROPPABLE(i) ||
+                                    IS_THROWABLE(i)));
 
     /* ---------- SNAPPABLE ------------------------------------------------ */
     SET_PROPERTY(i, EP_SNAPPABLE, (IS_DIGGABLE(i) ||
@@ -3254,7 +3360,7 @@ void InitElementPropertiesEngine(int engine_version)
     /* ---------- CAN_EXPLODE_3X3 ------------------------------------------ */
     SET_PROPERTY(i, EP_CAN_EXPLODE_3X3, (CAN_EXPLODE(i) &&
                                         !CAN_EXPLODE_1X1(i) &&
-                                        !CAN_EXPLODE_DYNA(i)));
+                                        !CAN_EXPLODE_CROSS(i)));
 
     /* ---------- CAN_EXPLODE_BY_DRAGONFIRE -------------------------------- */
     SET_PROPERTY(i, EP_CAN_EXPLODE_BY_DRAGONFIRE, CAN_EXPLODE_BY_FIRE(i));
@@ -3264,12 +3370,23 @@ void InitElementPropertiesEngine(int engine_version)
                                                  i == EL_BLACK_ORB));
 
     /* ---------- COULD_MOVE_INTO_ACID ------------------------------------- */
-    SET_PROPERTY(i, EP_COULD_MOVE_INTO_ACID, ((CAN_MOVE(i) && i != EL_SPRING)||
+    SET_PROPERTY(i, EP_COULD_MOVE_INTO_ACID, (ELEM_IS_PLAYER(i) ||
+                                             CAN_MOVE(i) ||
                                              IS_CUSTOM_ELEMENT(i)));
 
+    /* ---------- MAYBE_DONT_COLLIDE_WITH ---------------------------------- */
+    SET_PROPERTY(i, EP_MAYBE_DONT_COLLIDE_WITH, (i == EL_SP_SNIKSNAK ||
+                                                i == EL_SP_ELECTRON));
+
     /* ---------- CAN_MOVE_INTO_ACID --------------------------------------- */
-    if (!IS_CUSTOM_ELEMENT(i))
-      SET_PROPERTY(i, EP_CAN_MOVE_INTO_ACID,getMoveIntoAcidProperty(&level,i));
+    if (COULD_MOVE_INTO_ACID(i) && !IS_CUSTOM_ELEMENT(i))
+      SET_PROPERTY(i, EP_CAN_MOVE_INTO_ACID,
+                  getMoveIntoAcidProperty(&level, i));
+
+    /* ---------- DONT_COLLIDE_WITH ---------------------------------------- */
+    if (MAYBE_DONT_COLLIDE_WITH(i))
+      SET_PROPERTY(i, EP_DONT_COLLIDE_WITH,
+                  getDontCollideWithProperty(&level, i));
 
     /* ---------- SP_PORT -------------------------------------------------- */
     SET_PROPERTY(i, EP_SP_PORT, (IS_SP_ELEMENT(i) &&
@@ -3280,7 +3397,7 @@ void InitElementPropertiesEngine(int engine_version)
       printf("::: %d, %d, %d -> %d\n",
             CAN_EXPLODE_1X1(i),
             CAN_EXPLODE_3X3(i),
-            CAN_EXPLODE_DYNA(i),
+            CAN_EXPLODE_CROSS(i),
             CAN_EXPLODE(i));
 #endif
 
@@ -3363,7 +3480,7 @@ void InitElementPropertiesEngine(int engine_version)
   }
 
   /* set some other uninitialized values of custom elements in older levels */
-  if (engine_version < VERSION_IDENT(3,0,9,0))
+  if (engine_version < VERSION_IDENT(3,1,0,0))
   {
     for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
     {
@@ -3371,10 +3488,20 @@ void InitElementPropertiesEngine(int engine_version)
 
       element_info[element].access_direction = MV_ALL_DIRECTIONS;
 
-      element_info[element].explosion_delay = 18;
+      element_info[element].explosion_delay = 17;
       element_info[element].ignition_delay = 8;
     }
   }
+
+#if 0
+  /* set element properties that were handled incorrectly in older levels */
+  if (engine_version < VERSION_IDENT(3,1,0,0))
+  {
+    SET_PROPERTY(EL_SP_SNIKSNAK, EP_DONT_COLLIDE_WITH, FALSE);
+    SET_PROPERTY(EL_SP_ELECTRON, EP_DONT_COLLIDE_WITH, FALSE);
+  }
+#endif
+
 #endif
 
   /* this is needed because some graphics depend on element properties */