rnd-20040313-1-src
authorHolger Schemel <info@artsoft.org>
Sat, 13 Mar 2004 10:01:25 +0000 (11:01 +0100)
committerHolger Schemel <info@artsoft.org>
Sat, 30 Aug 2014 08:46:14 +0000 (10:46 +0200)
* "can move into acid" property now for all elements independently
* "can fall into acid" property for player stored in same bitfield now
* added option for deadliness for sp_sniksnak and sp_electron
* version number set to 3.1.0 (finally!)

ChangeLog
src/conftime.h
src/editor.c
src/files.c
src/game.c
src/init.c
src/init.h
src/main.h

index ef2f864552813a5f0544b85849a313df2a6d7a07..438cbfc310b5512cb4977e9cc1b836fa06ec9413 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,11 @@
+2004-03-13
+       * "can move into acid" property now for all elements independently
+       * "can fall into acid" property for player stored in same bitfield now
+       * added option for deadliness for sp_sniksnak and sp_electron
+       * version number set to 3.1.0 (finally!)
+
 2004-03-09
        * changed tape recording to only record input, not programmed actions
-       * YET TO COME ... added option ... for sp_sniksnak and sp_electron
 
 2004-03-08
        * fixed totally broken (every 8th frame skipped) step-by-step recording
        * fixed bug with wrong "Murphy" graphics (when digging etc.)
 
 2003-12-14
-       * Version number set to 3.0.9.
+       * version number set to 3.0.9
 
 2003-12-14
-       * Version 3.0.8 released.
+       * version 3.0.8 released
 
 2003-12-13
        * added function checked_free()
        * enhanced sniksnak turning movement (two steps instead of only one)
 
 2003-11-10
-       * Version number set to 3.0.8.
+       * version number set to 3.0.8
 
 2003-11-10
-       * Version 3.0.7 released.
+       * version 3.0.7 released
 
 2003-11-09
        * fixed reset of player animation frame when, for example,
        * fixed bug with player not getting smashed by rock sometimes
 
 2003-10-06
-       * Version number set to 3.0.7.
+       * version number set to 3.0.7
 
 2003-10-06
-       * Version 3.0.6 released.
+       * version 3.0.6 released
 
 2003-10-05
        * added support for MP3 music for SDL version through SMPEG library
        * fixed element tokens for certain file elements with ".active" etc.
 
 2003-09-29
-       * Version number set to 3.0.6.
+       * version number set to 3.0.6
 
 2003-09-29
-       * Version 3.0.5 released.
+       * version 3.0.5 released
 
 2003-09-28
        * now four envelope elements available
        * enhanced (remaining low-resolution) Supaplex graphics
 
 2003-09-13
-       * Version number set to 3.0.5.
+       * version number set to 3.0.5
 
 2003-09-13
-       * Version 3.0.4 released.
+       * version 3.0.4 released
 
 2003-09-12     src/tools.c
        * fixed bug in custom definition of crumbled element graphics
        * fixed bug in multiple config pages code that caused crashes
 
 2003-09-08
-       * Version number set to 3.0.4.
+       * version number set to 3.0.4
 
 2003-09-08
-       * Version 3.0.3 released.
+       * version 3.0.3 released
 
 2003-09-07
        * added music to Supaplex classic level set
        * fixed bug (missing array boundary check) which could crash the game
 
 2003-08-23
-       * Version number set to 3.0.3.
+       * version number set to 3.0.3
 
 2003-08-22
-       * Version 3.0.2 released.
+       * version 3.0.2 released
 
 2003-08-21     src/game.c
        * fixed bug with creating inaccessible elements at player position
        * fixed bug with messing up custom element properties in 3.0.0 levels
 
 2003-08-18
-       * Version number set to 3.0.2.
+       * version number set to 3.0.2
 
 2003-08-18
-       * Version 3.0.1 released.
+       * version 3.0.1 released
 
 2003-08-17     (no source files affected)
        * changed all "classic" PCX image files with 16 colors or less to
        * fixed bug with missing graphic for active red disk bomb
 
 2003-08-07     src/files.c, src/editor.c src/game.c, src/main.h
-       * Extended variable "level.gravity" to "level.initial_gravity" and
+       * extended variable "level.gravity" to "level.initial_gravity" and
          "game.current_gravity" to prevent level setting from being changed
-         by playing the level (keeping the runtime value after playing).
+         by playing the level (keeping the runtime value after playing)
 
-       * Fixed graphics bug when digging element that has 'crumbled' graphic
-         definition, but not 'diggable' graphic definition.
+       * fixed graphics bug when digging element that has 'crumbled' graphic
+         definition, but not 'diggable' graphic definition
 
 2003-08-06
-       * Version number set to 3.0.1.
+       * version number set to 3.0.1
 
 2003-08-05
-       * Version 3.0.0 released.
+       * version 3.0.0 released
 
 2003-08-05
        * various bug fixes; among others:
          - allow Murphy player graphic in levels with non-Supaplex elements
 
 2003-04-07
-       * Various changes.
-       * I have forgotten to document changes for some time.
+       * various changes
+       * I have forgotten to document changes for some time
 
 2002-12-31
-       * Pre-Release Version 2.2.0rc1 released.
+       * pre-release version 2.2.0rc1 released
 
 2002-08-25
-       * Version number set to 2.1.2.
+       * version number set to 2.1.2
 
 2002-08-13
-       * Version 2.1.1 released.
+       * version 2.1.1 released
 
 2002-08-10
-       * Version number set to 2.1.1.
+       * version number set to 2.1.1
 
 2002-08-05
-       * Version 2.1.0 released.
+       * version 2.1.0 released
        
 2002-05-19
-       * Version number set to 2.1.0.
+       * version number set to 2.1.0
 
 2002-04-03 to 2002-05-19       (various source files)
        * graphics, sounds and music now fully configurable
index 8605b78111360dcf53f8af625c1650c779cf7804..ff34cb787609f3cdc85184119caca95eb74308da 100644 (file)
@@ -1 +1 @@
-#define COMPILE_DATE_STRING "[2004-03-10 01:26]"
+#define COMPILE_DATE_STRING "[2004-03-13 04:25]"
index b20ff4544959574c17f1e10cdf177c90a1205931..af251d33341060df607549939c1b98f0e5dd9813 100644 (file)
 #define GADGET_ID_SP_BLOCK_LAST_FIELD  (GADGET_ID_CHECKBUTTON_FIRST + 9)
 #define GADGET_ID_CAN_FALL_INTO_ACID   (GADGET_ID_CHECKBUTTON_FIRST + 10)
 #define GADGET_ID_CAN_MOVE_INTO_ACID   (GADGET_ID_CHECKBUTTON_FIRST + 11)
