rnd-20070318-2-src
[rocksndiamonds.git] / src / init.c
1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back!               *
3 *----------------------------------------------------------*
4 * (c) 1995-2006 Artsoft Entertainment                      *
5 *               Holger Schemel                             *
6 *               Detmolder Strasse 189                      *
7 *               33604 Bielefeld                            *
8 *               Germany                                    *
9 *               e-mail: info@artsoft.org                   *
10 *----------------------------------------------------------*
11 * init.c                                                   *
12 ***********************************************************/
13
14 #include "libgame/libgame.h"
15
16 #include "init.h"
17 #include "events.h"
18 #include "screens.h"
19 #include "editor.h"
20 #include "game.h"
21 #include "tape.h"
22 #include "tools.h"
23 #include "files.h"
24 #include "network.h"
25 #include "netserv.h"
26 #include "cartoons.h"
27 #include "config.h"
28
29 #include "conf_e2g.c"   /* include auto-generated data structure definitions */
30 #include "conf_esg.c"   /* include auto-generated data structure definitions */
31 #include "conf_e2s.c"   /* include auto-generated data structure definitions */
32 #include "conf_fnt.c"   /* include auto-generated data structure definitions */
33 #include "conf_g2s.c"   /* include auto-generated data structure definitions */
34 #include "conf_g2m.c"   /* include auto-generated data structure definitions */
35
36
37 #define CONFIG_TOKEN_FONT_INITIAL               "font.initial"
38
39
40 static struct FontBitmapInfo font_initial[NUM_INITIAL_FONTS];
41
42 static int copy_properties[][5] =
43 {
44   {
45     EL_BUG,
46     EL_BUG_LEFT,                EL_BUG_RIGHT,
47     EL_BUG_UP,                  EL_BUG_DOWN
48   },
49   {
50     EL_SPACESHIP,
51     EL_SPACESHIP_LEFT,          EL_SPACESHIP_RIGHT,
52     EL_SPACESHIP_UP,            EL_SPACESHIP_DOWN
53   },
54   {
55     EL_BD_BUTTERFLY,
56     EL_BD_BUTTERFLY_LEFT,       EL_BD_BUTTERFLY_RIGHT,
57     EL_BD_BUTTERFLY_UP,         EL_BD_BUTTERFLY_DOWN
58   },
59   {
60     EL_BD_FIREFLY,
61     EL_BD_FIREFLY_LEFT,         EL_BD_FIREFLY_RIGHT,
62     EL_BD_FIREFLY_UP,           EL_BD_FIREFLY_DOWN
63   },
64   {
65     EL_PACMAN,
66     EL_PACMAN_LEFT,             EL_PACMAN_RIGHT,
67     EL_PACMAN_UP,               EL_PACMAN_DOWN
68   },
69   {
70     EL_YAMYAM,
71     EL_YAMYAM_LEFT,             EL_YAMYAM_RIGHT,
72     EL_YAMYAM_UP,               EL_YAMYAM_DOWN
73   },
74   {
75     EL_MOLE,
76     EL_MOLE_LEFT,               EL_MOLE_RIGHT,
77     EL_MOLE_UP,                 EL_MOLE_DOWN
78   },
79   {
80     -1,
81     -1, -1, -1, -1
82   }
83 };
84
85 void FreeGadgets()
86 {
87   FreeLevelEditorGadgets();
88   FreeGameButtons();
89   FreeTapeButtons();
90   FreeToolButtons();
91   FreeScreenGadgets();
92 }
93
94 void InitGadgets()
95 {
96   static boolean gadgets_initialized = FALSE;
97
98   if (gadgets_initialized)
99     FreeGadgets();
100
101   CreateLevelEditorGadgets();
102   CreateGameButtons();
103   CreateTapeButtons();
104   CreateToolButtons();
105   CreateScreenGadgets();
106
107   InitGadgetsSoundCallback(PlaySoundActivating, PlaySoundSelecting);
108
109   gadgets_initialized = TRUE;
110 }
111
112 inline void InitElementSmallImagesScaledUp(int graphic)
113 {
114   CreateImageWithSmallImages(graphic, graphic_info[graphic].scale_up_factor);
115 }
116
117 void InitElementSmallImages()
118 {
119   static int special_graphics[] =
120   {
121     IMG_EDITOR_ELEMENT_BORDER,
122     IMG_EDITOR_ELEMENT_BORDER_INPUT,
123     IMG_EDITOR_CASCADE_LIST,
124     IMG_EDITOR_CASCADE_LIST_ACTIVE,
125     -1
126   };
127   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
128   int num_property_mappings = getImageListPropertyMappingSize();
129   int i;
130
131   /* initialize normal images from static configuration */
132   for (i = 0; element_to_graphic[i].element > -1; i++)
133     InitElementSmallImagesScaledUp(element_to_graphic[i].graphic);
134
135   /* initialize special images from static configuration */
136   for (i = 0; element_to_special_graphic[i].element > -1; i++)
137     InitElementSmallImagesScaledUp(element_to_special_graphic[i].graphic);
138
139   /* initialize images from dynamic configuration (may be elements or other) */
140   for (i = 0; i < num_property_mappings; i++)
141     InitElementSmallImagesScaledUp(property_mapping[i].artwork_index);
142
143   /* initialize special images from above list (non-element images) */
144   for (i = 0; special_graphics[i] > -1; i++)
145     InitElementSmallImagesScaledUp(special_graphics[i]);
146 }
147
148 void InitScaledImages()
149 {
150   int i;
151
152   /* scale normal images from static configuration, if not already scaled */
153   for (i = 0; i < NUM_IMAGE_FILES; i++)
154     ScaleImage(i, graphic_info[i].scale_up_factor);
155 }
156
157 #if 1
158 /* !!! FIX THIS (CHANGE TO USING NORMAL ELEMENT GRAPHIC DEFINITIONS) !!! */
159 void SetBitmaps_EM(Bitmap **em_bitmap)
160 {
161   em_bitmap[0] = graphic_info[IMG_EMC_OBJECT].bitmap;
162   em_bitmap[1] = graphic_info[IMG_EMC_SPRITE].bitmap;
163 }
164 #endif
165
166 static int getFontBitmapID(int font_nr)
167 {
168   int special = -1;
169
170   if (game_status >= GAME_MODE_TITLE_INITIAL &&
171       game_status <= GAME_MODE_PSEUDO_PREVIEW)
172     special = game_status;
173   else if (game_status == GAME_MODE_PSEUDO_TYPENAME)
174     special = GFX_SPECIAL_ARG_MAIN;
175 #if 0
176   else if (game_status == GAME_MODE_PLAYING)
177     special = GFX_SPECIAL_ARG_DOOR;
178 #endif
179
180   if (special != -1)
181     return font_info[font_nr].special_bitmap_id[special];
182   else
183     return font_nr;
184 }
185
186 void InitFontGraphicInfo()
187 {
188   static struct FontBitmapInfo *font_bitmap_info = NULL;
189   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
190   int num_property_mappings = getImageListPropertyMappingSize();
191   int num_font_bitmaps = NUM_FONTS;
192   int i, j;
193
194   if (graphic_info == NULL)             /* still at startup phase */
195   {
196     InitFontInfo(font_initial, NUM_INITIAL_FONTS, getFontBitmapID);
197
198     return;
199   }
200
201   /* ---------- initialize font graphic definitions ---------- */
202
203   /* always start with reliable default values (normal font graphics) */
204   for (i = 0; i < NUM_FONTS; i++)
205     font_info[i].graphic = IMG_FONT_INITIAL_1;
206
207   /* initialize normal font/graphic mapping from static configuration */
208   for (i = 0; font_to_graphic[i].font_nr > -1; i++)
209   {
210     int font_nr = font_to_graphic[i].font_nr;
211     int special = font_to_graphic[i].special;
212     int graphic = font_to_graphic[i].graphic;
213
214     if (special != -1)
215       continue;
216
217     font_info[font_nr].graphic = graphic;
218   }
219
220   /* always start with reliable default values (special font graphics) */
221   for (i = 0; i < NUM_FONTS; i++)
222   {
223     for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
224     {
225       font_info[i].special_graphic[j] = font_info[i].graphic;
226       font_info[i].special_bitmap_id[j] = i;
227     }
228   }
229
230   /* initialize special font/graphic mapping from static configuration */
231   for (i = 0; font_to_graphic[i].font_nr > -1; i++)
232   {
233     int font_nr      = font_to_graphic[i].font_nr;
234     int special      = font_to_graphic[i].special;
235     int graphic      = font_to_graphic[i].graphic;
236     int base_graphic = font2baseimg(font_nr);
237
238     if (IS_SPECIAL_GFX_ARG(special))
239     {
240       boolean base_redefined =
241         getImageListEntryFromImageID(base_graphic)->redefined;
242       boolean special_redefined =
243         getImageListEntryFromImageID(graphic)->redefined;
244       boolean special_cloned = (graphic_info[graphic].clone_from != -1);
245
246       /* if the base font ("font.title_1", for example) has been redefined,
247          but not the special font ("font.title_1.LEVELS", for example), do not
248          use an existing (in this case considered obsolete) special font
249          anymore, but use the automatically determined default font */
250       /* special case: cloned special fonts must be explicitly redefined,
251          but are not automatically redefined by redefining base font */
252       if (base_redefined && !special_redefined && !special_cloned)
253         continue;
254
255       font_info[font_nr].special_graphic[special] = graphic;
256       font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
257       num_font_bitmaps++;
258     }
259   }
260
261   /* initialize special font/graphic mapping from dynamic configuration */
262   for (i = 0; i < num_property_mappings; i++)
263   {
264     int font_nr = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
265     int special = property_mapping[i].ext3_index;
266     int graphic = property_mapping[i].artwork_index;
267
268     if (font_nr < 0)
269       continue;
270
271     if (IS_SPECIAL_GFX_ARG(special))
272     {
273       font_info[font_nr].special_graphic[special] = graphic;
274       font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
275       num_font_bitmaps++;
276     }
277   }
278
279   /* correct special font/graphic mapping for cloned fonts for downwards
280      compatibility of PREVIEW fonts -- this is only needed for implicit
281      redefinition of special font by redefined base font, and only if other
282      fonts are cloned from this special font (like in the "Zelda" level set) */
283   for (i = 0; font_to_graphic[i].font_nr > -1; i++)
284   {
285     int font_nr = font_to_graphic[i].font_nr;
286     int special = font_to_graphic[i].special;
287     int graphic = font_to_graphic[i].graphic;
288
289     if (IS_SPECIAL_GFX_ARG(special))
290     {
291       boolean special_redefined =
292         getImageListEntryFromImageID(graphic)->redefined;
293       boolean special_cloned = (graphic_info[graphic].clone_from != -1);
294
295       if (special_cloned && !special_redefined)
296       {
297         int j;
298
299         for (j = 0; font_to_graphic[j].font_nr > -1; j++)
300         {
301           int font_nr2 = font_to_graphic[j].font_nr;
302           int special2 = font_to_graphic[j].special;
303           int graphic2 = font_to_graphic[j].graphic;
304
305           if (IS_SPECIAL_GFX_ARG(special2) &&
306               graphic2 == graphic_info[graphic].clone_from)
307           {
308             font_info[font_nr].special_graphic[special] =
309               font_info[font_nr2].special_graphic[special2];
310             font_info[font_nr].special_bitmap_id[special] =
311               font_info[font_nr2].special_bitmap_id[special2];
312           }
313         }
314       }
315     }
316   }
317
318   /* reset non-redefined ".active" font graphics if normal font is redefined */
319   /* (this different treatment is needed because normal and active fonts are
320      independently defined ("active" is not a property of font definitions!) */
321   for (i = 0; i < NUM_FONTS; i++)
322   {
323     int font_nr_base = i;
324     int font_nr_active = FONT_ACTIVE(font_nr_base);
325
326     /* check only those fonts with exist as normal and ".active" variant */
327     if (font_nr_base != font_nr_active)
328     {
329       int base_graphic = font_info[font_nr_base].graphic;
330       int active_graphic = font_info[font_nr_active].graphic;
331       boolean base_redefined =
332         getImageListEntryFromImageID(base_graphic)->redefined;
333       boolean active_redefined =
334         getImageListEntryFromImageID(active_graphic)->redefined;
335
336       /* if the base font ("font.menu_1", for example) has been redefined,
337          but not the active font ("font.menu_1.active", for example), do not
338          use an existing (in this case considered obsolete) active font
339          anymore, but use the automatically determined default font */
340       if (base_redefined && !active_redefined)
341         font_info[font_nr_active].graphic = base_graphic;
342
343       /* now also check each "special" font (which may be the same as above) */
344       for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
345       {
346         int base_graphic = font_info[font_nr_base].special_graphic[j];
347         int active_graphic = font_info[font_nr_active].special_graphic[j];
348         boolean base_redefined =
349           getImageListEntryFromImageID(base_graphic)->redefined;
350         boolean active_redefined =
351           getImageListEntryFromImageID(active_graphic)->redefined;
352
353         /* same as above, but check special graphic definitions, for example:
354            redefined "font.menu_1.MAIN" invalidates "font.menu_1.active.MAIN" */
355         if (base_redefined && !active_redefined)
356         {
357           font_info[font_nr_active].special_graphic[j] =
358             font_info[font_nr_base].special_graphic[j];
359           font_info[font_nr_active].special_bitmap_id[j] =
360             font_info[font_nr_base].special_bitmap_id[j];
361         }
362       }
363     }
364   }
365
366   /* ---------- initialize font bitmap array ---------- */
367
368   if (font_bitmap_info != NULL)
369     FreeFontInfo(font_bitmap_info);
370
371   font_bitmap_info =
372     checked_calloc(num_font_bitmaps * sizeof(struct FontBitmapInfo));
373
374   /* ---------- initialize font bitmap definitions ---------- */
375
376   for (i = 0; i < NUM_FONTS; i++)
377   {
378     if (i < NUM_INITIAL_FONTS)
379     {
380       font_bitmap_info[i] = font_initial[i];
381       continue;
382     }
383
384     for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
385     {
386       int font_bitmap_id = font_info[i].special_bitmap_id[j];
387       int graphic = font_info[i].special_graphic[j];
388
389       /* set 'graphic_info' for font entries, if uninitialized (guessed) */
390       if (graphic_info[graphic].anim_frames < MIN_NUM_CHARS_PER_FONT)
391       {
392         graphic_info[graphic].anim_frames = DEFAULT_NUM_CHARS_PER_FONT;
393         graphic_info[graphic].anim_frames_per_line = DEFAULT_NUM_CHARS_PER_LINE;
394       }
395
396       /* copy font relevant information from graphics information */
397       font_bitmap_info[font_bitmap_id].bitmap = graphic_info[graphic].bitmap;
398       font_bitmap_info[font_bitmap_id].src_x  = graphic_info[graphic].src_x;
399       font_bitmap_info[font_bitmap_id].src_y  = graphic_info[graphic].src_y;
400       font_bitmap_info[font_bitmap_id].width  = graphic_info[graphic].width;
401       font_bitmap_info[font_bitmap_id].height = graphic_info[graphic].height;
402
403       font_bitmap_info[font_bitmap_id].draw_xoffset =
404         graphic_info[graphic].draw_xoffset;
405       font_bitmap_info[font_bitmap_id].draw_yoffset =
406         graphic_info[graphic].draw_yoffset;
407
408       font_bitmap_info[font_bitmap_id].num_chars =
409         graphic_info[graphic].anim_frames;
410       font_bitmap_info[font_bitmap_id].num_chars_per_line =
411         graphic_info[graphic].anim_frames_per_line;
412     }
413   }
414
415   InitFontInfo(font_bitmap_info, num_font_bitmaps, getFontBitmapID);
416 }
417
418 void InitElementGraphicInfo()
419 {
420   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
421   int num_property_mappings = getImageListPropertyMappingSize();
422   int i, act, dir;
423
424   if (graphic_info == NULL)             /* still at startup phase */
425     return;
426
427   /* set values to -1 to identify later as "uninitialized" values */
428   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
429   {
430     for (act = 0; act < NUM_ACTIONS; act++)
431     {
432       element_info[i].graphic[act] = -1;
433       element_info[i].crumbled[act] = -1;
434
435       for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
436       {
437         element_info[i].direction_graphic[act][dir] = -1;
438         element_info[i].direction_crumbled[act][dir] = -1;
439       }
440     }
441   }
442
443   /* initialize normal element/graphic mapping from static configuration */
444   for (i = 0; element_to_graphic[i].element > -1; i++)
445   {
446     int element      = element_to_graphic[i].element;
447     int action       = element_to_graphic[i].action;
448     int direction    = element_to_graphic[i].direction;
449     boolean crumbled = element_to_graphic[i].crumbled;
450     int graphic      = element_to_graphic[i].graphic;
451     int base_graphic = el2baseimg(element);
452
453     if (graphic_info[graphic].bitmap == NULL)
454       continue;
455
456     if ((action > -1 || direction > -1 || crumbled == TRUE) &&
457         base_graphic != -1)
458     {
459       boolean base_redefined =
460         getImageListEntryFromImageID(base_graphic)->redefined;
461       boolean act_dir_redefined =
462         getImageListEntryFromImageID(graphic)->redefined;
463
464       /* if the base graphic ("emerald", for example) has been redefined,
465          but not the action graphic ("emerald.falling", for example), do not
466          use an existing (in this case considered obsolete) action graphic
467          anymore, but use the automatically determined default graphic */
468       if (base_redefined && !act_dir_redefined)
469         continue;
470     }
471
472     if (action < 0)
473       action = ACTION_DEFAULT;
474
475     if (crumbled)
476     {
477       if (direction > -1)
478         element_info[element].direction_crumbled[action][direction] = graphic;
479       else
480         element_info[element].crumbled[action] = graphic;
481     }
482     else
483     {
484       if (direction > -1)
485         element_info[element].direction_graphic[action][direction] = graphic;
486       else
487         element_info[element].graphic[action] = graphic;
488     }
489   }
490
491   /* initialize normal element/graphic mapping from dynamic configuration */
492   for (i = 0; i < num_property_mappings; i++)
493   {
494     int element   = property_mapping[i].base_index;
495     int action    = property_mapping[i].ext1_index;
496     int direction = property_mapping[i].ext2_index;
497     int special   = property_mapping[i].ext3_index;
498     int graphic   = property_mapping[i].artwork_index;
499     boolean crumbled = FALSE;
500
501     if (special == GFX_SPECIAL_ARG_CRUMBLED)
502     {
503       special = -1;
504       crumbled = TRUE;
505     }
506
507     if (graphic_info[graphic].bitmap == NULL)
508       continue;
509
510     if (element >= MAX_NUM_ELEMENTS || special != -1)
511       continue;
512
513     if (action < 0)
514       action = ACTION_DEFAULT;
515
516     if (crumbled)
517     {
518       if (direction < 0)
519         for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
520           element_info[element].direction_crumbled[action][dir] = -1;
521
522       if (direction > -1)
523         element_info[element].direction_crumbled[action][direction] = graphic;
524       else
525         element_info[element].crumbled[action] = graphic;
526     }
527     else
528     {
529       if (direction < 0)
530         for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
531           element_info[element].direction_graphic[action][dir] = -1;
532
533       if (direction > -1)
534         element_info[element].direction_graphic[action][direction] = graphic;
535       else
536         element_info[element].graphic[action] = graphic;
537     }
538   }
539
540   /* now copy all graphics that are defined to be cloned from other graphics */
541   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
542   {
543     int graphic = element_info[i].graphic[ACTION_DEFAULT];
544     int crumbled_like, diggable_like;
545
546     if (graphic == -1)
547       continue;
548
549     crumbled_like = graphic_info[graphic].crumbled_like;
550     diggable_like = graphic_info[graphic].diggable_like;
551
552     if (crumbled_like != -1 && element_info[i].crumbled[ACTION_DEFAULT] == -1)
553     {
554       for (act = 0; act < NUM_ACTIONS; act++)
555         element_info[i].crumbled[act] =
556           element_info[crumbled_like].crumbled[act];
557       for (act = 0; act < NUM_ACTIONS; act++)
558         for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
559           element_info[i].direction_crumbled[act][dir] =
560             element_info[crumbled_like].direction_crumbled[act][dir];
561     }
562
563     if (diggable_like != -1 && element_info[i].graphic[ACTION_DIGGING] == -1)
564     {
565       element_info[i].graphic[ACTION_DIGGING] =
566         element_info[diggable_like].graphic[ACTION_DIGGING];
567       for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
568         element_info[i].direction_graphic[ACTION_DIGGING][dir] =
569           element_info[diggable_like].direction_graphic[ACTION_DIGGING][dir];
570     }
571   }
572
573 #if 1
574   /* set hardcoded definitions for some runtime elements without graphic */
575   element_info[EL_AMOEBA_TO_DIAMOND].graphic[ACTION_DEFAULT] = IMG_AMOEBA_DEAD;
576 #endif
577
578 #if 1
579   /* set hardcoded definitions for some internal elements without graphic */
580   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
581   {
582     if (IS_EDITOR_CASCADE_INACTIVE(i))
583       element_info[i].graphic[ACTION_DEFAULT] = IMG_EDITOR_CASCADE_LIST;
584     else if (IS_EDITOR_CASCADE_ACTIVE(i))
585       element_info[i].graphic[ACTION_DEFAULT] = IMG_EDITOR_CASCADE_LIST_ACTIVE;
586   }
587 #endif
588
589   /* now set all undefined/invalid graphics to -1 to set to default after it */
590   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
591   {
592     for (act = 0; act < NUM_ACTIONS; act++)
593     {
594       int graphic;
595
596       graphic = element_info[i].graphic[act];
597       if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
598         element_info[i].graphic[act] = -1;
599
600       graphic = element_info[i].crumbled[act];
601       if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
602         element_info[i].crumbled[act] = -1;
603
604       for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
605       {
606         graphic = element_info[i].direction_graphic[act][dir];
607         if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
608           element_info[i].direction_graphic[act][dir] = -1;
609
610         graphic = element_info[i].direction_crumbled[act][dir];
611         if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
612           element_info[i].direction_crumbled[act][dir] = -1;
613       }
614     }
615   }
616
617   /* adjust graphics with 2nd tile for movement according to direction
618      (do this before correcting '-1' values to minimize calculations) */
619   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
620   {
621     for (act = 0; act < NUM_ACTIONS; act++)
622     {
623       for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
624       {
625         int graphic = element_info[i].direction_graphic[act][dir];
626         int move_dir = (act == ACTION_FALLING ? MV_BIT_DOWN : dir);
627
628         if (act == ACTION_FALLING)      /* special case */
629           graphic = element_info[i].graphic[act];
630
631         if (graphic != -1 &&
632             graphic_info[graphic].double_movement &&
633             graphic_info[graphic].swap_double_tiles != 0)
634         {
635           struct GraphicInfo *g = &graphic_info[graphic];
636           int src_x_front = g->src_x;
637           int src_y_front = g->src_y;
638           int src_x_back = g->src_x + g->offset2_x;
639           int src_y_back = g->src_y + g->offset2_y;
640           boolean frames_are_ordered_diagonally = (g->offset_x != 0 &&
641                                                    g->offset_y != 0);
642           boolean front_is_left_or_upper = (src_x_front < src_x_back ||
643                                             src_y_front < src_y_back);
644           boolean swap_movement_tiles_always = (g->swap_double_tiles == 1);
645           boolean swap_movement_tiles_autodetected =
646             (!frames_are_ordered_diagonally &&
647              ((move_dir == MV_BIT_LEFT  && !front_is_left_or_upper) ||
648               (move_dir == MV_BIT_UP    && !front_is_left_or_upper) ||
649               (move_dir == MV_BIT_RIGHT &&  front_is_left_or_upper) ||
650               (move_dir == MV_BIT_DOWN  &&  front_is_left_or_upper)));
651           Bitmap *dummy;
652
653           /* swap frontside and backside graphic tile coordinates, if needed */
654           if (swap_movement_tiles_always || swap_movement_tiles_autodetected)
655           {
656             /* get current (wrong) backside tile coordinates */
657             getGraphicSourceExt(graphic, 0, &dummy, &src_x_back, &src_y_back,
658                                 TRUE);
659
660             /* set frontside tile coordinates to backside tile coordinates */
661             g->src_x = src_x_back;
662             g->src_y = src_y_back;
663
664             /* invert tile offset to point to new backside tile coordinates */
665             g->offset2_x *= -1;
666             g->offset2_y *= -1;
667
668             /* do not swap front and backside tiles again after correction */
669             g->swap_double_tiles = 0;
670           }
671         }
672       }
673     }
674   }
675
676   /* now set all '-1' values to element specific default values */
677   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
678   {
679     int default_graphic = element_info[i].graphic[ACTION_DEFAULT];
680     int default_crumbled = element_info[i].crumbled[ACTION_DEFAULT];
681     int default_direction_graphic[NUM_DIRECTIONS_FULL];
682     int default_direction_crumbled[NUM_DIRECTIONS_FULL];
683
684     if (default_graphic == -1)
685       default_graphic = IMG_UNKNOWN;
686 #if 1
687     if (default_crumbled == -1)
688       default_crumbled = default_graphic;
689 #else
690     /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
691     if (default_crumbled == -1)
692       default_crumbled = IMG_EMPTY;
693 #endif
694
695     for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
696     {
697       default_direction_graphic[dir] =
698         element_info[i].direction_graphic[ACTION_DEFAULT][dir];
699       default_direction_crumbled[dir] =
700         element_info[i].direction_crumbled[ACTION_DEFAULT][dir];
701
702       if (default_direction_graphic[dir] == -1)
703         default_direction_graphic[dir] = default_graphic;
704 #if 1
705       if (default_direction_crumbled[dir] == -1)
706         default_direction_crumbled[dir] = default_direction_graphic[dir];
707 #else
708       /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
709       if (default_direction_crumbled[dir] == -1)
710         default_direction_crumbled[dir] = default_crumbled;
711 #endif
712     }
713
714     for (act = 0; act < NUM_ACTIONS; act++)
715     {
716       boolean act_remove = ((IS_DIGGABLE(i)    && act == ACTION_DIGGING)  ||
717                             (IS_SNAPPABLE(i)   && act == ACTION_SNAPPING) ||
718                             (IS_COLLECTIBLE(i) && act == ACTION_COLLECTING));
719       boolean act_turning = (act == ACTION_TURNING_FROM_LEFT ||
720                              act == ACTION_TURNING_FROM_RIGHT ||
721                              act == ACTION_TURNING_FROM_UP ||
722                              act == ACTION_TURNING_FROM_DOWN);
723
724       /* generic default action graphic (defined by "[default]" directive) */
725       int default_action_graphic = element_info[EL_DEFAULT].graphic[act];
726       int default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
727       int default_remove_graphic = IMG_EMPTY;
728
729       if (act_remove && default_action_graphic != -1)
730         default_remove_graphic = default_action_graphic;
731
732       /* look for special default action graphic (classic game specific) */
733       if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].graphic[act] != -1)
734         default_action_graphic = element_info[EL_BD_DEFAULT].graphic[act];
735       if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].graphic[act] != -1)
736         default_action_graphic = element_info[EL_SP_DEFAULT].graphic[act];
737       if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].graphic[act] != -1)
738         default_action_graphic = element_info[EL_SB_DEFAULT].graphic[act];
739
740       if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].crumbled[act] != -1)
741         default_action_crumbled = element_info[EL_BD_DEFAULT].crumbled[act];
742       if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].crumbled[act] != -1)
743         default_action_crumbled = element_info[EL_SP_DEFAULT].crumbled[act];
744       if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].crumbled[act] != -1)
745         default_action_crumbled = element_info[EL_SB_DEFAULT].crumbled[act];
746
747 #if 1
748       /* !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!! */
749       /* !!! make this better !!! */
750       if (i == EL_EMPTY_SPACE)
751       {
752         default_action_graphic = element_info[EL_DEFAULT].graphic[act];
753         default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
754       }
755 #endif
756
757       if (default_action_graphic == -1)
758         default_action_graphic = default_graphic;
759 #if 1
760       if (default_action_crumbled == -1)
761         default_action_crumbled = default_action_graphic;
762 #else
763       /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
764       if (default_action_crumbled == -1)
765         default_action_crumbled = default_crumbled;
766 #endif
767
768       for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
769       {
770         /* use action graphic as the default direction graphic, if undefined */
771         int default_action_direction_graphic = element_info[i].graphic[act];
772         int default_action_direction_crumbled = element_info[i].crumbled[act];
773
774         /* no graphic for current action -- use default direction graphic */
775         if (default_action_direction_graphic == -1)
776           default_action_direction_graphic =
777             (act_remove ? default_remove_graphic :
778              act_turning ?
779              element_info[i].direction_graphic[ACTION_TURNING][dir] :
780              default_action_graphic != default_graphic ?
781              default_action_graphic :
782              default_direction_graphic[dir]);
783
784         if (element_info[i].direction_graphic[act][dir] == -1)
785           element_info[i].direction_graphic[act][dir] =
786             default_action_direction_graphic;
787
788 #if 1
789         if (default_action_direction_crumbled == -1)
790           default_action_direction_crumbled =
791             element_info[i].direction_graphic[act][dir];
792 #else
793         if (default_action_direction_crumbled == -1)
794           default_action_direction_crumbled =
795             (act_remove ? default_remove_graphic :
796              act_turning ?
797              element_info[i].direction_crumbled[ACTION_TURNING][dir] :
798              default_action_crumbled != default_crumbled ?
799              default_action_crumbled :
800              default_direction_crumbled[dir]);
801 #endif
802
803         if (element_info[i].direction_crumbled[act][dir] == -1)
804           element_info[i].direction_crumbled[act][dir] =
805             default_action_direction_crumbled;
806       }
807
808       /* no graphic for this specific action -- use default action graphic */
809       if (element_info[i].graphic[act] == -1)
810         element_info[i].graphic[act] =
811           (act_remove ? default_remove_graphic :
812            act_turning ? element_info[i].graphic[ACTION_TURNING] :
813            default_action_graphic);
814 #if 1
815       if (element_info[i].crumbled[act] == -1)
816         element_info[i].crumbled[act] = element_info[i].graphic[act];
817 #else
818       if (element_info[i].crumbled[act] == -1)
819         element_info[i].crumbled[act] =
820           (act_remove ? default_remove_graphic :
821            act_turning ? element_info[i].crumbled[ACTION_TURNING] :
822            default_action_crumbled);
823 #endif
824     }
825   }
826
827 #if 0
828   /* !!! THIS ALSO CLEARS SPECIAL FLAGS (AND IS NOT NEEDED ANYWAY) !!! */
829   /* set animation mode to "none" for each graphic with only 1 frame */
830   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
831   {
832     for (act = 0; act < NUM_ACTIONS; act++)
833     {
834       int graphic = element_info[i].graphic[act];
835       int crumbled = element_info[i].crumbled[act];
836
837       if (graphic_info[graphic].anim_frames == 1)
838         graphic_info[graphic].anim_mode = ANIM_NONE;
839       if (graphic_info[crumbled].anim_frames == 1)
840         graphic_info[crumbled].anim_mode = ANIM_NONE;
841
842       for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
843       {
844         graphic = element_info[i].direction_graphic[act][dir];
845         crumbled = element_info[i].direction_crumbled[act][dir];
846
847         if (graphic_info[graphic].anim_frames == 1)
848           graphic_info[graphic].anim_mode = ANIM_NONE;
849         if (graphic_info[crumbled].anim_frames == 1)
850           graphic_info[crumbled].anim_mode = ANIM_NONE;
851       }
852     }
853   }
854 #endif
855
856 #if 0
857 #if DEBUG
858   if (options.verbose)
859   {
860     for (i = 0; i < MAX_NUM_ELEMENTS; i++)
861       if (element_info[i].graphic[ACTION_DEFAULT] == IMG_UNKNOWN &&
862           i != EL_UNKNOWN)
863         Error(ERR_INFO, "warning: no graphic for element '%s' (%d)",
864               element_info[i].token_name, i);
865   }
866 #endif
867 #endif
868 }
869
870 void InitElementSpecialGraphicInfo()
871 {
872   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
873   int num_property_mappings = getImageListPropertyMappingSize();
874   int i, j;
875
876   /* always start with reliable default values */
877   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
878     for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
879       element_info[i].special_graphic[j] =
880         element_info[i].graphic[ACTION_DEFAULT];
881
882   /* initialize special element/graphic mapping from static configuration */
883   for (i = 0; element_to_special_graphic[i].element > -1; i++)
884   {
885     int element = element_to_special_graphic[i].element;
886     int special = element_to_special_graphic[i].special;
887     int graphic = element_to_special_graphic[i].graphic;
888     int base_graphic = el2baseimg(element);
889     boolean base_redefined =
890       getImageListEntryFromImageID(base_graphic)->redefined;
891     boolean special_redefined =
892       getImageListEntryFromImageID(graphic)->redefined;
893
894     /* if the base graphic ("emerald", for example) has been redefined,
895        but not the special graphic ("emerald.EDITOR", for example), do not
896        use an existing (in this case considered obsolete) special graphic
897        anymore, but use the automatically created (down-scaled) graphic */
898     if (base_redefined && !special_redefined)
899       continue;
900
901     element_info[element].special_graphic[special] = graphic;
902   }
903
904   /* initialize special element/graphic mapping from dynamic configuration */
905   for (i = 0; i < num_property_mappings; i++)
906   {
907     int element = property_mapping[i].base_index;
908     int special = property_mapping[i].ext3_index;
909     int graphic = property_mapping[i].artwork_index;
910
911     if (element >= MAX_NUM_ELEMENTS)
912       continue;
913
914     if (IS_SPECIAL_GFX_ARG(special))
915       element_info[element].special_graphic[special] = graphic;
916   }
917
918   /* now set all undefined/invalid graphics to default */
919   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
920     for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
921       if (graphic_info[element_info[i].special_graphic[j]].bitmap == NULL)
922         element_info[i].special_graphic[j] =
923           element_info[i].graphic[ACTION_DEFAULT];
924 }
925
926 static int get_graphic_parameter_value(char *value_raw, char *suffix, int type)
927 {
928   int i;
929   int x = 0;
930
931   if (type != TYPE_TOKEN)
932     return get_parameter_value(value_raw, suffix, type);
933
934   if (strEqual(value_raw, ARG_UNDEFINED))
935     return ARG_UNDEFINED_VALUE;
936
937   /* !!! OPTIMIZE THIS BY USING HASH !!! */
938   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
939     if (strEqual(element_info[i].token_name, value_raw))
940       return i;
941
942   /* !!! OPTIMIZE THIS BY USING HASH !!! */
943   for (i = 0; image_config[i].token != NULL; i++)
944   {
945     int len_config_value = strlen(image_config[i].value);
946
947     if (!strEqual(&image_config[i].value[len_config_value - 4], ".pcx") &&
948         !strEqual(&image_config[i].value[len_config_value - 4], ".wav") &&
949         !strEqual(image_config[i].value, UNDEFINED_FILENAME))
950       continue;
951
952     if (strEqual(image_config[i].token, value_raw))
953       return x;
954
955     x++;
956   }
957
958   return -1;
959 }
960
961 static int get_scaled_graphic_width(int graphic)
962 {
963   int original_width = getOriginalImageWidthFromImageID(graphic);
964   int scale_up_factor = graphic_info[graphic].scale_up_factor;
965
966   return original_width * scale_up_factor;
967 }
968
969 static int get_scaled_graphic_height(int graphic)
970 {
971   int original_height = getOriginalImageHeightFromImageID(graphic);
972   int scale_up_factor = graphic_info[graphic].scale_up_factor;
973
974   return original_height * scale_up_factor;
975 }
976
977 static void set_graphic_parameters(int graphic)
978 {
979   struct FileInfo *image = getImageListEntryFromImageID(graphic);
980   char **parameter_raw = image->parameter;
981   Bitmap *src_bitmap = getBitmapFromImageID(graphic);
982   int parameter[NUM_GFX_ARGS];
983   int anim_frames_per_row = 1, anim_frames_per_col = 1;
984   int anim_frames_per_line = 1;
985   int i;
986
987   /* if fallback to default artwork is done, also use the default parameters */
988   if (image->fallback_to_default)
989     parameter_raw = image->default_parameter;
990
991   /* get integer values from string parameters */
992   for (i = 0; i < NUM_GFX_ARGS; i++)
993     parameter[i] = get_graphic_parameter_value(parameter_raw[i],
994                                                image_config_suffix[i].token,
995                                                image_config_suffix[i].type);
996
997   graphic_info[graphic].bitmap = src_bitmap;
998
999   /* always start with reliable default values */
1000   graphic_info[graphic].src_image_width = 0;
1001   graphic_info[graphic].src_image_height = 0;
1002   graphic_info[graphic].src_x = 0;
1003   graphic_info[graphic].src_y = 0;
1004   graphic_info[graphic].width  = TILEX; /* default for element graphics */
1005   graphic_info[graphic].height = TILEY; /* default for element graphics */
1006   graphic_info[graphic].offset_x = 0;   /* one or both of these values ... */
1007   graphic_info[graphic].offset_y = 0;   /* ... will be corrected later */
1008   graphic_info[graphic].offset2_x = 0;  /* one or both of these values ... */
1009   graphic_info[graphic].offset2_y = 0;  /* ... will be corrected later */
1010   graphic_info[graphic].swap_double_tiles = -1; /* auto-detect tile swapping */
1011   graphic_info[graphic].crumbled_like = -1;     /* do not use clone element */
1012   graphic_info[graphic].diggable_like = -1;     /* do not use clone element */
1013   graphic_info[graphic].border_size = TILEX / 8;  /* "CRUMBLED" border size */
1014   graphic_info[graphic].scale_up_factor = 1;    /* default: no scaling up */
1015   graphic_info[graphic].clone_from = -1;        /* do not use clone graphic */
1016   graphic_info[graphic].anim_delay_fixed = 0;
1017   graphic_info[graphic].anim_delay_random = 0;
1018   graphic_info[graphic].post_delay_fixed = 0;
1019   graphic_info[graphic].post_delay_random = 0;
1020   graphic_info[graphic].fade_delay = -1;
1021   graphic_info[graphic].post_delay = -1;
1022   graphic_info[graphic].auto_delay = -1;
1023   graphic_info[graphic].align = ALIGN_CENTER;   /* default for title screens */
1024   graphic_info[graphic].valign = VALIGN_MIDDLE; /* default for title screens */
1025   graphic_info[graphic].sort_priority = 0;      /* default for title screens */
1026
1027 #if 1
1028   /* optional zoom factor for scaling up the image to a larger size */
1029   if (parameter[GFX_ARG_SCALE_UP_FACTOR] != ARG_UNDEFINED_VALUE)
1030     graphic_info[graphic].scale_up_factor = parameter[GFX_ARG_SCALE_UP_FACTOR];
1031   if (graphic_info[graphic].scale_up_factor < 1)
1032     graphic_info[graphic].scale_up_factor = 1;          /* no scaling */
1033 #endif
1034
1035 #if 1
1036   if (graphic_info[graphic].use_image_size)
1037   {
1038     /* set new default bitmap size (with scaling, but without small images) */
1039     graphic_info[graphic].width  = get_scaled_graphic_width(graphic);
1040     graphic_info[graphic].height = get_scaled_graphic_height(graphic);
1041   }
1042 #endif
1043
1044   /* optional x and y tile position of animation frame sequence */
1045   if (parameter[GFX_ARG_XPOS] != ARG_UNDEFINED_VALUE)
1046     graphic_info[graphic].src_x = parameter[GFX_ARG_XPOS] * TILEX;
1047   if (parameter[GFX_ARG_YPOS] != ARG_UNDEFINED_VALUE)
1048     graphic_info[graphic].src_y = parameter[GFX_ARG_YPOS] * TILEY;
1049
1050   /* optional x and y pixel position of animation frame sequence */
1051   if (parameter[GFX_ARG_X] != ARG_UNDEFINED_VALUE)
1052     graphic_info[graphic].src_x = parameter[GFX_ARG_X];
1053   if (parameter[GFX_ARG_Y] != ARG_UNDEFINED_VALUE)
1054     graphic_info[graphic].src_y = parameter[GFX_ARG_Y];
1055
1056   /* optional width and height of each animation frame */
1057   if (parameter[GFX_ARG_WIDTH] != ARG_UNDEFINED_VALUE)
1058     graphic_info[graphic].width = parameter[GFX_ARG_WIDTH];
1059   if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE)
1060     graphic_info[graphic].height = parameter[GFX_ARG_HEIGHT];
1061
1062 #if 0
1063   /* optional zoom factor for scaling up the image to a larger size */
1064   if (parameter[GFX_ARG_SCALE_UP_FACTOR] != ARG_UNDEFINED_VALUE)
1065     graphic_info[graphic].scale_up_factor = parameter[GFX_ARG_SCALE_UP_FACTOR];
1066   if (graphic_info[graphic].scale_up_factor < 1)
1067     graphic_info[graphic].scale_up_factor = 1;          /* no scaling */
1068 #endif
1069
1070   if (src_bitmap)
1071   {
1072     /* get final bitmap size (with scaling, but without small images) */
1073     int src_image_width  = get_scaled_graphic_width(graphic);
1074     int src_image_height = get_scaled_graphic_height(graphic);
1075
1076     anim_frames_per_row = src_image_width  / graphic_info[graphic].width;
1077     anim_frames_per_col = src_image_height / graphic_info[graphic].height;
1078
1079     graphic_info[graphic].src_image_width  = src_image_width;
1080     graphic_info[graphic].src_image_height = src_image_height;
1081   }
1082
1083   /* correct x or y offset dependent of vertical or horizontal frame order */
1084   if (parameter[GFX_ARG_VERTICAL])      /* frames are ordered vertically */
1085   {
1086     graphic_info[graphic].offset_y =
1087       (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
1088        parameter[GFX_ARG_OFFSET] : graphic_info[graphic].height);
1089     anim_frames_per_line = anim_frames_per_col;
1090   }
1091   else                                  /* frames are ordered horizontally */
1092   {
1093     graphic_info[graphic].offset_x =
1094       (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
1095        parameter[GFX_ARG_OFFSET] : graphic_info[graphic].width);
1096     anim_frames_per_line = anim_frames_per_row;
1097   }
1098
1099   /* optionally, the x and y offset of frames can be specified directly */
1100   if (parameter[GFX_ARG_XOFFSET] != ARG_UNDEFINED_VALUE)
1101     graphic_info[graphic].offset_x = parameter[GFX_ARG_XOFFSET];
1102   if (parameter[GFX_ARG_YOFFSET] != ARG_UNDEFINED_VALUE)
1103     graphic_info[graphic].offset_y = parameter[GFX_ARG_YOFFSET];
1104
1105   /* optionally, moving animations may have separate start and end graphics */
1106   graphic_info[graphic].double_movement = parameter[GFX_ARG_2ND_MOVEMENT_TILE];
1107
1108   if (parameter[GFX_ARG_2ND_VERTICAL] == ARG_UNDEFINED_VALUE)
1109     parameter[GFX_ARG_2ND_VERTICAL] = !parameter[GFX_ARG_VERTICAL];
1110
1111   /* correct x or y offset2 dependent of vertical or horizontal frame order */
1112   if (parameter[GFX_ARG_2ND_VERTICAL])  /* frames are ordered vertically */
1113     graphic_info[graphic].offset2_y =
1114       (parameter[GFX_ARG_2ND_OFFSET] != ARG_UNDEFINED_VALUE ?
1115        parameter[GFX_ARG_2ND_OFFSET] : graphic_info[graphic].height);
1116   else                                  /* frames are ordered horizontally */
1117     graphic_info[graphic].offset2_x =
1118       (parameter[GFX_ARG_2ND_OFFSET] != ARG_UNDEFINED_VALUE ?
1119        parameter[GFX_ARG_2ND_OFFSET] : graphic_info[graphic].width);
1120
1121   /* optionally, the x and y offset of 2nd graphic can be specified directly */
1122   if (parameter[GFX_ARG_2ND_XOFFSET] != ARG_UNDEFINED_VALUE)
1123     graphic_info[graphic].offset2_x = parameter[GFX_ARG_2ND_XOFFSET];
1124   if (parameter[GFX_ARG_2ND_YOFFSET] != ARG_UNDEFINED_VALUE)
1125     graphic_info[graphic].offset2_y = parameter[GFX_ARG_2ND_YOFFSET];
1126
1127   /* optionally, the second movement tile can be specified as start tile */
1128   if (parameter[GFX_ARG_2ND_SWAP_TILES] != ARG_UNDEFINED_VALUE)
1129     graphic_info[graphic].swap_double_tiles= parameter[GFX_ARG_2ND_SWAP_TILES];
1130
1131   /* automatically determine correct number of frames, if not defined */
1132   if (parameter[GFX_ARG_FRAMES] != ARG_UNDEFINED_VALUE)
1133     graphic_info[graphic].anim_frames = parameter[GFX_ARG_FRAMES];
1134   else if (parameter[GFX_ARG_XPOS] == 0 && !parameter[GFX_ARG_VERTICAL])
1135     graphic_info[graphic].anim_frames = anim_frames_per_row;
1136   else if (parameter[GFX_ARG_YPOS] == 0 && parameter[GFX_ARG_VERTICAL])
1137     graphic_info[graphic].anim_frames = anim_frames_per_col;
1138   else
1139     graphic_info[graphic].anim_frames = 1;
1140
1141   if (graphic_info[graphic].anim_frames == 0)   /* frames must be at least 1 */
1142     graphic_info[graphic].anim_frames = 1;
1143
1144   graphic_info[graphic].anim_frames_per_line =
1145     (parameter[GFX_ARG_FRAMES_PER_LINE] != ARG_UNDEFINED_VALUE ?
1146      parameter[GFX_ARG_FRAMES_PER_LINE] : anim_frames_per_line);
1147
1148   graphic_info[graphic].anim_delay = parameter[GFX_ARG_DELAY];
1149   if (graphic_info[graphic].anim_delay == 0)    /* delay must be at least 1 */
1150     graphic_info[graphic].anim_delay = 1;
1151
1152   graphic_info[graphic].anim_mode = parameter[GFX_ARG_ANIM_MODE];
1153 #if 0
1154   if (graphic_info[graphic].anim_frames == 1)
1155     graphic_info[graphic].anim_mode = ANIM_NONE;
1156 #endif
1157
1158   /* automatically determine correct start frame, if not defined */
1159   if (parameter[GFX_ARG_START_FRAME] == ARG_UNDEFINED_VALUE)
1160     graphic_info[graphic].anim_start_frame = 0;
1161   else if (graphic_info[graphic].anim_mode & ANIM_REVERSE)
1162     graphic_info[graphic].anim_start_frame =
1163       graphic_info[graphic].anim_frames - parameter[GFX_ARG_START_FRAME] - 1;
1164   else
1165     graphic_info[graphic].anim_start_frame = parameter[GFX_ARG_START_FRAME];
1166
1167   /* animation synchronized with global frame counter, not move position */
1168   graphic_info[graphic].anim_global_sync = parameter[GFX_ARG_GLOBAL_SYNC];
1169
1170   /* optional element for cloning crumble graphics */
1171   if (parameter[GFX_ARG_CRUMBLED_LIKE] != ARG_UNDEFINED_VALUE)
1172     graphic_info[graphic].crumbled_like = parameter[GFX_ARG_CRUMBLED_LIKE];
1173
1174   /* optional element for cloning digging graphics */
1175   if (parameter[GFX_ARG_DIGGABLE_LIKE] != ARG_UNDEFINED_VALUE)
1176     graphic_info[graphic].diggable_like = parameter[GFX_ARG_DIGGABLE_LIKE];
1177
1178   /* optional border size for "crumbling" diggable graphics */
1179   if (parameter[GFX_ARG_BORDER_SIZE] != ARG_UNDEFINED_VALUE)
1180     graphic_info[graphic].border_size = parameter[GFX_ARG_BORDER_SIZE];
1181
1182   /* this is only used for player "boring" and "sleeping" actions */
1183   if (parameter[GFX_ARG_ANIM_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
1184     graphic_info[graphic].anim_delay_fixed =
1185       parameter[GFX_ARG_ANIM_DELAY_FIXED];
1186   if (parameter[GFX_ARG_ANIM_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
1187     graphic_info[graphic].anim_delay_random =
1188       parameter[GFX_ARG_ANIM_DELAY_RANDOM];
1189   if (parameter[GFX_ARG_POST_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
1190     graphic_info[graphic].post_delay_fixed =
1191       parameter[GFX_ARG_POST_DELAY_FIXED];
1192   if (parameter[GFX_ARG_POST_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
1193     graphic_info[graphic].post_delay_random =
1194       parameter[GFX_ARG_POST_DELAY_RANDOM];
1195
1196   /* this is only used for toon animations */
1197   graphic_info[graphic].step_offset = parameter[GFX_ARG_STEP_OFFSET];
1198   graphic_info[graphic].step_delay  = parameter[GFX_ARG_STEP_DELAY];
1199
1200   /* this is only used for drawing font characters */
1201   graphic_info[graphic].draw_xoffset = parameter[GFX_ARG_DRAW_XOFFSET];
1202   graphic_info[graphic].draw_yoffset = parameter[GFX_ARG_DRAW_YOFFSET];
1203
1204   /* this is only used for drawing envelope graphics */
1205   graphic_info[graphic].draw_masked = parameter[GFX_ARG_DRAW_MASKED];
1206
1207   /* optional graphic for cloning all graphics settings */
1208   if (parameter[GFX_ARG_CLONE_FROM] != ARG_UNDEFINED_VALUE)
1209     graphic_info[graphic].clone_from = parameter[GFX_ARG_CLONE_FROM];
1210
1211   /* optional settings for drawing title screens */
1212   if (parameter[GFX_ARG_FADE_DELAY] != ARG_UNDEFINED_VALUE)
1213     graphic_info[graphic].fade_delay = parameter[GFX_ARG_FADE_DELAY];
1214   if (parameter[GFX_ARG_POST_DELAY] != ARG_UNDEFINED_VALUE)
1215     graphic_info[graphic].post_delay = parameter[GFX_ARG_POST_DELAY];
1216   if (parameter[GFX_ARG_AUTO_DELAY] != ARG_UNDEFINED_VALUE)
1217     graphic_info[graphic].auto_delay = parameter[GFX_ARG_AUTO_DELAY];
1218   if (parameter[GFX_ARG_ALIGN] != ARG_UNDEFINED_VALUE)
1219     graphic_info[graphic].align = parameter[GFX_ARG_ALIGN];
1220   if (parameter[GFX_ARG_VALIGN] != ARG_UNDEFINED_VALUE)
1221     graphic_info[graphic].valign = parameter[GFX_ARG_VALIGN];
1222   if (parameter[GFX_ARG_SORT_PRIORITY] != ARG_UNDEFINED_VALUE)
1223     graphic_info[graphic].sort_priority = parameter[GFX_ARG_SORT_PRIORITY];
1224 }
1225
1226 static void set_cloned_graphic_parameters(int graphic)
1227 {
1228   int fallback_graphic = IMG_CHAR_EXCLAM;
1229   int max_num_images = getImageListSize();
1230   int clone_graphic = graphic_info[graphic].clone_from;
1231   int num_references_followed = 1;
1232
1233   while (graphic_info[clone_graphic].clone_from != -1 &&
1234          num_references_followed < max_num_images)
1235   {
1236     clone_graphic = graphic_info[clone_graphic].clone_from;
1237
1238     num_references_followed++;
1239   }
1240
1241   if (num_references_followed >= max_num_images)
1242   {
1243     Error(ERR_INFO_LINE, "-");
1244     Error(ERR_INFO, "warning: error found in config file:");
1245     Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
1246     Error(ERR_INFO, "- config token: '%s'", getTokenFromImageID(graphic));
1247     Error(ERR_INFO, "error: loop discovered when resolving cloned graphics");
1248     Error(ERR_INFO, "custom graphic rejected for this element/action");
1249
1250     if (graphic == fallback_graphic)
1251       Error(ERR_EXIT, "fatal error: no fallback graphic available");
1252
1253     Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic");
1254     Error(ERR_INFO_LINE, "-");
1255
1256     graphic_info[graphic] = graphic_info[fallback_graphic];
1257   }
1258   else
1259   {
1260     graphic_info[graphic] = graphic_info[clone_graphic];
1261     graphic_info[graphic].clone_from = clone_graphic;
1262   }
1263 }
1264
1265 static void InitGraphicInfo()
1266 {
1267   int fallback_graphic = IMG_CHAR_EXCLAM;
1268   int num_images = getImageListSize();
1269   int i;
1270
1271 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1272   static boolean clipmasks_initialized = FALSE;
1273   Pixmap src_pixmap;
1274   XGCValues clip_gc_values;
1275   unsigned long clip_gc_valuemask;
1276   GC copy_clipmask_gc = None;
1277 #endif
1278
1279   /* use image size as default values for width and height for these images */
1280   static int full_size_graphics[] =
1281   {
1282     IMG_GLOBAL_BORDER,
1283     IMG_GLOBAL_DOOR,
1284
1285     IMG_BACKGROUND_ENVELOPE_1,
1286     IMG_BACKGROUND_ENVELOPE_2,
1287     IMG_BACKGROUND_ENVELOPE_3,
1288     IMG_BACKGROUND_ENVELOPE_4,
1289
1290     IMG_BACKGROUND,
1291     IMG_BACKGROUND_TITLE_INITIAL,
1292     IMG_BACKGROUND_TITLE,
1293     IMG_BACKGROUND_MAIN,
1294     IMG_BACKGROUND_LEVELS,
1295     IMG_BACKGROUND_SCORES,
1296     IMG_BACKGROUND_EDITOR,
1297     IMG_BACKGROUND_INFO,
1298     IMG_BACKGROUND_INFO_ELEMENTS,
1299     IMG_BACKGROUND_INFO_MUSIC,
1300     IMG_BACKGROUND_INFO_CREDITS,
1301     IMG_BACKGROUND_INFO_PROGRAM,
1302     IMG_BACKGROUND_INFO_LEVELSET,
1303     IMG_BACKGROUND_SETUP,
1304     IMG_BACKGROUND_DOOR,
1305
1306     IMG_TITLESCREEN_INITIAL_1,
1307     IMG_TITLESCREEN_INITIAL_2,
1308     IMG_TITLESCREEN_INITIAL_3,
1309     IMG_TITLESCREEN_INITIAL_4,
1310     IMG_TITLESCREEN_INITIAL_5,
1311     IMG_TITLESCREEN_1,
1312     IMG_TITLESCREEN_2,
1313     IMG_TITLESCREEN_3,
1314     IMG_TITLESCREEN_4,
1315     IMG_TITLESCREEN_5,
1316
1317     -1
1318   };
1319
1320   checked_free(graphic_info);
1321
1322   graphic_info = checked_calloc(num_images * sizeof(struct GraphicInfo));
1323
1324 #if 1
1325   /* initialize "use_image_size" flag with default value */
1326   for (i = 0; i < num_images; i++)
1327     graphic_info[i].use_image_size = FALSE;
1328
1329   /* initialize "use_image_size" flag from static configuration above */
1330   for (i = 0; full_size_graphics[i] != -1; i++)
1331     graphic_info[full_size_graphics[i]].use_image_size = TRUE;
1332 #endif
1333
1334 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1335   if (clipmasks_initialized)
1336   {
1337     for (i = 0; i < num_images; i++)
1338     {
1339       if (graphic_info[i].clip_mask)
1340         XFreePixmap(display, graphic_info[i].clip_mask);
1341       if (graphic_info[i].clip_gc)
1342         XFreeGC(display, graphic_info[i].clip_gc);
1343
1344       graphic_info[i].clip_mask = None;
1345       graphic_info[i].clip_gc = None;
1346     }
1347   }
1348 #endif
1349
1350   /* first set all graphic paramaters ... */
1351   for (i = 0; i < num_images; i++)
1352     set_graphic_parameters(i);
1353
1354   /* ... then copy these parameters for cloned graphics */
1355   for (i = 0; i < num_images; i++)
1356     if (graphic_info[i].clone_from != -1)
1357       set_cloned_graphic_parameters(i);
1358
1359   for (i = 0; i < num_images; i++)
1360   {
1361     Bitmap *src_bitmap;
1362     int src_x, src_y;
1363     int width, height;
1364     int first_frame, last_frame;
1365     int src_bitmap_width, src_bitmap_height;
1366
1367     /* now check if no animation frames are outside of the loaded image */
1368
1369     if (graphic_info[i].bitmap == NULL)
1370       continue;         /* skip check for optional images that are undefined */
1371
1372     /* get image size (this can differ from the standard element tile size!) */
1373     width  = graphic_info[i].width;
1374     height = graphic_info[i].height;
1375
1376     /* get final bitmap size (with scaling, but without small images) */
1377     src_bitmap_width  = graphic_info[i].src_image_width;
1378     src_bitmap_height = graphic_info[i].src_image_height;
1379
1380     /* check if first animation frame is inside specified bitmap */
1381
1382     first_frame = 0;
1383     getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
1384
1385 #if 1
1386     /* this avoids calculating wrong start position for out-of-bounds frame */
1387     src_x = graphic_info[i].src_x;
1388     src_y = graphic_info[i].src_y;
1389 #endif
1390
1391     if (src_x < 0 || src_y < 0 ||
1392         src_x + width  > src_bitmap_width ||
1393         src_y + height > src_bitmap_height)
1394     {
1395       Error(ERR_INFO_LINE, "-");
1396       Error(ERR_INFO, "warning: error found in config file:");
1397       Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
1398       Error(ERR_INFO, "- config token: '%s'", getTokenFromImageID(i));
1399       Error(ERR_INFO, "- image file: '%s'", src_bitmap->source_filename);
1400       Error(ERR_INFO,
1401             "error: first animation frame out of bounds (%d, %d) [%d, %d]",
1402             src_x, src_y, src_bitmap_width, src_bitmap_height);
1403       Error(ERR_INFO, "custom graphic rejected for this element/action");
1404
1405       if (i == fallback_graphic)
1406         Error(ERR_EXIT, "fatal error: no fallback graphic available");
1407
1408       Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic");
1409       Error(ERR_INFO_LINE, "-");
1410
1411       graphic_info[i] = graphic_info[fallback_graphic];
1412     }
1413
1414     /* check if last animation frame is inside specified bitmap */
1415
1416     last_frame = graphic_info[i].anim_frames - 1;
1417     getGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y);
1418
1419     if (src_x < 0 || src_y < 0 ||
1420         src_x + width  > src_bitmap_width ||
1421         src_y + height > src_bitmap_height)
1422     {
1423       Error(ERR_INFO_LINE, "-");
1424       Error(ERR_INFO, "warning: error found in config file:");
1425       Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
1426       Error(ERR_INFO, "- config token: '%s'", getTokenFromImageID(i));
1427       Error(ERR_INFO, "- image file: '%s'", src_bitmap->source_filename);
1428       Error(ERR_INFO,
1429             "error: last animation frame (%d) out of bounds (%d, %d) [%d, %d]",
1430             last_frame, src_x, src_y, src_bitmap_width, src_bitmap_height);
1431       Error(ERR_INFO, "custom graphic rejected for this element/action");
1432
1433       if (i == fallback_graphic)
1434         Error(ERR_EXIT, "fatal error: no fallback graphic available");
1435
1436       Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic");
1437       Error(ERR_INFO_LINE, "-");
1438
1439       graphic_info[i] = graphic_info[fallback_graphic];
1440     }
1441
1442 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1443     /* currently we only need a tile clip mask from the first frame */
1444     getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
1445
1446     if (copy_clipmask_gc == None)
1447     {
1448       clip_gc_values.graphics_exposures = False;
1449       clip_gc_valuemask = GCGraphicsExposures;
1450       copy_clipmask_gc = XCreateGC(display, src_bitmap->clip_mask,
1451                                    clip_gc_valuemask, &clip_gc_values);
1452     }
1453
1454     graphic_info[i].clip_mask =
1455       XCreatePixmap(display, window->drawable, TILEX, TILEY, 1);
1456
1457     src_pixmap = src_bitmap->clip_mask;
1458     XCopyArea(display, src_pixmap, graphic_info[i].clip_mask,
1459               copy_clipmask_gc, src_x, src_y, TILEX, TILEY, 0, 0);
1460
1461     clip_gc_values.graphics_exposures = False;
1462     clip_gc_values.clip_mask = graphic_info[i].clip_mask;
1463     clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
1464
1465     graphic_info[i].clip_gc =
1466       XCreateGC(display, window->drawable, clip_gc_valuemask, &clip_gc_values);
1467 #endif
1468   }
1469
1470 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1471   if (copy_clipmask_gc)
1472     XFreeGC(display, copy_clipmask_gc);
1473
1474   clipmasks_initialized = TRUE;
1475 #endif
1476 }
1477
1478 static void InitElementSoundInfo()
1479 {
1480   struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1481   int num_property_mappings = getSoundListPropertyMappingSize();
1482   int i, j, act;
1483
1484   /* set values to -1 to identify later as "uninitialized" values */
1485   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1486     for (act = 0; act < NUM_ACTIONS; act++)
1487       element_info[i].sound[act] = -1;
1488
1489   /* initialize element/sound mapping from static configuration */
1490   for (i = 0; element_to_sound[i].element > -1; i++)
1491   {
1492     int element      = element_to_sound[i].element;
1493     int action       = element_to_sound[i].action;
1494     int sound        = element_to_sound[i].sound;
1495     boolean is_class = element_to_sound[i].is_class;
1496
1497     if (action < 0)
1498       action = ACTION_DEFAULT;
1499
1500     if (!is_class)
1501       element_info[element].sound[action] = sound;
1502     else
1503       for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1504         if (strEqual(element_info[j].class_name,
1505                      element_info[element].class_name))
1506           element_info[j].sound[action] = sound;
1507   }
1508
1509   /* initialize element class/sound mapping from dynamic configuration */
1510   for (i = 0; i < num_property_mappings; i++)
1511   {
1512     int element_class = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
1513     int action        = property_mapping[i].ext1_index;
1514     int sound         = property_mapping[i].artwork_index;
1515
1516     if (element_class < 0 || element_class >= MAX_NUM_ELEMENTS)
1517       continue;
1518
1519     if (action < 0)
1520       action = ACTION_DEFAULT;
1521
1522     for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1523       if (strEqual(element_info[j].class_name,
1524                    element_info[element_class].class_name))
1525         element_info[j].sound[action] = sound;
1526   }
1527
1528   /* initialize element/sound mapping from dynamic configuration */
1529   for (i = 0; i < num_property_mappings; i++)
1530   {
1531     int element = property_mapping[i].base_index;
1532     int action  = property_mapping[i].ext1_index;
1533     int sound   = property_mapping[i].artwork_index;
1534
1535     if (element >= MAX_NUM_ELEMENTS)
1536       continue;
1537
1538     if (action < 0)
1539       action = ACTION_DEFAULT;
1540
1541     element_info[element].sound[action] = sound;
1542   }
1543
1544   /* now set all '-1' values to element specific default values */
1545   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1546   {
1547     for (act = 0; act < NUM_ACTIONS; act++)
1548     {
1549       /* generic default action sound (defined by "[default]" directive) */
1550       int default_action_sound = element_info[EL_DEFAULT].sound[act];
1551
1552       /* look for special default action sound (classic game specific) */
1553       if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].sound[act] != -1)
1554         default_action_sound = element_info[EL_BD_DEFAULT].sound[act];
1555       if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].sound[act] != -1)
1556         default_action_sound = element_info[EL_SP_DEFAULT].sound[act];
1557       if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].sound[act] != -1)
1558         default_action_sound = element_info[EL_SB_DEFAULT].sound[act];
1559
1560       /* !!! there's no such thing as a "default action sound" !!! */
1561 #if 0
1562       /* look for element specific default sound (independent from action) */
1563       if (element_info[i].sound[ACTION_DEFAULT] != -1)
1564         default_action_sound = element_info[i].sound[ACTION_DEFAULT];
1565 #endif
1566
1567 #if 1
1568       /* !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!! */
1569       /* !!! make this better !!! */
1570       if (i == EL_EMPTY_SPACE)
1571         default_action_sound = element_info[EL_DEFAULT].sound[act];
1572 #endif
1573
1574       /* no sound for this specific action -- use default action sound */
1575       if (element_info[i].sound[act] == -1)
1576         element_info[i].sound[act] = default_action_sound;
1577     }
1578   }
1579
1580   /* copy sound settings to some elements that are only stored in level file
1581      in native R'n'D levels, but are used by game engine in native EM levels */
1582   for (i = 0; copy_properties[i][0] != -1; i++)
1583     for (j = 1; j <= 4; j++)
1584       for (act = 0; act < NUM_ACTIONS; act++)
1585         element_info[copy_properties[i][j]].sound[act] =
1586           element_info[copy_properties[i][0]].sound[act];
1587 }
1588
1589 static void InitGameModeSoundInfo()
1590 {
1591   int i;
1592
1593   /* set values to -1 to identify later as "uninitialized" values */
1594   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1595     menu.sound[i] = -1;
1596
1597   /* initialize gamemode/sound mapping from static configuration */
1598   for (i = 0; gamemode_to_sound[i].sound > -1; i++)
1599   {
1600     int gamemode = gamemode_to_sound[i].gamemode;
1601     int sound    = gamemode_to_sound[i].sound;
1602
1603     if (gamemode < 0)
1604       gamemode = GAME_MODE_DEFAULT;
1605
1606     menu.sound[gamemode] = sound;
1607   }
1608
1609   /* now set all '-1' values to levelset specific default values */
1610   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1611     if (menu.sound[i] == -1)
1612       menu.sound[i] = menu.sound[GAME_MODE_DEFAULT];
1613
1614 #if 0
1615   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1616     if (menu.sound[i] != -1)
1617       printf("::: menu.sound[%d] == %d\n", i, menu.sound[i]);
1618 #endif
1619 }
1620
1621 static void set_sound_parameters(int sound, char **parameter_raw)
1622 {
1623   int parameter[NUM_SND_ARGS];
1624   int i;
1625
1626   /* get integer values from string parameters */
1627   for (i = 0; i < NUM_SND_ARGS; i++)
1628     parameter[i] =
1629       get_parameter_value(parameter_raw[i],
1630                           sound_config_suffix[i].token,
1631                           sound_config_suffix[i].type);
1632
1633   /* explicit loop mode setting in configuration overrides default value */
1634   if (parameter[SND_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
1635     sound_info[sound].loop = parameter[SND_ARG_MODE_LOOP];
1636
1637   /* sound volume to change the original volume when loading the sound file */
1638   sound_info[sound].volume = parameter[SND_ARG_VOLUME];
1639
1640   /* sound priority to give certain sounds a higher or lower priority */
1641   sound_info[sound].priority = parameter[SND_ARG_PRIORITY];
1642 }
1643
1644 static void InitSoundInfo()
1645 {
1646   int *sound_effect_properties;
1647   int num_sounds = getSoundListSize();
1648   int i, j;
1649
1650   checked_free(sound_info);
1651
1652   sound_effect_properties = checked_calloc(num_sounds * sizeof(int));
1653   sound_info = checked_calloc(num_sounds * sizeof(struct SoundInfo));
1654
1655   /* initialize sound effect for all elements to "no sound" */
1656   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1657     for (j = 0; j < NUM_ACTIONS; j++)
1658       element_info[i].sound[j] = SND_UNDEFINED;
1659
1660   for (i = 0; i < num_sounds; i++)
1661   {
1662     struct FileInfo *sound = getSoundListEntry(i);
1663     int len_effect_text = strlen(sound->token);
1664
1665     sound_effect_properties[i] = ACTION_OTHER;
1666     sound_info[i].loop = FALSE;         /* default: play sound only once */
1667
1668 #if 0
1669     printf("::: sound %d: '%s'\n", i, sound->token);
1670 #endif
1671
1672     /* determine all loop sounds and identify certain sound classes */
1673
1674     for (j = 0; element_action_info[j].suffix; j++)
1675     {
1676       int len_action_text = strlen(element_action_info[j].suffix);
1677
1678       if (len_action_text < len_effect_text &&
1679           strEqual(&sound->token[len_effect_text - len_action_text],
1680                    element_action_info[j].suffix))
1681       {
1682         sound_effect_properties[i] = element_action_info[j].value;
1683         sound_info[i].loop = element_action_info[j].is_loop_sound;
1684
1685         break;
1686       }
1687     }
1688
1689     /* associate elements and some selected sound actions */
1690
1691     for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1692     {
1693       if (element_info[j].class_name)
1694       {
1695         int len_class_text = strlen(element_info[j].class_name);
1696
1697         if (len_class_text + 1 < len_effect_text &&
1698             strncmp(sound->token,
1699                     element_info[j].class_name, len_class_text) == 0 &&
1700             sound->token[len_class_text] == '.')
1701         {
1702           int sound_action_value = sound_effect_properties[i];
1703
1704           element_info[j].sound[sound_action_value] = i;
1705         }
1706       }
1707     }
1708
1709     set_sound_parameters(i, sound->parameter);
1710   }
1711
1712   free(sound_effect_properties);
1713 }
1714
1715 static void InitGameModeMusicInfo()
1716 {
1717   struct PropertyMapping *property_mapping = getMusicListPropertyMapping();
1718   int num_property_mappings = getMusicListPropertyMappingSize();
1719   int default_levelset_music = -1;
1720   int i;
1721
1722   /* set values to -1 to identify later as "uninitialized" values */
1723   for (i = 0; i < MAX_LEVELS; i++)
1724     levelset.music[i] = -1;
1725   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1726     menu.music[i] = -1;
1727
1728   /* initialize gamemode/music mapping from static configuration */
1729   for (i = 0; gamemode_to_music[i].music > -1; i++)
1730   {
1731     int gamemode = gamemode_to_music[i].gamemode;
1732     int music    = gamemode_to_music[i].music;
1733
1734 #if 0
1735     printf("::: gamemode == %d, music == %d\n", gamemode, music);
1736 #endif
1737
1738     if (gamemode < 0)
1739       gamemode = GAME_MODE_DEFAULT;
1740
1741     menu.music[gamemode] = music;
1742   }
1743
1744   /* initialize gamemode/music mapping from dynamic configuration */
1745   for (i = 0; i < num_property_mappings; i++)
1746   {
1747     int prefix   = property_mapping[i].base_index;
1748     int gamemode = property_mapping[i].ext1_index;
1749     int level    = property_mapping[i].ext2_index;
1750     int music    = property_mapping[i].artwork_index;
1751
1752 #if 0
1753     printf("::: prefix == %d, gamemode == %d, level == %d, music == %d\n",
1754            prefix, gamemode, level, music);
1755 #endif
1756
1757     if (prefix < 0 || prefix >= NUM_MUSIC_PREFIXES)
1758       continue;
1759
1760     if (gamemode < 0)
1761       gamemode = GAME_MODE_DEFAULT;
1762
1763     /* level specific music only allowed for in-game music */
1764     if (level != -1 && gamemode == GAME_MODE_DEFAULT)
1765       gamemode = GAME_MODE_PLAYING;
1766
1767     if (level == -1)
1768     {
1769       level = 0;
1770       default_levelset_music = music;
1771     }
1772
1773     if (gamemode == GAME_MODE_PLAYING || gamemode == GAME_MODE_DEFAULT)
1774       levelset.music[level] = music;
1775     if (gamemode != GAME_MODE_PLAYING)
1776       menu.music[gamemode] = music;
1777   }
1778
1779   /* now set all '-1' values to menu specific default values */
1780   /* (undefined values of "levelset.music[]" might stay at "-1" to
1781      allow dynamic selection of music files from music directory!) */
1782   for (i = 0; i < MAX_LEVELS; i++)
1783     if (levelset.music[i] == -1)
1784       levelset.music[i] = default_levelset_music;
1785   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1786     if (menu.music[i] == -1)
1787       menu.music[i] = menu.music[GAME_MODE_DEFAULT];
1788
1789 #if 0
1790   for (i = 0; i < MAX_LEVELS; i++)
1791     if (levelset.music[i] != -1)
1792       printf("::: levelset.music[%d] == %d\n", i, levelset.music[i]);
1793   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1794     if (menu.music[i] != -1)
1795       printf("::: menu.music[%d] == %d\n", i, menu.music[i]);
1796 #endif
1797 }
1798
1799 static void set_music_parameters(int music, char **parameter_raw)
1800 {
1801   int parameter[NUM_MUS_ARGS];
1802   int i;
1803
1804   /* get integer values from string parameters */
1805   for (i = 0; i < NUM_MUS_ARGS; i++)
1806     parameter[i] =
1807       get_parameter_value(parameter_raw[i],
1808                           music_config_suffix[i].token,
1809                           music_config_suffix[i].type);
1810
1811   /* explicit loop mode setting in configuration overrides default value */
1812   if (parameter[MUS_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
1813     music_info[music].loop = parameter[MUS_ARG_MODE_LOOP];
1814 }
1815
1816 static void InitMusicInfo()
1817 {
1818   int num_music = getMusicListSize();
1819   int i, j;
1820
1821   checked_free(music_info);
1822
1823   music_info = checked_calloc(num_music * sizeof(struct MusicInfo));
1824
1825   for (i = 0; i < num_music; i++)
1826   {
1827     struct FileInfo *music = getMusicListEntry(i);
1828     int len_music_text = strlen(music->token);
1829
1830     music_info[i].loop = TRUE;          /* default: play music in loop mode */
1831
1832     /* determine all loop music */
1833
1834     for (j = 0; music_prefix_info[j].prefix; j++)
1835     {
1836       int len_prefix_text = strlen(music_prefix_info[j].prefix);
1837
1838       if (len_prefix_text < len_music_text &&
1839           strncmp(music->token,
1840                   music_prefix_info[j].prefix, len_prefix_text) == 0)
1841       {
1842         music_info[i].loop = music_prefix_info[j].is_loop_music;
1843
1844         break;
1845       }
1846     }
1847
1848     set_music_parameters(i, music->parameter);
1849   }
1850 }
1851
1852 static void ReinitializeGraphics()
1853 {
1854   InitGraphicInfo();                    /* graphic properties mapping */
1855   InitElementGraphicInfo();             /* element game graphic mapping */
1856   InitElementSpecialGraphicInfo();      /* element special graphic mapping */
1857
1858   InitElementSmallImages();             /* scale elements to all needed sizes */
1859   InitScaledImages();                   /* scale all other images, if needed */
1860   InitFontGraphicInfo();                /* initialize text drawing functions */
1861
1862   InitGraphicInfo_EM();                 /* graphic mapping for EM engine */
1863
1864   SetMainBackgroundImage(IMG_BACKGROUND);
1865   SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
1866
1867   InitGadgets();
1868   InitToons();
1869 }
1870
1871 static void ReinitializeSounds()
1872 {
1873   InitSoundInfo();              /* sound properties mapping */
1874   InitElementSoundInfo();       /* element game sound mapping */
1875   InitGameModeSoundInfo();      /* game mode sound mapping */
1876
1877   InitPlayLevelSound();         /* internal game sound settings */
1878 }
1879
1880 static void ReinitializeMusic()
1881 {
1882   InitMusicInfo();              /* music properties mapping */
1883   InitGameModeMusicInfo();      /* game mode music mapping */
1884 }
1885
1886 static int get_special_property_bit(int element, int property_bit_nr)
1887 {
1888   struct PropertyBitInfo
1889   {
1890     int element;
1891     int bit_nr;
1892   };
1893
1894   static struct PropertyBitInfo pb_can_move_into_acid[] =
1895   {
1896     /* the player may be able fall into acid when gravity is activated */
1897     { EL_PLAYER_1,              0       },
1898     { EL_PLAYER_2,              0       },
1899     { EL_PLAYER_3,              0       },
1900     { EL_PLAYER_4,              0       },
1901     { EL_SP_MURPHY,             0       },
1902     { EL_SOKOBAN_FIELD_PLAYER,  0       },
1903
1904     /* all elements that can move may be able to also move into acid */
1905     { EL_BUG,                   1       },
1906     { EL_BUG_LEFT,              1       },
1907     { EL_BUG_RIGHT,             1       },
1908     { EL_BUG_UP,                1       },
1909     { EL_BUG_DOWN,              1       },
1910     { EL_SPACESHIP,             2       },
1911     { EL_SPACESHIP_LEFT,        2       },
1912     { EL_SPACESHIP_RIGHT,       2       },
1913     { EL_SPACESHIP_UP,          2       },
1914     { EL_SPACESHIP_DOWN,        2       },
1915     { EL_BD_BUTTERFLY,          3       },
1916     { EL_BD_BUTTERFLY_LEFT,     3       },
1917     { EL_BD_BUTTERFLY_RIGHT,    3       },
1918     { EL_BD_BUTTERFLY_UP,       3       },
1919     { EL_BD_BUTTERFLY_DOWN,     3       },
1920     { EL_BD_FIREFLY,            4       },
1921     { EL_BD_FIREFLY_LEFT,       4       },
1922     { EL_BD_FIREFLY_RIGHT,      4       },
1923     { EL_BD_FIREFLY_UP,         4       },
1924     { EL_BD_FIREFLY_DOWN,       4       },
1925     { EL_YAMYAM,                5       },
1926     { EL_YAMYAM_LEFT,           5       },
1927     { EL_YAMYAM_RIGHT,          5       },
1928     { EL_YAMYAM_UP,             5       },
1929     { EL_YAMYAM_DOWN,           5       },
1930     { EL_DARK_YAMYAM,           6       },
1931     { EL_ROBOT,                 7       },
1932     { EL_PACMAN,                8       },
1933     { EL_PACMAN_LEFT,           8       },
1934     { EL_PACMAN_RIGHT,          8       },
1935     { EL_PACMAN_UP,             8       },
1936     { EL_PACMAN_DOWN,           8       },
1937     { EL_MOLE,                  9       },
1938     { EL_MOLE_LEFT,             9       },
1939     { EL_MOLE_RIGHT,            9       },
1940     { EL_MOLE_UP,               9       },
1941     { EL_MOLE_DOWN,             9       },
1942     { EL_PENGUIN,               10      },
1943     { EL_PIG,                   11      },
1944     { EL_DRAGON,                12      },
1945     { EL_SATELLITE,             13      },
1946     { EL_SP_SNIKSNAK,           14      },
1947     { EL_SP_ELECTRON,           15      },
1948     { EL_BALLOON,               16      },
1949     { EL_SPRING,                17      },
1950     { EL_EMC_ANDROID,           18      },
1951
1952     { -1,                       -1      },
1953   };
1954
1955   static struct PropertyBitInfo pb_dont_collide_with[] =
1956   {
1957     { EL_SP_SNIKSNAK,           0       },
1958     { EL_SP_ELECTRON,           1       },
1959
1960     { -1,                       -1      },
1961   };
1962
1963   static struct
1964   {
1965     int bit_nr;
1966     struct PropertyBitInfo *pb_info;
1967   } pb_definition[] =
1968   {
1969     { EP_CAN_MOVE_INTO_ACID,    pb_can_move_into_acid   },
1970     { EP_DONT_COLLIDE_WITH,     pb_dont_collide_with    },
1971
1972     { -1,                       NULL                    },
1973   };
1974
1975   struct PropertyBitInfo *pb_info = NULL;
1976   int i;
1977
1978   for (i = 0; pb_definition[i].bit_nr != -1; i++)
1979     if (pb_definition[i].bit_nr == property_bit_nr)
1980       pb_info = pb_definition[i].pb_info;
1981
1982   if (pb_info == NULL)
1983     return -1;
1984
1985   for (i = 0; pb_info[i].element != -1; i++)
1986     if (pb_info[i].element == element)
1987       return pb_info[i].bit_nr;
1988
1989   return -1;
1990 }
1991
1992 void setBitfieldProperty(int *bitfield, int property_bit_nr, int element,
1993                          boolean property_value)
1994 {
1995   int bit_nr = get_special_property_bit(element, property_bit_nr);
1996
1997   if (bit_nr > -1)
1998   {
1999     if (property_value)
2000       *bitfield |=  (1 << bit_nr);
2001     else
2002       *bitfield &= ~(1 << bit_nr);
2003   }
2004 }
2005
2006 boolean getBitfieldProperty(int *bitfield, int property_bit_nr, int element)
2007 {
2008   int bit_nr = get_special_property_bit(element, property_bit_nr);
2009
2010   if (bit_nr > -1)
2011     return ((*bitfield & (1 << bit_nr)) != 0);
2012
2013   return FALSE;
2014 }
2015
2016 static void ResolveGroupElementExt(int group_element, int recursion_depth)
2017 {
2018   static int group_nr;
2019   static struct ElementGroupInfo *group;
2020   struct ElementGroupInfo *actual_group = element_info[group_element].group;
2021   int i;
2022
2023   if (actual_group == NULL)                     /* not yet initialized */
2024     return;
2025
2026   if (recursion_depth > NUM_GROUP_ELEMENTS)     /* recursion too deep */
2027   {
2028     Error(ERR_WARN, "recursion too deep when resolving group element %d",
2029           group_element - EL_GROUP_START + 1);
2030
2031     /* replace element which caused too deep recursion by question mark */
2032     group->element_resolved[group->num_elements_resolved++] = EL_UNKNOWN;
2033
2034     return;
2035   }
2036
2037   if (recursion_depth == 0)                     /* initialization */
2038   {
2039     group = actual_group;
2040     group_nr = GROUP_NR(group_element);
2041
2042     group->num_elements_resolved = 0;
2043     group->choice_pos = 0;
2044
2045     for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2046       element_info[i].in_group[group_nr] = FALSE;
2047   }
2048
2049   for (i = 0; i < actual_group->num_elements; i++)
2050   {
2051     int element = actual_group->element[i];
2052
2053     if (group->num_elements_resolved == NUM_FILE_ELEMENTS)
2054       break;
2055
2056     if (IS_GROUP_ELEMENT(element))
2057       ResolveGroupElementExt(element, recursion_depth + 1);
2058     else
2059     {
2060       group->element_resolved[group->num_elements_resolved++] = element;
2061       element_info[element].in_group[group_nr] = TRUE;
2062     }
2063   }
2064 }
2065
2066 void ResolveGroupElement(int group_element)
2067 {
2068   ResolveGroupElementExt(group_element, 0);
2069 }
2070
2071 void InitElementPropertiesStatic()
2072 {
2073   static int ep_diggable[] =
2074   {
2075     EL_SAND,
2076     EL_SP_BASE,
2077     EL_SP_BUGGY_BASE,
2078     EL_SP_BUGGY_BASE_ACTIVATING,
2079     EL_TRAP,
2080     EL_INVISIBLE_SAND,
2081     EL_INVISIBLE_SAND_ACTIVE,
2082     EL_EMC_GRASS,
2083
2084     /* !!! currently not diggable, but handled by 'ep_dont_run_into' !!! */
2085     /* (if amoeba can grow into anything diggable, maybe keep these out) */
2086 #if 0
2087     EL_LANDMINE,
2088     EL_DC_LANDMINE,
2089     EL_TRAP_ACTIVE,
2090     EL_SP_BUGGY_BASE_ACTIVE,
2091     EL_EMC_PLANT,
2092 #endif
2093
2094     -1
2095   };
2096
2097   static int ep_collectible_only[] =
2098   {
2099     EL_BD_DIAMOND,
2100     EL_EMERALD,
2101     EL_DIAMOND,
2102     EL_EMERALD_YELLOW,
2103     EL_EMERALD_RED,
2104     EL_EMERALD_PURPLE,
2105     EL_KEY_1,
2106     EL_KEY_2,
2107     EL_KEY_3,
2108     EL_KEY_4,
2109     EL_EM_KEY_1,
2110     EL_EM_KEY_2,
2111     EL_EM_KEY_3,
2112     EL_EM_KEY_4,
2113     EL_EMC_KEY_5,
2114     EL_EMC_KEY_6,
2115     EL_EMC_KEY_7,
2116     EL_EMC_KEY_8,
2117     EL_DYNAMITE,
2118     EL_EM_DYNAMITE,
2119     EL_DYNABOMB_INCREASE_NUMBER,
2120     EL_DYNABOMB_INCREASE_SIZE,
2121     EL_DYNABOMB_INCREASE_POWER,
2122     EL_SP_INFOTRON,
2123     EL_SP_DISK_RED,
2124     EL_PEARL,
2125     EL_CRYSTAL,
2126     EL_DC_KEY_WHITE,
2127     EL_SHIELD_NORMAL,
2128     EL_SHIELD_DEADLY,
2129     EL_EXTRA_TIME,
2130     EL_ENVELOPE_1,
2131     EL_ENVELOPE_2,
2132     EL_ENVELOPE_3,
2133     EL_ENVELOPE_4,
2134     EL_SPEED_PILL,
2135     EL_EMC_LENSES,
2136     EL_EMC_MAGNIFIER,
2137
2138 #if 0
2139     /* !!! handle separately !!! */
2140     EL_DC_LANDMINE,     /* deadly when running into, but can be snapped */
2141 #endif
2142
2143     -1
2144   };
2145
2146   static int ep_dont_run_into[] =
2147   {
2148     /* same elements as in 'ep_dont_touch' */
2149     EL_BUG,
2150     EL_SPACESHIP,
2151     EL_BD_BUTTERFLY,
2152     EL_BD_FIREFLY,
2153
2154     /* same elements as in 'ep_dont_collide_with' */
2155     EL_YAMYAM,
2156     EL_DARK_YAMYAM,
2157     EL_ROBOT,
2158     EL_PACMAN,
2159     EL_SP_SNIKSNAK,
2160     EL_SP_ELECTRON,
2161
2162     /* new elements */
2163     EL_AMOEBA_DROP,
2164     EL_ACID,
2165
2166     /* !!! maybe this should better be handled by 'ep_diggable' !!! */
2167 #if 1
2168     EL_LANDMINE,
2169     EL_DC_LANDMINE,
2170     EL_TRAP_ACTIVE,
2171     EL_SP_BUGGY_BASE_ACTIVE,
2172     EL_EMC_PLANT,
2173 #endif
2174
2175     -1
2176   };
2177
2178   static int ep_dont_collide_with[] =
2179   {
2180     /* same elements as in 'ep_dont_touch' */
2181     EL_BUG,
2182     EL_SPACESHIP,
2183     EL_BD_BUTTERFLY,
2184     EL_BD_FIREFLY,
2185
2186     /* new elements */
2187     EL_YAMYAM,
2188     EL_DARK_YAMYAM,
2189     EL_ROBOT,
2190     EL_PACMAN,
2191     EL_SP_SNIKSNAK,
2192     EL_SP_ELECTRON,
2193
2194     -1
2195   };
2196
2197   static int ep_dont_touch[] =
2198   {
2199     EL_BUG,
2200     EL_SPACESHIP,
2201     EL_BD_BUTTERFLY,
2202     EL_BD_FIREFLY,
2203
2204     -1
2205   };
2206
2207   static int ep_indestructible[] =
2208   {
2209     EL_STEELWALL,
2210     EL_ACID,
2211     EL_ACID_POOL_TOPLEFT,
2212     EL_ACID_POOL_TOPRIGHT,
2213     EL_ACID_POOL_BOTTOMLEFT,
2214     EL_ACID_POOL_BOTTOM,
2215     EL_ACID_POOL_BOTTOMRIGHT,
2216     EL_SP_HARDWARE_GRAY,
2217     EL_SP_HARDWARE_GREEN,
2218     EL_SP_HARDWARE_BLUE,
2219     EL_SP_HARDWARE_RED,
2220     EL_SP_HARDWARE_YELLOW,
2221     EL_SP_HARDWARE_BASE_1,
2222     EL_SP_HARDWARE_BASE_2,
2223     EL_SP_HARDWARE_BASE_3,
2224     EL_SP_HARDWARE_BASE_4,
2225     EL_SP_HARDWARE_BASE_5,
2226     EL_SP_HARDWARE_BASE_6,
2227     EL_INVISIBLE_STEELWALL,
2228     EL_INVISIBLE_STEELWALL_ACTIVE,
2229     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2230     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2231     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2232     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2233     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2234     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2235     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2236     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2237     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2238     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2239     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2240     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2241     EL_LIGHT_SWITCH,
2242     EL_LIGHT_SWITCH_ACTIVE,
2243     EL_SIGN_EXCLAMATION,
2244     EL_SIGN_RADIOACTIVITY,
2245     EL_SIGN_STOP,
2246     EL_SIGN_WHEELCHAIR,
2247     EL_SIGN_PARKING,
2248     EL_SIGN_NO_ENTRY,
2249     EL_SIGN_UNUSED_1,
2250     EL_SIGN_GIVE_WAY,
2251     EL_SIGN_ENTRY_FORBIDDEN,
2252     EL_SIGN_EMERGENCY_EXIT,
2253     EL_SIGN_YIN_YANG,
2254     EL_SIGN_UNUSED_2,
2255     EL_SIGN_SPERMS,
2256     EL_SIGN_BULLET,
2257     EL_SIGN_HEART,
2258     EL_SIGN_CROSS,
2259     EL_SIGN_FRANKIE,
2260     EL_STEEL_EXIT_CLOSED,
2261     EL_STEEL_EXIT_OPEN,
2262     EL_EM_STEEL_EXIT_CLOSED,
2263     EL_EM_STEEL_EXIT_OPEN,
2264     EL_DC_STEELWALL_1_LEFT,
2265     EL_DC_STEELWALL_1_RIGHT,
2266     EL_DC_STEELWALL_1_TOP,
2267     EL_DC_STEELWALL_1_BOTTOM,
2268     EL_DC_STEELWALL_1_HORIZONTAL,
2269     EL_DC_STEELWALL_1_VERTICAL,
2270     EL_DC_STEELWALL_1_TOPLEFT,
2271     EL_DC_STEELWALL_1_TOPRIGHT,
2272     EL_DC_STEELWALL_1_BOTTOMLEFT,
2273     EL_DC_STEELWALL_1_BOTTOMRIGHT,
2274     EL_DC_STEELWALL_1_TOPLEFT_2,
2275     EL_DC_STEELWALL_1_TOPRIGHT_2,
2276     EL_DC_STEELWALL_1_BOTTOMLEFT_2,
2277     EL_DC_STEELWALL_1_BOTTOMRIGHT_2,
2278     EL_DC_STEELWALL_2_LEFT,
2279     EL_DC_STEELWALL_2_RIGHT,
2280     EL_DC_STEELWALL_2_TOP,
2281     EL_DC_STEELWALL_2_BOTTOM,
2282     EL_DC_STEELWALL_2_HORIZONTAL,
2283     EL_DC_STEELWALL_2_VERTICAL,
2284     EL_DC_STEELWALL_2_MIDDLE,
2285     EL_DC_STEELWALL_2_SINGLE,
2286     EL_STEELWALL_SLIPPERY,
2287     EL_EMC_STEELWALL_1,
2288     EL_EMC_STEELWALL_2,
2289     EL_EMC_STEELWALL_3,
2290     EL_EMC_STEELWALL_4,
2291     EL_CRYSTAL,
2292     EL_GATE_1,
2293     EL_GATE_2,
2294     EL_GATE_3,
2295     EL_GATE_4,
2296     EL_GATE_1_GRAY,
2297     EL_GATE_2_GRAY,
2298     EL_GATE_3_GRAY,
2299     EL_GATE_4_GRAY,
2300     EL_GATE_1_GRAY_ACTIVE,
2301     EL_GATE_2_GRAY_ACTIVE,
2302     EL_GATE_3_GRAY_ACTIVE,
2303     EL_GATE_4_GRAY_ACTIVE,
2304     EL_EM_GATE_1,
2305     EL_EM_GATE_2,
2306     EL_EM_GATE_3,
2307     EL_EM_GATE_4,
2308     EL_EM_GATE_1_GRAY,
2309     EL_EM_GATE_2_GRAY,
2310     EL_EM_GATE_3_GRAY,
2311     EL_EM_GATE_4_GRAY,
2312     EL_EM_GATE_1_GRAY_ACTIVE,
2313     EL_EM_GATE_2_GRAY_ACTIVE,
2314     EL_EM_GATE_3_GRAY_ACTIVE,
2315     EL_EM_GATE_4_GRAY_ACTIVE,
2316     EL_EMC_GATE_5,
2317     EL_EMC_GATE_6,
2318     EL_EMC_GATE_7,
2319     EL_EMC_GATE_8,
2320     EL_EMC_GATE_5_GRAY,
2321     EL_EMC_GATE_6_GRAY,
2322     EL_EMC_GATE_7_GRAY,
2323     EL_EMC_GATE_8_GRAY,
2324     EL_EMC_GATE_5_GRAY_ACTIVE,
2325     EL_EMC_GATE_6_GRAY_ACTIVE,
2326     EL_EMC_GATE_7_GRAY_ACTIVE,
2327     EL_EMC_GATE_8_GRAY_ACTIVE,
2328     EL_DC_GATE_WHITE,
2329     EL_DC_GATE_WHITE_GRAY,
2330     EL_DC_GATE_WHITE_GRAY_ACTIVE,
2331     EL_DC_GATE_FAKE_GRAY,
2332     EL_SWITCHGATE_OPEN,
2333     EL_SWITCHGATE_OPENING,
2334     EL_SWITCHGATE_CLOSED,
2335     EL_SWITCHGATE_CLOSING,
2336 #if 1
2337     EL_DC_SWITCHGATE_SWITCH_UP,
2338     EL_DC_SWITCHGATE_SWITCH_DOWN,
2339 #endif
2340     EL_TIMEGATE_OPEN,
2341     EL_TIMEGATE_OPENING,
2342     EL_TIMEGATE_CLOSED,
2343     EL_TIMEGATE_CLOSING,
2344 #if 1
2345     EL_DC_TIMEGATE_SWITCH,
2346     EL_DC_TIMEGATE_SWITCH_ACTIVE,
2347 #endif
2348     EL_TUBE_ANY,
2349     EL_TUBE_VERTICAL,
2350     EL_TUBE_HORIZONTAL,
2351     EL_TUBE_VERTICAL_LEFT,
2352     EL_TUBE_VERTICAL_RIGHT,
2353     EL_TUBE_HORIZONTAL_UP,
2354     EL_TUBE_HORIZONTAL_DOWN,
2355     EL_TUBE_LEFT_UP,
2356     EL_TUBE_LEFT_DOWN,
2357     EL_TUBE_RIGHT_UP,
2358     EL_TUBE_RIGHT_DOWN,
2359     EL_EXPANDABLE_STEELWALL_HORIZONTAL,
2360     EL_EXPANDABLE_STEELWALL_VERTICAL,
2361     EL_EXPANDABLE_STEELWALL_ANY,
2362
2363     -1
2364   };
2365
2366   static int ep_slippery[] =
2367   {
2368     EL_WALL_SLIPPERY,
2369     EL_BD_WALL,
2370     EL_ROCK,
2371     EL_BD_ROCK,
2372     EL_EMERALD,
2373     EL_BD_DIAMOND,
2374     EL_EMERALD_YELLOW,
2375     EL_EMERALD_RED,
2376     EL_EMERALD_PURPLE,
2377     EL_DIAMOND,
2378     EL_BOMB,
2379     EL_NUT,
2380     EL_ROBOT_WHEEL_ACTIVE,
2381     EL_ROBOT_WHEEL,
2382     EL_TIME_ORB_FULL,
2383     EL_TIME_ORB_EMPTY,
2384     EL_LAMP_ACTIVE,
2385     EL_LAMP,
2386     EL_ACID_POOL_TOPLEFT,
2387     EL_ACID_POOL_TOPRIGHT,
2388     EL_SATELLITE,
2389     EL_SP_ZONK,
2390     EL_SP_INFOTRON,
2391     EL_SP_CHIP_SINGLE,
2392     EL_SP_CHIP_LEFT,
2393     EL_SP_CHIP_RIGHT,
2394     EL_SP_CHIP_TOP,
2395     EL_SP_CHIP_BOTTOM,
2396     EL_SPEED_PILL,
2397     EL_STEELWALL_SLIPPERY,
2398     EL_PEARL,
2399     EL_CRYSTAL,
2400     EL_EMC_WALL_SLIPPERY_1,
2401     EL_EMC_WALL_SLIPPERY_2,
2402     EL_EMC_WALL_SLIPPERY_3,
2403     EL_EMC_WALL_SLIPPERY_4,
2404     EL_EMC_MAGIC_BALL,
2405     EL_EMC_MAGIC_BALL_ACTIVE,
2406
2407     -1
2408   };
2409
2410   static int ep_can_change[] =
2411   {
2412     -1
2413   };
2414
2415   static int ep_can_move[] =
2416   {
2417     /* same elements as in 'pb_can_move_into_acid' */
2418     EL_BUG,
2419     EL_SPACESHIP,
2420     EL_BD_BUTTERFLY,
2421     EL_BD_FIREFLY,
2422     EL_YAMYAM,
2423     EL_DARK_YAMYAM,
2424     EL_ROBOT,
2425     EL_PACMAN,
2426     EL_MOLE,
2427     EL_PENGUIN,
2428     EL_PIG,
2429     EL_DRAGON,
2430     EL_SATELLITE,
2431     EL_SP_SNIKSNAK,
2432     EL_SP_ELECTRON,
2433     EL_BALLOON,
2434     EL_SPRING,
2435     EL_EMC_ANDROID,
2436
2437     -1
2438   };
2439
2440   static int ep_can_fall[] =
2441   {
2442     EL_ROCK,
2443     EL_BD_ROCK,
2444     EL_EMERALD,
2445     EL_BD_DIAMOND,
2446     EL_EMERALD_YELLOW,
2447     EL_EMERALD_RED,
2448     EL_EMERALD_PURPLE,
2449     EL_DIAMOND,
2450     EL_BOMB,
2451     EL_NUT,
2452     EL_AMOEBA_DROP,
2453     EL_QUICKSAND_FULL,
2454     EL_QUICKSAND_FAST_FULL,
2455     EL_MAGIC_WALL_FULL,
2456     EL_BD_MAGIC_WALL_FULL,
2457     EL_DC_MAGIC_WALL_FULL,
2458     EL_TIME_ORB_FULL,
2459     EL_TIME_ORB_EMPTY,
2460     EL_SP_ZONK,
2461     EL_SP_INFOTRON,
2462     EL_SP_DISK_ORANGE,
2463     EL_PEARL,
2464     EL_CRYSTAL,
2465     EL_SPRING,
2466     EL_DX_SUPABOMB,
2467
2468     -1
2469   };
2470
2471   static int ep_can_smash_player[] =
2472   {
2473     EL_ROCK,
2474     EL_BD_ROCK,
2475     EL_EMERALD,
2476     EL_BD_DIAMOND,
2477     EL_EMERALD_YELLOW,
2478     EL_EMERALD_RED,
2479     EL_EMERALD_PURPLE,
2480     EL_DIAMOND,
2481     EL_BOMB,
2482     EL_NUT,
2483     EL_AMOEBA_DROP,
2484     EL_TIME_ORB_FULL,
2485     EL_TIME_ORB_EMPTY,
2486     EL_SP_ZONK,
2487     EL_SP_INFOTRON,
2488     EL_SP_DISK_ORANGE,
2489     EL_PEARL,
2490     EL_CRYSTAL,
2491     EL_SPRING,
2492     EL_DX_SUPABOMB,
2493
2494     -1
2495   };
2496
2497   static int ep_can_smash_enemies[] =
2498   {
2499     EL_ROCK,
2500     EL_BD_ROCK,
2501     EL_SP_ZONK,
2502
2503     -1
2504   };
2505
2506   static int ep_can_smash_everything[] =
2507   {
2508     EL_ROCK,
2509     EL_BD_ROCK,
2510     EL_SP_ZONK,
2511
2512     -1
2513   };
2514
2515   static int ep_explodes_by_fire[] =
2516   {
2517     /* same elements as in 'ep_explodes_impact' */
2518     EL_BOMB,
2519     EL_SP_DISK_ORANGE,
2520     EL_DX_SUPABOMB,
2521
2522     /* same elements as in 'ep_explodes_smashed' */
2523     EL_SATELLITE,
2524     EL_PIG,
2525     EL_DRAGON,
2526     EL_MOLE,
2527
2528     /* new elements */
2529     EL_DYNAMITE,
2530     EL_DYNAMITE_ACTIVE,
2531     EL_EM_DYNAMITE,
2532     EL_EM_DYNAMITE_ACTIVE,
2533     EL_DYNABOMB_PLAYER_1_ACTIVE,
2534     EL_DYNABOMB_PLAYER_2_ACTIVE,
2535     EL_DYNABOMB_PLAYER_3_ACTIVE,
2536     EL_DYNABOMB_PLAYER_4_ACTIVE,
2537     EL_DYNABOMB_INCREASE_NUMBER,
2538     EL_DYNABOMB_INCREASE_SIZE,
2539     EL_DYNABOMB_INCREASE_POWER,
2540     EL_SP_DISK_RED_ACTIVE,
2541     EL_BUG,
2542     EL_PENGUIN,
2543     EL_SP_DISK_RED,
2544     EL_SP_DISK_YELLOW,
2545     EL_SP_SNIKSNAK,
2546     EL_SP_ELECTRON,
2547 #if 0
2548     EL_BLACK_ORB,
2549 #endif
2550
2551     -1
2552   };
2553
2554   static int ep_explodes_smashed[] =
2555   {
2556     /* same elements as in 'ep_explodes_impact' */
2557     EL_BOMB,
2558     EL_SP_DISK_ORANGE,
2559     EL_DX_SUPABOMB,
2560
2561     /* new elements */
2562     EL_SATELLITE,
2563     EL_PIG,
2564     EL_DRAGON,
2565     EL_MOLE,
2566
2567     -1
2568   };
2569
2570   static int ep_explodes_impact[] =
2571   {
2572     EL_BOMB,
2573     EL_SP_DISK_ORANGE,
2574     EL_DX_SUPABOMB,
2575
2576     -1
2577   };
2578
2579   static int ep_walkable_over[] =
2580   {
2581     EL_EMPTY_SPACE,
2582     EL_SP_EMPTY_SPACE,
2583     EL_SOKOBAN_FIELD_EMPTY,
2584     EL_EXIT_OPEN,
2585     EL_EM_EXIT_OPEN,
2586     EL_SP_EXIT_OPEN,
2587     EL_SP_EXIT_OPENING,
2588     EL_STEEL_EXIT_OPEN,
2589     EL_EM_STEEL_EXIT_OPEN,
2590     EL_GATE_1,
2591     EL_GATE_2,
2592     EL_GATE_3,
2593     EL_GATE_4,
2594     EL_GATE_1_GRAY,
2595     EL_GATE_2_GRAY,
2596     EL_GATE_3_GRAY,
2597     EL_GATE_4_GRAY,
2598     EL_GATE_1_GRAY_ACTIVE,
2599     EL_GATE_2_GRAY_ACTIVE,
2600     EL_GATE_3_GRAY_ACTIVE,
2601     EL_GATE_4_GRAY_ACTIVE,
2602     EL_PENGUIN,
2603     EL_PIG,
2604     EL_DRAGON,
2605
2606     -1
2607   };
2608
2609   static int ep_walkable_inside[] =
2610   {
2611     EL_TUBE_ANY,
2612     EL_TUBE_VERTICAL,
2613     EL_TUBE_HORIZONTAL,
2614     EL_TUBE_VERTICAL_LEFT,
2615     EL_TUBE_VERTICAL_RIGHT,
2616     EL_TUBE_HORIZONTAL_UP,
2617     EL_TUBE_HORIZONTAL_DOWN,
2618     EL_TUBE_LEFT_UP,
2619     EL_TUBE_LEFT_DOWN,
2620     EL_TUBE_RIGHT_UP,
2621     EL_TUBE_RIGHT_DOWN,
2622
2623     -1
2624   };
2625
2626   static int ep_walkable_under[] =
2627   {
2628     -1
2629   };
2630
2631   static int ep_passable_over[] =
2632   {
2633     EL_EM_GATE_1,
2634     EL_EM_GATE_2,
2635     EL_EM_GATE_3,
2636     EL_EM_GATE_4,
2637     EL_EM_GATE_1_GRAY,
2638     EL_EM_GATE_2_GRAY,
2639     EL_EM_GATE_3_GRAY,
2640     EL_EM_GATE_4_GRAY,
2641     EL_EM_GATE_1_GRAY_ACTIVE,
2642     EL_EM_GATE_2_GRAY_ACTIVE,
2643     EL_EM_GATE_3_GRAY_ACTIVE,
2644     EL_EM_GATE_4_GRAY_ACTIVE,
2645     EL_EMC_GATE_5,
2646     EL_EMC_GATE_6,
2647     EL_EMC_GATE_7,
2648     EL_EMC_GATE_8,
2649     EL_EMC_GATE_5_GRAY,
2650     EL_EMC_GATE_6_GRAY,
2651     EL_EMC_GATE_7_GRAY,
2652     EL_EMC_GATE_8_GRAY,
2653     EL_EMC_GATE_5_GRAY_ACTIVE,
2654     EL_EMC_GATE_6_GRAY_ACTIVE,
2655     EL_EMC_GATE_7_GRAY_ACTIVE,
2656     EL_EMC_GATE_8_GRAY_ACTIVE,
2657     EL_DC_GATE_WHITE,
2658     EL_DC_GATE_WHITE_GRAY,
2659     EL_DC_GATE_WHITE_GRAY_ACTIVE,
2660     EL_SWITCHGATE_OPEN,
2661     EL_TIMEGATE_OPEN,
2662
2663     -1
2664   };
2665
2666   static int ep_passable_inside[] =
2667   {
2668     EL_SP_PORT_LEFT,
2669     EL_SP_PORT_RIGHT,
2670     EL_SP_PORT_UP,
2671     EL_SP_PORT_DOWN,
2672     EL_SP_PORT_HORIZONTAL,
2673     EL_SP_PORT_VERTICAL,
2674     EL_SP_PORT_ANY,
2675     EL_SP_GRAVITY_PORT_LEFT,
2676     EL_SP_GRAVITY_PORT_RIGHT,
2677     EL_SP_GRAVITY_PORT_UP,
2678     EL_SP_GRAVITY_PORT_DOWN,
2679     EL_SP_GRAVITY_ON_PORT_LEFT,
2680     EL_SP_GRAVITY_ON_PORT_RIGHT,
2681     EL_SP_GRAVITY_ON_PORT_UP,
2682     EL_SP_GRAVITY_ON_PORT_DOWN,
2683     EL_SP_GRAVITY_OFF_PORT_LEFT,
2684     EL_SP_GRAVITY_OFF_PORT_RIGHT,
2685     EL_SP_GRAVITY_OFF_PORT_UP,
2686     EL_SP_GRAVITY_OFF_PORT_DOWN,
2687
2688     -1
2689   };
2690
2691   static int ep_passable_under[] =
2692   {
2693     -1
2694   };
2695
2696   static int ep_droppable[] =
2697   {
2698     -1
2699   };
2700
2701   static int ep_explodes_1x1_old[] =
2702   {
2703     -1
2704   };
2705
2706   static int ep_pushable[] =
2707   {
2708     EL_ROCK,
2709     EL_BOMB,
2710     EL_DX_SUPABOMB,
2711     EL_NUT,
2712     EL_TIME_ORB_EMPTY,
2713     EL_SP_ZONK,
2714     EL_SP_DISK_ORANGE,
2715     EL_SPRING,
2716     EL_BD_ROCK,
2717     EL_SOKOBAN_OBJECT,
2718     EL_SOKOBAN_FIELD_FULL,
2719     EL_SATELLITE,
2720     EL_SP_DISK_YELLOW,
2721     EL_BALLOON,
2722     EL_EMC_ANDROID,
2723
2724     -1
2725   };
2726
2727   static int ep_explodes_cross_old[] =
2728   {
2729     -1
2730   };
2731
2732   static int ep_protected[] =
2733   {
2734     /* same elements as in 'ep_walkable_inside' */
2735     EL_TUBE_ANY,
2736     EL_TUBE_VERTICAL,
2737     EL_TUBE_HORIZONTAL,
2738     EL_TUBE_VERTICAL_LEFT,
2739     EL_TUBE_VERTICAL_RIGHT,
2740     EL_TUBE_HORIZONTAL_UP,
2741     EL_TUBE_HORIZONTAL_DOWN,
2742     EL_TUBE_LEFT_UP,
2743     EL_TUBE_LEFT_DOWN,
2744     EL_TUBE_RIGHT_UP,
2745     EL_TUBE_RIGHT_DOWN,
2746
2747     /* same elements as in 'ep_passable_over' */
2748     EL_EM_GATE_1,
2749     EL_EM_GATE_2,
2750     EL_EM_GATE_3,
2751     EL_EM_GATE_4,
2752     EL_EM_GATE_1_GRAY,
2753     EL_EM_GATE_2_GRAY,
2754     EL_EM_GATE_3_GRAY,
2755     EL_EM_GATE_4_GRAY,
2756     EL_EM_GATE_1_GRAY_ACTIVE,
2757     EL_EM_GATE_2_GRAY_ACTIVE,
2758     EL_EM_GATE_3_GRAY_ACTIVE,
2759     EL_EM_GATE_4_GRAY_ACTIVE,
2760     EL_EMC_GATE_5,
2761     EL_EMC_GATE_6,
2762     EL_EMC_GATE_7,
2763     EL_EMC_GATE_8,
2764     EL_EMC_GATE_5_GRAY,
2765     EL_EMC_GATE_6_GRAY,
2766     EL_EMC_GATE_7_GRAY,
2767     EL_EMC_GATE_8_GRAY,
2768     EL_EMC_GATE_5_GRAY_ACTIVE,
2769     EL_EMC_GATE_6_GRAY_ACTIVE,
2770     EL_EMC_GATE_7_GRAY_ACTIVE,
2771     EL_EMC_GATE_8_GRAY_ACTIVE,
2772     EL_DC_GATE_WHITE,
2773     EL_DC_GATE_WHITE_GRAY,
2774     EL_DC_GATE_WHITE_GRAY_ACTIVE,
2775     EL_SWITCHGATE_OPEN,
2776     EL_TIMEGATE_OPEN,
2777
2778     /* same elements as in 'ep_passable_inside' */
2779     EL_SP_PORT_LEFT,
2780     EL_SP_PORT_RIGHT,
2781     EL_SP_PORT_UP,
2782     EL_SP_PORT_DOWN,
2783     EL_SP_PORT_HORIZONTAL,
2784     EL_SP_PORT_VERTICAL,
2785     EL_SP_PORT_ANY,
2786     EL_SP_GRAVITY_PORT_LEFT,
2787     EL_SP_GRAVITY_PORT_RIGHT,
2788     EL_SP_GRAVITY_PORT_UP,
2789     EL_SP_GRAVITY_PORT_DOWN,
2790     EL_SP_GRAVITY_ON_PORT_LEFT,
2791     EL_SP_GRAVITY_ON_PORT_RIGHT,
2792     EL_SP_GRAVITY_ON_PORT_UP,
2793     EL_SP_GRAVITY_ON_PORT_DOWN,
2794     EL_SP_GRAVITY_OFF_PORT_LEFT,
2795     EL_SP_GRAVITY_OFF_PORT_RIGHT,
2796     EL_SP_GRAVITY_OFF_PORT_UP,
2797     EL_SP_GRAVITY_OFF_PORT_DOWN,
2798
2799     -1
2800   };
2801
2802   static int ep_throwable[] =
2803   {
2804     -1
2805   };
2806
2807   static int ep_can_explode[] =
2808   {
2809     /* same elements as in 'ep_explodes_impact' */
2810     EL_BOMB,
2811     EL_SP_DISK_ORANGE,
2812     EL_DX_SUPABOMB,
2813
2814     /* same elements as in 'ep_explodes_smashed' */
2815     EL_SATELLITE,
2816     EL_PIG,
2817     EL_DRAGON,
2818     EL_MOLE,
2819
2820     /* elements that can explode by explosion or by dragonfire */
2821     EL_DYNAMITE,
2822     EL_DYNAMITE_ACTIVE,
2823     EL_EM_DYNAMITE,
2824     EL_EM_DYNAMITE_ACTIVE,
2825     EL_DYNABOMB_PLAYER_1_ACTIVE,
2826     EL_DYNABOMB_PLAYER_2_ACTIVE,
2827     EL_DYNABOMB_PLAYER_3_ACTIVE,
2828     EL_DYNABOMB_PLAYER_4_ACTIVE,
2829     EL_DYNABOMB_INCREASE_NUMBER,
2830     EL_DYNABOMB_INCREASE_SIZE,
2831     EL_DYNABOMB_INCREASE_POWER,
2832     EL_SP_DISK_RED_ACTIVE,
2833     EL_BUG,
2834     EL_PENGUIN,
2835     EL_SP_DISK_RED,
2836     EL_SP_DISK_YELLOW,
2837     EL_SP_SNIKSNAK,
2838     EL_SP_ELECTRON,
2839
2840     /* elements that can explode only by explosion */
2841     EL_BLACK_ORB,
2842
2843     -1
2844   };
2845
2846   static int ep_gravity_reachable[] =
2847   {
2848     EL_SAND,
2849     EL_SP_BASE,
2850     EL_TRAP,
2851     EL_INVISIBLE_SAND,
2852     EL_INVISIBLE_SAND_ACTIVE,
2853     EL_SP_PORT_LEFT,
2854     EL_SP_PORT_RIGHT,
2855     EL_SP_PORT_UP,
2856     EL_SP_PORT_DOWN,
2857     EL_SP_PORT_HORIZONTAL,
2858     EL_SP_PORT_VERTICAL,
2859     EL_SP_PORT_ANY,
2860     EL_SP_GRAVITY_PORT_LEFT,
2861     EL_SP_GRAVITY_PORT_RIGHT,
2862     EL_SP_GRAVITY_PORT_UP,
2863     EL_SP_GRAVITY_PORT_DOWN,
2864     EL_SP_GRAVITY_ON_PORT_LEFT,
2865     EL_SP_GRAVITY_ON_PORT_RIGHT,
2866     EL_SP_GRAVITY_ON_PORT_UP,
2867     EL_SP_GRAVITY_ON_PORT_DOWN,
2868     EL_SP_GRAVITY_OFF_PORT_LEFT,
2869     EL_SP_GRAVITY_OFF_PORT_RIGHT,
2870     EL_SP_GRAVITY_OFF_PORT_UP,
2871     EL_SP_GRAVITY_OFF_PORT_DOWN,
2872     EL_EMC_GRASS,
2873
2874     -1
2875   };
2876
2877   static int ep_player[] =
2878   {
2879     EL_PLAYER_1,
2880     EL_PLAYER_2,
2881     EL_PLAYER_3,
2882     EL_PLAYER_4,
2883     EL_SP_MURPHY,
2884     EL_SOKOBAN_FIELD_PLAYER,
2885     EL_TRIGGER_PLAYER,
2886
2887     -1
2888   };
2889
2890   static int ep_can_pass_magic_wall[] =
2891   {
2892     EL_ROCK,
2893     EL_BD_ROCK,
2894     EL_EMERALD,
2895     EL_BD_DIAMOND,
2896     EL_EMERALD_YELLOW,
2897     EL_EMERALD_RED,
2898     EL_EMERALD_PURPLE,
2899     EL_DIAMOND,
2900
2901     -1
2902   };
2903
2904   static int ep_can_pass_dc_magic_wall[] =
2905   {
2906     EL_ROCK,
2907     EL_BD_ROCK,
2908     EL_EMERALD,
2909     EL_BD_DIAMOND,
2910     EL_EMERALD_YELLOW,
2911     EL_EMERALD_RED,
2912     EL_EMERALD_PURPLE,
2913     EL_DIAMOND,
2914     EL_PEARL,
2915     EL_CRYSTAL,
2916
2917     -1
2918   };
2919
2920   static int ep_switchable[] =
2921   {
2922     EL_ROBOT_WHEEL,
2923     EL_SP_TERMINAL,
2924     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2925     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2926     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2927     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2928     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2929     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2930     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2931     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2932     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2933     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2934     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2935     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2936     EL_SWITCHGATE_SWITCH_UP,
2937     EL_SWITCHGATE_SWITCH_DOWN,
2938     EL_DC_SWITCHGATE_SWITCH_UP,
2939     EL_DC_SWITCHGATE_SWITCH_DOWN,
2940     EL_LIGHT_SWITCH,
2941     EL_LIGHT_SWITCH_ACTIVE,
2942     EL_TIMEGATE_SWITCH,
2943     EL_DC_TIMEGATE_SWITCH,
2944     EL_BALLOON_SWITCH_LEFT,
2945     EL_BALLOON_SWITCH_RIGHT,
2946     EL_BALLOON_SWITCH_UP,
2947     EL_BALLOON_SWITCH_DOWN,
2948     EL_BALLOON_SWITCH_ANY,
2949     EL_BALLOON_SWITCH_NONE,
2950     EL_LAMP,
2951     EL_TIME_ORB_FULL,
2952     EL_EMC_MAGIC_BALL_SWITCH,
2953     EL_EMC_MAGIC_BALL_SWITCH_ACTIVE,
2954
2955     -1
2956   };
2957
2958   static int ep_bd_element[] =
2959   {
2960     EL_EMPTY,
2961     EL_SAND,
2962     EL_WALL_SLIPPERY,
2963     EL_BD_WALL,
2964     EL_ROCK,
2965     EL_BD_ROCK,
2966     EL_BD_DIAMOND,
2967     EL_BD_MAGIC_WALL,
2968     EL_EXIT_CLOSED,
2969     EL_EXIT_OPEN,
2970     EL_STEELWALL,
2971     EL_PLAYER_1,
2972     EL_PLAYER_2,
2973     EL_PLAYER_3,
2974     EL_PLAYER_4,
2975     EL_BD_FIREFLY,
2976     EL_BD_FIREFLY_1,
2977     EL_BD_FIREFLY_2,
2978     EL_BD_FIREFLY_3,
2979     EL_BD_FIREFLY_4,
2980     EL_BD_BUTTERFLY,
2981     EL_BD_BUTTERFLY_1,
2982     EL_BD_BUTTERFLY_2,
2983     EL_BD_BUTTERFLY_3,
2984     EL_BD_BUTTERFLY_4,
2985     EL_BD_AMOEBA,
2986     EL_CHAR_QUESTION,
2987     EL_UNKNOWN,
2988
2989     -1
2990   };
2991
2992   static int ep_sp_element[] =
2993   {
2994     /* should always be valid */
2995     EL_EMPTY,
2996
2997     /* standard classic Supaplex elements */
2998     EL_SP_EMPTY,
2999     EL_SP_ZONK,
3000     EL_SP_BASE,
3001     EL_SP_MURPHY,
3002     EL_SP_INFOTRON,
3003     EL_SP_CHIP_SINGLE,
3004     EL_SP_HARDWARE_GRAY,
3005     EL_SP_EXIT_CLOSED,
3006     EL_SP_EXIT_OPEN,
3007     EL_SP_DISK_ORANGE,
3008     EL_SP_PORT_RIGHT,
3009     EL_SP_PORT_DOWN,
3010     EL_SP_PORT_LEFT,
3011     EL_SP_PORT_UP,
3012     EL_SP_GRAVITY_PORT_RIGHT,
3013     EL_SP_GRAVITY_PORT_DOWN,
3014     EL_SP_GRAVITY_PORT_LEFT,
3015     EL_SP_GRAVITY_PORT_UP,
3016     EL_SP_SNIKSNAK,
3017     EL_SP_DISK_YELLOW,
3018     EL_SP_TERMINAL,
3019     EL_SP_DISK_RED,
3020     EL_SP_PORT_VERTICAL,
3021     EL_SP_PORT_HORIZONTAL,
3022     EL_SP_PORT_ANY,
3023     EL_SP_ELECTRON,
3024     EL_SP_BUGGY_BASE,
3025     EL_SP_CHIP_LEFT,
3026     EL_SP_CHIP_RIGHT,
3027     EL_SP_HARDWARE_BASE_1,
3028     EL_SP_HARDWARE_GREEN,
3029     EL_SP_HARDWARE_BLUE,
3030     EL_SP_HARDWARE_RED,
3031     EL_SP_HARDWARE_YELLOW,
3032     EL_SP_HARDWARE_BASE_2,
3033     EL_SP_HARDWARE_BASE_3,
3034     EL_SP_HARDWARE_BASE_4,
3035     EL_SP_HARDWARE_BASE_5,
3036     EL_SP_HARDWARE_BASE_6,
3037     EL_SP_CHIP_TOP,
3038     EL_SP_CHIP_BOTTOM,
3039
3040     /* additional elements that appeared in newer Supaplex levels */
3041     EL_INVISIBLE_WALL,
3042
3043     /* additional gravity port elements (not switching, but setting gravity) */
3044     EL_SP_GRAVITY_ON_PORT_LEFT,
3045     EL_SP_GRAVITY_ON_PORT_RIGHT,
3046     EL_SP_GRAVITY_ON_PORT_UP,
3047     EL_SP_GRAVITY_ON_PORT_DOWN,
3048     EL_SP_GRAVITY_OFF_PORT_LEFT,
3049     EL_SP_GRAVITY_OFF_PORT_RIGHT,
3050     EL_SP_GRAVITY_OFF_PORT_UP,
3051     EL_SP_GRAVITY_OFF_PORT_DOWN,
3052
3053     /* more than one Murphy in a level results in an inactive clone */
3054     EL_SP_MURPHY_CLONE,
3055
3056     /* runtime Supaplex elements */
3057     EL_SP_DISK_RED_ACTIVE,
3058     EL_SP_TERMINAL_ACTIVE,
3059     EL_SP_BUGGY_BASE_ACTIVATING,
3060     EL_SP_BUGGY_BASE_ACTIVE,
3061     EL_SP_EXIT_OPENING,
3062     EL_SP_EXIT_CLOSING,
3063
3064     -1
3065   };
3066
3067   static int ep_sb_element[] =
3068   {
3069     EL_EMPTY,
3070     EL_STEELWALL,
3071     EL_SOKOBAN_OBJECT,
3072     EL_SOKOBAN_FIELD_EMPTY,
3073     EL_SOKOBAN_FIELD_FULL,
3074     EL_SOKOBAN_FIELD_PLAYER,
3075     EL_PLAYER_1,
3076     EL_PLAYER_2,
3077     EL_PLAYER_3,
3078     EL_PLAYER_4,
3079     EL_INVISIBLE_STEELWALL,
3080
3081     -1
3082   };
3083
3084   static int ep_gem[] =
3085   {
3086     EL_BD_DIAMOND,
3087     EL_EMERALD,
3088     EL_EMERALD_YELLOW,
3089     EL_EMERALD_RED,
3090     EL_EMERALD_PURPLE,
3091     EL_DIAMOND,
3092
3093     -1
3094   };
3095
3096   static int ep_food_dark_yamyam[] =
3097   {
3098     EL_SAND,
3099     EL_BUG,
3100     EL_SPACESHIP,
3101     EL_BD_BUTTERFLY,
3102     EL_BD_FIREFLY,
3103     EL_YAMYAM,
3104     EL_ROBOT,
3105     EL_PACMAN,
3106     EL_AMOEBA_DROP,
3107     EL_AMOEBA_DEAD,
3108     EL_AMOEBA_WET,
3109     EL_AMOEBA_DRY,
3110     EL_AMOEBA_FULL,
3111     EL_BD_AMOEBA,
3112     EL_EMERALD,
3113     EL_BD_DIAMOND,
3114     EL_EMERALD_YELLOW,
3115     EL_EMERALD_RED,
3116     EL_EMERALD_PURPLE,
3117     EL_DIAMOND,
3118     EL_PEARL,
3119     EL_CRYSTAL,
3120
3121     -1
3122   };
3123
3124   static int ep_food_penguin[] =
3125   {
3126     EL_EMERALD,
3127     EL_BD_DIAMOND,
3128     EL_EMERALD_YELLOW,
3129     EL_EMERALD_RED,
3130     EL_EMERALD_PURPLE,
3131     EL_DIAMOND,
3132     EL_PEARL,
3133     EL_CRYSTAL,
3134
3135     -1
3136   };
3137
3138   static int ep_food_pig[] =
3139   {
3140     EL_EMERALD,
3141     EL_BD_DIAMOND,
3142     EL_EMERALD_YELLOW,
3143     EL_EMERALD_RED,
3144     EL_EMERALD_PURPLE,
3145     EL_DIAMOND,
3146
3147     -1
3148   };
3149
3150   static int ep_historic_wall[] =
3151   {
3152     EL_STEELWALL,
3153     EL_GATE_1,
3154     EL_GATE_2,
3155     EL_GATE_3,
3156     EL_GATE_4,
3157     EL_GATE_1_GRAY,
3158     EL_GATE_2_GRAY,
3159     EL_GATE_3_GRAY,
3160     EL_GATE_4_GRAY,
3161     EL_GATE_1_GRAY_ACTIVE,
3162     EL_GATE_2_GRAY_ACTIVE,
3163     EL_GATE_3_GRAY_ACTIVE,
3164     EL_GATE_4_GRAY_ACTIVE,
3165     EL_EM_GATE_1,
3166     EL_EM_GATE_2,
3167     EL_EM_GATE_3,
3168     EL_EM_GATE_4,
3169     EL_EM_GATE_1_GRAY,
3170     EL_EM_GATE_2_GRAY,
3171     EL_EM_GATE_3_GRAY,
3172     EL_EM_GATE_4_GRAY,
3173     EL_EM_GATE_1_GRAY_ACTIVE,
3174     EL_EM_GATE_2_GRAY_ACTIVE,
3175     EL_EM_GATE_3_GRAY_ACTIVE,
3176     EL_EM_GATE_4_GRAY_ACTIVE,
3177     EL_EXIT_CLOSED,
3178     EL_EXIT_OPENING,
3179     EL_EXIT_OPEN,
3180     EL_WALL,
3181     EL_WALL_SLIPPERY,
3182     EL_EXPANDABLE_WALL,
3183     EL_EXPANDABLE_WALL_HORIZONTAL,
3184     EL_EXPANDABLE_WALL_VERTICAL,
3185     EL_EXPANDABLE_WALL_ANY,
3186     EL_EXPANDABLE_WALL_GROWING,
3187     EL_BD_EXPANDABLE_WALL,
3188     EL_BD_WALL,
3189     EL_SP_CHIP_SINGLE,
3190     EL_SP_CHIP_LEFT,
3191     EL_SP_CHIP_RIGHT,
3192     EL_SP_CHIP_TOP,
3193     EL_SP_CHIP_BOTTOM,
3194     EL_SP_HARDWARE_GRAY,
3195     EL_SP_HARDWARE_GREEN,
3196     EL_SP_HARDWARE_BLUE,
3197     EL_SP_HARDWARE_RED,
3198     EL_SP_HARDWARE_YELLOW,
3199     EL_SP_HARDWARE_BASE_1,
3200     EL_SP_HARDWARE_BASE_2,
3201     EL_SP_HARDWARE_BASE_3,
3202     EL_SP_HARDWARE_BASE_4,
3203     EL_SP_HARDWARE_BASE_5,
3204     EL_SP_HARDWARE_BASE_6,
3205     EL_SP_TERMINAL,
3206     EL_SP_TERMINAL_ACTIVE,
3207     EL_SP_EXIT_CLOSED,
3208     EL_SP_EXIT_OPEN,
3209     EL_INVISIBLE_STEELWALL,
3210     EL_INVISIBLE_STEELWALL_ACTIVE,
3211     EL_INVISIBLE_WALL,
3212     EL_INVISIBLE_WALL_ACTIVE,
3213     EL_STEELWALL_SLIPPERY,
3214     EL_EMC_STEELWALL_1,
3215     EL_EMC_STEELWALL_2,
3216     EL_EMC_STEELWALL_3,
3217     EL_EMC_STEELWALL_4,
3218     EL_EMC_WALL_1,
3219     EL_EMC_WALL_2,
3220     EL_EMC_WALL_3,
3221     EL_EMC_WALL_4,
3222     EL_EMC_WALL_5,
3223     EL_EMC_WALL_6,
3224     EL_EMC_WALL_7,
3225     EL_EMC_WALL_8,
3226
3227     -1
3228   };
3229
3230   static int ep_historic_solid[] =
3231   {
3232     EL_WALL,
3233     EL_EXPANDABLE_WALL,
3234     EL_EXPANDABLE_WALL_HORIZONTAL,
3235     EL_EXPANDABLE_WALL_VERTICAL,
3236     EL_EXPANDABLE_WALL_ANY,
3237     EL_BD_EXPANDABLE_WALL,
3238     EL_BD_WALL,
3239     EL_WALL_SLIPPERY,
3240     EL_EXIT_CLOSED,
3241     EL_EXIT_OPENING,
3242     EL_EXIT_OPEN,
3243     EL_AMOEBA_DEAD,
3244     EL_AMOEBA_WET,
3245     EL_AMOEBA_DRY,
3246     EL_AMOEBA_FULL,
3247     EL_BD_AMOEBA,
3248     EL_QUICKSAND_EMPTY,
3249     EL_QUICKSAND_FULL,
3250     EL_QUICKSAND_FILLING,
3251     EL_QUICKSAND_EMPTYING,
3252     EL_MAGIC_WALL,
3253     EL_MAGIC_WALL_ACTIVE,
3254     EL_MAGIC_WALL_EMPTYING,
3255     EL_MAGIC_WALL_FILLING,
3256     EL_MAGIC_WALL_FULL,
3257     EL_MAGIC_WALL_DEAD,
3258     EL_BD_MAGIC_WALL,
3259     EL_BD_MAGIC_WALL_ACTIVE,
3260     EL_BD_MAGIC_WALL_EMPTYING,
3261     EL_BD_MAGIC_WALL_FULL,
3262     EL_BD_MAGIC_WALL_FILLING,
3263     EL_BD_MAGIC_WALL_DEAD,
3264     EL_GAME_OF_LIFE,
3265     EL_BIOMAZE,
3266     EL_SP_CHIP_SINGLE,
3267     EL_SP_CHIP_LEFT,
3268     EL_SP_CHIP_RIGHT,
3269     EL_SP_CHIP_TOP,
3270     EL_SP_CHIP_BOTTOM,
3271     EL_SP_TERMINAL,
3272     EL_SP_TERMINAL_ACTIVE,
3273     EL_SP_EXIT_CLOSED,
3274     EL_SP_EXIT_OPEN,
3275     EL_INVISIBLE_WALL,
3276     EL_INVISIBLE_WALL_ACTIVE,
3277     EL_SWITCHGATE_SWITCH_UP,
3278     EL_SWITCHGATE_SWITCH_DOWN,
3279     EL_DC_SWITCHGATE_SWITCH_UP,
3280     EL_DC_SWITCHGATE_SWITCH_DOWN,
3281     EL_TIMEGATE_SWITCH,
3282     EL_TIMEGATE_SWITCH_ACTIVE,
3283     EL_DC_TIMEGATE_SWITCH,
3284     EL_DC_TIMEGATE_SWITCH_ACTIVE,
3285     EL_EMC_WALL_1,
3286     EL_EMC_WALL_2,
3287     EL_EMC_WALL_3,
3288     EL_EMC_WALL_4,
3289     EL_EMC_WALL_5,
3290     EL_EMC_WALL_6,
3291     EL_EMC_WALL_7,
3292     EL_EMC_WALL_8,
3293     EL_WALL_PEARL,
3294     EL_WALL_CRYSTAL,
3295
3296     /* the following elements are a direct copy of "indestructible" elements,
3297        except "EL_ACID", which is "indestructible", but not "solid"! */
3298 #if 0
3299     EL_ACID,
3300 #endif
3301     EL_STEELWALL,
3302     EL_ACID_POOL_TOPLEFT,
3303     EL_ACID_POOL_TOPRIGHT,
3304     EL_ACID_POOL_BOTTOMLEFT,
3305     EL_ACID_POOL_BOTTOM,
3306     EL_ACID_POOL_BOTTOMRIGHT,
3307     EL_SP_HARDWARE_GRAY,
3308     EL_SP_HARDWARE_GREEN,
3309     EL_SP_HARDWARE_BLUE,
3310     EL_SP_HARDWARE_RED,
3311     EL_SP_HARDWARE_YELLOW,
3312     EL_SP_HARDWARE_BASE_1,
3313     EL_SP_HARDWARE_BASE_2,
3314     EL_SP_HARDWARE_BASE_3,
3315     EL_SP_HARDWARE_BASE_4,
3316     EL_SP_HARDWARE_BASE_5,
3317     EL_SP_HARDWARE_BASE_6,
3318     EL_INVISIBLE_STEELWALL,
3319     EL_INVISIBLE_STEELWALL_ACTIVE,
3320     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3321     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3322     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3323     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3324     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3325     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3326     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3327     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3328     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3329     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3330     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3331     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3332     EL_LIGHT_SWITCH,
3333     EL_LIGHT_SWITCH_ACTIVE,
3334     EL_SIGN_EXCLAMATION,
3335     EL_SIGN_RADIOACTIVITY,
3336     EL_SIGN_STOP,
3337     EL_SIGN_WHEELCHAIR,
3338     EL_SIGN_PARKING,
3339     EL_SIGN_NO_ENTRY,
3340     EL_SIGN_UNUSED_1,
3341     EL_SIGN_GIVE_WAY,
3342     EL_SIGN_ENTRY_FORBIDDEN,
3343     EL_SIGN_EMERGENCY_EXIT,
3344     EL_SIGN_YIN_YANG,
3345     EL_SIGN_UNUSED_2,
3346     EL_SIGN_SPERMS,
3347     EL_SIGN_BULLET,
3348     EL_SIGN_HEART,
3349     EL_SIGN_CROSS,
3350     EL_SIGN_FRANKIE,
3351     EL_STEEL_EXIT_CLOSED,
3352     EL_STEEL_EXIT_OPEN,
3353     EL_DC_STEELWALL_1_LEFT,
3354     EL_DC_STEELWALL_1_RIGHT,
3355     EL_DC_STEELWALL_1_TOP,
3356     EL_DC_STEELWALL_1_BOTTOM,
3357     EL_DC_STEELWALL_1_HORIZONTAL,
3358     EL_DC_STEELWALL_1_VERTICAL,
3359     EL_DC_STEELWALL_1_TOPLEFT,
3360     EL_DC_STEELWALL_1_TOPRIGHT,
3361     EL_DC_STEELWALL_1_BOTTOMLEFT,
3362     EL_DC_STEELWALL_1_BOTTOMRIGHT,
3363     EL_DC_STEELWALL_1_TOPLEFT_2,
3364     EL_DC_STEELWALL_1_TOPRIGHT_2,
3365     EL_DC_STEELWALL_1_BOTTOMLEFT_2,
3366     EL_DC_STEELWALL_1_BOTTOMRIGHT_2,
3367     EL_DC_STEELWALL_2_LEFT,
3368     EL_DC_STEELWALL_2_RIGHT,
3369     EL_DC_STEELWALL_2_TOP,
3370     EL_DC_STEELWALL_2_BOTTOM,
3371     EL_DC_STEELWALL_2_HORIZONTAL,
3372     EL_DC_STEELWALL_2_VERTICAL,
3373     EL_DC_STEELWALL_2_MIDDLE,
3374     EL_DC_STEELWALL_2_SINGLE,
3375     EL_STEELWALL_SLIPPERY,
3376     EL_EMC_STEELWALL_1,
3377     EL_EMC_STEELWALL_2,
3378     EL_EMC_STEELWALL_3,
3379     EL_EMC_STEELWALL_4,
3380     EL_CRYSTAL,
3381     EL_GATE_1,
3382     EL_GATE_2,
3383     EL_GATE_3,
3384     EL_GATE_4,
3385     EL_GATE_1_GRAY,
3386     EL_GATE_2_GRAY,
3387     EL_GATE_3_GRAY,
3388     EL_GATE_4_GRAY,
3389     EL_GATE_1_GRAY_ACTIVE,
3390     EL_GATE_2_GRAY_ACTIVE,
3391     EL_GATE_3_GRAY_ACTIVE,
3392     EL_GATE_4_GRAY_ACTIVE,
3393     EL_EM_GATE_1,
3394     EL_EM_GATE_2,
3395     EL_EM_GATE_3,
3396     EL_EM_GATE_4,
3397     EL_EM_GATE_1_GRAY,
3398     EL_EM_GATE_2_GRAY,
3399     EL_EM_GATE_3_GRAY,
3400     EL_EM_GATE_4_GRAY,
3401     EL_EM_GATE_1_GRAY_ACTIVE,
3402     EL_EM_GATE_2_GRAY_ACTIVE,
3403     EL_EM_GATE_3_GRAY_ACTIVE,
3404     EL_EM_GATE_4_GRAY_ACTIVE,
3405     EL_SWITCHGATE_OPEN,
3406     EL_SWITCHGATE_OPENING,
3407     EL_SWITCHGATE_CLOSED,
3408     EL_SWITCHGATE_CLOSING,
3409     EL_TIMEGATE_OPEN,
3410     EL_TIMEGATE_OPENING,
3411     EL_TIMEGATE_CLOSED,
3412     EL_TIMEGATE_CLOSING,
3413     EL_TUBE_ANY,
3414     EL_TUBE_VERTICAL,
3415     EL_TUBE_HORIZONTAL,
3416     EL_TUBE_VERTICAL_LEFT,
3417     EL_TUBE_VERTICAL_RIGHT,
3418     EL_TUBE_HORIZONTAL_UP,
3419     EL_TUBE_HORIZONTAL_DOWN,
3420     EL_TUBE_LEFT_UP,
3421     EL_TUBE_LEFT_DOWN,
3422     EL_TUBE_RIGHT_UP,
3423     EL_TUBE_RIGHT_DOWN,
3424
3425     -1
3426   };
3427
3428   static int ep_classic_enemy[] =
3429   {
3430     EL_BUG,
3431     EL_SPACESHIP,
3432     EL_BD_BUTTERFLY,
3433     EL_BD_FIREFLY,
3434
3435     EL_YAMYAM,
3436     EL_DARK_YAMYAM,
3437     EL_ROBOT,
3438     EL_PACMAN,
3439     EL_SP_SNIKSNAK,
3440     EL_SP_ELECTRON,
3441
3442     -1
3443   };
3444
3445   static int ep_belt[] =
3446   {
3447     EL_CONVEYOR_BELT_1_LEFT,
3448     EL_CONVEYOR_BELT_1_MIDDLE,
3449     EL_CONVEYOR_BELT_1_RIGHT,
3450     EL_CONVEYOR_BELT_2_LEFT,
3451     EL_CONVEYOR_BELT_2_MIDDLE,
3452     EL_CONVEYOR_BELT_2_RIGHT,
3453     EL_CONVEYOR_BELT_3_LEFT,
3454     EL_CONVEYOR_BELT_3_MIDDLE,
3455     EL_CONVEYOR_BELT_3_RIGHT,
3456     EL_CONVEYOR_BELT_4_LEFT,
3457     EL_CONVEYOR_BELT_4_MIDDLE,
3458     EL_CONVEYOR_BELT_4_RIGHT,
3459
3460     -1
3461   };
3462
3463   static int ep_belt_active[] =
3464   {
3465     EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
3466     EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE,
3467     EL_CONVEYOR_BELT_1_RIGHT_ACTIVE,
3468     EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
3469     EL_CONVEYOR_BELT_2_MIDDLE_ACTIVE,
3470     EL_CONVEYOR_BELT_2_RIGHT_ACTIVE,
3471     EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
3472     EL_CONVEYOR_BELT_3_MIDDLE_ACTIVE,
3473     EL_CONVEYOR_BELT_3_RIGHT_ACTIVE,
3474     EL_CONVEYOR_BELT_4_LEFT_ACTIVE,
3475     EL_CONVEYOR_BELT_4_MIDDLE_ACTIVE,
3476     EL_CONVEYOR_BELT_4_RIGHT_ACTIVE,
3477
3478     -1
3479   };
3480
3481   static int ep_belt_switch[] =
3482   {
3483     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3484     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3485     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3486     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3487     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3488     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3489     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3490     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3491     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3492     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3493     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3494     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3495
3496     -1
3497   };
3498
3499   static int ep_tube[] =
3500   {
3501     EL_TUBE_LEFT_UP,
3502     EL_TUBE_LEFT_DOWN,
3503     EL_TUBE_RIGHT_UP,
3504     EL_TUBE_RIGHT_DOWN,
3505     EL_TUBE_HORIZONTAL,
3506     EL_TUBE_HORIZONTAL_UP,
3507     EL_TUBE_HORIZONTAL_DOWN,
3508     EL_TUBE_VERTICAL,
3509     EL_TUBE_VERTICAL_LEFT,
3510     EL_TUBE_VERTICAL_RIGHT,
3511     EL_TUBE_ANY,
3512
3513     -1
3514   };
3515
3516   static int ep_acid_pool[] =
3517   {
3518     EL_ACID_POOL_TOPLEFT,
3519     EL_ACID_POOL_TOPRIGHT,
3520     EL_ACID_POOL_BOTTOMLEFT,
3521     EL_ACID_POOL_BOTTOM,
3522     EL_ACID_POOL_BOTTOMRIGHT,
3523
3524     -1
3525   };
3526
3527   static int ep_keygate[] =
3528   {
3529     EL_GATE_1,
3530     EL_GATE_2,
3531     EL_GATE_3,
3532     EL_GATE_4,
3533     EL_GATE_1_GRAY,
3534     EL_GATE_2_GRAY,
3535     EL_GATE_3_GRAY,
3536     EL_GATE_4_GRAY,
3537     EL_GATE_1_GRAY_ACTIVE,
3538     EL_GATE_2_GRAY_ACTIVE,
3539     EL_GATE_3_GRAY_ACTIVE,
3540     EL_GATE_4_GRAY_ACTIVE,
3541     EL_EM_GATE_1,
3542     EL_EM_GATE_2,
3543     EL_EM_GATE_3,
3544     EL_EM_GATE_4,
3545     EL_EM_GATE_1_GRAY,
3546     EL_EM_GATE_2_GRAY,
3547     EL_EM_GATE_3_GRAY,
3548     EL_EM_GATE_4_GRAY,
3549     EL_EM_GATE_1_GRAY_ACTIVE,
3550     EL_EM_GATE_2_GRAY_ACTIVE,
3551     EL_EM_GATE_3_GRAY_ACTIVE,
3552     EL_EM_GATE_4_GRAY_ACTIVE,
3553     EL_EMC_GATE_5,
3554     EL_EMC_GATE_6,
3555     EL_EMC_GATE_7,
3556     EL_EMC_GATE_8,
3557     EL_EMC_GATE_5_GRAY,
3558     EL_EMC_GATE_6_GRAY,
3559     EL_EMC_GATE_7_GRAY,
3560     EL_EMC_GATE_8_GRAY,
3561     EL_EMC_GATE_5_GRAY_ACTIVE,
3562     EL_EMC_GATE_6_GRAY_ACTIVE,
3563     EL_EMC_GATE_7_GRAY_ACTIVE,
3564     EL_EMC_GATE_8_GRAY_ACTIVE,
3565     EL_DC_GATE_WHITE,
3566     EL_DC_GATE_WHITE_GRAY,
3567     EL_DC_GATE_WHITE_GRAY_ACTIVE,
3568
3569     -1
3570   };
3571
3572   static int ep_amoeboid[] =
3573   {
3574     EL_AMOEBA_DEAD,
3575     EL_AMOEBA_WET,
3576     EL_AMOEBA_DRY,
3577     EL_AMOEBA_FULL,
3578     EL_BD_AMOEBA,
3579     EL_EMC_DRIPPER,
3580
3581     -1
3582   };
3583
3584   static int ep_amoebalive[] =
3585   {
3586     EL_AMOEBA_WET,
3587     EL_AMOEBA_DRY,
3588     EL_AMOEBA_FULL,
3589     EL_BD_AMOEBA,
3590     EL_EMC_DRIPPER,
3591
3592     -1
3593   };
3594
3595   static int ep_has_editor_content[] =
3596   {
3597     EL_PLAYER_1,
3598     EL_PLAYER_2,
3599     EL_PLAYER_3,
3600     EL_PLAYER_4,
3601     EL_SP_MURPHY,
3602     EL_YAMYAM,
3603     EL_YAMYAM_LEFT,
3604     EL_YAMYAM_RIGHT,
3605     EL_YAMYAM_UP,
3606     EL_YAMYAM_DOWN,
3607     EL_AMOEBA_WET,
3608     EL_AMOEBA_DRY,
3609     EL_AMOEBA_FULL,
3610     EL_BD_AMOEBA,
3611     EL_EMC_MAGIC_BALL,
3612     EL_EMC_ANDROID,
3613
3614     -1
3615   };
3616
3617   static int ep_can_turn_each_move[] =
3618   {
3619     /* !!! do something with this one !!! */
3620     -1
3621   };
3622
3623   static int ep_can_grow[] =
3624   {
3625     EL_BD_AMOEBA,
3626     EL_AMOEBA_DROP,
3627     EL_AMOEBA_WET,
3628     EL_AMOEBA_DRY,
3629     EL_AMOEBA_FULL,
3630     EL_GAME_OF_LIFE,
3631     EL_BIOMAZE,
3632     EL_EMC_DRIPPER,
3633
3634     -1
3635   };
3636
3637   static int ep_active_bomb[] =
3638   {
3639     EL_DYNAMITE_ACTIVE,
3640     EL_EM_DYNAMITE_ACTIVE,
3641     EL_DYNABOMB_PLAYER_1_ACTIVE,
3642     EL_DYNABOMB_PLAYER_2_ACTIVE,
3643     EL_DYNABOMB_PLAYER_3_ACTIVE,
3644     EL_DYNABOMB_PLAYER_4_ACTIVE,
3645     EL_SP_DISK_RED_ACTIVE,
3646
3647     -1
3648   };
3649
3650   static int ep_inactive[] =
3651   {
3652     EL_EMPTY,
3653     EL_SAND,
3654     EL_WALL,
3655     EL_BD_WALL,
3656     EL_WALL_SLIPPERY,
3657     EL_STEELWALL,
3658     EL_AMOEBA_DEAD,
3659     EL_QUICKSAND_EMPTY,
3660     EL_QUICKSAND_FAST_EMPTY,
3661     EL_STONEBLOCK,
3662     EL_ROBOT_WHEEL,
3663     EL_KEY_1,
3664     EL_KEY_2,
3665     EL_KEY_3,
3666     EL_KEY_4,
3667     EL_EM_KEY_1,
3668     EL_EM_KEY_2,
3669     EL_EM_KEY_3,
3670     EL_EM_KEY_4,
3671     EL_EMC_KEY_5,
3672     EL_EMC_KEY_6,
3673     EL_EMC_KEY_7,
3674     EL_EMC_KEY_8,
3675     EL_GATE_1,
3676     EL_GATE_2,
3677     EL_GATE_3,
3678     EL_GATE_4,
3679     EL_GATE_1_GRAY,
3680     EL_GATE_2_GRAY,
3681     EL_GATE_3_GRAY,
3682     EL_GATE_4_GRAY,
3683     EL_GATE_1_GRAY_ACTIVE,
3684     EL_GATE_2_GRAY_ACTIVE,
3685     EL_GATE_3_GRAY_ACTIVE,
3686     EL_GATE_4_GRAY_ACTIVE,
3687     EL_EM_GATE_1,
3688     EL_EM_GATE_2,
3689     EL_EM_GATE_3,
3690     EL_EM_GATE_4,
3691     EL_EM_GATE_1_GRAY,
3692     EL_EM_GATE_2_GRAY,
3693     EL_EM_GATE_3_GRAY,
3694     EL_EM_GATE_4_GRAY,
3695     EL_EM_GATE_1_GRAY_ACTIVE,
3696     EL_EM_GATE_2_GRAY_ACTIVE,
3697     EL_EM_GATE_3_GRAY_ACTIVE,
3698     EL_EM_GATE_4_GRAY_ACTIVE,
3699     EL_EMC_GATE_5,
3700     EL_EMC_GATE_6,
3701     EL_EMC_GATE_7,
3702     EL_EMC_GATE_8,
3703     EL_EMC_GATE_5_GRAY,
3704     EL_EMC_GATE_6_GRAY,
3705     EL_EMC_GATE_7_GRAY,
3706     EL_EMC_GATE_8_GRAY,
3707     EL_EMC_GATE_5_GRAY_ACTIVE,
3708     EL_EMC_GATE_6_GRAY_ACTIVE,
3709     EL_EMC_GATE_7_GRAY_ACTIVE,
3710     EL_EMC_GATE_8_GRAY_ACTIVE,
3711     EL_DC_GATE_WHITE,
3712     EL_DC_GATE_WHITE_GRAY,
3713     EL_DC_GATE_WHITE_GRAY_ACTIVE,
3714     EL_DC_GATE_FAKE_GRAY,
3715     EL_DYNAMITE,
3716     EL_EM_DYNAMITE,
3717     EL_INVISIBLE_STEELWALL,
3718     EL_INVISIBLE_WALL,
3719     EL_INVISIBLE_SAND,
3720     EL_LAMP,
3721     EL_LAMP_ACTIVE,
3722     EL_WALL_EMERALD,
3723     EL_WALL_DIAMOND,
3724     EL_WALL_BD_DIAMOND,
3725     EL_WALL_EMERALD_YELLOW,
3726     EL_DYNABOMB_INCREASE_NUMBER,
3727     EL_DYNABOMB_INCREASE_SIZE,
3728     EL_DYNABOMB_INCREASE_POWER,
3729 #if 0
3730     EL_SOKOBAN_OBJECT,
3731 #endif
3732     EL_SOKOBAN_FIELD_EMPTY,
3733     EL_SOKOBAN_FIELD_FULL,
3734     EL_WALL_EMERALD_RED,
3735     EL_WALL_EMERALD_PURPLE,
3736     EL_ACID_POOL_TOPLEFT,
3737     EL_ACID_POOL_TOPRIGHT,
3738     EL_ACID_POOL_BOTTOMLEFT,
3739     EL_ACID_POOL_BOTTOM,
3740     EL_ACID_POOL_BOTTOMRIGHT,
3741     EL_MAGIC_WALL,
3742     EL_MAGIC_WALL_DEAD,
3743     EL_BD_MAGIC_WALL,
3744     EL_BD_MAGIC_WALL_DEAD,
3745     EL_DC_MAGIC_WALL,
3746     EL_DC_MAGIC_WALL_DEAD,
3747     EL_AMOEBA_TO_DIAMOND,
3748     EL_BLOCKED,
3749     EL_SP_EMPTY,
3750     EL_SP_BASE,
3751     EL_SP_PORT_RIGHT,
3752     EL_SP_PORT_DOWN,
3753     EL_SP_PORT_LEFT,
3754     EL_SP_PORT_UP,
3755     EL_SP_GRAVITY_PORT_RIGHT,
3756     EL_SP_GRAVITY_PORT_DOWN,
3757     EL_SP_GRAVITY_PORT_LEFT,
3758     EL_SP_GRAVITY_PORT_UP,
3759     EL_SP_PORT_HORIZONTAL,
3760     EL_SP_PORT_VERTICAL,
3761     EL_SP_PORT_ANY,
3762     EL_SP_DISK_RED,
3763 #if 0
3764     EL_SP_DISK_YELLOW,
3765 #endif
3766     EL_SP_CHIP_SINGLE,
3767     EL_SP_CHIP_LEFT,
3768     EL_SP_CHIP_RIGHT,
3769     EL_SP_CHIP_TOP,
3770     EL_SP_CHIP_BOTTOM,
3771     EL_SP_HARDWARE_GRAY,
3772     EL_SP_HARDWARE_GREEN,
3773     EL_SP_HARDWARE_BLUE,
3774     EL_SP_HARDWARE_RED,
3775     EL_SP_HARDWARE_YELLOW,
3776     EL_SP_HARDWARE_BASE_1,
3777     EL_SP_HARDWARE_BASE_2,
3778     EL_SP_HARDWARE_BASE_3,
3779     EL_SP_HARDWARE_BASE_4,
3780     EL_SP_HARDWARE_BASE_5,
3781     EL_SP_HARDWARE_BASE_6,
3782     EL_SP_GRAVITY_ON_PORT_LEFT,
3783     EL_SP_GRAVITY_ON_PORT_RIGHT,
3784     EL_SP_GRAVITY_ON_PORT_UP,
3785     EL_SP_GRAVITY_ON_PORT_DOWN,
3786     EL_SP_GRAVITY_OFF_PORT_LEFT,
3787     EL_SP_GRAVITY_OFF_PORT_RIGHT,
3788     EL_SP_GRAVITY_OFF_PORT_UP,
3789     EL_SP_GRAVITY_OFF_PORT_DOWN,
3790     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3791     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3792     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3793     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3794     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3795     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3796     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3797     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3798     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3799     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3800     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3801     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3802     EL_SIGN_EXCLAMATION,
3803     EL_SIGN_RADIOACTIVITY,
3804     EL_SIGN_STOP,
3805     EL_SIGN_WHEELCHAIR,
3806     EL_SIGN_PARKING,
3807     EL_SIGN_NO_ENTRY,
3808     EL_SIGN_UNUSED_1,
3809     EL_SIGN_GIVE_WAY,
3810     EL_SIGN_ENTRY_FORBIDDEN,
3811     EL_SIGN_EMERGENCY_EXIT,
3812     EL_SIGN_YIN_YANG,
3813     EL_SIGN_UNUSED_2,
3814     EL_SIGN_SPERMS,
3815     EL_SIGN_BULLET,
3816     EL_SIGN_HEART,
3817     EL_SIGN_CROSS,
3818     EL_SIGN_FRANKIE,
3819     EL_DC_STEELWALL_1_LEFT,
3820     EL_DC_STEELWALL_1_RIGHT,
3821     EL_DC_STEELWALL_1_TOP,
3822     EL_DC_STEELWALL_1_BOTTOM,
3823     EL_DC_STEELWALL_1_HORIZONTAL,
3824     EL_DC_STEELWALL_1_VERTICAL,
3825     EL_DC_STEELWALL_1_TOPLEFT,
3826     EL_DC_STEELWALL_1_TOPRIGHT,
3827     EL_DC_STEELWALL_1_BOTTOMLEFT,
3828     EL_DC_STEELWALL_1_BOTTOMRIGHT,
3829     EL_DC_STEELWALL_1_TOPLEFT_2,
3830     EL_DC_STEELWALL_1_TOPRIGHT_2,
3831     EL_DC_STEELWALL_1_BOTTOMLEFT_2,
3832     EL_DC_STEELWALL_1_BOTTOMRIGHT_2,
3833     EL_DC_STEELWALL_2_LEFT,
3834     EL_DC_STEELWALL_2_RIGHT,
3835     EL_DC_STEELWALL_2_TOP,
3836     EL_DC_STEELWALL_2_BOTTOM,
3837     EL_DC_STEELWALL_2_HORIZONTAL,
3838     EL_DC_STEELWALL_2_VERTICAL,
3839     EL_DC_STEELWALL_2_MIDDLE,
3840     EL_DC_STEELWALL_2_SINGLE,
3841     EL_STEELWALL_SLIPPERY,
3842     EL_EMC_STEELWALL_1,
3843     EL_EMC_STEELWALL_2,
3844     EL_EMC_STEELWALL_3,
3845     EL_EMC_STEELWALL_4,
3846     EL_EMC_WALL_SLIPPERY_1,
3847     EL_EMC_WALL_SLIPPERY_2,
3848     EL_EMC_WALL_SLIPPERY_3,
3849     EL_EMC_WALL_SLIPPERY_4,
3850     EL_EMC_WALL_1,
3851     EL_EMC_WALL_2,
3852     EL_EMC_WALL_3,
3853     EL_EMC_WALL_4,
3854     EL_EMC_WALL_5,
3855     EL_EMC_WALL_6,
3856     EL_EMC_WALL_7,
3857     EL_EMC_WALL_8,
3858     EL_EMC_WALL_9,
3859     EL_EMC_WALL_10,
3860     EL_EMC_WALL_11,
3861     EL_EMC_WALL_12,
3862     EL_EMC_WALL_13,
3863     EL_EMC_WALL_14,
3864     EL_EMC_WALL_15,
3865     EL_EMC_WALL_16,
3866
3867     -1
3868   };
3869
3870   static int ep_em_slippery_wall[] =
3871   {
3872     -1
3873   };
3874
3875   static int ep_gfx_crumbled[] =
3876   {
3877     EL_SAND,
3878     EL_LANDMINE,
3879     EL_DC_LANDMINE,
3880     EL_TRAP,
3881     EL_TRAP_ACTIVE,
3882
3883     -1
3884   };
3885
3886   static int ep_editor_cascade_active[] =
3887   {
3888     EL_INTERNAL_CASCADE_BD_ACTIVE,
3889     EL_INTERNAL_CASCADE_EM_ACTIVE,
3890     EL_INTERNAL_CASCADE_EMC_ACTIVE,
3891     EL_INTERNAL_CASCADE_RND_ACTIVE,
3892     EL_INTERNAL_CASCADE_SB_ACTIVE,
3893     EL_INTERNAL_CASCADE_SP_ACTIVE,
3894     EL_INTERNAL_CASCADE_DC_ACTIVE,
3895     EL_INTERNAL_CASCADE_DX_ACTIVE,
3896     EL_INTERNAL_CASCADE_CHARS_ACTIVE,
3897     EL_INTERNAL_CASCADE_STEEL_CHARS_ACTIVE,
3898     EL_INTERNAL_CASCADE_CE_ACTIVE,
3899     EL_INTERNAL_CASCADE_GE_ACTIVE,
3900     EL_INTERNAL_CASCADE_REF_ACTIVE,
3901     EL_INTERNAL_CASCADE_USER_ACTIVE,
3902     EL_INTERNAL_CASCADE_DYNAMIC_ACTIVE,
3903
3904     -1
3905   };
3906
3907   static int ep_editor_cascade_inactive[] =
3908   {
3909     EL_INTERNAL_CASCADE_BD,
3910     EL_INTERNAL_CASCADE_EM,
3911     EL_INTERNAL_CASCADE_EMC,
3912     EL_INTERNAL_CASCADE_RND,
3913     EL_INTERNAL_CASCADE_SB,
3914     EL_INTERNAL_CASCADE_SP,
3915     EL_INTERNAL_CASCADE_DC,
3916     EL_INTERNAL_CASCADE_DX,
3917     EL_INTERNAL_CASCADE_CHARS,
3918     EL_INTERNAL_CASCADE_STEEL_CHARS,
3919     EL_INTERNAL_CASCADE_CE,
3920     EL_INTERNAL_CASCADE_GE,
3921     EL_INTERNAL_CASCADE_REF,
3922     EL_INTERNAL_CASCADE_USER,
3923     EL_INTERNAL_CASCADE_DYNAMIC,
3924
3925     -1
3926   };
3927
3928   static int ep_obsolete[] =
3929   {
3930     EL_PLAYER_OBSOLETE,
3931     EL_KEY_OBSOLETE,
3932     EL_EM_KEY_1_FILE_OBSOLETE,
3933     EL_EM_KEY_2_FILE_OBSOLETE,
3934     EL_EM_KEY_3_FILE_OBSOLETE,
3935     EL_EM_KEY_4_FILE_OBSOLETE,
3936     EL_ENVELOPE_OBSOLETE,
3937
3938     -1
3939   };
3940
3941   static struct
3942   {
3943     int *elements;
3944     int property;
3945   } element_properties[] =
3946   {
3947     { ep_diggable,                      EP_DIGGABLE                     },
3948     { ep_collectible_only,              EP_COLLECTIBLE_ONLY             },
3949     { ep_dont_run_into,                 EP_DONT_RUN_INTO                },
3950     { ep_dont_collide_with,             EP_DONT_COLLIDE_WITH            },
3951     { ep_dont_touch,                    EP_DONT_TOUCH                   },
3952     { ep_indestructible,                EP_INDESTRUCTIBLE               },
3953     { ep_slippery,                      EP_SLIPPERY                     },
3954     { ep_can_change,                    EP_CAN_CHANGE                   },
3955     { ep_can_move,                      EP_CAN_MOVE                     },
3956     { ep_can_fall,                      EP_CAN_FALL                     },
3957     { ep_can_smash_player,              EP_CAN_SMASH_PLAYER             },
3958     { ep_can_smash_enemies,             EP_CAN_SMASH_ENEMIES            },
3959     { ep_can_smash_everything,          EP_CAN_SMASH_EVERYTHING         },
3960     { ep_explodes_by_fire,              EP_EXPLODES_BY_FIRE             },
3961     { ep_explodes_smashed,              EP_EXPLODES_SMASHED             },
3962     { ep_explodes_impact,               EP_EXPLODES_IMPACT              },
3963     { ep_walkable_over,                 EP_WALKABLE_OVER                },
3964     { ep_walkable_inside,               EP_WALKABLE_INSIDE              },
3965     { ep_walkable_under,                EP_WALKABLE_UNDER               },
3966     { ep_passable_over,                 EP_PASSABLE_OVER                },
3967     { ep_passable_inside,               EP_PASSABLE_INSIDE              },
3968     { ep_passable_under,                EP_PASSABLE_UNDER               },
3969     { ep_droppable,                     EP_DROPPABLE                    },
3970     { ep_explodes_1x1_old,              EP_EXPLODES_1X1_OLD             },
3971     { ep_pushable,                      EP_PUSHABLE                     },
3972     { ep_explodes_cross_old,            EP_EXPLODES_CROSS_OLD           },
3973     { ep_protected,                     EP_PROTECTED                    },
3974     { ep_throwable,                     EP_THROWABLE                    },
3975     { ep_can_explode,                   EP_CAN_EXPLODE                  },
3976     { ep_gravity_reachable,             EP_GRAVITY_REACHABLE            },
3977
3978     { ep_player,                        EP_PLAYER                       },
3979     { ep_can_pass_magic_wall,           EP_CAN_PASS_MAGIC_WALL          },
3980     { ep_can_pass_dc_magic_wall,        EP_CAN_PASS_DC_MAGIC_WALL       },
3981     { ep_switchable,                    EP_SWITCHABLE                   },
3982     { ep_bd_element,                    EP_BD_ELEMENT                   },
3983     { ep_sp_element,                    EP_SP_ELEMENT                   },
3984     { ep_sb_element,                    EP_SB_ELEMENT                   },
3985     { ep_gem,                           EP_GEM                          },
3986     { ep_food_dark_yamyam,              EP_FOOD_DARK_YAMYAM             },
3987     { ep_food_penguin,                  EP_FOOD_PENGUIN                 },
3988     { ep_food_pig,                      EP_FOOD_PIG                     },
3989     { ep_historic_wall,                 EP_HISTORIC_WALL                },
3990     { ep_historic_solid,                EP_HISTORIC_SOLID               },
3991     { ep_classic_enemy,                 EP_CLASSIC_ENEMY                },
3992     { ep_belt,                          EP_BELT                         },
3993     { ep_belt_active,                   EP_BELT_ACTIVE                  },
3994     { ep_belt_switch,                   EP_BELT_SWITCH                  },
3995     { ep_tube,                          EP_TUBE                         },
3996     { ep_acid_pool,                     EP_ACID_POOL                    },
3997     { ep_keygate,                       EP_KEYGATE                      },
3998     { ep_amoeboid,                      EP_AMOEBOID                     },
3999     { ep_amoebalive,                    EP_AMOEBALIVE                   },
4000     { ep_has_editor_content,            EP_HAS_EDITOR_CONTENT           },
4001     { ep_can_turn_each_move,            EP_CAN_TURN_EACH_MOVE           },
4002     { ep_can_grow,                      EP_CAN_GROW                     },
4003     { ep_active_bomb,                   EP_ACTIVE_BOMB                  },
4004     { ep_inactive,                      EP_INACTIVE                     },
4005
4006     { ep_em_slippery_wall,              EP_EM_SLIPPERY_WALL             },
4007
4008     { ep_gfx_crumbled,                  EP_GFX_CRUMBLED                 },
4009
4010     { ep_editor_cascade_active,         EP_EDITOR_CASCADE_ACTIVE        },
4011     { ep_editor_cascade_inactive,       EP_EDITOR_CASCADE_INACTIVE      },
4012
4013     { ep_obsolete,                      EP_OBSOLETE                     },
4014
4015     { NULL,                             -1                              }
4016   };
4017
4018   int i, j, k;
4019
4020   /* always start with reliable default values (element has no properties) */
4021   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4022     for (j = 0; j < NUM_ELEMENT_PROPERTIES; j++)
4023       SET_PROPERTY(i, j, FALSE);
4024
4025   /* set all base element properties from above array definitions */
4026   for (i = 0; element_properties[i].elements != NULL; i++)
4027     for (j = 0; (element_properties[i].elements)[j] != -1; j++)
4028       SET_PROPERTY((element_properties[i].elements)[j],
4029                    element_properties[i].property, TRUE);
4030
4031   /* copy properties to some elements that are only stored in level file */
4032   for (i = 0; i < NUM_ELEMENT_PROPERTIES; i++)
4033     for (j = 0; copy_properties[j][0] != -1; j++)
4034       if (HAS_PROPERTY(copy_properties[j][0], i))
4035         for (k = 1; k <= 4; k++)
4036           SET_PROPERTY(copy_properties[j][k], i, TRUE);
4037
4038   /* set static element properties that are not listed in array definitions */
4039   for (i = EL_STEEL_CHAR_START; i <= EL_STEEL_CHAR_END; i++)
4040     SET_PROPERTY(i, EP_INDESTRUCTIBLE, TRUE);
4041 }
4042
4043 void InitElementPropertiesEngine(int engine_version)
4044 {
4045   static int no_wall_properties[] =
4046   {
4047     EP_DIGGABLE,
4048     EP_COLLECTIBLE_ONLY,
4049     EP_DONT_RUN_INTO,
4050     EP_DONT_COLLIDE_WITH,
4051     EP_CAN_MOVE,
4052     EP_CAN_FALL,
4053     EP_CAN_SMASH_PLAYER,
4054     EP_CAN_SMASH_ENEMIES,
4055     EP_CAN_SMASH_EVERYTHING,
4056     EP_PUSHABLE,
4057
4058     EP_PLAYER,
4059     EP_GEM,
4060     EP_FOOD_DARK_YAMYAM,
4061     EP_FOOD_PENGUIN,
4062     EP_BELT,
4063     EP_BELT_ACTIVE,
4064     EP_TUBE,
4065     EP_AMOEBOID,
4066     EP_AMOEBALIVE,
4067     EP_ACTIVE_BOMB,
4068
4069     EP_ACCESSIBLE,
4070
4071     -1
4072   };
4073
4074   int i, j;
4075
4076   /* important: after initialization in InitElementPropertiesStatic(), the
4077      elements are not again initialized to a default value; therefore all
4078      changes have to make sure that they leave the element with a defined
4079      property (which means that conditional property changes must be set to
4080      a reliable default value before) */
4081
4082   /* resolve group elements */
4083   for (i = 0; i < NUM_GROUP_ELEMENTS; i++)
4084     ResolveGroupElement(EL_GROUP_START + i);
4085
4086   /* set all special, combined or engine dependent element properties */
4087   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4088   {
4089     /* ---------- INACTIVE ------------------------------------------------- */
4090     SET_PROPERTY(i, EP_INACTIVE, ((i >= EL_CHAR_START &&
4091                                    i <= EL_CHAR_END) ||
4092                                   (i >= EL_STEEL_CHAR_START &&
4093                                    i <= EL_STEEL_CHAR_END)));
4094
4095     /* ---------- WALKABLE, PASSABLE, ACCESSIBLE --------------------------- */
4096     SET_PROPERTY(i, EP_WALKABLE, (IS_WALKABLE_OVER(i) ||
4097                                   IS_WALKABLE_INSIDE(i) ||
4098                                   IS_WALKABLE_UNDER(i)));
4099
4100     SET_PROPERTY(i, EP_PASSABLE, (IS_PASSABLE_OVER(i) ||
4101                                   IS_PASSABLE_INSIDE(i) ||
4102                                   IS_PASSABLE_UNDER(i)));
4103
4104     SET_PROPERTY(i, EP_ACCESSIBLE_OVER, (IS_WALKABLE_OVER(i) ||
4105                                          IS_PASSABLE_OVER(i)));
4106
4107     SET_PROPERTY(i, EP_ACCESSIBLE_INSIDE, (IS_WALKABLE_INSIDE(i) ||
4108                                            IS_PASSABLE_INSIDE(i)));
4109
4110     SET_PROPERTY(i, EP_ACCESSIBLE_UNDER, (IS_WALKABLE_UNDER(i) ||
4111                                           IS_PASSABLE_UNDER(i)));
4112
4113     SET_PROPERTY(i, EP_ACCESSIBLE, (IS_WALKABLE(i) ||
4114                                     IS_PASSABLE(i)));
4115
4116     /* ---------- COLLECTIBLE ---------------------------------------------- */
4117     SET_PROPERTY(i, EP_COLLECTIBLE, (IS_COLLECTIBLE_ONLY(i) ||
4118                                      IS_DROPPABLE(i) ||
4119                                      IS_THROWABLE(i)));
4120
4121     /* ---------- SNAPPABLE ------------------------------------------------ */
4122     SET_PROPERTY(i, EP_SNAPPABLE, (IS_DIGGABLE(i) ||
4123                                    IS_COLLECTIBLE(i) ||
4124                                    IS_SWITCHABLE(i) ||
4125                                    i == EL_BD_ROCK));
4126
4127     /* ---------- WALL ----------------------------------------------------- */
4128     SET_PROPERTY(i, EP_WALL, TRUE);     /* default: element is wall */
4129
4130     for (j = 0; no_wall_properties[j] != -1; j++)
4131       if (HAS_PROPERTY(i, no_wall_properties[j]) ||
4132           i >= EL_FIRST_RUNTIME_UNREAL)
4133         SET_PROPERTY(i, EP_WALL, FALSE);
4134
4135     if (IS_HISTORIC_WALL(i))
4136       SET_PROPERTY(i, EP_WALL, TRUE);
4137
4138     /* ---------- SOLID_FOR_PUSHING ---------------------------------------- */
4139     if (engine_version < VERSION_IDENT(2,2,0,0))
4140       SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, IS_HISTORIC_SOLID(i));
4141     else
4142       SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, (!IS_WALKABLE(i) &&
4143                                              !IS_DIGGABLE(i) &&
4144                                              !IS_COLLECTIBLE(i)));
4145
4146     /* ---------- DRAGONFIRE_PROOF ----------------------------------------- */
4147     if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
4148       SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE);
4149     else
4150       SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_CUSTOM_ELEMENT(i) &&
4151                                             IS_INDESTRUCTIBLE(i)));
4152
4153     /* ---------- EXPLOSION_PROOF ------------------------------------------ */
4154     if (i == EL_FLAMES)
4155       SET_PROPERTY(i, EP_EXPLOSION_PROOF, TRUE);
4156     else if (engine_version < VERSION_IDENT(2,2,0,0))
4157       SET_PROPERTY(i, EP_EXPLOSION_PROOF, IS_INDESTRUCTIBLE(i));
4158     else
4159       SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
4160                                            (!IS_WALKABLE(i) ||
4161                                             IS_PROTECTED(i))));
4162
4163     if (IS_CUSTOM_ELEMENT(i))
4164     {
4165       /* these are additional properties which are initially false when set */
4166
4167       /* ---------- DONT_COLLIDE_WITH / DONT_RUN_INTO ---------------------- */
4168       if (DONT_TOUCH(i))
4169         SET_PROPERTY(i, EP_DONT_COLLIDE_WITH, TRUE);
4170       if (DONT_COLLIDE_WITH(i))
4171         SET_PROPERTY(i, EP_DONT_RUN_INTO, TRUE);
4172
4173       /* ---------- CAN_SMASH_ENEMIES / CAN_SMASH_PLAYER ------------------- */
4174       if (CAN_SMASH_EVERYTHING(i))
4175         SET_PROPERTY(i, EP_CAN_SMASH_ENEMIES, TRUE);
4176       if (CAN_SMASH_ENEMIES(i))
4177         SET_PROPERTY(i, EP_CAN_SMASH_PLAYER, TRUE);
4178     }
4179
4180     /* ---------- CAN_SMASH ------------------------------------------------ */
4181     SET_PROPERTY(i, EP_CAN_SMASH, (CAN_SMASH_PLAYER(i) ||
4182                                    CAN_SMASH_ENEMIES(i) ||
4183                                    CAN_SMASH_EVERYTHING(i)));
4184
4185     /* ---------- CAN_EXPLODE_BY_FIRE -------------------------------------- */
4186     SET_PROPERTY(i, EP_CAN_EXPLODE_BY_FIRE, (CAN_EXPLODE(i) &&
4187                                              EXPLODES_BY_FIRE(i)));
4188
4189     /* ---------- CAN_EXPLODE_SMASHED -------------------------------------- */
4190     SET_PROPERTY(i, EP_CAN_EXPLODE_SMASHED, (CAN_EXPLODE(i) &&
4191                                              EXPLODES_SMASHED(i)));
4192
4193     /* ---------- CAN_EXPLODE_IMPACT --------------------------------------- */
4194     SET_PROPERTY(i, EP_CAN_EXPLODE_IMPACT, (CAN_EXPLODE(i) &&
4195                                             EXPLODES_IMPACT(i)));
4196
4197     /* ---------- CAN_EXPLODE_BY_DRAGONFIRE -------------------------------- */
4198     SET_PROPERTY(i, EP_CAN_EXPLODE_BY_DRAGONFIRE, CAN_EXPLODE_BY_FIRE(i));
4199
4200     /* ---------- CAN_EXPLODE_BY_EXPLOSION --------------------------------- */
4201     SET_PROPERTY(i, EP_CAN_EXPLODE_BY_EXPLOSION, (CAN_EXPLODE_BY_FIRE(i) ||
4202                                                   i == EL_BLACK_ORB));
4203
4204     /* ---------- COULD_MOVE_INTO_ACID ------------------------------------- */
4205     SET_PROPERTY(i, EP_COULD_MOVE_INTO_ACID, (ELEM_IS_PLAYER(i) ||
4206                                               CAN_MOVE(i) ||
4207                                               IS_CUSTOM_ELEMENT(i)));
4208
4209     /* ---------- MAYBE_DONT_COLLIDE_WITH ---------------------------------- */
4210     SET_PROPERTY(i, EP_MAYBE_DONT_COLLIDE_WITH, (i == EL_SP_SNIKSNAK ||
4211                                                  i == EL_SP_ELECTRON));
4212
4213     /* ---------- CAN_MOVE_INTO_ACID --------------------------------------- */
4214     if (COULD_MOVE_INTO_ACID(i) && !IS_CUSTOM_ELEMENT(i))
4215       SET_PROPERTY(i, EP_CAN_MOVE_INTO_ACID,
4216                    getMoveIntoAcidProperty(&level, i));
4217
4218     /* ---------- DONT_COLLIDE_WITH ---------------------------------------- */
4219     if (MAYBE_DONT_COLLIDE_WITH(i))
4220       SET_PROPERTY(i, EP_DONT_COLLIDE_WITH,
4221                    getDontCollideWithProperty(&level, i));
4222
4223     /* ---------- SP_PORT -------------------------------------------------- */
4224     SET_PROPERTY(i, EP_SP_PORT, (IS_SP_ELEMENT(i) &&
4225                                  IS_PASSABLE_INSIDE(i)));
4226
4227     /* ---------- CAN_BE_CLONED_BY_ANDROID --------------------------------- */
4228     for (j = 0; j < level.num_android_clone_elements; j++)
4229       SET_PROPERTY(i, EP_CAN_BE_CLONED_BY_ANDROID,
4230                    (i != EL_EMPTY &&
4231                     IS_EQUAL_OR_IN_GROUP(i, level.android_clone_element[j])));
4232
4233     /* ---------- CAN_CHANGE ----------------------------------------------- */
4234     SET_PROPERTY(i, EP_CAN_CHANGE, FALSE);      /* default: cannot change */
4235     for (j = 0; j < element_info[i].num_change_pages; j++)
4236       if (element_info[i].change_page[j].can_change)
4237         SET_PROPERTY(i, EP_CAN_CHANGE, TRUE);
4238
4239     /* ---------- HAS_ACTION ----------------------------------------------- */
4240     SET_PROPERTY(i, EP_HAS_ACTION, FALSE);      /* default: has no action */
4241     for (j = 0; j < element_info[i].num_change_pages; j++)
4242       if (element_info[i].change_page[j].has_action)
4243         SET_PROPERTY(i, EP_HAS_ACTION, TRUE);
4244
4245     /* ---------- CAN_CHANGE_OR_HAS_ACTION --------------------------------- */
4246     SET_PROPERTY(i, EP_CAN_CHANGE_OR_HAS_ACTION, (CAN_CHANGE(i) ||
4247                                                   HAS_ACTION(i)));
4248
4249     /* ---------- GFX_CRUMBLED --------------------------------------------- */
4250 #if 1
4251     SET_PROPERTY(i, EP_GFX_CRUMBLED,
4252                  element_info[i].crumbled[ACTION_DEFAULT] !=
4253                  element_info[i].graphic[ACTION_DEFAULT]);
4254 #else
4255     /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
4256     SET_PROPERTY(i, EP_GFX_CRUMBLED,
4257                  element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
4258 #endif
4259
4260     /* ---------- EDITOR_CASCADE ------------------------------------------- */
4261     SET_PROPERTY(i, EP_EDITOR_CASCADE, (IS_EDITOR_CASCADE_ACTIVE(i) ||
4262                                         IS_EDITOR_CASCADE_INACTIVE(i)));
4263   }
4264
4265   /* dynamically adjust element properties according to game engine version */
4266   {
4267     static int ep_em_slippery_wall[] =
4268     {
4269       EL_WALL,
4270       EL_STEELWALL,
4271       EL_EXPANDABLE_WALL,
4272       EL_EXPANDABLE_WALL_HORIZONTAL,
4273       EL_EXPANDABLE_WALL_VERTICAL,
4274       EL_EXPANDABLE_WALL_ANY,
4275       EL_EXPANDABLE_STEELWALL_HORIZONTAL,
4276       EL_EXPANDABLE_STEELWALL_VERTICAL,
4277       EL_EXPANDABLE_STEELWALL_ANY,
4278       EL_EXPANDABLE_STEELWALL_GROWING,
4279       -1
4280     };
4281
4282     /* special EM style gems behaviour */
4283     for (i = 0; ep_em_slippery_wall[i] != -1; i++)
4284       SET_PROPERTY(ep_em_slippery_wall[i], EP_EM_SLIPPERY_WALL,
4285                    level.em_slippery_gems);
4286
4287     /* "EL_EXPANDABLE_WALL_GROWING" wasn't slippery for EM gems in 2.0.1 */
4288     SET_PROPERTY(EL_EXPANDABLE_WALL_GROWING, EP_EM_SLIPPERY_WALL,
4289                  (level.em_slippery_gems &&
4290                   engine_version > VERSION_IDENT(2,0,1,0)));
4291   }
4292
4293   /* this is needed because some graphics depend on element properties */
4294   if (game_status == GAME_MODE_PLAYING)
4295     InitElementGraphicInfo();
4296 }
4297
4298 void InitElementPropertiesAfterLoading(int engine_version)
4299 {
4300   int i;
4301
4302   /* set some other uninitialized values of custom elements in older levels */
4303   if (engine_version < VERSION_IDENT(3,1,0,0))
4304   {
4305     for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
4306     {
4307       int element = EL_CUSTOM_START + i;
4308
4309       element_info[element].access_direction = MV_ALL_DIRECTIONS;
4310
4311       element_info[element].explosion_delay = 17;
4312       element_info[element].ignition_delay = 8;
4313     }
4314   }
4315 }
4316
4317 static void InitGlobal()
4318 {
4319   int i;
4320
4321   for (i = 0; i < MAX_NUM_ELEMENTS + 1; i++)
4322   {
4323     /* check if element_name_info entry defined for each element in "main.h" */
4324     if (i < MAX_NUM_ELEMENTS && element_name_info[i].token_name == NULL)
4325       Error(ERR_EXIT, "undefined 'element_name_info' entry for element %d", i);
4326
4327     element_info[i].token_name = element_name_info[i].token_name;
4328     element_info[i].class_name = element_name_info[i].class_name;
4329     element_info[i].editor_description=element_name_info[i].editor_description;
4330
4331 #if 0
4332     printf("%04d: %s\n", i, element_name_info[i].token_name);
4333 #endif
4334   }
4335
4336   global.autoplay_leveldir = NULL;
4337   global.convert_leveldir = NULL;
4338
4339   global.frames_per_second = 0;
4340   global.fps_slowdown = FALSE;
4341   global.fps_slowdown_factor = 1;
4342 }
4343
4344 void Execute_Command(char *command)
4345 {
4346   int i;
4347
4348   if (strEqual(command, "print graphicsinfo.conf"))
4349   {
4350     printf("# You can configure additional/alternative image files here.\n");
4351     printf("# (The entries below are default and therefore commented out.)\n");
4352     printf("\n");
4353     printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
4354     printf("\n");
4355     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
4356     printf("\n");
4357
4358     for (i = 0; image_config[i].token != NULL; i++)
4359       printf("# %s\n", getFormattedSetupEntry(image_config[i].token,
4360                                               image_config[i].value));
4361
4362     exit(0);
4363   }
4364   else if (strEqual(command, "print soundsinfo.conf"))
4365   {
4366     printf("# You can configure additional/alternative sound files here.\n");
4367     printf("# (The entries below are default and therefore commented out.)\n");
4368     printf("\n");
4369     printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
4370     printf("\n");
4371     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
4372     printf("\n");
4373
4374     for (i = 0; sound_config[i].token != NULL; i++)
4375       printf("# %s\n", getFormattedSetupEntry(sound_config[i].token,
4376                                               sound_config[i].value));
4377
4378     exit(0);
4379   }
4380   else if (strEqual(command, "print musicinfo.conf"))
4381   {
4382     printf("# You can configure additional/alternative music files here.\n");
4383     printf("# (The entries below are default and therefore commented out.)\n");
4384     printf("\n");
4385     printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
4386     printf("\n");
4387     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
4388     printf("\n");
4389
4390     for (i = 0; music_config[i].token != NULL; i++)
4391       printf("# %s\n", getFormattedSetupEntry(music_config[i].token,
4392                                               music_config[i].value));
4393
4394     exit(0);
4395   }
4396   else if (strEqual(command, "print editorsetup.conf"))
4397   {
4398     printf("# You can configure your personal editor element list here.\n");
4399     printf("# (The entries below are default and therefore commented out.)\n");
4400     printf("\n");
4401
4402     /* this is needed to be able to check element list for cascade elements */
4403     InitElementPropertiesStatic();
4404     InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
4405
4406     PrintEditorElementList();
4407
4408     exit(0);
4409   }
4410   else if (strEqual(command, "print helpanim.conf"))
4411   {
4412     printf("# You can configure different element help animations here.\n");
4413     printf("# (The entries below are default and therefore commented out.)\n");
4414     printf("\n");
4415
4416     for (i = 0; helpanim_config[i].token != NULL; i++)
4417     {
4418       printf("# %s\n", getFormattedSetupEntry(helpanim_config[i].token,
4419                                               helpanim_config[i].value));
4420
4421       if (strEqual(helpanim_config[i].token, "end"))
4422         printf("#\n");
4423     }
4424
4425     exit(0);
4426   }
4427   else if (strEqual(command, "print helptext.conf"))
4428   {
4429     printf("# You can configure different element help text here.\n");
4430     printf("# (The entries below are default and therefore commented out.)\n");
4431     printf("\n");
4432
4433     for (i = 0; helptext_config[i].token != NULL; i++)
4434       printf("# %s\n", getFormattedSetupEntry(helptext_config[i].token,
4435                                               helptext_config[i].value));
4436
4437     exit(0);
4438   }
4439   else if (strncmp(command, "dump level ", 11) == 0)
4440   {
4441     char *filename = &command[11];
4442
4443     if (!fileExists(filename))
4444       Error(ERR_EXIT, "cannot open file '%s'", filename);
4445
4446     LoadLevelFromFilename(&level, filename);
4447     DumpLevel(&level);
4448
4449     exit(0);
4450   }
4451   else if (strncmp(command, "dump tape ", 10) == 0)
4452   {
4453     char *filename = &command[10];
4454
4455     if (!fileExists(filename))
4456       Error(ERR_EXIT, "cannot open file '%s'", filename);
4457
4458     LoadTapeFromFilename(filename);
4459     DumpTape(&tape);
4460
4461     exit(0);
4462   }
4463   else if (strncmp(command, "autoplay ", 9) == 0)
4464   {
4465     char *str_ptr = getStringCopy(&command[9]); /* read command parameters */
4466
4467     while (*str_ptr != '\0')                    /* continue parsing string */
4468     {
4469       /* cut leading whitespace from string, replace it by string terminator */
4470       while (*str_ptr == ' ' || *str_ptr == '\t')
4471         *str_ptr++ = '\0';
4472
4473       if (*str_ptr == '\0')                     /* end of string reached */
4474         break;
4475
4476       if (global.autoplay_leveldir == NULL)     /* read level set string */
4477       {
4478         global.autoplay_leveldir = str_ptr;
4479         global.autoplay_all = TRUE;             /* default: play all tapes */
4480
4481         for (i = 0; i < MAX_TAPES_PER_SET; i++)
4482           global.autoplay_level[i] = FALSE;
4483       }
4484       else                                      /* read level number string */
4485       {
4486         int level_nr = atoi(str_ptr);           /* get level_nr value */
4487
4488         if (level_nr >= 0 && level_nr < MAX_TAPES_PER_SET)
4489           global.autoplay_level[level_nr] = TRUE;
4490
4491         global.autoplay_all = FALSE;
4492       }
4493
4494       /* advance string pointer to the next whitespace (or end of string) */
4495       while (*str_ptr != ' ' && *str_ptr != '\t' && *str_ptr != '\0')
4496         str_ptr++;
4497     }
4498   }
4499   else if (strncmp(command, "convert ", 8) == 0)
4500   {
4501     char *str_copy = getStringCopy(&command[8]);
4502     char *str_ptr = strchr(str_copy, ' ');
4503
4504     global.convert_leveldir = str_copy;
4505     global.convert_level_nr = -1;
4506
4507     if (str_ptr != NULL)                        /* level number follows */
4508     {
4509       *str_ptr++ = '\0';                        /* terminate leveldir string */
4510       global.convert_level_nr = atoi(str_ptr);  /* get level_nr value */
4511     }
4512   }
4513
4514 #if DEBUG
4515 #if defined(TARGET_SDL)
4516   else if (strEqual(command, "SDL_ListModes"))
4517   {
4518     SDL_Rect **modes;
4519     int i;
4520
4521     SDL_Init(SDL_INIT_VIDEO);
4522
4523     /* get available fullscreen/hardware modes */
4524     modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
4525
4526     /* check if there are any modes available */
4527     if (modes == NULL)
4528     {
4529       printf("No modes available!\n");
4530
4531       exit(-1);
4532     }
4533
4534     /* check if our resolution is restricted */
4535     if (modes == (SDL_Rect **)-1)
4536     {
4537       printf("All resolutions available.\n");
4538     }
4539     else
4540     {
4541       printf("Available Modes:\n");
4542
4543       for(i = 0; modes[i]; i++)
4544         printf("  %d x %d\n", modes[i]->w, modes[i]->h);
4545     }
4546
4547     exit(0);
4548   }
4549 #endif
4550 #endif
4551
4552   else
4553   {
4554     Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
4555   }
4556 }
4557
4558 static void InitSetup()
4559 {
4560   LoadSetup();                                  /* global setup info */
4561
4562   /* set some options from setup file */
4563
4564   if (setup.options.verbose)
4565     options.verbose = TRUE;
4566 }
4567
4568 static void InitGameInfo()
4569 {
4570   game.restart_level = FALSE;
4571 }
4572
4573 static void InitPlayerInfo()
4574 {
4575   int i;
4576
4577   /* choose default local player */
4578   local_player = &stored_player[0];
4579
4580   for (i = 0; i < MAX_PLAYERS; i++)
4581     stored_player[i].connected = FALSE;
4582
4583   local_player->connected = TRUE;
4584 }
4585
4586 static void InitArtworkInfo()
4587 {
4588   LoadArtworkInfo();
4589 }
4590
4591 static char *get_string_in_brackets(char *string)
4592 {
4593   char *string_in_brackets = checked_malloc(strlen(string) + 3);
4594
4595   sprintf(string_in_brackets, "[%s]", string);
4596
4597   return string_in_brackets;
4598 }
4599
4600 static char *get_level_id_suffix(int id_nr)
4601 {
4602   char *id_suffix = checked_malloc(1 + 3 + 1);
4603
4604   if (id_nr < 0 || id_nr > 999)
4605     id_nr = 0;
4606
4607   sprintf(id_suffix, ".%03d", id_nr);
4608
4609   return id_suffix;
4610 }
4611
4612 #if 0
4613 static char *get_element_class_token(int element)
4614 {
4615   char *element_class_name = element_info[element].class_name;
4616   char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
4617
4618   sprintf(element_class_token, "[%s]", element_class_name);
4619
4620   return element_class_token;
4621 }
4622
4623 static char *get_action_class_token(int action)
4624 {
4625   char *action_class_name = &element_action_info[action].suffix[1];
4626   char *action_class_token = checked_malloc(strlen(action_class_name) + 3);
4627
4628   sprintf(action_class_token, "[%s]", action_class_name);
4629
4630   return action_class_token;
4631 }
4632 #endif
4633
4634 static void InitArtworkConfig()
4635 {
4636   static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
4637   static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + 1];
4638   static char *music_id_prefix[NUM_MUSIC_PREFIXES + 1];
4639   static char *action_id_suffix[NUM_ACTIONS + 1];
4640   static char *direction_id_suffix[NUM_DIRECTIONS_FULL + 1];
4641   static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
4642   static char *level_id_suffix[MAX_LEVELS + 1];
4643   static char *dummy[1] = { NULL };
4644   static char *ignore_generic_tokens[] =
4645   {
4646     "name",
4647     "sort_priority",
4648     NULL
4649   };
4650   static char **ignore_image_tokens;
4651   static char **ignore_sound_tokens;
4652   static char **ignore_music_tokens;
4653   int num_ignore_generic_tokens;
4654   int num_ignore_image_tokens;
4655   int num_ignore_sound_tokens;
4656   int num_ignore_music_tokens;
4657   int i;
4658
4659   /* dynamically determine list of generic tokens to be ignored */
4660   num_ignore_generic_tokens = 0;
4661   for (i = 0; ignore_generic_tokens[i] != NULL; i++)
4662     num_ignore_generic_tokens++;
4663
4664   /* dynamically determine list of image tokens to be ignored */
4665   num_ignore_image_tokens = num_ignore_generic_tokens;
4666   for (i = 0; image_config_vars[i].token != NULL; i++)
4667     num_ignore_image_tokens++;
4668   ignore_image_tokens =
4669     checked_malloc((num_ignore_image_tokens + 1) * sizeof(char *));
4670   for (i = 0; i < num_ignore_generic_tokens; i++)
4671     ignore_image_tokens[i] = ignore_generic_tokens[i];
4672   for (i = 0; i < num_ignore_image_tokens - num_ignore_generic_tokens; i++)
4673     ignore_image_tokens[num_ignore_generic_tokens + i] =
4674       image_config_vars[i].token;
4675   ignore_image_tokens[num_ignore_image_tokens] = NULL;
4676
4677   /* dynamically determine list of sound tokens to be ignored */
4678   num_ignore_sound_tokens = num_ignore_generic_tokens;
4679   ignore_sound_tokens =
4680     checked_malloc((num_ignore_sound_tokens + 1) * sizeof(char *));
4681   for (i = 0; i < num_ignore_generic_tokens; i++)
4682     ignore_sound_tokens[i] = ignore_generic_tokens[i];
4683   ignore_sound_tokens[num_ignore_sound_tokens] = NULL;
4684
4685   /* dynamically determine list of music tokens to be ignored */
4686   num_ignore_music_tokens = num_ignore_generic_tokens;
4687   ignore_music_tokens =
4688     checked_malloc((num_ignore_music_tokens + 1) * sizeof(char *));
4689   for (i = 0; i < num_ignore_generic_tokens; i++)
4690     ignore_music_tokens[i] = ignore_generic_tokens[i];
4691   ignore_music_tokens[num_ignore_music_tokens] = NULL;
4692
4693   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4694     image_id_prefix[i] = element_info[i].token_name;
4695   for (i = 0; i < NUM_FONTS; i++)
4696     image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
4697   image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
4698
4699   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4700     sound_id_prefix[i] = element_info[i].token_name;
4701   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4702     sound_id_prefix[MAX_NUM_ELEMENTS + i] =
4703       get_string_in_brackets(element_info[i].class_name);
4704   sound_id_prefix[2 * MAX_NUM_ELEMENTS] = NULL;
4705
4706   for (i = 0; i < NUM_MUSIC_PREFIXES; i++)
4707     music_id_prefix[i] = music_prefix_info[i].prefix;
4708   music_id_prefix[NUM_MUSIC_PREFIXES] = NULL;
4709
4710   for (i = 0; i < NUM_ACTIONS; i++)
4711     action_id_suffix[i] = element_action_info[i].suffix;
4712   action_id_suffix[NUM_ACTIONS] = NULL;
4713
4714   for (i = 0; i < NUM_DIRECTIONS_FULL; i++)
4715     direction_id_suffix[i] = element_direction_info[i].suffix;
4716   direction_id_suffix[NUM_DIRECTIONS_FULL] = NULL;
4717
4718   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
4719     special_id_suffix[i] = special_suffix_info[i].suffix;
4720   special_id_suffix[NUM_SPECIAL_GFX_ARGS] = NULL;
4721
4722   for (i = 0; i < MAX_LEVELS; i++)
4723     level_id_suffix[i] = get_level_id_suffix(i);
4724   level_id_suffix[MAX_LEVELS] = NULL;
4725
4726   InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
4727                 image_id_prefix, action_id_suffix, direction_id_suffix,
4728                 special_id_suffix, ignore_image_tokens);
4729   InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
4730                 sound_id_prefix, action_id_suffix, dummy,
4731                 special_id_suffix, ignore_sound_tokens);
4732   InitMusicList(music_config, NUM_MUSIC_FILES, music_config_suffix,
4733                 music_id_prefix, special_id_suffix, level_id_suffix,
4734                 dummy, ignore_music_tokens);
4735 }
4736
4737 static void InitMixer()
4738 {
4739   OpenAudio();
4740   StartMixer();
4741 }
4742
4743 void InitGfx()
4744 {
4745   char *filename_font_initial = NULL;
4746   Bitmap *bitmap_font_initial = NULL;
4747   int font_height;
4748   int i, j;
4749
4750   /* determine settings for initial font (for displaying startup messages) */
4751   for (i = 0; image_config[i].token != NULL; i++)
4752   {
4753     for (j = 0; j < NUM_INITIAL_FONTS; j++)
4754     {
4755       char font_token[128];
4756       int len_font_token;
4757
4758       sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1);
4759       len_font_token = strlen(font_token);
4760
4761       if (strEqual(image_config[i].token, font_token))
4762         filename_font_initial = image_config[i].value;
4763       else if (strlen(image_config[i].token) > len_font_token &&
4764                strncmp(image_config[i].token, font_token, len_font_token) == 0)
4765       {
4766         if (strEqual(&image_config[i].token[len_font_token], ".x"))
4767           font_initial[j].src_x = atoi(image_config[i].value);
4768         else if (strEqual(&image_config[i].token[len_font_token], ".y"))
4769           font_initial[j].src_y = atoi(image_config[i].value);
4770         else if (strEqual(&image_config[i].token[len_font_token], ".width"))
4771           font_initial[j].width = atoi(image_config[i].value);
4772         else if (strEqual(&image_config[i].token[len_font_token],".height"))
4773           font_initial[j].height = atoi(image_config[i].value);
4774       }
4775     }
4776   }
4777
4778   for (j = 0; j < NUM_INITIAL_FONTS; j++)
4779   {
4780     font_initial[j].num_chars = DEFAULT_NUM_CHARS_PER_FONT;
4781     font_initial[j].num_chars_per_line = DEFAULT_NUM_CHARS_PER_LINE;
4782   }
4783
4784   if (filename_font_initial == NULL)    /* should not happen */
4785     Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
4786
4787   /* create additional image buffers for double-buffering and cross-fading */
4788   bitmap_db_cross = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
4789   bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
4790   bitmap_db_panel = CreateBitmap(DXSIZE, DYSIZE, DEFAULT_DEPTH);
4791   bitmap_db_door  = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
4792
4793   /* initialize screen properties */
4794   InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
4795                    REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
4796                    bitmap_db_field);
4797   InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
4798   InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
4799   InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
4800
4801   bitmap_font_initial = LoadCustomImage(filename_font_initial);
4802
4803   for (j = 0; j < NUM_INITIAL_FONTS; j++)
4804     font_initial[j].bitmap = bitmap_font_initial;
4805
4806   InitFontGraphicInfo();
4807
4808   font_height = getFontHeight(FC_RED);
4809
4810 #if 1
4811   DrawInitText(getWindowTitleString(), 20, FC_YELLOW);
4812 #else
4813   DrawInitText(getProgramInitString(), 20, FC_YELLOW);
4814 #endif
4815   DrawInitText(PROGRAM_COPYRIGHT_STRING, 50, FC_RED);
4816   DrawInitText(PROGRAM_WEBSITE_STRING, WIN_YSIZE - 20 - font_height, FC_RED);
4817
4818   DrawInitText("Loading graphics", 120, FC_GREEN);
4819 }
4820
4821 void RedrawBackground()
4822 {
4823   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
4824              0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
4825
4826   redraw_mask = REDRAW_ALL;
4827 }
4828
4829 void InitGfxBackground()
4830 {
4831   int x, y;
4832
4833   fieldbuffer = bitmap_db_field;
4834   SetDrawtoField(DRAW_BACKBUFFER);
4835
4836   RedrawBackground();
4837
4838   ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
4839   ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
4840
4841   for (x = 0; x < MAX_BUF_XSIZE; x++)
4842     for (y = 0; y < MAX_BUF_YSIZE; y++)
4843       redraw[x][y] = 0;
4844   redraw_tiles = 0;
4845   redraw_mask = REDRAW_ALL;
4846 }
4847
4848 static void InitLevelInfo()
4849 {
4850   LoadLevelInfo();                              /* global level info */
4851   LoadLevelSetup_LastSeries();                  /* last played series info */
4852   LoadLevelSetup_SeriesInfo();                  /* last played level info */
4853 }
4854
4855 void InitLevelArtworkInfo()
4856 {
4857   LoadLevelArtworkInfo();
4858 }
4859
4860 static void InitImages()
4861 {
4862   setLevelArtworkDir(artwork.gfx_first);
4863
4864 #if 0
4865   printf("::: InitImages for '%s' ['%s', '%s'] ['%s', '%s']\n",
4866          leveldir_current->identifier,
4867          artwork.gfx_current_identifier,
4868          artwork.gfx_current->identifier,
4869          leveldir_current->graphics_set,
4870          leveldir_current->graphics_path);
4871 #endif
4872
4873   ReloadCustomImages();
4874
4875   LoadCustomElementDescriptions();
4876   LoadSpecialMenuDesignSettings();
4877
4878   ReinitializeGraphics();
4879 }
4880
4881 static void InitSound(char *identifier)
4882 {
4883   if (identifier == NULL)
4884     identifier = artwork.snd_current->identifier;
4885
4886   /* set artwork path to send it to the sound server process */
4887   setLevelArtworkDir(artwork.snd_first);
4888
4889   InitReloadCustomSounds(identifier);
4890   ReinitializeSounds();
4891 }
4892
4893 static void InitMusic(char *identifier)
4894 {
4895   if (identifier == NULL)
4896     identifier = artwork.mus_current->identifier;
4897
4898   /* set artwork path to send it to the sound server process */
4899   setLevelArtworkDir(artwork.mus_first);
4900
4901   InitReloadCustomMusic(identifier);
4902   ReinitializeMusic();
4903 }
4904
4905 void InitNetworkServer()
4906 {
4907 #if defined(NETWORK_AVALIABLE)
4908   int nr_wanted;
4909 #endif
4910
4911   if (!options.network)
4912     return;
4913
4914 #if defined(NETWORK_AVALIABLE)
4915   nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
4916
4917   if (!ConnectToServer(options.server_host, options.server_port))
4918     Error(ERR_EXIT, "cannot connect to network game server");
4919
4920   SendToServer_PlayerName(setup.player_name);
4921   SendToServer_ProtocolVersion();
4922
4923   if (nr_wanted)
4924     SendToServer_NrWanted(nr_wanted);
4925 #endif
4926 }
4927
4928 static char *getNewArtworkIdentifier(int type)
4929 {
4930   static char *leveldir_current_identifier[3] = { NULL, NULL, NULL };
4931   static boolean last_override_level_artwork[3] = { FALSE, FALSE, FALSE };
4932   static boolean last_has_level_artwork_set[3] = { FALSE, FALSE, FALSE };
4933   static boolean initialized[3] = { FALSE, FALSE, FALSE };
4934   TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
4935   boolean setup_override_artwork = SETUP_OVERRIDE_ARTWORK(setup, type);
4936   char *setup_artwork_set = SETUP_ARTWORK_SET(setup, type);
4937   char *leveldir_identifier = leveldir_current->identifier;
4938 #if 1
4939   /* !!! setLevelArtworkDir() should be moved to an earlier stage !!! */
4940   char *leveldir_artwork_set = setLevelArtworkDir(artwork_first_node);
4941 #else
4942   char *leveldir_artwork_set = LEVELDIR_ARTWORK_SET(leveldir_current, type);
4943 #endif
4944   boolean has_level_artwork_set = (leveldir_artwork_set != NULL);
4945   char *artwork_current_identifier;
4946   char *artwork_new_identifier = NULL;  /* default: nothing has changed */
4947
4948   /* leveldir_current may be invalid (level group, parent link) */
4949   if (!validLevelSeries(leveldir_current))
4950     return NULL;
4951
4952   /* 1st step: determine artwork set to be activated in descending order:
4953      --------------------------------------------------------------------
4954      1. setup artwork (when configured to override everything else)
4955      2. artwork set configured in "levelinfo.conf" of current level set
4956         (artwork in level directory will have priority when loading later)
4957      3. artwork in level directory (stored in artwork sub-directory)
4958      4. setup artwork (currently configured in setup menu) */
4959
4960   if (setup_override_artwork)
4961     artwork_current_identifier = setup_artwork_set;
4962   else if (leveldir_artwork_set != NULL)
4963     artwork_current_identifier = leveldir_artwork_set;
4964   else if (getTreeInfoFromIdentifier(artwork_first_node, leveldir_identifier))
4965     artwork_current_identifier = leveldir_identifier;
4966   else
4967     artwork_current_identifier = setup_artwork_set;
4968
4969
4970   /* 2nd step: check if it is really needed to reload artwork set
4971      ------------------------------------------------------------ */
4972
4973 #if 0
4974   if (type == ARTWORK_TYPE_GRAPHICS)
4975     printf("::: 0: '%s' ['%s', '%s'] ['%s' ('%s')]\n",
4976            artwork_new_identifier,
4977            ARTWORK_CURRENT_IDENTIFIER(artwork, type),
4978            artwork_current_identifier,
4979            leveldir_current->graphics_set,
4980            leveldir_current->identifier);
4981 #endif
4982
4983   /* ---------- reload if level set and also artwork set has changed ------- */
4984   if (leveldir_current_identifier[type] != leveldir_identifier &&
4985       (last_has_level_artwork_set[type] || has_level_artwork_set))
4986     artwork_new_identifier = artwork_current_identifier;
4987
4988   leveldir_current_identifier[type] = leveldir_identifier;
4989   last_has_level_artwork_set[type] = has_level_artwork_set;
4990
4991 #if 0
4992   if (type == ARTWORK_TYPE_GRAPHICS)
4993     printf("::: 1: '%s'\n", artwork_new_identifier);
4994 #endif
4995
4996   /* ---------- reload if "override artwork" setting has changed ----------- */
4997   if (last_override_level_artwork[type] != setup_override_artwork)
4998     artwork_new_identifier = artwork_current_identifier;
4999
5000   last_override_level_artwork[type] = setup_override_artwork;
5001
5002 #if 0
5003   if (type == ARTWORK_TYPE_GRAPHICS)
5004     printf("::: 2: '%s'\n", artwork_new_identifier);
5005 #endif
5006
5007   /* ---------- reload if current artwork identifier has changed ----------- */
5008   if (!strEqual(ARTWORK_CURRENT_IDENTIFIER(artwork, type),
5009                 artwork_current_identifier))
5010     artwork_new_identifier = artwork_current_identifier;
5011
5012   *(ARTWORK_CURRENT_IDENTIFIER_PTR(artwork, type))= artwork_current_identifier;
5013
5014 #if 0
5015   if (type == ARTWORK_TYPE_GRAPHICS)
5016     printf("::: 3: '%s'\n", artwork_new_identifier);
5017 #endif
5018
5019   /* ---------- do not reload directly after starting ---------------------- */
5020   if (!initialized[type])
5021     artwork_new_identifier = NULL;
5022
5023   initialized[type] = TRUE;
5024
5025 #if 0
5026   if (type == ARTWORK_TYPE_GRAPHICS)
5027     printf("::: 4: '%s'\n", artwork_new_identifier);
5028 #endif
5029
5030 #if 0
5031   if (type == ARTWORK_TYPE_GRAPHICS)
5032     printf("CHECKING OLD/NEW GFX:\n- OLD: %s\n- NEW: %s ['%s', '%s'] ['%s']\n",
5033            artwork.gfx_current_identifier, artwork_current_identifier,
5034            artwork.gfx_current->identifier, leveldir_current->graphics_set,
5035            artwork_new_identifier);
5036 #endif
5037
5038   return artwork_new_identifier;
5039 }
5040
5041 void ReloadCustomArtwork(int force_reload)
5042 {
5043   char *gfx_new_identifier;
5044   char *snd_new_identifier;
5045   char *mus_new_identifier;
5046   boolean force_reload_gfx = (force_reload & (1 << ARTWORK_TYPE_GRAPHICS));
5047   boolean force_reload_snd = (force_reload & (1 << ARTWORK_TYPE_SOUNDS));
5048   boolean force_reload_mus = (force_reload & (1 << ARTWORK_TYPE_MUSIC));
5049   boolean redraw_screen = FALSE;
5050
5051   force_reload_gfx |= AdjustGraphicsForEMC();
5052
5053   gfx_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_GRAPHICS);
5054   snd_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_SOUNDS);
5055   mus_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_MUSIC);
5056
5057   if (gfx_new_identifier != NULL || force_reload_gfx)
5058   {
5059 #if 0
5060     printf("RELOADING GRAPHICS '%s' -> '%s' ['%s', '%s']\n",
5061            artwork.gfx_current_identifier,
5062            gfx_new_identifier,
5063            artwork.gfx_current->identifier,
5064            leveldir_current->graphics_set);
5065 #endif
5066
5067     ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
5068
5069     InitImages();
5070
5071     redraw_screen = TRUE;
5072   }
5073
5074   if (snd_new_identifier != NULL || force_reload_snd)
5075   {
5076     ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
5077
5078     InitSound(snd_new_identifier);
5079
5080     redraw_screen = TRUE;
5081   }
5082
5083   if (mus_new_identifier != NULL || force_reload_mus)
5084   {
5085     ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
5086
5087     InitMusic(mus_new_identifier);
5088
5089     redraw_screen = TRUE;
5090   }
5091
5092   if (redraw_screen)
5093   {
5094     RedrawBackground();
5095
5096     /* force redraw of (open or closed) door graphics */
5097     SetDoorState(DOOR_OPEN_ALL);
5098     CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
5099   }
5100 }
5101
5102 void KeyboardAutoRepeatOffUnlessAutoplay()
5103 {
5104   if (global.autoplay_leveldir == NULL)
5105     KeyboardAutoRepeatOff();
5106 }
5107
5108
5109 /* ========================================================================= */
5110 /* OpenAll()                                                                 */
5111 /* ========================================================================= */
5112
5113 void OpenAll()
5114 {
5115   InitGlobal();                 /* initialize some global variables */
5116
5117   if (options.execute_command)
5118     Execute_Command(options.execute_command);
5119
5120   if (options.serveronly)
5121   {
5122 #if defined(PLATFORM_UNIX)
5123     NetworkServer(options.server_port, options.serveronly);
5124 #else
5125     Error(ERR_WARN, "networking only supported in Unix version");
5126 #endif
5127
5128     exit(0);                    /* never reached, server loops forever */
5129   }
5130
5131   InitSetup();
5132
5133   InitGameInfo();
5134   InitPlayerInfo();
5135   InitArtworkInfo();            /* needed before loading gfx, sound & music */
5136   InitArtworkConfig();          /* needed before forking sound child process */
5137   InitMixer();
5138
5139   InitCounter();
5140
5141   InitRND(NEW_RANDOMIZE);
5142   InitSimpleRandom(NEW_RANDOMIZE);
5143
5144   InitJoysticks();
5145
5146   InitVideoDisplay();
5147   InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
5148
5149   InitEventFilter(FilterMouseMotionEvents);
5150
5151   InitElementPropertiesStatic();
5152   InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
5153
5154   InitGfx();
5155
5156   // debug_print_timestamp(0, "INIT");
5157   InitLevelInfo();
5158   // debug_print_timestamp(0, "TIME InitLevelInfo:        ");
5159   InitLevelArtworkInfo();
5160   // debug_print_timestamp(0, "TIME InitLevelArtworkInfo: ");
5161
5162   InitImages();                 /* needs to know current level directory */
5163   InitSound(NULL);              /* needs to know current level directory */
5164   InitMusic(NULL);              /* needs to know current level directory */
5165
5166   InitGfxBackground();
5167
5168 #if 1
5169   em_open_all();
5170 #endif
5171
5172   if (global.autoplay_leveldir)
5173   {
5174     AutoPlayTape();
5175     return;
5176   }
5177   else if (global.convert_leveldir)
5178   {
5179     ConvertLevels();
5180     return;
5181   }
5182
5183   game_status = GAME_MODE_MAIN;
5184
5185   DrawMainMenu();
5186
5187   InitNetworkServer();
5188 }
5189
5190 void CloseAllAndExit(int exit_value)
5191 {
5192   StopSounds();
5193   FreeAllSounds();
5194   FreeAllMusic();
5195   CloseAudio();         /* called after freeing sounds (needed for SDL) */
5196
5197 #if 1
5198   em_close_all();
5199 #endif
5200
5201   FreeAllImages();
5202
5203 #if defined(TARGET_SDL)
5204   if (network_server)   /* terminate network server */
5205     SDL_KillThread(server_thread);
5206 #endif
5207
5208   CloseVideoDisplay();
5209   ClosePlatformDependentStuff();
5210
5211   if (exit_value != 0)
5212     NotifyUserAboutErrorFile();
5213
5214   exit(exit_value);
5215 }