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