-#define GADGET_ID_CUSTOM_EXPLODE_RESULT        (GADGET_ID_CHECKBUTTON_FIRST + 12)
-#define GADGET_ID_CUSTOM_EXPLODE_FIRE  (GADGET_ID_CHECKBUTTON_FIRST + 13)
-#define GADGET_ID_CUSTOM_EXPLODE_SMASH (GADGET_ID_CHECKBUTTON_FIRST + 14)
-#define GADGET_ID_CUSTOM_EXPLODE_IMPACT        (GADGET_ID_CHECKBUTTON_FIRST + 15)
-#define GADGET_ID_CUSTOM_WALK_TO_OBJECT        (GADGET_ID_CHECKBUTTON_FIRST + 16)
-#define GADGET_ID_CUSTOM_DEADLY                (GADGET_ID_CHECKBUTTON_FIRST + 17)
-#define GADGET_ID_CUSTOM_CAN_MOVE      (GADGET_ID_CHECKBUTTON_FIRST + 18)
-#define GADGET_ID_CUSTOM_CAN_FALL      (GADGET_ID_CHECKBUTTON_FIRST + 19)
-#define GADGET_ID_CUSTOM_CAN_SMASH     (GADGET_ID_CHECKBUTTON_FIRST + 20)
-#define GADGET_ID_CUSTOM_SLIPPERY      (GADGET_ID_CHECKBUTTON_FIRST + 21)
-#define GADGET_ID_CUSTOM_ACCESSIBLE    (GADGET_ID_CHECKBUTTON_FIRST + 22)
-#define GADGET_ID_CUSTOM_USE_GRAPHIC   (GADGET_ID_CHECKBUTTON_FIRST + 23)
-#define GADGET_ID_CUSTOM_USE_TEMPLATE  (GADGET_ID_CHECKBUTTON_FIRST + 24)
-#define GADGET_ID_CUSTOM_CAN_CHANGE    (GADGET_ID_CHECKBUTTON_FIRST + 25)
-#define GADGET_ID_CHANGE_USE_CONTENT   (GADGET_ID_CHECKBUTTON_FIRST + 26)
-#define GADGET_ID_CHANGE_USE_EXPLOSION (GADGET_ID_CHECKBUTTON_FIRST + 27)
-#define GADGET_ID_CHANGE_ONLY_COMPLETE (GADGET_ID_CHECKBUTTON_FIRST + 28)
-#define GADGET_ID_CHANGE_USE_RANDOM    (GADGET_ID_CHECKBUTTON_FIRST + 29)
-#define GADGET_ID_CHANGE_DELAY         (GADGET_ID_CHECKBUTTON_FIRST + 30)
-#define GADGET_ID_CHANGE_BY_DIRECT_ACT (GADGET_ID_CHECKBUTTON_FIRST + 31)
-#define GADGET_ID_CHANGE_BY_OTHER_ACT  (GADGET_ID_CHECKBUTTON_FIRST + 32)
+#define GADGET_ID_DONT_COLLIDE_WITH    (GADGET_ID_CHECKBUTTON_FIRST + 12)
+#define GADGET_ID_CUSTOM_EXPLODE_RESULT        (GADGET_ID_CHECKBUTTON_FIRST + 13)
+#define GADGET_ID_CUSTOM_EXPLODE_FIRE  (GADGET_ID_CHECKBUTTON_FIRST + 14)
+#define GADGET_ID_CUSTOM_EXPLODE_SMASH (GADGET_ID_CHECKBUTTON_FIRST + 15)
+#define GADGET_ID_CUSTOM_EXPLODE_IMPACT        (GADGET_ID_CHECKBUTTON_FIRST + 16)
+#define GADGET_ID_CUSTOM_WALK_TO_OBJECT        (GADGET_ID_CHECKBUTTON_FIRST + 17)
+#define GADGET_ID_CUSTOM_DEADLY                (GADGET_ID_CHECKBUTTON_FIRST + 18)
+#define GADGET_ID_CUSTOM_CAN_MOVE      (GADGET_ID_CHECKBUTTON_FIRST + 19)
+#define GADGET_ID_CUSTOM_CAN_FALL      (GADGET_ID_CHECKBUTTON_FIRST + 20)
+#define GADGET_ID_CUSTOM_CAN_SMASH     (GADGET_ID_CHECKBUTTON_FIRST + 21)
+#define GADGET_ID_CUSTOM_SLIPPERY      (GADGET_ID_CHECKBUTTON_FIRST + 22)
+#define GADGET_ID_CUSTOM_ACCESSIBLE    (GADGET_ID_CHECKBUTTON_FIRST + 23)
+#define GADGET_ID_CUSTOM_USE_GRAPHIC   (GADGET_ID_CHECKBUTTON_FIRST + 24)
+#define GADGET_ID_CUSTOM_USE_TEMPLATE  (GADGET_ID_CHECKBUTTON_FIRST + 25)
+#define GADGET_ID_CUSTOM_CAN_CHANGE    (GADGET_ID_CHECKBUTTON_FIRST + 26)
+#define GADGET_ID_CHANGE_USE_CONTENT   (GADGET_ID_CHECKBUTTON_FIRST + 27)
+#define GADGET_ID_CHANGE_USE_EXPLOSION (GADGET_ID_CHECKBUTTON_FIRST + 28)
+#define GADGET_ID_CHANGE_ONLY_COMPLETE (GADGET_ID_CHECKBUTTON_FIRST + 29)
+#define GADGET_ID_CHANGE_USE_RANDOM    (GADGET_ID_CHECKBUTTON_FIRST + 30)
+#define GADGET_ID_CHANGE_DELAY         (GADGET_ID_CHECKBUTTON_FIRST + 31)
+#define GADGET_ID_CHANGE_BY_DIRECT_ACT (GADGET_ID_CHECKBUTTON_FIRST + 32)
+#define GADGET_ID_CHANGE_BY_OTHER_ACT  (GADGET_ID_CHECKBUTTON_FIRST + 33)
 
 /* gadgets for buttons in element list */
-#define GADGET_ID_ELEMENTLIST_FIRST    (GADGET_ID_CHECKBUTTON_FIRST + 33)
+#define GADGET_ID_ELEMENTLIST_FIRST    (GADGET_ID_CHECKBUTTON_FIRST + 34)
 #define GADGET_ID_ELEMENTLIST_LAST     (GADGET_ID_ELEMENTLIST_FIRST +  \
                                        ED_NUM_ELEMENTLIST_BUTTONS - 1)
 
 #define ED_CHECKBUTTON_ID_SP_BLOCK_LAST_FIELD  7
 #define ED_CHECKBUTTON_ID_CAN_FALL_INTO_ACID   8
 #define ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID   9
