#define EP_CAN_SMASH 69
#define EP_CAN_EXPLODE 70
#define EP_CAN_EXPLODE_3X3 71
+#define EP_SP_PORT 72
/* values for internal purpose only (level editor) */
-#define EP_EXPLODE_RESULT 72
-#define EP_WALK_TO_OBJECT 73
-#define EP_DEADLY 74
+#define EP_EXPLODE_RESULT 73
+#define EP_WALK_TO_OBJECT 74
+#define EP_DEADLY 75
-#define NUM_ELEMENT_PROPERTIES 75
+#define NUM_ELEMENT_PROPERTIES 76
#define NUM_EP_BITFIELDS ((NUM_ELEMENT_PROPERTIES + 31) / 32)
#define EP_BITFIELD_BASE 0
#define MV_BIT_TURNING_LEFT_RIGHT 14
#define MV_BIT_TURNING_RIGHT_LEFT 15
#define MV_BIT_TURNING_RANDOM 16
+#define MV_BIT_PREVIOUS 17
/* values for special move patterns for custom elements */
#define MV_HORIZONTAL (MV_LEFT | MV_RIGHT)
#define MV_VERTICAL (MV_UP | MV_DOWN)
#define MV_ALL_DIRECTIONS (MV_HORIZONTAL | MV_VERTICAL)
#define MV_ANY_DIRECTION (MV_ALL_DIRECTIONS)
+#define MV_RANDOM (MV_ALL_DIRECTIONS)
+#define MV_AUTOMATIC (MV_NO_MOVING)
#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_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_PREVIOUS (1 << MV_BIT_PREVIOUS)
+
+/* values for elements left behind by custom elements */
+#define LEAVE_TYPE_UNLIMITED 0
+#define LEAVE_TYPE_LIMITED 1
/* values for slippery property for custom elements */
#define SLIPPERY_ANY_RANDOM 0
#define CAN_SMASH(e) HAS_PROPERTY(e, EP_CAN_SMASH)
#define CAN_EXPLODE(e) HAS_PROPERTY(e, EP_CAN_EXPLODE)
#define CAN_EXPLODE_3X3(e) HAS_PROPERTY(e, EP_CAN_EXPLODE_3X3)
+#define IS_SP_PORT(e) HAS_PROPERTY(e, EP_SP_PORT)
/* special macros used in game engine */
#define IS_CUSTOM_ELEMENT(e) ((e) >= EL_CUSTOM_START && \
#define MAX_ENVELOPE_TEXT_LEN (MAX_ENVELOPE_XSIZE * MAX_ENVELOPE_YSIZE)
#define MIN_CHANGE_PAGES 1
#define MAX_CHANGE_PAGES 16
+#define MIN_ELEMENTS_IN_GROUP 1
+#define MAX_ELEMENTS_IN_GROUP 16
/* values for elements with content */
#define MIN_ELEMENT_CONTENTS 1
#define EL_DARK_YAMYAM 60
#define EL_BD_MAGIC_WALL 61
#define EL_INVISIBLE_STEELWALL 62
-
-#define EL_MAZE_RUNNER 63
-
+#define EL_SOKOBAN_FIELD_PLAYER 63
#define EL_DYNABOMB_INCREASE_NUMBER 64
#define EL_DYNABOMB_INCREASE_SIZE 65
#define EL_DYNABOMB_INCREASE_POWER 66
#define EL_EXPANDABLE_WALL_GROWING (EL_FIRST_RUNTIME_UNREAL + 8)
#define EL_FLAMES (EL_FIRST_RUNTIME_UNREAL + 9)
#define EL_PLAYER_IS_LEAVING (EL_FIRST_RUNTIME_UNREAL + 10)
-#define EL_QUICKSAND_FILLING (EL_FIRST_RUNTIME_UNREAL + 11)
-#define EL_MAGIC_WALL_FILLING (EL_FIRST_RUNTIME_UNREAL + 12)
-#define EL_BD_MAGIC_WALL_FILLING (EL_FIRST_RUNTIME_UNREAL + 13)
+#define EL_PLAYER_IS_EXPLODING_1 (EL_FIRST_RUNTIME_UNREAL + 11)
+#define EL_PLAYER_IS_EXPLODING_2 (EL_FIRST_RUNTIME_UNREAL + 12)
+#define EL_PLAYER_IS_EXPLODING_3 (EL_FIRST_RUNTIME_UNREAL + 13)
+#define EL_PLAYER_IS_EXPLODING_4 (EL_FIRST_RUNTIME_UNREAL + 14)
+#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)
/* dummy elements (never used as game elements, only used as graphics) */
-#define EL_FIRST_DUMMY (EL_FIRST_RUNTIME_UNREAL + 14)
+#define EL_FIRST_DUMMY (EL_FIRST_RUNTIME_UNREAL + 18)
#define EL_STEELWALL_TOPLEFT (EL_FIRST_DUMMY + 0)
#define EL_STEELWALL_TOPRIGHT (EL_FIRST_DUMMY + 1)
#define EL_BD_DEFAULT (EL_FIRST_DUMMY + 22)
#define EL_SP_DEFAULT (EL_FIRST_DUMMY + 23)
#define EL_SB_DEFAULT (EL_FIRST_DUMMY + 24)
-#define EL_DUMMY (EL_FIRST_DUMMY + 25)
-#define MAX_NUM_ELEMENTS (EL_FIRST_DUMMY + 26)
+/* internal elements (only used for internal purposes like copying) */
+#define EL_FIRST_INTERNAL (EL_FIRST_DUMMY + 25)
+
+#define EL_INTERNAL_EDITOR (EL_FIRST_INTERNAL + 0)
+#define EL_INTERNAL_DUMMY (EL_FIRST_INTERNAL + 1)
+
+#define MAX_NUM_ELEMENTS (EL_FIRST_INTERNAL + 2)
/* values for graphics/sounds action types */
{
int nr;
int type;
+ boolean packed;
+ char *basename;
char *filename;
};
int other_action; /* change triggered by other element actions */
};
+struct ElementGroupInfo
+{
+ int num_elements; /* number of elements in this group */
+ short element[MAX_ELEMENTS_IN_GROUP]; /* list of elements in this group */
+
+ int choice_mode; /* how to choose element from group */
+
+ /* ---------- internal values used at runtime when playing ---------- */
+
+ /* the following is the same as above, but with recursively resolved group
+ elements (group elements may also contain further group elements!) */
+ int num_elements_resolved;
+ short element_resolved[NUM_FILE_ELEMENTS];
+
+ int choice_pos; /* current element choice position */
+};
+
struct ElementInfo
{
/* ---------- token and description strings ---------- */
char *class_name; /* element class used in config files */
char *editor_description; /* pre-defined description for level editor */
char *custom_description; /* alternative description from config file */
- char description[MAX_ELEMENT_NAME_LEN + 1]; /* for custom elements */
+ char description[MAX_ELEMENT_NAME_LEN + 1]; /* for custom/group elements */
/* ---------- graphic and sound definitions ---------- */
int move_pattern; /* direction movable element moves to */
int move_direction_initial; /* initial direction element moves to */
int move_stepsize; /* step size element moves with */
+ int move_enter_element; /* element that can be entered (and removed) */
+ int move_leave_element; /* element that can be left behind */
+ int move_leave_type; /* change (limited) or leave (unlimited) */
int slippery_type; /* how/where other elements slip away */
int num_change_pages; /* actual number of change pages */
int current_change_page; /* currently edited change page */
+ struct ElementGroupInfo *group; /* pointer to element group info */
+
/* ---------- internal values used at runtime when playing ---------- */
unsigned long change_events; /* bitfield for combined change events */
int event_page_nr[NUM_CHANGE_EVENTS]; /* page number for each event */
struct ElementChangeInfo *event_page[NUM_CHANGE_EVENTS]; /* page for event */
+ boolean in_group[NUM_GROUP_ELEMENTS];
+
+ boolean can_leave_element; /* element can leave other element behind */
+ boolean can_leave_element_last;
+
/* ---------- internal values used in level editor ---------- */
int access_type; /* walkable or passable */