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