-#define ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC   10
-#define ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE  11
-#define ED_CHECKBUTTON_ID_CUSTOM_ACCESSIBLE    12
-#define ED_CHECKBUTTON_ID_CUSTOM_WALK_TO_OBJECT        13
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_MOVE      14
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_FALL      15
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_SMASH     16
-#define ED_CHECKBUTTON_ID_CUSTOM_SLIPPERY      17
-#define ED_CHECKBUTTON_ID_CUSTOM_DEADLY                18
-#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_RESULT        19
-#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_FIRE  20
-#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_SMASH 21
-#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_IMPACT        22
-#define ED_CHECKBUTTON_ID_CUSTOM_CAN_CHANGE    23
-#define ED_CHECKBUTTON_ID_CHANGE_DELAY         24
-#define ED_CHECKBUTTON_ID_CHANGE_BY_DIRECT_ACT 25
-#define ED_CHECKBUTTON_ID_CHANGE_BY_OTHER_ACT  26
-#define ED_CHECKBUTTON_ID_CHANGE_USE_EXPLOSION 27
-#define ED_CHECKBUTTON_ID_CHANGE_USE_CONTENT   28
-#define ED_CHECKBUTTON_ID_CHANGE_ONLY_COMPLETE 29
-#define ED_CHECKBUTTON_ID_CHANGE_USE_RANDOM    30
-
-#define ED_NUM_CHECKBUTTONS                    31
+#define ED_CHECKBUTTON_ID_DONT_COLLIDE_WITH    10
+#define ED_CHECKBUTTON_ID_CUSTOM_USE_GRAPHIC   11
+#define ED_CHECKBUTTON_ID_CUSTOM_USE_TEMPLATE  12
+#define ED_CHECKBUTTON_ID_CUSTOM_ACCESSIBLE    13
+#define ED_CHECKBUTTON_ID_CUSTOM_WALK_TO_OBJECT        14
+#define ED_CHECKBUTTON_ID_CUSTOM_CAN_MOVE      15
+#define ED_CHECKBUTTON_ID_CUSTOM_CAN_FALL      16
+#define ED_CHECKBUTTON_ID_CUSTOM_CAN_SMASH     17
+#define ED_CHECKBUTTON_ID_CUSTOM_SLIPPERY      18
+#define ED_CHECKBUTTON_ID_CUSTOM_DEADLY                19
+#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_RESULT        20
+#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_FIRE  21
+#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_SMASH 22
+#define ED_CHECKBUTTON_ID_CUSTOM_EXPLODE_IMPACT        23
+#define ED_CHECKBUTTON_ID_CUSTOM_CAN_CHANGE    24
+#define ED_CHECKBUTTON_ID_CHANGE_DELAY         25
+#define ED_CHECKBUTTON_ID_CHANGE_BY_DIRECT_ACT 26
+#define ED_CHECKBUTTON_ID_CHANGE_BY_OTHER_ACT  27
+#define ED_CHECKBUTTON_ID_CHANGE_USE_EXPLOSION 28
+#define ED_CHECKBUTTON_ID_CHANGE_USE_CONTENT   29
+#define ED_CHECKBUTTON_ID_CHANGE_ONLY_COMPLETE 30
+#define ED_CHECKBUTTON_ID_CHANGE_USE_RANDOM    31
+
+#define ED_NUM_CHECKBUTTONS                    32
 
 #define ED_CHECKBUTTON_ID_LEVEL_FIRST  ED_CHECKBUTTON_ID_DOUBLE_SPEED
 #define ED_CHECKBUTTON_ID_LEVEL_LAST   ED_CHECKBUTTON_ID_RANDOM_RESTRICTED
@@ -1942,7 +1944,7 @@ static struct
   {
     ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(0),
     GADGET_ID_CAN_FALL_INTO_ACID,      GADGET_ID_NONE,
-    &level.player_can_fall_into_acid,
+    &custom_element_properties[EP_CAN_MOVE_INTO_ACID],
     NULL,
     "can fall into acid (with gravity)","player can fall into acid pool"
   },
@@ -1953,6 +1955,13 @@ static struct
     NULL,
     "can move into acid",              "element can move into acid pool"
   },
+  {
+    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(1),
+    GADGET_ID_DONT_COLLIDE_WITH,       GADGET_ID_NONE,
+    &custom_element_properties[EP_DONT_COLLIDE_WITH],
+    NULL,
+    "deadly when colliding with",      "element is deadly when hitting player"
+  },
 
   /* ---------- element settings: configure 1 (custom elements) ----------- */
 
@@ -5217,8 +5226,7 @@ static void MapCheckbuttonGadget(int id)
   int y;       /* set after gadget position was modified */
 
   /* set position for "stickybutton" and "can move into acid" gadgets */
-  if (id == ED_CHECKBUTTON_ID_STICK_ELEMENT ||
-      id == ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID)
+  if (id == ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID)
     ModifyGadget(gi, GDI_Y, SY + checkbutton_info[id].y, GDI_END);
 
   y = gi->y + yoffset;
@@ -5790,10 +5798,13 @@ static void CopyGroupElementPropertiesToEditor(int element)
 static void CopyClassicElementPropertiesToEditor(int element)
 {
 #if 1
-  if (COULD_MOVE_INTO_ACID(element))
+  if (ELEM_IS_PLAYER(element) || COULD_MOVE_INTO_ACID(element))
     custom_element_properties[EP_CAN_MOVE_INTO_ACID] =
       getMoveIntoAcidProperty(&level, element);
 
+  if (MAYBE_DONT_COLLIDE_WITH(element))
+    custom_element_properties[EP_DONT_COLLIDE_WITH] =
+      getDontCollideWithProperty(&level, element);
 #else
 
   if (COULD_MOVE_INTO_ACID(element))
@@ -5966,10 +5977,13 @@ static void CopyGroupElementPropertiesToGame(int element)
 static void CopyClassicElementPropertiesToGame(int element)
 {
 #if 1
-  if (COULD_MOVE_INTO_ACID(element))
+  if (ELEM_IS_PLAYER(element) || COULD_MOVE_INTO_ACID(element))
     setMoveIntoAcidProperty(&level, element,
                            custom_element_properties[EP_CAN_MOVE_INTO_ACID]);
 
+  if (MAYBE_DONT_COLLIDE_WITH(element))
+    setDontCollideWithProperty(&level, element,
+                             custom_element_properties[EP_DONT_COLLIDE_WITH]);
 #else
 
   if (COULD_MOVE_INTO_ACID(element))
@@ -6836,7 +6850,7 @@ static boolean checkPropertiesConfig(int element)
       ELEM_IS_PLAYER(element) ||
       HAS_CONTENT(element) ||
       COULD_MOVE_INTO_ACID(element) ||
-      element == EL_SPRING)
+      MAYBE_DONT_COLLIDE_WITH(element))
     return TRUE;
   else
     for (i = 0; elements_with_counter[i].element != -1; i++)
@@ -6866,6 +6880,7 @@ static void DrawPropertiesConfig()
 
       counterbutton_info[counter_id].y =
        ED_SETTINGS_YPOS((HAS_CONTENT(properties_element) ? 1 : 0) +
+                        (MAYBE_DONT_COLLIDE_WITH(properties_element) ? 1 : 0)+
                         (COULD_MOVE_INTO_ACID(properties_element) ? 1 : 0));
 
       counterbutton_info[counter_id].value = elements_with_counter[i].value;
