0521c3b7d5b3852e5d2ae4ade8c3589b7b6ea622
[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_RETURN, "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_RETURN_LINE, "-");
1196     Error(ERR_RETURN, "warning: error found in config file:");
1197     Error(ERR_RETURN, "- config file: '%s'", getImageConfigFilename());
1198     Error(ERR_RETURN, "- config token: '%s'", getTokenFromImageID(graphic));
1199     Error(ERR_RETURN, "error: loop discovered when resolving cloned graphics");
1200     Error(ERR_RETURN, "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_RETURN, "fallback done to 'char_exclam' for this graphic");
1206     Error(ERR_RETURN_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_RETURN_LINE, "-");
1348       Error(ERR_RETURN, "warning: error found in config file:");
1349       Error(ERR_RETURN, "- config file: '%s'", getImageConfigFilename());
1350       Error(ERR_RETURN, "- config token: '%s'", getTokenFromImageID(i));
1351       Error(ERR_RETURN, "- image file: '%s'", src_bitmap->source_filename);
1352       Error(ERR_RETURN,
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_RETURN, "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_RETURN, "fallback done to 'char_exclam' for this graphic");
1361       Error(ERR_RETURN_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_RETURN_LINE, "-");
1376       Error(ERR_RETURN, "warning: error found in config file:");
1377       Error(ERR_RETURN, "- config file: '%s'", getImageConfigFilename());
1378       Error(ERR_RETURN, "- config token: '%s'", getTokenFromImageID(i));
1379       Error(ERR_RETURN, "- image file: '%s'", src_bitmap->source_filename);
1380       Error(ERR_RETURN,
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_RETURN, "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_RETURN, "fallback done to 'char_exclam' for this graphic");
1389       Error(ERR_RETURN_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 resolve_group_element(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_element - EL_GROUP_START;
1993
1994     group->num_elements_resolved = 0;
1995     group->choice_pos = 0;
1996   }
1997
1998   for (i = 0; i < actual_group->num_elements; i++)
1999   {
2000     int element = actual_group->element[i];
2001
2002     if (group->num_elements_resolved == NUM_FILE_ELEMENTS)
2003       break;
2004
2005     if (IS_GROUP_ELEMENT(element))
2006       resolve_group_element(element, recursion_depth + 1);
2007     else
2008     {
2009       group->element_resolved[group->num_elements_resolved++] = element;
2010       element_info[element].in_group[group_nr] = TRUE;
2011     }
2012   }
2013 }
2014
2015 void InitElementPropertiesStatic()
2016 {
2017   static int ep_diggable[] =
2018   {
2019     EL_SAND,
2020     EL_SP_BASE,
2021     EL_SP_BUGGY_BASE,
2022     EL_SP_BUGGY_BASE_ACTIVATING,
2023     EL_TRAP,
2024     EL_INVISIBLE_SAND,
2025     EL_INVISIBLE_SAND_ACTIVE,
2026     EL_EMC_GRASS,
2027
2028     /* !!! currently not diggable, but handled by 'ep_dont_run_into' !!! */
2029     /* (if amoeba can grow into anything diggable, maybe keep these out) */
2030 #if 0
2031     EL_LANDMINE,
2032     EL_DC_LANDMINE,
2033     EL_TRAP_ACTIVE,
2034     EL_SP_BUGGY_BASE_ACTIVE,
2035     EL_EMC_PLANT,
2036 #endif
2037
2038     -1
2039   };
2040
2041   static int ep_collectible_only[] =
2042   {
2043     EL_BD_DIAMOND,
2044     EL_EMERALD,
2045     EL_DIAMOND,
2046     EL_EMERALD_YELLOW,
2047     EL_EMERALD_RED,
2048     EL_EMERALD_PURPLE,
2049     EL_KEY_1,
2050     EL_KEY_2,
2051     EL_KEY_3,
2052     EL_KEY_4,
2053     EL_EM_KEY_1,
2054     EL_EM_KEY_2,
2055     EL_EM_KEY_3,
2056     EL_EM_KEY_4,
2057     EL_EMC_KEY_5,
2058     EL_EMC_KEY_6,
2059     EL_EMC_KEY_7,
2060     EL_EMC_KEY_8,
2061     EL_DYNAMITE,
2062     EL_EM_DYNAMITE,
2063     EL_DYNABOMB_INCREASE_NUMBER,
2064     EL_DYNABOMB_INCREASE_SIZE,
2065     EL_DYNABOMB_INCREASE_POWER,
2066     EL_SP_INFOTRON,
2067     EL_SP_DISK_RED,
2068     EL_PEARL,
2069     EL_CRYSTAL,
2070     EL_DC_KEY_WHITE,
2071     EL_SHIELD_NORMAL,
2072     EL_SHIELD_DEADLY,
2073     EL_EXTRA_TIME,
2074     EL_ENVELOPE_1,
2075     EL_ENVELOPE_2,
2076     EL_ENVELOPE_3,
2077     EL_ENVELOPE_4,
2078     EL_SPEED_PILL,
2079     EL_EMC_LENSES,
2080     EL_EMC_MAGNIFIER,
2081
2082 #if 0
2083     /* !!! handle separately !!! */
2084     EL_DC_LANDMINE,     /* deadly when running into, but can be snapped */
2085 #endif
2086
2087     -1
2088   };
2089
2090   static int ep_dont_run_into[] =
2091   {
2092     /* same elements as in 'ep_dont_touch' */
2093     EL_BUG,
2094     EL_SPACESHIP,
2095     EL_BD_BUTTERFLY,
2096     EL_BD_FIREFLY,
2097
2098     /* same elements as in 'ep_dont_collide_with' */
2099     EL_YAMYAM,
2100     EL_DARK_YAMYAM,
2101     EL_ROBOT,
2102     EL_PACMAN,
2103     EL_SP_SNIKSNAK,
2104     EL_SP_ELECTRON,
2105
2106     /* new elements */
2107     EL_AMOEBA_DROP,
2108     EL_ACID,
2109
2110     /* !!! maybe this should better be handled by 'ep_diggable' !!! */
2111 #if 1
2112     EL_LANDMINE,
2113     EL_DC_LANDMINE,
2114     EL_TRAP_ACTIVE,
2115     EL_SP_BUGGY_BASE_ACTIVE,
2116     EL_EMC_PLANT,
2117 #endif
2118
2119     -1
2120   };
2121
2122   static int ep_dont_collide_with[] =
2123   {
2124     /* same elements as in 'ep_dont_touch' */
2125     EL_BUG,
2126     EL_SPACESHIP,
2127     EL_BD_BUTTERFLY,
2128     EL_BD_FIREFLY,
2129
2130     /* new elements */
2131     EL_YAMYAM,
2132     EL_DARK_YAMYAM,
2133     EL_ROBOT,
2134     EL_PACMAN,
2135     EL_SP_SNIKSNAK,
2136     EL_SP_ELECTRON,
2137
2138     -1
2139   };
2140
2141   static int ep_dont_touch[] =
2142   {
2143     EL_BUG,
2144     EL_SPACESHIP,
2145     EL_BD_BUTTERFLY,
2146     EL_BD_FIREFLY,
2147
2148     -1
2149   };
2150
2151   static int ep_indestructible[] =
2152   {
2153     EL_STEELWALL,
2154     EL_ACID,
2155     EL_ACID_POOL_TOPLEFT,
2156     EL_ACID_POOL_TOPRIGHT,
2157     EL_ACID_POOL_BOTTOMLEFT,
2158     EL_ACID_POOL_BOTTOM,
2159     EL_ACID_POOL_BOTTOMRIGHT,
2160     EL_SP_HARDWARE_GRAY,
2161     EL_SP_HARDWARE_GREEN,
2162     EL_SP_HARDWARE_BLUE,
2163     EL_SP_HARDWARE_RED,
2164     EL_SP_HARDWARE_YELLOW,
2165     EL_SP_HARDWARE_BASE_1,
2166     EL_SP_HARDWARE_BASE_2,
2167     EL_SP_HARDWARE_BASE_3,
2168     EL_SP_HARDWARE_BASE_4,
2169     EL_SP_HARDWARE_BASE_5,
2170     EL_SP_HARDWARE_BASE_6,
2171     EL_INVISIBLE_STEELWALL,
2172     EL_INVISIBLE_STEELWALL_ACTIVE,
2173     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2174     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2175     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2176     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2177     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2178     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2179     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2180     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2181     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2182     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2183     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2184     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2185     EL_LIGHT_SWITCH,
2186     EL_LIGHT_SWITCH_ACTIVE,
2187     EL_SIGN_EXCLAMATION,
2188     EL_SIGN_RADIOACTIVITY,
2189     EL_SIGN_STOP,
2190     EL_SIGN_WHEELCHAIR,
2191     EL_SIGN_PARKING,
2192     EL_SIGN_NO_ENTRY,
2193     EL_SIGN_UNUSED_1,
2194     EL_SIGN_GIVE_WAY,
2195     EL_SIGN_ENTRY_FORBIDDEN,
2196     EL_SIGN_EMERGENCY_EXIT,
2197     EL_SIGN_YIN_YANG,
2198     EL_SIGN_UNUSED_2,
2199     EL_SIGN_SPERMS,
2200     EL_SIGN_BULLET,
2201     EL_SIGN_HEART,
2202     EL_SIGN_CROSS,
2203     EL_SIGN_FRANKIE,
2204     EL_STEEL_EXIT_CLOSED,
2205     EL_STEEL_EXIT_OPEN,
2206     EL_EM_STEEL_EXIT_CLOSED,
2207     EL_EM_STEEL_EXIT_OPEN,
2208     EL_DC_STEELWALL_1_LEFT,
2209     EL_DC_STEELWALL_1_RIGHT,
2210     EL_DC_STEELWALL_1_TOP,
2211     EL_DC_STEELWALL_1_BOTTOM,
2212     EL_DC_STEELWALL_1_HORIZONTAL,
2213     EL_DC_STEELWALL_1_VERTICAL,
2214     EL_DC_STEELWALL_1_TOPLEFT,
2215     EL_DC_STEELWALL_1_TOPRIGHT,
2216     EL_DC_STEELWALL_1_BOTTOMLEFT,
2217     EL_DC_STEELWALL_1_BOTTOMRIGHT,
2218     EL_DC_STEELWALL_1_TOPLEFT_2,
2219     EL_DC_STEELWALL_1_TOPRIGHT_2,
2220     EL_DC_STEELWALL_1_BOTTOMLEFT_2,
2221     EL_DC_STEELWALL_1_BOTTOMRIGHT_2,
2222     EL_DC_STEELWALL_2_LEFT,
2223     EL_DC_STEELWALL_2_RIGHT,
2224     EL_DC_STEELWALL_2_TOP,
2225     EL_DC_STEELWALL_2_BOTTOM,
2226     EL_DC_STEELWALL_2_HORIZONTAL,
2227     EL_DC_STEELWALL_2_VERTICAL,
2228     EL_DC_STEELWALL_2_MIDDLE,
2229     EL_DC_STEELWALL_2_SINGLE,
2230     EL_STEELWALL_SLIPPERY,
2231     EL_EMC_STEELWALL_1,
2232     EL_EMC_STEELWALL_2,
2233     EL_EMC_STEELWALL_3,
2234     EL_EMC_STEELWALL_4,
2235     EL_CRYSTAL,
2236     EL_GATE_1,
2237     EL_GATE_2,
2238     EL_GATE_3,
2239     EL_GATE_4,
2240     EL_GATE_1_GRAY,
2241     EL_GATE_2_GRAY,
2242     EL_GATE_3_GRAY,
2243     EL_GATE_4_GRAY,
2244     EL_GATE_1_GRAY_ACTIVE,
2245     EL_GATE_2_GRAY_ACTIVE,
2246     EL_GATE_3_GRAY_ACTIVE,
2247     EL_GATE_4_GRAY_ACTIVE,
2248     EL_EM_GATE_1,
2249     EL_EM_GATE_2,
2250     EL_EM_GATE_3,
2251     EL_EM_GATE_4,
2252     EL_EM_GATE_1_GRAY,
2253     EL_EM_GATE_2_GRAY,
2254     EL_EM_GATE_3_GRAY,
2255     EL_EM_GATE_4_GRAY,
2256     EL_EM_GATE_1_GRAY_ACTIVE,
2257     EL_EM_GATE_2_GRAY_ACTIVE,
2258     EL_EM_GATE_3_GRAY_ACTIVE,
2259     EL_EM_GATE_4_GRAY_ACTIVE,
2260     EL_EMC_GATE_5,
2261     EL_EMC_GATE_6,
2262     EL_EMC_GATE_7,
2263     EL_EMC_GATE_8,
2264     EL_EMC_GATE_5_GRAY,
2265     EL_EMC_GATE_6_GRAY,
2266     EL_EMC_GATE_7_GRAY,
2267     EL_EMC_GATE_8_GRAY,
2268     EL_EMC_GATE_5_GRAY_ACTIVE,
2269     EL_EMC_GATE_6_GRAY_ACTIVE,
2270     EL_EMC_GATE_7_GRAY_ACTIVE,
2271     EL_EMC_GATE_8_GRAY_ACTIVE,
2272     EL_DC_GATE_WHITE,
2273     EL_DC_GATE_WHITE_GRAY,
2274     EL_DC_GATE_WHITE_GRAY_ACTIVE,
2275     EL_DC_GATE_FAKE_GRAY,
2276     EL_SWITCHGATE_OPEN,
2277     EL_SWITCHGATE_OPENING,
2278     EL_SWITCHGATE_CLOSED,
2279     EL_SWITCHGATE_CLOSING,
2280 #if 1
2281     EL_DC_SWITCHGATE_SWITCH_UP,
2282     EL_DC_SWITCHGATE_SWITCH_DOWN,
2283 #endif
2284     EL_TIMEGATE_OPEN,
2285     EL_TIMEGATE_OPENING,
2286     EL_TIMEGATE_CLOSED,
2287     EL_TIMEGATE_CLOSING,
2288 #if 1
2289     EL_DC_TIMEGATE_SWITCH,
2290     EL_DC_TIMEGATE_SWITCH_ACTIVE,
2291 #endif
2292     EL_TUBE_ANY,
2293     EL_TUBE_VERTICAL,
2294     EL_TUBE_HORIZONTAL,
2295     EL_TUBE_VERTICAL_LEFT,
2296     EL_TUBE_VERTICAL_RIGHT,
2297     EL_TUBE_HORIZONTAL_UP,
2298     EL_TUBE_HORIZONTAL_DOWN,
2299     EL_TUBE_LEFT_UP,
2300     EL_TUBE_LEFT_DOWN,
2301     EL_TUBE_RIGHT_UP,
2302     EL_TUBE_RIGHT_DOWN,
2303     EL_EXPANDABLE_STEELWALL_HORIZONTAL,
2304     EL_EXPANDABLE_STEELWALL_VERTICAL,
2305     EL_EXPANDABLE_STEELWALL_ANY,
2306
2307     -1
2308   };
2309
2310   static int ep_slippery[] =
2311   {
2312     EL_WALL_SLIPPERY,
2313     EL_BD_WALL,
2314     EL_ROCK,
2315     EL_BD_ROCK,
2316     EL_EMERALD,
2317     EL_BD_DIAMOND,
2318     EL_EMERALD_YELLOW,
2319     EL_EMERALD_RED,
2320     EL_EMERALD_PURPLE,
2321     EL_DIAMOND,
2322     EL_BOMB,
2323     EL_NUT,
2324     EL_ROBOT_WHEEL_ACTIVE,
2325     EL_ROBOT_WHEEL,
2326     EL_TIME_ORB_FULL,
2327     EL_TIME_ORB_EMPTY,
2328     EL_LAMP_ACTIVE,
2329     EL_LAMP,
2330     EL_ACID_POOL_TOPLEFT,
2331     EL_ACID_POOL_TOPRIGHT,
2332     EL_SATELLITE,
2333     EL_SP_ZONK,
2334     EL_SP_INFOTRON,
2335     EL_SP_CHIP_SINGLE,
2336     EL_SP_CHIP_LEFT,
2337     EL_SP_CHIP_RIGHT,
2338     EL_SP_CHIP_TOP,
2339     EL_SP_CHIP_BOTTOM,
2340     EL_SPEED_PILL,
2341     EL_STEELWALL_SLIPPERY,
2342     EL_PEARL,
2343     EL_CRYSTAL,
2344     EL_EMC_WALL_SLIPPERY_1,
2345     EL_EMC_WALL_SLIPPERY_2,
2346     EL_EMC_WALL_SLIPPERY_3,
2347     EL_EMC_WALL_SLIPPERY_4,
2348     EL_EMC_MAGIC_BALL,
2349     EL_EMC_MAGIC_BALL_ACTIVE,
2350
2351     -1
2352   };
2353
2354   static int ep_can_change[] =
2355   {
2356     -1
2357   };
2358
2359   static int ep_can_move[] =
2360   {
2361     /* same elements as in 'pb_can_move_into_acid' */
2362     EL_BUG,
2363     EL_SPACESHIP,
2364     EL_BD_BUTTERFLY,
2365     EL_BD_FIREFLY,
2366     EL_YAMYAM,
2367     EL_DARK_YAMYAM,
2368     EL_ROBOT,
2369     EL_PACMAN,
2370     EL_MOLE,
2371     EL_PENGUIN,
2372     EL_PIG,
2373     EL_DRAGON,
2374     EL_SATELLITE,
2375     EL_SP_SNIKSNAK,
2376     EL_SP_ELECTRON,
2377     EL_BALLOON,
2378     EL_SPRING,
2379     EL_EMC_ANDROID,
2380
2381     -1
2382   };
2383
2384   static int ep_can_fall[] =
2385   {
2386     EL_ROCK,
2387     EL_BD_ROCK,
2388     EL_EMERALD,
2389     EL_BD_DIAMOND,
2390     EL_EMERALD_YELLOW,
2391     EL_EMERALD_RED,
2392     EL_EMERALD_PURPLE,
2393     EL_DIAMOND,
2394     EL_BOMB,
2395     EL_NUT,
2396     EL_AMOEBA_DROP,
2397     EL_QUICKSAND_FULL,
2398     EL_QUICKSAND_FAST_FULL,
2399     EL_MAGIC_WALL_FULL,
2400     EL_BD_MAGIC_WALL_FULL,
2401     EL_DC_MAGIC_WALL_FULL,
2402     EL_TIME_ORB_FULL,
2403     EL_TIME_ORB_EMPTY,
2404     EL_SP_ZONK,
2405     EL_SP_INFOTRON,
2406     EL_SP_DISK_ORANGE,
2407     EL_PEARL,
2408     EL_CRYSTAL,
2409     EL_SPRING,
2410     EL_DX_SUPABOMB,
2411
2412     -1
2413   };
2414
2415   static int ep_can_smash_player[] =
2416   {
2417     EL_ROCK,
2418     EL_BD_ROCK,
2419     EL_EMERALD,
2420     EL_BD_DIAMOND,
2421     EL_EMERALD_YELLOW,
2422     EL_EMERALD_RED,
2423     EL_EMERALD_PURPLE,
2424     EL_DIAMOND,
2425     EL_BOMB,
2426     EL_NUT,
2427     EL_AMOEBA_DROP,
2428     EL_TIME_ORB_FULL,
2429     EL_TIME_ORB_EMPTY,
2430     EL_SP_ZONK,
2431     EL_SP_INFOTRON,
2432     EL_SP_DISK_ORANGE,
2433     EL_PEARL,
2434     EL_CRYSTAL,
2435     EL_SPRING,
2436     EL_DX_SUPABOMB,
2437
2438     -1
2439   };
2440
2441   static int ep_can_smash_enemies[] =
2442   {
2443     EL_ROCK,
2444     EL_BD_ROCK,
2445     EL_SP_ZONK,
2446
2447     -1
2448   };
2449
2450   static int ep_can_smash_everything[] =
2451   {
2452     EL_ROCK,
2453     EL_BD_ROCK,
2454     EL_SP_ZONK,
2455
2456     -1
2457   };
2458
2459   static int ep_explodes_by_fire[] =
2460   {
2461     /* same elements as in 'ep_explodes_impact' */
2462     EL_BOMB,
2463     EL_SP_DISK_ORANGE,
2464     EL_DX_SUPABOMB,
2465
2466     /* same elements as in 'ep_explodes_smashed' */
2467     EL_SATELLITE,
2468     EL_PIG,
2469     EL_DRAGON,
2470     EL_MOLE,
2471
2472     /* new elements */
2473     EL_DYNAMITE,
2474     EL_DYNAMITE_ACTIVE,
2475     EL_EM_DYNAMITE,
2476     EL_EM_DYNAMITE_ACTIVE,
2477     EL_DYNABOMB_PLAYER_1_ACTIVE,
2478     EL_DYNABOMB_PLAYER_2_ACTIVE,
2479     EL_DYNABOMB_PLAYER_3_ACTIVE,
2480     EL_DYNABOMB_PLAYER_4_ACTIVE,
2481     EL_DYNABOMB_INCREASE_NUMBER,
2482     EL_DYNABOMB_INCREASE_SIZE,
2483     EL_DYNABOMB_INCREASE_POWER,
2484     EL_SP_DISK_RED_ACTIVE,
2485     EL_BUG,
2486     EL_PENGUIN,
2487     EL_SP_DISK_RED,
2488     EL_SP_DISK_YELLOW,
2489     EL_SP_SNIKSNAK,
2490     EL_SP_ELECTRON,
2491 #if 0
2492     EL_BLACK_ORB,
2493 #endif
2494
2495     -1
2496   };
2497
2498   static int ep_explodes_smashed[] =
2499   {
2500     /* same elements as in 'ep_explodes_impact' */
2501     EL_BOMB,
2502     EL_SP_DISK_ORANGE,
2503     EL_DX_SUPABOMB,
2504
2505     /* new elements */
2506     EL_SATELLITE,
2507     EL_PIG,
2508     EL_DRAGON,
2509     EL_MOLE,
2510
2511     -1
2512   };
2513
2514   static int ep_explodes_impact[] =
2515   {
2516     EL_BOMB,
2517     EL_SP_DISK_ORANGE,
2518     EL_DX_SUPABOMB,
2519
2520     -1
2521   };
2522
2523   static int ep_walkable_over[] =
2524   {
2525     EL_EMPTY_SPACE,
2526     EL_SP_EMPTY_SPACE,
2527     EL_SOKOBAN_FIELD_EMPTY,
2528     EL_EXIT_OPEN,
2529     EL_EM_EXIT_OPEN,
2530     EL_SP_EXIT_OPEN,
2531     EL_SP_EXIT_OPENING,
2532     EL_STEEL_EXIT_OPEN,
2533     EL_EM_STEEL_EXIT_OPEN,
2534     EL_GATE_1,
2535     EL_GATE_2,
2536     EL_GATE_3,
2537     EL_GATE_4,
2538     EL_GATE_1_GRAY,
2539     EL_GATE_2_GRAY,
2540     EL_GATE_3_GRAY,
2541     EL_GATE_4_GRAY,
2542     EL_GATE_1_GRAY_ACTIVE,
2543     EL_GATE_2_GRAY_ACTIVE,
2544     EL_GATE_3_GRAY_ACTIVE,
2545     EL_GATE_4_GRAY_ACTIVE,
2546     EL_PENGUIN,
2547     EL_PIG,
2548     EL_DRAGON,
2549
2550     -1
2551   };
2552
2553   static int ep_walkable_inside[] =
2554   {
2555     EL_TUBE_ANY,
2556     EL_TUBE_VERTICAL,
2557     EL_TUBE_HORIZONTAL,
2558     EL_TUBE_VERTICAL_LEFT,
2559     EL_TUBE_VERTICAL_RIGHT,
2560     EL_TUBE_HORIZONTAL_UP,
2561     EL_TUBE_HORIZONTAL_DOWN,
2562     EL_TUBE_LEFT_UP,
2563     EL_TUBE_LEFT_DOWN,
2564     EL_TUBE_RIGHT_UP,
2565     EL_TUBE_RIGHT_DOWN,
2566
2567     -1
2568   };
2569
2570   static int ep_walkable_under[] =
2571   {
2572     -1
2573   };
2574
2575   static int ep_passable_over[] =
2576   {
2577     EL_EM_GATE_1,
2578     EL_EM_GATE_2,
2579     EL_EM_GATE_3,
2580     EL_EM_GATE_4,
2581     EL_EM_GATE_1_GRAY,
2582     EL_EM_GATE_2_GRAY,
2583     EL_EM_GATE_3_GRAY,
2584     EL_EM_GATE_4_GRAY,
2585     EL_EM_GATE_1_GRAY_ACTIVE,
2586     EL_EM_GATE_2_GRAY_ACTIVE,
2587     EL_EM_GATE_3_GRAY_ACTIVE,
2588     EL_EM_GATE_4_GRAY_ACTIVE,
2589     EL_EMC_GATE_5,
2590     EL_EMC_GATE_6,
2591     EL_EMC_GATE_7,
2592     EL_EMC_GATE_8,
2593     EL_EMC_GATE_5_GRAY,
2594     EL_EMC_GATE_6_GRAY,
2595     EL_EMC_GATE_7_GRAY,
2596     EL_EMC_GATE_8_GRAY,
2597     EL_EMC_GATE_5_GRAY_ACTIVE,
2598     EL_EMC_GATE_6_GRAY_ACTIVE,
2599     EL_EMC_GATE_7_GRAY_ACTIVE,
2600     EL_EMC_GATE_8_GRAY_ACTIVE,
2601     EL_DC_GATE_WHITE,
2602     EL_DC_GATE_WHITE_GRAY,
2603     EL_DC_GATE_WHITE_GRAY_ACTIVE,
2604     EL_SWITCHGATE_OPEN,
2605     EL_TIMEGATE_OPEN,
2606
2607     -1
2608   };
2609
2610   static int ep_passable_inside[] =
2611   {
2612     EL_SP_PORT_LEFT,
2613     EL_SP_PORT_RIGHT,
2614     EL_SP_PORT_UP,
2615     EL_SP_PORT_DOWN,
2616     EL_SP_PORT_HORIZONTAL,
2617     EL_SP_PORT_VERTICAL,
2618     EL_SP_PORT_ANY,
2619     EL_SP_GRAVITY_PORT_LEFT,
2620     EL_SP_GRAVITY_PORT_RIGHT,
2621     EL_SP_GRAVITY_PORT_UP,
2622     EL_SP_GRAVITY_PORT_DOWN,
2623     EL_SP_GRAVITY_ON_PORT_LEFT,
2624     EL_SP_GRAVITY_ON_PORT_RIGHT,
2625     EL_SP_GRAVITY_ON_PORT_UP,
2626     EL_SP_GRAVITY_ON_PORT_DOWN,
2627     EL_SP_GRAVITY_OFF_PORT_LEFT,
2628     EL_SP_GRAVITY_OFF_PORT_RIGHT,
2629     EL_SP_GRAVITY_OFF_PORT_UP,
2630     EL_SP_GRAVITY_OFF_PORT_DOWN,
2631
2632     -1
2633   };
2634
2635   static int ep_passable_under[] =
2636   {
2637     -1
2638   };
2639
2640   static int ep_droppable[] =
2641   {
2642     -1
2643   };
2644
2645   static int ep_explodes_1x1_old[] =
2646   {
2647     -1
2648   };
2649
2650   static int ep_pushable[] =
2651   {
2652     EL_ROCK,
2653     EL_BOMB,
2654     EL_DX_SUPABOMB,
2655     EL_NUT,
2656     EL_TIME_ORB_EMPTY,
2657     EL_SP_ZONK,
2658     EL_SP_DISK_ORANGE,
2659     EL_SPRING,
2660     EL_BD_ROCK,
2661     EL_SOKOBAN_OBJECT,
2662     EL_SOKOBAN_FIELD_FULL,
2663     EL_SATELLITE,
2664     EL_SP_DISK_YELLOW,
2665     EL_BALLOON,
2666     EL_EMC_ANDROID,
2667
2668     -1
2669   };
2670
2671   static int ep_explodes_cross_old[] =
2672   {
2673     -1
2674   };
2675
2676   static int ep_protected[] =
2677   {
2678     /* same elements as in 'ep_walkable_inside' */
2679     EL_TUBE_ANY,
2680     EL_TUBE_VERTICAL,
2681     EL_TUBE_HORIZONTAL,
2682     EL_TUBE_VERTICAL_LEFT,
2683     EL_TUBE_VERTICAL_RIGHT,
2684     EL_TUBE_HORIZONTAL_UP,
2685     EL_TUBE_HORIZONTAL_DOWN,
2686     EL_TUBE_LEFT_UP,
2687     EL_TUBE_LEFT_DOWN,
2688     EL_TUBE_RIGHT_UP,
2689     EL_TUBE_RIGHT_DOWN,
2690
2691     /* same elements as in 'ep_passable_over' */
2692     EL_EM_GATE_1,
2693     EL_EM_GATE_2,
2694     EL_EM_GATE_3,
2695     EL_EM_GATE_4,
2696     EL_EM_GATE_1_GRAY,
2697     EL_EM_GATE_2_GRAY,
2698     EL_EM_GATE_3_GRAY,
2699     EL_EM_GATE_4_GRAY,
2700     EL_EM_GATE_1_GRAY_ACTIVE,
2701     EL_EM_GATE_2_GRAY_ACTIVE,
2702     EL_EM_GATE_3_GRAY_ACTIVE,
2703     EL_EM_GATE_4_GRAY_ACTIVE,
2704     EL_EMC_GATE_5,
2705     EL_EMC_GATE_6,
2706     EL_EMC_GATE_7,
2707     EL_EMC_GATE_8,
2708     EL_EMC_GATE_5_GRAY,
2709     EL_EMC_GATE_6_GRAY,
2710     EL_EMC_GATE_7_GRAY,
2711     EL_EMC_GATE_8_GRAY,
2712     EL_EMC_GATE_5_GRAY_ACTIVE,
2713     EL_EMC_GATE_6_GRAY_ACTIVE,
2714     EL_EMC_GATE_7_GRAY_ACTIVE,
2715     EL_EMC_GATE_8_GRAY_ACTIVE,
2716     EL_DC_GATE_WHITE,
2717     EL_DC_GATE_WHITE_GRAY,
2718     EL_DC_GATE_WHITE_GRAY_ACTIVE,
2719     EL_SWITCHGATE_OPEN,
2720     EL_TIMEGATE_OPEN,
2721
2722     /* same elements as in 'ep_passable_inside' */
2723     EL_SP_PORT_LEFT,
2724     EL_SP_PORT_RIGHT,
2725     EL_SP_PORT_UP,
2726     EL_SP_PORT_DOWN,
2727     EL_SP_PORT_HORIZONTAL,
2728     EL_SP_PORT_VERTICAL,
2729     EL_SP_PORT_ANY,
2730     EL_SP_GRAVITY_PORT_LEFT,
2731     EL_SP_GRAVITY_PORT_RIGHT,
2732     EL_SP_GRAVITY_PORT_UP,
2733     EL_SP_GRAVITY_PORT_DOWN,
2734     EL_SP_GRAVITY_ON_PORT_LEFT,
2735     EL_SP_GRAVITY_ON_PORT_RIGHT,
2736     EL_SP_GRAVITY_ON_PORT_UP,
2737     EL_SP_GRAVITY_ON_PORT_DOWN,
2738     EL_SP_GRAVITY_OFF_PORT_LEFT,
2739     EL_SP_GRAVITY_OFF_PORT_RIGHT,
2740     EL_SP_GRAVITY_OFF_PORT_UP,
2741     EL_SP_GRAVITY_OFF_PORT_DOWN,
2742
2743     -1
2744   };
2745
2746   static int ep_throwable[] =
2747   {
2748     -1
2749   };
2750
2751   static int ep_can_explode[] =
2752   {
2753     /* same elements as in 'ep_explodes_impact' */
2754     EL_BOMB,
2755     EL_SP_DISK_ORANGE,
2756     EL_DX_SUPABOMB,
2757
2758     /* same elements as in 'ep_explodes_smashed' */
2759     EL_SATELLITE,
2760     EL_PIG,
2761     EL_DRAGON,
2762     EL_MOLE,
2763
2764     /* elements that can explode by explosion or by dragonfire */
2765     EL_DYNAMITE,
2766     EL_DYNAMITE_ACTIVE,
2767     EL_EM_DYNAMITE,
2768     EL_EM_DYNAMITE_ACTIVE,
2769     EL_DYNABOMB_PLAYER_1_ACTIVE,
2770     EL_DYNABOMB_PLAYER_2_ACTIVE,
2771     EL_DYNABOMB_PLAYER_3_ACTIVE,
2772     EL_DYNABOMB_PLAYER_4_ACTIVE,
2773     EL_DYNABOMB_INCREASE_NUMBER,
2774     EL_DYNABOMB_INCREASE_SIZE,
2775     EL_DYNABOMB_INCREASE_POWER,
2776     EL_SP_DISK_RED_ACTIVE,
2777     EL_BUG,
2778     EL_PENGUIN,
2779     EL_SP_DISK_RED,
2780     EL_SP_DISK_YELLOW,
2781     EL_SP_SNIKSNAK,
2782     EL_SP_ELECTRON,
2783
2784     /* elements that can explode only by explosion */
2785     EL_BLACK_ORB,
2786
2787     -1
2788   };
2789
2790   static int ep_gravity_reachable[] =
2791   {
2792     EL_SAND,
2793     EL_SP_BASE,
2794     EL_TRAP,
2795     EL_INVISIBLE_SAND,
2796     EL_INVISIBLE_SAND_ACTIVE,
2797     EL_SP_PORT_LEFT,
2798     EL_SP_PORT_RIGHT,
2799     EL_SP_PORT_UP,
2800     EL_SP_PORT_DOWN,
2801     EL_SP_PORT_HORIZONTAL,
2802     EL_SP_PORT_VERTICAL,
2803     EL_SP_PORT_ANY,
2804     EL_SP_GRAVITY_PORT_LEFT,
2805     EL_SP_GRAVITY_PORT_RIGHT,
2806     EL_SP_GRAVITY_PORT_UP,
2807     EL_SP_GRAVITY_PORT_DOWN,
2808     EL_SP_GRAVITY_ON_PORT_LEFT,
2809     EL_SP_GRAVITY_ON_PORT_RIGHT,
2810     EL_SP_GRAVITY_ON_PORT_UP,
2811     EL_SP_GRAVITY_ON_PORT_DOWN,
2812     EL_SP_GRAVITY_OFF_PORT_LEFT,
2813     EL_SP_GRAVITY_OFF_PORT_RIGHT,
2814     EL_SP_GRAVITY_OFF_PORT_UP,
2815     EL_SP_GRAVITY_OFF_PORT_DOWN,
2816     EL_EMC_GRASS,
2817
2818     -1
2819   };
2820
2821   static int ep_player[] =
2822   {
2823     EL_PLAYER_1,
2824     EL_PLAYER_2,
2825     EL_PLAYER_3,
2826     EL_PLAYER_4,
2827     EL_SP_MURPHY,
2828     EL_SOKOBAN_FIELD_PLAYER,
2829     EL_TRIGGER_PLAYER,
2830
2831     -1
2832   };
2833
2834   static int ep_can_pass_magic_wall[] =
2835   {
2836     EL_ROCK,
2837     EL_BD_ROCK,
2838     EL_EMERALD,
2839     EL_BD_DIAMOND,
2840     EL_EMERALD_YELLOW,
2841     EL_EMERALD_RED,
2842     EL_EMERALD_PURPLE,
2843     EL_DIAMOND,
2844
2845     -1
2846   };
2847
2848   static int ep_can_pass_dc_magic_wall[] =
2849   {
2850     EL_ROCK,
2851     EL_BD_ROCK,
2852     EL_EMERALD,
2853     EL_BD_DIAMOND,
2854     EL_EMERALD_YELLOW,
2855     EL_EMERALD_RED,
2856     EL_EMERALD_PURPLE,
2857     EL_DIAMOND,
2858     EL_PEARL,
2859     EL_CRYSTAL,
2860
2861     -1
2862   };
2863
2864   static int ep_switchable[] =
2865   {
2866     EL_ROBOT_WHEEL,
2867     EL_SP_TERMINAL,
2868     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2869     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2870     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2871     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2872     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2873     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2874     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2875     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2876     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2877     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2878     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2879     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2880     EL_SWITCHGATE_SWITCH_UP,
2881     EL_SWITCHGATE_SWITCH_DOWN,
2882     EL_DC_SWITCHGATE_SWITCH_UP,
2883     EL_DC_SWITCHGATE_SWITCH_DOWN,
2884     EL_LIGHT_SWITCH,
2885     EL_LIGHT_SWITCH_ACTIVE,
2886     EL_TIMEGATE_SWITCH,
2887     EL_DC_TIMEGATE_SWITCH,
2888     EL_BALLOON_SWITCH_LEFT,
2889     EL_BALLOON_SWITCH_RIGHT,
2890     EL_BALLOON_SWITCH_UP,
2891     EL_BALLOON_SWITCH_DOWN,
2892     EL_BALLOON_SWITCH_ANY,
2893     EL_BALLOON_SWITCH_NONE,
2894     EL_LAMP,
2895     EL_TIME_ORB_FULL,
2896     EL_EMC_MAGIC_BALL_SWITCH,
2897     EL_EMC_MAGIC_BALL_SWITCH_ACTIVE,
2898
2899     -1
2900   };
2901
2902   static int ep_bd_element[] =
2903   {
2904     EL_EMPTY,
2905     EL_SAND,
2906     EL_WALL_SLIPPERY,
2907     EL_BD_WALL,
2908     EL_ROCK,
2909     EL_BD_ROCK,
2910     EL_BD_DIAMOND,
2911     EL_BD_MAGIC_WALL,
2912     EL_EXIT_CLOSED,
2913     EL_EXIT_OPEN,
2914     EL_STEELWALL,
2915     EL_PLAYER_1,
2916     EL_PLAYER_2,
2917     EL_PLAYER_3,
2918     EL_PLAYER_4,
2919     EL_BD_FIREFLY,
2920     EL_BD_FIREFLY_1,
2921     EL_BD_FIREFLY_2,
2922     EL_BD_FIREFLY_3,
2923     EL_BD_FIREFLY_4,
2924     EL_BD_BUTTERFLY,
2925     EL_BD_BUTTERFLY_1,
2926     EL_BD_BUTTERFLY_2,
2927     EL_BD_BUTTERFLY_3,
2928     EL_BD_BUTTERFLY_4,
2929     EL_BD_AMOEBA,
2930     EL_CHAR_QUESTION,
2931     EL_UNKNOWN,
2932
2933     -1
2934   };
2935
2936   static int ep_sp_element[] =
2937   {
2938     /* should always be valid */
2939     EL_EMPTY,
2940
2941     /* standard classic Supaplex elements */
2942     EL_SP_EMPTY,
2943     EL_SP_ZONK,
2944     EL_SP_BASE,
2945     EL_SP_MURPHY,
2946     EL_SP_INFOTRON,
2947     EL_SP_CHIP_SINGLE,
2948     EL_SP_HARDWARE_GRAY,
2949     EL_SP_EXIT_CLOSED,
2950     EL_SP_EXIT_OPEN,
2951     EL_SP_DISK_ORANGE,
2952     EL_SP_PORT_RIGHT,
2953     EL_SP_PORT_DOWN,
2954     EL_SP_PORT_LEFT,
2955     EL_SP_PORT_UP,
2956     EL_SP_GRAVITY_PORT_RIGHT,
2957     EL_SP_GRAVITY_PORT_DOWN,
2958     EL_SP_GRAVITY_PORT_LEFT,
2959     EL_SP_GRAVITY_PORT_UP,
2960     EL_SP_SNIKSNAK,
2961     EL_SP_DISK_YELLOW,
2962     EL_SP_TERMINAL,
2963     EL_SP_DISK_RED,
2964     EL_SP_PORT_VERTICAL,
2965     EL_SP_PORT_HORIZONTAL,
2966     EL_SP_PORT_ANY,
2967     EL_SP_ELECTRON,
2968     EL_SP_BUGGY_BASE,
2969     EL_SP_CHIP_LEFT,
2970     EL_SP_CHIP_RIGHT,
2971     EL_SP_HARDWARE_BASE_1,
2972     EL_SP_HARDWARE_GREEN,
2973     EL_SP_HARDWARE_BLUE,
2974     EL_SP_HARDWARE_RED,
2975     EL_SP_HARDWARE_YELLOW,
2976     EL_SP_HARDWARE_BASE_2,
2977     EL_SP_HARDWARE_BASE_3,
2978     EL_SP_HARDWARE_BASE_4,
2979     EL_SP_HARDWARE_BASE_5,
2980     EL_SP_HARDWARE_BASE_6,
2981     EL_SP_CHIP_TOP,
2982     EL_SP_CHIP_BOTTOM,
2983
2984     /* additional elements that appeared in newer Supaplex levels */
2985     EL_INVISIBLE_WALL,
2986
2987     /* additional gravity port elements (not switching, but setting gravity) */
2988     EL_SP_GRAVITY_ON_PORT_LEFT,
2989     EL_SP_GRAVITY_ON_PORT_RIGHT,
2990     EL_SP_GRAVITY_ON_PORT_UP,
2991     EL_SP_GRAVITY_ON_PORT_DOWN,
2992     EL_SP_GRAVITY_OFF_PORT_LEFT,
2993     EL_SP_GRAVITY_OFF_PORT_RIGHT,
2994     EL_SP_GRAVITY_OFF_PORT_UP,
2995     EL_SP_GRAVITY_OFF_PORT_DOWN,
2996
2997     /* more than one Murphy in a level results in an inactive clone */
2998     EL_SP_MURPHY_CLONE,
2999
3000     /* runtime Supaplex elements */
3001     EL_SP_DISK_RED_ACTIVE,
3002     EL_SP_TERMINAL_ACTIVE,
3003     EL_SP_BUGGY_BASE_ACTIVATING,
3004     EL_SP_BUGGY_BASE_ACTIVE,
3005     EL_SP_EXIT_OPENING,
3006     EL_SP_EXIT_CLOSING,
3007
3008     -1
3009   };
3010
3011   static int ep_sb_element[] =
3012   {
3013     EL_EMPTY,
3014     EL_STEELWALL,
3015     EL_SOKOBAN_OBJECT,
3016     EL_SOKOBAN_FIELD_EMPTY,
3017     EL_SOKOBAN_FIELD_FULL,
3018     EL_SOKOBAN_FIELD_PLAYER,
3019     EL_PLAYER_1,
3020     EL_PLAYER_2,
3021     EL_PLAYER_3,
3022     EL_PLAYER_4,
3023     EL_INVISIBLE_STEELWALL,
3024
3025     -1
3026   };
3027
3028   static int ep_gem[] =
3029   {
3030     EL_BD_DIAMOND,
3031     EL_EMERALD,
3032     EL_EMERALD_YELLOW,
3033     EL_EMERALD_RED,
3034     EL_EMERALD_PURPLE,
3035     EL_DIAMOND,
3036
3037     -1
3038   };
3039
3040   static int ep_food_dark_yamyam[] =
3041   {
3042     EL_SAND,
3043     EL_BUG,
3044     EL_SPACESHIP,
3045     EL_BD_BUTTERFLY,
3046     EL_BD_FIREFLY,
3047     EL_YAMYAM,
3048     EL_ROBOT,
3049     EL_PACMAN,
3050     EL_AMOEBA_DROP,
3051     EL_AMOEBA_DEAD,
3052     EL_AMOEBA_WET,
3053     EL_AMOEBA_DRY,
3054     EL_AMOEBA_FULL,
3055     EL_BD_AMOEBA,
3056     EL_EMERALD,
3057     EL_BD_DIAMOND,
3058     EL_EMERALD_YELLOW,
3059     EL_EMERALD_RED,
3060     EL_EMERALD_PURPLE,
3061     EL_DIAMOND,
3062     EL_PEARL,
3063     EL_CRYSTAL,
3064
3065     -1
3066   };
3067
3068   static int ep_food_penguin[] =
3069   {
3070     EL_EMERALD,
3071     EL_BD_DIAMOND,
3072     EL_EMERALD_YELLOW,
3073     EL_EMERALD_RED,
3074     EL_EMERALD_PURPLE,
3075     EL_DIAMOND,
3076     EL_PEARL,
3077     EL_CRYSTAL,
3078
3079     -1
3080   };
3081
3082   static int ep_food_pig[] =
3083   {
3084     EL_EMERALD,
3085     EL_BD_DIAMOND,
3086     EL_EMERALD_YELLOW,
3087     EL_EMERALD_RED,
3088     EL_EMERALD_PURPLE,
3089     EL_DIAMOND,
3090
3091     -1
3092   };
3093
3094   static int ep_historic_wall[] =
3095   {
3096     EL_STEELWALL,
3097     EL_GATE_1,
3098     EL_GATE_2,
3099     EL_GATE_3,
3100     EL_GATE_4,
3101     EL_GATE_1_GRAY,
3102     EL_GATE_2_GRAY,
3103     EL_GATE_3_GRAY,
3104     EL_GATE_4_GRAY,
3105     EL_GATE_1_GRAY_ACTIVE,
3106     EL_GATE_2_GRAY_ACTIVE,
3107     EL_GATE_3_GRAY_ACTIVE,
3108     EL_GATE_4_GRAY_ACTIVE,
3109     EL_EM_GATE_1,
3110     EL_EM_GATE_2,
3111     EL_EM_GATE_3,
3112     EL_EM_GATE_4,
3113     EL_EM_GATE_1_GRAY,
3114     EL_EM_GATE_2_GRAY,
3115     EL_EM_GATE_3_GRAY,
3116     EL_EM_GATE_4_GRAY,
3117     EL_EM_GATE_1_GRAY_ACTIVE,
3118     EL_EM_GATE_2_GRAY_ACTIVE,
3119     EL_EM_GATE_3_GRAY_ACTIVE,
3120     EL_EM_GATE_4_GRAY_ACTIVE,
3121     EL_EXIT_CLOSED,
3122     EL_EXIT_OPENING,
3123     EL_EXIT_OPEN,
3124     EL_WALL,
3125     EL_WALL_SLIPPERY,
3126     EL_EXPANDABLE_WALL,
3127     EL_EXPANDABLE_WALL_HORIZONTAL,
3128     EL_EXPANDABLE_WALL_VERTICAL,
3129     EL_EXPANDABLE_WALL_ANY,
3130     EL_EXPANDABLE_WALL_GROWING,
3131     EL_BD_EXPANDABLE_WALL,
3132     EL_BD_WALL,
3133     EL_SP_CHIP_SINGLE,
3134     EL_SP_CHIP_LEFT,
3135     EL_SP_CHIP_RIGHT,
3136     EL_SP_CHIP_TOP,
3137     EL_SP_CHIP_BOTTOM,
3138     EL_SP_HARDWARE_GRAY,
3139     EL_SP_HARDWARE_GREEN,
3140     EL_SP_HARDWARE_BLUE,
3141     EL_SP_HARDWARE_RED,
3142     EL_SP_HARDWARE_YELLOW,
3143     EL_SP_HARDWARE_BASE_1,
3144     EL_SP_HARDWARE_BASE_2,
3145     EL_SP_HARDWARE_BASE_3,
3146     EL_SP_HARDWARE_BASE_4,
3147     EL_SP_HARDWARE_BASE_5,
3148     EL_SP_HARDWARE_BASE_6,
3149     EL_SP_TERMINAL,
3150     EL_SP_TERMINAL_ACTIVE,
3151     EL_SP_EXIT_CLOSED,
3152     EL_SP_EXIT_OPEN,
3153     EL_INVISIBLE_STEELWALL,
3154     EL_INVISIBLE_STEELWALL_ACTIVE,
3155     EL_INVISIBLE_WALL,
3156     EL_INVISIBLE_WALL_ACTIVE,
3157     EL_STEELWALL_SLIPPERY,
3158     EL_EMC_STEELWALL_1,
3159     EL_EMC_STEELWALL_2,
3160     EL_EMC_STEELWALL_3,
3161     EL_EMC_STEELWALL_4,
3162     EL_EMC_WALL_1,
3163     EL_EMC_WALL_2,
3164     EL_EMC_WALL_3,
3165     EL_EMC_WALL_4,
3166     EL_EMC_WALL_5,
3167     EL_EMC_WALL_6,
3168     EL_EMC_WALL_7,
3169     EL_EMC_WALL_8,
3170
3171     -1
3172   };
3173
3174   static int ep_historic_solid[] =
3175   {
3176     EL_WALL,
3177     EL_EXPANDABLE_WALL,
3178     EL_EXPANDABLE_WALL_HORIZONTAL,
3179     EL_EXPANDABLE_WALL_VERTICAL,
3180     EL_EXPANDABLE_WALL_ANY,
3181     EL_BD_EXPANDABLE_WALL,
3182     EL_BD_WALL,
3183     EL_WALL_SLIPPERY,
3184     EL_EXIT_CLOSED,
3185     EL_EXIT_OPENING,
3186     EL_EXIT_OPEN,
3187     EL_AMOEBA_DEAD,
3188     EL_AMOEBA_WET,
3189     EL_AMOEBA_DRY,
3190     EL_AMOEBA_FULL,
3191     EL_BD_AMOEBA,
3192     EL_QUICKSAND_EMPTY,
3193     EL_QUICKSAND_FULL,
3194     EL_QUICKSAND_FILLING,
3195     EL_QUICKSAND_EMPTYING,
3196     EL_MAGIC_WALL,
3197     EL_MAGIC_WALL_ACTIVE,
3198     EL_MAGIC_WALL_EMPTYING,
3199     EL_MAGIC_WALL_FILLING,
3200     EL_MAGIC_WALL_FULL,
3201     EL_MAGIC_WALL_DEAD,
3202     EL_BD_MAGIC_WALL,
3203     EL_BD_MAGIC_WALL_ACTIVE,
3204     EL_BD_MAGIC_WALL_EMPTYING,
3205     EL_BD_MAGIC_WALL_FULL,
3206     EL_BD_MAGIC_WALL_FILLING,
3207     EL_BD_MAGIC_WALL_DEAD,
3208     EL_GAME_OF_LIFE,
3209     EL_BIOMAZE,
3210     EL_SP_CHIP_SINGLE,
3211     EL_SP_CHIP_LEFT,
3212     EL_SP_CHIP_RIGHT,
3213     EL_SP_CHIP_TOP,
3214     EL_SP_CHIP_BOTTOM,
3215     EL_SP_TERMINAL,
3216     EL_SP_TERMINAL_ACTIVE,
3217     EL_SP_EXIT_CLOSED,
3218     EL_SP_EXIT_OPEN,
3219     EL_INVISIBLE_WALL,
3220     EL_INVISIBLE_WALL_ACTIVE,
3221     EL_SWITCHGATE_SWITCH_UP,
3222     EL_SWITCHGATE_SWITCH_DOWN,
3223     EL_DC_SWITCHGATE_SWITCH_UP,
3224     EL_DC_SWITCHGATE_SWITCH_DOWN,
3225     EL_TIMEGATE_SWITCH,
3226     EL_TIMEGATE_SWITCH_ACTIVE,
3227     EL_DC_TIMEGATE_SWITCH,
3228     EL_DC_TIMEGATE_SWITCH_ACTIVE,
3229     EL_EMC_WALL_1,
3230     EL_EMC_WALL_2,
3231     EL_EMC_WALL_3,
3232     EL_EMC_WALL_4,
3233     EL_EMC_WALL_5,
3234     EL_EMC_WALL_6,
3235     EL_EMC_WALL_7,
3236     EL_EMC_WALL_8,
3237     EL_WALL_PEARL,
3238     EL_WALL_CRYSTAL,
3239
3240     /* the following elements are a direct copy of "indestructible" elements,
3241        except "EL_ACID", which is "indestructible", but not "solid"! */
3242 #if 0
3243     EL_ACID,
3244 #endif
3245     EL_STEELWALL,
3246     EL_ACID_POOL_TOPLEFT,
3247     EL_ACID_POOL_TOPRIGHT,
3248     EL_ACID_POOL_BOTTOMLEFT,
3249     EL_ACID_POOL_BOTTOM,
3250     EL_ACID_POOL_BOTTOMRIGHT,
3251     EL_SP_HARDWARE_GRAY,
3252     EL_SP_HARDWARE_GREEN,
3253     EL_SP_HARDWARE_BLUE,
3254     EL_SP_HARDWARE_RED,
3255     EL_SP_HARDWARE_YELLOW,
3256     EL_SP_HARDWARE_BASE_1,
3257     EL_SP_HARDWARE_BASE_2,
3258     EL_SP_HARDWARE_BASE_3,
3259     EL_SP_HARDWARE_BASE_4,
3260     EL_SP_HARDWARE_BASE_5,
3261     EL_SP_HARDWARE_BASE_6,
3262     EL_INVISIBLE_STEELWALL,
3263     EL_INVISIBLE_STEELWALL_ACTIVE,
3264     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3265     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3266     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3267     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3268     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3269     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3270     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3271     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3272     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3273     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3274     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3275     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3276     EL_LIGHT_SWITCH,
3277     EL_LIGHT_SWITCH_ACTIVE,
3278     EL_SIGN_EXCLAMATION,
3279     EL_SIGN_RADIOACTIVITY,
3280     EL_SIGN_STOP,
3281     EL_SIGN_WHEELCHAIR,
3282     EL_SIGN_PARKING,
3283     EL_SIGN_NO_ENTRY,
3284     EL_SIGN_UNUSED_1,
3285     EL_SIGN_GIVE_WAY,
3286     EL_SIGN_ENTRY_FORBIDDEN,
3287     EL_SIGN_EMERGENCY_EXIT,
3288     EL_SIGN_YIN_YANG,
3289     EL_SIGN_UNUSED_2,
3290     EL_SIGN_SPERMS,
3291     EL_SIGN_BULLET,
3292     EL_SIGN_HEART,
3293     EL_SIGN_CROSS,
3294     EL_SIGN_FRANKIE,
3295     EL_STEEL_EXIT_CLOSED,
3296     EL_STEEL_EXIT_OPEN,
3297     EL_DC_STEELWALL_1_LEFT,
3298     EL_DC_STEELWALL_1_RIGHT,
3299     EL_DC_STEELWALL_1_TOP,
3300     EL_DC_STEELWALL_1_BOTTOM,
3301     EL_DC_STEELWALL_1_HORIZONTAL,
3302     EL_DC_STEELWALL_1_VERTICAL,
3303     EL_DC_STEELWALL_1_TOPLEFT,
3304     EL_DC_STEELWALL_1_TOPRIGHT,
3305     EL_DC_STEELWALL_1_BOTTOMLEFT,
3306     EL_DC_STEELWALL_1_BOTTOMRIGHT,
3307     EL_DC_STEELWALL_1_TOPLEFT_2,
3308     EL_DC_STEELWALL_1_TOPRIGHT_2,
3309     EL_DC_STEELWALL_1_BOTTOMLEFT_2,
3310     EL_DC_STEELWALL_1_BOTTOMRIGHT_2,
3311     EL_DC_STEELWALL_2_LEFT,
3312     EL_DC_STEELWALL_2_RIGHT,
3313     EL_DC_STEELWALL_2_TOP,
3314     EL_DC_STEELWALL_2_BOTTOM,
3315     EL_DC_STEELWALL_2_HORIZONTAL,
3316     EL_DC_STEELWALL_2_VERTICAL,
3317     EL_DC_STEELWALL_2_MIDDLE,
3318     EL_DC_STEELWALL_2_SINGLE,
3319     EL_STEELWALL_SLIPPERY,
3320     EL_EMC_STEELWALL_1,
3321     EL_EMC_STEELWALL_2,
3322     EL_EMC_STEELWALL_3,
3323     EL_EMC_STEELWALL_4,
3324     EL_CRYSTAL,
3325     EL_GATE_1,
3326     EL_GATE_2,
3327     EL_GATE_3,
3328     EL_GATE_4,
3329     EL_GATE_1_GRAY,
3330     EL_GATE_2_GRAY,
3331     EL_GATE_3_GRAY,
3332     EL_GATE_4_GRAY,
3333     EL_GATE_1_GRAY_ACTIVE,
3334     EL_GATE_2_GRAY_ACTIVE,
3335     EL_GATE_3_GRAY_ACTIVE,
3336     EL_GATE_4_GRAY_ACTIVE,
3337     EL_EM_GATE_1,
3338     EL_EM_GATE_2,
3339     EL_EM_GATE_3,
3340     EL_EM_GATE_4,
3341     EL_EM_GATE_1_GRAY,
3342     EL_EM_GATE_2_GRAY,
3343     EL_EM_GATE_3_GRAY,
3344     EL_EM_GATE_4_GRAY,
3345     EL_EM_GATE_1_GRAY_ACTIVE,
3346     EL_EM_GATE_2_GRAY_ACTIVE,
3347     EL_EM_GATE_3_GRAY_ACTIVE,
3348     EL_EM_GATE_4_GRAY_ACTIVE,
3349     EL_SWITCHGATE_OPEN,
3350     EL_SWITCHGATE_OPENING,
3351     EL_SWITCHGATE_CLOSED,
3352     EL_SWITCHGATE_CLOSING,
3353     EL_TIMEGATE_OPEN,
3354     EL_TIMEGATE_OPENING,
3355     EL_TIMEGATE_CLOSED,
3356     EL_TIMEGATE_CLOSING,
3357     EL_TUBE_ANY,
3358     EL_TUBE_VERTICAL,
3359     EL_TUBE_HORIZONTAL,
3360     EL_TUBE_VERTICAL_LEFT,
3361     EL_TUBE_VERTICAL_RIGHT,
3362     EL_TUBE_HORIZONTAL_UP,
3363     EL_TUBE_HORIZONTAL_DOWN,
3364     EL_TUBE_LEFT_UP,
3365     EL_TUBE_LEFT_DOWN,
3366     EL_TUBE_RIGHT_UP,
3367     EL_TUBE_RIGHT_DOWN,
3368
3369     -1
3370   };
3371
3372   static int ep_classic_enemy[] =
3373   {
3374     EL_BUG,
3375     EL_SPACESHIP,
3376     EL_BD_BUTTERFLY,
3377     EL_BD_FIREFLY,
3378
3379     EL_YAMYAM,
3380     EL_DARK_YAMYAM,
3381     EL_ROBOT,
3382     EL_PACMAN,
3383     EL_SP_SNIKSNAK,
3384     EL_SP_ELECTRON,
3385
3386     -1
3387   };
3388
3389   static int ep_belt[] =
3390   {
3391     EL_CONVEYOR_BELT_1_LEFT,
3392     EL_CONVEYOR_BELT_1_MIDDLE,
3393     EL_CONVEYOR_BELT_1_RIGHT,
3394     EL_CONVEYOR_BELT_2_LEFT,
3395     EL_CONVEYOR_BELT_2_MIDDLE,
3396     EL_CONVEYOR_BELT_2_RIGHT,
3397     EL_CONVEYOR_BELT_3_LEFT,
3398     EL_CONVEYOR_BELT_3_MIDDLE,
3399     EL_CONVEYOR_BELT_3_RIGHT,
3400     EL_CONVEYOR_BELT_4_LEFT,
3401     EL_CONVEYOR_BELT_4_MIDDLE,
3402     EL_CONVEYOR_BELT_4_RIGHT,
3403
3404     -1
3405   };
3406
3407   static int ep_belt_active[] =
3408   {
3409     EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
3410     EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE,
3411     EL_CONVEYOR_BELT_1_RIGHT_ACTIVE,
3412     EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
3413     EL_CONVEYOR_BELT_2_MIDDLE_ACTIVE,
3414     EL_CONVEYOR_BELT_2_RIGHT_ACTIVE,
3415     EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
3416     EL_CONVEYOR_BELT_3_MIDDLE_ACTIVE,
3417     EL_CONVEYOR_BELT_3_RIGHT_ACTIVE,
3418     EL_CONVEYOR_BELT_4_LEFT_ACTIVE,
3419     EL_CONVEYOR_BELT_4_MIDDLE_ACTIVE,
3420     EL_CONVEYOR_BELT_4_RIGHT_ACTIVE,
3421
3422     -1
3423   };
3424
3425   static int ep_belt_switch[] =
3426   {
3427     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3428     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3429     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3430     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3431     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3432     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3433     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3434     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3435     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3436     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3437     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3438     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3439
3440     -1
3441   };
3442
3443   static int ep_tube[] =
3444   {
3445     EL_TUBE_LEFT_UP,
3446     EL_TUBE_LEFT_DOWN,
3447     EL_TUBE_RIGHT_UP,
3448     EL_TUBE_RIGHT_DOWN,
3449     EL_TUBE_HORIZONTAL,
3450     EL_TUBE_HORIZONTAL_UP,
3451     EL_TUBE_HORIZONTAL_DOWN,
3452     EL_TUBE_VERTICAL,
3453     EL_TUBE_VERTICAL_LEFT,
3454     EL_TUBE_VERTICAL_RIGHT,
3455     EL_TUBE_ANY,
3456
3457     -1
3458   };
3459
3460   static int ep_acid_pool[] =
3461   {
3462     EL_ACID_POOL_TOPLEFT,
3463     EL_ACID_POOL_TOPRIGHT,
3464     EL_ACID_POOL_BOTTOMLEFT,
3465     EL_ACID_POOL_BOTTOM,
3466     EL_ACID_POOL_BOTTOMRIGHT,
3467
3468     -1
3469   };
3470
3471   static int ep_keygate[] =
3472   {
3473     EL_GATE_1,
3474     EL_GATE_2,
3475     EL_GATE_3,
3476     EL_GATE_4,
3477     EL_GATE_1_GRAY,
3478     EL_GATE_2_GRAY,
3479     EL_GATE_3_GRAY,
3480     EL_GATE_4_GRAY,
3481     EL_GATE_1_GRAY_ACTIVE,
3482     EL_GATE_2_GRAY_ACTIVE,
3483     EL_GATE_3_GRAY_ACTIVE,
3484     EL_GATE_4_GRAY_ACTIVE,
3485     EL_EM_GATE_1,
3486     EL_EM_GATE_2,
3487     EL_EM_GATE_3,
3488     EL_EM_GATE_4,
3489     EL_EM_GATE_1_GRAY,
3490     EL_EM_GATE_2_GRAY,
3491     EL_EM_GATE_3_GRAY,
3492     EL_EM_GATE_4_GRAY,
3493     EL_EM_GATE_1_GRAY_ACTIVE,
3494     EL_EM_GATE_2_GRAY_ACTIVE,
3495     EL_EM_GATE_3_GRAY_ACTIVE,
3496     EL_EM_GATE_4_GRAY_ACTIVE,
3497     EL_EMC_GATE_5,
3498     EL_EMC_GATE_6,
3499     EL_EMC_GATE_7,
3500     EL_EMC_GATE_8,
3501     EL_EMC_GATE_5_GRAY,
3502     EL_EMC_GATE_6_GRAY,
3503     EL_EMC_GATE_7_GRAY,
3504     EL_EMC_GATE_8_GRAY,
3505     EL_EMC_GATE_5_GRAY_ACTIVE,
3506     EL_EMC_GATE_6_GRAY_ACTIVE,
3507     EL_EMC_GATE_7_GRAY_ACTIVE,
3508     EL_EMC_GATE_8_GRAY_ACTIVE,
3509     EL_DC_GATE_WHITE,
3510     EL_DC_GATE_WHITE_GRAY,
3511     EL_DC_GATE_WHITE_GRAY_ACTIVE,
3512
3513     -1
3514   };
3515
3516   static int ep_amoeboid[] =
3517   {
3518     EL_AMOEBA_DEAD,
3519     EL_AMOEBA_WET,
3520     EL_AMOEBA_DRY,
3521     EL_AMOEBA_FULL,
3522     EL_BD_AMOEBA,
3523     EL_EMC_DRIPPER,
3524
3525     -1
3526   };
3527
3528   static int ep_amoebalive[] =
3529   {
3530     EL_AMOEBA_WET,
3531     EL_AMOEBA_DRY,
3532     EL_AMOEBA_FULL,
3533     EL_BD_AMOEBA,
3534     EL_EMC_DRIPPER,
3535
3536     -1
3537   };
3538
3539   static int ep_has_editor_content[] =
3540   {
3541     EL_PLAYER_1,
3542     EL_PLAYER_2,
3543     EL_PLAYER_3,
3544     EL_PLAYER_4,
3545     EL_SP_MURPHY,
3546     EL_YAMYAM,
3547     EL_YAMYAM_LEFT,
3548     EL_YAMYAM_RIGHT,
3549     EL_YAMYAM_UP,
3550     EL_YAMYAM_DOWN,
3551     EL_AMOEBA_WET,
3552     EL_AMOEBA_DRY,
3553     EL_AMOEBA_FULL,
3554     EL_BD_AMOEBA,
3555     EL_EMC_MAGIC_BALL,
3556     EL_EMC_ANDROID,
3557
3558     -1
3559   };
3560
3561   static int ep_can_turn_each_move[] =
3562   {
3563     /* !!! do something with this one !!! */
3564     -1
3565   };
3566
3567   static int ep_can_grow[] =
3568   {
3569     EL_BD_AMOEBA,
3570     EL_AMOEBA_DROP,
3571     EL_AMOEBA_WET,
3572     EL_AMOEBA_DRY,
3573     EL_AMOEBA_FULL,
3574     EL_GAME_OF_LIFE,
3575     EL_BIOMAZE,
3576     EL_EMC_DRIPPER,
3577
3578     -1
3579   };
3580
3581   static int ep_active_bomb[] =
3582   {
3583     EL_DYNAMITE_ACTIVE,
3584     EL_EM_DYNAMITE_ACTIVE,
3585     EL_DYNABOMB_PLAYER_1_ACTIVE,
3586     EL_DYNABOMB_PLAYER_2_ACTIVE,
3587     EL_DYNABOMB_PLAYER_3_ACTIVE,
3588     EL_DYNABOMB_PLAYER_4_ACTIVE,
3589     EL_SP_DISK_RED_ACTIVE,
3590
3591     -1
3592   };
3593
3594   static int ep_inactive[] =
3595   {
3596     EL_EMPTY,
3597     EL_SAND,
3598     EL_WALL,
3599     EL_BD_WALL,
3600     EL_WALL_SLIPPERY,
3601     EL_STEELWALL,
3602     EL_AMOEBA_DEAD,
3603     EL_QUICKSAND_EMPTY,
3604     EL_QUICKSAND_FAST_EMPTY,
3605     EL_STONEBLOCK,
3606     EL_ROBOT_WHEEL,
3607     EL_KEY_1,
3608     EL_KEY_2,
3609     EL_KEY_3,
3610     EL_KEY_4,
3611     EL_EM_KEY_1,
3612     EL_EM_KEY_2,
3613     EL_EM_KEY_3,
3614     EL_EM_KEY_4,
3615     EL_EMC_KEY_5,
3616     EL_EMC_KEY_6,
3617     EL_EMC_KEY_7,
3618     EL_EMC_KEY_8,
3619     EL_GATE_1,
3620     EL_GATE_2,
3621     EL_GATE_3,
3622     EL_GATE_4,
3623     EL_GATE_1_GRAY,
3624     EL_GATE_2_GRAY,
3625     EL_GATE_3_GRAY,
3626     EL_GATE_4_GRAY,
3627     EL_GATE_1_GRAY_ACTIVE,
3628     EL_GATE_2_GRAY_ACTIVE,
3629     EL_GATE_3_GRAY_ACTIVE,
3630     EL_GATE_4_GRAY_ACTIVE,
3631     EL_EM_GATE_1,
3632     EL_EM_GATE_2,
3633     EL_EM_GATE_3,
3634     EL_EM_GATE_4,
3635     EL_EM_GATE_1_GRAY,
3636     EL_EM_GATE_2_GRAY,
3637     EL_EM_GATE_3_GRAY,
3638     EL_EM_GATE_4_GRAY,
3639     EL_EM_GATE_1_GRAY_ACTIVE,
3640     EL_EM_GATE_2_GRAY_ACTIVE,
3641     EL_EM_GATE_3_GRAY_ACTIVE,
3642     EL_EM_GATE_4_GRAY_ACTIVE,
3643     EL_EMC_GATE_5,
3644     EL_EMC_GATE_6,
3645     EL_EMC_GATE_7,
3646     EL_EMC_GATE_8,
3647     EL_EMC_GATE_5_GRAY,
3648     EL_EMC_GATE_6_GRAY,
3649     EL_EMC_GATE_7_GRAY,
3650     EL_EMC_GATE_8_GRAY,
3651     EL_EMC_GATE_5_GRAY_ACTIVE,
3652     EL_EMC_GATE_6_GRAY_ACTIVE,
3653     EL_EMC_GATE_7_GRAY_ACTIVE,
3654     EL_EMC_GATE_8_GRAY_ACTIVE,
3655     EL_DC_GATE_WHITE,
3656     EL_DC_GATE_WHITE_GRAY,
3657     EL_DC_GATE_WHITE_GRAY_ACTIVE,
3658     EL_DC_GATE_FAKE_GRAY,
3659     EL_DYNAMITE,
3660     EL_EM_DYNAMITE,
3661     EL_INVISIBLE_STEELWALL,
3662     EL_INVISIBLE_WALL,
3663     EL_INVISIBLE_SAND,
3664     EL_LAMP,
3665     EL_LAMP_ACTIVE,
3666     EL_WALL_EMERALD,
3667     EL_WALL_DIAMOND,
3668     EL_WALL_BD_DIAMOND,
3669     EL_WALL_EMERALD_YELLOW,
3670     EL_DYNABOMB_INCREASE_NUMBER,
3671     EL_DYNABOMB_INCREASE_SIZE,
3672     EL_DYNABOMB_INCREASE_POWER,
3673 #if 0
3674     EL_SOKOBAN_OBJECT,
3675 #endif
3676     EL_SOKOBAN_FIELD_EMPTY,
3677     EL_SOKOBAN_FIELD_FULL,
3678     EL_WALL_EMERALD_RED,
3679     EL_WALL_EMERALD_PURPLE,
3680     EL_ACID_POOL_TOPLEFT,
3681     EL_ACID_POOL_TOPRIGHT,
3682     EL_ACID_POOL_BOTTOMLEFT,
3683     EL_ACID_POOL_BOTTOM,
3684     EL_ACID_POOL_BOTTOMRIGHT,
3685     EL_MAGIC_WALL,
3686     EL_MAGIC_WALL_DEAD,
3687     EL_BD_MAGIC_WALL,
3688     EL_BD_MAGIC_WALL_DEAD,
3689     EL_DC_MAGIC_WALL,
3690     EL_DC_MAGIC_WALL_DEAD,
3691     EL_AMOEBA_TO_DIAMOND,
3692     EL_BLOCKED,
3693     EL_SP_EMPTY,
3694     EL_SP_BASE,
3695     EL_SP_PORT_RIGHT,
3696     EL_SP_PORT_DOWN,
3697     EL_SP_PORT_LEFT,
3698     EL_SP_PORT_UP,
3699     EL_SP_GRAVITY_PORT_RIGHT,
3700     EL_SP_GRAVITY_PORT_DOWN,
3701     EL_SP_GRAVITY_PORT_LEFT,
3702     EL_SP_GRAVITY_PORT_UP,
3703     EL_SP_PORT_HORIZONTAL,
3704     EL_SP_PORT_VERTICAL,
3705     EL_SP_PORT_ANY,
3706     EL_SP_DISK_RED,
3707 #if 0
3708     EL_SP_DISK_YELLOW,
3709 #endif
3710     EL_SP_CHIP_SINGLE,
3711     EL_SP_CHIP_LEFT,
3712     EL_SP_CHIP_RIGHT,
3713     EL_SP_CHIP_TOP,
3714     EL_SP_CHIP_BOTTOM,
3715     EL_SP_HARDWARE_GRAY,
3716     EL_SP_HARDWARE_GREEN,
3717     EL_SP_HARDWARE_BLUE,
3718     EL_SP_HARDWARE_RED,
3719     EL_SP_HARDWARE_YELLOW,
3720     EL_SP_HARDWARE_BASE_1,
3721     EL_SP_HARDWARE_BASE_2,
3722     EL_SP_HARDWARE_BASE_3,
3723     EL_SP_HARDWARE_BASE_4,
3724     EL_SP_HARDWARE_BASE_5,
3725     EL_SP_HARDWARE_BASE_6,
3726     EL_SP_GRAVITY_ON_PORT_LEFT,
3727     EL_SP_GRAVITY_ON_PORT_RIGHT,
3728     EL_SP_GRAVITY_ON_PORT_UP,
3729     EL_SP_GRAVITY_ON_PORT_DOWN,
3730     EL_SP_GRAVITY_OFF_PORT_LEFT,
3731     EL_SP_GRAVITY_OFF_PORT_RIGHT,
3732     EL_SP_GRAVITY_OFF_PORT_UP,
3733     EL_SP_GRAVITY_OFF_PORT_DOWN,
3734     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3735     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3736     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3737     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3738     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3739     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3740     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3741     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3742     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3743     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3744     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3745     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3746     EL_SIGN_EXCLAMATION,
3747     EL_SIGN_RADIOACTIVITY,
3748     EL_SIGN_STOP,
3749     EL_SIGN_WHEELCHAIR,
3750     EL_SIGN_PARKING,
3751     EL_SIGN_NO_ENTRY,
3752     EL_SIGN_UNUSED_1,
3753     EL_SIGN_GIVE_WAY,
3754     EL_SIGN_ENTRY_FORBIDDEN,
3755     EL_SIGN_EMERGENCY_EXIT,
3756     EL_SIGN_YIN_YANG,
3757     EL_SIGN_UNUSED_2,
3758     EL_SIGN_SPERMS,
3759     EL_SIGN_BULLET,
3760     EL_SIGN_HEART,
3761     EL_SIGN_CROSS,
3762     EL_SIGN_FRANKIE,
3763     EL_DC_STEELWALL_1_LEFT,
3764     EL_DC_STEELWALL_1_RIGHT,
3765     EL_DC_STEELWALL_1_TOP,
3766     EL_DC_STEELWALL_1_BOTTOM,
3767     EL_DC_STEELWALL_1_HORIZONTAL,
3768     EL_DC_STEELWALL_1_VERTICAL,
3769     EL_DC_STEELWALL_1_TOPLEFT,
3770     EL_DC_STEELWALL_1_TOPRIGHT,
3771     EL_DC_STEELWALL_1_BOTTOMLEFT,
3772     EL_DC_STEELWALL_1_BOTTOMRIGHT,
3773     EL_DC_STEELWALL_1_TOPLEFT_2,
3774     EL_DC_STEELWALL_1_TOPRIGHT_2,
3775     EL_DC_STEELWALL_1_BOTTOMLEFT_2,
3776     EL_DC_STEELWALL_1_BOTTOMRIGHT_2,
3777     EL_DC_STEELWALL_2_LEFT,
3778     EL_DC_STEELWALL_2_RIGHT,
3779     EL_DC_STEELWALL_2_TOP,
3780     EL_DC_STEELWALL_2_BOTTOM,
3781     EL_DC_STEELWALL_2_HORIZONTAL,
3782     EL_DC_STEELWALL_2_VERTICAL,
3783     EL_DC_STEELWALL_2_MIDDLE,
3784     EL_DC_STEELWALL_2_SINGLE,
3785     EL_STEELWALL_SLIPPERY,
3786     EL_EMC_STEELWALL_1,
3787     EL_EMC_STEELWALL_2,
3788     EL_EMC_STEELWALL_3,
3789     EL_EMC_STEELWALL_4,
3790     EL_EMC_WALL_SLIPPERY_1,
3791     EL_EMC_WALL_SLIPPERY_2,
3792     EL_EMC_WALL_SLIPPERY_3,
3793     EL_EMC_WALL_SLIPPERY_4,
3794     EL_EMC_WALL_1,
3795     EL_EMC_WALL_2,
3796     EL_EMC_WALL_3,
3797     EL_EMC_WALL_4,
3798     EL_EMC_WALL_5,
3799     EL_EMC_WALL_6,
3800     EL_EMC_WALL_7,
3801     EL_EMC_WALL_8,
3802     EL_EMC_WALL_9,
3803     EL_EMC_WALL_10,
3804     EL_EMC_WALL_11,
3805     EL_EMC_WALL_12,
3806     EL_EMC_WALL_13,
3807     EL_EMC_WALL_14,
3808     EL_EMC_WALL_15,
3809     EL_EMC_WALL_16,
3810
3811     -1
3812   };
3813
3814   static int ep_em_slippery_wall[] =
3815   {
3816     -1
3817   };
3818
3819   static int ep_gfx_crumbled[] =
3820   {
3821     EL_SAND,
3822     EL_LANDMINE,
3823     EL_DC_LANDMINE,
3824     EL_TRAP,
3825     EL_TRAP_ACTIVE,
3826
3827     -1
3828   };
3829
3830   static int ep_editor_cascade_active[] =
3831   {
3832     EL_INTERNAL_CASCADE_BD_ACTIVE,
3833     EL_INTERNAL_CASCADE_EM_ACTIVE,
3834     EL_INTERNAL_CASCADE_EMC_ACTIVE,
3835     EL_INTERNAL_CASCADE_RND_ACTIVE,
3836     EL_INTERNAL_CASCADE_SB_ACTIVE,
3837     EL_INTERNAL_CASCADE_SP_ACTIVE,
3838     EL_INTERNAL_CASCADE_DC_ACTIVE,
3839     EL_INTERNAL_CASCADE_DX_ACTIVE,
3840     EL_INTERNAL_CASCADE_CHARS_ACTIVE,
3841     EL_INTERNAL_CASCADE_STEEL_CHARS_ACTIVE,
3842     EL_INTERNAL_CASCADE_CE_ACTIVE,
3843     EL_INTERNAL_CASCADE_GE_ACTIVE,
3844     EL_INTERNAL_CASCADE_REF_ACTIVE,
3845     EL_INTERNAL_CASCADE_USER_ACTIVE,
3846     EL_INTERNAL_CASCADE_DYNAMIC_ACTIVE,
3847
3848     -1
3849   };
3850
3851   static int ep_editor_cascade_inactive[] =
3852   {
3853     EL_INTERNAL_CASCADE_BD,
3854     EL_INTERNAL_CASCADE_EM,
3855     EL_INTERNAL_CASCADE_EMC,
3856     EL_INTERNAL_CASCADE_RND,
3857     EL_INTERNAL_CASCADE_SB,
3858     EL_INTERNAL_CASCADE_SP,
3859     EL_INTERNAL_CASCADE_DC,
3860     EL_INTERNAL_CASCADE_DX,
3861     EL_INTERNAL_CASCADE_CHARS,
3862     EL_INTERNAL_CASCADE_STEEL_CHARS,
3863     EL_INTERNAL_CASCADE_CE,
3864     EL_INTERNAL_CASCADE_GE,
3865     EL_INTERNAL_CASCADE_REF,
3866     EL_INTERNAL_CASCADE_USER,
3867     EL_INTERNAL_CASCADE_DYNAMIC,
3868
3869     -1
3870   };
3871
3872   static int ep_obsolete[] =
3873   {
3874     EL_PLAYER_OBSOLETE,
3875     EL_KEY_OBSOLETE,
3876     EL_EM_KEY_1_FILE_OBSOLETE,
3877     EL_EM_KEY_2_FILE_OBSOLETE,
3878     EL_EM_KEY_3_FILE_OBSOLETE,
3879     EL_EM_KEY_4_FILE_OBSOLETE,
3880     EL_ENVELOPE_OBSOLETE,
3881
3882     -1
3883   };
3884
3885   static struct
3886   {
3887     int *elements;
3888     int property;
3889   } element_properties[] =
3890   {
3891     { ep_diggable,                      EP_DIGGABLE                     },
3892     { ep_collectible_only,              EP_COLLECTIBLE_ONLY             },
3893     { ep_dont_run_into,                 EP_DONT_RUN_INTO                },
3894     { ep_dont_collide_with,             EP_DONT_COLLIDE_WITH            },
3895     { ep_dont_touch,                    EP_DONT_TOUCH                   },
3896     { ep_indestructible,                EP_INDESTRUCTIBLE               },
3897     { ep_slippery,                      EP_SLIPPERY                     },
3898     { ep_can_change,                    EP_CAN_CHANGE                   },
3899     { ep_can_move,                      EP_CAN_MOVE                     },
3900     { ep_can_fall,                      EP_CAN_FALL                     },
3901     { ep_can_smash_player,              EP_CAN_SMASH_PLAYER             },
3902     { ep_can_smash_enemies,             EP_CAN_SMASH_ENEMIES            },
3903     { ep_can_smash_everything,          EP_CAN_SMASH_EVERYTHING         },
3904     { ep_explodes_by_fire,              EP_EXPLODES_BY_FIRE             },
3905     { ep_explodes_smashed,              EP_EXPLODES_SMASHED             },
3906     { ep_explodes_impact,               EP_EXPLODES_IMPACT              },
3907     { ep_walkable_over,                 EP_WALKABLE_OVER                },
3908     { ep_walkable_inside,               EP_WALKABLE_INSIDE              },
3909     { ep_walkable_under,                EP_WALKABLE_UNDER               },
3910     { ep_passable_over,                 EP_PASSABLE_OVER                },
3911     { ep_passable_inside,               EP_PASSABLE_INSIDE              },
3912     { ep_passable_under,                EP_PASSABLE_UNDER               },
3913     { ep_droppable,                     EP_DROPPABLE                    },
3914     { ep_explodes_1x1_old,              EP_EXPLODES_1X1_OLD             },
3915     { ep_pushable,                      EP_PUSHABLE                     },
3916     { ep_explodes_cross_old,            EP_EXPLODES_CROSS_OLD           },
3917     { ep_protected,                     EP_PROTECTED                    },
3918     { ep_throwable,                     EP_THROWABLE                    },
3919     { ep_can_explode,                   EP_CAN_EXPLODE                  },
3920     { ep_gravity_reachable,             EP_GRAVITY_REACHABLE            },
3921
3922     { ep_player,                        EP_PLAYER                       },
3923     { ep_can_pass_magic_wall,           EP_CAN_PASS_MAGIC_WALL          },
3924     { ep_can_pass_dc_magic_wall,        EP_CAN_PASS_DC_MAGIC_WALL       },
3925     { ep_switchable,                    EP_SWITCHABLE                   },
3926     { ep_bd_element,                    EP_BD_ELEMENT                   },
3927     { ep_sp_element,                    EP_SP_ELEMENT                   },
3928     { ep_sb_element,                    EP_SB_ELEMENT                   },
3929     { ep_gem,                           EP_GEM                          },
3930     { ep_food_dark_yamyam,              EP_FOOD_DARK_YAMYAM             },
3931     { ep_food_penguin,                  EP_FOOD_PENGUIN                 },
3932     { ep_food_pig,                      EP_FOOD_PIG                     },
3933     { ep_historic_wall,                 EP_HISTORIC_WALL                },
3934     { ep_historic_solid,                EP_HISTORIC_SOLID               },
3935     { ep_classic_enemy,                 EP_CLASSIC_ENEMY                },
3936     { ep_belt,                          EP_BELT                         },
3937     { ep_belt_active,                   EP_BELT_ACTIVE                  },
3938     { ep_belt_switch,                   EP_BELT_SWITCH                  },
3939     { ep_tube,                          EP_TUBE                         },
3940     { ep_acid_pool,                     EP_ACID_POOL                    },
3941     { ep_keygate,                       EP_KEYGATE                      },
3942     { ep_amoeboid,                      EP_AMOEBOID                     },
3943     { ep_amoebalive,                    EP_AMOEBALIVE                   },
3944     { ep_has_editor_content,            EP_HAS_EDITOR_CONTENT           },
3945     { ep_can_turn_each_move,            EP_CAN_TURN_EACH_MOVE           },
3946     { ep_can_grow,                      EP_CAN_GROW                     },
3947     { ep_active_bomb,                   EP_ACTIVE_BOMB                  },
3948     { ep_inactive,                      EP_INACTIVE                     },
3949
3950     { ep_em_slippery_wall,              EP_EM_SLIPPERY_WALL             },
3951
3952     { ep_gfx_crumbled,                  EP_GFX_CRUMBLED                 },
3953
3954     { ep_editor_cascade_active,         EP_EDITOR_CASCADE_ACTIVE        },
3955     { ep_editor_cascade_inactive,       EP_EDITOR_CASCADE_INACTIVE      },
3956
3957     { ep_obsolete,                      EP_OBSOLETE                     },
3958
3959     { NULL,                             -1                              }
3960   };
3961
3962   int i, j, k;
3963
3964   /* always start with reliable default values (element has no properties) */
3965   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3966     for (j = 0; j < NUM_ELEMENT_PROPERTIES; j++)
3967       SET_PROPERTY(i, j, FALSE);
3968
3969   /* set all base element properties from above array definitions */
3970   for (i = 0; element_properties[i].elements != NULL; i++)
3971     for (j = 0; (element_properties[i].elements)[j] != -1; j++)
3972       SET_PROPERTY((element_properties[i].elements)[j],
3973                    element_properties[i].property, TRUE);
3974
3975   /* copy properties to some elements that are only stored in level file */
3976   for (i = 0; i < NUM_ELEMENT_PROPERTIES; i++)
3977     for (j = 0; copy_properties[j][0] != -1; j++)
3978       if (HAS_PROPERTY(copy_properties[j][0], i))
3979         for (k = 1; k <= 4; k++)
3980           SET_PROPERTY(copy_properties[j][k], i, TRUE);
3981
3982   /* set static element properties that are not listed in array definitions */
3983   for (i = EL_STEEL_CHAR_START; i <= EL_STEEL_CHAR_END; i++)
3984     SET_PROPERTY(i, EP_INDESTRUCTIBLE, TRUE);
3985 }
3986
3987 void InitElementPropertiesEngine(int engine_version)
3988 {
3989   static int no_wall_properties[] =
3990   {
3991     EP_DIGGABLE,
3992     EP_COLLECTIBLE_ONLY,
3993     EP_DONT_RUN_INTO,
3994     EP_DONT_COLLIDE_WITH,
3995     EP_CAN_MOVE,
3996     EP_CAN_FALL,
3997     EP_CAN_SMASH_PLAYER,
3998     EP_CAN_SMASH_ENEMIES,
3999     EP_CAN_SMASH_EVERYTHING,
4000     EP_PUSHABLE,
4001
4002     EP_PLAYER,
4003     EP_GEM,
4004     EP_FOOD_DARK_YAMYAM,
4005     EP_FOOD_PENGUIN,
4006     EP_BELT,
4007     EP_BELT_ACTIVE,
4008     EP_TUBE,
4009     EP_AMOEBOID,
4010     EP_AMOEBALIVE,
4011     EP_ACTIVE_BOMB,
4012
4013     EP_ACCESSIBLE,
4014
4015     -1
4016   };
4017
4018   int i, j;
4019
4020   /* important: after initialization in InitElementPropertiesStatic(), the
4021      elements are not again initialized to a default value; therefore all
4022      changes have to make sure that they leave the element with a defined
4023      property (which means that conditional property changes must be set to
4024      a reliable default value before) */
4025
4026   /* ---------- recursively resolve group elements ------------------------- */
4027
4028   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4029     for (j = 0; j < NUM_GROUP_ELEMENTS; j++)
4030       element_info[i].in_group[j] = FALSE;
4031
4032   for (i = 0; i < NUM_GROUP_ELEMENTS; i++)
4033     resolve_group_element(EL_GROUP_START + i, 0);
4034
4035   /* set all special, combined or engine dependent element properties */
4036   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4037   {
4038     /* ---------- INACTIVE ------------------------------------------------- */
4039     SET_PROPERTY(i, EP_INACTIVE, ((i >= EL_CHAR_START &&
4040                                    i <= EL_CHAR_END) ||
4041                                   (i >= EL_STEEL_CHAR_START &&
4042                                    i <= EL_STEEL_CHAR_END)));
4043
4044     /* ---------- WALKABLE, PASSABLE, ACCESSIBLE --------------------------- */
4045     SET_PROPERTY(i, EP_WALKABLE, (IS_WALKABLE_OVER(i) ||
4046                                   IS_WALKABLE_INSIDE(i) ||
4047                                   IS_WALKABLE_UNDER(i)));
4048
4049     SET_PROPERTY(i, EP_PASSABLE, (IS_PASSABLE_OVER(i) ||
4050                                   IS_PASSABLE_INSIDE(i) ||
4051                                   IS_PASSABLE_UNDER(i)));
4052
4053     SET_PROPERTY(i, EP_ACCESSIBLE_OVER, (IS_WALKABLE_OVER(i) ||
4054                                          IS_PASSABLE_OVER(i)));
4055
4056     SET_PROPERTY(i, EP_ACCESSIBLE_INSIDE, (IS_WALKABLE_INSIDE(i) ||
4057                                            IS_PASSABLE_INSIDE(i)));
4058
4059     SET_PROPERTY(i, EP_ACCESSIBLE_UNDER, (IS_WALKABLE_UNDER(i) ||
4060                                           IS_PASSABLE_UNDER(i)));
4061
4062     SET_PROPERTY(i, EP_ACCESSIBLE, (IS_WALKABLE(i) ||
4063                                     IS_PASSABLE(i)));
4064
4065     /* ---------- COLLECTIBLE ---------------------------------------------- */
4066     SET_PROPERTY(i, EP_COLLECTIBLE, (IS_COLLECTIBLE_ONLY(i) ||
4067                                      IS_DROPPABLE(i) ||
4068                                      IS_THROWABLE(i)));
4069
4070     /* ---------- SNAPPABLE ------------------------------------------------ */
4071     SET_PROPERTY(i, EP_SNAPPABLE, (IS_DIGGABLE(i) ||
4072                                    IS_COLLECTIBLE(i) ||
4073                                    IS_SWITCHABLE(i) ||
4074                                    i == EL_BD_ROCK));
4075
4076     /* ---------- WALL ----------------------------------------------------- */
4077     SET_PROPERTY(i, EP_WALL, TRUE);     /* default: element is wall */
4078
4079     for (j = 0; no_wall_properties[j] != -1; j++)
4080       if (HAS_PROPERTY(i, no_wall_properties[j]) ||
4081           i >= EL_FIRST_RUNTIME_UNREAL)
4082         SET_PROPERTY(i, EP_WALL, FALSE);
4083
4084     if (IS_HISTORIC_WALL(i))
4085       SET_PROPERTY(i, EP_WALL, TRUE);
4086
4087     /* ---------- SOLID_FOR_PUSHING ---------------------------------------- */
4088     if (engine_version < VERSION_IDENT(2,2,0,0))
4089       SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, IS_HISTORIC_SOLID(i));
4090     else
4091       SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, (!IS_WALKABLE(i) &&
4092                                              !IS_DIGGABLE(i) &&
4093                                              !IS_COLLECTIBLE(i)));
4094
4095     /* ---------- DRAGONFIRE_PROOF ----------------------------------------- */
4096     if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
4097       SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE);
4098     else
4099       SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_CUSTOM_ELEMENT(i) &&
4100                                             IS_INDESTRUCTIBLE(i)));
4101
4102     /* ---------- EXPLOSION_PROOF ------------------------------------------ */
4103     if (i == EL_FLAMES)
4104       SET_PROPERTY(i, EP_EXPLOSION_PROOF, TRUE);
4105     else if (engine_version < VERSION_IDENT(2,2,0,0))
4106       SET_PROPERTY(i, EP_EXPLOSION_PROOF, IS_INDESTRUCTIBLE(i));
4107     else
4108       SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
4109                                            (!IS_WALKABLE(i) ||
4110                                             IS_PROTECTED(i))));
4111
4112     if (IS_CUSTOM_ELEMENT(i))
4113     {
4114       /* these are additional properties which are initially false when set */
4115
4116       /* ---------- DONT_COLLIDE_WITH / DONT_RUN_INTO ---------------------- */
4117       if (DONT_TOUCH(i))
4118         SET_PROPERTY(i, EP_DONT_COLLIDE_WITH, TRUE);
4119       if (DONT_COLLIDE_WITH(i))
4120         SET_PROPERTY(i, EP_DONT_RUN_INTO, TRUE);
4121
4122       /* ---------- CAN_SMASH_ENEMIES / CAN_SMASH_PLAYER ------------------- */
4123       if (CAN_SMASH_EVERYTHING(i))
4124         SET_PROPERTY(i, EP_CAN_SMASH_ENEMIES, TRUE);
4125       if (CAN_SMASH_ENEMIES(i))
4126         SET_PROPERTY(i, EP_CAN_SMASH_PLAYER, TRUE);
4127     }
4128
4129     /* ---------- CAN_SMASH ------------------------------------------------ */
4130     SET_PROPERTY(i, EP_CAN_SMASH, (CAN_SMASH_PLAYER(i) ||
4131                                    CAN_SMASH_ENEMIES(i) ||
4132                                    CAN_SMASH_EVERYTHING(i)));
4133
4134     /* ---------- CAN_EXPLODE_BY_FIRE -------------------------------------- */
4135     SET_PROPERTY(i, EP_CAN_EXPLODE_BY_FIRE, (CAN_EXPLODE(i) &&
4136                                              EXPLODES_BY_FIRE(i)));
4137
4138     /* ---------- CAN_EXPLODE_SMASHED -------------------------------------- */
4139     SET_PROPERTY(i, EP_CAN_EXPLODE_SMASHED, (CAN_EXPLODE(i) &&
4140                                              EXPLODES_SMASHED(i)));
4141
4142     /* ---------- CAN_EXPLODE_IMPACT --------------------------------------- */
4143     SET_PROPERTY(i, EP_CAN_EXPLODE_IMPACT, (CAN_EXPLODE(i) &&
4144                                             EXPLODES_IMPACT(i)));
4145
4146     /* ---------- CAN_EXPLODE_BY_DRAGONFIRE -------------------------------- */
4147     SET_PROPERTY(i, EP_CAN_EXPLODE_BY_DRAGONFIRE, CAN_EXPLODE_BY_FIRE(i));
4148
4149     /* ---------- CAN_EXPLODE_BY_EXPLOSION --------------------------------- */
4150     SET_PROPERTY(i, EP_CAN_EXPLODE_BY_EXPLOSION, (CAN_EXPLODE_BY_FIRE(i) ||
4151                                                   i == EL_BLACK_ORB));
4152
4153     /* ---------- COULD_MOVE_INTO_ACID ------------------------------------- */
4154     SET_PROPERTY(i, EP_COULD_MOVE_INTO_ACID, (ELEM_IS_PLAYER(i) ||
4155                                               CAN_MOVE(i) ||
4156                                               IS_CUSTOM_ELEMENT(i)));
4157
4158     /* ---------- MAYBE_DONT_COLLIDE_WITH ---------------------------------- */
4159     SET_PROPERTY(i, EP_MAYBE_DONT_COLLIDE_WITH, (i == EL_SP_SNIKSNAK ||
4160                                                  i == EL_SP_ELECTRON));
4161
4162     /* ---------- CAN_MOVE_INTO_ACID --------------------------------------- */
4163     if (COULD_MOVE_INTO_ACID(i) && !IS_CUSTOM_ELEMENT(i))
4164       SET_PROPERTY(i, EP_CAN_MOVE_INTO_ACID,
4165                    getMoveIntoAcidProperty(&level, i));
4166
4167     /* ---------- DONT_COLLIDE_WITH ---------------------------------------- */
4168     if (MAYBE_DONT_COLLIDE_WITH(i))
4169       SET_PROPERTY(i, EP_DONT_COLLIDE_WITH,
4170                    getDontCollideWithProperty(&level, i));
4171
4172     /* ---------- SP_PORT -------------------------------------------------- */
4173     SET_PROPERTY(i, EP_SP_PORT, (IS_SP_ELEMENT(i) &&
4174                                  IS_PASSABLE_INSIDE(i)));
4175
4176     /* ---------- CAN_BE_CLONED_BY_ANDROID --------------------------------- */
4177     for (j = 0; j < level.num_android_clone_elements; j++)
4178       SET_PROPERTY(i, EP_CAN_BE_CLONED_BY_ANDROID,
4179                    (i != EL_EMPTY &&
4180                     IS_EQUAL_OR_IN_GROUP(i, level.android_clone_element[j])));
4181
4182     /* ---------- CAN_CHANGE ----------------------------------------------- */
4183     SET_PROPERTY(i, EP_CAN_CHANGE, FALSE);      /* default: cannot change */
4184     for (j = 0; j < element_info[i].num_change_pages; j++)
4185       if (element_info[i].change_page[j].can_change)
4186         SET_PROPERTY(i, EP_CAN_CHANGE, TRUE);
4187
4188     /* ---------- HAS_ACTION ----------------------------------------------- */
4189     SET_PROPERTY(i, EP_HAS_ACTION, FALSE);      /* default: has no action */
4190     for (j = 0; j < element_info[i].num_change_pages; j++)
4191       if (element_info[i].change_page[j].has_action)
4192         SET_PROPERTY(i, EP_HAS_ACTION, TRUE);
4193
4194     /* ---------- CAN_CHANGE_OR_HAS_ACTION --------------------------------- */
4195     SET_PROPERTY(i, EP_CAN_CHANGE_OR_HAS_ACTION, (CAN_CHANGE(i) ||
4196                                                   HAS_ACTION(i)));
4197
4198     /* ---------- GFX_CRUMBLED --------------------------------------------- */
4199 #if 1
4200     SET_PROPERTY(i, EP_GFX_CRUMBLED,
4201                  element_info[i].crumbled[ACTION_DEFAULT] !=
4202                  element_info[i].graphic[ACTION_DEFAULT]);
4203 #else
4204     /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
4205     SET_PROPERTY(i, EP_GFX_CRUMBLED,
4206                  element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
4207 #endif
4208
4209     /* ---------- EDITOR_CASCADE ------------------------------------------- */
4210     SET_PROPERTY(i, EP_EDITOR_CASCADE, (IS_EDITOR_CASCADE_ACTIVE(i) ||
4211                                         IS_EDITOR_CASCADE_INACTIVE(i)));
4212   }
4213
4214   /* dynamically adjust element properties according to game engine version */
4215   {
4216     static int ep_em_slippery_wall[] =
4217     {
4218       EL_WALL,
4219       EL_STEELWALL,
4220       EL_EXPANDABLE_WALL,
4221       EL_EXPANDABLE_WALL_HORIZONTAL,
4222       EL_EXPANDABLE_WALL_VERTICAL,
4223       EL_EXPANDABLE_WALL_ANY,
4224       EL_EXPANDABLE_STEELWALL_HORIZONTAL,
4225       EL_EXPANDABLE_STEELWALL_VERTICAL,
4226       EL_EXPANDABLE_STEELWALL_ANY,
4227       EL_EXPANDABLE_STEELWALL_GROWING,
4228       -1
4229     };
4230
4231     /* special EM style gems behaviour */
4232     for (i = 0; ep_em_slippery_wall[i] != -1; i++)
4233       SET_PROPERTY(ep_em_slippery_wall[i], EP_EM_SLIPPERY_WALL,
4234                    level.em_slippery_gems);
4235
4236     /* "EL_EXPANDABLE_WALL_GROWING" wasn't slippery for EM gems in 2.0.1 */
4237     SET_PROPERTY(EL_EXPANDABLE_WALL_GROWING, EP_EM_SLIPPERY_WALL,
4238                  (level.em_slippery_gems &&
4239                   engine_version > VERSION_IDENT(2,0,1,0)));
4240   }
4241
4242   /* this is needed because some graphics depend on element properties */
4243   if (game_status == GAME_MODE_PLAYING)
4244     InitElementGraphicInfo();
4245 }
4246
4247 void InitElementPropertiesAfterLoading(int engine_version)
4248 {
4249   int i;
4250
4251   /* set some other uninitialized values of custom elements in older levels */
4252   if (engine_version < VERSION_IDENT(3,1,0,0))
4253   {
4254     for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
4255     {
4256       int element = EL_CUSTOM_START + i;
4257
4258       element_info[element].access_direction = MV_ALL_DIRECTIONS;
4259
4260       element_info[element].explosion_delay = 17;
4261       element_info[element].ignition_delay = 8;
4262     }
4263   }
4264 }
4265
4266 static void InitGlobal()
4267 {
4268   int i;
4269
4270   for (i = 0; i < MAX_NUM_ELEMENTS + 1; i++)
4271   {
4272     /* check if element_name_info entry defined for each element in "main.h" */
4273     if (i < MAX_NUM_ELEMENTS && element_name_info[i].token_name == NULL)
4274       Error(ERR_EXIT, "undefined 'element_name_info' entry for element %d", i);
4275
4276     element_info[i].token_name = element_name_info[i].token_name;
4277     element_info[i].class_name = element_name_info[i].class_name;
4278     element_info[i].editor_description=element_name_info[i].editor_description;
4279
4280 #if 0
4281     printf("%04d: %s\n", i, element_name_info[i].token_name);
4282 #endif
4283   }
4284
4285   global.autoplay_leveldir = NULL;
4286   global.convert_leveldir = NULL;
4287
4288   global.frames_per_second = 0;
4289   global.fps_slowdown = FALSE;
4290   global.fps_slowdown_factor = 1;
4291 }
4292
4293 void Execute_Command(char *command)
4294 {
4295   int i;
4296
4297   if (strEqual(command, "print graphicsinfo.conf"))
4298   {
4299     printf("# You can configure additional/alternative image files here.\n");
4300     printf("# (The entries below are default and therefore commented out.)\n");
4301     printf("\n");
4302     printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
4303     printf("\n");
4304     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
4305     printf("\n");
4306
4307     for (i = 0; image_config[i].token != NULL; i++)
4308       printf("# %s\n", getFormattedSetupEntry(image_config[i].token,
4309                                               image_config[i].value));
4310
4311     exit(0);
4312   }
4313   else if (strEqual(command, "print soundsinfo.conf"))
4314   {
4315     printf("# You can configure additional/alternative sound files here.\n");
4316     printf("# (The entries below are default and therefore commented out.)\n");
4317     printf("\n");
4318     printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
4319     printf("\n");
4320     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
4321     printf("\n");
4322
4323     for (i = 0; sound_config[i].token != NULL; i++)
4324       printf("# %s\n", getFormattedSetupEntry(sound_config[i].token,
4325                                               sound_config[i].value));
4326
4327     exit(0);
4328   }
4329   else if (strEqual(command, "print musicinfo.conf"))
4330   {
4331     printf("# You can configure additional/alternative music files here.\n");
4332     printf("# (The entries below are default and therefore commented out.)\n");
4333     printf("\n");
4334     printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
4335     printf("\n");
4336     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
4337     printf("\n");
4338
4339     for (i = 0; music_config[i].token != NULL; i++)
4340       printf("# %s\n", getFormattedSetupEntry(music_config[i].token,
4341                                               music_config[i].value));
4342
4343     exit(0);
4344   }
4345   else if (strEqual(command, "print editorsetup.conf"))
4346   {
4347     printf("# You can configure your personal editor element list here.\n");
4348     printf("# (The entries below are default and therefore commented out.)\n");
4349     printf("\n");
4350
4351     /* this is needed to be able to check element list for cascade elements */
4352     InitElementPropertiesStatic();
4353     InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
4354
4355     PrintEditorElementList();
4356
4357     exit(0);
4358   }
4359   else if (strEqual(command, "print helpanim.conf"))
4360   {
4361     printf("# You can configure different element help animations here.\n");
4362     printf("# (The entries below are default and therefore commented out.)\n");
4363     printf("\n");
4364
4365     for (i = 0; helpanim_config[i].token != NULL; i++)
4366     {
4367       printf("# %s\n", getFormattedSetupEntry(helpanim_config[i].token,
4368                                               helpanim_config[i].value));
4369
4370       if (strEqual(helpanim_config[i].token, "end"))
4371         printf("#\n");
4372     }
4373
4374     exit(0);
4375   }
4376   else if (strEqual(command, "print helptext.conf"))
4377   {
4378     printf("# You can configure different element help text here.\n");
4379     printf("# (The entries below are default and therefore commented out.)\n");
4380     printf("\n");
4381
4382     for (i = 0; helptext_config[i].token != NULL; i++)
4383       printf("# %s\n", getFormattedSetupEntry(helptext_config[i].token,
4384                                               helptext_config[i].value));
4385
4386     exit(0);
4387   }
4388   else if (strncmp(command, "dump level ", 11) == 0)
4389   {
4390     char *filename = &command[11];
4391
4392     if (!fileExists(filename))
4393       Error(ERR_EXIT, "cannot open file '%s'", filename);
4394
4395     LoadLevelFromFilename(&level, filename);
4396     DumpLevel(&level);
4397
4398     exit(0);
4399   }
4400   else if (strncmp(command, "dump tape ", 10) == 0)
4401   {
4402     char *filename = &command[10];
4403
4404     if (!fileExists(filename))
4405       Error(ERR_EXIT, "cannot open file '%s'", filename);
4406
4407     LoadTapeFromFilename(filename);
4408     DumpTape(&tape);
4409
4410     exit(0);
4411   }
4412   else if (strncmp(command, "autoplay ", 9) == 0)
4413   {
4414     char *str_ptr = getStringCopy(&command[9]); /* read command parameters */
4415
4416     while (*str_ptr != '\0')                    /* continue parsing string */
4417     {
4418       /* cut leading whitespace from string, replace it by string terminator */
4419       while (*str_ptr == ' ' || *str_ptr == '\t')
4420         *str_ptr++ = '\0';
4421
4422       if (*str_ptr == '\0')                     /* end of string reached */
4423         break;
4424
4425       if (global.autoplay_leveldir == NULL)     /* read level set string */
4426       {
4427         global.autoplay_leveldir = str_ptr;
4428         global.autoplay_all = TRUE;             /* default: play all tapes */
4429
4430         for (i = 0; i < MAX_TAPES_PER_SET; i++)
4431           global.autoplay_level[i] = FALSE;
4432       }
4433       else                                      /* read level number string */
4434       {
4435         int level_nr = atoi(str_ptr);           /* get level_nr value */
4436
4437         if (level_nr >= 0 && level_nr < MAX_TAPES_PER_SET)
4438           global.autoplay_level[level_nr] = TRUE;
4439
4440         global.autoplay_all = FALSE;
4441       }
4442
4443       /* advance string pointer to the next whitespace (or end of string) */
4444       while (*str_ptr != ' ' && *str_ptr != '\t' && *str_ptr != '\0')
4445         str_ptr++;
4446     }
4447   }
4448   else if (strncmp(command, "convert ", 8) == 0)
4449   {
4450     char *str_copy = getStringCopy(&command[8]);
4451     char *str_ptr = strchr(str_copy, ' ');
4452
4453     global.convert_leveldir = str_copy;
4454     global.convert_level_nr = -1;
4455
4456     if (str_ptr != NULL)                        /* level number follows */
4457     {
4458       *str_ptr++ = '\0';                        /* terminate leveldir string */
4459       global.convert_level_nr = atoi(str_ptr);  /* get level_nr value */
4460     }
4461   }
4462
4463 #if DEBUG
4464 #if defined(TARGET_SDL)
4465   else if (strEqual(command, "SDL_ListModes"))
4466   {
4467     SDL_Rect **modes;
4468     int i;
4469
4470     SDL_Init(SDL_INIT_VIDEO);
4471
4472     /* get available fullscreen/hardware modes */
4473     modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
4474
4475     /* check if there are any modes available */
4476     if (modes == NULL)
4477     {
4478       printf("No modes available!\n");
4479
4480       exit(-1);
4481     }
4482
4483     /* check if our resolution is restricted */
4484     if (modes == (SDL_Rect **)-1)
4485     {
4486       printf("All resolutions available.\n");
4487     }
4488     else
4489     {
4490       printf("Available Modes:\n");
4491
4492       for(i = 0; modes[i]; i++)
4493         printf("  %d x %d\n", modes[i]->w, modes[i]->h);
4494     }
4495
4496     exit(0);
4497   }
4498 #endif
4499 #endif
4500
4501   else
4502   {
4503     Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
4504   }
4505 }
4506
4507 static void InitSetup()
4508 {
4509   LoadSetup();                                  /* global setup info */
4510
4511   /* set some options from setup file */
4512
4513   if (setup.options.verbose)
4514     options.verbose = TRUE;
4515 }
4516
4517 static void InitGameInfo()
4518 {
4519   game.restart_level = FALSE;
4520 }
4521
4522 static void InitPlayerInfo()
4523 {
4524   int i;
4525
4526   /* choose default local player */
4527   local_player = &stored_player[0];
4528
4529   for (i = 0; i < MAX_PLAYERS; i++)
4530     stored_player[i].connected = FALSE;
4531
4532   local_player->connected = TRUE;
4533 }
4534
4535 static void InitArtworkInfo()
4536 {
4537   LoadArtworkInfo();
4538 }
4539
4540 static char *get_string_in_brackets(char *string)
4541 {
4542   char *string_in_brackets = checked_malloc(strlen(string) + 3);
4543
4544   sprintf(string_in_brackets, "[%s]", string);
4545
4546   return string_in_brackets;
4547 }
4548
4549 static char *get_level_id_suffix(int id_nr)
4550 {
4551   char *id_suffix = checked_malloc(1 + 3 + 1);
4552
4553   if (id_nr < 0 || id_nr > 999)
4554     id_nr = 0;
4555
4556   sprintf(id_suffix, ".%03d", id_nr);
4557
4558   return id_suffix;
4559 }
4560
4561 #if 0
4562 static char *get_element_class_token(int element)
4563 {
4564   char *element_class_name = element_info[element].class_name;
4565   char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
4566
4567   sprintf(element_class_token, "[%s]", element_class_name);
4568
4569   return element_class_token;
4570 }
4571
4572 static char *get_action_class_token(int action)
4573 {
4574   char *action_class_name = &element_action_info[action].suffix[1];
4575   char *action_class_token = checked_malloc(strlen(action_class_name) + 3);
4576
4577   sprintf(action_class_token, "[%s]", action_class_name);
4578
4579   return action_class_token;
4580 }
4581 #endif
4582
4583 static void InitArtworkConfig()
4584 {
4585   static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
4586   static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + 1];
4587   static char *music_id_prefix[NUM_MUSIC_PREFIXES + 1];
4588   static char *action_id_suffix[NUM_ACTIONS + 1];
4589   static char *direction_id_suffix[NUM_DIRECTIONS_FULL + 1];
4590   static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
4591   static char *level_id_suffix[MAX_LEVELS + 1];
4592   static char *dummy[1] = { NULL };
4593   static char *ignore_generic_tokens[] =
4594   {
4595     "name",
4596     "sort_priority",
4597     NULL
4598   };
4599   static char **ignore_image_tokens;
4600   static char **ignore_sound_tokens;
4601   static char **ignore_music_tokens;
4602   int num_ignore_generic_tokens;
4603   int num_ignore_image_tokens;
4604   int num_ignore_sound_tokens;
4605   int num_ignore_music_tokens;
4606   int i;
4607
4608   /* dynamically determine list of generic tokens to be ignored */
4609   num_ignore_generic_tokens = 0;
4610   for (i = 0; ignore_generic_tokens[i] != NULL; i++)
4611     num_ignore_generic_tokens++;
4612
4613   /* dynamically determine list of image tokens to be ignored */
4614   num_ignore_image_tokens = num_ignore_generic_tokens;
4615   for (i = 0; image_config_vars[i].token != NULL; i++)
4616     num_ignore_image_tokens++;
4617   ignore_image_tokens =
4618     checked_malloc((num_ignore_image_tokens + 1) * sizeof(char *));
4619   for (i = 0; i < num_ignore_generic_tokens; i++)
4620     ignore_image_tokens[i] = ignore_generic_tokens[i];
4621   for (i = 0; i < num_ignore_image_tokens - num_ignore_generic_tokens; i++)
4622     ignore_image_tokens[num_ignore_generic_tokens + i] =
4623       image_config_vars[i].token;
4624   ignore_image_tokens[num_ignore_image_tokens] = NULL;
4625
4626   /* dynamically determine list of sound tokens to be ignored */
4627   num_ignore_sound_tokens = num_ignore_generic_tokens;
4628   ignore_sound_tokens =
4629     checked_malloc((num_ignore_sound_tokens + 1) * sizeof(char *));
4630   for (i = 0; i < num_ignore_generic_tokens; i++)
4631     ignore_sound_tokens[i] = ignore_generic_tokens[i];
4632   ignore_sound_tokens[num_ignore_sound_tokens] = NULL;
4633
4634   /* dynamically determine list of music tokens to be ignored */
4635   num_ignore_music_tokens = num_ignore_generic_tokens;
4636   ignore_music_tokens =
4637     checked_malloc((num_ignore_music_tokens + 1) * sizeof(char *));
4638   for (i = 0; i < num_ignore_generic_tokens; i++)
4639     ignore_music_tokens[i] = ignore_generic_tokens[i];
4640   ignore_music_tokens[num_ignore_music_tokens] = NULL;
4641
4642   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4643     image_id_prefix[i] = element_info[i].token_name;
4644   for (i = 0; i < NUM_FONTS; i++)
4645     image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
4646   image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
4647
4648   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4649     sound_id_prefix[i] = element_info[i].token_name;
4650   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4651     sound_id_prefix[MAX_NUM_ELEMENTS + i] =
4652       get_string_in_brackets(element_info[i].class_name);
4653   sound_id_prefix[2 * MAX_NUM_ELEMENTS] = NULL;
4654
4655   for (i = 0; i < NUM_MUSIC_PREFIXES; i++)
4656     music_id_prefix[i] = music_prefix_info[i].prefix;
4657   music_id_prefix[NUM_MUSIC_PREFIXES] = NULL;
4658
4659   for (i = 0; i < NUM_ACTIONS; i++)
4660     action_id_suffix[i] = element_action_info[i].suffix;
4661   action_id_suffix[NUM_ACTIONS] = NULL;
4662
4663   for (i = 0; i < NUM_DIRECTIONS_FULL; i++)
4664     direction_id_suffix[i] = element_direction_info[i].suffix;
4665   direction_id_suffix[NUM_DIRECTIONS_FULL] = NULL;
4666
4667   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
4668     special_id_suffix[i] = special_suffix_info[i].suffix;
4669   special_id_suffix[NUM_SPECIAL_GFX_ARGS] = NULL;
4670
4671   for (i = 0; i < MAX_LEVELS; i++)
4672     level_id_suffix[i] = get_level_id_suffix(i);
4673   level_id_suffix[MAX_LEVELS] = NULL;
4674
4675   InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
4676                 image_id_prefix, action_id_suffix, direction_id_suffix,
4677                 special_id_suffix, ignore_image_tokens);
4678   InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
4679                 sound_id_prefix, action_id_suffix, dummy,
4680                 special_id_suffix, ignore_sound_tokens);
4681   InitMusicList(music_config, NUM_MUSIC_FILES, music_config_suffix,
4682                 music_id_prefix, special_id_suffix, level_id_suffix,
4683                 dummy, ignore_music_tokens);
4684 }
4685
4686 static void InitMixer()
4687 {
4688   OpenAudio();
4689   StartMixer();
4690 }
4691
4692 void InitGfx()
4693 {
4694   char *filename_font_initial = NULL;
4695   Bitmap *bitmap_font_initial = NULL;
4696   int font_height;
4697   int i, j;
4698
4699   /* determine settings for initial font (for displaying startup messages) */
4700   for (i = 0; image_config[i].token != NULL; i++)
4701   {
4702     for (j = 0; j < NUM_INITIAL_FONTS; j++)
4703     {
4704       char font_token[128];
4705       int len_font_token;
4706
4707       sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1);
4708       len_font_token = strlen(font_token);
4709
4710       if (strEqual(image_config[i].token, font_token))
4711         filename_font_initial = image_config[i].value;
4712       else if (strlen(image_config[i].token) > len_font_token &&
4713                strncmp(image_config[i].token, font_token, len_font_token) == 0)
4714       {
4715         if (strEqual(&image_config[i].token[len_font_token], ".x"))
4716           font_initial[j].src_x = atoi(image_config[i].value);
4717         else if (strEqual(&image_config[i].token[len_font_token], ".y"))
4718           font_initial[j].src_y = atoi(image_config[i].value);
4719         else if (strEqual(&image_config[i].token[len_font_token], ".width"))
4720           font_initial[j].width = atoi(image_config[i].value);
4721         else if (strEqual(&image_config[i].token[len_font_token],".height"))
4722           font_initial[j].height = atoi(image_config[i].value);
4723       }
4724     }
4725   }
4726
4727   for (j = 0; j < NUM_INITIAL_FONTS; j++)
4728   {
4729     font_initial[j].num_chars = DEFAULT_NUM_CHARS_PER_FONT;
4730     font_initial[j].num_chars_per_line = DEFAULT_NUM_CHARS_PER_LINE;
4731   }
4732
4733   if (filename_font_initial == NULL)    /* should not happen */
4734     Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
4735
4736   /* create additional image buffers for double-buffering and cross-fading */
4737   bitmap_db_cross = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
4738   bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
4739   bitmap_db_panel = CreateBitmap(DXSIZE, DYSIZE, DEFAULT_DEPTH);
4740   bitmap_db_door  = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
4741
4742   /* initialize screen properties */
4743   InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
4744                    REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
4745                    bitmap_db_field);
4746   InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
4747   InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
4748   InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
4749
4750   bitmap_font_initial = LoadCustomImage(filename_font_initial);
4751
4752   for (j = 0; j < NUM_INITIAL_FONTS; j++)
4753     font_initial[j].bitmap = bitmap_font_initial;
4754
4755   InitFontGraphicInfo();
4756
4757   font_height = getFontHeight(FC_RED);
4758
4759 #if 1
4760   DrawInitText(getWindowTitleString(), 20, FC_YELLOW);
4761 #else
4762   DrawInitText(getProgramInitString(), 20, FC_YELLOW);
4763 #endif
4764   DrawInitText(PROGRAM_COPYRIGHT_STRING, 50, FC_RED);
4765   DrawInitText(PROGRAM_WEBSITE_STRING, WIN_YSIZE - 20 - font_height, FC_RED);
4766
4767   DrawInitText("Loading graphics", 120, FC_GREEN);
4768 }
4769
4770 void RedrawBackground()
4771 {
4772   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
4773              0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
4774
4775   redraw_mask = REDRAW_ALL;
4776 }
4777
4778 void InitGfxBackground()
4779 {
4780   int x, y;
4781
4782   fieldbuffer = bitmap_db_field;
4783   SetDrawtoField(DRAW_BACKBUFFER);
4784
4785   RedrawBackground();
4786
4787   ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
4788   ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
4789
4790   for (x = 0; x < MAX_BUF_XSIZE; x++)
4791     for (y = 0; y < MAX_BUF_YSIZE; y++)
4792       redraw[x][y] = 0;
4793   redraw_tiles = 0;
4794   redraw_mask = REDRAW_ALL;
4795 }
4796
4797 static void InitLevelInfo()
4798 {
4799   LoadLevelInfo();                              /* global level info */
4800   LoadLevelSetup_LastSeries();                  /* last played series info */
4801   LoadLevelSetup_SeriesInfo();                  /* last played level info */
4802 }
4803
4804 void InitLevelArtworkInfo()
4805 {
4806   LoadLevelArtworkInfo();
4807 }
4808
4809 static void InitImages()
4810 {
4811   setLevelArtworkDir(artwork.gfx_first);
4812
4813 #if 0
4814   printf("::: InitImages for '%s' ['%s', '%s'] ['%s', '%s']\n",
4815          leveldir_current->identifier,
4816          artwork.gfx_current_identifier,
4817          artwork.gfx_current->identifier,
4818          leveldir_current->graphics_set,
4819          leveldir_current->graphics_path);
4820 #endif
4821
4822   ReloadCustomImages();
4823
4824   LoadCustomElementDescriptions();
4825   LoadSpecialMenuDesignSettings();
4826
4827   ReinitializeGraphics();
4828 }
4829
4830 static void InitSound(char *identifier)
4831 {
4832   if (identifier == NULL)
4833     identifier = artwork.snd_current->identifier;
4834
4835   /* set artwork path to send it to the sound server process */
4836   setLevelArtworkDir(artwork.snd_first);
4837
4838   InitReloadCustomSounds(identifier);
4839   ReinitializeSounds();
4840 }
4841
4842 static void InitMusic(char *identifier)
4843 {
4844   if (identifier == NULL)
4845     identifier = artwork.mus_current->identifier;
4846
4847   /* set artwork path to send it to the sound server process */
4848   setLevelArtworkDir(artwork.mus_first);
4849
4850   InitReloadCustomMusic(identifier);
4851   ReinitializeMusic();
4852 }
4853
4854 void InitNetworkServer()
4855 {
4856 #if defined(NETWORK_AVALIABLE)
4857   int nr_wanted;
4858 #endif
4859
4860   if (!options.network)
4861     return;
4862
4863 #if defined(NETWORK_AVALIABLE)
4864   nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
4865
4866   if (!ConnectToServer(options.server_host, options.server_port))
4867     Error(ERR_EXIT, "cannot connect to network game server");
4868
4869   SendToServer_PlayerName(setup.player_name);
4870   SendToServer_ProtocolVersion();
4871
4872   if (nr_wanted)
4873     SendToServer_NrWanted(nr_wanted);
4874 #endif
4875 }
4876
4877 static char *getNewArtworkIdentifier(int type)
4878 {
4879   static char *leveldir_current_identifier[3] = { NULL, NULL, NULL };
4880   static boolean last_override_level_artwork[3] = { FALSE, FALSE, FALSE };
4881   static boolean last_has_level_artwork_set[3] = { FALSE, FALSE, FALSE };
4882   static boolean initialized[3] = { FALSE, FALSE, FALSE };
4883   TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
4884   boolean setup_override_artwork = SETUP_OVERRIDE_ARTWORK(setup, type);
4885   char *setup_artwork_set = SETUP_ARTWORK_SET(setup, type);
4886   char *leveldir_identifier = leveldir_current->identifier;
4887 #if 1
4888   /* !!! setLevelArtworkDir() should be moved to an earlier stage !!! */
4889   char *leveldir_artwork_set = setLevelArtworkDir(artwork_first_node);
4890 #else
4891   char *leveldir_artwork_set = LEVELDIR_ARTWORK_SET(leveldir_current, type);
4892 #endif
4893   boolean has_level_artwork_set = (leveldir_artwork_set != NULL);
4894   char *artwork_current_identifier;
4895   char *artwork_new_identifier = NULL;  /* default: nothing has changed */
4896
4897   /* leveldir_current may be invalid (level group, parent link) */
4898   if (!validLevelSeries(leveldir_current))
4899     return NULL;
4900
4901   /* 1st step: determine artwork set to be activated in descending order:
4902      --------------------------------------------------------------------
4903      1. setup artwork (when configured to override everything else)
4904      2. artwork set configured in "levelinfo.conf" of current level set
4905         (artwork in level directory will have priority when loading later)
4906      3. artwork in level directory (stored in artwork sub-directory)
4907      4. setup artwork (currently configured in setup menu) */
4908
4909   if (setup_override_artwork)
4910     artwork_current_identifier = setup_artwork_set;
4911   else if (leveldir_artwork_set != NULL)
4912     artwork_current_identifier = leveldir_artwork_set;
4913   else if (getTreeInfoFromIdentifier(artwork_first_node, leveldir_identifier))
4914     artwork_current_identifier = leveldir_identifier;
4915   else
4916     artwork_current_identifier = setup_artwork_set;
4917
4918
4919   /* 2nd step: check if it is really needed to reload artwork set
4920      ------------------------------------------------------------ */
4921
4922 #if 0
4923   if (type == ARTWORK_TYPE_GRAPHICS)
4924     printf("::: 0: '%s' ['%s', '%s'] ['%s' ('%s')]\n",
4925            artwork_new_identifier,
4926            ARTWORK_CURRENT_IDENTIFIER(artwork, type),
4927            artwork_current_identifier,
4928            leveldir_current->graphics_set,
4929            leveldir_current->identifier);
4930 #endif
4931
4932   /* ---------- reload if level set and also artwork set has changed ------- */
4933   if (leveldir_current_identifier[type] != leveldir_identifier &&
4934       (last_has_level_artwork_set[type] || has_level_artwork_set))
4935     artwork_new_identifier = artwork_current_identifier;
4936
4937   leveldir_current_identifier[type] = leveldir_identifier;
4938   last_has_level_artwork_set[type] = has_level_artwork_set;
4939
4940 #if 0
4941   if (type == ARTWORK_TYPE_GRAPHICS)
4942     printf("::: 1: '%s'\n", artwork_new_identifier);
4943 #endif
4944
4945   /* ---------- reload if "override artwork" setting has changed ----------- */
4946   if (last_override_level_artwork[type] != setup_override_artwork)
4947     artwork_new_identifier = artwork_current_identifier;
4948
4949   last_override_level_artwork[type] = setup_override_artwork;
4950
4951 #if 0
4952   if (type == ARTWORK_TYPE_GRAPHICS)
4953     printf("::: 2: '%s'\n", artwork_new_identifier);
4954 #endif
4955
4956   /* ---------- reload if current artwork identifier has changed ----------- */
4957   if (!strEqual(ARTWORK_CURRENT_IDENTIFIER(artwork, type),
4958                 artwork_current_identifier))
4959     artwork_new_identifier = artwork_current_identifier;
4960
4961   *(ARTWORK_CURRENT_IDENTIFIER_PTR(artwork, type))= artwork_current_identifier;
4962
4963 #if 0
4964   if (type == ARTWORK_TYPE_GRAPHICS)
4965     printf("::: 3: '%s'\n", artwork_new_identifier);
4966 #endif
4967
4968   /* ---------- do not reload directly after starting ---------------------- */
4969   if (!initialized[type])
4970     artwork_new_identifier = NULL;
4971
4972   initialized[type] = TRUE;
4973
4974 #if 0
4975   if (type == ARTWORK_TYPE_GRAPHICS)
4976     printf("::: 4: '%s'\n", artwork_new_identifier);
4977 #endif
4978
4979 #if 0
4980   if (type == ARTWORK_TYPE_GRAPHICS)
4981     printf("CHECKING OLD/NEW GFX:\n- OLD: %s\n- NEW: %s ['%s', '%s'] ['%s']\n",
4982            artwork.gfx_current_identifier, artwork_current_identifier,
4983            artwork.gfx_current->identifier, leveldir_current->graphics_set,
4984            artwork_new_identifier);
4985 #endif
4986
4987   return artwork_new_identifier;
4988 }
4989
4990 void ReloadCustomArtwork(int force_reload)
4991 {
4992   char *gfx_new_identifier;
4993   char *snd_new_identifier;
4994   char *mus_new_identifier;
4995   boolean force_reload_gfx = (force_reload & (1 << ARTWORK_TYPE_GRAPHICS));
4996   boolean force_reload_snd = (force_reload & (1 << ARTWORK_TYPE_SOUNDS));
4997   boolean force_reload_mus = (force_reload & (1 << ARTWORK_TYPE_MUSIC));
4998   boolean redraw_screen = FALSE;
4999
5000   force_reload_gfx |= AdjustGraphicsForEMC();
5001
5002   gfx_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_GRAPHICS);
5003   snd_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_SOUNDS);
5004   mus_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_MUSIC);
5005
5006   if (gfx_new_identifier != NULL || force_reload_gfx)
5007   {
5008 #if 0
5009     printf("RELOADING GRAPHICS '%s' -> '%s' ['%s', '%s']\n",
5010            artwork.gfx_current_identifier,
5011            gfx_new_identifier,
5012            artwork.gfx_current->identifier,
5013            leveldir_current->graphics_set);
5014 #endif
5015
5016     ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
5017
5018     InitImages();
5019
5020     redraw_screen = TRUE;
5021   }
5022
5023   if (snd_new_identifier != NULL || force_reload_snd)
5024   {
5025     ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
5026
5027     InitSound(snd_new_identifier);
5028
5029     redraw_screen = TRUE;
5030   }
5031
5032   if (mus_new_identifier != NULL || force_reload_mus)
5033   {
5034     ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
5035
5036     InitMusic(mus_new_identifier);
5037
5038     redraw_screen = TRUE;
5039   }
5040
5041   if (redraw_screen)
5042   {
5043     RedrawBackground();
5044
5045     /* force redraw of (open or closed) door graphics */
5046     SetDoorState(DOOR_OPEN_ALL);
5047     CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
5048   }
5049 }
5050
5051 void KeyboardAutoRepeatOffUnlessAutoplay()
5052 {
5053   if (global.autoplay_leveldir == NULL)
5054     KeyboardAutoRepeatOff();
5055 }
5056
5057
5058 /* ========================================================================= */
5059 /* OpenAll()                                                                 */
5060 /* ========================================================================= */
5061
5062 void OpenAll()
5063 {
5064   InitGlobal();                 /* initialize some global variables */
5065
5066   if (options.execute_command)
5067     Execute_Command(options.execute_command);
5068
5069   if (options.serveronly)
5070   {
5071 #if defined(PLATFORM_UNIX)
5072     NetworkServer(options.server_port, options.serveronly);
5073 #else
5074     Error(ERR_WARN, "networking only supported in Unix version");
5075 #endif
5076
5077     exit(0);                    /* never reached, server loops forever */
5078   }
5079
5080   InitSetup();
5081
5082   InitGameInfo();
5083   InitPlayerInfo();
5084   InitArtworkInfo();            /* needed before loading gfx, sound & music */
5085   InitArtworkConfig();          /* needed before forking sound child process */
5086   InitMixer();
5087
5088   InitCounter();
5089
5090   InitRND(NEW_RANDOMIZE);
5091   InitSimpleRandom(NEW_RANDOMIZE);
5092
5093   InitJoysticks();
5094
5095   InitVideoDisplay();
5096   InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
5097
5098   InitEventFilter(FilterMouseMotionEvents);
5099
5100   InitElementPropertiesStatic();
5101   InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
5102
5103   InitGfx();
5104
5105   // debug_print_timestamp(0, "INIT");
5106   InitLevelInfo();
5107   // debug_print_timestamp(0, "TIME InitLevelInfo:        ");
5108   InitLevelArtworkInfo();
5109   // debug_print_timestamp(0, "TIME InitLevelArtworkInfo: ");
5110
5111   InitImages();                 /* needs to know current level directory */
5112   InitSound(NULL);              /* needs to know current level directory */
5113   InitMusic(NULL);              /* needs to know current level directory */
5114
5115   InitGfxBackground();
5116
5117 #if 1
5118   em_open_all();
5119 #endif
5120
5121   if (global.autoplay_leveldir)
5122   {
5123     AutoPlayTape();
5124     return;
5125   }
5126   else if (global.convert_leveldir)
5127   {
5128     ConvertLevels();
5129     return;
5130   }
5131
5132   game_status = GAME_MODE_MAIN;
5133
5134   DrawMainMenu();
5135
5136   InitNetworkServer();
5137 }
5138
5139 void CloseAllAndExit(int exit_value)
5140 {
5141   StopSounds();
5142   FreeAllSounds();
5143   FreeAllMusic();
5144   CloseAudio();         /* called after freeing sounds (needed for SDL) */
5145
5146 #if 1
5147   em_close_all();
5148 #endif
5149
5150   FreeAllImages();
5151
5152 #if defined(TARGET_SDL)
5153   if (network_server)   /* terminate network server */
5154     SDL_KillThread(server_thread);
5155 #endif
5156
5157   CloseVideoDisplay();
5158   ClosePlatformDependentStuff();
5159
5160   if (exit_value != 0)
5161     NotifyUserAboutErrorFile();
5162
5163   exit(exit_value);
5164 }