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