@@ -6911,6 +6926,9 @@ static void DrawPropertiesConfig()
     MapCheckbuttonGadget(ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID);
   }
 
+  if (MAYBE_DONT_COLLIDE_WITH(properties_element))
+    MapCheckbuttonGadget(ED_CHECKBUTTON_ID_DONT_COLLIDE_WITH);
+
   if (properties_element == EL_SPRING)
     MapCheckbuttonGadget(ED_CHECKBUTTON_ID_USE_SPRING_BUG);
 
@@ -8372,7 +8390,9 @@ static void HandleCheckbuttons(struct GadgetInfo *gi)
 
   *checkbutton_info[type_id].value ^= TRUE;
 
-  if (type_id == ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID ||
+  if (type_id == ED_CHECKBUTTON_ID_CAN_FALL_INTO_ACID ||
+      type_id == ED_CHECKBUTTON_ID_CAN_MOVE_INTO_ACID ||
+      type_id == ED_CHECKBUTTON_ID_DONT_COLLIDE_WITH ||
       (((type_id >= ED_CHECKBUTTON_ID_CUSTOM_FIRST &&
         type_id <= ED_CHECKBUTTON_ID_CUSTOM_LAST) ||
        (type_id >= ED_CHECKBUTTON_ID_CHANGE_FIRST &&
index 154d228e6257993a10f00e67c448000976756128..cd56a7c5ba5705e14a4297d536dca8d02034c648 100644 (file)
@@ -29,7 +29,7 @@
 #define CHUNK_SIZE_NONE                -1      /* do not write chunk size    */
 #define FILE_VERS_CHUNK_SIZE   8       /* size of file version chunk */
 #define LEVEL_HEADER_SIZE      80      /* size of level file header  */
-#define LEVEL_HEADER_UNUSED    6       /* unused level header bytes  */
+#define LEVEL_HEADER_UNUSED    4       /* unused level header bytes  */
 #define LEVEL_CHUNK_CNT2_SIZE  160     /* size of level CNT2 chunk   */
 #define LEVEL_CHUNK_CNT2_UNUSED        11      /* unused CNT2 chunk bytes    */
 #define LEVEL_CHUNK_CNT3_HEADER        16      /* size of level CNT3 header  */
@@ -160,12 +160,10 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
   level->block_last_field = FALSE;
   level->sp_block_last_field = TRUE;
 
-  level->use_spring_bug = FALSE;
-
   level->can_move_into_acid_bits = ~0; /* everything can move into acid */
+  level->dont_collide_with_bits = ~0;  /* always deadly when colliding  */
 
-  level->player_can_fall_into_acid = TRUE;
-
+  level->use_spring_bug = FALSE;
   level->use_step_counter = FALSE;
 
   level->use_custom_template = FALSE;
@@ -682,15 +680,12 @@ static int LoadLevel_HEAD(FILE *file, int chunk_size, struct LevelInfo *level)
 
   level->block_last_field      = (getFile8Bit(file) == 1 ? TRUE : FALSE);
   level->sp_block_last_field   = (getFile8Bit(file) == 1 ? TRUE : FALSE);
+  level->can_move_into_acid_bits = getFile32BitBE(file);
+  level->dont_collide_with_bits = getFile8Bit(file);
 
   level->use_spring_bug                = (getFile8Bit(file) == 1 ? TRUE : FALSE);
-
-  level->can_move_into_acid_bits = getFile16BitBE(file);
-
   level->use_step_counter      = (getFile8Bit(file) == 1 ? TRUE : FALSE);
 
-  level->player_can_fall_into_acid = (getFile8Bit(file) == 1 ? TRUE : FALSE);
-
   ReadUnusedBytesFromFile(file, LEVEL_HEADER_UNUSED);
 
   return chunk_size;
@@ -2093,11 +2088,12 @@ static void LoadLevel_InitVersion(struct LevelInfo *level, char *filename)
     if (level->game_version < VERSION_IDENT(2,2,0,0))
       level->use_spring_bug = TRUE;
 
-    if (level->game_version < VERSION_IDENT(3,0,9,0))
+    if (level->game_version < VERSION_IDENT(3,1,0,0))
     {
       int i, j;
 
       level->can_move_into_acid_bits = 0; /* nothing can move into acid */
+      level->dont_collide_with_bits = 0; /* nothing is deadly when colliding */
 
       setMoveIntoAcidProperty(level, EL_ROBOT,     TRUE);
       setMoveIntoAcidProperty(level, EL_SATELLITE, TRUE);
@@ -2418,15 +2414,12 @@ static void SaveLevel_HEAD(FILE *file, struct LevelInfo *level)
 
   putFile8Bit(file, (level->block_last_field ? 1 : 0));
   putFile8Bit(file, (level->sp_block_last_field ? 1 : 0));
+  putFile32BitBE(file, level->can_move_into_acid_bits);
+  putFile8Bit(file, level->dont_collide_with_bits);
 
   putFile8Bit(file, (level->use_spring_bug ? 1 : 0));
-
-  putFile16BitBE(file, level->can_move_into_acid_bits);
-
   putFile8Bit(file, (level->use_step_counter ? 1 : 0));
 
-  putFile8Bit(file, (level->player_can_fall_into_acid ? 1 : 0));
-
   WriteUnusedBytesToFile(file, LEVEL_HEADER_UNUSED);
 }
 
index f5cf3d8e25162c6d1b9f4a84699ac3f5068d3e0b..d90ff0c34cb52df8ed137d44ccd4d94961854dbd 100644 (file)
 #define GET_MAX_MOVE_DELAY(e)  (   (element_info[e].move_delay_fixed) + \
                                    (element_info[e].move_delay_random))
 
-#define ELEMENT_CAN_ENTER_FIELD_BASE(e, x, y, condition)               \
+#define ELEMENT_CAN_ENTER_FIELD_BASE_X(x, y, condition)                        \
+               (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) ||                \
+                                       (condition)))
+
+#define ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, condition)             \
                (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) ||                \
                                        (CAN_MOVE_INTO_ACID(e) &&       \
                                         Feld[x][y] == EL_ACID) ||      \
                                        (condition)))
 
-#if 0
-#define ELEMENT_CAN_ENTER_FIELD_GENERIC(e, x, y, condition)            \
+#define ELEMENT_CAN_ENTER_FIELD_BASE_3(e, x, y, condition)             \
+               (IN_LEV_FIELD(x, y) && (IS_FREE_OR_PLAYER(x, y) ||      \
+                                       (CAN_MOVE_INTO_ACID(e) &&       \
+                                        Feld[x][y] == EL_ACID) ||      \
+                                       (condition)))
+
+#define ELEMENT_CAN_ENTER_FIELD_BASE_4(e, x, y, condition)             \
                (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) ||                \
                                        (condition) ||                  \
+                                       (CAN_MOVE_INTO_ACID(e) &&       \
+                                        Feld[x][y] == EL_ACID) ||      \
                                        (DONT_COLLIDE_WITH(e) &&        \
                                         IS_PLAYER(x, y) &&             \
                                         !PLAYER_ENEMY_PROTECTED(x, y))))
