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