+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
-#define COMPILE_DATE_STRING "[2004-03-10 01:26]"
+#define COMPILE_DATE_STRING "[2004-03-13 04:25]"
#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
{
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"
},
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) ----------- */
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;
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))
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))
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++)
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;
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);
*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 &&
#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 */
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;
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;
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);
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);
}
#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))
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);
}
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);
}
/* 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 */
}
}
}
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;
#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
{
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)
#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);
}
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);
}
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);
}
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);
}
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);
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)
{
#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
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;
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;
#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)))
{
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)
- 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]);
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) &&
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);
return FALSE;
}
+#endif
void InitElementPropertiesStatic()
{
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) &&
}
/* 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++)
{
}
}
+#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 */
#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);
#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"
boolean use_murphy_graphic;
boolean block_last_field;
+ boolean can_fall_into_acid;
boolean LevelSolved, GameOver;
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;