-#else
+
+#if 0
 #define ELEMENT_CAN_ENTER_FIELD_GENERIC(e, x, y, condition)            \
                (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) ||                \
                                        (condition) ||                  \
-                                       (CAN_MOVE_INTO_ACID(e) &&       \
-                                        Feld[x][y] == EL_ACID) ||      \
                                        (DONT_COLLIDE_WITH(e) &&        \
                                         IS_PLAYER(x, y) &&             \
                                         !PLAYER_ENEMY_PROTECTED(x, y))))
 #endif
 
-#define ELEMENT_CAN_ENTER_FIELD_GENERIC_2(x, y, condition)             \
-               (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) ||                \
-                                       (condition)))
-
 #define ELEMENT_CAN_ENTER_FIELD(e, x, y)                               \
-       ELEMENT_CAN_ENTER_FIELD_GENERIC(e, x, y, 0)
-
-#define ELEMENT_CAN_ENTER_FIELD_OR_ACID(e, x, y)                       \
-       ELEMENT_CAN_ENTER_FIELD_GENERIC(e, x, y, (Feld[x][y] == EL_ACID))
+       ELEMENT_CAN_ENTER_FIELD_BASE_4(e, x, y, 0)
 
-#define ELEMENT_CAN_ENTER_FIELD_OR_ACID_2(x, y)                                \
-       ELEMENT_CAN_ENTER_FIELD_GENERIC_2(x, y, (Feld[x][y] == EL_ACID))
+#if 1
+#define SATELLITE_CAN_ENTER_FIELD(x, y)                                        \
+       ELEMENT_CAN_ENTER_FIELD_BASE_2(EL_SATELLITE, x, y, 0)
+#else
+#define SATELLITE_CAN_ENTER_FIELD(x, y)                                        \
+       ELEMENT_CAN_ENTER_FIELD_BASE_X(x, y, Feld[x][y] == EL_ACID)
+#endif
 
 #if 0
 #define ENEMY_CAN_ENTER_FIELD(e, x, y) (IN_LEV_FIELD(x, y) && IS_FREE(x, y))
-#else
-#define ENEMY_CAN_ENTER_FIELD(e, x, y) ELEMENT_CAN_ENTER_FIELD_BASE(e, x, y, 0)
 #endif
 
-#define YAMYAM_CAN_ENTER_FIELD(x, y)                                   \
+#define ENEMY_CAN_ENTER_FIELD(e, x, y)                                 \
+       ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, 0)
+
+#if 1
+
+#define YAMYAM_CAN_ENTER_FIELD(e, x, y)                                        \
+       ELEMENT_CAN_ENTER_FIELD_BASE_3(e, x, y, Feld[x][y] == EL_DIAMOND)
+
+#define DARK_YAMYAM_CAN_ENTER_FIELD(e, x, y)                           \
+       ELEMENT_CAN_ENTER_FIELD_BASE_3(e, x,y, IS_FOOD_DARK_YAMYAM(Feld[x][y]))
+
+#define PACMAN_CAN_ENTER_FIELD(e, x, y)                                        \
+       ELEMENT_CAN_ENTER_FIELD_BASE_3(e, x, y, IS_AMOEBOID(Feld[x][y]))
+
+#define PIG_CAN_ENTER_FIELD(e, x, y)                                   \
+       ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, IS_FOOD_PIG(Feld[x][y]))
+
+#define PENGUIN_CAN_ENTER_FIELD(e, x, y)                               \
+       ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, (Feld[x][y] == EL_EXIT_OPEN ||\
+                                                IS_FOOD_PENGUIN(Feld[x][y])))
+#define DRAGON_CAN_ENTER_FIELD(e, x, y)                                        \
+       ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, 0)
+
+#define MOLE_CAN_ENTER_FIELD(e, x, y, condition)                       \
+       ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, (condition))
+
+#define SPRING_CAN_ENTER_FIELD(e, x, y)                                        \
+       ELEMENT_CAN_ENTER_FIELD_BASE_2(e, x, y, 0)
+
+#else
+
+#define YAMYAM_CAN_ENTER_FIELD(e, x, y)                                        \
                (IN_LEV_FIELD(x, y) && (IS_FREE_OR_PLAYER(x, y) ||      \
-                                       (CAN_MOVE_INTO_ACID(EL_YAMYAM) && \
+                                       (CAN_MOVE_INTO_ACID(e) &&       \
                                         Feld[x][y] == EL_ACID) ||      \
                                        Feld[x][y] == EL_DIAMOND))
 
-#define DARK_YAMYAM_CAN_ENTER_FIELD(x, y)                              \
+#define DARK_YAMYAM_CAN_ENTER_FIELD(e, x, y)                           \
                (IN_LEV_FIELD(x, y) && (IS_FREE_OR_PLAYER(x, y) ||      \
-                                       (CAN_MOVE_INTO_ACID(EL_DARK_YAMYAM) &&\
+                                       (CAN_MOVE_INTO_ACID(e) &&       \
                                         Feld[x][y] == EL_ACID) ||      \
                                        IS_FOOD_DARK_YAMYAM(Feld[x][y])))
 
-#define PACMAN_CAN_ENTER_FIELD(x, y)                                   \
+#define PACMAN_CAN_ENTER_FIELD(e, x, y)                                        \
                (IN_LEV_FIELD(x, y) && (IS_FREE_OR_PLAYER(x, y) ||      \
-                                       (CAN_MOVE_INTO_ACID(EL_PACMAN) && \
+                                       (CAN_MOVE_INTO_ACID(e) &&       \
                                         Feld[x][y] == EL_ACID) ||      \
                                        IS_AMOEBOID(Feld[x][y])))
 
-#define PIG_CAN_ENTER_FIELD(x, y)                                      \
+#define PIG_CAN_ENTER_FIELD(e, x, y)                                   \
                (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) ||                \
-                                       (CAN_MOVE_INTO_ACID(EL_PIG) &&  \
+                                       (CAN_MOVE_INTO_ACID(e) &&       \
                                         Feld[x][y] == EL_ACID) ||      \
                                        IS_FOOD_PIG(Feld[x][y])))
 
-#define PENGUIN_CAN_ENTER_FIELD(x, y)                                  \
+#define PENGUIN_CAN_ENTER_FIELD(e, x, y)                               \
                (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) ||                \
-                                       (CAN_MOVE_INTO_ACID(EL_PENGUIN) && \
+                                       (CAN_MOVE_INTO_ACID(e) &&       \
                                         Feld[x][y] == EL_ACID) ||      \
                                        IS_FOOD_PENGUIN(Feld[x][y]) ||  \
                                        Feld[x][y] == EL_EXIT_OPEN))
 
-#define DRAGON_CAN_ENTER_FIELD(x, y)                                   \
+#define DRAGON_CAN_ENTER_FIELD(e, x, y)                                        \
                (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) ||                \
-                                       (CAN_MOVE_INTO_ACID(EL_DRAGON) && \
+                                       (CAN_MOVE_INTO_ACID(e) &&       \
                                         Feld[x][y] == EL_ACID)))
 
