#include "conf_snd.h" /* include auto-generated data structure definitions */
#include "conf_mus.h" /* include auto-generated data structure definitions */
-#define IMG_UNDEFINED (-1)
-#define IMG_EMPTY IMG_EMPTY_SPACE
-#define IMG_SP_EMPTY IMG_SP_EMPTY_SPACE
-#define IMG_EXPLOSION IMG_DEFAULT_EXPLODING
-#define IMG_CHAR_START IMG_CHAR_SPACE
-#define IMG_CUSTOM_START IMG_CUSTOM_1
-
-#define SND_UNDEFINED (-1)
-#define MUS_UNDEFINED (-1)
-
-#define WIN_XSIZE 672
-#define WIN_YSIZE 560
-
-#define SCR_FIELDX 17
-#define SCR_FIELDY 17
-#define MAX_BUF_XSIZE (SCR_FIELDX + 2)
-#define MAX_BUF_YSIZE (SCR_FIELDY + 2)
-#define MIN_LEV_FIELDX 3
-#define MIN_LEV_FIELDY 3
-#define STD_LEV_FIELDX 64
-#define STD_LEV_FIELDY 32
-#define MAX_LEV_FIELDX 128
-#define MAX_LEV_FIELDY 128
-
-#define SCREENX(a) ((a) - scroll_x)
-#define SCREENY(a) ((a) - scroll_y)
-#define LEVELX(a) ((a) + scroll_x)
-#define LEVELY(a) ((a) + scroll_y)
+#define IMG_UNDEFINED (-1)
+#define IMG_EMPTY IMG_EMPTY_SPACE
+#define IMG_SP_EMPTY IMG_SP_EMPTY_SPACE
+#define IMG_EXPLOSION IMG_DEFAULT_EXPLODING
+#define IMG_CHAR_START IMG_CHAR_SPACE
+#define IMG_CUSTOM_START IMG_CUSTOM_1
+
+#define SND_UNDEFINED (-1)
+#define MUS_UNDEFINED (-1)
+
+#define WIN_XSIZE 672
+#define WIN_YSIZE 560
+
+#define SCR_FIELDX 17
+#define SCR_FIELDY 17
+#define MAX_BUF_XSIZE (SCR_FIELDX + 2)
+#define MAX_BUF_YSIZE (SCR_FIELDY + 2)
+#define MIN_LEV_FIELDX 3
+#define MIN_LEV_FIELDY 3
+#define STD_LEV_FIELDX 64
+#define STD_LEV_FIELDY 32
+#define MAX_LEV_FIELDX MAX_PLAYFIELD_WIDTH
+#define MAX_LEV_FIELDY MAX_PLAYFIELD_HEIGHT
+
+#define SCREENX(a) ((a) - scroll_x)
+#define SCREENY(a) ((a) - scroll_y)
+#define LEVELX(a) ((a) + scroll_x)
+#define LEVELY(a) ((a) + scroll_y)
#define IN_VIS_FIELD(x,y) ((x)>=0 && (x)<SCR_FIELDX && (y)>=0 &&(y)<SCR_FIELDY)
#define IN_SCR_FIELD(x,y) ((x)>=BX1 && (x)<=BX2 && (y)>=BY1 &&(y)<=BY2)
#define IN_LEV_FIELD(x,y) ((x)>=0 && (x)<lev_fieldx && (y)>=0 &&(y)<lev_fieldy)
/* values for configurable properties (custom elem's only, else pre-defined) */
-#define EP_DIGGABLE 0
-#define EP_COLLECTIBLE_ONLY 1
-#define EP_DONT_RUN_INTO 2
-#define EP_DONT_COLLIDE_WITH 3
-#define EP_DONT_TOUCH 4
-#define EP_INDESTRUCTIBLE 5
-#define EP_SLIPPERY 6
-#define EP_CAN_CHANGE 7
-#define EP_CAN_MOVE 8
-#define EP_CAN_FALL 9
-#define EP_CAN_SMASH_PLAYER 10
-#define EP_CAN_SMASH_ENEMIES 11
-#define EP_CAN_SMASH_EVERYTHING 12
-#define EP_EXPLODES_BY_FIRE 13
-#define EP_EXPLODES_SMASHED 14
-#define EP_EXPLODES_IMPACT 15
-#define EP_WALKABLE_OVER 16
-#define EP_WALKABLE_INSIDE 17
-#define EP_WALKABLE_UNDER 18
-#define EP_PASSABLE_OVER 19
-#define EP_PASSABLE_INSIDE 20
-#define EP_PASSABLE_UNDER 21
-#define EP_DROPPABLE 22
-#define EP_EXPLODES_1X1_OLD 23
-#define EP_PUSHABLE 24
-#define EP_EXPLODES_CROSS_OLD 25
-#define EP_PROTECTED 26
-#define EP_CAN_MOVE_INTO_ACID 27
-#define EP_THROWABLE 28
-#define EP_CAN_EXPLODE 29
-#define EP_GRAVITY_REACHABLE 30
+#define EP_DIGGABLE 0
+#define EP_COLLECTIBLE_ONLY 1
+#define EP_DONT_RUN_INTO 2
+#define EP_DONT_COLLIDE_WITH 3
+#define EP_DONT_TOUCH 4
+#define EP_INDESTRUCTIBLE 5
+#define EP_SLIPPERY 6
+#define EP_CAN_CHANGE 7
+#define EP_CAN_MOVE 8
+#define EP_CAN_FALL 9
+#define EP_CAN_SMASH_PLAYER 10
+#define EP_CAN_SMASH_ENEMIES 11
+#define EP_CAN_SMASH_EVERYTHING 12
+#define EP_EXPLODES_BY_FIRE 13
+#define EP_EXPLODES_SMASHED 14
+#define EP_EXPLODES_IMPACT 15
+#define EP_WALKABLE_OVER 16
+#define EP_WALKABLE_INSIDE 17
+#define EP_WALKABLE_UNDER 18
+#define EP_PASSABLE_OVER 19
+#define EP_PASSABLE_INSIDE 20
+#define EP_PASSABLE_UNDER 21
+#define EP_DROPPABLE 22
+#define EP_EXPLODES_1X1_OLD 23
+#define EP_PUSHABLE 24
+#define EP_EXPLODES_CROSS_OLD 25
+#define EP_PROTECTED 26
+#define EP_CAN_MOVE_INTO_ACID 27
+#define EP_THROWABLE 28
+#define EP_CAN_EXPLODE 29
+#define EP_GRAVITY_REACHABLE 30
/* values for pre-defined properties */
-#define EP_PLAYER 32
-#define EP_CAN_PASS_MAGIC_WALL 33
-#define EP_SWITCHABLE 34
-#define EP_BD_ELEMENT 35
-#define EP_SP_ELEMENT 36
-#define EP_SB_ELEMENT 37
-#define EP_GEM 38
-#define EP_FOOD_DARK_YAMYAM 39
-#define EP_FOOD_PENGUIN 40
-#define EP_FOOD_PIG 41
-#define EP_HISTORIC_WALL 42
-#define EP_HISTORIC_SOLID 43
-#define EP_CLASSIC_ENEMY 44
-#define EP_BELT 45
-#define EP_BELT_ACTIVE 46
-#define EP_BELT_SWITCH 47
-#define EP_TUBE 48
-#define EP_KEYGATE 49
-#define EP_AMOEBOID 50
-#define EP_AMOEBALIVE 51
-#define EP_HAS_CONTENT 52
-#define EP_CAN_TURN_EACH_MOVE 53
-#define EP_CAN_GROW 54
-#define EP_ACTIVE_BOMB 55
-#define EP_INACTIVE 56
+#define EP_PLAYER 32
+#define EP_CAN_PASS_MAGIC_WALL 33
+#define EP_SWITCHABLE 34
+#define EP_BD_ELEMENT 35
+#define EP_SP_ELEMENT 36
+#define EP_SB_ELEMENT 37
+#define EP_GEM 38
+#define EP_FOOD_DARK_YAMYAM 39
+#define EP_FOOD_PENGUIN 40
+#define EP_FOOD_PIG 41
+#define EP_HISTORIC_WALL 42
+#define EP_HISTORIC_SOLID 43
+#define EP_CLASSIC_ENEMY 44
+#define EP_BELT 45
+#define EP_BELT_ACTIVE 46
+#define EP_BELT_SWITCH 47
+#define EP_TUBE 48
+#define EP_KEYGATE 49
+#define EP_AMOEBOID 50
+#define EP_AMOEBALIVE 51
+#define EP_HAS_EDITOR_CONTENT 52
+#define EP_CAN_TURN_EACH_MOVE 53
+#define EP_CAN_GROW 54
+#define EP_ACTIVE_BOMB 55
+#define EP_INACTIVE 56
/* values for special configurable properties (depending on level settings) */
-#define EP_EM_SLIPPERY_WALL 57
+#define EP_EM_SLIPPERY_WALL 57
/* values for special graphics properties (no effect on game engine) */
-#define EP_GFX_CRUMBLED 58
+#define EP_GFX_CRUMBLED 58
/* values for derived properties (determined from properties above) */
-#define EP_ACCESSIBLE_OVER 59
-#define EP_ACCESSIBLE_INSIDE 60
-#define EP_ACCESSIBLE_UNDER 61
-#define EP_WALKABLE 62
-#define EP_PASSABLE 63
-#define EP_ACCESSIBLE 64
-#define EP_COLLECTIBLE 65
-#define EP_SNAPPABLE 66
-#define EP_WALL 67
-#define EP_SOLID_FOR_PUSHING 68
-#define EP_DRAGONFIRE_PROOF 69
-#define EP_EXPLOSION_PROOF 70
-#define EP_CAN_SMASH 71
-#define EP_EXPLODES_3X3_OLD 72
-#define EP_CAN_EXPLODE_BY_FIRE 73
-#define EP_CAN_EXPLODE_SMASHED 74
-#define EP_CAN_EXPLODE_IMPACT 75
-#define EP_SP_PORT 76
+#define EP_ACCESSIBLE_OVER 59
+#define EP_ACCESSIBLE_INSIDE 60
+#define EP_ACCESSIBLE_UNDER 61
+#define EP_WALKABLE 62
+#define EP_PASSABLE 63
+#define EP_ACCESSIBLE 64
+#define EP_COLLECTIBLE 65
+#define EP_SNAPPABLE 66
+#define EP_WALL 67
+#define EP_SOLID_FOR_PUSHING 68
+#define EP_DRAGONFIRE_PROOF 69
+#define EP_EXPLOSION_PROOF 70
+#define EP_CAN_SMASH 71
+#define EP_EXPLODES_3X3_OLD 72
+#define EP_CAN_EXPLODE_BY_FIRE 73
+#define EP_CAN_EXPLODE_SMASHED 74
+#define EP_CAN_EXPLODE_IMPACT 75
+#define EP_SP_PORT 76
#define EP_CAN_EXPLODE_BY_DRAGONFIRE 77
#define EP_CAN_EXPLODE_BY_EXPLOSION 78
#define EP_COULD_MOVE_INTO_ACID 79
#define EP_MAYBE_DONT_COLLIDE_WITH 80
+#define EP_CAN_BE_CLONED_BY_ANDROID 81
/* values for internal purpose only (level editor) */
-#define EP_WALK_TO_OBJECT 81
-#define EP_DEADLY 82
+#define EP_WALK_TO_OBJECT 82
+#define EP_DEADLY 83
+#define EP_EDITOR_CASCADE 84
+#define EP_EDITOR_CASCADE_ACTIVE 85
+#define EP_EDITOR_CASCADE_INACTIVE 86
/* values for internal purpose only (game engine) */
-#define EP_HAS_ACTION 83
-#define EP_CAN_CHANGE_OR_HAS_ACTION 84
+#define EP_HAS_ACTION 87
+#define EP_CAN_CHANGE_OR_HAS_ACTION 88
-#define NUM_ELEMENT_PROPERTIES 85
+#define NUM_ELEMENT_PROPERTIES 89
-#define NUM_EP_BITFIELDS ((NUM_ELEMENT_PROPERTIES + 31) / 32)
-#define EP_BITFIELD_BASE 0
+#define NUM_EP_BITFIELDS ((NUM_ELEMENT_PROPERTIES + 31) / 32)
+#define EP_BITFIELD_BASE 0
-#define EP_BITMASK_DEFAULT 0
+#define EP_BITMASK_DEFAULT 0
-#define PROPERTY_BIT(p) (1 << ((p) % 32))
-#define PROPERTY_VAR(e,p) (Properties[e][(p) / 32])
+#define PROPERTY_BIT(p) (1 << ((p) % 32))
+#if 1
+#define PROPERTY_VAR(e,p) (element_info[e].properties[(p) / 32])
+#else
+#define PROPERTY_VAR(e,p) (Properties[e][(p) / 32])
+#endif
#define HAS_PROPERTY(e,p) ((PROPERTY_VAR(e, p) & PROPERTY_BIT(p)) != 0)
#define SET_PROPERTY(e,p,v) ((v) ? \
(PROPERTY_VAR(e,p) |= PROPERTY_BIT(p)) : \
/* values for change events for custom elements (stored in level file) */
-#define CE_DELAY 0
-#define CE_TOUCHED_BY_PLAYER 1
-#define CE_PRESSED_BY_PLAYER 2
-#define CE_PUSHED_BY_PLAYER 3
-#define CE_DROPPED_BY_PLAYER 4
-#define CE_HITTING_SOMETHING 5
-#define CE_IMPACT 6
-#define CE_SMASHED 7
-#define CE_TOUCHING_X 8
-#define CE_CHANGE_OF_X 9
-#define CE_EXPLOSION_OF_X 10
-#define CE_PLAYER_TOUCHES_X 11
-#define CE_PLAYER_PRESSES_X 12
-#define CE_PLAYER_PUSHES_X 13
-#define CE_PLAYER_COLLECTS_X 14
-#define CE_PLAYER_DROPS_X 15
-#define CE_COUNT_AT_ZERO 16
-#define CE_COUNT_AT_ZERO_OF_X 17
-#define CE_BY_OTHER_ACTION 18 /* activates other element events */
-#define CE_BY_DIRECT_ACTION 19 /* activates direct element events */
-#define CE_PLAYER_DIGS_X 20
-#define CE_ENTERED_BY_PLAYER 21
-#define CE_LEFT_BY_PLAYER 22
-#define CE_PLAYER_ENTERS_X 23
-#define CE_PLAYER_LEAVES_X 24
-#define CE_SWITCHED 25
-#define CE_SWITCH_OF_X 26
-#define CE_HIT_BY_SOMETHING 27
-#define CE_HITTING_X 28
-#define CE_HIT_BY_X 29
-#define CE_BLOCKED 30
-
-#define NUM_CHANGE_EVENTS 31
-
-#define CE_BITMASK_DEFAULT 0
-
-#define CH_EVENT_VAR(e,c) (element_info[e].change->has_event[c])
-#define CH_ANY_EVENT_VAR(e,c) (element_info[e].has_change_event[c])
-
-#define PAGE_HAS_CHANGE_EVENT(p,c) ((p)->has_event[c])
-#define HAS_CHANGE_EVENT(e,c) (IS_CUSTOM_ELEMENT(e) && \
- CH_EVENT_VAR(e,c))
-#define HAS_ANY_CHANGE_EVENT(e,c) (IS_CUSTOM_ELEMENT(e) && \
- CH_ANY_EVENT_VAR(e,c))
-
-#define SET_CHANGE_EVENT(e,c,v) (IS_CUSTOM_ELEMENT(e) ? \
- CH_EVENT_VAR(e,c) = (v) : 0)
-#define SET_ANY_CHANGE_EVENT(e,c,v) (IS_CUSTOM_ELEMENT(e) ? \
- CH_ANY_EVENT_VAR(e,c) = (v) : 0)
+#define CE_DELAY 0
+#define CE_TOUCHED_BY_PLAYER 1
+#define CE_PRESSED_BY_PLAYER 2
+#define CE_PUSHED_BY_PLAYER 3
+#define CE_DROPPED_BY_PLAYER 4
+#define CE_HITTING_SOMETHING 5
+#define CE_IMPACT 6
+#define CE_SMASHED 7
+#define CE_TOUCHING_X 8
+#define CE_CHANGE_OF_X 9
+#define CE_EXPLOSION_OF_X 10
+#define CE_PLAYER_TOUCHES_X 11
+#define CE_PLAYER_PRESSES_X 12
+#define CE_PLAYER_PUSHES_X 13
+#define CE_PLAYER_COLLECTS_X 14
+#define CE_PLAYER_DROPS_X 15
+#define CE_VALUE_GETS_ZERO 16
+#define CE_VALUE_GETS_ZERO_OF_X 17
+#define CE_BY_OTHER_ACTION 18
+#define CE_BY_DIRECT_ACTION 19
+#define CE_PLAYER_DIGS_X 20
+#define CE_ENTERED_BY_PLAYER 21
+#define CE_LEFT_BY_PLAYER 22
+#define CE_PLAYER_ENTERS_X 23
+#define CE_PLAYER_LEAVES_X 24
+#define CE_SWITCHED 25
+#define CE_SWITCH_OF_X 26
+#define CE_HIT_BY_SOMETHING 27
+#define CE_HITTING_X 28
+#define CE_HIT_BY_X 29
+#define CE_BLOCKED 30
+#define CE_SWITCHED_BY_PLAYER 31
+#define CE_PLAYER_SWITCHES_X 32
+#define CE_SNAPPED_BY_PLAYER 33
+#define CE_PLAYER_SNAPS_X 34
+#define CE_MOVE_OF_X 35
+#define CE_DIGGING_X 36
+#define CE_CREATION_OF_X 37
+
+#define NUM_CHANGE_EVENTS 38
+
+#define CE_BITMASK_DEFAULT 0
+
+#define CH_EVENT_VAR(e,c) (element_info[e].change->has_event[c])
+#define CH_ANY_EVENT_VAR(e,c) (element_info[e].has_change_event[c])
+
+#define PAGE_HAS_CHANGE_EVENT(p,c) ((p)->has_event[c])
+#define HAS_CHANGE_EVENT(e,c) (IS_CUSTOM_ELEMENT(e) && \
+ CH_EVENT_VAR(e,c))
+#define HAS_ANY_CHANGE_EVENT(e,c) (IS_CUSTOM_ELEMENT(e) && \
+ CH_ANY_EVENT_VAR(e,c))
+
+#define SET_CHANGE_EVENT(e,c,v) (IS_CUSTOM_ELEMENT(e) ? \
+ CH_EVENT_VAR(e,c) = (v) : 0)
+#define SET_ANY_CHANGE_EVENT(e,c,v) (IS_CUSTOM_ELEMENT(e) ? \
+ CH_ANY_EVENT_VAR(e,c) = (v) : 0)
/* values for player bitmasks */
-#define PLAYER_BITS_NONE 0
-#define PLAYER_BITS_1 (1 << 0)
-#define PLAYER_BITS_2 (1 << 1)
-#define PLAYER_BITS_3 (1 << 2)
-#define PLAYER_BITS_4 (1 << 3)
-#define PLAYER_BITS_ANY (PLAYER_BITS_1 | \
- PLAYER_BITS_2 | \
- PLAYER_BITS_3 | \
- PLAYER_BITS_4)
-#define PLAYER_BITS_TRIGGER (1 << 4)
+#define PLAYER_BITS_NONE 0
+#define PLAYER_BITS_1 (1 << 0)
+#define PLAYER_BITS_2 (1 << 1)
+#define PLAYER_BITS_3 (1 << 2)
+#define PLAYER_BITS_4 (1 << 3)
+#define PLAYER_BITS_ANY (PLAYER_BITS_1 | \
+ PLAYER_BITS_2 | \
+ PLAYER_BITS_3 | \
+ PLAYER_BITS_4)
+#define PLAYER_BITS_TRIGGER (1 << 4)
+
+/* values for move directions (bits 0 - 3: basic move directions) */
+#define MV_BIT_PREVIOUS 4
+#define MV_BIT_TRIGGER 5
+#define MV_BIT_TRIGGER_BACK 6
+#define MV_BIT_NORMAL MV_BIT_TRIGGER
+#define MV_BIT_REVERSE MV_BIT_TRIGGER_BACK
+
+#define MV_PREVIOUS (1 << MV_BIT_PREVIOUS)
+#define MV_TRIGGER (1 << MV_BIT_TRIGGER)
+#define MV_TRIGGER_BACK (1 << MV_BIT_TRIGGER_BACK)
+#define MV_NORMAL (1 << MV_BIT_NORMAL)
+#define MV_REVERSE (1 << MV_BIT_REVERSE)
+
+/* values for move stepsize */
+#define STEPSIZE_NOT_MOVING 0
+#define STEPSIZE_VERY_SLOW 1
+#define STEPSIZE_SLOW 2
+#define STEPSIZE_NORMAL 4
+#define STEPSIZE_FAST 8
+#define STEPSIZE_VERY_FAST 16
+#define STEPSIZE_EVEN_FASTER 32
+#define STEPSIZE_SLOWER 50 /* (symbolic value only) */
+#define STEPSIZE_FASTER 200 /* (symbolic value only) */
+#define STEPSIZE_RESET 100 /* (symbolic value only) */
/* values for change side for custom elements */
-#define CH_SIDE_NONE MV_NO_MOVING
-#define CH_SIDE_LEFT MV_LEFT
-#define CH_SIDE_RIGHT MV_RIGHT
-#define CH_SIDE_TOP MV_UP
-#define CH_SIDE_BOTTOM MV_DOWN
-#define CH_SIDE_LEFT_RIGHT MV_HORIZONTAL
-#define CH_SIDE_TOP_BOTTOM MV_VERTICAL
-#define CH_SIDE_ANY MV_ANY_DIRECTION
+#define CH_SIDE_NONE MV_NONE
+#define CH_SIDE_LEFT MV_LEFT
+#define CH_SIDE_RIGHT MV_RIGHT
+#define CH_SIDE_TOP MV_UP
+#define CH_SIDE_BOTTOM MV_DOWN
+#define CH_SIDE_LEFT_RIGHT MV_HORIZONTAL
+#define CH_SIDE_TOP_BOTTOM MV_VERTICAL
+#define CH_SIDE_ANY MV_ANY_DIRECTION
/* values for change player for custom elements */
-#define CH_PLAYER_NONE PLAYER_BITS_NONE
-#define CH_PLAYER_1 PLAYER_BITS_1
-#define CH_PLAYER_2 PLAYER_BITS_2
-#define CH_PLAYER_3 PLAYER_BITS_3
-#define CH_PLAYER_4 PLAYER_BITS_4
-#define CH_PLAYER_ANY PLAYER_BITS_ANY
+#define CH_PLAYER_NONE PLAYER_BITS_NONE
+#define CH_PLAYER_1 PLAYER_BITS_1
+#define CH_PLAYER_2 PLAYER_BITS_2
+#define CH_PLAYER_3 PLAYER_BITS_3
+#define CH_PLAYER_4 PLAYER_BITS_4
+#define CH_PLAYER_ANY PLAYER_BITS_ANY
/* values for change page for custom elements */
-#define CH_PAGE_ANY_FILE (0xff)
-#define CH_PAGE_ANY (0xffffffff)
+#define CH_PAGE_ANY_FILE (0xff)
+#define CH_PAGE_ANY (0xffffffff)
/* values for change power for custom elements */
-#define CP_WHEN_EMPTY 0
-#define CP_WHEN_DIGGABLE 1
-#define CP_WHEN_DESTRUCTIBLE 2
-#define CP_WHEN_COLLECTIBLE 3
-#define CP_WHEN_REMOVABLE 4
-#define CP_WHEN_WALKABLE 5
+#define CP_WHEN_EMPTY 0
+#define CP_WHEN_DIGGABLE 1
+#define CP_WHEN_DESTRUCTIBLE 2
+#define CP_WHEN_COLLECTIBLE 3
+#define CP_WHEN_REMOVABLE 4
+#define CP_WHEN_WALKABLE 5
/* values for change actions for custom elements */
-#define CA_NO_ACTION 0
-#define CA_EXIT_PLAYER 1
-#define CA_KILL_PLAYER 2
-#define CA_RESTART_LEVEL 3
-#define CA_SHOW_ENVELOPE 4
-#define CA_ADD_KEY 5
-#define CA_DEL_KEY 6
-#define CA_SET_PLAYER_SPEED 7
-#define CA_SET_GEMS 8
-#define CA_SET_TIME 9
-#define CA_SET_SCORE 10
-#define CA_SET_CE_SCORE 11
-#define CA_SET_CE_COUNT 12
-#define CA_SET_DYNABOMB_NUMBER 13
-#define CA_SET_DYNABOMB_SIZE 14
-#define CA_SET_DYNABOMB_POWER 15
-#define CA_TOGGLE_PLAYER_GRAVITY 16
-#define CA_ENABLE_PLAYER_GRAVITY 17
-#define CA_DISABLE_PLAYER_GRAVITY 18
+#define CA_NO_ACTION 0
+#define CA_EXIT_PLAYER 1
+#define CA_KILL_PLAYER 2
+#define CA_MOVE_PLAYER 3
+#define CA_RESTART_LEVEL 4
+#define CA_SHOW_ENVELOPE 5
+#define CA_SET_LEVEL_TIME 6
+#define CA_SET_LEVEL_GEMS 7
+#define CA_SET_LEVEL_SCORE 8
+#define CA_SET_LEVEL_WIND 9
+#define CA_SET_LEVEL_GRAVITY 10
+#define CA_SET_PLAYER_KEYS 11
+#define CA_SET_PLAYER_SPEED 12
+#define CA_SET_PLAYER_SHIELD 13
+#define CA_SET_PLAYER_ARTWORK 14
+#define CA_SET_CE_SCORE 15
+#define CA_SET_CE_VALUE 16
+#define CA_SET_ENGINE_SCAN_MODE 17
+
+#define CA_HEADLINE_LEVEL_ACTIONS 250
+#define CA_HEADLINE_PLAYER_ACTIONS 251
+#define CA_HEADLINE_CE_ACTIONS 252
+#define CA_HEADLINE_ENGINE_ACTIONS 253
+#define CA_UNDEFINED 255
/* values for change action mode for custom elements */
-#define CA_MODE_UNDEFINED 0
-#define CA_MODE_SET 1
-#define CA_MODE_ADD 2
-#define CA_MODE_SUBTRACT 3
-#define CA_MODE_MULTIPLY 4
-#define CA_MODE_DIVIDE 5
-#define CA_MODE_MODULO 6
+#define CA_MODE_UNDEFINED 0
+#define CA_MODE_SET 1
+#define CA_MODE_ADD 2
+#define CA_MODE_SUBTRACT 3
+#define CA_MODE_MULTIPLY 4
+#define CA_MODE_DIVIDE 5
+#define CA_MODE_MODULO 6
/* values for change action parameters for custom elements */
-#define CA_ARG_MIN 0
-#define CA_ARG_0 0
-#define CA_ARG_1 1
-#define CA_ARG_2 2
-#define CA_ARG_3 3
-#define CA_ARG_4 4
-#define CA_ARG_5 5
-#define CA_ARG_10 10
-#define CA_ARG_100 100
-#define CA_ARG_1000 1000
-#define CA_ARG_MAX 9999
-#define CA_ARG_PLAYER 10000
-#define CA_ARG_PLAYER_HEADLINE (CA_ARG_PLAYER + 0)
-#define CA_ARG_PLAYER_1 (CA_ARG_PLAYER + PLAYER_BITS_1)
-#define CA_ARG_PLAYER_2 (CA_ARG_PLAYER + PLAYER_BITS_2)
-#define CA_ARG_PLAYER_3 (CA_ARG_PLAYER + PLAYER_BITS_3)
-#define CA_ARG_PLAYER_4 (CA_ARG_PLAYER + PLAYER_BITS_4)
-#define CA_ARG_PLAYER_ANY (CA_ARG_PLAYER + PLAYER_BITS_ANY)
-#define CA_ARG_PLAYER_TRIGGER (CA_ARG_PLAYER + PLAYER_BITS_TRIGGER)
-#define CA_ARG_NUMBER 20000
-#define CA_ARG_NUMBER_HEADLINE (CA_ARG_NUMBER + 0)
-#define CA_ARG_NUMBER_MIN (CA_ARG_NUMBER + 1)
-#define CA_ARG_NUMBER_MAX (CA_ARG_NUMBER + 2)
-#define CA_ARG_NUMBER_NORMAL (CA_ARG_NUMBER + 3)
-#define CA_ARG_NUMBER_RESET (CA_ARG_NUMBER + 4)
-#define CA_ARG_NUMBER_CE_SCORE (CA_ARG_NUMBER + 5)
-#define CA_ARG_NUMBER_CE_COUNT (CA_ARG_NUMBER + 6)
-#define CA_ARG_NUMBER_CE_DELAY (CA_ARG_NUMBER + 7)
-#define CA_ARG_ELEMENT 30000
-#define CA_ARG_ELEMENT_HEADLINE (CA_ARG_ELEMENT + 0)
-#define CA_ARG_ELEMENT_TARGET (CA_ARG_ELEMENT + 1)
-#define CA_ARG_ELEMENT_TRIGGER (CA_ARG_ELEMENT + 2)
-#define CA_ARG_UNDEFINED 30999
+#define CA_ARG_MIN 0
+#define CA_ARG_0 0
+#define CA_ARG_1 1
+#define CA_ARG_2 2
+#define CA_ARG_3 3
+#define CA_ARG_4 4
+#define CA_ARG_5 5
+#define CA_ARG_6 6
+#define CA_ARG_7 7
+#define CA_ARG_8 8
+#define CA_ARG_9 9
+#define CA_ARG_10 10
+#define CA_ARG_100 100
+#define CA_ARG_1000 1000
+#define CA_ARG_MAX 9999
+#define CA_ARG_PLAYER 10000
+#define CA_ARG_PLAYER_1 (CA_ARG_PLAYER + PLAYER_BITS_1)
+#define CA_ARG_PLAYER_2 (CA_ARG_PLAYER + PLAYER_BITS_2)
+#define CA_ARG_PLAYER_3 (CA_ARG_PLAYER + PLAYER_BITS_3)
+#define CA_ARG_PLAYER_4 (CA_ARG_PLAYER + PLAYER_BITS_4)
+#define CA_ARG_PLAYER_ANY (CA_ARG_PLAYER + PLAYER_BITS_ANY)
+#define CA_ARG_PLAYER_TRIGGER (CA_ARG_PLAYER + PLAYER_BITS_TRIGGER)
+#define CA_ARG_PLAYER_HEADLINE (CA_ARG_PLAYER + 999)
+#define CA_ARG_NUMBER 11000
+#define CA_ARG_NUMBER_MIN (CA_ARG_NUMBER + 0)
+#define CA_ARG_NUMBER_MAX (CA_ARG_NUMBER + 1)
+#define CA_ARG_NUMBER_RESET (CA_ARG_NUMBER + 2)
+#define CA_ARG_NUMBER_CE_SCORE (CA_ARG_NUMBER + 3)
+#define CA_ARG_NUMBER_CE_VALUE (CA_ARG_NUMBER + 4)
+#define CA_ARG_NUMBER_CE_DELAY (CA_ARG_NUMBER + 5)
+#define CA_ARG_NUMBER_LEVEL_TIME (CA_ARG_NUMBER + 6)
+#define CA_ARG_NUMBER_LEVEL_GEMS (CA_ARG_NUMBER + 7)
+#define CA_ARG_NUMBER_LEVEL_SCORE (CA_ARG_NUMBER + 8)
+#define CA_ARG_NUMBER_HEADLINE (CA_ARG_NUMBER + 999)
+#define CA_ARG_ELEMENT 12000
+#define CA_ARG_ELEMENT_RESET (CA_ARG_ELEMENT + 0)
+#define CA_ARG_ELEMENT_TARGET (CA_ARG_ELEMENT + 1)
+#define CA_ARG_ELEMENT_TRIGGER (CA_ARG_ELEMENT + 2)
+#define CA_ARG_ELEMENT_HEADLINE (CA_ARG_ELEMENT + 998)
+#define CA_ARG_ELEMENT_CV_TARGET (CA_ARG_ELEMENT_TARGET)
+#define CA_ARG_ELEMENT_CV_TRIGGER (CA_ARG_ELEMENT_TRIGGER)
+#define CA_ARG_ELEMENT_CV_HEADLINE (CA_ARG_ELEMENT_HEADLINE)
+#define CA_ARG_ELEMENT_NR_TARGET (CA_ARG_ELEMENT + 3)
+#define CA_ARG_ELEMENT_NR_TRIGGER (CA_ARG_ELEMENT + 4)
+#define CA_ARG_ELEMENT_NR_HEADLINE (CA_ARG_ELEMENT + 999)
+#define CA_ARG_SPEED 13000
+#define CA_ARG_SPEED_NOT_MOVING (CA_ARG_SPEED + STEPSIZE_NOT_MOVING)
+#define CA_ARG_SPEED_VERY_SLOW (CA_ARG_SPEED + STEPSIZE_VERY_SLOW)
+#define CA_ARG_SPEED_SLOW (CA_ARG_SPEED + STEPSIZE_SLOW)
+#define CA_ARG_SPEED_NORMAL (CA_ARG_SPEED + STEPSIZE_NORMAL)
+#define CA_ARG_SPEED_FAST (CA_ARG_SPEED + STEPSIZE_FAST)
+#define CA_ARG_SPEED_VERY_FAST (CA_ARG_SPEED + STEPSIZE_VERY_FAST)
+#define CA_ARG_SPEED_EVEN_FASTER (CA_ARG_SPEED + STEPSIZE_EVEN_FASTER)
+#define CA_ARG_SPEED_SLOWER (CA_ARG_SPEED + STEPSIZE_SLOWER)
+#define CA_ARG_SPEED_FASTER (CA_ARG_SPEED + STEPSIZE_FASTER)
+#define CA_ARG_SPEED_RESET (CA_ARG_SPEED + STEPSIZE_RESET)
+#define CA_ARG_SPEED_HEADLINE (CA_ARG_SPEED + 999)
+#define CA_ARG_GRAVITY 14000
+#define CA_ARG_GRAVITY_OFF (CA_ARG_GRAVITY + 0)
+#define CA_ARG_GRAVITY_ON (CA_ARG_GRAVITY + 1)
+#define CA_ARG_GRAVITY_TOGGLE (CA_ARG_GRAVITY + 2)
+#define CA_ARG_GRAVITY_HEADLINE (CA_ARG_GRAVITY + 999)
+#define CA_ARG_DIRECTION 15000
+#define CA_ARG_DIRECTION_NONE (CA_ARG_DIRECTION + MV_NONE)
+#define CA_ARG_DIRECTION_LEFT (CA_ARG_DIRECTION + MV_LEFT)
+#define CA_ARG_DIRECTION_RIGHT (CA_ARG_DIRECTION + MV_RIGHT)
+#define CA_ARG_DIRECTION_UP (CA_ARG_DIRECTION + MV_UP)
+#define CA_ARG_DIRECTION_DOWN (CA_ARG_DIRECTION + MV_DOWN)
+#define CA_ARG_DIRECTION_TRIGGER (CA_ARG_DIRECTION + MV_TRIGGER)
+#define CA_ARG_DIRECTION_TRIGGER_BACK (CA_ARG_DIRECTION + MV_TRIGGER_BACK)
+#define CA_ARG_DIRECTION_HEADLINE (CA_ARG_DIRECTION + 999)
+#define CA_ARG_SHIELD 16000
+#define CA_ARG_SHIELD_OFF (CA_ARG_SHIELD + 0)
+#define CA_ARG_SHIELD_NORMAL (CA_ARG_SHIELD + 1)
+#define CA_ARG_SHIELD_DEADLY (CA_ARG_SHIELD + 2)
+#define CA_ARG_SHIELD_HEADLINE (CA_ARG_SHIELD + 999)
+#define CA_ARG_SCAN_MODE 17000
+#define CA_ARG_SCAN_MODE_NORMAL (CA_ARG_SCAN_MODE + MV_NORMAL)
+#define CA_ARG_SCAN_MODE_REVERSE (CA_ARG_SCAN_MODE + MV_REVERSE)
+#define CA_ARG_SCAN_MODE_HEADLINE (CA_ARG_SCAN_MODE + 999)
+#define CA_ARG_UNDEFINED 65535
/* values for custom move patterns (bits 0 - 3: basic move directions) */
-#define MV_BIT_TOWARDS_PLAYER 4
-#define MV_BIT_AWAY_FROM_PLAYER 5
-#define MV_BIT_ALONG_LEFT_SIDE 6
-#define MV_BIT_ALONG_RIGHT_SIDE 7
-#define MV_BIT_TURNING_LEFT 8
-#define MV_BIT_TURNING_RIGHT 9
-#define MV_BIT_WHEN_PUSHED 10
-#define MV_BIT_MAZE_RUNNER 11
-#define MV_BIT_MAZE_HUNTER 12
-#define MV_BIT_WHEN_DROPPED 13
-#define MV_BIT_TURNING_LEFT_RIGHT 14
-#define MV_BIT_TURNING_RIGHT_LEFT 15
-#define MV_BIT_TURNING_RANDOM 16
+#define MV_BIT_TOWARDS_PLAYER 4
+#define MV_BIT_AWAY_FROM_PLAYER 5
+#define MV_BIT_ALONG_LEFT_SIDE 6
+#define MV_BIT_ALONG_RIGHT_SIDE 7
+#define MV_BIT_TURNING_LEFT 8
+#define MV_BIT_TURNING_RIGHT 9
+#define MV_BIT_WHEN_PUSHED 10
+#define MV_BIT_MAZE_RUNNER 11
+#define MV_BIT_MAZE_HUNTER 12
+#define MV_BIT_WHEN_DROPPED 13
+#define MV_BIT_TURNING_LEFT_RIGHT 14
+#define MV_BIT_TURNING_RIGHT_LEFT 15
+#define MV_BIT_TURNING_RANDOM 16
+#define MV_BIT_WIND_DIRECTION 17
/* values for custom move patterns */
-#define MV_TOWARDS_PLAYER (1 << MV_BIT_TOWARDS_PLAYER)
-#define MV_AWAY_FROM_PLAYER (1 << MV_BIT_AWAY_FROM_PLAYER)
-#define MV_ALONG_LEFT_SIDE (1 << MV_BIT_ALONG_LEFT_SIDE)
-#define MV_ALONG_RIGHT_SIDE (1 << MV_BIT_ALONG_RIGHT_SIDE)
-#define MV_TURNING_LEFT (1 << MV_BIT_TURNING_LEFT)
-#define MV_TURNING_RIGHT (1 << MV_BIT_TURNING_RIGHT)
-#define MV_WHEN_PUSHED (1 << MV_BIT_WHEN_PUSHED)
-#define MV_MAZE_RUNNER (1 << MV_BIT_MAZE_RUNNER)
-#define MV_MAZE_HUNTER (1 << MV_BIT_MAZE_HUNTER)
-#define MV_MAZE_RUNNER_STYLE (MV_MAZE_RUNNER | MV_MAZE_HUNTER)
-#define MV_WHEN_DROPPED (1 << MV_BIT_WHEN_DROPPED)
-#define MV_TURNING_LEFT_RIGHT (1 << MV_BIT_TURNING_LEFT_RIGHT)
-#define MV_TURNING_RIGHT_LEFT (1 << MV_BIT_TURNING_RIGHT_LEFT)
-#define MV_TURNING_RANDOM (1 << MV_BIT_TURNING_RANDOM)
-
-/* values for initial move direction (bits 0 - 3: basic move directions) */
-#define MV_START_BIT_PREVIOUS 4
+#define MV_TOWARDS_PLAYER (1 << MV_BIT_TOWARDS_PLAYER)
+#define MV_AWAY_FROM_PLAYER (1 << MV_BIT_AWAY_FROM_PLAYER)
+#define MV_ALONG_LEFT_SIDE (1 << MV_BIT_ALONG_LEFT_SIDE)
+#define MV_ALONG_RIGHT_SIDE (1 << MV_BIT_ALONG_RIGHT_SIDE)
+#define MV_TURNING_LEFT (1 << MV_BIT_TURNING_LEFT)
+#define MV_TURNING_RIGHT (1 << MV_BIT_TURNING_RIGHT)
+#define MV_WHEN_PUSHED (1 << MV_BIT_WHEN_PUSHED)
+#define MV_MAZE_RUNNER (1 << MV_BIT_MAZE_RUNNER)
+#define MV_MAZE_HUNTER (1 << MV_BIT_MAZE_HUNTER)
+#define MV_MAZE_RUNNER_STYLE (MV_MAZE_RUNNER | MV_MAZE_HUNTER)
+#define MV_WHEN_DROPPED (1 << MV_BIT_WHEN_DROPPED)
+#define MV_TURNING_LEFT_RIGHT (1 << MV_BIT_TURNING_LEFT_RIGHT)
+#define MV_TURNING_RIGHT_LEFT (1 << MV_BIT_TURNING_RIGHT_LEFT)
+#define MV_TURNING_RANDOM (1 << MV_BIT_TURNING_RANDOM)
+#define MV_WIND_DIRECTION (1 << MV_BIT_WIND_DIRECTION)
/* values for initial move direction */
-#define MV_START_AUTOMATIC (MV_NO_MOVING)
-#define MV_START_LEFT (MV_LEFT)
-#define MV_START_RIGHT (MV_RIGHT)
-#define MV_START_UP (MV_UP)
-#define MV_START_DOWN (MV_DOWN)
-#define MV_START_RANDOM (MV_ALL_DIRECTIONS)
-#define MV_START_PREVIOUS (1 << MV_START_BIT_PREVIOUS)
+#define MV_START_NONE (MV_NONE)
+#define MV_START_AUTOMATIC (MV_NONE)
+#define MV_START_LEFT (MV_LEFT)
+#define MV_START_RIGHT (MV_RIGHT)
+#define MV_START_UP (MV_UP)
+#define MV_START_DOWN (MV_DOWN)
+#define MV_START_RANDOM (MV_ALL_DIRECTIONS)
+#define MV_START_PREVIOUS (MV_PREVIOUS)
/* values for elements left behind by custom elements */
-#define LEAVE_TYPE_UNLIMITED 0
-#define LEAVE_TYPE_LIMITED 1
+#define LEAVE_TYPE_UNLIMITED 0
+#define LEAVE_TYPE_LIMITED 1
/* values for slippery property for custom elements */
-#define SLIPPERY_ANY_RANDOM 0
-#define SLIPPERY_ANY_LEFT_RIGHT 1
-#define SLIPPERY_ANY_RIGHT_LEFT 2
-#define SLIPPERY_ONLY_LEFT 3
-#define SLIPPERY_ONLY_RIGHT 4
+#define SLIPPERY_ANY_RANDOM 0
+#define SLIPPERY_ANY_LEFT_RIGHT 1
+#define SLIPPERY_ANY_RIGHT_LEFT 2
+#define SLIPPERY_ONLY_LEFT 3
+#define SLIPPERY_ONLY_RIGHT 4
/* values for explosion type for custom elements */
-#define EXPLODES_3X3 0
-#define EXPLODES_1X1 1
-#define EXPLODES_CROSS 2
+#define EXPLODES_3X3 0
+#define EXPLODES_1X1 1
+#define EXPLODES_CROSS 2
/* macros for configurable properties */
#define IS_DIGGABLE(e) HAS_PROPERTY(e, EP_DIGGABLE)
#define IS_KEYGATE(e) HAS_PROPERTY(e, EP_KEYGATE)
#define IS_AMOEBOID(e) HAS_PROPERTY(e, EP_AMOEBOID)
#define IS_AMOEBALIVE(e) HAS_PROPERTY(e, EP_AMOEBALIVE)
-#define HAS_CONTENT(e) HAS_PROPERTY(e, EP_HAS_CONTENT)
+#define HAS_EDITOR_CONTENT(e) HAS_PROPERTY(e, EP_HAS_EDITOR_CONTENT)
#define CAN_TURN_EACH_MOVE(e) HAS_PROPERTY(e, EP_CAN_TURN_EACH_MOVE)
#define CAN_GROW(e) HAS_PROPERTY(e, EP_CAN_GROW)
#define IS_ACTIVE_BOMB(e) HAS_PROPERTY(e, EP_ACTIVE_BOMB)
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)
+#define CAN_BE_CLONED_BY_ANDROID(e) \
+ HAS_PROPERTY(e, EP_CAN_BE_CLONED_BY_ANDROID)
+
+#define IS_EDITOR_CASCADE(e) HAS_PROPERTY(e, EP_EDITOR_CASCADE)
+#define IS_EDITOR_CASCADE_ACTIVE(e) \
+ HAS_PROPERTY(e, EP_EDITOR_CASCADE_ACTIVE)
+#define IS_EDITOR_CASCADE_INACTIVE(e) \
+ HAS_PROPERTY(e, EP_EDITOR_CASCADE_INACTIVE)
+
#define HAS_ACTION(e) HAS_PROPERTY(e, EP_HAS_ACTION)
#define CAN_CHANGE_OR_HAS_ACTION(e) \
HAS_PROPERTY(e, EP_CAN_CHANGE_OR_HAS_ACTION)
#define IS_RND_GATE_GRAY(e) ((e) >= EL_GATE_1_GRAY && \
(e) <= EL_GATE_4_GRAY)
+#define IS_RND_GATE_GRAY_ACTIVE(e) ((e) >= EL_GATE_1_GRAY_ACTIVE && \
+ (e) <= EL_GATE_4_GRAY_ACTIVE)
#define IS_EM_GATE_GRAY(e) ((e) >= EL_EM_GATE_1_GRAY && \
(e) <= EL_EM_GATE_4_GRAY)
+#define IS_EM_GATE_GRAY_ACTIVE(e) ((e) >= EL_EM_GATE_1_GRAY_ACTIVE && \
+ (e) <= EL_EM_GATE_4_GRAY_ACTIVE)
#define IS_EMC_GATE_GRAY(e) ((e) >= EL_EMC_GATE_5_GRAY && \
(e) <= EL_EMC_GATE_8_GRAY)
+#define IS_EMC_GATE_GRAY_ACTIVE(e) ((e) >= EL_EMC_GATE_5_GRAY_ACTIVE && \
+ (e) <= EL_EMC_GATE_8_GRAY_ACTIVE)
#define IS_GATE_GRAY(e) (IS_RND_GATE_GRAY(e) || \
IS_EM_GATE_GRAY(e) || \
IS_EMC_GATE_GRAY(e))
+#define IS_GATE_GRAY_ACTIVE(e) (IS_RND_GATE_GRAY_ACTIVE(e) || \
+ IS_EM_GATE_GRAY_ACTIVE(e) || \
+ IS_EMC_GATE_GRAY_ACTIVE(e))
#define RND_GATE_GRAY_NR(e) ((e) - EL_GATE_1_GRAY)
+#define RND_GATE_GRAY_ACTIVE_NR(e) ((e) - EL_GATE_1_GRAY_ACTIVE)
#define EM_GATE_GRAY_NR(e) ((e) - EL_EM_GATE_1_GRAY)
+#define EM_GATE_GRAY_ACTIVE_NR(e) ((e) - EL_EM_GATE_1_GRAY_ACTIVE)
#define EMC_GATE_GRAY_NR(e) ((e) - EL_EMC_GATE_5_GRAY + 4)
+#define EMC_GATE_GRAY_ACTIVE_NR(e) ((e) - EL_EMC_GATE_5_GRAY_ACTIVE + 4)
#define GATE_GRAY_NR(e) (IS_RND_GATE_GRAY(e) ? RND_GATE_GRAY_NR(e) : \
IS_EM_GATE_GRAY(e) ? EM_GATE_GRAY_NR(e) : \
IS_EMC_GATE_GRAY(e) ? EMC_GATE_GRAY_NR(e) : 0)
#define GFX_ELEMENT(e) (element_info[e].use_gfx_element ? \
element_info[e].gfx_element : e)
+#if 1
+#define TILE_GFX_ELEMENT(x, y) \
+ (GfxElement[x][y] != EL_UNDEFINED && \
+ Feld[x][y] != EL_EXPLOSION ? \
+ GfxElement[x][y] : Feld[x][y])
+#else
+#define TILE_GFX_ELEMENT(x, y) \
+ GFX_ELEMENT(GfxElement[x][y] != EL_UNDEFINED && \
+ Feld[x][y] != EL_EXPLOSION ? \
+ GfxElement[x][y] : Feld[x][y])
+#endif
+
/* !!! "use sound" deactivated due to problems with level "bug machine" !!! */
/* (solution: add separate "use sound of element" to level file and editor) */
#if 0
#define SND_ELEMENT(e) (e)
#endif
+#if 1
+#define GROUP_NR(e) ((e) - EL_GROUP_START)
+#define IS_IN_GROUP(e, nr) (element_info[e].in_group[nr] == TRUE)
+#define IS_IN_GROUP_EL(e, ge) (IS_IN_GROUP(e, (ge) - EL_GROUP_START))
+
+#define IS_EQUAL_OR_IN_GROUP(e, ge) \
+ (IS_GROUP_ELEMENT(ge) ? IS_IN_GROUP(e, GROUP_NR(ge)) : (e) == (ge))
+#endif
+
#define IS_PLAYER(x, y) (ELEM_IS_PLAYER(StorePlayer[x][y]))
#define IS_FREE(x, y) (Feld[x][y] == EL_EMPTY && !IS_PLAYER(x, y))
#define IS_FALLING(x,y) (MovPos[x][y] != 0 && MovDir[x][y] == MV_DOWN)
#define IS_BLOCKED(x,y) (Feld[x][y] == EL_BLOCKED)
+#define IS_MV_DIAGONAL(x) ((x) & MV_HORIZONTAL && (x) & MV_VERTICAL)
+
#define EL_CHANGED(e) ((e) == EL_ROCK ? EL_EMERALD : \
(e) == EL_BD_ROCK ? EL_BD_DIAMOND : \
(e) == EL_EMERALD ? EL_DIAMOND : \
#define PLAYER_NR_GFX(g,i) ((g) + i * (IMG_PLAYER_2 - IMG_PLAYER_1))
+#define GET_PLAYER_ELEMENT(e) ((e) >= EL_PLAYER_1 && (e) <= EL_PLAYER_4 ? \
+ (e) : EL_PLAYER_1)
+
+#define GET_PLAYER_NR(e) (GET_PLAYER_ELEMENT(e) - EL_PLAYER_1)
+
#define ANIM_FRAMES(g) (graphic_info[g].anim_frames)
#define ANIM_DELAY(g) (graphic_info[g].anim_delay)
#define ANIM_MODE(g) (graphic_info[g].anim_mode)
#define IS_LOOP_SOUND(s) (sound_info[s].loop)
+#define EL_CASCADE_ACTIVE(e) (IS_EDITOR_CASCADE_INACTIVE(e) ? (e) + 1 : (e))
+#define EL_CASCADE_INACTIVE(e) (IS_EDITOR_CASCADE_ACTIVE(e) ? (e) - 1 : (e))
+#define EL_CASCADE_TOGGLE(e) (IS_EDITOR_CASCADE_INACTIVE(e) ? (e) + 1 : \
+ IS_EDITOR_CASCADE_ACTIVE(e) ? (e) - 1 : (e))
+
+#define EL_NAME(e) ((e) >= 0 ? element_info[e].token_name : "(?)")
/* fundamental game speed values */
#define ONE_SECOND_DELAY 1000 /* delay value for one second */
#define MAX_CHANGE_PAGES 32
#define MIN_ELEMENTS_IN_GROUP 1
#define MAX_ELEMENTS_IN_GROUP 16
+#define MIN_ANDROID_ELEMENTS 1
+#define MAX_ANDROID_ELEMENTS 16
/* values for elements with content */
#define MIN_ELEMENT_CONTENTS 1
#define STD_ELEMENT_CONTENTS 4
#define MAX_ELEMENT_CONTENTS 8
-#define NUM_MAGIC_BALL_CONTENTS 8
#define LEVEL_SCORE_ELEMENTS 16 /* level elements with score */
#define EL_EM_GATE_3_GRAY 252
#define EL_EM_GATE_4_GRAY 253
-#define EL_UNUSED_254 254
-#define EL_UNUSED_255 255
+#define EL_EM_DYNAMITE 254
+#define EL_EM_DYNAMITE_ACTIVE 255
#define EL_PEARL 256
#define EL_CRYSTAL 257
#define EL_TRIGGER_ELEMENT 657
#define EL_TRIGGER_PLAYER 658
+/* SP style elements */
#define EL_SP_GRAVITY_ON_PORT_RIGHT 659
#define EL_SP_GRAVITY_ON_PORT_DOWN 660
#define EL_SP_GRAVITY_ON_PORT_LEFT 661
#define EL_SP_GRAVITY_OFF_PORT_LEFT 665
#define EL_SP_GRAVITY_OFF_PORT_UP 666
-
-/* the following EMC style elements are currently not implemented in R'n'D */
+/* EMC style elements */
#define EL_BALLOON_SWITCH_NONE 667
#define EL_EMC_GATE_5 668
#define EL_EMC_GATE_6 669
#define EL_EMC_FAKE_ACID 703
#define EL_EMC_DRIPPER 704
-#define NUM_FILE_ELEMENTS 705
+#define EL_TRIGGER_CE_VALUE 705
+
+#define NUM_FILE_ELEMENTS 706
/* "real" (and therefore drawable) runtime elements */
#define EL_BD_MAGIC_WALL_EMPTYING (EL_FIRST_RUNTIME_REAL + 42)
#define EL_MAGIC_WALL_DEAD (EL_FIRST_RUNTIME_REAL + 43)
#define EL_BD_MAGIC_WALL_DEAD (EL_FIRST_RUNTIME_REAL + 44)
+#define EL_EMC_FAKE_GRASS_ACTIVE (EL_FIRST_RUNTIME_REAL + 45)
+#define EL_GATE_1_GRAY_ACTIVE (EL_FIRST_RUNTIME_REAL + 46)
+#define EL_GATE_2_GRAY_ACTIVE (EL_FIRST_RUNTIME_REAL + 47)
+#define EL_GATE_3_GRAY_ACTIVE (EL_FIRST_RUNTIME_REAL + 48)
+#define EL_GATE_4_GRAY_ACTIVE (EL_FIRST_RUNTIME_REAL + 49)
+#define EL_EM_GATE_1_GRAY_ACTIVE (EL_FIRST_RUNTIME_REAL + 50)
+#define EL_EM_GATE_2_GRAY_ACTIVE (EL_FIRST_RUNTIME_REAL + 51)
+#define EL_EM_GATE_3_GRAY_ACTIVE (EL_FIRST_RUNTIME_REAL + 52)
+#define EL_EM_GATE_4_GRAY_ACTIVE (EL_FIRST_RUNTIME_REAL + 53)
+#define EL_EMC_GATE_5_GRAY_ACTIVE (EL_FIRST_RUNTIME_REAL + 54)
+#define EL_EMC_GATE_6_GRAY_ACTIVE (EL_FIRST_RUNTIME_REAL + 55)
+#define EL_EMC_GATE_7_GRAY_ACTIVE (EL_FIRST_RUNTIME_REAL + 56)
+#define EL_EMC_GATE_8_GRAY_ACTIVE (EL_FIRST_RUNTIME_REAL + 57)
+#define EL_EMC_DRIPPER_ACTIVE (EL_FIRST_RUNTIME_REAL + 58)
+#define EL_EMC_SPRING_BUMPER_ACTIVE (EL_FIRST_RUNTIME_REAL + 59)
/* "unreal" (and therefore not drawable) runtime elements */
-#define EL_FIRST_RUNTIME_UNREAL (EL_FIRST_RUNTIME_REAL + 45)
+#define EL_FIRST_RUNTIME_UNREAL (EL_FIRST_RUNTIME_REAL + 60)
#define EL_BLOCKED (EL_FIRST_RUNTIME_UNREAL + 0)
#define EL_EXPLOSION (EL_FIRST_RUNTIME_UNREAL + 1)
#define EL_QUICKSAND_FILLING (EL_FIRST_RUNTIME_UNREAL + 15)
#define EL_MAGIC_WALL_FILLING (EL_FIRST_RUNTIME_UNREAL + 16)
#define EL_BD_MAGIC_WALL_FILLING (EL_FIRST_RUNTIME_UNREAL + 17)
+#define EL_ELEMENT_SNAPPING (EL_FIRST_RUNTIME_UNREAL + 18)
+#define EL_DIAGONAL_SHRINKING (EL_FIRST_RUNTIME_UNREAL + 19)
+#define EL_DIAGONAL_GROWING (EL_FIRST_RUNTIME_UNREAL + 20)
+
+#define NUM_RUNTIME_ELEMENTS (EL_FIRST_RUNTIME_UNREAL + 21)
/* dummy elements (never used as game elements, only used as graphics) */
-#define EL_FIRST_DUMMY (EL_FIRST_RUNTIME_UNREAL + 18)
+#define EL_FIRST_DUMMY NUM_RUNTIME_ELEMENTS
#define EL_STEELWALL_TOPLEFT (EL_FIRST_DUMMY + 0)
#define EL_STEELWALL_TOPRIGHT (EL_FIRST_DUMMY + 1)
#define EL_INTERNAL_CLIPBOARD_GROUP (EL_FIRST_INTERNAL + 2)
#define EL_INTERNAL_DUMMY (EL_FIRST_INTERNAL + 3)
+#define EL_INTERNAL_CASCADE_BD (EL_FIRST_INTERNAL + 4)
+#define EL_INTERNAL_CASCADE_BD_ACTIVE (EL_FIRST_INTERNAL + 5)
+#define EL_INTERNAL_CASCADE_EM (EL_FIRST_INTERNAL + 6)
+#define EL_INTERNAL_CASCADE_EM_ACTIVE (EL_FIRST_INTERNAL + 7)
+#define EL_INTERNAL_CASCADE_EMC (EL_FIRST_INTERNAL + 8)
+#define EL_INTERNAL_CASCADE_EMC_ACTIVE (EL_FIRST_INTERNAL + 9)
+#define EL_INTERNAL_CASCADE_RND (EL_FIRST_INTERNAL + 10)
+#define EL_INTERNAL_CASCADE_RND_ACTIVE (EL_FIRST_INTERNAL + 11)
+#define EL_INTERNAL_CASCADE_SB (EL_FIRST_INTERNAL + 12)
+#define EL_INTERNAL_CASCADE_SB_ACTIVE (EL_FIRST_INTERNAL + 13)
+#define EL_INTERNAL_CASCADE_SP (EL_FIRST_INTERNAL + 14)
+#define EL_INTERNAL_CASCADE_SP_ACTIVE (EL_FIRST_INTERNAL + 15)
+#define EL_INTERNAL_CASCADE_DC (EL_FIRST_INTERNAL + 16)
+#define EL_INTERNAL_CASCADE_DC_ACTIVE (EL_FIRST_INTERNAL + 17)
+#define EL_INTERNAL_CASCADE_DX (EL_FIRST_INTERNAL + 18)
+#define EL_INTERNAL_CASCADE_DX_ACTIVE (EL_FIRST_INTERNAL + 19)
+#define EL_INTERNAL_CASCADE_CHARS (EL_FIRST_INTERNAL + 20)
+#define EL_INTERNAL_CASCADE_CHARS_ACTIVE (EL_FIRST_INTERNAL + 21)
+#define EL_INTERNAL_CASCADE_CE (EL_FIRST_INTERNAL + 22)
+#define EL_INTERNAL_CASCADE_CE_ACTIVE (EL_FIRST_INTERNAL + 23)
+#define EL_INTERNAL_CASCADE_GE (EL_FIRST_INTERNAL + 24)
+#define EL_INTERNAL_CASCADE_GE_ACTIVE (EL_FIRST_INTERNAL + 25)
+#define EL_INTERNAL_CASCADE_USER (EL_FIRST_INTERNAL + 26)
+#define EL_INTERNAL_CASCADE_USER_ACTIVE (EL_FIRST_INTERNAL + 27)
+#define EL_INTERNAL_CASCADE_GENERIC (EL_FIRST_INTERNAL + 28)
+#define EL_INTERNAL_CASCADE_GENERIC_ACTIVE (EL_FIRST_INTERNAL + 29)
+#define EL_INTERNAL_CASCADE_DYNAMIC (EL_FIRST_INTERNAL + 30)
+#define EL_INTERNAL_CASCADE_DYNAMIC_ACTIVE (EL_FIRST_INTERNAL + 31)
+
#define EL_INTERNAL_CLIPBOARD_START (EL_FIRST_INTERNAL + 0)
#define EL_INTERNAL_CLIPBOARD_END (EL_FIRST_INTERNAL + 2)
#define EL_INTERNAL_START (EL_FIRST_INTERNAL + 0)
-#define EL_INTERNAL_END (EL_FIRST_INTERNAL + 3)
+#define EL_INTERNAL_END (EL_FIRST_INTERNAL + 31)
-#define MAX_NUM_ELEMENTS (EL_FIRST_INTERNAL + 4)
+#define MAX_NUM_ELEMENTS (EL_FIRST_INTERNAL + 32)
/* values for graphics/sounds action types */
#define ACTION_TURNING_FROM_DOWN 46
#define ACTION_SMASHED_BY_ROCK 47
#define ACTION_SMASHED_BY_SPRING 48
-#define ACTION_SLURPED_BY_SPRING 49
+#define ACTION_EATING 49
#define ACTION_TWINKLING 50
#define ACTION_SPLASHING 51
-#define ACTION_OTHER 52
-
-#define NUM_ACTIONS 53
+#define ACTION_PAGE_1 52
+#define ACTION_PAGE_2 53
+#define ACTION_PAGE_3 54
+#define ACTION_PAGE_4 55
+#define ACTION_PAGE_5 56
+#define ACTION_PAGE_6 57
+#define ACTION_PAGE_7 58
+#define ACTION_PAGE_8 59
+#define ACTION_PAGE_9 60
+#define ACTION_PAGE_10 61
+#define ACTION_PAGE_11 62
+#define ACTION_PAGE_12 63
+#define ACTION_PAGE_13 64
+#define ACTION_PAGE_14 65
+#define ACTION_PAGE_15 66
+#define ACTION_PAGE_16 67
+#define ACTION_PAGE_17 68
+#define ACTION_PAGE_18 69
+#define ACTION_PAGE_19 70
+#define ACTION_PAGE_20 71
+#define ACTION_PAGE_21 72
+#define ACTION_PAGE_22 73
+#define ACTION_PAGE_23 74
+#define ACTION_PAGE_24 75
+#define ACTION_PAGE_25 76
+#define ACTION_PAGE_26 77
+#define ACTION_PAGE_27 78
+#define ACTION_PAGE_28 79
+#define ACTION_PAGE_29 80
+#define ACTION_PAGE_30 81
+#define ACTION_PAGE_31 82
+#define ACTION_PAGE_32 83
+#define ACTION_OTHER 84
+
+#define NUM_ACTIONS 85
#define ACTION_BORING_LAST ACTION_BORING_10
#define ACTION_SLEEPING_LAST ACTION_SLEEPING_3
/* program information and versioning definitions */
-
-#define RELEASE_311 FALSE
-
-#if RELEASE_311
-#define PROGRAM_VERSION_MAJOR 3
-#define PROGRAM_VERSION_MINOR 1
-#define PROGRAM_VERSION_PATCH 2
-#define PROGRAM_VERSION_BUILD 0
-#else
-/* !!! make sure that packaging script can find unique version number !!! */
#define PROGRAM_VERSION_MAJOR 3
#define PROGRAM_VERSION_MINOR 2
#define PROGRAM_VERSION_PATCH 0
-#define PROGRAM_VERSION_BUILD 3
-#endif
+#define PROGRAM_VERSION_BUILD 7
#define PROGRAM_TITLE_STRING "Rocks'n'Diamonds"
#define PROGRAM_AUTHOR_STRING "Holger Schemel"
-#define PROGRAM_COPYRIGHT_STRING "Copyright ©1995-2005 by Holger Schemel"
+#define PROGRAM_COPYRIGHT_STRING "Copyright ©1995-2006 by Holger Schemel"
#define ICON_TITLE_STRING PROGRAM_TITLE_STRING
#define COOKIE_PREFIX "ROCKSNDIAMONDS"
struct DoorInfo
{
+ int width;
+ int height;
int step_offset;
int step_delay;
int anim_mode;
int Score;
};
+struct Content
+{
+ int e[3][3];
+};
+
struct PlayerInfo
{
boolean present; /* player present in level playfield */
int GfxAction;
- boolean use_murphy_graphic;
+ boolean use_murphy;
+ int artwork_element;
boolean block_last_field;
int block_delay_adjustment; /* needed for different engine versions */
boolean is_bored;
boolean is_sleeping;
+ boolean cannot_move;
+
int frame_counter_bored;
int frame_counter_sleeping;
int move_delay;
int move_delay_value;
+ int move_delay_value_next;
int move_delay_reset_counter;
int push_delay;
int score[LEVEL_SCORE_ELEMENTS];
- int yamyam_content[MAX_ELEMENT_CONTENTS][3][3];
+ struct Content yamyam_content[MAX_ELEMENT_CONTENTS];
int num_yamyam_contents;
int amoeba_speed;
int amoeba_content;
+ int game_of_life[4];
+ int biomaze[4];
+
int time_magic_wall;
int time_wheel;
int time_light;
int time_timegate;
+ int shield_normal_time;
+ int shield_deadly_time;
+
+ int extra_time;
+ int time_orb_time;
+
+ int extra_time_score;
+
+ int start_element[MAX_PLAYERS];
+ boolean use_start_element[MAX_PLAYERS];
+
+ int artwork_element[MAX_PLAYERS];
+ boolean use_artwork_element[MAX_PLAYERS];
+
+ int explosion_element[MAX_PLAYERS];
+ boolean use_explosion_element[MAX_PLAYERS];
+
+#if 1
/* values for the new EMC elements */
int android_move_time;
int android_clone_time;
int lenses_time;
int magnify_time;
int wind_direction_initial;
- int ball_content[NUM_MAGIC_BALL_CONTENTS][3][3];
+
+ struct Content ball_content[MAX_ELEMENT_CONTENTS];
+ int num_ball_contents;
+
+#if 0
boolean android_array[16];
+#endif
+ int num_android_clone_elements;
+ int android_clone_element[MAX_ANDROID_ELEMENTS];
+#endif
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;
+ int initial_player_stepsize; /* initial player speed */
+
boolean initial_gravity;
boolean em_slippery_gems; /* EM style "gems slip from wall" behaviour */
boolean use_spring_bug; /* for compatibility with old levels */
+ boolean use_time_orb_bug; /* for compatibility with old levels */
boolean instant_relocation; /* no visual delay when relocating player */
boolean can_pass_to_walkable; /* player can pass to empty or walkable tile */
boolean grow_into_diggable; /* amoeba can grow into anything diggable */
+ boolean continuous_snapping; /* repeated snapping without releasing key */
+ boolean block_snap_field; /* snapping blocks field to show animation */
boolean block_last_field; /* player blocks previous field while moving */
boolean sp_block_last_field; /* player blocks previous field while moving */
/* (for the latest engine version, these flags should always be "FALSE") */
boolean use_change_when_pushing_bug;
boolean use_block_last_field_bug;
+ boolean max_num_changes_per_frame;
+ boolean use_reverse_scan_direction;
/* variable within running game */
int yamyam_content_nr;
int belt_dir[4];
int belt_dir_nr[4];
int switchgate_pos;
- int balloon_dir;
+ int wind_direction;
boolean gravity;
boolean explosions_delayed;
boolean envelope_active;
+#if 1
+ /* values for the new EMC elements */
+ int lenses_time_left;
+ int magnify_time_left;
+ boolean ball_state;
+ int ball_content_nr;
+#endif
+
/* values for player idle animation (no effect on engine) */
int player_boring_delay_fixed;
int player_boring_delay_random;
/* values for special game initialization control */
boolean restart_level;
+
+ /* values for special game control */
+ int centered_player_nr;
+ int centered_player_nr_next;
};
struct GlobalInfo
int trigger_side; /* side triggering change */
int trigger_page; /* page triggering change */
- short target_element; /* target element after change */
+ int target_element; /* target element after change */
int delay_fixed; /* added frame delay before changed (fixed) */
int delay_random; /* added frame delay before changed (random) */
int delay_frames; /* either 1 (frames) or 50 (seconds; 50 fps) */
- short trigger_element; /* element triggering change */
+ int trigger_element; /* element triggering change */
- int target_content[3][3]; /* elements for extended change target */
+ struct Content target_content;/* elements for extended change target */
boolean use_target_content; /* use extended change target */
boolean only_if_complete; /* only use complete target content */
boolean use_random_replace; /* use random value for replacing elements */
void (*post_change_function)(int x, int y);
short actual_trigger_element; /* element that actually triggered change */
+ int actual_trigger_side; /* element side that triggered the change */
int actual_trigger_player; /* player which actually triggered change */
+ int actual_trigger_ce_value; /* CE value of element that triggered change */
boolean can_change_or_has_action; /* can_change | has_action */
struct ElementGroupInfo
{
int num_elements; /* number of elements in this group */
- short element[MAX_ELEMENTS_IN_GROUP]; /* list of elements in this group */
+ int element[MAX_ELEMENTS_IN_GROUP]; /* list of elements in this group */
int choice_mode; /* how to choose element from group */
/* ---------- graphic and sound definitions ---------- */
int graphic[NUM_ACTIONS]; /* default graphics for several actions */
- int direction_graphic[NUM_ACTIONS][NUM_DIRECTIONS];
+ int direction_graphic[NUM_ACTIONS][NUM_DIRECTIONS_FULL];
/* special graphics for left/right/up/down */
int crumbled[NUM_ACTIONS]; /* crumbled graphics for several actions */
- int direction_crumbled[NUM_ACTIONS][NUM_DIRECTIONS];
+ int direction_crumbled[NUM_ACTIONS][NUM_DIRECTIONS_FULL];
/* crumbled graphics for left/right/up/down */
int special_graphic[NUM_SPECIAL_GFX_ARGS];
/* ---------- special element property values ---------- */
+ unsigned long properties[NUM_EP_BITFIELDS]; /* element base properties */
+
boolean use_gfx_element; /* use custom graphic element */
- short gfx_element; /* optional custom graphic element */
+ int gfx_element; /* optional custom graphic element */
int access_direction; /* accessible from which direction */
int collect_score_initial; /* initial score value for collecting */
int collect_count_initial; /* initial count value for collecting */
+ int ce_value_fixed_initial; /* initial value for custom variable (fix) */
+ int ce_value_random_initial; /* initial value for custom variable (rnd) */
+ boolean use_last_ce_value; /* use value from element before change */
+
int push_delay_fixed; /* constant delay before pushing */
int push_delay_random; /* additional random delay before pushing */
int drop_delay_fixed; /* constant delay after dropping */
int slippery_type; /* how/where other elements slip away */
- int content[3][3]; /* new elements after explosion */
+ struct Content content; /* new elements after explosion */
int explosion_type; /* type of explosion, like 3x3, 3+3 or 1x1 */
int explosion_delay; /* duration of explosion of this element */
extern short MovDelay[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short ChangeDelay[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short ChangePage[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
-extern short Count[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+extern short CustomValue[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short Store[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short Store2[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short StorePlayer[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short Back[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern boolean Stop[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern boolean Pushed[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
-extern boolean Changed[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+extern short ChangeCount[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short ChangeEvent[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short WasJustMoving[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern short WasJustFalling[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern int RunnerVisit[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern int PlayerVisit[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+#if 0
extern unsigned long Properties[MAX_NUM_ELEMENTS][NUM_EP_BITFIELDS];
+#endif
extern int GfxFrame[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
extern int GfxRandom[MAX_LEV_FIELDX][MAX_LEV_FIELDY];