rnd-20070209-1-src
[rocksndiamonds.git] / src / init.c
1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back!               *
3 *----------------------------------------------------------*
4 * (c) 1995-2006 Artsoft Entertainment                      *
5 *               Holger Schemel                             *
6 *               Detmolder Strasse 189                      *
7 *               33604 Bielefeld                            *
8 *               Germany                                    *
9 *               e-mail: info@artsoft.org                   *
10 *----------------------------------------------------------*
11 * init.c                                                   *
12 ***********************************************************/
13
14 #include "libgame/libgame.h"
15
16 #include "init.h"
17 #include "events.h"
18 #include "screens.h"
19 #include "editor.h"
20 #include "game.h"
21 #include "tape.h"
22 #include "tools.h"
23 #include "files.h"
24 #include "network.h"
25 #include "netserv.h"
26 #include "cartoons.h"
27 #include "config.h"
28
29 #include "conf_e2g.c"   /* include auto-generated data structure definitions */
30 #include "conf_esg.c"   /* include auto-generated data structure definitions */
31 #include "conf_e2s.c"   /* include auto-generated data structure definitions */
32 #include "conf_fnt.c"   /* include auto-generated data structure definitions */
33 #include "conf_g2s.c"   /* include auto-generated data structure definitions */
34 #include "conf_g2m.c"   /* include auto-generated data structure definitions */
35
36
37 #define CONFIG_TOKEN_FONT_INITIAL               "font.initial"
38
39
40 static struct FontBitmapInfo font_initial[NUM_INITIAL_FONTS];
41
42 static int copy_properties[][5] =
43 {
44   {
45     EL_BUG,
46     EL_BUG_LEFT,                EL_BUG_RIGHT,
47     EL_BUG_UP,                  EL_BUG_DOWN
48   },
49   {
50     EL_SPACESHIP,
51     EL_SPACESHIP_LEFT,          EL_SPACESHIP_RIGHT,
52     EL_SPACESHIP_UP,            EL_SPACESHIP_DOWN
53   },
54   {
55     EL_BD_BUTTERFLY,
56     EL_BD_BUTTERFLY_LEFT,       EL_BD_BUTTERFLY_RIGHT,
57     EL_BD_BUTTERFLY_UP,         EL_BD_BUTTERFLY_DOWN
58   },
59   {
60     EL_BD_FIREFLY,
61     EL_BD_FIREFLY_LEFT,         EL_BD_FIREFLY_RIGHT,
62     EL_BD_FIREFLY_UP,           EL_BD_FIREFLY_DOWN
63   },
64   {
65     EL_PACMAN,
66     EL_PACMAN_LEFT,             EL_PACMAN_RIGHT,
67     EL_PACMAN_UP,               EL_PACMAN_DOWN
68   },
69   {
70     EL_YAMYAM,
71     EL_YAMYAM_LEFT,             EL_YAMYAM_RIGHT,
72     EL_YAMYAM_UP,               EL_YAMYAM_DOWN
73   },
74   {
75     EL_MOLE,
76     EL_MOLE_LEFT,               EL_MOLE_RIGHT,
77     EL_MOLE_UP,                 EL_MOLE_DOWN
78   },
79   {
80     -1,
81     -1, -1, -1, -1
82   }
83 };
84
85 void FreeGadgets()
86 {
87   FreeLevelEditorGadgets();
88   FreeGameButtons();
89   FreeTapeButtons();
90   FreeToolButtons();
91   FreeScreenGadgets();
92 }
93
94 void InitGadgets()
95 {
96   static boolean gadgets_initialized = FALSE;
97
98   if (gadgets_initialized)
99     FreeGadgets();
100
101   CreateLevelEditorGadgets();
102   CreateGameButtons();
103   CreateTapeButtons();
104   CreateToolButtons();
105   CreateScreenGadgets();
106
107   InitGadgetsSoundCallback(PlaySoundActivating, PlaySoundSelecting);
108
109   gadgets_initialized = TRUE;
110 }
111
112 inline void InitElementSmallImagesScaledUp(int graphic)
113 {
114   CreateImageWithSmallImages(graphic, graphic_info[graphic].scale_up_factor);
115 }
116
117 void InitElementSmallImages()
118 {
119   static int special_graphics[] =
120   {
121     IMG_EDITOR_ELEMENT_BORDER,
122     IMG_EDITOR_ELEMENT_BORDER_INPUT,
123     IMG_EDITOR_CASCADE_LIST,
124     IMG_EDITOR_CASCADE_LIST_ACTIVE,
125     -1
126   };
127   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
128   int num_property_mappings = getImageListPropertyMappingSize();
129   int i;
130
131   /* initialize normal images from static configuration */
132   for (i = 0; element_to_graphic[i].element > -1; i++)
133     InitElementSmallImagesScaledUp(element_to_graphic[i].graphic);
134
135   /* initialize special images from static configuration */
136   for (i = 0; element_to_special_graphic[i].element > -1; i++)
137     InitElementSmallImagesScaledUp(element_to_special_graphic[i].graphic);
138
139   /* initialize images from dynamic configuration (may be elements or other) */
140   for (i = 0; i < num_property_mappings; i++)
141     InitElementSmallImagesScaledUp(property_mapping[i].artwork_index);
142
143   /* initialize special images from above list (non-element images) */
144   for (i = 0; special_graphics[i] > -1; i++)
145     InitElementSmallImagesScaledUp(special_graphics[i]);
146 }
147
148 void InitScaledImages()
149 {
150   int i;
151
152   /* scale normal images from static configuration, if not already scaled */
153   for (i = 0; i < NUM_IMAGE_FILES; i++)
154     ScaleImage(i, graphic_info[i].scale_up_factor);
155 }
156
157 #if 1
158 /* !!! FIX THIS (CHANGE TO USING NORMAL ELEMENT GRAPHIC DEFINITIONS) !!! */
159 void SetBitmaps_EM(Bitmap **em_bitmap)
160 {
161   em_bitmap[0] = graphic_info[IMG_EMC_OBJECT].bitmap;
162   em_bitmap[1] = graphic_info[IMG_EMC_SPRITE].bitmap;
163 }
164 #endif
165
166 static int getFontBitmapID(int font_nr)
167 {
168   int special = -1;
169
170   if (game_status >= GAME_MODE_TITLE && game_status <= GAME_MODE_PSEUDO_PREVIEW)
171     special = game_status;
172   else if (game_status == GAME_MODE_PSEUDO_TYPENAME)
173     special = GFX_SPECIAL_ARG_MAIN;
174   else if (game_status == GAME_MODE_PLAYING)
175     special = GFX_SPECIAL_ARG_DOOR;
176
177   if (special != -1)
178     return font_info[font_nr].special_bitmap_id[special];
179   else
180     return font_nr;
181 }
182
183 void InitFontGraphicInfo()
184 {
185   static struct FontBitmapInfo *font_bitmap_info = NULL;
186   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
187   int num_property_mappings = getImageListPropertyMappingSize();
188   int num_font_bitmaps = NUM_FONTS;
189   int i, j;
190
191   if (graphic_info == NULL)             /* still at startup phase */
192   {
193     InitFontInfo(font_initial, NUM_INITIAL_FONTS, getFontBitmapID);
194
195     return;
196   }
197
198   /* ---------- initialize font graphic definitions ---------- */
199
200   /* always start with reliable default values (normal font graphics) */
201   for (i = 0; i < NUM_FONTS; i++)
202     font_info[i].graphic = IMG_FONT_INITIAL_1;
203
204   /* initialize normal font/graphic mapping from static configuration */
205   for (i = 0; font_to_graphic[i].font_nr > -1; i++)
206   {
207     int font_nr = font_to_graphic[i].font_nr;
208     int special = font_to_graphic[i].special;
209     int graphic = font_to_graphic[i].graphic;
210
211     if (special != -1)
212       continue;
213
214     font_info[font_nr].graphic = graphic;
215   }
216
217   /* always start with reliable default values (special font graphics) */
218   for (i = 0; i < NUM_FONTS; i++)
219   {
220     for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
221     {
222       font_info[i].special_graphic[j] = font_info[i].graphic;
223       font_info[i].special_bitmap_id[j] = i;
224     }
225   }
226
227   /* initialize special font/graphic mapping from static configuration */
228   for (i = 0; font_to_graphic[i].font_nr > -1; i++)
229   {
230     int font_nr      = font_to_graphic[i].font_nr;
231     int special      = font_to_graphic[i].special;
232     int graphic      = font_to_graphic[i].graphic;
233     int base_graphic = font2baseimg(font_nr);
234
235     if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
236     {
237       boolean base_redefined =
238         getImageListEntryFromImageID(base_graphic)->redefined;
239       boolean special_redefined =
240         getImageListEntryFromImageID(graphic)->redefined;
241
242       /* if the base font ("font.title_1", for example) has been redefined,
243          but not the special font ("font.title_1.LEVELS", for example), do not
244          use an existing (in this case considered obsolete) special font
245          anymore, but use the automatically determined default font */
246       if (base_redefined && !special_redefined)
247         continue;
248
249       font_info[font_nr].special_graphic[special] = graphic;
250       font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
251       num_font_bitmaps++;
252     }
253   }
254
255   /* initialize special font/graphic mapping from dynamic configuration */
256   for (i = 0; i < num_property_mappings; i++)
257   {
258     int font_nr = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
259     int special = property_mapping[i].ext3_index;
260     int graphic = property_mapping[i].artwork_index;
261
262     if (font_nr < 0)
263       continue;
264
265     if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
266     {
267       font_info[font_nr].special_graphic[special] = graphic;
268       font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
269       num_font_bitmaps++;
270     }
271   }
272
273   /* reset non-redefined ".active" font graphics if normal font is redefined */
274   /* (this different treatment is needed because normal and active fonts are
275      independently defined ("active" is not a property of font definitions!) */
276   for (i = 0; i < NUM_FONTS; i++)
277   {
278     int font_nr_base = i;
279     int font_nr_active = FONT_ACTIVE(font_nr_base);
280
281     /* check only those fonts with exist as normal and ".active" variant */
282     if (font_nr_base != font_nr_active)
283     {
284       int base_graphic = font_info[font_nr_base].graphic;
285       int active_graphic = font_info[font_nr_active].graphic;
286       boolean base_redefined =
287         getImageListEntryFromImageID(base_graphic)->redefined;
288       boolean active_redefined =
289         getImageListEntryFromImageID(active_graphic)->redefined;
290
291       /* if the base font ("font.menu_1", for example) has been redefined,
292          but not the active font ("font.menu_1.active", for example), do not
293          use an existing (in this case considered obsolete) active font
294          anymore, but use the automatically determined default font */
295       if (base_redefined && !active_redefined)
296         font_info[font_nr_active].graphic = base_graphic;
297
298       /* now also check each "special" font (which may be the same as above) */
299       for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
300       {
301         int base_graphic = font_info[font_nr_base].special_graphic[j];
302         int active_graphic = font_info[font_nr_active].special_graphic[j];
303         boolean base_redefined =
304           getImageListEntryFromImageID(base_graphic)->redefined;
305         boolean active_redefined =
306           getImageListEntryFromImageID(active_graphic)->redefined;
307
308         /* same as above, but check special graphic definitions, for example:
309            redefined "font.menu_1.MAIN" invalidates "font.menu_1.active.MAIN" */
310         if (base_redefined && !active_redefined)
311         {
312           font_info[font_nr_active].special_graphic[j] =
313             font_info[font_nr_base].special_graphic[j];
314           font_info[font_nr_active].special_bitmap_id[j] =
315             font_info[font_nr_base].special_bitmap_id[j];
316         }
317       }
318     }
319   }
320
321   /* ---------- initialize font bitmap array ---------- */
322
323   if (font_bitmap_info != NULL)
324     FreeFontInfo(font_bitmap_info);
325
326   font_bitmap_info =
327     checked_calloc(num_font_bitmaps * sizeof(struct FontBitmapInfo));
328
329   /* ---------- initialize font bitmap definitions ---------- */
330
331   for (i = 0; i < NUM_FONTS; i++)
332   {
333     if (i < NUM_INITIAL_FONTS)
334     {
335       font_bitmap_info[i] = font_initial[i];
336       continue;
337     }
338
339     for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
340     {
341       int font_bitmap_id = font_info[i].special_bitmap_id[j];
342       int graphic = font_info[i].special_graphic[j];
343
344       /* set 'graphic_info' for font entries, if uninitialized (guessed) */
345       if (graphic_info[graphic].anim_frames < MIN_NUM_CHARS_PER_FONT)
346       {
347         graphic_info[graphic].anim_frames = DEFAULT_NUM_CHARS_PER_FONT;
348         graphic_info[graphic].anim_frames_per_line = DEFAULT_NUM_CHARS_PER_LINE;
349       }
350
351       /* copy font relevant information from graphics information */
352       font_bitmap_info[font_bitmap_id].bitmap = graphic_info[graphic].bitmap;
353       font_bitmap_info[font_bitmap_id].src_x  = graphic_info[graphic].src_x;
354       font_bitmap_info[font_bitmap_id].src_y  = graphic_info[graphic].src_y;
355       font_bitmap_info[font_bitmap_id].width  = graphic_info[graphic].width;
356       font_bitmap_info[font_bitmap_id].height = graphic_info[graphic].height;
357
358       font_bitmap_info[font_bitmap_id].draw_xoffset =
359         graphic_info[graphic].draw_xoffset;
360       font_bitmap_info[font_bitmap_id].draw_yoffset =
361         graphic_info[graphic].draw_yoffset;
362
363       font_bitmap_info[font_bitmap_id].num_chars =
364         graphic_info[graphic].anim_frames;
365       font_bitmap_info[font_bitmap_id].num_chars_per_line =
366         graphic_info[graphic].anim_frames_per_line;
367     }
368   }
369
370   InitFontInfo(font_bitmap_info, num_font_bitmaps, getFontBitmapID);
371 }
372
373 void InitElementGraphicInfo()
374 {
375   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
376   int num_property_mappings = getImageListPropertyMappingSize();
377   int i, act, dir;
378
379   if (graphic_info == NULL)             /* still at startup phase */
380     return;
381
382   /* set values to -1 to identify later as "uninitialized" values */
383   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
384   {
385     for (act = 0; act < NUM_ACTIONS; act++)
386     {
387       element_info[i].graphic[act] = -1;
388       element_info[i].crumbled[act] = -1;
389
390       for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
391       {
392         element_info[i].direction_graphic[act][dir] = -1;
393         element_info[i].direction_crumbled[act][dir] = -1;
394       }
395     }
396   }
397
398   /* initialize normal element/graphic mapping from static configuration */
399   for (i = 0; element_to_graphic[i].element > -1; i++)
400   {
401     int element      = element_to_graphic[i].element;
402     int action       = element_to_graphic[i].action;
403     int direction    = element_to_graphic[i].direction;
404     boolean crumbled = element_to_graphic[i].crumbled;
405     int graphic      = element_to_graphic[i].graphic;
406     int base_graphic = el2baseimg(element);
407
408     if (graphic_info[graphic].bitmap == NULL)
409       continue;
410
411     if ((action > -1 || direction > -1 || crumbled == TRUE) &&
412         base_graphic != -1)
413     {
414       boolean base_redefined =
415         getImageListEntryFromImageID(base_graphic)->redefined;
416       boolean act_dir_redefined =
417         getImageListEntryFromImageID(graphic)->redefined;
418
419       /* if the base graphic ("emerald", for example) has been redefined,
420          but not the action graphic ("emerald.falling", for example), do not
421          use an existing (in this case considered obsolete) action graphic
422          anymore, but use the automatically determined default graphic */
423       if (base_redefined && !act_dir_redefined)
424         continue;
425     }
426
427     if (action < 0)
428       action = ACTION_DEFAULT;
429
430     if (crumbled)
431     {
432       if (direction > -1)
433         element_info[element].direction_crumbled[action][direction] = graphic;
434       else
435         element_info[element].crumbled[action] = graphic;
436     }
437     else
438     {
439       if (direction > -1)
440         element_info[element].direction_graphic[action][direction] = graphic;
441       else
442         element_info[element].graphic[action] = graphic;
443     }
444   }
445
446   /* initialize normal element/graphic mapping from dynamic configuration */
447   for (i = 0; i < num_property_mappings; i++)
448   {
449     int element   = property_mapping[i].base_index;
450     int action    = property_mapping[i].ext1_index;
451     int direction = property_mapping[i].ext2_index;
452     int special   = property_mapping[i].ext3_index;
453     int graphic   = property_mapping[i].artwork_index;
454     boolean crumbled = FALSE;
455
456     if (special == GFX_SPECIAL_ARG_CRUMBLED)
457     {
458       special = -1;
459       crumbled = TRUE;
460     }
461
462     if (graphic_info[graphic].bitmap == NULL)
463       continue;
464
465     if (element >= MAX_NUM_ELEMENTS || special != -1)
466       continue;
467
468     if (action < 0)
469       action = ACTION_DEFAULT;
470
471     if (crumbled)
472     {
473       if (direction < 0)
474         for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
475           element_info[element].direction_crumbled[action][dir] = -1;
476
477       if (direction > -1)
478         element_info[element].direction_crumbled[action][direction] = graphic;
479       else
480         element_info[element].crumbled[action] = graphic;
481     }
482     else
483     {
484       if (direction < 0)
485         for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
486           element_info[element].direction_graphic[action][dir] = -1;
487
488       if (direction > -1)
489         element_info[element].direction_graphic[action][direction] = graphic;
490       else
491         element_info[element].graphic[action] = graphic;
492     }
493   }
494
495   /* now copy all graphics that are defined to be cloned from other graphics */
496   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
497   {
498     int graphic = element_info[i].graphic[ACTION_DEFAULT];
499     int crumbled_like, diggable_like;
500
501     if (graphic == -1)
502       continue;
503
504     crumbled_like = graphic_info[graphic].crumbled_like;
505     diggable_like = graphic_info[graphic].diggable_like;
506
507     if (crumbled_like != -1 && element_info[i].crumbled[ACTION_DEFAULT] == -1)
508     {
509       for (act = 0; act < NUM_ACTIONS; act++)
510         element_info[i].crumbled[act] =
511           element_info[crumbled_like].crumbled[act];
512       for (act = 0; act < NUM_ACTIONS; act++)
513         for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
514           element_info[i].direction_crumbled[act][dir] =
515             element_info[crumbled_like].direction_crumbled[act][dir];
516     }
517
518     if (diggable_like != -1 && element_info[i].graphic[ACTION_DIGGING] == -1)
519     {
520       element_info[i].graphic[ACTION_DIGGING] =
521         element_info[diggable_like].graphic[ACTION_DIGGING];
522       for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
523         element_info[i].direction_graphic[ACTION_DIGGING][dir] =
524           element_info[diggable_like].direction_graphic[ACTION_DIGGING][dir];
525     }
526   }
527
528 #if 1
529   /* set hardcoded definitions for some runtime elements without graphic */
530   element_info[EL_AMOEBA_TO_DIAMOND].graphic[ACTION_DEFAULT] = IMG_AMOEBA_DEAD;
531 #endif
532
533 #if 1
534   /* set hardcoded definitions for some internal elements without graphic */
535   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
536   {
537     if (IS_EDITOR_CASCADE_INACTIVE(i))
538       element_info[i].graphic[ACTION_DEFAULT] = IMG_EDITOR_CASCADE_LIST;
539     else if (IS_EDITOR_CASCADE_ACTIVE(i))
540       element_info[i].graphic[ACTION_DEFAULT] = IMG_EDITOR_CASCADE_LIST_ACTIVE;
541   }
542 #endif
543
544   /* now set all undefined/invalid graphics to -1 to set to default after it */
545   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
546   {
547     for (act = 0; act < NUM_ACTIONS; act++)
548     {
549       int graphic;
550
551       graphic = element_info[i].graphic[act];
552       if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
553         element_info[i].graphic[act] = -1;
554
555       graphic = element_info[i].crumbled[act];
556       if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
557         element_info[i].crumbled[act] = -1;
558
559       for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
560       {
561         graphic = element_info[i].direction_graphic[act][dir];
562         if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
563           element_info[i].direction_graphic[act][dir] = -1;
564
565         graphic = element_info[i].direction_crumbled[act][dir];
566         if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
567           element_info[i].direction_crumbled[act][dir] = -1;
568       }
569     }
570   }
571
572   /* adjust graphics with 2nd tile for movement according to direction
573      (do this before correcting '-1' values to minimize calculations) */
574   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
575   {
576     for (act = 0; act < NUM_ACTIONS; act++)
577     {
578       for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
579       {
580         int graphic = element_info[i].direction_graphic[act][dir];
581         int move_dir = (act == ACTION_FALLING ? MV_BIT_DOWN : dir);
582
583         if (act == ACTION_FALLING)      /* special case */
584           graphic = element_info[i].graphic[act];
585
586         if (graphic != -1 &&
587             graphic_info[graphic].double_movement &&
588             graphic_info[graphic].swap_double_tiles != 0)
589         {
590           struct GraphicInfo *g = &graphic_info[graphic];
591           int src_x_front = g->src_x;
592           int src_y_front = g->src_y;
593           int src_x_back = g->src_x + g->offset2_x;
594           int src_y_back = g->src_y + g->offset2_y;
595           boolean frames_are_ordered_diagonally = (g->offset_x != 0 &&
596                                                    g->offset_y != 0);
597           boolean front_is_left_or_upper = (src_x_front < src_x_back ||
598                                             src_y_front < src_y_back);
599           boolean swap_movement_tiles_always = (g->swap_double_tiles == 1);
600           boolean swap_movement_tiles_autodetected =
601             (!frames_are_ordered_diagonally &&
602              ((move_dir == MV_BIT_LEFT  && !front_is_left_or_upper) ||
603               (move_dir == MV_BIT_UP    && !front_is_left_or_upper) ||
604               (move_dir == MV_BIT_RIGHT &&  front_is_left_or_upper) ||
605               (move_dir == MV_BIT_DOWN  &&  front_is_left_or_upper)));
606           Bitmap *dummy;
607
608           /* swap frontside and backside graphic tile coordinates, if needed */
609           if (swap_movement_tiles_always || swap_movement_tiles_autodetected)
610           {
611             /* get current (wrong) backside tile coordinates */
612             getGraphicSourceExt(graphic, 0, &dummy, &src_x_back, &src_y_back,
613                                 TRUE);
614
615             /* set frontside tile coordinates to backside tile coordinates */
616             g->src_x = src_x_back;
617             g->src_y = src_y_back;
618
619             /* invert tile offset to point to new backside tile coordinates */
620             g->offset2_x *= -1;
621             g->offset2_y *= -1;
622
623             /* do not swap front and backside tiles again after correction */
624             g->swap_double_tiles = 0;
625           }
626         }
627       }
628     }
629   }
630
631   /* now set all '-1' values to element specific default values */
632   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
633   {
634     int default_graphic = element_info[i].graphic[ACTION_DEFAULT];
635     int default_crumbled = element_info[i].crumbled[ACTION_DEFAULT];
636     int default_direction_graphic[NUM_DIRECTIONS_FULL];
637     int default_direction_crumbled[NUM_DIRECTIONS_FULL];
638
639     if (default_graphic == -1)
640       default_graphic = IMG_UNKNOWN;
641 #if 1
642     if (default_crumbled == -1)
643       default_crumbled = default_graphic;
644 #else
645     /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
646     if (default_crumbled == -1)
647       default_crumbled = IMG_EMPTY;
648 #endif
649
650     for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
651     {
652       default_direction_graphic[dir] =
653         element_info[i].direction_graphic[ACTION_DEFAULT][dir];
654       default_direction_crumbled[dir] =
655         element_info[i].direction_crumbled[ACTION_DEFAULT][dir];
656
657       if (default_direction_graphic[dir] == -1)
658         default_direction_graphic[dir] = default_graphic;
659 #if 1
660       if (default_direction_crumbled[dir] == -1)
661         default_direction_crumbled[dir] = default_direction_graphic[dir];
662 #else
663       /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
664       if (default_direction_crumbled[dir] == -1)
665         default_direction_crumbled[dir] = default_crumbled;
666 #endif
667     }
668
669     for (act = 0; act < NUM_ACTIONS; act++)
670     {
671       boolean act_remove = ((IS_DIGGABLE(i)    && act == ACTION_DIGGING)  ||
672                             (IS_SNAPPABLE(i)   && act == ACTION_SNAPPING) ||
673                             (IS_COLLECTIBLE(i) && act == ACTION_COLLECTING));
674       boolean act_turning = (act == ACTION_TURNING_FROM_LEFT ||
675                              act == ACTION_TURNING_FROM_RIGHT ||
676                              act == ACTION_TURNING_FROM_UP ||
677                              act == ACTION_TURNING_FROM_DOWN);
678
679       /* generic default action graphic (defined by "[default]" directive) */
680       int default_action_graphic = element_info[EL_DEFAULT].graphic[act];
681       int default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
682       int default_remove_graphic = IMG_EMPTY;
683
684       if (act_remove && default_action_graphic != -1)
685         default_remove_graphic = default_action_graphic;
686
687       /* look for special default action graphic (classic game specific) */
688       if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].graphic[act] != -1)
689         default_action_graphic = element_info[EL_BD_DEFAULT].graphic[act];
690       if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].graphic[act] != -1)
691         default_action_graphic = element_info[EL_SP_DEFAULT].graphic[act];
692       if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].graphic[act] != -1)
693         default_action_graphic = element_info[EL_SB_DEFAULT].graphic[act];
694
695       if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].crumbled[act] != -1)
696         default_action_crumbled = element_info[EL_BD_DEFAULT].crumbled[act];
697       if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].crumbled[act] != -1)
698         default_action_crumbled = element_info[EL_SP_DEFAULT].crumbled[act];
699       if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].crumbled[act] != -1)
700         default_action_crumbled = element_info[EL_SB_DEFAULT].crumbled[act];
701
702 #if 1
703       /* !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!! */
704       /* !!! make this better !!! */
705       if (i == EL_EMPTY_SPACE)
706       {
707         default_action_graphic = element_info[EL_DEFAULT].graphic[act];
708         default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
709       }
710 #endif
711
712       if (default_action_graphic == -1)
713         default_action_graphic = default_graphic;
714 #if 1
715       if (default_action_crumbled == -1)
716         default_action_crumbled = default_action_graphic;
717 #else
718       /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
719       if (default_action_crumbled == -1)
720         default_action_crumbled = default_crumbled;
721 #endif
722
723       for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
724       {
725         /* use action graphic as the default direction graphic, if undefined */
726         int default_action_direction_graphic = element_info[i].graphic[act];
727         int default_action_direction_crumbled = element_info[i].crumbled[act];
728
729         /* no graphic for current action -- use default direction graphic */
730         if (default_action_direction_graphic == -1)
731           default_action_direction_graphic =
732             (act_remove ? default_remove_graphic :
733              act_turning ?
734              element_info[i].direction_graphic[ACTION_TURNING][dir] :
735              default_action_graphic != default_graphic ?
736              default_action_graphic :
737              default_direction_graphic[dir]);
738
739         if (element_info[i].direction_graphic[act][dir] == -1)
740           element_info[i].direction_graphic[act][dir] =
741             default_action_direction_graphic;
742
743 #if 1
744         if (default_action_direction_crumbled == -1)
745           default_action_direction_crumbled =
746             element_info[i].direction_graphic[act][dir];
747 #else
748         if (default_action_direction_crumbled == -1)
749           default_action_direction_crumbled =
750             (act_remove ? default_remove_graphic :
751              act_turning ?
752              element_info[i].direction_crumbled[ACTION_TURNING][dir] :
753              default_action_crumbled != default_crumbled ?
754              default_action_crumbled :
755              default_direction_crumbled[dir]);
756 #endif
757
758         if (element_info[i].direction_crumbled[act][dir] == -1)
759           element_info[i].direction_crumbled[act][dir] =
760             default_action_direction_crumbled;
761       }
762
763       /* no graphic for this specific action -- use default action graphic */
764       if (element_info[i].graphic[act] == -1)
765         element_info[i].graphic[act] =
766           (act_remove ? default_remove_graphic :
767            act_turning ? element_info[i].graphic[ACTION_TURNING] :
768            default_action_graphic);
769 #if 1
770       if (element_info[i].crumbled[act] == -1)
771         element_info[i].crumbled[act] = element_info[i].graphic[act];
772 #else
773       if (element_info[i].crumbled[act] == -1)
774         element_info[i].crumbled[act] =
775           (act_remove ? default_remove_graphic :
776            act_turning ? element_info[i].crumbled[ACTION_TURNING] :
777            default_action_crumbled);
778 #endif
779     }
780   }
781
782 #if 0
783   /* !!! THIS ALSO CLEARS SPECIAL FLAGS (AND IS NOT NEEDED ANYWAY) !!! */
784   /* set animation mode to "none" for each graphic with only 1 frame */
785   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
786   {
787     for (act = 0; act < NUM_ACTIONS; act++)
788     {
789       int graphic = element_info[i].graphic[act];
790       int crumbled = element_info[i].crumbled[act];
791
792       if (graphic_info[graphic].anim_frames == 1)
793         graphic_info[graphic].anim_mode = ANIM_NONE;
794       if (graphic_info[crumbled].anim_frames == 1)
795         graphic_info[crumbled].anim_mode = ANIM_NONE;
796
797       for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
798       {
799         graphic = element_info[i].direction_graphic[act][dir];
800         crumbled = element_info[i].direction_crumbled[act][dir];
801
802         if (graphic_info[graphic].anim_frames == 1)
803           graphic_info[graphic].anim_mode = ANIM_NONE;
804         if (graphic_info[crumbled].anim_frames == 1)
805           graphic_info[crumbled].anim_mode = ANIM_NONE;
806       }
807     }
808   }
809 #endif
810
811 #if 0
812 #if DEBUG
813   if (options.verbose)
814   {
815     for (i = 0; i < MAX_NUM_ELEMENTS; i++)
816       if (element_info[i].graphic[ACTION_DEFAULT] == IMG_UNKNOWN &&
817           i != EL_UNKNOWN)
818         Error(ERR_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_keygate[] =
3461   {
3462     EL_GATE_1,
3463     EL_GATE_2,
3464     EL_GATE_3,
3465     EL_GATE_4,
3466     EL_GATE_1_GRAY,
3467     EL_GATE_2_GRAY,
3468     EL_GATE_3_GRAY,
3469     EL_GATE_4_GRAY,
3470     EL_GATE_1_GRAY_ACTIVE,
3471     EL_GATE_2_GRAY_ACTIVE,
3472     EL_GATE_3_GRAY_ACTIVE,
3473     EL_GATE_4_GRAY_ACTIVE,
3474     EL_EM_GATE_1,
3475     EL_EM_GATE_2,
3476     EL_EM_GATE_3,
3477     EL_EM_GATE_4,
3478     EL_EM_GATE_1_GRAY,
3479     EL_EM_GATE_2_GRAY,
3480     EL_EM_GATE_3_GRAY,
3481     EL_EM_GATE_4_GRAY,
3482     EL_EM_GATE_1_GRAY_ACTIVE,
3483     EL_EM_GATE_2_GRAY_ACTIVE,
3484     EL_EM_GATE_3_GRAY_ACTIVE,
3485     EL_EM_GATE_4_GRAY_ACTIVE,
3486     EL_EMC_GATE_5,
3487     EL_EMC_GATE_6,
3488     EL_EMC_GATE_7,
3489     EL_EMC_GATE_8,
3490     EL_EMC_GATE_5_GRAY,
3491     EL_EMC_GATE_6_GRAY,
3492     EL_EMC_GATE_7_GRAY,
3493     EL_EMC_GATE_8_GRAY,
3494     EL_EMC_GATE_5_GRAY_ACTIVE,
3495     EL_EMC_GATE_6_GRAY_ACTIVE,
3496     EL_EMC_GATE_7_GRAY_ACTIVE,
3497     EL_EMC_GATE_8_GRAY_ACTIVE,
3498     EL_DC_GATE_WHITE,
3499     EL_DC_GATE_WHITE_GRAY,
3500     EL_DC_GATE_WHITE_GRAY_ACTIVE,
3501
3502     -1
3503   };
3504
3505   static int ep_amoeboid[] =
3506   {
3507     EL_AMOEBA_DEAD,
3508     EL_AMOEBA_WET,
3509     EL_AMOEBA_DRY,
3510     EL_AMOEBA_FULL,
3511     EL_BD_AMOEBA,
3512     EL_EMC_DRIPPER,
3513
3514     -1
3515   };
3516
3517   static int ep_amoebalive[] =
3518   {
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_has_editor_content[] =
3529   {
3530     EL_PLAYER_1,
3531     EL_PLAYER_2,
3532     EL_PLAYER_3,
3533     EL_PLAYER_4,
3534     EL_SP_MURPHY,
3535     EL_YAMYAM,
3536     EL_YAMYAM_LEFT,
3537     EL_YAMYAM_RIGHT,
3538     EL_YAMYAM_UP,
3539     EL_YAMYAM_DOWN,
3540     EL_AMOEBA_WET,
3541     EL_AMOEBA_DRY,
3542     EL_AMOEBA_FULL,
3543     EL_BD_AMOEBA,
3544     EL_EMC_MAGIC_BALL,
3545     EL_EMC_ANDROID,
3546
3547     -1
3548   };
3549
3550   static int ep_can_turn_each_move[] =
3551   {
3552     /* !!! do something with this one !!! */
3553     -1
3554   };
3555
3556   static int ep_can_grow[] =
3557   {
3558     EL_BD_AMOEBA,
3559     EL_AMOEBA_DROP,
3560     EL_AMOEBA_WET,
3561     EL_AMOEBA_DRY,
3562     EL_AMOEBA_FULL,
3563     EL_GAME_OF_LIFE,
3564     EL_BIOMAZE,
3565     EL_EMC_DRIPPER,
3566
3567     -1
3568   };
3569
3570   static int ep_active_bomb[] =
3571   {
3572     EL_DYNAMITE_ACTIVE,
3573     EL_EM_DYNAMITE_ACTIVE,
3574     EL_DYNABOMB_PLAYER_1_ACTIVE,
3575     EL_DYNABOMB_PLAYER_2_ACTIVE,
3576     EL_DYNABOMB_PLAYER_3_ACTIVE,
3577     EL_DYNABOMB_PLAYER_4_ACTIVE,
3578     EL_SP_DISK_RED_ACTIVE,
3579
3580     -1
3581   };
3582
3583   static int ep_inactive[] =
3584   {
3585     EL_EMPTY,
3586     EL_SAND,
3587     EL_WALL,
3588     EL_BD_WALL,
3589     EL_WALL_SLIPPERY,
3590     EL_STEELWALL,
3591     EL_AMOEBA_DEAD,
3592     EL_QUICKSAND_EMPTY,
3593     EL_QUICKSAND_FAST_EMPTY,
3594     EL_STONEBLOCK,
3595     EL_ROBOT_WHEEL,
3596     EL_KEY_1,
3597     EL_KEY_2,
3598     EL_KEY_3,
3599     EL_KEY_4,
3600     EL_EM_KEY_1,
3601     EL_EM_KEY_2,
3602     EL_EM_KEY_3,
3603     EL_EM_KEY_4,
3604     EL_EMC_KEY_5,
3605     EL_EMC_KEY_6,
3606     EL_EMC_KEY_7,
3607     EL_EMC_KEY_8,
3608     EL_GATE_1,
3609     EL_GATE_2,
3610     EL_GATE_3,
3611     EL_GATE_4,
3612     EL_GATE_1_GRAY,
3613     EL_GATE_2_GRAY,
3614     EL_GATE_3_GRAY,
3615     EL_GATE_4_GRAY,
3616     EL_GATE_1_GRAY_ACTIVE,
3617     EL_GATE_2_GRAY_ACTIVE,
3618     EL_GATE_3_GRAY_ACTIVE,
3619     EL_GATE_4_GRAY_ACTIVE,
3620     EL_EM_GATE_1,
3621     EL_EM_GATE_2,
3622     EL_EM_GATE_3,
3623     EL_EM_GATE_4,
3624     EL_EM_GATE_1_GRAY,
3625     EL_EM_GATE_2_GRAY,
3626     EL_EM_GATE_3_GRAY,
3627     EL_EM_GATE_4_GRAY,
3628     EL_EM_GATE_1_GRAY_ACTIVE,
3629     EL_EM_GATE_2_GRAY_ACTIVE,
3630     EL_EM_GATE_3_GRAY_ACTIVE,
3631     EL_EM_GATE_4_GRAY_ACTIVE,
3632     EL_EMC_GATE_5,
3633     EL_EMC_GATE_6,
3634     EL_EMC_GATE_7,
3635     EL_EMC_GATE_8,
3636     EL_EMC_GATE_5_GRAY,
3637     EL_EMC_GATE_6_GRAY,
3638     EL_EMC_GATE_7_GRAY,
3639     EL_EMC_GATE_8_GRAY,
3640     EL_EMC_GATE_5_GRAY_ACTIVE,
3641     EL_EMC_GATE_6_GRAY_ACTIVE,
3642     EL_EMC_GATE_7_GRAY_ACTIVE,
3643     EL_EMC_GATE_8_GRAY_ACTIVE,
3644     EL_DC_GATE_WHITE,
3645     EL_DC_GATE_WHITE_GRAY,
3646     EL_DC_GATE_WHITE_GRAY_ACTIVE,
3647     EL_DC_GATE_FAKE_GRAY,
3648     EL_DYNAMITE,
3649     EL_EM_DYNAMITE,
3650     EL_INVISIBLE_STEELWALL,
3651     EL_INVISIBLE_WALL,
3652     EL_INVISIBLE_SAND,
3653     EL_LAMP,
3654     EL_LAMP_ACTIVE,
3655     EL_WALL_EMERALD,
3656     EL_WALL_DIAMOND,
3657     EL_WALL_BD_DIAMOND,
3658     EL_WALL_EMERALD_YELLOW,
3659     EL_DYNABOMB_INCREASE_NUMBER,
3660     EL_DYNABOMB_INCREASE_SIZE,
3661     EL_DYNABOMB_INCREASE_POWER,
3662 #if 0
3663     EL_SOKOBAN_OBJECT,
3664 #endif
3665     EL_SOKOBAN_FIELD_EMPTY,
3666     EL_SOKOBAN_FIELD_FULL,
3667     EL_WALL_EMERALD_RED,
3668     EL_WALL_EMERALD_PURPLE,
3669     EL_ACID_POOL_TOPLEFT,
3670     EL_ACID_POOL_TOPRIGHT,
3671     EL_ACID_POOL_BOTTOMLEFT,
3672     EL_ACID_POOL_BOTTOM,
3673     EL_ACID_POOL_BOTTOMRIGHT,
3674     EL_MAGIC_WALL,
3675     EL_MAGIC_WALL_DEAD,
3676     EL_BD_MAGIC_WALL,
3677     EL_BD_MAGIC_WALL_DEAD,
3678     EL_DC_MAGIC_WALL,
3679     EL_DC_MAGIC_WALL_DEAD,
3680     EL_AMOEBA_TO_DIAMOND,
3681     EL_BLOCKED,
3682     EL_SP_EMPTY,
3683     EL_SP_BASE,
3684     EL_SP_PORT_RIGHT,
3685     EL_SP_PORT_DOWN,
3686     EL_SP_PORT_LEFT,
3687     EL_SP_PORT_UP,
3688     EL_SP_GRAVITY_PORT_RIGHT,
3689     EL_SP_GRAVITY_PORT_DOWN,
3690     EL_SP_GRAVITY_PORT_LEFT,
3691     EL_SP_GRAVITY_PORT_UP,
3692     EL_SP_PORT_HORIZONTAL,
3693     EL_SP_PORT_VERTICAL,
3694     EL_SP_PORT_ANY,
3695     EL_SP_DISK_RED,
3696 #if 0
3697     EL_SP_DISK_YELLOW,
3698 #endif
3699     EL_SP_CHIP_SINGLE,
3700     EL_SP_CHIP_LEFT,
3701     EL_SP_CHIP_RIGHT,
3702     EL_SP_CHIP_TOP,
3703     EL_SP_CHIP_BOTTOM,
3704     EL_SP_HARDWARE_GRAY,
3705     EL_SP_HARDWARE_GREEN,
3706     EL_SP_HARDWARE_BLUE,
3707     EL_SP_HARDWARE_RED,
3708     EL_SP_HARDWARE_YELLOW,
3709     EL_SP_HARDWARE_BASE_1,
3710     EL_SP_HARDWARE_BASE_2,
3711     EL_SP_HARDWARE_BASE_3,
3712     EL_SP_HARDWARE_BASE_4,
3713     EL_SP_HARDWARE_BASE_5,
3714     EL_SP_HARDWARE_BASE_6,
3715     EL_SP_GRAVITY_ON_PORT_LEFT,
3716     EL_SP_GRAVITY_ON_PORT_RIGHT,
3717     EL_SP_GRAVITY_ON_PORT_UP,
3718     EL_SP_GRAVITY_ON_PORT_DOWN,
3719     EL_SP_GRAVITY_OFF_PORT_LEFT,
3720     EL_SP_GRAVITY_OFF_PORT_RIGHT,
3721     EL_SP_GRAVITY_OFF_PORT_UP,
3722     EL_SP_GRAVITY_OFF_PORT_DOWN,
3723     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3724     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3725     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3726     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3727     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3728     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3729     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3730     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3731     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3732     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3733     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3734     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3735     EL_SIGN_EXCLAMATION,
3736     EL_SIGN_RADIOACTIVITY,
3737     EL_SIGN_STOP,
3738     EL_SIGN_WHEELCHAIR,
3739     EL_SIGN_PARKING,
3740     EL_SIGN_NO_ENTRY,
3741     EL_SIGN_UNUSED_1,
3742     EL_SIGN_GIVE_WAY,
3743     EL_SIGN_ENTRY_FORBIDDEN,
3744     EL_SIGN_EMERGENCY_EXIT,
3745     EL_SIGN_YIN_YANG,
3746     EL_SIGN_UNUSED_2,
3747     EL_SIGN_SPERMS,
3748     EL_SIGN_BULLET,
3749     EL_SIGN_HEART,
3750     EL_SIGN_CROSS,
3751     EL_SIGN_FRANKIE,
3752     EL_DC_STEELWALL_1_LEFT,
3753     EL_DC_STEELWALL_1_RIGHT,
3754     EL_DC_STEELWALL_1_TOP,
3755     EL_DC_STEELWALL_1_BOTTOM,
3756     EL_DC_STEELWALL_1_HORIZONTAL,
3757     EL_DC_STEELWALL_1_VERTICAL,
3758     EL_DC_STEELWALL_1_TOPLEFT,
3759     EL_DC_STEELWALL_1_TOPRIGHT,
3760     EL_DC_STEELWALL_1_BOTTOMLEFT,
3761     EL_DC_STEELWALL_1_BOTTOMRIGHT,
3762     EL_DC_STEELWALL_1_TOPLEFT_2,
3763     EL_DC_STEELWALL_1_TOPRIGHT_2,
3764     EL_DC_STEELWALL_1_BOTTOMLEFT_2,
3765     EL_DC_STEELWALL_1_BOTTOMRIGHT_2,
3766     EL_DC_STEELWALL_2_LEFT,
3767     EL_DC_STEELWALL_2_RIGHT,
3768     EL_DC_STEELWALL_2_TOP,
3769     EL_DC_STEELWALL_2_BOTTOM,
3770     EL_DC_STEELWALL_2_HORIZONTAL,
3771     EL_DC_STEELWALL_2_VERTICAL,
3772     EL_DC_STEELWALL_2_MIDDLE,
3773     EL_DC_STEELWALL_2_SINGLE,
3774     EL_STEELWALL_SLIPPERY,
3775     EL_EMC_STEELWALL_1,
3776     EL_EMC_STEELWALL_2,
3777     EL_EMC_STEELWALL_3,
3778     EL_EMC_STEELWALL_4,
3779     EL_EMC_WALL_SLIPPERY_1,
3780     EL_EMC_WALL_SLIPPERY_2,
3781     EL_EMC_WALL_SLIPPERY_3,
3782     EL_EMC_WALL_SLIPPERY_4,
3783     EL_EMC_WALL_1,
3784     EL_EMC_WALL_2,
3785     EL_EMC_WALL_3,
3786     EL_EMC_WALL_4,
3787     EL_EMC_WALL_5,
3788     EL_EMC_WALL_6,
3789     EL_EMC_WALL_7,
3790     EL_EMC_WALL_8,
3791     EL_EMC_WALL_9,
3792     EL_EMC_WALL_10,
3793     EL_EMC_WALL_11,
3794     EL_EMC_WALL_12,
3795     EL_EMC_WALL_13,
3796     EL_EMC_WALL_14,
3797     EL_EMC_WALL_15,
3798     EL_EMC_WALL_16,
3799
3800     -1
3801   };
3802
3803   static int ep_em_slippery_wall[] =
3804   {
3805     -1
3806   };
3807
3808   static int ep_gfx_crumbled[] =
3809   {
3810     EL_SAND,
3811     EL_LANDMINE,
3812     EL_DC_LANDMINE,
3813     EL_TRAP,
3814     EL_TRAP_ACTIVE,
3815
3816     -1
3817   };
3818
3819   static int ep_editor_cascade_active[] =
3820   {
3821     EL_INTERNAL_CASCADE_BD_ACTIVE,
3822     EL_INTERNAL_CASCADE_EM_ACTIVE,
3823     EL_INTERNAL_CASCADE_EMC_ACTIVE,
3824     EL_INTERNAL_CASCADE_RND_ACTIVE,
3825     EL_INTERNAL_CASCADE_SB_ACTIVE,
3826     EL_INTERNAL_CASCADE_SP_ACTIVE,
3827     EL_INTERNAL_CASCADE_DC_ACTIVE,
3828     EL_INTERNAL_CASCADE_DX_ACTIVE,
3829     EL_INTERNAL_CASCADE_CHARS_ACTIVE,
3830     EL_INTERNAL_CASCADE_STEEL_CHARS_ACTIVE,
3831     EL_INTERNAL_CASCADE_CE_ACTIVE,
3832     EL_INTERNAL_CASCADE_GE_ACTIVE,
3833     EL_INTERNAL_CASCADE_REF_ACTIVE,
3834     EL_INTERNAL_CASCADE_USER_ACTIVE,
3835     EL_INTERNAL_CASCADE_DYNAMIC_ACTIVE,
3836
3837     -1
3838   };
3839
3840   static int ep_editor_cascade_inactive[] =
3841   {
3842     EL_INTERNAL_CASCADE_BD,
3843     EL_INTERNAL_CASCADE_EM,
3844     EL_INTERNAL_CASCADE_EMC,
3845     EL_INTERNAL_CASCADE_RND,
3846     EL_INTERNAL_CASCADE_SB,
3847     EL_INTERNAL_CASCADE_SP,
3848     EL_INTERNAL_CASCADE_DC,
3849     EL_INTERNAL_CASCADE_DX,
3850     EL_INTERNAL_CASCADE_CHARS,
3851     EL_INTERNAL_CASCADE_STEEL_CHARS,
3852     EL_INTERNAL_CASCADE_CE,
3853     EL_INTERNAL_CASCADE_GE,
3854     EL_INTERNAL_CASCADE_REF,
3855     EL_INTERNAL_CASCADE_USER,
3856     EL_INTERNAL_CASCADE_DYNAMIC,
3857
3858     -1
3859   };
3860
3861   static int ep_obsolete[] =
3862   {
3863     EL_PLAYER_OBSOLETE,
3864     EL_KEY_OBSOLETE,
3865     EL_EM_KEY_1_FILE_OBSOLETE,
3866     EL_EM_KEY_2_FILE_OBSOLETE,
3867     EL_EM_KEY_3_FILE_OBSOLETE,
3868     EL_EM_KEY_4_FILE_OBSOLETE,
3869     EL_ENVELOPE_OBSOLETE,
3870
3871     -1
3872   };
3873
3874   static struct
3875   {
3876     int *elements;
3877     int property;
3878   } element_properties[] =
3879   {
3880     { ep_diggable,                      EP_DIGGABLE                     },
3881     { ep_collectible_only,              EP_COLLECTIBLE_ONLY             },
3882     { ep_dont_run_into,                 EP_DONT_RUN_INTO                },
3883     { ep_dont_collide_with,             EP_DONT_COLLIDE_WITH            },
3884     { ep_dont_touch,                    EP_DONT_TOUCH                   },
3885     { ep_indestructible,                EP_INDESTRUCTIBLE               },
3886     { ep_slippery,                      EP_SLIPPERY                     },
3887     { ep_can_change,                    EP_CAN_CHANGE                   },
3888     { ep_can_move,                      EP_CAN_MOVE                     },
3889     { ep_can_fall,                      EP_CAN_FALL                     },
3890     { ep_can_smash_player,              EP_CAN_SMASH_PLAYER             },
3891     { ep_can_smash_enemies,             EP_CAN_SMASH_ENEMIES            },
3892     { ep_can_smash_everything,          EP_CAN_SMASH_EVERYTHING         },
3893     { ep_explodes_by_fire,              EP_EXPLODES_BY_FIRE             },
3894     { ep_explodes_smashed,              EP_EXPLODES_SMASHED             },
3895     { ep_explodes_impact,               EP_EXPLODES_IMPACT              },
3896     { ep_walkable_over,                 EP_WALKABLE_OVER                },
3897     { ep_walkable_inside,               EP_WALKABLE_INSIDE              },
3898     { ep_walkable_under,                EP_WALKABLE_UNDER               },
3899     { ep_passable_over,                 EP_PASSABLE_OVER                },
3900     { ep_passable_inside,               EP_PASSABLE_INSIDE              },
3901     { ep_passable_under,                EP_PASSABLE_UNDER               },
3902     { ep_droppable,                     EP_DROPPABLE                    },
3903     { ep_explodes_1x1_old,              EP_EXPLODES_1X1_OLD             },
3904     { ep_pushable,                      EP_PUSHABLE                     },
3905     { ep_explodes_cross_old,            EP_EXPLODES_CROSS_OLD           },
3906     { ep_protected,                     EP_PROTECTED                    },
3907     { ep_throwable,                     EP_THROWABLE                    },
3908     { ep_can_explode,                   EP_CAN_EXPLODE                  },
3909     { ep_gravity_reachable,             EP_GRAVITY_REACHABLE            },
3910
3911     { ep_player,                        EP_PLAYER                       },
3912     { ep_can_pass_magic_wall,           EP_CAN_PASS_MAGIC_WALL          },
3913     { ep_can_pass_dc_magic_wall,        EP_CAN_PASS_DC_MAGIC_WALL       },
3914     { ep_switchable,                    EP_SWITCHABLE                   },
3915     { ep_bd_element,                    EP_BD_ELEMENT                   },
3916     { ep_sp_element,                    EP_SP_ELEMENT                   },
3917     { ep_sb_element,                    EP_SB_ELEMENT                   },
3918     { ep_gem,                           EP_GEM                          },
3919     { ep_food_dark_yamyam,              EP_FOOD_DARK_YAMYAM             },
3920     { ep_food_penguin,                  EP_FOOD_PENGUIN                 },
3921     { ep_food_pig,                      EP_FOOD_PIG                     },
3922     { ep_historic_wall,                 EP_HISTORIC_WALL                },
3923     { ep_historic_solid,                EP_HISTORIC_SOLID               },
3924     { ep_classic_enemy,                 EP_CLASSIC_ENEMY                },
3925     { ep_belt,                          EP_BELT                         },
3926     { ep_belt_active,                   EP_BELT_ACTIVE                  },
3927     { ep_belt_switch,                   EP_BELT_SWITCH                  },
3928     { ep_tube,                          EP_TUBE                         },
3929     { ep_keygate,                       EP_KEYGATE                      },
3930     { ep_amoeboid,                      EP_AMOEBOID                     },
3931     { ep_amoebalive,                    EP_AMOEBALIVE                   },
3932     { ep_has_editor_content,            EP_HAS_EDITOR_CONTENT           },
3933     { ep_can_turn_each_move,            EP_CAN_TURN_EACH_MOVE           },
3934     { ep_can_grow,                      EP_CAN_GROW                     },
3935     { ep_active_bomb,                   EP_ACTIVE_BOMB                  },
3936     { ep_inactive,                      EP_INACTIVE                     },
3937
3938     { ep_em_slippery_wall,              EP_EM_SLIPPERY_WALL             },
3939
3940     { ep_gfx_crumbled,                  EP_GFX_CRUMBLED                 },
3941
3942     { ep_editor_cascade_active,         EP_EDITOR_CASCADE_ACTIVE        },
3943     { ep_editor_cascade_inactive,       EP_EDITOR_CASCADE_INACTIVE      },
3944
3945     { ep_obsolete,                      EP_OBSOLETE                     },
3946
3947     { NULL,                             -1                              }
3948   };
3949
3950   int i, j, k;
3951
3952   /* always start with reliable default values (element has no properties) */
3953   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3954     for (j = 0; j < NUM_ELEMENT_PROPERTIES; j++)
3955       SET_PROPERTY(i, j, FALSE);
3956
3957   /* set all base element properties from above array definitions */
3958   for (i = 0; element_properties[i].elements != NULL; i++)
3959     for (j = 0; (element_properties[i].elements)[j] != -1; j++)
3960       SET_PROPERTY((element_properties[i].elements)[j],
3961                    element_properties[i].property, TRUE);
3962
3963   /* copy properties to some elements that are only stored in level file */
3964   for (i = 0; i < NUM_ELEMENT_PROPERTIES; i++)
3965     for (j = 0; copy_properties[j][0] != -1; j++)
3966       if (HAS_PROPERTY(copy_properties[j][0], i))
3967         for (k = 1; k <= 4; k++)
3968           SET_PROPERTY(copy_properties[j][k], i, TRUE);
3969
3970   /* set static element properties that are not listed in array definitions */
3971   for (i = EL_STEEL_CHAR_START; i <= EL_STEEL_CHAR_END; i++)
3972     SET_PROPERTY(i, EP_INDESTRUCTIBLE, TRUE);
3973 }
3974
3975 void InitElementPropertiesEngine(int engine_version)
3976 {
3977   static int no_wall_properties[] =
3978   {
3979     EP_DIGGABLE,
3980     EP_COLLECTIBLE_ONLY,
3981     EP_DONT_RUN_INTO,
3982     EP_DONT_COLLIDE_WITH,
3983     EP_CAN_MOVE,
3984     EP_CAN_FALL,
3985     EP_CAN_SMASH_PLAYER,
3986     EP_CAN_SMASH_ENEMIES,
3987     EP_CAN_SMASH_EVERYTHING,
3988     EP_PUSHABLE,
3989
3990     EP_PLAYER,
3991     EP_GEM,
3992     EP_FOOD_DARK_YAMYAM,
3993     EP_FOOD_PENGUIN,
3994     EP_BELT,
3995     EP_BELT_ACTIVE,
3996     EP_TUBE,
3997     EP_AMOEBOID,
3998     EP_AMOEBALIVE,
3999     EP_ACTIVE_BOMB,
4000
4001     EP_ACCESSIBLE,
4002
4003     -1
4004   };
4005
4006   int i, j;
4007
4008   /* important: after initialization in InitElementPropertiesStatic(), the
4009      elements are not again initialized to a default value; therefore all
4010      changes have to make sure that they leave the element with a defined
4011      property (which means that conditional property changes must be set to
4012      a reliable default value before) */
4013
4014   /* ---------- recursively resolve group elements ------------------------- */
4015
4016   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4017     for (j = 0; j < NUM_GROUP_ELEMENTS; j++)
4018       element_info[i].in_group[j] = FALSE;
4019
4020   for (i = 0; i < NUM_GROUP_ELEMENTS; i++)
4021     resolve_group_element(EL_GROUP_START + i, 0);
4022
4023   /* set all special, combined or engine dependent element properties */
4024   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4025   {
4026     /* ---------- INACTIVE ------------------------------------------------- */
4027     SET_PROPERTY(i, EP_INACTIVE, ((i >= EL_CHAR_START &&
4028                                    i <= EL_CHAR_END) ||
4029                                   (i >= EL_STEEL_CHAR_START &&
4030                                    i <= EL_STEEL_CHAR_END)));
4031
4032     /* ---------- WALKABLE, PASSABLE, ACCESSIBLE --------------------------- */
4033     SET_PROPERTY(i, EP_WALKABLE, (IS_WALKABLE_OVER(i) ||
4034                                   IS_WALKABLE_INSIDE(i) ||
4035                                   IS_WALKABLE_UNDER(i)));
4036
4037     SET_PROPERTY(i, EP_PASSABLE, (IS_PASSABLE_OVER(i) ||
4038                                   IS_PASSABLE_INSIDE(i) ||
4039                                   IS_PASSABLE_UNDER(i)));
4040
4041     SET_PROPERTY(i, EP_ACCESSIBLE_OVER, (IS_WALKABLE_OVER(i) ||
4042                                          IS_PASSABLE_OVER(i)));
4043
4044     SET_PROPERTY(i, EP_ACCESSIBLE_INSIDE, (IS_WALKABLE_INSIDE(i) ||
4045                                            IS_PASSABLE_INSIDE(i)));
4046
4047     SET_PROPERTY(i, EP_ACCESSIBLE_UNDER, (IS_WALKABLE_UNDER(i) ||
4048                                           IS_PASSABLE_UNDER(i)));
4049
4050     SET_PROPERTY(i, EP_ACCESSIBLE, (IS_WALKABLE(i) ||
4051                                     IS_PASSABLE(i)));
4052
4053     /* ---------- COLLECTIBLE ---------------------------------------------- */
4054     SET_PROPERTY(i, EP_COLLECTIBLE, (IS_COLLECTIBLE_ONLY(i) ||
4055                                      IS_DROPPABLE(i) ||
4056                                      IS_THROWABLE(i)));
4057
4058     /* ---------- SNAPPABLE ------------------------------------------------ */
4059     SET_PROPERTY(i, EP_SNAPPABLE, (IS_DIGGABLE(i) ||
4060                                    IS_COLLECTIBLE(i) ||
4061                                    IS_SWITCHABLE(i) ||
4062                                    i == EL_BD_ROCK));
4063
4064     /* ---------- WALL ----------------------------------------------------- */
4065     SET_PROPERTY(i, EP_WALL, TRUE);     /* default: element is wall */
4066
4067     for (j = 0; no_wall_properties[j] != -1; j++)
4068       if (HAS_PROPERTY(i, no_wall_properties[j]) ||
4069           i >= EL_FIRST_RUNTIME_UNREAL)
4070         SET_PROPERTY(i, EP_WALL, FALSE);
4071
4072     if (IS_HISTORIC_WALL(i))
4073       SET_PROPERTY(i, EP_WALL, TRUE);
4074
4075     /* ---------- SOLID_FOR_PUSHING ---------------------------------------- */
4076     if (engine_version < VERSION_IDENT(2,2,0,0))
4077       SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, IS_HISTORIC_SOLID(i));
4078     else
4079       SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, (!IS_WALKABLE(i) &&
4080                                              !IS_DIGGABLE(i) &&
4081                                              !IS_COLLECTIBLE(i)));
4082
4083     /* ---------- DRAGONFIRE_PROOF ----------------------------------------- */
4084     if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
4085       SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE);
4086     else
4087       SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_CUSTOM_ELEMENT(i) &&
4088                                             IS_INDESTRUCTIBLE(i)));
4089
4090     /* ---------- EXPLOSION_PROOF ------------------------------------------ */
4091     if (i == EL_FLAMES)
4092       SET_PROPERTY(i, EP_EXPLOSION_PROOF, TRUE);
4093     else if (engine_version < VERSION_IDENT(2,2,0,0))
4094       SET_PROPERTY(i, EP_EXPLOSION_PROOF, IS_INDESTRUCTIBLE(i));
4095     else
4096       SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
4097                                            (!IS_WALKABLE(i) ||
4098                                             IS_PROTECTED(i))));
4099
4100     if (IS_CUSTOM_ELEMENT(i))
4101     {
4102       /* these are additional properties which are initially false when set */
4103
4104       /* ---------- DONT_COLLIDE_WITH / DONT_RUN_INTO ---------------------- */
4105       if (DONT_TOUCH(i))
4106         SET_PROPERTY(i, EP_DONT_COLLIDE_WITH, TRUE);
4107       if (DONT_COLLIDE_WITH(i))
4108         SET_PROPERTY(i, EP_DONT_RUN_INTO, TRUE);
4109
4110       /* ---------- CAN_SMASH_ENEMIES / CAN_SMASH_PLAYER ------------------- */
4111       if (CAN_SMASH_EVERYTHING(i))
4112         SET_PROPERTY(i, EP_CAN_SMASH_ENEMIES, TRUE);
4113       if (CAN_SMASH_ENEMIES(i))
4114         SET_PROPERTY(i, EP_CAN_SMASH_PLAYER, TRUE);
4115     }
4116
4117     /* ---------- CAN_SMASH ------------------------------------------------ */
4118     SET_PROPERTY(i, EP_CAN_SMASH, (CAN_SMASH_PLAYER(i) ||
4119                                    CAN_SMASH_ENEMIES(i) ||
4120                                    CAN_SMASH_EVERYTHING(i)));
4121
4122     /* ---------- CAN_EXPLODE_BY_FIRE -------------------------------------- */
4123     SET_PROPERTY(i, EP_CAN_EXPLODE_BY_FIRE, (CAN_EXPLODE(i) &&
4124                                              EXPLODES_BY_FIRE(i)));
4125
4126     /* ---------- CAN_EXPLODE_SMASHED -------------------------------------- */
4127     SET_PROPERTY(i, EP_CAN_EXPLODE_SMASHED, (CAN_EXPLODE(i) &&
4128                                              EXPLODES_SMASHED(i)));
4129
4130     /* ---------- CAN_EXPLODE_IMPACT --------------------------------------- */
4131     SET_PROPERTY(i, EP_CAN_EXPLODE_IMPACT, (CAN_EXPLODE(i) &&
4132                                             EXPLODES_IMPACT(i)));
4133
4134     /* ---------- CAN_EXPLODE_BY_DRAGONFIRE -------------------------------- */
4135     SET_PROPERTY(i, EP_CAN_EXPLODE_BY_DRAGONFIRE, CAN_EXPLODE_BY_FIRE(i));
4136
4137     /* ---------- CAN_EXPLODE_BY_EXPLOSION --------------------------------- */
4138     SET_PROPERTY(i, EP_CAN_EXPLODE_BY_EXPLOSION, (CAN_EXPLODE_BY_FIRE(i) ||
4139                                                   i == EL_BLACK_ORB));
4140
4141     /* ---------- COULD_MOVE_INTO_ACID ------------------------------------- */
4142     SET_PROPERTY(i, EP_COULD_MOVE_INTO_ACID, (ELEM_IS_PLAYER(i) ||
4143                                               CAN_MOVE(i) ||
4144                                               IS_CUSTOM_ELEMENT(i)));
4145
4146     /* ---------- MAYBE_DONT_COLLIDE_WITH ---------------------------------- */
4147     SET_PROPERTY(i, EP_MAYBE_DONT_COLLIDE_WITH, (i == EL_SP_SNIKSNAK ||
4148                                                  i == EL_SP_ELECTRON));
4149
4150     /* ---------- CAN_MOVE_INTO_ACID --------------------------------------- */
4151     if (COULD_MOVE_INTO_ACID(i) && !IS_CUSTOM_ELEMENT(i))
4152       SET_PROPERTY(i, EP_CAN_MOVE_INTO_ACID,
4153                    getMoveIntoAcidProperty(&level, i));
4154
4155     /* ---------- DONT_COLLIDE_WITH ---------------------------------------- */
4156     if (MAYBE_DONT_COLLIDE_WITH(i))
4157       SET_PROPERTY(i, EP_DONT_COLLIDE_WITH,
4158                    getDontCollideWithProperty(&level, i));
4159
4160     /* ---------- SP_PORT -------------------------------------------------- */
4161     SET_PROPERTY(i, EP_SP_PORT, (IS_SP_ELEMENT(i) &&
4162                                  IS_PASSABLE_INSIDE(i)));
4163
4164     /* ---------- CAN_BE_CLONED_BY_ANDROID --------------------------------- */
4165     for (j = 0; j < level.num_android_clone_elements; j++)
4166       SET_PROPERTY(i, EP_CAN_BE_CLONED_BY_ANDROID,
4167                    (i != EL_EMPTY &&
4168                     IS_EQUAL_OR_IN_GROUP(i, level.android_clone_element[j])));
4169
4170     /* ---------- CAN_CHANGE ----------------------------------------------- */
4171     SET_PROPERTY(i, EP_CAN_CHANGE, FALSE);      /* default: cannot change */
4172     for (j = 0; j < element_info[i].num_change_pages; j++)
4173       if (element_info[i].change_page[j].can_change)
4174         SET_PROPERTY(i, EP_CAN_CHANGE, TRUE);
4175
4176     /* ---------- HAS_ACTION ----------------------------------------------- */
4177     SET_PROPERTY(i, EP_HAS_ACTION, FALSE);      /* default: has no action */
4178     for (j = 0; j < element_info[i].num_change_pages; j++)
4179       if (element_info[i].change_page[j].has_action)
4180         SET_PROPERTY(i, EP_HAS_ACTION, TRUE);
4181
4182     /* ---------- CAN_CHANGE_OR_HAS_ACTION --------------------------------- */
4183     SET_PROPERTY(i, EP_CAN_CHANGE_OR_HAS_ACTION, (CAN_CHANGE(i) ||
4184                                                   HAS_ACTION(i)));
4185
4186     /* ---------- GFX_CRUMBLED --------------------------------------------- */
4187 #if 1
4188     SET_PROPERTY(i, EP_GFX_CRUMBLED,
4189                  element_info[i].crumbled[ACTION_DEFAULT] !=
4190                  element_info[i].graphic[ACTION_DEFAULT]);
4191 #else
4192     /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
4193     SET_PROPERTY(i, EP_GFX_CRUMBLED,
4194                  element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
4195 #endif
4196
4197     /* ---------- EDITOR_CASCADE ------------------------------------------- */
4198     SET_PROPERTY(i, EP_EDITOR_CASCADE, (IS_EDITOR_CASCADE_ACTIVE(i) ||
4199                                         IS_EDITOR_CASCADE_INACTIVE(i)));
4200   }
4201
4202   /* dynamically adjust element properties according to game engine version */
4203   {
4204     static int ep_em_slippery_wall[] =
4205     {
4206       EL_WALL,
4207       EL_STEELWALL,
4208       EL_EXPANDABLE_WALL,
4209       EL_EXPANDABLE_WALL_HORIZONTAL,
4210       EL_EXPANDABLE_WALL_VERTICAL,
4211       EL_EXPANDABLE_WALL_ANY,
4212       EL_EXPANDABLE_STEELWALL_HORIZONTAL,
4213       EL_EXPANDABLE_STEELWALL_VERTICAL,
4214       EL_EXPANDABLE_STEELWALL_ANY,
4215       EL_EXPANDABLE_STEELWALL_GROWING,
4216       -1
4217     };
4218
4219     /* special EM style gems behaviour */
4220     for (i = 0; ep_em_slippery_wall[i] != -1; i++)
4221       SET_PROPERTY(ep_em_slippery_wall[i], EP_EM_SLIPPERY_WALL,
4222                    level.em_slippery_gems);
4223
4224     /* "EL_EXPANDABLE_WALL_GROWING" wasn't slippery for EM gems in 2.0.1 */
4225     SET_PROPERTY(EL_EXPANDABLE_WALL_GROWING, EP_EM_SLIPPERY_WALL,
4226                  (level.em_slippery_gems &&
4227                   engine_version > VERSION_IDENT(2,0,1,0)));
4228   }
4229
4230   /* this is needed because some graphics depend on element properties */
4231   if (game_status == GAME_MODE_PLAYING)
4232     InitElementGraphicInfo();
4233 }
4234
4235 void InitElementPropertiesAfterLoading(int engine_version)
4236 {
4237   int i;
4238
4239   /* set some other uninitialized values of custom elements in older levels */
4240   if (engine_version < VERSION_IDENT(3,1,0,0))
4241   {
4242     for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
4243     {
4244       int element = EL_CUSTOM_START + i;
4245
4246       element_info[element].access_direction = MV_ALL_DIRECTIONS;
4247
4248       element_info[element].explosion_delay = 17;
4249       element_info[element].ignition_delay = 8;
4250     }
4251   }
4252 }
4253
4254 static void InitGlobal()
4255 {
4256   int i;
4257
4258   for (i = 0; i < MAX_NUM_ELEMENTS + 1; i++)
4259   {
4260     /* check if element_name_info entry defined for each element in "main.h" */
4261     if (i < MAX_NUM_ELEMENTS && element_name_info[i].token_name == NULL)
4262       Error(ERR_EXIT, "undefined 'element_name_info' entry for element %d", i);
4263
4264     element_info[i].token_name = element_name_info[i].token_name;
4265     element_info[i].class_name = element_name_info[i].class_name;
4266     element_info[i].editor_description=element_name_info[i].editor_description;
4267
4268 #if 0
4269     printf("%04d: %s\n", i, element_name_info[i].token_name);
4270 #endif
4271   }
4272
4273   global.autoplay_leveldir = NULL;
4274   global.convert_leveldir = NULL;
4275
4276   global.frames_per_second = 0;
4277   global.fps_slowdown = FALSE;
4278   global.fps_slowdown_factor = 1;
4279 }
4280
4281 void Execute_Command(char *command)
4282 {
4283   int i;
4284
4285   if (strEqual(command, "print graphicsinfo.conf"))
4286   {
4287     printf("# You can configure additional/alternative image files here.\n");
4288     printf("# (The entries below are default and therefore commented out.)\n");
4289     printf("\n");
4290     printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
4291     printf("\n");
4292     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
4293     printf("\n");
4294
4295     for (i = 0; image_config[i].token != NULL; i++)
4296       printf("# %s\n", getFormattedSetupEntry(image_config[i].token,
4297                                               image_config[i].value));
4298
4299     exit(0);
4300   }
4301   else if (strEqual(command, "print soundsinfo.conf"))
4302   {
4303     printf("# You can configure additional/alternative sound files here.\n");
4304     printf("# (The entries below are default and therefore commented out.)\n");
4305     printf("\n");
4306     printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
4307     printf("\n");
4308     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
4309     printf("\n");
4310
4311     for (i = 0; sound_config[i].token != NULL; i++)
4312       printf("# %s\n", getFormattedSetupEntry(sound_config[i].token,
4313                                               sound_config[i].value));
4314
4315     exit(0);
4316   }
4317   else if (strEqual(command, "print musicinfo.conf"))
4318   {
4319     printf("# You can configure additional/alternative music files here.\n");
4320     printf("# (The entries below are default and therefore commented out.)\n");
4321     printf("\n");
4322     printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
4323     printf("\n");
4324     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
4325     printf("\n");
4326
4327     for (i = 0; music_config[i].token != NULL; i++)
4328       printf("# %s\n", getFormattedSetupEntry(music_config[i].token,
4329                                               music_config[i].value));
4330
4331     exit(0);
4332   }
4333   else if (strEqual(command, "print editorsetup.conf"))
4334   {
4335     printf("# You can configure your personal editor element list here.\n");
4336     printf("# (The entries below are default and therefore commented out.)\n");
4337     printf("\n");
4338
4339     /* this is needed to be able to check element list for cascade elements */
4340     InitElementPropertiesStatic();
4341     InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
4342
4343     PrintEditorElementList();
4344
4345     exit(0);
4346   }
4347   else if (strEqual(command, "print helpanim.conf"))
4348   {
4349     printf("# You can configure different element help animations here.\n");
4350     printf("# (The entries below are default and therefore commented out.)\n");
4351     printf("\n");
4352
4353     for (i = 0; helpanim_config[i].token != NULL; i++)
4354     {
4355       printf("# %s\n", getFormattedSetupEntry(helpanim_config[i].token,
4356                                               helpanim_config[i].value));
4357
4358       if (strEqual(helpanim_config[i].token, "end"))
4359         printf("#\n");
4360     }
4361
4362     exit(0);
4363   }
4364   else if (strEqual(command, "print helptext.conf"))
4365   {
4366     printf("# You can configure different element help text here.\n");
4367     printf("# (The entries below are default and therefore commented out.)\n");
4368     printf("\n");
4369
4370     for (i = 0; helptext_config[i].token != NULL; i++)
4371       printf("# %s\n", getFormattedSetupEntry(helptext_config[i].token,
4372                                               helptext_config[i].value));
4373
4374     exit(0);
4375   }
4376   else if (strncmp(command, "dump level ", 11) == 0)
4377   {
4378     char *filename = &command[11];
4379
4380     if (!fileExists(filename))
4381       Error(ERR_EXIT, "cannot open file '%s'", filename);
4382
4383     LoadLevelFromFilename(&level, filename);
4384     DumpLevel(&level);
4385
4386     exit(0);
4387   }
4388   else if (strncmp(command, "dump tape ", 10) == 0)
4389   {
4390     char *filename = &command[10];
4391
4392     if (!fileExists(filename))
4393       Error(ERR_EXIT, "cannot open file '%s'", filename);
4394
4395     LoadTapeFromFilename(filename);
4396     DumpTape(&tape);
4397
4398     exit(0);
4399   }
4400   else if (strncmp(command, "autoplay ", 9) == 0)
4401   {
4402     char *str_ptr = getStringCopy(&command[9]); /* read command parameters */
4403
4404     while (*str_ptr != '\0')                    /* continue parsing string */
4405     {
4406       /* cut leading whitespace from string, replace it by string terminator */
4407       while (*str_ptr == ' ' || *str_ptr == '\t')
4408         *str_ptr++ = '\0';
4409
4410       if (*str_ptr == '\0')                     /* end of string reached */
4411         break;
4412
4413       if (global.autoplay_leveldir == NULL)     /* read level set string */
4414       {
4415         global.autoplay_leveldir = str_ptr;
4416         global.autoplay_all = TRUE;             /* default: play all tapes */
4417
4418         for (i = 0; i < MAX_TAPES_PER_SET; i++)
4419           global.autoplay_level[i] = FALSE;
4420       }
4421       else                                      /* read level number string */
4422       {
4423         int level_nr = atoi(str_ptr);           /* get level_nr value */
4424
4425         if (level_nr >= 0 && level_nr < MAX_TAPES_PER_SET)
4426           global.autoplay_level[level_nr] = TRUE;
4427
4428         global.autoplay_all = FALSE;
4429       }
4430
4431       /* advance string pointer to the next whitespace (or end of string) */
4432       while (*str_ptr != ' ' && *str_ptr != '\t' && *str_ptr != '\0')
4433         str_ptr++;
4434     }
4435   }
4436   else if (strncmp(command, "convert ", 8) == 0)
4437   {
4438     char *str_copy = getStringCopy(&command[8]);
4439     char *str_ptr = strchr(str_copy, ' ');
4440
4441     global.convert_leveldir = str_copy;
4442     global.convert_level_nr = -1;
4443
4444     if (str_ptr != NULL)                        /* level number follows */
4445     {
4446       *str_ptr++ = '\0';                        /* terminate leveldir string */
4447       global.convert_level_nr = atoi(str_ptr);  /* get level_nr value */
4448     }
4449   }
4450
4451 #if DEBUG
4452 #if defined(TARGET_SDL)
4453   else if (strEqual(command, "SDL_ListModes"))
4454   {
4455     SDL_Rect **modes;
4456     int i;
4457
4458     SDL_Init(SDL_INIT_VIDEO);
4459
4460     /* get available fullscreen/hardware modes */
4461     modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
4462
4463     /* check if there are any modes available */
4464     if (modes == NULL)
4465     {
4466       printf("No modes available!\n");
4467
4468       exit(-1);
4469     }
4470
4471     /* check if our resolution is restricted */
4472     if (modes == (SDL_Rect **)-1)
4473     {
4474       printf("All resolutions available.\n");
4475     }
4476     else
4477     {
4478       printf("Available Modes:\n");
4479
4480       for(i = 0; modes[i]; i++)
4481         printf("  %d x %d\n", modes[i]->w, modes[i]->h);
4482     }
4483
4484     exit(0);
4485   }
4486 #endif
4487 #endif
4488
4489   else
4490   {
4491     Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
4492   }
4493 }
4494
4495 static void InitSetup()
4496 {
4497   LoadSetup();                                  /* global setup info */
4498
4499   /* set some options from setup file */
4500
4501   if (setup.options.verbose)
4502     options.verbose = TRUE;
4503 }
4504
4505 static void InitGameInfo()
4506 {
4507   game.restart_level = FALSE;
4508 }
4509
4510 static void InitPlayerInfo()
4511 {
4512   int i;
4513
4514   /* choose default local player */
4515   local_player = &stored_player[0];
4516
4517   for (i = 0; i < MAX_PLAYERS; i++)
4518     stored_player[i].connected = FALSE;
4519
4520   local_player->connected = TRUE;
4521 }
4522
4523 static void InitArtworkInfo()
4524 {
4525   LoadArtworkInfo();
4526 }
4527
4528 static char *get_string_in_brackets(char *string)
4529 {
4530   char *string_in_brackets = checked_malloc(strlen(string) + 3);
4531
4532   sprintf(string_in_brackets, "[%s]", string);
4533
4534   return string_in_brackets;
4535 }
4536
4537 static char *get_level_id_suffix(int id_nr)
4538 {
4539   char *id_suffix = checked_malloc(1 + 3 + 1);
4540
4541   if (id_nr < 0 || id_nr > 999)
4542     id_nr = 0;
4543
4544   sprintf(id_suffix, ".%03d", id_nr);
4545
4546   return id_suffix;
4547 }
4548
4549 #if 0
4550 static char *get_element_class_token(int element)
4551 {
4552   char *element_class_name = element_info[element].class_name;
4553   char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
4554
4555   sprintf(element_class_token, "[%s]", element_class_name);
4556
4557   return element_class_token;
4558 }
4559
4560 static char *get_action_class_token(int action)
4561 {
4562   char *action_class_name = &element_action_info[action].suffix[1];
4563   char *action_class_token = checked_malloc(strlen(action_class_name) + 3);
4564
4565   sprintf(action_class_token, "[%s]", action_class_name);
4566
4567   return action_class_token;
4568 }
4569 #endif
4570
4571 static void InitArtworkConfig()
4572 {
4573   static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
4574   static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + 1];
4575   static char *music_id_prefix[NUM_MUSIC_PREFIXES + 1];
4576   static char *action_id_suffix[NUM_ACTIONS + 1];
4577   static char *direction_id_suffix[NUM_DIRECTIONS_FULL + 1];
4578   static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
4579   static char *level_id_suffix[MAX_LEVELS + 1];
4580   static char *dummy[1] = { NULL };
4581   static char *ignore_generic_tokens[] =
4582   {
4583     "name",
4584     "sort_priority",
4585     NULL
4586   };
4587   static char **ignore_image_tokens;
4588   static char **ignore_sound_tokens;
4589   static char **ignore_music_tokens;
4590   int num_ignore_generic_tokens;
4591   int num_ignore_image_tokens;
4592   int num_ignore_sound_tokens;
4593   int num_ignore_music_tokens;
4594   int i;
4595
4596   /* dynamically determine list of generic tokens to be ignored */
4597   num_ignore_generic_tokens = 0;
4598   for (i = 0; ignore_generic_tokens[i] != NULL; i++)
4599     num_ignore_generic_tokens++;
4600
4601   /* dynamically determine list of image tokens to be ignored */
4602   num_ignore_image_tokens = num_ignore_generic_tokens;
4603   for (i = 0; image_config_vars[i].token != NULL; i++)
4604     num_ignore_image_tokens++;
4605   ignore_image_tokens =
4606     checked_malloc((num_ignore_image_tokens + 1) * sizeof(char *));
4607   for (i = 0; i < num_ignore_generic_tokens; i++)
4608     ignore_image_tokens[i] = ignore_generic_tokens[i];
4609   for (i = 0; i < num_ignore_image_tokens - num_ignore_generic_tokens; i++)
4610     ignore_image_tokens[num_ignore_generic_tokens + i] =
4611       image_config_vars[i].token;
4612   ignore_image_tokens[num_ignore_image_tokens] = NULL;
4613
4614   /* dynamically determine list of sound tokens to be ignored */
4615   num_ignore_sound_tokens = num_ignore_generic_tokens;
4616   ignore_sound_tokens =
4617     checked_malloc((num_ignore_sound_tokens + 1) * sizeof(char *));
4618   for (i = 0; i < num_ignore_generic_tokens; i++)
4619     ignore_sound_tokens[i] = ignore_generic_tokens[i];
4620   ignore_sound_tokens[num_ignore_sound_tokens] = NULL;
4621
4622   /* dynamically determine list of music tokens to be ignored */
4623   num_ignore_music_tokens = num_ignore_generic_tokens;
4624   ignore_music_tokens =
4625     checked_malloc((num_ignore_music_tokens + 1) * sizeof(char *));
4626   for (i = 0; i < num_ignore_generic_tokens; i++)
4627     ignore_music_tokens[i] = ignore_generic_tokens[i];
4628   ignore_music_tokens[num_ignore_music_tokens] = NULL;
4629
4630   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4631     image_id_prefix[i] = element_info[i].token_name;
4632   for (i = 0; i < NUM_FONTS; i++)
4633     image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
4634   image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
4635
4636   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4637     sound_id_prefix[i] = element_info[i].token_name;
4638   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4639     sound_id_prefix[MAX_NUM_ELEMENTS + i] =
4640       get_string_in_brackets(element_info[i].class_name);
4641   sound_id_prefix[2 * MAX_NUM_ELEMENTS] = NULL;
4642
4643   for (i = 0; i < NUM_MUSIC_PREFIXES; i++)
4644     music_id_prefix[i] = music_prefix_info[i].prefix;
4645   music_id_prefix[NUM_MUSIC_PREFIXES] = NULL;
4646
4647   for (i = 0; i < NUM_ACTIONS; i++)
4648     action_id_suffix[i] = element_action_info[i].suffix;
4649   action_id_suffix[NUM_ACTIONS] = NULL;
4650
4651   for (i = 0; i < NUM_DIRECTIONS_FULL; i++)
4652     direction_id_suffix[i] = element_direction_info[i].suffix;
4653   direction_id_suffix[NUM_DIRECTIONS_FULL] = NULL;
4654
4655   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
4656     special_id_suffix[i] = special_suffix_info[i].suffix;
4657   special_id_suffix[NUM_SPECIAL_GFX_ARGS] = NULL;
4658
4659   for (i = 0; i < MAX_LEVELS; i++)
4660     level_id_suffix[i] = get_level_id_suffix(i);
4661   level_id_suffix[MAX_LEVELS] = NULL;
4662
4663   InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
4664                 image_id_prefix, action_id_suffix, direction_id_suffix,
4665                 special_id_suffix, ignore_image_tokens);
4666   InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
4667                 sound_id_prefix, action_id_suffix, dummy,
4668                 special_id_suffix, ignore_sound_tokens);
4669   InitMusicList(music_config, NUM_MUSIC_FILES, music_config_suffix,
4670                 music_id_prefix, special_id_suffix, level_id_suffix,
4671                 dummy, ignore_music_tokens);
4672 }
4673
4674 static void InitMixer()
4675 {
4676   OpenAudio();
4677   StartMixer();
4678 }
4679
4680 void InitGfx()
4681 {
4682   char *filename_font_initial = NULL;
4683   Bitmap *bitmap_font_initial = NULL;
4684   int font_height;
4685   int i, j;
4686
4687   /* determine settings for initial font (for displaying startup messages) */
4688   for (i = 0; image_config[i].token != NULL; i++)
4689   {
4690     for (j = 0; j < NUM_INITIAL_FONTS; j++)
4691     {
4692       char font_token[128];
4693       int len_font_token;
4694
4695       sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1);
4696       len_font_token = strlen(font_token);
4697
4698       if (strEqual(image_config[i].token, font_token))
4699         filename_font_initial = image_config[i].value;
4700       else if (strlen(image_config[i].token) > len_font_token &&
4701                strncmp(image_config[i].token, font_token, len_font_token) == 0)
4702       {
4703         if (strEqual(&image_config[i].token[len_font_token], ".x"))
4704           font_initial[j].src_x = atoi(image_config[i].value);
4705         else if (strEqual(&image_config[i].token[len_font_token], ".y"))
4706           font_initial[j].src_y = atoi(image_config[i].value);
4707         else if (strEqual(&image_config[i].token[len_font_token], ".width"))
4708           font_initial[j].width = atoi(image_config[i].value);
4709         else if (strEqual(&image_config[i].token[len_font_token],".height"))
4710           font_initial[j].height = atoi(image_config[i].value);
4711       }
4712     }
4713   }
4714
4715   for (j = 0; j < NUM_INITIAL_FONTS; j++)
4716   {
4717     font_initial[j].num_chars = DEFAULT_NUM_CHARS_PER_FONT;
4718     font_initial[j].num_chars_per_line = DEFAULT_NUM_CHARS_PER_LINE;
4719   }
4720
4721   if (filename_font_initial == NULL)    /* should not happen */
4722     Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
4723
4724   /* create additional image buffers for double-buffering and cross-fading */
4725   bitmap_db_cross = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
4726   bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
4727   bitmap_db_panel = CreateBitmap(DXSIZE, DYSIZE, DEFAULT_DEPTH);
4728   bitmap_db_door  = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
4729
4730   /* initialize screen properties */
4731   InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
4732                    REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
4733                    bitmap_db_field);
4734   InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
4735   InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
4736   InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
4737
4738   bitmap_font_initial = LoadCustomImage(filename_font_initial);
4739
4740   for (j = 0; j < NUM_INITIAL_FONTS; j++)
4741     font_initial[j].bitmap = bitmap_font_initial;
4742
4743   InitFontGraphicInfo();
4744
4745   font_height = getFontHeight(FC_RED);
4746
4747 #if 1
4748   DrawInitText(getWindowTitleString(), 20, FC_YELLOW);
4749 #else
4750   DrawInitText(getProgramInitString(), 20, FC_YELLOW);
4751 #endif
4752   DrawInitText(PROGRAM_COPYRIGHT_STRING, 50, FC_RED);
4753   DrawInitText(PROGRAM_WEBSITE_STRING, WIN_YSIZE - 20 - font_height, FC_RED);
4754
4755   DrawInitText("Loading graphics", 120, FC_GREEN);
4756 }
4757
4758 void RedrawBackground()
4759 {
4760   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
4761              0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
4762
4763   redraw_mask = REDRAW_ALL;
4764 }
4765
4766 void InitGfxBackground()
4767 {
4768   int x, y;
4769
4770   fieldbuffer = bitmap_db_field;
4771   SetDrawtoField(DRAW_BACKBUFFER);
4772
4773   RedrawBackground();
4774
4775   ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
4776   ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
4777
4778   for (x = 0; x < MAX_BUF_XSIZE; x++)
4779     for (y = 0; y < MAX_BUF_YSIZE; y++)
4780       redraw[x][y] = 0;
4781   redraw_tiles = 0;
4782   redraw_mask = REDRAW_ALL;
4783 }
4784
4785 static void InitLevelInfo()
4786 {
4787   LoadLevelInfo();                              /* global level info */
4788   LoadLevelSetup_LastSeries();                  /* last played series info */
4789   LoadLevelSetup_SeriesInfo();                  /* last played level info */
4790 }
4791
4792 void InitLevelArtworkInfo()
4793 {
4794   LoadLevelArtworkInfo();
4795 }
4796
4797 static void InitImages()
4798 {
4799   setLevelArtworkDir(artwork.gfx_first);
4800
4801 #if 0
4802   printf("::: InitImages for '%s' ['%s', '%s'] ['%s', '%s']\n",
4803          leveldir_current->identifier,
4804          artwork.gfx_current_identifier,
4805          artwork.gfx_current->identifier,
4806          leveldir_current->graphics_set,
4807          leveldir_current->graphics_path);
4808 #endif
4809
4810   ReloadCustomImages();
4811
4812   LoadCustomElementDescriptions();
4813   LoadSpecialMenuDesignSettings();
4814
4815   ReinitializeGraphics();
4816 }
4817
4818 static void InitSound(char *identifier)
4819 {
4820   if (identifier == NULL)
4821     identifier = artwork.snd_current->identifier;
4822
4823   /* set artwork path to send it to the sound server process */
4824   setLevelArtworkDir(artwork.snd_first);
4825
4826   InitReloadCustomSounds(identifier);
4827   ReinitializeSounds();
4828 }
4829
4830 static void InitMusic(char *identifier)
4831 {
4832   if (identifier == NULL)
4833     identifier = artwork.mus_current->identifier;
4834
4835   /* set artwork path to send it to the sound server process */
4836   setLevelArtworkDir(artwork.mus_first);
4837
4838   InitReloadCustomMusic(identifier);
4839   ReinitializeMusic();
4840 }
4841
4842 void InitNetworkServer()
4843 {
4844 #if defined(NETWORK_AVALIABLE)
4845   int nr_wanted;
4846 #endif
4847
4848   if (!options.network)
4849     return;
4850
4851 #if defined(NETWORK_AVALIABLE)
4852   nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
4853
4854   if (!ConnectToServer(options.server_host, options.server_port))
4855     Error(ERR_EXIT, "cannot connect to network game server");
4856
4857   SendToServer_PlayerName(setup.player_name);
4858   SendToServer_ProtocolVersion();
4859
4860   if (nr_wanted)
4861     SendToServer_NrWanted(nr_wanted);
4862 #endif
4863 }
4864
4865 static char *getNewArtworkIdentifier(int type)
4866 {
4867   static char *leveldir_current_identifier[3] = { NULL, NULL, NULL };
4868   static boolean last_override_level_artwork[3] = { FALSE, FALSE, FALSE };
4869   static boolean last_has_level_artwork_set[3] = { FALSE, FALSE, FALSE };
4870   static boolean initialized[3] = { FALSE, FALSE, FALSE };
4871   TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
4872   boolean setup_override_artwork = SETUP_OVERRIDE_ARTWORK(setup, type);
4873   char *setup_artwork_set = SETUP_ARTWORK_SET(setup, type);
4874   char *leveldir_identifier = leveldir_current->identifier;
4875 #if 1
4876   /* !!! setLevelArtworkDir() should be moved to an earlier stage !!! */
4877   char *leveldir_artwork_set = setLevelArtworkDir(artwork_first_node);
4878 #else
4879   char *leveldir_artwork_set = LEVELDIR_ARTWORK_SET(leveldir_current, type);
4880 #endif
4881   boolean has_level_artwork_set = (leveldir_artwork_set != NULL);
4882   char *artwork_current_identifier;
4883   char *artwork_new_identifier = NULL;  /* default: nothing has changed */
4884
4885   /* leveldir_current may be invalid (level group, parent link) */
4886   if (!validLevelSeries(leveldir_current))
4887     return NULL;
4888
4889   /* 1st step: determine artwork set to be activated in descending order:
4890      --------------------------------------------------------------------
4891      1. setup artwork (when configured to override everything else)
4892      2. artwork set configured in "levelinfo.conf" of current level set
4893         (artwork in level directory will have priority when loading later)
4894      3. artwork in level directory (stored in artwork sub-directory)
4895      4. setup artwork (currently configured in setup menu) */
4896
4897   if (setup_override_artwork)
4898     artwork_current_identifier = setup_artwork_set;
4899   else if (leveldir_artwork_set != NULL)
4900     artwork_current_identifier = leveldir_artwork_set;
4901   else if (getTreeInfoFromIdentifier(artwork_first_node, leveldir_identifier))
4902     artwork_current_identifier = leveldir_identifier;
4903   else
4904     artwork_current_identifier = setup_artwork_set;
4905
4906
4907   /* 2nd step: check if it is really needed to reload artwork set
4908      ------------------------------------------------------------ */
4909
4910 #if 0
4911   if (type == ARTWORK_TYPE_GRAPHICS)
4912     printf("::: 0: '%s' ['%s', '%s'] ['%s' ('%s')]\n",
4913            artwork_new_identifier,
4914            ARTWORK_CURRENT_IDENTIFIER(artwork, type),
4915            artwork_current_identifier,
4916            leveldir_current->graphics_set,
4917            leveldir_current->identifier);
4918 #endif
4919
4920   /* ---------- reload if level set and also artwork set has changed ------- */
4921   if (leveldir_current_identifier[type] != leveldir_identifier &&
4922       (last_has_level_artwork_set[type] || has_level_artwork_set))
4923     artwork_new_identifier = artwork_current_identifier;
4924
4925   leveldir_current_identifier[type] = leveldir_identifier;
4926   last_has_level_artwork_set[type] = has_level_artwork_set;
4927
4928 #if 0
4929   if (type == ARTWORK_TYPE_GRAPHICS)
4930     printf("::: 1: '%s'\n", artwork_new_identifier);
4931 #endif
4932
4933   /* ---------- reload if "override artwork" setting has changed ----------- */
4934   if (last_override_level_artwork[type] != setup_override_artwork)
4935     artwork_new_identifier = artwork_current_identifier;
4936
4937   last_override_level_artwork[type] = setup_override_artwork;
4938
4939 #if 0
4940   if (type == ARTWORK_TYPE_GRAPHICS)
4941     printf("::: 2: '%s'\n", artwork_new_identifier);
4942 #endif
4943
4944   /* ---------- reload if current artwork identifier has changed ----------- */
4945   if (!strEqual(ARTWORK_CURRENT_IDENTIFIER(artwork, type),
4946                 artwork_current_identifier))
4947     artwork_new_identifier = artwork_current_identifier;
4948
4949   *(ARTWORK_CURRENT_IDENTIFIER_PTR(artwork, type))= artwork_current_identifier;
4950
4951 #if 0
4952   if (type == ARTWORK_TYPE_GRAPHICS)
4953     printf("::: 3: '%s'\n", artwork_new_identifier);
4954 #endif
4955
4956   /* ---------- do not reload directly after starting ---------------------- */
4957   if (!initialized[type])
4958     artwork_new_identifier = NULL;
4959
4960   initialized[type] = TRUE;
4961
4962 #if 0
4963   if (type == ARTWORK_TYPE_GRAPHICS)
4964     printf("::: 4: '%s'\n", artwork_new_identifier);
4965 #endif
4966
4967 #if 0
4968   if (type == ARTWORK_TYPE_GRAPHICS)
4969     printf("CHECKING OLD/NEW GFX:\n- OLD: %s\n- NEW: %s ['%s', '%s'] ['%s']\n",
4970            artwork.gfx_current_identifier, artwork_current_identifier,
4971            artwork.gfx_current->identifier, leveldir_current->graphics_set,
4972            artwork_new_identifier);
4973 #endif
4974
4975   return artwork_new_identifier;
4976 }
4977
4978 void ReloadCustomArtwork(int force_reload)
4979 {
4980   char *gfx_new_identifier;
4981   char *snd_new_identifier;
4982   char *mus_new_identifier;
4983   boolean force_reload_gfx = (force_reload & (1 << ARTWORK_TYPE_GRAPHICS));
4984   boolean force_reload_snd = (force_reload & (1 << ARTWORK_TYPE_SOUNDS));
4985   boolean force_reload_mus = (force_reload & (1 << ARTWORK_TYPE_MUSIC));
4986   boolean redraw_screen = FALSE;
4987
4988   force_reload_gfx |= AdjustGraphicsForEMC();
4989
4990   gfx_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_GRAPHICS);
4991   snd_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_SOUNDS);
4992   mus_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_MUSIC);
4993
4994   if (gfx_new_identifier != NULL || force_reload_gfx)
4995   {
4996 #if 0
4997     printf("RELOADING GRAPHICS '%s' -> '%s' ['%s', '%s']\n",
4998            artwork.gfx_current_identifier,
4999            gfx_new_identifier,
5000            artwork.gfx_current->identifier,
5001            leveldir_current->graphics_set);
5002 #endif
5003
5004     ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
5005
5006     InitImages();
5007
5008     redraw_screen = TRUE;
5009   }
5010
5011   if (snd_new_identifier != NULL || force_reload_snd)
5012   {
5013     ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
5014
5015     InitSound(snd_new_identifier);
5016
5017     redraw_screen = TRUE;
5018   }
5019
5020   if (mus_new_identifier != NULL || force_reload_mus)
5021   {
5022     ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
5023
5024     InitMusic(mus_new_identifier);
5025
5026     redraw_screen = TRUE;
5027   }
5028
5029   if (redraw_screen)
5030   {
5031     RedrawBackground();
5032
5033     /* force redraw of (open or closed) door graphics */
5034     SetDoorState(DOOR_OPEN_ALL);
5035     CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
5036   }
5037 }
5038
5039 void KeyboardAutoRepeatOffUnlessAutoplay()
5040 {
5041   if (global.autoplay_leveldir == NULL)
5042     KeyboardAutoRepeatOff();
5043 }
5044
5045
5046 /* ========================================================================= */
5047 /* OpenAll()                                                                 */
5048 /* ========================================================================= */
5049
5050 void OpenAll()
5051 {
5052   InitGlobal();                 /* initialize some global variables */
5053
5054   if (options.execute_command)
5055     Execute_Command(options.execute_command);
5056
5057   if (options.serveronly)
5058   {
5059 #if defined(PLATFORM_UNIX)
5060     NetworkServer(options.server_port, options.serveronly);
5061 #else
5062     Error(ERR_WARN, "networking only supported in Unix version");
5063 #endif
5064
5065     exit(0);                    /* never reached, server loops forever */
5066   }
5067
5068   InitSetup();
5069
5070   InitGameInfo();
5071   InitPlayerInfo();
5072   InitArtworkInfo();            /* needed before loading gfx, sound & music */
5073   InitArtworkConfig();          /* needed before forking sound child process */
5074   InitMixer();
5075
5076   InitCounter();
5077
5078   InitRND(NEW_RANDOMIZE);
5079   InitSimpleRandom(NEW_RANDOMIZE);
5080
5081   InitJoysticks();
5082
5083   InitVideoDisplay();
5084   InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
5085
5086   InitEventFilter(FilterMouseMotionEvents);
5087
5088   InitElementPropertiesStatic();
5089   InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
5090
5091   InitGfx();
5092
5093   // debug_print_timestamp(0, "INIT");
5094   InitLevelInfo();
5095   // debug_print_timestamp(0, "TIME InitLevelInfo:        ");
5096   InitLevelArtworkInfo();
5097   // debug_print_timestamp(0, "TIME InitLevelArtworkInfo: ");
5098
5099   InitImages();                 /* needs to know current level directory */
5100   InitSound(NULL);              /* needs to know current level directory */
5101   InitMusic(NULL);              /* needs to know current level directory */
5102
5103   InitGfxBackground();
5104
5105 #if 1
5106   em_open_all();
5107 #endif
5108
5109   if (global.autoplay_leveldir)
5110   {
5111     AutoPlayTape();
5112     return;
5113   }
5114   else if (global.convert_leveldir)
5115   {
5116     ConvertLevels();
5117     return;
5118   }
5119
5120   game_status = GAME_MODE_MAIN;
5121
5122   DrawMainMenu();
5123
5124   InitNetworkServer();
5125 }
5126
5127 void CloseAllAndExit(int exit_value)
5128 {
5129   StopSounds();
5130   FreeAllSounds();
5131   FreeAllMusic();
5132   CloseAudio();         /* called after freeing sounds (needed for SDL) */
5133
5134 #if 1
5135   em_close_all();
5136 #endif
5137
5138   FreeAllImages();
5139
5140 #if defined(TARGET_SDL)
5141   if (network_server)   /* terminate network server */
5142     SDL_KillThread(server_thread);
5143 #endif
5144
5145   CloseVideoDisplay();
5146   ClosePlatformDependentStuff();
5147
5148   if (exit_value != 0)
5149     NotifyUserAboutErrorFile();
5150
5151   exit(exit_value);
5152 }