-#define MOLE_CAN_ENTER_FIELD(x, y, condition)                          \
+#define MOLE_CAN_ENTER_FIELD(e, x, y, condition)                       \
                (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) ||                \
-                                       (CAN_MOVE_INTO_ACID(EL_MOLE) && \
+                                       (CAN_MOVE_INTO_ACID(e) &&       \
                                         Feld[x][y] == EL_ACID) ||      \
                                        (condition)))
 
-#define SPRING_CAN_ENTER_FIELD(x, y)                                   \
+#define SPRING_CAN_ENTER_FIELD(e, x, y)                                        \
                (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) ||                \
-                                       (CAN_MOVE_INTO_ACID(EL_SPRING) && \
+                                       (CAN_MOVE_INTO_ACID(e) &&       \
                                         Feld[x][y] == EL_ACID)))
 
+#endif
+
 #define GROUP_NR(e)            ((e) - EL_GROUP_START)
 #define MOVE_ENTER_EL(e)       (element_info[e].move_enter_element)
 #define IS_IN_GROUP(e, nr)     (element_info[e].in_group[nr] == TRUE)
 #endif
 
 #define CUSTOM_ELEMENT_CAN_ENTER_FIELD(e, x, y)                                \
-       ELEMENT_CAN_ENTER_FIELD_GENERIC(e, x, y, CE_ENTER_FIELD_COND(e, x, y))
+       ELEMENT_CAN_ENTER_FIELD_BASE_4(e, x, y, CE_ENTER_FIELD_COND(e, x, y))
 
 #define IN_LEV_FIELD_AND_IS_FREE(x, y)  (IN_LEV_FIELD(x, y) &&  IS_FREE(x, y))
 #define IN_LEV_FIELD_AND_NOT_FREE(x, y) (IN_LEV_FIELD(x, y) && !IS_FREE(x, y))
@@ -910,7 +949,7 @@ static inline void InitField_WithBug1(int x, int y, boolean init_game)
   InitField(x, y, init_game);
 
   /* not needed to call InitMovDir() -- already done by InitField()! */
-  if (game.engine_version < VERSION_IDENT(3,0,9,0) &&
+  if (game.engine_version < VERSION_IDENT(3,1,0,0) &&
       CAN_MOVE(Feld[x][y]))
     InitMovDir(x, y);
 }
@@ -922,7 +961,7 @@ static inline void InitField_WithBug2(int x, int y, boolean init_game)
   InitField(x, y, init_game);
 
   /* not needed to call InitMovDir() -- already done by InitField()! */
-  if (game.engine_version < VERSION_IDENT(3,0,9,0) &&
+  if (game.engine_version < VERSION_IDENT(3,1,0,0) &&
       CAN_MOVE(old_element) &&
       (old_element < EL_MOLE_LEFT || old_element > EL_MOLE_DOWN))
     InitMovDir(x, y);
@@ -1260,14 +1299,14 @@ static void InitGameEngine()
   }
 
   /* set push delay value for Supaplex elements for newer engine versions */
-  if (game.engine_version >= VERSION_IDENT(3,0,9,0))
+  if (game.engine_version >= VERSION_IDENT(3,1,0,0))
   {
     for (i = 0; i < MAX_NUM_ELEMENTS; i++)
     {
       if (IS_SP_ELEMENT(i))
       {
-       element_info[i].push_delay_fixed  = 6;
-       element_info[i].push_delay_random = 0;
+       element_info[i].push_delay_fixed  = 6;  /* just enough to escape ... */
+       element_info[i].push_delay_random = 0;  /* ... from falling zonk     */
       }
     }
   }
@@ -1391,6 +1430,7 @@ void InitGame()
     player->use_murphy_graphic = FALSE;
 
     player->block_last_field = FALSE;
+    player->can_fall_into_acid = CAN_MOVE_INTO_ACID(player->element_nr);
 
     player->actual_frame_counter = 0;
 
@@ -3070,7 +3110,7 @@ void Explode(int ex, int ey, int phase, int mode)
 #if 1
     /* !!! not needed !!! */
 #if 1
