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