-    if (game.engine_version < VERSION_IDENT(3,0,9,0) &&
+    if (game.engine_version < VERSION_IDENT(3,1,0,0) &&
        CAN_MOVE(Feld[x][y]) && Feld[x][y] != EL_MOLE)
       InitMovDir(x, y);
 #else
@@ -3985,9 +4025,9 @@ inline static void TurnRoundExt(int x, int y)
   {
     TestIfBadThingTouchesOtherBadThing(x, y);
 
-    if (ELEMENT_CAN_ENTER_FIELD_GENERIC(element, left_x, left_y, 0))
+    if (ELEMENT_CAN_ENTER_FIELD_BASE_4(element, left_x, left_y, 0))
       MovDir[x][y] = left_dir;
-    else if (!ELEMENT_CAN_ENTER_FIELD_GENERIC(element, move_x, move_y, 0))
+    else if (!ELEMENT_CAN_ENTER_FIELD_BASE_4(element, move_x, move_y, 0))
       MovDir[x][y] = right_dir;
 
     if (MovDir[x][y] != old_move_dir)
@@ -3996,8 +4036,8 @@ inline static void TurnRoundExt(int x, int y)
 #endif
   else if (element == EL_YAMYAM)
   {
-    boolean can_turn_left  = YAMYAM_CAN_ENTER_FIELD(left_x, left_y);
-    boolean can_turn_right = YAMYAM_CAN_ENTER_FIELD(right_x, right_y);
+    boolean can_turn_left  = YAMYAM_CAN_ENTER_FIELD(element, left_x, left_y);
+    boolean can_turn_right = YAMYAM_CAN_ENTER_FIELD(element, right_x, right_y);
 
     if (can_turn_left && can_turn_right)
       MovDir[x][y] = (RND(3) ? (RND(2) ? left_dir : right_dir) : back_dir);
@@ -4012,8 +4052,10 @@ inline static void TurnRoundExt(int x, int y)
   }
   else if (element == EL_DARK_YAMYAM)
   {
-    boolean can_turn_left  = DARK_YAMYAM_CAN_ENTER_FIELD(left_x, left_y);
-    boolean can_turn_right = DARK_YAMYAM_CAN_ENTER_FIELD(right_x, right_y);
+    boolean can_turn_left  = DARK_YAMYAM_CAN_ENTER_FIELD(element,
+                                                        left_x, left_y);
+    boolean can_turn_right = DARK_YAMYAM_CAN_ENTER_FIELD(element,
+                                                        right_x, right_y);
 
     if (can_turn_left && can_turn_right)
       MovDir[x][y] = (RND(3) ? (RND(2) ? left_dir : right_dir) : back_dir);
@@ -4028,8 +4070,8 @@ inline static void TurnRoundExt(int x, int y)
   }
   else if (element == EL_PACMAN)
   {
-    boolean can_turn_left  = PACMAN_CAN_ENTER_FIELD(left_x, left_y);
-    boolean can_turn_right = PACMAN_CAN_ENTER_FIELD(right_x, right_y);
+    boolean can_turn_left  = PACMAN_CAN_ENTER_FIELD(element, left_x, left_y);
+    boolean can_turn_right = PACMAN_CAN_ENTER_FIELD(element, right_x, right_y);
 
     if (can_turn_left && can_turn_right)
       MovDir[x][y] = (RND(3) ? (RND(2) ? left_dir : right_dir) : back_dir);
@@ -4044,9 +4086,9 @@ inline static void TurnRoundExt(int x, int y)
   }
   else if (element == EL_PIG)
   {
-    boolean can_turn_left  = PIG_CAN_ENTER_FIELD(left_x, left_y);
-    boolean can_turn_right = PIG_CAN_ENTER_FIELD(right_x, right_y);
-    boolean can_move_on    = PIG_CAN_ENTER_FIELD(move_x, move_y);
+    boolean can_turn_left  = PIG_CAN_ENTER_FIELD(element, left_x, left_y);
+    boolean can_turn_right = PIG_CAN_ENTER_FIELD(element, right_x, right_y);
+    boolean can_move_on    = PIG_CAN_ENTER_FIELD(element, move_x, move_y);
     boolean should_turn_left, should_turn_right, should_move_on;
     int rnd_value = 24;
     int rnd = RND(rnd_value);
@@ -4107,9 +4149,9 @@ inline static void TurnRoundExt(int x, int y)
   }
   else if (element == EL_DRAGON)
   {
-    boolean can_turn_left  = DRAGON_CAN_ENTER_FIELD(left_x, left_y);
-    boolean can_turn_right = DRAGON_CAN_ENTER_FIELD(right_x, right_y);
-    boolean can_move_on    = DRAGON_CAN_ENTER_FIELD(move_x, move_y);
+    boolean can_turn_left  = DRAGON_CAN_ENTER_FIELD(element, left_x, left_y);
+    boolean can_turn_right = DRAGON_CAN_ENTER_FIELD(element, right_x, right_y);
+    boolean can_move_on    = DRAGON_CAN_ENTER_FIELD(element, move_x, move_y);
     int rnd_value = 24;
     int rnd = RND(rnd_value);
 
@@ -4157,17 +4199,17 @@ inline static void TurnRoundExt(int x, int y)
   else if (element == EL_MOLE)
   {
     boolean can_move_on =
-      (MOLE_CAN_ENTER_FIELD(move_x, move_y,
+      (MOLE_CAN_ENTER_FIELD(element, move_x, move_y,
                            IS_AMOEBOID(Feld[move_x][move_y]) ||
                            Feld[move_x][move_y] == EL_AMOEBA_SHRINKING));
     if (!can_move_on)
     {
       boolean can_turn_left =
-       (MOLE_CAN_ENTER_FIELD(left_x, left_y,
+       (MOLE_CAN_ENTER_FIELD(element, left_x, left_y,
                              IS_AMOEBOID(Feld[left_x][left_y])));
 
       boolean can_turn_right =
-       (MOLE_CAN_ENTER_FIELD(right_x, right_y,
+       (MOLE_CAN_ENTER_FIELD(element, right_x, right_y,
                              IS_AMOEBOID(Feld[right_x][right_y])));
 
       if (can_turn_left && can_turn_right)
@@ -4190,12 +4232,12 @@ inline static void TurnRoundExt(int x, int y)
   {
 #if 0
     if (MovDir[x][y] & MV_HORIZONTAL &&
-       !SPRING_CAN_ENTER_FIELD(move_x, move_y))
+       !SPRING_CAN_ENTER_FIELD(element, move_x, move_y))
       MovDir[x][y] = MV_NO_MOVING;
 #else
     if (MovDir[x][y] & MV_HORIZONTAL &&
-       (!SPRING_CAN_ENTER_FIELD(move_x, move_y) ||
-        SPRING_CAN_ENTER_FIELD(x, y + 1)))
+       (!SPRING_CAN_ENTER_FIELD(element, move_x, move_y) ||
+        SPRING_CAN_ENTER_FIELD(element, x, y + 1)))
       MovDir[x][y] = MV_NO_MOVING;
 #endif
 
@@ -4302,14 +4344,14 @@ inline static void TurnRoundExt(int x, int y)
          new_move_dir & (first_horiz ? MV_HORIZONTAL : MV_VERTICAL);
        Moving2Blocked(x, y, &newx, &newy);
 
-       if (PENGUIN_CAN_ENTER_FIELD(newx, newy))
+       if (PENGUIN_CAN_ENTER_FIELD(EL_PENGUIN, newx, newy))
          return;
 
        MovDir[x][y] =
          new_move_dir & (!first_horiz ? MV_HORIZONTAL : MV_VERTICAL);
        Moving2Blocked(x, y, &newx, &newy);
 
-       if (PENGUIN_CAN_ENTER_FIELD(newx, newy))
+       if (PENGUIN_CAN_ENTER_FIELD(EL_PENGUIN, newx, newy))
          return;
 
        MovDir[x][y] = old_move_dir;
@@ -4331,14 +4373,14 @@ inline static void TurnRoundExt(int x, int y)
          new_move_dir & (first_horiz ? MV_HORIZONTAL : MV_VERTICAL);
        Moving2Blocked(x, y, &newx, &newy);
 
-       if (ELEMENT_CAN_ENTER_FIELD_OR_ACID_2(newx, newy))
+       if (SATELLITE_CAN_ENTER_FIELD(newx, newy))
          return;
 
        MovDir[x][y] =
          new_move_dir & (!first_horiz ? MV_HORIZONTAL : MV_VERTICAL);
        Moving2Blocked(x, y, &newx, &newy);
 
-       if (ELEMENT_CAN_ENTER_FIELD_OR_ACID_2(newx, newy))
+       if (SATELLITE_CAN_ENTER_FIELD(newx, newy))
          return;
 
        MovDir[x][y] = old_move_dir;
@@ -4944,7 +4986,7 @@ void StartMoving(int x, int y)
 #endif
 
 #if 1
-    if (game.engine_version >= VERSION_IDENT(3,0,9,0) &&
+    if (game.engine_version >= VERSION_IDENT(3,1,0,0) &&
        WasJustMoving[x][y] && IN_LEV_FIELD(newx, newy) &&
        (Feld[newx][newy] == EL_BLOCKED || IS_PLAYER(newx, newy)))
     {
@@ -5175,7 +5217,7 @@ void StartMoving(int x, int y)
     else if (CAN_MOVE_INTO_ACID(element) &&
             IN_LEV_FIELD(newx, newy) && Feld[newx][newy] == EL_ACID &&
             (MovDir[x][y] == MV_DOWN ||
-             game.engine_version > VERSION_IDENT(3,0,8,0)))
+             game.engine_version >= VERSION_IDENT(3,1,0,0)))
 #else
     else if (CAN_MOVE_INTO_ACID(element) && MovDir[x][y] == MV_DOWN &&
             IN_LEV_FIELD(newx, newy) && Feld[newx][newy] == EL_ACID)
@@ -7520,6 +7562,7 @@ void GameActions()
        - rnd_equinox_tetrachloride 048
        - rnd_equinox_tetrachloride_ii 096
        - rnd_emanuel_schmieg 002
+       - doctor_sloan_ww 020
     */
     if (stored_player[i].MovPos == 0)
       CheckGravityMovement(&stored_player[i]);
@@ -8215,7 +8258,7 @@ static void CheckGravityMovement(struct PlayerInfo *player)
     boolean player_can_fall_down =
       (IN_LEV_FIELD(jx, jy + 1) &&
        (IS_FREE(jx, jy + 1) ||
-       (Feld[jx][jy + 1] == EL_ACID && level.player_can_fall_into_acid)));
+       (Feld[jx][jy + 1] == EL_ACID && player->can_fall_into_acid)));
 #else
     boolean player_can_fall_down =
       (IN_LEV_FIELD(jx, jy + 1) &&
index df191e0ab886fd2cc740db2a0edfe8a04ac685c0..c4528006afb2aaf0d448f94d61713fa981968f9a 100644 (file)
@@ -1569,71 +1569,133 @@ 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[] =
-  {
-    /* all element that can move */
-    { 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       },
-    { EL_SPRING,               10      },
+  };
+
+  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       },
+
+    /* 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);
@@ -1656,6 +1718,7 @@ boolean getMoveIntoAcidProperty(struct LevelInfo *level, int element)
 
   return FALSE;
 }
+#endif
 
 void InitElementPropertiesStatic()
 {
@@ -3270,9 +3333,19 @@ void InitElementPropertiesEngine(int engine_version)
     SET_PROPERTY(i, EP_COULD_MOVE_INTO_ACID, (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) &&
@@ -3366,7 +3439,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++)
     {
@@ -3379,12 +3452,15 @@ void InitElementPropertiesEngine(int engine_version)
     }
   }
 
+#if 0
   /* set element properties that were handled incorrectly in older levels */
-  if (engine_version < VERSION_IDENT(3,0,9,0))
+  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 */
index af5f39815e7b5d16e35b595561deb6934e9863cc..ca22ef6e1662a2c7acd76fb2accae3b710fd36b2 100644 (file)
 
 #include "main.h"
 
+#if 1
+#define setMoveIntoAcidProperty(l, e, v)       \
+       (setBitfieldProperty(&(l)->can_move_into_acid_bits,     \
+                            EP_CAN_MOVE_INTO_ACID, e, v))
+#define getMoveIntoAcidProperty(l, e)          \
+       (getBitfieldProperty(&(l)->can_move_into_acid_bits,     \
+                            EP_CAN_MOVE_INTO_ACID, e))
+#define setDontCollideWithProperty(l, e, v)    \
+       (setBitfieldProperty(&(l)->can_move_into_acid_bits,     \
+                            EP_DONT_COLLIDE_WITH, e, v))
+#define getDontCollideWithProperty(l, e)       \
+       (getBitfieldProperty(&(l)->can_move_into_acid_bits,     \
+                            EP_DONT_COLLIDE_WITH, e))
+
+void setBitfieldProperty(int *, int, int, boolean);
+boolean getBitfieldProperty(int *, int, int);
+
+#else
+
 void setMoveIntoAcidProperty(struct LevelInfo *, int, boolean);
 boolean getMoveIntoAcidProperty(struct LevelInfo *, int);
+#endif
+
 void InitElementPropertiesStatic(void);
 void InitElementPropertiesEngine(int);
 
index e55db3cb28fcf1426bb398300481d42ce5614177..cb739c041ccedc618bd196d452b74247444433eb 100644 (file)
 #define EP_CAN_EXPLODE         70
 #define EP_CAN_EXPLODE_3X3     71
 #define EP_SP_PORT             72
-#define EP_CAN_EXPLODE_BY_DRAGONFIRE 73
-#define EP_CAN_EXPLODE_BY_EXPLOSION  74
-#define EP_COULD_MOVE_INTO_ACID        75
+#define EP_CAN_EXPLODE_BY_DRAGONFIRE   73
+#define EP_CAN_EXPLODE_BY_EXPLOSION    74
+#define EP_COULD_MOVE_INTO_ACID                75
+#define EP_MAYBE_DONT_COLLIDE_WITH     76
 
 /* values for internal purpose only (level editor) */
-#define EP_EXPLODE_RESULT      76
-#define EP_WALK_TO_OBJECT      77
-#define EP_DEADLY              78
+#define EP_EXPLODE_RESULT      77
+#define EP_WALK_TO_OBJECT      78
+#define EP_DEADLY              79
 
-#define NUM_ELEMENT_PROPERTIES 79
+#define NUM_ELEMENT_PROPERTIES 80
 
 #define NUM_EP_BITFIELDS       ((NUM_ELEMENT_PROPERTIES + 31) / 32)
 #define EP_BITFIELD_BASE       0
 #define CAN_EXPLODE_BY_EXPLOSION(e)    \
                                HAS_PROPERTY(e, EP_CAN_EXPLODE_BY_EXPLOSION)
 #define COULD_MOVE_INTO_ACID(e)        HAS_PROPERTY(e, EP_COULD_MOVE_INTO_ACID)
+#define MAYBE_DONT_COLLIDE_WITH(e)  HAS_PROPERTY(e, EP_MAYBE_DONT_COLLIDE_WITH)
 
 /* special macros used in game engine */
 #define IS_CUSTOM_ELEMENT(e)   ((e) >= EL_CUSTOM_START &&              \
 /* program information and versioning definitions */
 
 #define PROGRAM_VERSION_MAJOR  3
-#define PROGRAM_VERSION_MINOR  0
-#define PROGRAM_VERSION_PATCH  9
+#define PROGRAM_VERSION_MINOR  1
+#define PROGRAM_VERSION_PATCH  0
 #define PROGRAM_VERSION_BUILD  0
 
 #define PROGRAM_TITLE_STRING   "Rocks'n'Diamonds"
@@ -1313,6 +1315,7 @@ struct PlayerInfo
   boolean use_murphy_graphic;
 
   boolean block_last_field;
+  boolean can_fall_into_acid;
 
   boolean LevelSolved, GameOver;
 
@@ -1423,9 +1426,8 @@ struct LevelInfo
   int time_light;
   int time_timegate;
 
-  int can_move_into_acid_bits; /* bits indicate property for element groups */
-
-  boolean player_can_fall_into_acid;
+  int can_move_into_acid_bits; /* bitfield to store property for elements */
+  int dont_collide_with_bits;  /* bitfield to store property for elements */
 
   boolean double_speed;
   boolean initial_gravity;