added detecting use of touch device for user input on current platform
[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 "anim.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 // forward declaration for internal use
88 static int get_graphic_parameter_value(char *, char *, int);
89
90
91 static void DrawInitAnim(void)
92 {
93   struct GraphicInfo *graphic_info_last = graphic_info;
94   int graphic = 0;
95   static unsigned int action_delay = 0;
96   unsigned int action_delay_value = GameFrameDelay;
97   int sync_frame = FrameCounter;
98   int x, y;
99
100   // prevent OS (Windows) from complaining about program not responding
101   CheckQuitEvent();
102
103   if (game_status != GAME_MODE_LOADING)
104     return;
105
106   if (anim_initial.bitmap == NULL || window == NULL)
107     return;
108
109   if (!DelayReached(&action_delay, action_delay_value))
110     return;
111
112   if (init_last.busy.x == -1)
113     init_last.busy.x = WIN_XSIZE / 2;
114   if (init_last.busy.y == -1)
115     init_last.busy.y = WIN_YSIZE / 2;
116
117   x = ALIGNED_TEXT_XPOS(&init_last.busy);
118   y = ALIGNED_TEXT_YPOS(&init_last.busy);
119
120   graphic_info = &anim_initial;         // graphic == 0 => anim_initial
121
122   if (sync_frame % anim_initial.anim_delay == 0)
123   {
124     Bitmap *src_bitmap;
125     int src_x, src_y;
126     int width = graphic_info[graphic].width;
127     int height = graphic_info[graphic].height;
128     int frame = getGraphicAnimationFrame(graphic, sync_frame);
129
130     getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
131     BlitBitmap(src_bitmap, window, src_x, src_y, width, height, x, y);
132   }
133
134   graphic_info = graphic_info_last;
135
136   FrameCounter++;
137 }
138
139 static void DrawProgramInfo(void)
140 {
141   int font1_nr = FC_YELLOW;
142   int font2_nr = FC_RED;
143   int font2_height = getFontHeight(font2_nr);
144   int ypos1 = 20;
145   int ypos2 = 50;
146   int ypos3 = WIN_YSIZE - 20 - font2_height;
147
148   DrawInitText(getProgramInitString(),           ypos1, font1_nr);
149   DrawInitText(setup.internal.program_copyright, ypos2, font2_nr);
150   DrawInitText(setup.internal.program_website,   ypos3, font2_nr);
151 }
152
153 static void FreeGadgets(void)
154 {
155   FreeLevelEditorGadgets();
156   FreeGameButtons();
157   FreeTapeButtons();
158   FreeToolButtons();
159   FreeScreenGadgets();
160 }
161
162 void InitGadgets(void)
163 {
164   static boolean gadgets_initialized = FALSE;
165
166   if (gadgets_initialized)
167     FreeGadgets();
168
169   CreateLevelEditorGadgets();
170   CreateGameButtons();
171   CreateTapeButtons();
172   CreateToolButtons();
173   CreateScreenGadgets();
174
175   InitGadgetsSoundCallback(PlaySoundActivating, PlaySoundSelecting);
176
177   gadgets_initialized = TRUE;
178 }
179
180 static void InitElementSmallImagesScaledUp(int graphic)
181 {
182   struct GraphicInfo *g = &graphic_info[graphic];
183
184   // create small and game tile sized bitmaps (and scale up, if needed)
185   CreateImageWithSmallImages(graphic, g->scale_up_factor, g->tile_size);
186 }
187
188 static void InitElementSmallImages(void)
189 {
190   print_timestamp_init("InitElementSmallImages");
191
192   static int special_graphics[] =
193   {
194     IMG_FLAMES_1_LEFT,
195     IMG_FLAMES_2_LEFT,
196     IMG_FLAMES_3_LEFT,
197     IMG_FLAMES_1_RIGHT,
198     IMG_FLAMES_2_RIGHT,
199     IMG_FLAMES_3_RIGHT,
200     IMG_FLAMES_1_UP,
201     IMG_FLAMES_2_UP,
202     IMG_FLAMES_3_UP,
203     IMG_FLAMES_1_DOWN,
204     IMG_FLAMES_2_DOWN,
205     IMG_FLAMES_3_DOWN,
206     IMG_EDITOR_ELEMENT_BORDER,
207     IMG_EDITOR_ELEMENT_BORDER_INPUT,
208     IMG_EDITOR_CASCADE_LIST,
209     IMG_EDITOR_CASCADE_LIST_ACTIVE,
210     -1
211   };
212   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
213   int num_property_mappings = getImageListPropertyMappingSize();
214   int i;
215
216   print_timestamp_time("getImageListPropertyMapping/Size");
217
218   print_timestamp_init("InitElementSmallImagesScaledUp (1)");
219   // initialize normal element images from static configuration
220   for (i = 0; element_to_graphic[i].element > -1; i++)
221     InitElementSmallImagesScaledUp(element_to_graphic[i].graphic);
222   print_timestamp_done("InitElementSmallImagesScaledUp (1)");
223
224   // initialize special element images from static configuration
225   for (i = 0; element_to_special_graphic[i].element > -1; i++)
226     InitElementSmallImagesScaledUp(element_to_special_graphic[i].graphic);
227   print_timestamp_time("InitElementSmallImagesScaledUp (2)");
228
229   // initialize element images from dynamic configuration
230   for (i = 0; i < num_property_mappings; i++)
231     if (property_mapping[i].base_index < MAX_NUM_ELEMENTS)
232       InitElementSmallImagesScaledUp(property_mapping[i].artwork_index);
233   print_timestamp_time("InitElementSmallImagesScaledUp (3)");
234
235   // initialize special non-element images from above list
236   for (i = 0; special_graphics[i] > -1; i++)
237     InitElementSmallImagesScaledUp(special_graphics[i]);
238   print_timestamp_time("InitElementSmallImagesScaledUp (4)");
239
240   print_timestamp_done("InitElementSmallImages");
241 }
242
243 static void InitScaledImagesScaledUp(int graphic)
244 {
245   struct GraphicInfo *g = &graphic_info[graphic];
246
247   ScaleImage(graphic, g->scale_up_factor);
248 }
249
250 static void InitScaledImages(void)
251 {
252   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
253   int num_property_mappings = getImageListPropertyMappingSize();
254   int i;
255
256   // scale normal images from static configuration, if not already scaled
257   for (i = 0; i < NUM_IMAGE_FILES; i++)
258     InitScaledImagesScaledUp(i);
259
260   // scale images from dynamic configuration, if not already scaled
261   for (i = 0; i < num_property_mappings; i++)
262     InitScaledImagesScaledUp(property_mapping[i].artwork_index);
263 }
264
265 static void InitBitmapPointers(void)
266 {
267   int num_images = getImageListSize();
268   int i;
269
270   // standard size bitmap may have changed -- update default bitmap pointer
271   for (i = 0; i < num_images; i++)
272     if (graphic_info[i].bitmaps)
273       graphic_info[i].bitmap = graphic_info[i].bitmaps[IMG_BITMAP_STANDARD];
274 }
275
276 void InitImageTextures(void)
277 {
278   int i, j, k;
279
280   FreeAllImageTextures();
281
282   for (i = IMG_GLOBAL_BORDER_FIRST; i <= IMG_GLOBAL_BORDER_LAST; i++)
283     CreateImageTextures(i);
284
285   for (i = 0; i < MAX_NUM_TOONS; i++)
286     CreateImageTextures(IMG_TOON_1 + i);
287
288   for (i = 0; i < NUM_GLOBAL_ANIMS; i++)
289   {
290     for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++)
291     {
292       for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++)
293       {
294         int graphic = global_anim_info[i].graphic[j][k];
295
296         if (graphic == IMG_UNDEFINED)
297           continue;
298
299         CreateImageTextures(graphic);
300       }
301     }
302   }
303 }
304
305 #if 1
306 // !!! FIX THIS (CHANGE TO USING NORMAL ELEMENT GRAPHIC DEFINITIONS) !!!
307 void SetBitmaps_EM(Bitmap **em_bitmap)
308 {
309   em_bitmap[0] = graphic_info[IMG_EMC_OBJECT].bitmap;
310   em_bitmap[1] = graphic_info[IMG_EMC_SPRITE].bitmap;
311 }
312 #endif
313
314 #if 0
315 // !!! FIX THIS (CHANGE TO USING NORMAL ELEMENT GRAPHIC DEFINITIONS) !!!
316 void SetBitmaps_SP(Bitmap **sp_bitmap)
317 {
318   *sp_bitmap = graphic_info[IMG_SP_OBJECTS].bitmap;
319 }
320 #endif
321
322 static int getFontBitmapID(int font_nr)
323 {
324   int special = -1;
325
326   // (special case: do not use special font for GAME_MODE_LOADING)
327   if (game_status >= GAME_MODE_TITLE_INITIAL &&
328       game_status <= GAME_MODE_PSEUDO_PREVIEW)
329     special = game_status;
330   else if (game_status == GAME_MODE_PSEUDO_TYPENAME)
331     special = GFX_SPECIAL_ARG_MAIN;
332
333   if (special != -1)
334     return font_info[font_nr].special_bitmap_id[special];
335   else
336     return font_nr;
337 }
338
339 static int getFontFromToken(char *token)
340 {
341   char *value = getHashEntry(font_token_hash, token);
342
343   if (value != NULL)
344     return atoi(value);
345
346   // if font not found, use reliable default value
347   return FONT_INITIAL_1;
348 }
349
350 static void InitFontGraphicInfo(void)
351 {
352   static struct FontBitmapInfo *font_bitmap_info = NULL;
353   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
354   int num_property_mappings = getImageListPropertyMappingSize();
355   int num_font_bitmaps = NUM_FONTS;
356   int i, j;
357
358   if (graphic_info == NULL)             // still at startup phase
359   {
360     InitFontInfo(font_initial, NUM_INITIAL_FONTS,
361                  getFontBitmapID, getFontFromToken);
362
363     return;
364   }
365
366   // ---------- initialize font graphic definitions ----------
367
368   // always start with reliable default values (normal font graphics)
369   for (i = 0; i < NUM_FONTS; i++)
370     font_info[i].graphic = IMG_FONT_INITIAL_1;
371
372   // initialize normal font/graphic mapping from static configuration
373   for (i = 0; font_to_graphic[i].font_nr > -1; i++)
374   {
375     int font_nr = font_to_graphic[i].font_nr;
376     int special = font_to_graphic[i].special;
377     int graphic = font_to_graphic[i].graphic;
378
379     if (special != -1)
380       continue;
381
382     font_info[font_nr].graphic = graphic;
383   }
384
385   // always start with reliable default values (special font graphics)
386   for (i = 0; i < NUM_FONTS; i++)
387   {
388     for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
389     {
390       font_info[i].special_graphic[j] = font_info[i].graphic;
391       font_info[i].special_bitmap_id[j] = i;
392     }
393   }
394
395   // initialize special font/graphic mapping from static configuration
396   for (i = 0; font_to_graphic[i].font_nr > -1; i++)
397   {
398     int font_nr      = font_to_graphic[i].font_nr;
399     int special      = font_to_graphic[i].special;
400     int graphic      = font_to_graphic[i].graphic;
401     int base_graphic = font2baseimg(font_nr);
402
403     if (IS_SPECIAL_GFX_ARG(special))
404     {
405       boolean base_redefined =
406         getImageListEntryFromImageID(base_graphic)->redefined;
407       boolean special_redefined =
408         getImageListEntryFromImageID(graphic)->redefined;
409       boolean special_cloned = (graphic_info[graphic].clone_from != -1);
410
411       /* if the base font ("font.title_1", for example) has been redefined,
412          but not the special font ("font.title_1.LEVELS", for example), do not
413          use an existing (in this case considered obsolete) special font
414          anymore, but use the automatically determined default font */
415       /* special case: cloned special fonts must be explicitly redefined,
416          but are not automatically redefined by redefining base font */
417       if (base_redefined && !special_redefined && !special_cloned)
418         continue;
419
420       font_info[font_nr].special_graphic[special] = graphic;
421       font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
422       num_font_bitmaps++;
423     }
424   }
425
426   // initialize special font/graphic mapping from dynamic configuration
427   for (i = 0; i < num_property_mappings; i++)
428   {
429     int font_nr = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
430     int special = property_mapping[i].ext3_index;
431     int graphic = property_mapping[i].artwork_index;
432
433     if (font_nr < 0 || font_nr >= NUM_FONTS)
434       continue;
435
436     if (IS_SPECIAL_GFX_ARG(special))
437     {
438       font_info[font_nr].special_graphic[special] = graphic;
439       font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
440       num_font_bitmaps++;
441     }
442   }
443
444   /* correct special font/graphic mapping for cloned fonts for downwards
445      compatibility of PREVIEW fonts -- this is only needed for implicit
446      redefinition of special font by redefined base font, and only if other
447      fonts are cloned from this special font (like in the "Zelda" level set) */
448   for (i = 0; font_to_graphic[i].font_nr > -1; i++)
449   {
450     int font_nr = font_to_graphic[i].font_nr;
451     int special = font_to_graphic[i].special;
452     int graphic = font_to_graphic[i].graphic;
453
454     if (IS_SPECIAL_GFX_ARG(special))
455     {
456       boolean special_redefined =
457         getImageListEntryFromImageID(graphic)->redefined;
458       boolean special_cloned = (graphic_info[graphic].clone_from != -1);
459
460       if (special_cloned && !special_redefined)
461       {
462         int j;
463
464         for (j = 0; font_to_graphic[j].font_nr > -1; j++)
465         {
466           int font_nr2 = font_to_graphic[j].font_nr;
467           int special2 = font_to_graphic[j].special;
468           int graphic2 = font_to_graphic[j].graphic;
469
470           if (IS_SPECIAL_GFX_ARG(special2) &&
471               graphic2 == graphic_info[graphic].clone_from)
472           {
473             font_info[font_nr].special_graphic[special] =
474               font_info[font_nr2].special_graphic[special2];
475             font_info[font_nr].special_bitmap_id[special] =
476               font_info[font_nr2].special_bitmap_id[special2];
477           }
478         }
479       }
480     }
481   }
482
483   // reset non-redefined ".active" font graphics if normal font is redefined
484   // (this different treatment is needed because normal and active fonts are
485   // independently defined ("active" is not a property of font definitions!)
486   for (i = 0; i < NUM_FONTS; i++)
487   {
488     int font_nr_base = i;
489     int font_nr_active = FONT_ACTIVE(font_nr_base);
490
491     // check only those fonts with exist as normal and ".active" variant
492     if (font_nr_base != font_nr_active)
493     {
494       int base_graphic = font_info[font_nr_base].graphic;
495       int active_graphic = font_info[font_nr_active].graphic;
496       boolean base_redefined =
497         getImageListEntryFromImageID(base_graphic)->redefined;
498       boolean active_redefined =
499         getImageListEntryFromImageID(active_graphic)->redefined;
500
501       /* if the base font ("font.menu_1", for example) has been redefined,
502          but not the active font ("font.menu_1.active", for example), do not
503          use an existing (in this case considered obsolete) active font
504          anymore, but use the automatically determined default font */
505       if (base_redefined && !active_redefined)
506         font_info[font_nr_active].graphic = base_graphic;
507
508       // now also check each "special" font (which may be the same as above)
509       for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
510       {
511         int base_graphic = font_info[font_nr_base].special_graphic[j];
512         int active_graphic = font_info[font_nr_active].special_graphic[j];
513         boolean base_redefined =
514           getImageListEntryFromImageID(base_graphic)->redefined;
515         boolean active_redefined =
516           getImageListEntryFromImageID(active_graphic)->redefined;
517
518         // same as above, but check special graphic definitions, for example:
519         // redefined "font.menu_1.MAIN" invalidates "font.menu_1.active.MAIN"
520         if (base_redefined && !active_redefined)
521         {
522           font_info[font_nr_active].special_graphic[j] =
523             font_info[font_nr_base].special_graphic[j];
524           font_info[font_nr_active].special_bitmap_id[j] =
525             font_info[font_nr_base].special_bitmap_id[j];
526         }
527       }
528     }
529   }
530
531   // ---------- initialize font bitmap array ----------
532
533   if (font_bitmap_info != NULL)
534     FreeFontInfo(font_bitmap_info);
535
536   font_bitmap_info =
537     checked_calloc(num_font_bitmaps * sizeof(struct FontBitmapInfo));
538
539   // ---------- initialize font bitmap definitions ----------
540
541   for (i = 0; i < NUM_FONTS; i++)
542   {
543     if (i < NUM_INITIAL_FONTS)
544     {
545       font_bitmap_info[i] = font_initial[i];
546       continue;
547     }
548
549     for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
550     {
551       int font_bitmap_id = font_info[i].special_bitmap_id[j];
552       int graphic = font_info[i].special_graphic[j];
553
554       // set 'graphic_info' for font entries, if uninitialized (guessed)
555       if (graphic_info[graphic].anim_frames < MIN_NUM_CHARS_PER_FONT)
556       {
557         graphic_info[graphic].anim_frames = DEFAULT_NUM_CHARS_PER_FONT;
558         graphic_info[graphic].anim_frames_per_line = DEFAULT_NUM_CHARS_PER_LINE;
559       }
560
561       // copy font relevant information from graphics information
562       font_bitmap_info[font_bitmap_id].bitmap = graphic_info[graphic].bitmap;
563       font_bitmap_info[font_bitmap_id].src_x  = graphic_info[graphic].src_x;
564       font_bitmap_info[font_bitmap_id].src_y  = graphic_info[graphic].src_y;
565       font_bitmap_info[font_bitmap_id].width  = graphic_info[graphic].width;
566       font_bitmap_info[font_bitmap_id].height = graphic_info[graphic].height;
567
568       font_bitmap_info[font_bitmap_id].offset_x =
569         graphic_info[graphic].offset_x;
570       font_bitmap_info[font_bitmap_id].offset_y =
571         graphic_info[graphic].offset_y;
572
573       font_bitmap_info[font_bitmap_id].draw_xoffset =
574         graphic_info[graphic].draw_xoffset;
575       font_bitmap_info[font_bitmap_id].draw_yoffset =
576         graphic_info[graphic].draw_yoffset;
577
578       font_bitmap_info[font_bitmap_id].num_chars =
579         graphic_info[graphic].anim_frames;
580       font_bitmap_info[font_bitmap_id].num_chars_per_line =
581         graphic_info[graphic].anim_frames_per_line;
582     }
583   }
584
585   InitFontInfo(font_bitmap_info, num_font_bitmaps,
586                getFontBitmapID, getFontFromToken);
587 }
588
589 static void InitGlobalAnimGraphicInfo(void)
590 {
591   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
592   int num_property_mappings = getImageListPropertyMappingSize();
593   int i, j, k;
594
595   if (graphic_info == NULL)             // still at startup phase
596     return;
597
598   // always start with reliable default values (no global animations)
599   for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS; i++)
600     for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++)
601       for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++)
602         global_anim_info[i].graphic[j][k] = IMG_UNDEFINED;
603
604   // initialize global animation definitions from static configuration
605   for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS; i++)
606   {
607     int j = GLOBAL_ANIM_ID_PART_BASE;
608     int k = GFX_SPECIAL_ARG_DEFAULT;
609
610     global_anim_info[i].graphic[j][k] = IMG_GFX_GLOBAL_ANIM_1 + i;
611   }
612
613   // initialize global animation definitions from dynamic configuration
614   for (i = 0; i < num_property_mappings; i++)
615   {
616     int anim_nr = property_mapping[i].base_index - MAX_NUM_ELEMENTS - NUM_FONTS;
617     int part_nr = property_mapping[i].ext1_index - ACTION_PART_1;
618     int special = property_mapping[i].ext3_index;
619     int graphic = property_mapping[i].artwork_index;
620
621     if (anim_nr < 0 || anim_nr >= NUM_GLOBAL_ANIM_TOKENS)
622       continue;
623
624     // set animation part to base part, if not specified
625     if (!IS_GLOBAL_ANIM_PART(part_nr))
626       part_nr = GLOBAL_ANIM_ID_PART_BASE;
627
628     // set animation screen to default, if not specified
629     if (!IS_SPECIAL_GFX_ARG(special))
630       special = GFX_SPECIAL_ARG_DEFAULT;
631
632     global_anim_info[anim_nr].graphic[part_nr][special] = graphic;
633
634     // fix default value for ".draw_masked" (for backward compatibility)
635     struct GraphicInfo *g = &graphic_info[graphic];
636     struct FileInfo *image = getImageListEntryFromImageID(graphic);
637     char **parameter_raw = image->parameter;
638     int p = GFX_ARG_DRAW_MASKED;
639     int draw_masked = get_graphic_parameter_value(parameter_raw[p],
640                                                   image_config_suffix[p].token,
641                                                   image_config_suffix[p].type);
642
643     // if ".draw_masked" parameter is undefined, use default value "TRUE"
644     if (draw_masked == ARG_UNDEFINED_VALUE)
645       g->draw_masked = TRUE;
646   }
647
648 #if 0
649   printf("::: InitGlobalAnimGraphicInfo\n");
650
651   for (i = 0; i < NUM_GLOBAL_ANIMS; i++)
652     for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++)
653       for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++)
654         if (global_anim_info[i].graphic[j][k] != IMG_UNDEFINED &&
655             graphic_info[global_anim_info[i].graphic[j][k]].bitmap != NULL)
656           printf("::: - anim %d, part %d, mode %d => %d\n",
657                  i, j, k, global_anim_info[i].graphic[j][k]);
658 #endif
659 }
660
661 static void InitGlobalAnimSoundInfo(void)
662 {
663   struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
664   int num_property_mappings = getSoundListPropertyMappingSize();
665   int i, j, k;
666
667   // always start with reliable default values (no global animation sounds)
668   for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS; i++)
669     for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++)
670       for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++)
671         global_anim_info[i].sound[j][k] = SND_UNDEFINED;
672
673   // initialize global animation sound definitions from dynamic configuration
674   for (i = 0; i < num_property_mappings; i++)
675   {
676     int anim_nr = property_mapping[i].base_index - 2 * MAX_NUM_ELEMENTS;
677     int part_nr = property_mapping[i].ext1_index - ACTION_PART_1;
678     int special = property_mapping[i].ext3_index;
679     int sound   = property_mapping[i].artwork_index;
680
681     // sound uses control definition; map it to position of graphic (artwork)
682     anim_nr -= GLOBAL_ANIM_ID_CONTROL_FIRST;
683
684     if (anim_nr < 0 || anim_nr >= NUM_GLOBAL_ANIM_TOKENS)
685       continue;
686
687     // set animation part to base part, if not specified
688     if (!IS_GLOBAL_ANIM_PART(part_nr))
689       part_nr = GLOBAL_ANIM_ID_PART_BASE;
690
691     // set animation screen to default, if not specified
692     if (!IS_SPECIAL_GFX_ARG(special))
693       special = GFX_SPECIAL_ARG_DEFAULT;
694
695     global_anim_info[anim_nr].sound[part_nr][special] = sound;
696   }
697
698 #if 0
699   printf("::: InitGlobalAnimSoundInfo\n");
700
701   for (i = 0; i < NUM_GLOBAL_ANIMS; i++)
702     for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++)
703       for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++)
704         if (global_anim_info[i].sound[j][k] != SND_UNDEFINED)
705           printf("::: - anim %d, part %d, mode %d => %d\n",
706                  i, j, k, global_anim_info[i].sound[j][k]);
707 #endif
708 }
709
710 static void InitGlobalAnimMusicInfo(void)
711 {
712   struct PropertyMapping *property_mapping = getMusicListPropertyMapping();
713   int num_property_mappings = getMusicListPropertyMappingSize();
714   int i, j, k;
715
716   // always start with reliable default values (no global animation music)
717   for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS; i++)
718     for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++)
719       for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++)
720         global_anim_info[i].music[j][k] = MUS_UNDEFINED;
721
722   // initialize global animation music definitions from dynamic configuration
723   for (i = 0; i < num_property_mappings; i++)
724   {
725     int anim_nr = property_mapping[i].base_index - NUM_MUSIC_PREFIXES;
726     int part_nr = property_mapping[i].ext1_index - ACTION_PART_1;
727     int special = property_mapping[i].ext2_index;
728     int music   = property_mapping[i].artwork_index;
729
730     // music uses control definition; map it to position of graphic (artwork)
731     anim_nr -= GLOBAL_ANIM_ID_CONTROL_FIRST;
732
733     if (anim_nr < 0 || anim_nr >= NUM_GLOBAL_ANIM_TOKENS)
734       continue;
735
736     // set animation part to base part, if not specified
737     if (!IS_GLOBAL_ANIM_PART(part_nr))
738       part_nr = GLOBAL_ANIM_ID_PART_BASE;
739
740     // set animation screen to default, if not specified
741     if (!IS_SPECIAL_GFX_ARG(special))
742       special = GFX_SPECIAL_ARG_DEFAULT;
743
744     global_anim_info[anim_nr].music[part_nr][special] = music;
745   }
746
747 #if 0
748   printf("::: InitGlobalAnimMusicInfo\n");
749
750   for (i = 0; i < NUM_GLOBAL_ANIMS; i++)
751     for (j = 0; j < NUM_GLOBAL_ANIM_PARTS_ALL; j++)
752       for (k = 0; k < NUM_SPECIAL_GFX_ARGS; k++)
753         if (global_anim_info[i].music[j][k] != MUS_UNDEFINED)
754           printf("::: - anim %d, part %d, mode %d => %d\n",
755                  i, j, k, global_anim_info[i].music[j][k]);
756 #endif
757 }
758
759 static void InitElementGraphicInfo(void)
760 {
761   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
762   int num_property_mappings = getImageListPropertyMappingSize();
763   int i, act, dir;
764
765   if (graphic_info == NULL)             // still at startup phase
766     return;
767
768   // set values to -1 to identify later as "uninitialized" values
769   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
770   {
771     for (act = 0; act < NUM_ACTIONS; act++)
772     {
773       element_info[i].graphic[act] = -1;
774       element_info[i].crumbled[act] = -1;
775
776       for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
777       {
778         element_info[i].direction_graphic[act][dir] = -1;
779         element_info[i].direction_crumbled[act][dir] = -1;
780       }
781     }
782   }
783
784   UPDATE_BUSY_STATE();
785
786   // initialize normal element/graphic mapping from static configuration
787   for (i = 0; element_to_graphic[i].element > -1; i++)
788   {
789     int element      = element_to_graphic[i].element;
790     int action       = element_to_graphic[i].action;
791     int direction    = element_to_graphic[i].direction;
792     boolean crumbled = element_to_graphic[i].crumbled;
793     int graphic      = element_to_graphic[i].graphic;
794     int base_graphic = el2baseimg(element);
795
796     if (graphic_info[graphic].bitmap == NULL)
797       continue;
798
799     if ((action > -1 || direction > -1 || crumbled == TRUE) &&
800         base_graphic != -1)
801     {
802       boolean base_redefined =
803         getImageListEntryFromImageID(base_graphic)->redefined;
804       boolean act_dir_redefined =
805         getImageListEntryFromImageID(graphic)->redefined;
806
807       /* if the base graphic ("emerald", for example) has been redefined,
808          but not the action graphic ("emerald.falling", for example), do not
809          use an existing (in this case considered obsolete) action graphic
810          anymore, but use the automatically determined default graphic */
811       if (base_redefined && !act_dir_redefined)
812         continue;
813     }
814
815     if (action < 0)
816       action = ACTION_DEFAULT;
817
818     if (crumbled)
819     {
820       if (direction > -1)
821         element_info[element].direction_crumbled[action][direction] = graphic;
822       else
823         element_info[element].crumbled[action] = graphic;
824     }
825     else
826     {
827       if (direction > -1)
828         element_info[element].direction_graphic[action][direction] = graphic;
829       else
830         element_info[element].graphic[action] = graphic;
831     }
832   }
833
834   // initialize normal element/graphic mapping from dynamic configuration
835   for (i = 0; i < num_property_mappings; i++)
836   {
837     int element   = property_mapping[i].base_index;
838     int action    = property_mapping[i].ext1_index;
839     int direction = property_mapping[i].ext2_index;
840     int special   = property_mapping[i].ext3_index;
841     int graphic   = property_mapping[i].artwork_index;
842     boolean crumbled = FALSE;
843
844     if (special == GFX_SPECIAL_ARG_CRUMBLED)
845     {
846       special = -1;
847       crumbled = TRUE;
848     }
849
850     if (graphic_info[graphic].bitmap == NULL)
851       continue;
852
853     if (element >= MAX_NUM_ELEMENTS || special != -1)
854       continue;
855
856     if (action < 0)
857       action = ACTION_DEFAULT;
858
859     if (crumbled)
860     {
861       if (direction < 0)
862         for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
863           element_info[element].direction_crumbled[action][dir] = -1;
864
865       if (direction > -1)
866         element_info[element].direction_crumbled[action][direction] = graphic;
867       else
868         element_info[element].crumbled[action] = graphic;
869     }
870     else
871     {
872       if (direction < 0)
873         for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
874           element_info[element].direction_graphic[action][dir] = -1;
875
876       if (direction > -1)
877         element_info[element].direction_graphic[action][direction] = graphic;
878       else
879         element_info[element].graphic[action] = graphic;
880     }
881   }
882
883   // now copy all graphics that are defined to be cloned from other graphics
884   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
885   {
886     int graphic = element_info[i].graphic[ACTION_DEFAULT];
887     int crumbled_like, diggable_like;
888
889     if (graphic == -1)
890       continue;
891
892     crumbled_like = graphic_info[graphic].crumbled_like;
893     diggable_like = graphic_info[graphic].diggable_like;
894
895     if (crumbled_like != -1 && element_info[i].crumbled[ACTION_DEFAULT] == -1)
896     {
897       for (act = 0; act < NUM_ACTIONS; act++)
898         element_info[i].crumbled[act] =
899           element_info[crumbled_like].crumbled[act];
900       for (act = 0; act < NUM_ACTIONS; act++)
901         for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
902           element_info[i].direction_crumbled[act][dir] =
903             element_info[crumbled_like].direction_crumbled[act][dir];
904     }
905
906     if (diggable_like != -1 && element_info[i].graphic[ACTION_DIGGING] == -1)
907     {
908       element_info[i].graphic[ACTION_DIGGING] =
909         element_info[diggable_like].graphic[ACTION_DIGGING];
910       for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
911         element_info[i].direction_graphic[ACTION_DIGGING][dir] =
912           element_info[diggable_like].direction_graphic[ACTION_DIGGING][dir];
913     }
914   }
915
916   // set hardcoded definitions for some runtime elements without graphic
917   element_info[EL_AMOEBA_TO_DIAMOND].graphic[ACTION_DEFAULT] = IMG_AMOEBA_DEAD;
918
919   // set hardcoded definitions for some internal elements without graphic
920   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
921   {
922     if (IS_EDITOR_CASCADE_INACTIVE(i))
923       element_info[i].graphic[ACTION_DEFAULT] = IMG_EDITOR_CASCADE_LIST;
924     else if (IS_EDITOR_CASCADE_ACTIVE(i))
925       element_info[i].graphic[ACTION_DEFAULT] = IMG_EDITOR_CASCADE_LIST_ACTIVE;
926   }
927
928   // now set all undefined/invalid graphics to -1 to set to default after it
929   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
930   {
931     for (act = 0; act < NUM_ACTIONS; act++)
932     {
933       int graphic;
934
935       graphic = element_info[i].graphic[act];
936       if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
937         element_info[i].graphic[act] = -1;
938
939       graphic = element_info[i].crumbled[act];
940       if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
941         element_info[i].crumbled[act] = -1;
942
943       for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
944       {
945         graphic = element_info[i].direction_graphic[act][dir];
946         if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
947           element_info[i].direction_graphic[act][dir] = -1;
948
949         graphic = element_info[i].direction_crumbled[act][dir];
950         if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
951           element_info[i].direction_crumbled[act][dir] = -1;
952       }
953     }
954   }
955
956   UPDATE_BUSY_STATE();
957
958   // adjust graphics with 2nd tile for movement according to direction
959   // (do this before correcting '-1' values to minimize calculations)
960   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
961   {
962     for (act = 0; act < NUM_ACTIONS; act++)
963     {
964       for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
965       {
966         int graphic = element_info[i].direction_graphic[act][dir];
967         int move_dir = (act == ACTION_FALLING ? MV_BIT_DOWN : dir);
968
969         if (act == ACTION_FALLING)      // special case
970           graphic = element_info[i].graphic[act];
971
972         if (graphic != -1 &&
973             graphic_info[graphic].double_movement &&
974             graphic_info[graphic].swap_double_tiles != 0)
975         {
976           struct GraphicInfo *g = &graphic_info[graphic];
977           int src_x_front = g->src_x;
978           int src_y_front = g->src_y;
979           int src_x_back = g->src_x + g->offset2_x;
980           int src_y_back = g->src_y + g->offset2_y;
981           boolean frames_are_ordered_diagonally = (g->offset_x != 0 &&
982                                                    g->offset_y != 0);
983           boolean front_is_left_or_upper = (src_x_front < src_x_back ||
984                                             src_y_front < src_y_back);
985           boolean swap_movement_tiles_always = (g->swap_double_tiles == 1);
986           boolean swap_movement_tiles_autodetected =
987             (!frames_are_ordered_diagonally &&
988              ((move_dir == MV_BIT_LEFT  && !front_is_left_or_upper) ||
989               (move_dir == MV_BIT_UP    && !front_is_left_or_upper) ||
990               (move_dir == MV_BIT_RIGHT &&  front_is_left_or_upper) ||
991               (move_dir == MV_BIT_DOWN  &&  front_is_left_or_upper)));
992
993           // swap frontside and backside graphic tile coordinates, if needed
994           if (swap_movement_tiles_always || swap_movement_tiles_autodetected)
995           {
996             // get current (wrong) backside tile coordinates
997             getGraphicSourceXY(graphic, 0, &src_x_back, &src_y_back, TRUE);
998
999             // set frontside tile coordinates to backside tile coordinates
1000             g->src_x = src_x_back;
1001             g->src_y = src_y_back;
1002
1003             // invert tile offset to point to new backside tile coordinates
1004             g->offset2_x *= -1;
1005             g->offset2_y *= -1;
1006
1007             // do not swap front and backside tiles again after correction
1008             g->swap_double_tiles = 0;
1009           }
1010         }
1011       }
1012     }
1013   }
1014
1015   UPDATE_BUSY_STATE();
1016
1017   // now set all '-1' values to element specific default values
1018   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1019   {
1020     int default_graphic = element_info[i].graphic[ACTION_DEFAULT];
1021     int default_crumbled = element_info[i].crumbled[ACTION_DEFAULT];
1022     int default_direction_graphic[NUM_DIRECTIONS_FULL];
1023     int default_direction_crumbled[NUM_DIRECTIONS_FULL];
1024
1025     if (default_graphic == -1)
1026       default_graphic = IMG_UNKNOWN;
1027
1028     if (default_crumbled == -1)
1029       default_crumbled = default_graphic;
1030
1031     for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
1032     {
1033       default_direction_graphic[dir] =
1034         element_info[i].direction_graphic[ACTION_DEFAULT][dir];
1035       default_direction_crumbled[dir] =
1036         element_info[i].direction_crumbled[ACTION_DEFAULT][dir];
1037
1038       if (default_direction_graphic[dir] == -1)
1039         default_direction_graphic[dir] = default_graphic;
1040
1041       if (default_direction_crumbled[dir] == -1)
1042         default_direction_crumbled[dir] = default_direction_graphic[dir];
1043     }
1044
1045     for (act = 0; act < NUM_ACTIONS; act++)
1046     {
1047       boolean act_remove = ((IS_DIGGABLE(i)    && act == ACTION_DIGGING)  ||
1048                             (IS_SNAPPABLE(i)   && act == ACTION_SNAPPING) ||
1049                             (IS_COLLECTIBLE(i) && act == ACTION_COLLECTING));
1050       boolean act_turning = (act == ACTION_TURNING_FROM_LEFT ||
1051                              act == ACTION_TURNING_FROM_RIGHT ||
1052                              act == ACTION_TURNING_FROM_UP ||
1053                              act == ACTION_TURNING_FROM_DOWN);
1054
1055       // generic default action graphic (defined by "[default]" directive)
1056       int default_action_graphic = element_info[EL_DEFAULT].graphic[act];
1057       int default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
1058       int default_remove_graphic = IMG_EMPTY;
1059
1060       if (act_remove && default_action_graphic != -1)
1061         default_remove_graphic = default_action_graphic;
1062
1063       // look for special default action graphic (classic game specific)
1064       if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].graphic[act] != -1)
1065         default_action_graphic = element_info[EL_BD_DEFAULT].graphic[act];
1066       if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].graphic[act] != -1)
1067         default_action_graphic = element_info[EL_SP_DEFAULT].graphic[act];
1068       if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].graphic[act] != -1)
1069         default_action_graphic = element_info[EL_SB_DEFAULT].graphic[act];
1070       if (IS_MM_ELEMENT(i) && element_info[EL_MM_DEFAULT].graphic[act] != -1)
1071         default_action_graphic = element_info[EL_MM_DEFAULT].graphic[act];
1072
1073       if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].crumbled[act] != -1)
1074         default_action_crumbled = element_info[EL_BD_DEFAULT].crumbled[act];
1075       if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].crumbled[act] != -1)
1076         default_action_crumbled = element_info[EL_SP_DEFAULT].crumbled[act];
1077       if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].crumbled[act] != -1)
1078         default_action_crumbled = element_info[EL_SB_DEFAULT].crumbled[act];
1079       if (IS_MM_ELEMENT(i) && element_info[EL_MM_DEFAULT].crumbled[act] != -1)
1080         default_action_crumbled = element_info[EL_MM_DEFAULT].crumbled[act];
1081
1082       // !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!!
1083       // !!! make this better !!!
1084       if (i == EL_EMPTY_SPACE)
1085       {
1086         default_action_graphic = element_info[EL_DEFAULT].graphic[act];
1087         default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
1088       }
1089
1090       if (default_action_graphic == -1)
1091         default_action_graphic = default_graphic;
1092
1093       if (default_action_crumbled == -1)
1094         default_action_crumbled = default_action_graphic;
1095
1096       for (dir = 0; dir < NUM_DIRECTIONS_FULL; dir++)
1097       {
1098         // use action graphic as the default direction graphic, if undefined
1099         int default_action_direction_graphic = element_info[i].graphic[act];
1100         int default_action_direction_crumbled = element_info[i].crumbled[act];
1101
1102         // no graphic for current action -- use default direction graphic
1103         if (default_action_direction_graphic == -1)
1104           default_action_direction_graphic =
1105             (act_remove ? default_remove_graphic :
1106              act_turning ?
1107              element_info[i].direction_graphic[ACTION_TURNING][dir] :
1108              default_action_graphic != default_graphic ?
1109              default_action_graphic :
1110              default_direction_graphic[dir]);
1111
1112         if (element_info[i].direction_graphic[act][dir] == -1)
1113           element_info[i].direction_graphic[act][dir] =
1114             default_action_direction_graphic;
1115
1116         if (default_action_direction_crumbled == -1)
1117           default_action_direction_crumbled =
1118             element_info[i].direction_graphic[act][dir];
1119
1120         if (element_info[i].direction_crumbled[act][dir] == -1)
1121           element_info[i].direction_crumbled[act][dir] =
1122             default_action_direction_crumbled;
1123       }
1124
1125       // no graphic for this specific action -- use default action graphic
1126       if (element_info[i].graphic[act] == -1)
1127         element_info[i].graphic[act] =
1128           (act_remove ? default_remove_graphic :
1129            act_turning ? element_info[i].graphic[ACTION_TURNING] :
1130            default_action_graphic);
1131
1132       if (element_info[i].crumbled[act] == -1)
1133         element_info[i].crumbled[act] = element_info[i].graphic[act];
1134     }
1135   }
1136
1137   UPDATE_BUSY_STATE();
1138 }
1139
1140 static void InitElementSpecialGraphicInfo(void)
1141 {
1142   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
1143   int num_property_mappings = getImageListPropertyMappingSize();
1144   int i, j;
1145
1146   // always start with reliable default values
1147   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1148     for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
1149       element_info[i].special_graphic[j] =
1150         element_info[i].graphic[ACTION_DEFAULT];
1151
1152   // initialize special element/graphic mapping from static configuration
1153   for (i = 0; element_to_special_graphic[i].element > -1; i++)
1154   {
1155     int element = element_to_special_graphic[i].element;
1156     int special = element_to_special_graphic[i].special;
1157     int graphic = element_to_special_graphic[i].graphic;
1158     int base_graphic = el2baseimg(element);
1159     boolean base_redefined =
1160       getImageListEntryFromImageID(base_graphic)->redefined;
1161     boolean special_redefined =
1162       getImageListEntryFromImageID(graphic)->redefined;
1163
1164     /* if the base graphic ("emerald", for example) has been redefined,
1165        but not the special graphic ("emerald.EDITOR", for example), do not
1166        use an existing (in this case considered obsolete) special graphic
1167        anymore, but use the automatically created (down-scaled) graphic */
1168     if (base_redefined && !special_redefined)
1169       continue;
1170
1171     element_info[element].special_graphic[special] = graphic;
1172   }
1173
1174   // initialize special element/graphic mapping from dynamic configuration
1175   for (i = 0; i < num_property_mappings; i++)
1176   {
1177     int element   = property_mapping[i].base_index;
1178     int action    = property_mapping[i].ext1_index;
1179     int direction = property_mapping[i].ext2_index;
1180     int special   = property_mapping[i].ext3_index;
1181     int graphic   = property_mapping[i].artwork_index;
1182
1183     // for action ".active", replace element with active element, if exists
1184     if (action == ACTION_ACTIVE && element != ELEMENT_ACTIVE(element))
1185     {
1186       element = ELEMENT_ACTIVE(element);
1187       action = -1;
1188     }
1189
1190     if (element >= MAX_NUM_ELEMENTS)
1191       continue;
1192
1193     // do not change special graphic if action or direction was specified
1194     if (action != -1 || direction != -1)
1195       continue;
1196
1197     if (IS_SPECIAL_GFX_ARG(special))
1198       element_info[element].special_graphic[special] = graphic;
1199   }
1200
1201   // now set all undefined/invalid graphics to default
1202   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1203     for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
1204       if (graphic_info[element_info[i].special_graphic[j]].bitmap == NULL)
1205         element_info[i].special_graphic[j] =
1206           element_info[i].graphic[ACTION_DEFAULT];
1207 }
1208
1209 static int get_graphic_parameter_value(char *value_raw, char *suffix, int type)
1210 {
1211   if (type != TYPE_ELEMENT && type != TYPE_GRAPHIC)
1212     return get_parameter_value(value_raw, suffix, type);
1213
1214   if (strEqual(value_raw, ARG_UNDEFINED))
1215     return ARG_UNDEFINED_VALUE;
1216
1217   if (type == TYPE_ELEMENT)
1218   {
1219     char *value = getHashEntry(element_token_hash, value_raw);
1220
1221     if (value == NULL)
1222     {
1223       Error(ERR_INFO_LINE, "-");
1224       Error(ERR_INFO, "warning: error found in config file:");
1225       Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
1226       Error(ERR_INFO, "error: invalid element token '%s'", value_raw);
1227       Error(ERR_INFO, "custom graphic rejected for this element/action");
1228       Error(ERR_INFO, "fallback done to undefined element for this graphic");
1229       Error(ERR_INFO_LINE, "-");
1230     }
1231
1232     return (value != NULL ? atoi(value) : EL_UNDEFINED);
1233   }
1234   else if (type == TYPE_GRAPHIC)
1235   {
1236     char *value = getHashEntry(graphic_token_hash, value_raw);
1237     int fallback_graphic = IMG_CHAR_EXCLAM;
1238
1239     if (value == NULL)
1240     {
1241       Error(ERR_INFO_LINE, "-");
1242       Error(ERR_INFO, "warning: error found in config file:");
1243       Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
1244       Error(ERR_INFO, "error: invalid graphic token '%s'", value_raw);
1245       Error(ERR_INFO, "custom graphic rejected for this element/action");
1246       Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic");
1247       Error(ERR_INFO_LINE, "-");
1248     }
1249
1250     return (value != NULL ? atoi(value) : fallback_graphic);
1251   }
1252
1253   return -1;
1254 }
1255
1256 static int get_scaled_graphic_width(int graphic)
1257 {
1258   int original_width = getOriginalImageWidthFromImageID(graphic);
1259   int scale_up_factor = graphic_info[graphic].scale_up_factor;
1260
1261   return original_width * scale_up_factor;
1262 }
1263
1264 static int get_scaled_graphic_height(int graphic)
1265 {
1266   int original_height = getOriginalImageHeightFromImageID(graphic);
1267   int scale_up_factor = graphic_info[graphic].scale_up_factor;
1268
1269   return original_height * scale_up_factor;
1270 }
1271
1272 static void set_graphic_parameters_ext(int graphic, int *parameter,
1273                                        Bitmap **src_bitmaps)
1274 {
1275   struct GraphicInfo *g = &graphic_info[graphic];
1276   Bitmap *src_bitmap = (src_bitmaps ? src_bitmaps[IMG_BITMAP_STANDARD] : NULL);
1277   int anim_frames_per_row = 1, anim_frames_per_col = 1;
1278   int anim_frames_per_line = 1;
1279
1280   // always start with reliable default values
1281   g->src_image_width = 0;
1282   g->src_image_height = 0;
1283   g->src_x = 0;
1284   g->src_y = 0;
1285   g->width  = TILEX;                    // default for element graphics
1286   g->height = TILEY;                    // default for element graphics
1287   g->offset_x = 0;                      // one or both of these values ...
1288   g->offset_y = 0;                      // ... will be corrected later
1289   g->offset2_x = 0;                     // one or both of these values ...
1290   g->offset2_y = 0;                     // ... will be corrected later
1291   g->swap_double_tiles = -1;            // auto-detect tile swapping
1292   g->crumbled_like = -1;                // do not use clone element
1293   g->diggable_like = -1;                // do not use clone element
1294   g->border_size = TILEX / 8;           // "CRUMBLED" border size
1295   g->scale_up_factor = 1;               // default: no scaling up
1296   g->tile_size = TILESIZE;              // default: standard tile size
1297   g->clone_from = -1;                   // do not use clone graphic
1298   g->init_delay_fixed = 0;
1299   g->init_delay_random = 0;
1300   g->anim_delay_fixed = 0;
1301   g->anim_delay_random = 0;
1302   g->post_delay_fixed = 0;
1303   g->post_delay_random = 0;
1304   g->init_event = ANIM_EVENT_DEFAULT;
1305   g->anim_event = ANIM_EVENT_DEFAULT;
1306   g->init_event_action = -1;
1307   g->anim_event_action = -1;
1308   g->draw_masked = FALSE;
1309   g->draw_order = 0;
1310   g->fade_mode = FADE_MODE_DEFAULT;
1311   g->fade_delay = -1;
1312   g->post_delay = -1;
1313   g->auto_delay = -1;
1314   g->align = ALIGN_CENTER;              // default for title screens
1315   g->valign = VALIGN_MIDDLE;            // default for title screens
1316   g->sort_priority = 0;                 // default for title screens
1317   g->class = 0;
1318   g->style = STYLE_DEFAULT;
1319
1320   g->bitmaps = src_bitmaps;
1321   g->bitmap = src_bitmap;
1322
1323   // optional zoom factor for scaling up the image to a larger size
1324   if (parameter[GFX_ARG_SCALE_UP_FACTOR] != ARG_UNDEFINED_VALUE)
1325     g->scale_up_factor = parameter[GFX_ARG_SCALE_UP_FACTOR];
1326   if (g->scale_up_factor < 1)
1327     g->scale_up_factor = 1;             // no scaling
1328
1329   // optional tile size for using non-standard image size
1330   if (parameter[GFX_ARG_TILE_SIZE] != ARG_UNDEFINED_VALUE)
1331   {
1332     g->tile_size = parameter[GFX_ARG_TILE_SIZE];
1333
1334 #if 0
1335     // CHECK: should tile sizes less than standard tile size be allowed?
1336     if (g->tile_size < TILESIZE)
1337       g->tile_size = TILESIZE;          // standard tile size
1338 #endif
1339
1340     // when setting tile size, also set width and height accordingly
1341     g->width  = g->tile_size;
1342     g->height = g->tile_size;
1343   }
1344
1345   if (g->use_image_size)
1346   {
1347     // set new default bitmap size (with scaling, but without small images)
1348     g->width  = get_scaled_graphic_width(graphic);
1349     g->height = get_scaled_graphic_height(graphic);
1350   }
1351
1352   // optional width and height of each animation frame
1353   if (parameter[GFX_ARG_WIDTH] != ARG_UNDEFINED_VALUE)
1354     g->width = parameter[GFX_ARG_WIDTH];
1355   if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE)
1356     g->height = parameter[GFX_ARG_HEIGHT];
1357
1358   // optional x and y tile position of animation frame sequence
1359   if (parameter[GFX_ARG_XPOS] != ARG_UNDEFINED_VALUE)
1360     g->src_x = parameter[GFX_ARG_XPOS] * g->width;
1361   if (parameter[GFX_ARG_YPOS] != ARG_UNDEFINED_VALUE)
1362     g->src_y = parameter[GFX_ARG_YPOS] * g->height;
1363
1364   // optional x and y pixel position of animation frame sequence
1365   if (parameter[GFX_ARG_X] != ARG_UNDEFINED_VALUE)
1366     g->src_x = parameter[GFX_ARG_X];
1367   if (parameter[GFX_ARG_Y] != ARG_UNDEFINED_VALUE)
1368     g->src_y = parameter[GFX_ARG_Y];
1369
1370   if (src_bitmap)
1371   {
1372     if (g->width <= 0)
1373     {
1374       Error(ERR_INFO_LINE, "-");
1375       Error(ERR_WARN, "invalid value %d for '%s.width' (fallback done to %d)",
1376             g->width, getTokenFromImageID(graphic), TILEX);
1377       Error(ERR_INFO_LINE, "-");
1378
1379       g->width = TILEX;         // will be checked to be inside bitmap later
1380     }
1381
1382     if (g->height <= 0)
1383     {
1384       Error(ERR_INFO_LINE, "-");
1385       Error(ERR_WARN, "invalid value %d for '%s.height' (fallback done to %d)",
1386             g->height, getTokenFromImageID(graphic), TILEY);
1387       Error(ERR_INFO_LINE, "-");
1388
1389       g->height = TILEY;        // will be checked to be inside bitmap later
1390     }
1391   }
1392
1393   if (src_bitmap)
1394   {
1395     // get final bitmap size (with scaling, but without small images)
1396     int src_image_width  = get_scaled_graphic_width(graphic);
1397     int src_image_height = get_scaled_graphic_height(graphic);
1398
1399     if (src_image_width == 0 || src_image_height == 0)
1400     {
1401       // only happens when loaded outside artwork system (like "global.busy")
1402       src_image_width  = src_bitmap->width;
1403       src_image_height = src_bitmap->height;
1404     }
1405
1406     if (parameter[GFX_ARG_TILE_SIZE] != ARG_UNDEFINED_VALUE)
1407     {
1408       anim_frames_per_row = MAX(1, src_image_width  / g->tile_size);
1409       anim_frames_per_col = MAX(1, src_image_height / g->tile_size);
1410     }
1411     else
1412     {
1413       anim_frames_per_row = MAX(1, src_image_width  / g->width);
1414       anim_frames_per_col = MAX(1, src_image_height / g->height);
1415     }
1416
1417     g->src_image_width  = src_image_width;
1418     g->src_image_height = src_image_height;
1419   }
1420
1421   // correct x or y offset dependent of vertical or horizontal frame order
1422   if (parameter[GFX_ARG_VERTICAL])      // frames are ordered vertically
1423   {
1424     g->offset_y = (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
1425                    parameter[GFX_ARG_OFFSET] : g->height);
1426     anim_frames_per_line = anim_frames_per_col;
1427   }
1428   else                                  // frames are ordered horizontally
1429   {
1430     g->offset_x = (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
1431                    parameter[GFX_ARG_OFFSET] : g->width);
1432     anim_frames_per_line = anim_frames_per_row;
1433   }
1434
1435   // optionally, the x and y offset of frames can be specified directly
1436   if (parameter[GFX_ARG_XOFFSET] != ARG_UNDEFINED_VALUE)
1437     g->offset_x = parameter[GFX_ARG_XOFFSET];
1438   if (parameter[GFX_ARG_YOFFSET] != ARG_UNDEFINED_VALUE)
1439     g->offset_y = parameter[GFX_ARG_YOFFSET];
1440
1441   // optionally, moving animations may have separate start and end graphics
1442   g->double_movement = parameter[GFX_ARG_2ND_MOVEMENT_TILE];
1443
1444   if (parameter[GFX_ARG_2ND_VERTICAL] == ARG_UNDEFINED_VALUE)
1445     parameter[GFX_ARG_2ND_VERTICAL] = !parameter[GFX_ARG_VERTICAL];
1446
1447   // correct x or y offset2 dependent of vertical or horizontal frame order
1448   if (parameter[GFX_ARG_2ND_VERTICAL])  // frames are ordered vertically
1449     g->offset2_y = (parameter[GFX_ARG_2ND_OFFSET] != ARG_UNDEFINED_VALUE ?
1450                     parameter[GFX_ARG_2ND_OFFSET] : g->height);
1451   else                                  // frames are ordered horizontally
1452     g->offset2_x = (parameter[GFX_ARG_2ND_OFFSET] != ARG_UNDEFINED_VALUE ?
1453                     parameter[GFX_ARG_2ND_OFFSET] : g->width);
1454
1455   // optionally, the x and y offset of 2nd graphic can be specified directly
1456   if (parameter[GFX_ARG_2ND_XOFFSET] != ARG_UNDEFINED_VALUE)
1457     g->offset2_x = parameter[GFX_ARG_2ND_XOFFSET];
1458   if (parameter[GFX_ARG_2ND_YOFFSET] != ARG_UNDEFINED_VALUE)
1459     g->offset2_y = parameter[GFX_ARG_2ND_YOFFSET];
1460
1461   // optionally, the second movement tile can be specified as start tile
1462   if (parameter[GFX_ARG_2ND_SWAP_TILES] != ARG_UNDEFINED_VALUE)
1463     g->swap_double_tiles= parameter[GFX_ARG_2ND_SWAP_TILES];
1464
1465   // automatically determine correct number of frames, if not defined
1466   if (parameter[GFX_ARG_FRAMES] != ARG_UNDEFINED_VALUE)
1467     g->anim_frames = parameter[GFX_ARG_FRAMES];
1468   else if (parameter[GFX_ARG_XPOS] == 0 && !parameter[GFX_ARG_VERTICAL])
1469     g->anim_frames = anim_frames_per_row;
1470   else if (parameter[GFX_ARG_YPOS] == 0 && parameter[GFX_ARG_VERTICAL])
1471     g->anim_frames = anim_frames_per_col;
1472   else
1473     g->anim_frames = 1;
1474
1475   if (g->anim_frames == 0)              // frames must be at least 1
1476     g->anim_frames = 1;
1477
1478   g->anim_frames_per_line =
1479     (parameter[GFX_ARG_FRAMES_PER_LINE] != ARG_UNDEFINED_VALUE ?
1480      parameter[GFX_ARG_FRAMES_PER_LINE] : anim_frames_per_line);
1481
1482   g->anim_delay = parameter[GFX_ARG_DELAY];
1483   if (g->anim_delay == 0)               // delay must be at least 1
1484     g->anim_delay = 1;
1485
1486   g->anim_mode = parameter[GFX_ARG_ANIM_MODE];
1487
1488   // automatically determine correct start frame, if not defined
1489   if (parameter[GFX_ARG_START_FRAME] == ARG_UNDEFINED_VALUE)
1490     g->anim_start_frame = 0;
1491   else if (g->anim_mode & ANIM_REVERSE)
1492     g->anim_start_frame = g->anim_frames - parameter[GFX_ARG_START_FRAME] - 1;
1493   else
1494     g->anim_start_frame = parameter[GFX_ARG_START_FRAME];
1495
1496   // animation synchronized with global frame counter, not move position
1497   g->anim_global_sync = parameter[GFX_ARG_GLOBAL_SYNC];
1498
1499   // optional element for cloning crumble graphics
1500   if (parameter[GFX_ARG_CRUMBLED_LIKE] != ARG_UNDEFINED_VALUE)
1501     g->crumbled_like = parameter[GFX_ARG_CRUMBLED_LIKE];
1502
1503   // optional element for cloning digging graphics
1504   if (parameter[GFX_ARG_DIGGABLE_LIKE] != ARG_UNDEFINED_VALUE)
1505     g->diggable_like = parameter[GFX_ARG_DIGGABLE_LIKE];
1506
1507   // optional border size for "crumbling" diggable graphics
1508   if (parameter[GFX_ARG_BORDER_SIZE] != ARG_UNDEFINED_VALUE)
1509     g->border_size = parameter[GFX_ARG_BORDER_SIZE];
1510
1511   // used for global animations and player "boring" and "sleeping" actions
1512   if (parameter[GFX_ARG_INIT_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
1513     g->init_delay_fixed = parameter[GFX_ARG_INIT_DELAY_FIXED];
1514   if (parameter[GFX_ARG_INIT_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
1515     g->init_delay_random = parameter[GFX_ARG_INIT_DELAY_RANDOM];
1516   if (parameter[GFX_ARG_ANIM_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
1517     g->anim_delay_fixed = parameter[GFX_ARG_ANIM_DELAY_FIXED];
1518   if (parameter[GFX_ARG_ANIM_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
1519     g->anim_delay_random = parameter[GFX_ARG_ANIM_DELAY_RANDOM];
1520   if (parameter[GFX_ARG_POST_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
1521     g->post_delay_fixed = parameter[GFX_ARG_POST_DELAY_FIXED];
1522   if (parameter[GFX_ARG_POST_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
1523     g->post_delay_random = parameter[GFX_ARG_POST_DELAY_RANDOM];
1524
1525   // used for global animations
1526   if (parameter[GFX_ARG_INIT_EVENT] != ARG_UNDEFINED_VALUE)
1527     g->init_event = parameter[GFX_ARG_INIT_EVENT];
1528   if (parameter[GFX_ARG_ANIM_EVENT] != ARG_UNDEFINED_VALUE)
1529     g->anim_event = parameter[GFX_ARG_ANIM_EVENT];
1530   if (parameter[GFX_ARG_INIT_EVENT_ACTION] != ARG_UNDEFINED_VALUE)
1531     g->init_event_action = parameter[GFX_ARG_INIT_EVENT_ACTION];
1532   if (parameter[GFX_ARG_ANIM_EVENT_ACTION] != ARG_UNDEFINED_VALUE)
1533     g->anim_event_action = parameter[GFX_ARG_ANIM_EVENT_ACTION];
1534
1535   // used for toon animations and global animations
1536   g->step_offset  = parameter[GFX_ARG_STEP_OFFSET];
1537   g->step_xoffset = parameter[GFX_ARG_STEP_XOFFSET];
1538   g->step_yoffset = parameter[GFX_ARG_STEP_YOFFSET];
1539   g->step_delay   = parameter[GFX_ARG_STEP_DELAY];
1540   g->direction    = parameter[GFX_ARG_DIRECTION];
1541   g->position     = parameter[GFX_ARG_POSITION];
1542   g->x            = parameter[GFX_ARG_X];       // (may be uninitialized,
1543   g->y            = parameter[GFX_ARG_Y];       // unlike src_x and src_y)
1544
1545   // this is only used for drawing font characters
1546   g->draw_xoffset = parameter[GFX_ARG_DRAW_XOFFSET];
1547   g->draw_yoffset = parameter[GFX_ARG_DRAW_YOFFSET];
1548
1549   // use a different default value for global animations and toons
1550   if ((graphic >= IMG_GFX_GLOBAL_ANIM_1 && graphic <= IMG_GFX_GLOBAL_ANIM_8) ||
1551       (graphic >= IMG_TOON_1            && graphic <= IMG_TOON_20))
1552     g->draw_masked = TRUE;
1553
1554   // this is used for drawing envelopes, global animations and toons
1555   if (parameter[GFX_ARG_DRAW_MASKED] != ARG_UNDEFINED_VALUE)
1556     g->draw_masked = parameter[GFX_ARG_DRAW_MASKED];
1557
1558   // used for toon animations and global animations
1559   if (parameter[GFX_ARG_DRAW_ORDER] != ARG_UNDEFINED_VALUE)
1560     g->draw_order = parameter[GFX_ARG_DRAW_ORDER];
1561
1562   // optional graphic for cloning all graphics settings
1563   if (parameter[GFX_ARG_CLONE_FROM] != ARG_UNDEFINED_VALUE)
1564     g->clone_from = parameter[GFX_ARG_CLONE_FROM];
1565
1566   // optional settings for drawing title screens and title messages
1567   if (parameter[GFX_ARG_FADE_MODE] != ARG_UNDEFINED_VALUE)
1568     g->fade_mode = parameter[GFX_ARG_FADE_MODE];
1569   if (parameter[GFX_ARG_FADE_DELAY] != ARG_UNDEFINED_VALUE)
1570     g->fade_delay = parameter[GFX_ARG_FADE_DELAY];
1571   if (parameter[GFX_ARG_POST_DELAY] != ARG_UNDEFINED_VALUE)
1572     g->post_delay = parameter[GFX_ARG_POST_DELAY];
1573   if (parameter[GFX_ARG_AUTO_DELAY] != ARG_UNDEFINED_VALUE)
1574     g->auto_delay = parameter[GFX_ARG_AUTO_DELAY];
1575   if (parameter[GFX_ARG_ALIGN] != ARG_UNDEFINED_VALUE)
1576     g->align = parameter[GFX_ARG_ALIGN];
1577   if (parameter[GFX_ARG_VALIGN] != ARG_UNDEFINED_VALUE)
1578     g->valign = parameter[GFX_ARG_VALIGN];
1579   if (parameter[GFX_ARG_SORT_PRIORITY] != ARG_UNDEFINED_VALUE)
1580     g->sort_priority = parameter[GFX_ARG_SORT_PRIORITY];
1581
1582   if (parameter[GFX_ARG_CLASS] != ARG_UNDEFINED_VALUE)
1583     g->class = parameter[GFX_ARG_CLASS];
1584   if (parameter[GFX_ARG_STYLE] != ARG_UNDEFINED_VALUE)
1585     g->style = parameter[GFX_ARG_STYLE];
1586
1587   // this is only used for drawing menu buttons and text
1588   g->active_xoffset = parameter[GFX_ARG_ACTIVE_XOFFSET];
1589   g->active_yoffset = parameter[GFX_ARG_ACTIVE_YOFFSET];
1590   g->pressed_xoffset = parameter[GFX_ARG_PRESSED_XOFFSET];
1591   g->pressed_yoffset = parameter[GFX_ARG_PRESSED_YOFFSET];
1592 }
1593
1594 static void set_graphic_parameters(int graphic)
1595 {
1596   struct FileInfo *image = getImageListEntryFromImageID(graphic);
1597   char **parameter_raw = image->parameter;
1598   Bitmap **src_bitmaps = getBitmapsFromImageID(graphic);
1599   int parameter[NUM_GFX_ARGS];
1600   int i;
1601
1602   // if fallback to default artwork is done, also use the default parameters
1603   if (image->fallback_to_default)
1604     parameter_raw = image->default_parameter;
1605
1606   // get integer values from string parameters
1607   for (i = 0; i < NUM_GFX_ARGS; i++)
1608     parameter[i] = get_graphic_parameter_value(parameter_raw[i],
1609                                                image_config_suffix[i].token,
1610                                                image_config_suffix[i].type);
1611
1612   set_graphic_parameters_ext(graphic, parameter, src_bitmaps);
1613
1614   UPDATE_BUSY_STATE();
1615 }
1616
1617 static void set_cloned_graphic_parameters(int graphic)
1618 {
1619   int fallback_graphic = IMG_CHAR_EXCLAM;
1620   int max_num_images = getImageListSize();
1621   int clone_graphic = graphic_info[graphic].clone_from;
1622   int num_references_followed = 1;
1623
1624   while (graphic_info[clone_graphic].clone_from != -1 &&
1625          num_references_followed < max_num_images)
1626   {
1627     clone_graphic = graphic_info[clone_graphic].clone_from;
1628
1629     num_references_followed++;
1630   }
1631
1632   if (num_references_followed >= max_num_images)
1633   {
1634     Error(ERR_INFO_LINE, "-");
1635     Error(ERR_INFO, "warning: error found in config file:");
1636     Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
1637     Error(ERR_INFO, "- config token: '%s'", getTokenFromImageID(graphic));
1638     Error(ERR_INFO, "error: loop discovered when resolving cloned graphics");
1639     Error(ERR_INFO, "custom graphic rejected for this element/action");
1640
1641     if (graphic == fallback_graphic)
1642       Error(ERR_EXIT, "no fallback graphic available");
1643
1644     Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic");
1645     Error(ERR_INFO_LINE, "-");
1646
1647     graphic_info[graphic] = graphic_info[fallback_graphic];
1648   }
1649   else
1650   {
1651     graphic_info[graphic] = graphic_info[clone_graphic];
1652     graphic_info[graphic].clone_from = clone_graphic;
1653   }
1654 }
1655
1656 static void InitGraphicInfo(void)
1657 {
1658   int fallback_graphic = IMG_CHAR_EXCLAM;
1659   int num_images = getImageListSize();
1660   int i;
1661
1662   // use image size as default values for width and height for these images
1663   static int full_size_graphics[] =
1664   {
1665     IMG_GLOBAL_BORDER,
1666     IMG_GLOBAL_BORDER_MAIN,
1667     IMG_GLOBAL_BORDER_SCORES,
1668     IMG_GLOBAL_BORDER_EDITOR,
1669     IMG_GLOBAL_BORDER_PLAYING,
1670     IMG_GLOBAL_DOOR,
1671
1672     IMG_BACKGROUND_ENVELOPE_1,
1673     IMG_BACKGROUND_ENVELOPE_2,
1674     IMG_BACKGROUND_ENVELOPE_3,
1675     IMG_BACKGROUND_ENVELOPE_4,
1676     IMG_BACKGROUND_REQUEST,
1677
1678     IMG_BACKGROUND,
1679     IMG_BACKGROUND_TITLE_INITIAL,
1680     IMG_BACKGROUND_TITLE,
1681     IMG_BACKGROUND_MAIN,
1682     IMG_BACKGROUND_LEVELS,
1683     IMG_BACKGROUND_LEVELNR,
1684     IMG_BACKGROUND_SCORES,
1685     IMG_BACKGROUND_EDITOR,
1686     IMG_BACKGROUND_INFO,
1687     IMG_BACKGROUND_INFO_ELEMENTS,
1688     IMG_BACKGROUND_INFO_MUSIC,
1689     IMG_BACKGROUND_INFO_CREDITS,
1690     IMG_BACKGROUND_INFO_PROGRAM,
1691     IMG_BACKGROUND_INFO_VERSION,
1692     IMG_BACKGROUND_INFO_LEVELSET,
1693     IMG_BACKGROUND_SETUP,
1694     IMG_BACKGROUND_PLAYING,
1695     IMG_BACKGROUND_DOOR,
1696     IMG_BACKGROUND_TAPE,
1697     IMG_BACKGROUND_PANEL,
1698     IMG_BACKGROUND_PALETTE,
1699     IMG_BACKGROUND_TOOLBOX,
1700
1701     IMG_TITLESCREEN_INITIAL_1,
1702     IMG_TITLESCREEN_INITIAL_2,
1703     IMG_TITLESCREEN_INITIAL_3,
1704     IMG_TITLESCREEN_INITIAL_4,
1705     IMG_TITLESCREEN_INITIAL_5,
1706     IMG_TITLESCREEN_1,
1707     IMG_TITLESCREEN_2,
1708     IMG_TITLESCREEN_3,
1709     IMG_TITLESCREEN_4,
1710     IMG_TITLESCREEN_5,
1711
1712     IMG_BACKGROUND_TITLEMESSAGE_INITIAL_1,
1713     IMG_BACKGROUND_TITLEMESSAGE_INITIAL_2,
1714     IMG_BACKGROUND_TITLEMESSAGE_INITIAL_3,
1715     IMG_BACKGROUND_TITLEMESSAGE_INITIAL_4,
1716     IMG_BACKGROUND_TITLEMESSAGE_INITIAL_5,
1717     IMG_BACKGROUND_TITLEMESSAGE_1,
1718     IMG_BACKGROUND_TITLEMESSAGE_2,
1719     IMG_BACKGROUND_TITLEMESSAGE_3,
1720     IMG_BACKGROUND_TITLEMESSAGE_4,
1721     IMG_BACKGROUND_TITLEMESSAGE_5,
1722
1723     -1
1724   };
1725
1726   checked_free(graphic_info);
1727
1728   graphic_info = checked_calloc(num_images * sizeof(struct GraphicInfo));
1729
1730   // initialize "use_image_size" flag with default value
1731   for (i = 0; i < num_images; i++)
1732     graphic_info[i].use_image_size = FALSE;
1733
1734   // initialize "use_image_size" flag from static configuration above
1735   for (i = 0; full_size_graphics[i] != -1; i++)
1736     graphic_info[full_size_graphics[i]].use_image_size = TRUE;
1737
1738   // first set all graphic paramaters ...
1739   for (i = 0; i < num_images; i++)
1740     set_graphic_parameters(i);
1741
1742   // ... then copy these parameters for cloned graphics
1743   for (i = 0; i < num_images; i++)
1744     if (graphic_info[i].clone_from != -1)
1745       set_cloned_graphic_parameters(i);
1746
1747   for (i = 0; i < num_images; i++)
1748   {
1749     Bitmap *src_bitmap = graphic_info[i].bitmap;
1750     int src_x, src_y;
1751     int width, height;
1752     int last_frame;
1753     int src_bitmap_width, src_bitmap_height;
1754
1755     // now check if no animation frames are outside of the loaded image
1756
1757     if (graphic_info[i].bitmap == NULL)
1758       continue;         // skip check for optional images that are undefined
1759
1760     // get image size (this can differ from the standard element tile size!)
1761     width  = graphic_info[i].width;
1762     height = graphic_info[i].height;
1763
1764     // get final bitmap size (with scaling, but without small images)
1765     src_bitmap_width  = graphic_info[i].src_image_width;
1766     src_bitmap_height = graphic_info[i].src_image_height;
1767
1768     // check if first animation frame is inside specified bitmap
1769
1770     // do not use getGraphicSourceXY() here to get position of first frame;
1771     // this avoids calculating wrong start position for out-of-bounds frame
1772     src_x = graphic_info[i].src_x;
1773     src_y = graphic_info[i].src_y;
1774
1775     if (program.headless)
1776       continue;
1777
1778     if (src_x < 0 || src_y < 0 ||
1779         src_x + width  > src_bitmap_width ||
1780         src_y + height > src_bitmap_height)
1781     {
1782       Error(ERR_INFO_LINE, "-");
1783       Error(ERR_INFO, "warning: error found in config file:");
1784       Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
1785       Error(ERR_INFO, "- config token: '%s'", getTokenFromImageID(i));
1786       Error(ERR_INFO, "- image file: '%s'", src_bitmap->source_filename);
1787       Error(ERR_INFO, "- frame size: %d, %d", width, height);
1788       Error(ERR_INFO,
1789             "error: first animation frame out of bounds (%d, %d) [%d, %d]",
1790             src_x, src_y, src_bitmap_width, src_bitmap_height);
1791       Error(ERR_INFO, "custom graphic rejected for this element/action");
1792
1793       if (i == fallback_graphic)
1794         Error(ERR_EXIT, "no fallback graphic available");
1795
1796       Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic");
1797       Error(ERR_INFO_LINE, "-");
1798
1799       graphic_info[i] = graphic_info[fallback_graphic];
1800
1801       // if first frame out of bounds, do not check last frame anymore
1802       continue;
1803     }
1804
1805     // check if last animation frame is inside specified bitmap
1806
1807     last_frame = graphic_info[i].anim_frames - 1;
1808     getGraphicSourceXY(i, last_frame, &src_x, &src_y, FALSE);
1809
1810     if (src_x < 0 || src_y < 0 ||
1811         src_x + width  > src_bitmap_width ||
1812         src_y + height > src_bitmap_height)
1813     {
1814       Error(ERR_INFO_LINE, "-");
1815       Error(ERR_INFO, "warning: error found in config file:");
1816       Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
1817       Error(ERR_INFO, "- config token: '%s'", getTokenFromImageID(i));
1818       Error(ERR_INFO, "- image file: '%s'", src_bitmap->source_filename);
1819       Error(ERR_INFO, "- frame size: %d, %d", width, height);
1820       Error(ERR_INFO,
1821             "error: last animation frame (%d) out of bounds (%d, %d) [%d, %d]",
1822             last_frame, src_x, src_y, src_bitmap_width, src_bitmap_height);
1823       Error(ERR_INFO, "custom graphic rejected for this element/action");
1824
1825       if (i == fallback_graphic)
1826         Error(ERR_EXIT, "no fallback graphic available");
1827
1828       Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic");
1829       Error(ERR_INFO_LINE, "-");
1830
1831       graphic_info[i] = graphic_info[fallback_graphic];
1832     }
1833   }
1834 }
1835
1836 static void InitGraphicCompatibilityInfo(void)
1837 {
1838   struct FileInfo *fi_global_door =
1839     getImageListEntryFromImageID(IMG_GLOBAL_DOOR);
1840   int num_images = getImageListSize();
1841   int i;
1842
1843   /* the following compatibility handling is needed for the following case:
1844      versions up to 3.3.0.0 used one large bitmap "global.door" for various
1845      graphics mainly used for door and panel graphics, like editor, tape and
1846      in-game buttons with hard-coded bitmap positions and button sizes; as
1847      these graphics now have individual definitions, redefining "global.door"
1848      to change all these graphics at once like before does not work anymore
1849      (because all those individual definitions still have their default values);
1850      to solve this, remap all those individual definitions that are not
1851      redefined to the new bitmap of "global.door" if it was redefined */
1852
1853   // special compatibility handling if image "global.door" was redefined
1854   if (fi_global_door->redefined)
1855   {
1856     for (i = 0; i < num_images; i++)
1857     {
1858       struct FileInfo *fi = getImageListEntryFromImageID(i);
1859
1860       // process only those images that still use the default settings
1861       if (!fi->redefined)
1862       {
1863         // process all images which default to same image as "global.door"
1864         if (strEqual(fi->default_filename, fi_global_door->default_filename))
1865         {
1866           // printf("::: special treatment needed for token '%s'\n", fi->token);
1867
1868           graphic_info[i].bitmaps = graphic_info[IMG_GLOBAL_DOOR].bitmaps;
1869           graphic_info[i].bitmap  = graphic_info[IMG_GLOBAL_DOOR].bitmap;
1870         }
1871       }
1872     }
1873   }
1874
1875   InitGraphicCompatibilityInfo_Doors();
1876 }
1877
1878 static void InitElementSoundInfo(void)
1879 {
1880   struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1881   int num_property_mappings = getSoundListPropertyMappingSize();
1882   int i, j, act;
1883
1884   // set values to -1 to identify later as "uninitialized" values
1885   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1886     for (act = 0; act < NUM_ACTIONS; act++)
1887       element_info[i].sound[act] = -1;
1888
1889   // initialize element/sound mapping from static configuration
1890   for (i = 0; element_to_sound[i].element > -1; i++)
1891   {
1892     int element      = element_to_sound[i].element;
1893     int action       = element_to_sound[i].action;
1894     int sound        = element_to_sound[i].sound;
1895     boolean is_class = element_to_sound[i].is_class;
1896
1897     if (action < 0)
1898       action = ACTION_DEFAULT;
1899
1900     if (!is_class)
1901       element_info[element].sound[action] = sound;
1902     else
1903       for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1904         if (strEqual(element_info[j].class_name,
1905                      element_info[element].class_name))
1906           element_info[j].sound[action] = sound;
1907   }
1908
1909   // initialize element class/sound mapping from dynamic configuration
1910   for (i = 0; i < num_property_mappings; i++)
1911   {
1912     int element_class = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
1913     int action        = property_mapping[i].ext1_index;
1914     int sound         = property_mapping[i].artwork_index;
1915
1916     if (element_class < 0 || element_class >= MAX_NUM_ELEMENTS)
1917       continue;
1918
1919     if (action < 0)
1920       action = ACTION_DEFAULT;
1921
1922     for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1923       if (strEqual(element_info[j].class_name,
1924                    element_info[element_class].class_name))
1925         element_info[j].sound[action] = sound;
1926   }
1927
1928   // initialize element/sound mapping from dynamic configuration
1929   for (i = 0; i < num_property_mappings; i++)
1930   {
1931     int element = property_mapping[i].base_index;
1932     int action  = property_mapping[i].ext1_index;
1933     int sound   = property_mapping[i].artwork_index;
1934
1935     if (element >= MAX_NUM_ELEMENTS)
1936       continue;
1937
1938     if (action < 0)
1939       action = ACTION_DEFAULT;
1940
1941     element_info[element].sound[action] = sound;
1942   }
1943
1944   // now set all '-1' values to element specific default values
1945   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1946   {
1947     for (act = 0; act < NUM_ACTIONS; act++)
1948     {
1949       // generic default action sound (defined by "[default]" directive)
1950       int default_action_sound = element_info[EL_DEFAULT].sound[act];
1951
1952       // look for special default action sound (classic game specific)
1953       if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].sound[act] != -1)
1954         default_action_sound = element_info[EL_BD_DEFAULT].sound[act];
1955       if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].sound[act] != -1)
1956         default_action_sound = element_info[EL_SP_DEFAULT].sound[act];
1957       if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].sound[act] != -1)
1958         default_action_sound = element_info[EL_SB_DEFAULT].sound[act];
1959       if (IS_MM_ELEMENT(i) && element_info[EL_MM_DEFAULT].sound[act] != -1)
1960         default_action_sound = element_info[EL_MM_DEFAULT].sound[act];
1961
1962       // !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!!
1963       // !!! make this better !!!
1964       if (i == EL_EMPTY_SPACE)
1965         default_action_sound = element_info[EL_DEFAULT].sound[act];
1966
1967       // no sound for this specific action -- use default action sound
1968       if (element_info[i].sound[act] == -1)
1969         element_info[i].sound[act] = default_action_sound;
1970     }
1971   }
1972
1973   // copy sound settings to some elements that are only stored in level file
1974   // in native R'n'D levels, but are used by game engine in native EM levels
1975   for (i = 0; copy_properties[i][0] != -1; i++)
1976     for (j = 1; j <= 4; j++)
1977       for (act = 0; act < NUM_ACTIONS; act++)
1978         element_info[copy_properties[i][j]].sound[act] =
1979           element_info[copy_properties[i][0]].sound[act];
1980 }
1981
1982 static void InitGameModeSoundInfo(void)
1983 {
1984   int i;
1985
1986   // set values to -1 to identify later as "uninitialized" values
1987   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1988     menu.sound[i] = -1;
1989
1990   // initialize gamemode/sound mapping from static configuration
1991   for (i = 0; gamemode_to_sound[i].sound > -1; i++)
1992   {
1993     int gamemode = gamemode_to_sound[i].gamemode;
1994     int sound    = gamemode_to_sound[i].sound;
1995
1996     if (gamemode < 0)
1997       gamemode = GAME_MODE_DEFAULT;
1998
1999     menu.sound[gamemode] = sound;
2000   }
2001
2002   // now set all '-1' values to levelset specific default values
2003   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
2004     if (menu.sound[i] == -1)
2005       menu.sound[i] = menu.sound[GAME_MODE_DEFAULT];
2006 }
2007
2008 static void set_sound_parameters(int sound, char **parameter_raw)
2009 {
2010   int parameter[NUM_SND_ARGS];
2011   int i;
2012
2013   // get integer values from string parameters
2014   for (i = 0; i < NUM_SND_ARGS; i++)
2015     parameter[i] =
2016       get_parameter_value(parameter_raw[i],
2017                           sound_config_suffix[i].token,
2018                           sound_config_suffix[i].type);
2019
2020   // explicit loop mode setting in configuration overrides default value
2021   if (parameter[SND_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
2022     sound_info[sound].loop = parameter[SND_ARG_MODE_LOOP];
2023
2024   // sound volume to change the original volume when loading the sound file
2025   sound_info[sound].volume = parameter[SND_ARG_VOLUME];
2026
2027   // sound priority to give certain sounds a higher or lower priority
2028   sound_info[sound].priority = parameter[SND_ARG_PRIORITY];
2029 }
2030
2031 static void InitSoundInfo(void)
2032 {
2033   int *sound_effect_properties;
2034   int num_sounds = getSoundListSize();
2035   int i, j;
2036
2037   checked_free(sound_info);
2038
2039   sound_effect_properties = checked_calloc(num_sounds * sizeof(int));
2040   sound_info = checked_calloc(num_sounds * sizeof(struct SoundInfo));
2041
2042   // initialize sound effect for all elements to "no sound"
2043   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2044     for (j = 0; j < NUM_ACTIONS; j++)
2045       element_info[i].sound[j] = SND_UNDEFINED;
2046
2047   for (i = 0; i < num_sounds; i++)
2048   {
2049     struct FileInfo *sound = getSoundListEntry(i);
2050     int len_effect_text = strlen(sound->token);
2051
2052     sound_effect_properties[i] = ACTION_OTHER;
2053     sound_info[i].loop = FALSE;         // default: play sound only once
2054
2055     // determine all loop sounds and identify certain sound classes
2056
2057     for (j = 0; element_action_info[j].suffix; j++)
2058     {
2059       int len_action_text = strlen(element_action_info[j].suffix);
2060
2061       if (len_action_text < len_effect_text &&
2062           strEqual(&sound->token[len_effect_text - len_action_text],
2063                    element_action_info[j].suffix))
2064       {
2065         sound_effect_properties[i] = element_action_info[j].value;
2066         sound_info[i].loop = element_action_info[j].is_loop_sound;
2067
2068         break;
2069       }
2070     }
2071
2072     // associate elements and some selected sound actions
2073
2074     for (j = 0; j < MAX_NUM_ELEMENTS; j++)
2075     {
2076       if (element_info[j].class_name)
2077       {
2078         int len_class_text = strlen(element_info[j].class_name);
2079
2080         if (len_class_text + 1 < len_effect_text &&
2081             strncmp(sound->token,
2082                     element_info[j].class_name, len_class_text) == 0 &&
2083             sound->token[len_class_text] == '.')
2084         {
2085           int sound_action_value = sound_effect_properties[i];
2086
2087           element_info[j].sound[sound_action_value] = i;
2088         }
2089       }
2090     }
2091
2092     set_sound_parameters(i, sound->parameter);
2093   }
2094
2095   free(sound_effect_properties);
2096 }
2097
2098 static void InitGameModeMusicInfo(void)
2099 {
2100   struct PropertyMapping *property_mapping = getMusicListPropertyMapping();
2101   int num_property_mappings = getMusicListPropertyMappingSize();
2102   int default_levelset_music = -1;
2103   int i;
2104
2105   // set values to -1 to identify later as "uninitialized" values
2106   for (i = 0; i < MAX_LEVELS; i++)
2107     levelset.music[i] = -1;
2108   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
2109     menu.music[i] = -1;
2110
2111   // initialize gamemode/music mapping from static configuration
2112   for (i = 0; gamemode_to_music[i].music > -1; i++)
2113   {
2114     int gamemode = gamemode_to_music[i].gamemode;
2115     int music    = gamemode_to_music[i].music;
2116
2117     if (gamemode < 0)
2118       gamemode = GAME_MODE_DEFAULT;
2119
2120     menu.music[gamemode] = music;
2121   }
2122
2123   // initialize gamemode/music mapping from dynamic configuration
2124   for (i = 0; i < num_property_mappings; i++)
2125   {
2126     int prefix   = property_mapping[i].base_index;
2127     int gamemode = property_mapping[i].ext2_index;
2128     int level    = property_mapping[i].ext3_index;
2129     int music    = property_mapping[i].artwork_index;
2130
2131     if (prefix < 0 || prefix >= NUM_MUSIC_PREFIXES)
2132       continue;
2133
2134     if (gamemode < 0)
2135       gamemode = GAME_MODE_DEFAULT;
2136
2137     // level specific music only allowed for in-game music
2138     if (level != -1 && gamemode == GAME_MODE_DEFAULT)
2139       gamemode = GAME_MODE_PLAYING;
2140
2141     if (level == -1)
2142     {
2143       level = 0;
2144       default_levelset_music = music;
2145     }
2146
2147     if (gamemode == GAME_MODE_PLAYING || gamemode == GAME_MODE_DEFAULT)
2148       levelset.music[level] = music;
2149     if (gamemode != GAME_MODE_PLAYING)
2150       menu.music[gamemode] = music;
2151   }
2152
2153   // now set all '-1' values to menu specific default values
2154   // (undefined values of "levelset.music[]" might stay at "-1" to
2155   // allow dynamic selection of music files from music directory!)
2156   for (i = 0; i < MAX_LEVELS; i++)
2157     if (levelset.music[i] == -1)
2158       levelset.music[i] = default_levelset_music;
2159   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
2160     if (menu.music[i] == -1)
2161       menu.music[i] = menu.music[GAME_MODE_DEFAULT];
2162 }
2163
2164 static void set_music_parameters(int music, char **parameter_raw)
2165 {
2166   int parameter[NUM_MUS_ARGS];
2167   int i;
2168
2169   // get integer values from string parameters
2170   for (i = 0; i < NUM_MUS_ARGS; i++)
2171     parameter[i] =
2172       get_parameter_value(parameter_raw[i],
2173                           music_config_suffix[i].token,
2174                           music_config_suffix[i].type);
2175
2176   // explicit loop mode setting in configuration overrides default value
2177   if (parameter[MUS_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
2178     music_info[music].loop = parameter[MUS_ARG_MODE_LOOP];
2179 }
2180
2181 static void InitMusicInfo(void)
2182 {
2183   int num_music = getMusicListSize();
2184   int i, j;
2185
2186   checked_free(music_info);
2187
2188   music_info = checked_calloc(num_music * sizeof(struct MusicInfo));
2189
2190   for (i = 0; i < num_music; i++)
2191   {
2192     struct FileInfo *music = getMusicListEntry(i);
2193     int len_music_text = strlen(music->token);
2194
2195     music_info[i].loop = TRUE;          // default: play music in loop mode
2196
2197     // determine all loop music
2198
2199     for (j = 0; music_prefix_info[j].prefix; j++)
2200     {
2201       int len_prefix_text = strlen(music_prefix_info[j].prefix);
2202
2203       if (len_prefix_text < len_music_text &&
2204           strncmp(music->token,
2205                   music_prefix_info[j].prefix, len_prefix_text) == 0)
2206       {
2207         music_info[i].loop = music_prefix_info[j].is_loop_music;
2208
2209         break;
2210       }
2211     }
2212
2213     set_music_parameters(i, music->parameter);
2214   }
2215 }
2216
2217 static void ReinitializeGraphics(void)
2218 {
2219   print_timestamp_init("ReinitializeGraphics");
2220
2221   InitGfxTileSizeInfo(game.tile_size, TILESIZE);
2222
2223   InitGraphicInfo();                    // graphic properties mapping
2224   print_timestamp_time("InitGraphicInfo");
2225   InitElementGraphicInfo();             // element game graphic mapping
2226   print_timestamp_time("InitElementGraphicInfo");
2227   InitElementSpecialGraphicInfo();      // element special graphic mapping
2228   print_timestamp_time("InitElementSpecialGraphicInfo");
2229
2230   InitElementSmallImages();             // scale elements to all needed sizes
2231   print_timestamp_time("InitElementSmallImages");
2232   InitScaledImages();                   // scale all other images, if needed
2233   print_timestamp_time("InitScaledImages");
2234   InitBitmapPointers();                 // set standard size bitmap pointers
2235   print_timestamp_time("InitBitmapPointers");
2236   InitFontGraphicInfo();                // initialize text drawing functions
2237   print_timestamp_time("InitFontGraphicInfo");
2238   InitGlobalAnimGraphicInfo();          // initialize global animation config
2239   print_timestamp_time("InitGlobalAnimGraphicInfo");
2240
2241   InitImageTextures();                  // create textures for certain images
2242   print_timestamp_time("InitImageTextures");
2243
2244   InitGraphicInfo_EM();                 // graphic mapping for EM engine
2245   print_timestamp_time("InitGraphicInfo_EM");
2246
2247   InitGraphicCompatibilityInfo();
2248   print_timestamp_time("InitGraphicCompatibilityInfo");
2249
2250   SetMainBackgroundImage(IMG_BACKGROUND);
2251   print_timestamp_time("SetMainBackgroundImage");
2252   SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
2253   print_timestamp_time("SetDoorBackgroundImage");
2254
2255   InitGadgets();
2256   print_timestamp_time("InitGadgets");
2257   InitDoors();
2258   print_timestamp_time("InitDoors");
2259
2260   print_timestamp_done("ReinitializeGraphics");
2261 }
2262
2263 static void ReinitializeSounds(void)
2264 {
2265   InitSoundInfo();              // sound properties mapping
2266   InitElementSoundInfo();       // element game sound mapping
2267   InitGameModeSoundInfo();      // game mode sound mapping
2268   InitGlobalAnimSoundInfo();    // global animation sound settings
2269
2270   InitPlayLevelSound();         // internal game sound settings
2271 }
2272
2273 static void ReinitializeMusic(void)
2274 {
2275   InitMusicInfo();              // music properties mapping
2276   InitGameModeMusicInfo();      // game mode music mapping
2277   InitGlobalAnimMusicInfo();    // global animation music settings
2278 }
2279
2280 static int get_special_property_bit(int element, int property_bit_nr)
2281 {
2282   struct PropertyBitInfo
2283   {
2284     int element;
2285     int bit_nr;
2286   };
2287
2288   static struct PropertyBitInfo pb_can_move_into_acid[] =
2289   {
2290     // the player may be able fall into acid when gravity is activated
2291     { EL_PLAYER_1,              0       },
2292     { EL_PLAYER_2,              0       },
2293     { EL_PLAYER_3,              0       },
2294     { EL_PLAYER_4,              0       },
2295     { EL_SP_MURPHY,             0       },
2296     { EL_SOKOBAN_FIELD_PLAYER,  0       },
2297
2298     // all elements that can move may be able to also move into acid
2299     { EL_BUG,                   1       },
2300     { EL_BUG_LEFT,              1       },
2301     { EL_BUG_RIGHT,             1       },
2302     { EL_BUG_UP,                1       },
2303     { EL_BUG_DOWN,              1       },
2304     { EL_SPACESHIP,             2       },
2305     { EL_SPACESHIP_LEFT,        2       },
2306     { EL_SPACESHIP_RIGHT,       2       },
2307     { EL_SPACESHIP_UP,          2       },
2308     { EL_SPACESHIP_DOWN,        2       },
2309     { EL_BD_BUTTERFLY,          3       },
2310     { EL_BD_BUTTERFLY_LEFT,     3       },
2311     { EL_BD_BUTTERFLY_RIGHT,    3       },
2312     { EL_BD_BUTTERFLY_UP,       3       },
2313     { EL_BD_BUTTERFLY_DOWN,     3       },
2314     { EL_BD_FIREFLY,            4       },
2315     { EL_BD_FIREFLY_LEFT,       4       },
2316     { EL_BD_FIREFLY_RIGHT,      4       },
2317     { EL_BD_FIREFLY_UP,         4       },
2318     { EL_BD_FIREFLY_DOWN,       4       },
2319     { EL_YAMYAM,                5       },
2320     { EL_YAMYAM_LEFT,           5       },
2321     { EL_YAMYAM_RIGHT,          5       },
2322     { EL_YAMYAM_UP,             5       },
2323     { EL_YAMYAM_DOWN,           5       },
2324     { EL_DARK_YAMYAM,           6       },
2325     { EL_ROBOT,                 7       },
2326     { EL_PACMAN,                8       },
2327     { EL_PACMAN_LEFT,           8       },
2328     { EL_PACMAN_RIGHT,          8       },
2329     { EL_PACMAN_UP,             8       },
2330     { EL_PACMAN_DOWN,           8       },
2331     { EL_MOLE,                  9       },
2332     { EL_MOLE_LEFT,             9       },
2333     { EL_MOLE_RIGHT,            9       },
2334     { EL_MOLE_UP,               9       },
2335     { EL_MOLE_DOWN,             9       },
2336     { EL_PENGUIN,               10      },
2337     { EL_PIG,                   11      },
2338     { EL_DRAGON,                12      },
2339     { EL_SATELLITE,             13      },
2340     { EL_SP_SNIKSNAK,           14      },
2341     { EL_SP_ELECTRON,           15      },
2342     { EL_BALLOON,               16      },
2343     { EL_SPRING,                17      },
2344     { EL_EMC_ANDROID,           18      },
2345
2346     { -1,                       -1      },
2347   };
2348
2349   static struct PropertyBitInfo pb_dont_collide_with[] =
2350   {
2351     { EL_SP_SNIKSNAK,           0       },
2352     { EL_SP_ELECTRON,           1       },
2353
2354     { -1,                       -1      },
2355   };
2356
2357   static struct
2358   {
2359     int bit_nr;
2360     struct PropertyBitInfo *pb_info;
2361   } pb_definition[] =
2362   {
2363     { EP_CAN_MOVE_INTO_ACID,    pb_can_move_into_acid   },
2364     { EP_DONT_COLLIDE_WITH,     pb_dont_collide_with    },
2365
2366     { -1,                       NULL                    },
2367   };
2368
2369   struct PropertyBitInfo *pb_info = NULL;
2370   int i;
2371
2372   for (i = 0; pb_definition[i].bit_nr != -1; i++)
2373     if (pb_definition[i].bit_nr == property_bit_nr)
2374       pb_info = pb_definition[i].pb_info;
2375
2376   if (pb_info == NULL)
2377     return -1;
2378
2379   for (i = 0; pb_info[i].element != -1; i++)
2380     if (pb_info[i].element == element)
2381       return pb_info[i].bit_nr;
2382
2383   return -1;
2384 }
2385
2386 void setBitfieldProperty(int *bitfield, int property_bit_nr, int element,
2387                          boolean property_value)
2388 {
2389   int bit_nr = get_special_property_bit(element, property_bit_nr);
2390
2391   if (bit_nr > -1)
2392   {
2393     if (property_value)
2394       *bitfield |=  (1 << bit_nr);
2395     else
2396       *bitfield &= ~(1 << bit_nr);
2397   }
2398 }
2399
2400 boolean getBitfieldProperty(int *bitfield, int property_bit_nr, int element)
2401 {
2402   int bit_nr = get_special_property_bit(element, property_bit_nr);
2403
2404   if (bit_nr > -1)
2405     return ((*bitfield & (1 << bit_nr)) != 0);
2406
2407   return FALSE;
2408 }
2409
2410 static void ResolveGroupElementExt(int group_element, int recursion_depth)
2411 {
2412   static int group_nr;
2413   static struct ElementGroupInfo *group;
2414   struct ElementGroupInfo *actual_group = element_info[group_element].group;
2415   int i;
2416
2417   if (actual_group == NULL)                     // not yet initialized
2418     return;
2419
2420   if (recursion_depth > NUM_GROUP_ELEMENTS)     // recursion too deep
2421   {
2422     Error(ERR_WARN, "recursion too deep when resolving group element %d",
2423           group_element - EL_GROUP_START + 1);
2424
2425     // replace element which caused too deep recursion by question mark
2426     group->element_resolved[group->num_elements_resolved++] = EL_UNKNOWN;
2427
2428     return;
2429   }
2430
2431   if (recursion_depth == 0)                     // initialization
2432   {
2433     group = actual_group;
2434     group_nr = GROUP_NR(group_element);
2435
2436     group->num_elements_resolved = 0;
2437     group->choice_pos = 0;
2438
2439     for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2440       element_info[i].in_group[group_nr] = FALSE;
2441   }
2442
2443   for (i = 0; i < actual_group->num_elements; i++)
2444   {
2445     int element = actual_group->element[i];
2446
2447     if (group->num_elements_resolved == NUM_FILE_ELEMENTS)
2448       break;
2449
2450     if (IS_GROUP_ELEMENT(element))
2451       ResolveGroupElementExt(element, recursion_depth + 1);
2452     else
2453     {
2454       group->element_resolved[group->num_elements_resolved++] = element;
2455       element_info[element].in_group[group_nr] = TRUE;
2456     }
2457   }
2458 }
2459
2460 void ResolveGroupElement(int group_element)
2461 {
2462   ResolveGroupElementExt(group_element, 0);
2463 }
2464
2465 void InitElementPropertiesStatic(void)
2466 {
2467   static boolean clipboard_elements_initialized = FALSE;
2468
2469   static int ep_diggable[] =
2470   {
2471     EL_SAND,
2472     EL_SP_BASE,
2473     EL_SP_BUGGY_BASE,
2474     EL_SP_BUGGY_BASE_ACTIVATING,
2475     EL_TRAP,
2476     EL_INVISIBLE_SAND,
2477     EL_INVISIBLE_SAND_ACTIVE,
2478     EL_EMC_GRASS,
2479
2480     // !!! currently not diggable, but handled by 'ep_dont_run_into' !!!
2481     // (if amoeba can grow into anything diggable, maybe keep these out)
2482 #if 0
2483     EL_LANDMINE,
2484     EL_DC_LANDMINE,
2485     EL_TRAP_ACTIVE,
2486     EL_SP_BUGGY_BASE_ACTIVE,
2487     EL_EMC_PLANT,
2488 #endif
2489
2490     -1
2491   };
2492
2493   static int ep_collectible_only[] =
2494   {
2495     EL_BD_DIAMOND,
2496     EL_EMERALD,
2497     EL_DIAMOND,
2498     EL_EMERALD_YELLOW,
2499     EL_EMERALD_RED,
2500     EL_EMERALD_PURPLE,
2501     EL_KEY_1,
2502     EL_KEY_2,
2503     EL_KEY_3,
2504     EL_KEY_4,
2505     EL_EM_KEY_1,
2506     EL_EM_KEY_2,
2507     EL_EM_KEY_3,
2508     EL_EM_KEY_4,
2509     EL_EMC_KEY_5,
2510     EL_EMC_KEY_6,
2511     EL_EMC_KEY_7,
2512     EL_EMC_KEY_8,
2513     EL_DYNAMITE,
2514     EL_EM_DYNAMITE,
2515     EL_DYNABOMB_INCREASE_NUMBER,
2516     EL_DYNABOMB_INCREASE_SIZE,
2517     EL_DYNABOMB_INCREASE_POWER,
2518     EL_SP_INFOTRON,
2519     EL_SP_DISK_RED,
2520     EL_PEARL,
2521     EL_CRYSTAL,
2522     EL_DC_KEY_WHITE,
2523     EL_SHIELD_NORMAL,
2524     EL_SHIELD_DEADLY,
2525     EL_EXTRA_TIME,
2526     EL_ENVELOPE_1,
2527     EL_ENVELOPE_2,
2528     EL_ENVELOPE_3,
2529     EL_ENVELOPE_4,
2530     EL_SPEED_PILL,
2531     EL_EMC_LENSES,
2532     EL_EMC_MAGNIFIER,
2533
2534 #if 0
2535     // !!! handle separately !!!
2536     EL_DC_LANDMINE,     // deadly when running into, but can be snapped
2537 #endif
2538
2539     -1
2540   };
2541
2542   static int ep_dont_run_into[] =
2543   {
2544     // same elements as in 'ep_dont_touch'
2545     EL_BUG,
2546     EL_SPACESHIP,
2547     EL_BD_BUTTERFLY,
2548     EL_BD_FIREFLY,
2549
2550     // same elements as in 'ep_dont_collide_with'
2551     EL_YAMYAM,
2552     EL_DARK_YAMYAM,
2553     EL_ROBOT,
2554     EL_PACMAN,
2555     EL_SP_SNIKSNAK,
2556     EL_SP_ELECTRON,
2557
2558     // new elements
2559     EL_AMOEBA_DROP,
2560     EL_ACID,
2561
2562     // !!! maybe this should better be handled by 'ep_diggable' !!!
2563 #if 1
2564     EL_LANDMINE,
2565     EL_DC_LANDMINE,
2566     EL_TRAP_ACTIVE,
2567     EL_SP_BUGGY_BASE_ACTIVE,
2568     EL_EMC_PLANT,
2569 #endif
2570
2571     -1
2572   };
2573
2574   static int ep_dont_collide_with[] =
2575   {
2576     // same elements as in 'ep_dont_touch'
2577     EL_BUG,
2578     EL_SPACESHIP,
2579     EL_BD_BUTTERFLY,
2580     EL_BD_FIREFLY,
2581
2582     // new elements
2583     EL_YAMYAM,
2584     EL_DARK_YAMYAM,
2585     EL_ROBOT,
2586     EL_PACMAN,
2587     EL_SP_SNIKSNAK,
2588     EL_SP_ELECTRON,
2589
2590     -1
2591   };
2592
2593   static int ep_dont_touch[] =
2594   {
2595     EL_BUG,
2596     EL_SPACESHIP,
2597     EL_BD_BUTTERFLY,
2598     EL_BD_FIREFLY,
2599
2600     -1
2601   };
2602
2603   static int ep_indestructible[] =
2604   {
2605     EL_STEELWALL,
2606     EL_ACID,
2607     EL_ACID_POOL_TOPLEFT,
2608     EL_ACID_POOL_TOPRIGHT,
2609     EL_ACID_POOL_BOTTOMLEFT,
2610     EL_ACID_POOL_BOTTOM,
2611     EL_ACID_POOL_BOTTOMRIGHT,
2612     EL_SP_HARDWARE_GRAY,
2613     EL_SP_HARDWARE_GREEN,
2614     EL_SP_HARDWARE_BLUE,
2615     EL_SP_HARDWARE_RED,
2616     EL_SP_HARDWARE_YELLOW,
2617     EL_SP_HARDWARE_BASE_1,
2618     EL_SP_HARDWARE_BASE_2,
2619     EL_SP_HARDWARE_BASE_3,
2620     EL_SP_HARDWARE_BASE_4,
2621     EL_SP_HARDWARE_BASE_5,
2622     EL_SP_HARDWARE_BASE_6,
2623     EL_INVISIBLE_STEELWALL,
2624     EL_INVISIBLE_STEELWALL_ACTIVE,
2625     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2626     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2627     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2628     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2629     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2630     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2631     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2632     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2633     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2634     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2635     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2636     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2637     EL_LIGHT_SWITCH,
2638     EL_LIGHT_SWITCH_ACTIVE,
2639     EL_SIGN_EXCLAMATION,
2640     EL_SIGN_RADIOACTIVITY,
2641     EL_SIGN_STOP,
2642     EL_SIGN_WHEELCHAIR,
2643     EL_SIGN_PARKING,
2644     EL_SIGN_NO_ENTRY,
2645     EL_SIGN_UNUSED_1,
2646     EL_SIGN_GIVE_WAY,
2647     EL_SIGN_ENTRY_FORBIDDEN,
2648     EL_SIGN_EMERGENCY_EXIT,
2649     EL_SIGN_YIN_YANG,
2650     EL_SIGN_UNUSED_2,
2651     EL_SIGN_SPERMS,
2652     EL_SIGN_BULLET,
2653     EL_SIGN_HEART,
2654     EL_SIGN_CROSS,
2655     EL_SIGN_FRANKIE,
2656     EL_STEEL_EXIT_CLOSED,
2657     EL_STEEL_EXIT_OPEN,
2658     EL_STEEL_EXIT_OPENING,
2659     EL_STEEL_EXIT_CLOSING,
2660     EL_EM_STEEL_EXIT_CLOSED,
2661     EL_EM_STEEL_EXIT_OPEN,
2662     EL_EM_STEEL_EXIT_OPENING,
2663     EL_EM_STEEL_EXIT_CLOSING,
2664     EL_DC_STEELWALL_1_LEFT,
2665     EL_DC_STEELWALL_1_RIGHT,
2666     EL_DC_STEELWALL_1_TOP,
2667     EL_DC_STEELWALL_1_BOTTOM,
2668     EL_DC_STEELWALL_1_HORIZONTAL,
2669     EL_DC_STEELWALL_1_VERTICAL,
2670     EL_DC_STEELWALL_1_TOPLEFT,
2671     EL_DC_STEELWALL_1_TOPRIGHT,
2672     EL_DC_STEELWALL_1_BOTTOMLEFT,
2673     EL_DC_STEELWALL_1_BOTTOMRIGHT,
2674     EL_DC_STEELWALL_1_TOPLEFT_2,
2675     EL_DC_STEELWALL_1_TOPRIGHT_2,
2676     EL_DC_STEELWALL_1_BOTTOMLEFT_2,
2677     EL_DC_STEELWALL_1_BOTTOMRIGHT_2,
2678     EL_DC_STEELWALL_2_LEFT,
2679     EL_DC_STEELWALL_2_RIGHT,
2680     EL_DC_STEELWALL_2_TOP,
2681     EL_DC_STEELWALL_2_BOTTOM,
2682     EL_DC_STEELWALL_2_HORIZONTAL,
2683     EL_DC_STEELWALL_2_VERTICAL,
2684     EL_DC_STEELWALL_2_MIDDLE,
2685     EL_DC_STEELWALL_2_SINGLE,
2686     EL_STEELWALL_SLIPPERY,
2687     EL_EMC_STEELWALL_1,
2688     EL_EMC_STEELWALL_2,
2689     EL_EMC_STEELWALL_3,
2690     EL_EMC_STEELWALL_4,
2691     EL_CRYSTAL,
2692     EL_GATE_1,
2693     EL_GATE_2,
2694     EL_GATE_3,
2695     EL_GATE_4,
2696     EL_GATE_1_GRAY,
2697     EL_GATE_2_GRAY,
2698     EL_GATE_3_GRAY,
2699     EL_GATE_4_GRAY,
2700     EL_GATE_1_GRAY_ACTIVE,
2701     EL_GATE_2_GRAY_ACTIVE,
2702     EL_GATE_3_GRAY_ACTIVE,
2703     EL_GATE_4_GRAY_ACTIVE,
2704     EL_EM_GATE_1,
2705     EL_EM_GATE_2,
2706     EL_EM_GATE_3,
2707     EL_EM_GATE_4,
2708     EL_EM_GATE_1_GRAY,
2709     EL_EM_GATE_2_GRAY,
2710     EL_EM_GATE_3_GRAY,
2711     EL_EM_GATE_4_GRAY,
2712     EL_EM_GATE_1_GRAY_ACTIVE,
2713     EL_EM_GATE_2_GRAY_ACTIVE,
2714     EL_EM_GATE_3_GRAY_ACTIVE,
2715     EL_EM_GATE_4_GRAY_ACTIVE,
2716     EL_EMC_GATE_5,
2717     EL_EMC_GATE_6,
2718     EL_EMC_GATE_7,
2719     EL_EMC_GATE_8,
2720     EL_EMC_GATE_5_GRAY,
2721     EL_EMC_GATE_6_GRAY,
2722     EL_EMC_GATE_7_GRAY,
2723     EL_EMC_GATE_8_GRAY,
2724     EL_EMC_GATE_5_GRAY_ACTIVE,
2725     EL_EMC_GATE_6_GRAY_ACTIVE,
2726     EL_EMC_GATE_7_GRAY_ACTIVE,
2727     EL_EMC_GATE_8_GRAY_ACTIVE,
2728     EL_DC_GATE_WHITE,
2729     EL_DC_GATE_WHITE_GRAY,
2730     EL_DC_GATE_WHITE_GRAY_ACTIVE,
2731     EL_DC_GATE_FAKE_GRAY,
2732     EL_SWITCHGATE_OPEN,
2733     EL_SWITCHGATE_OPENING,
2734     EL_SWITCHGATE_CLOSED,
2735     EL_SWITCHGATE_CLOSING,
2736     EL_DC_SWITCHGATE_SWITCH_UP,
2737     EL_DC_SWITCHGATE_SWITCH_DOWN,
2738     EL_TIMEGATE_OPEN,
2739     EL_TIMEGATE_OPENING,
2740     EL_TIMEGATE_CLOSED,
2741     EL_TIMEGATE_CLOSING,
2742     EL_DC_TIMEGATE_SWITCH,
2743     EL_DC_TIMEGATE_SWITCH_ACTIVE,
2744     EL_TUBE_ANY,
2745     EL_TUBE_VERTICAL,
2746     EL_TUBE_HORIZONTAL,
2747     EL_TUBE_VERTICAL_LEFT,
2748     EL_TUBE_VERTICAL_RIGHT,
2749     EL_TUBE_HORIZONTAL_UP,
2750     EL_TUBE_HORIZONTAL_DOWN,
2751     EL_TUBE_LEFT_UP,
2752     EL_TUBE_LEFT_DOWN,
2753     EL_TUBE_RIGHT_UP,
2754     EL_TUBE_RIGHT_DOWN,
2755     EL_EXPANDABLE_STEELWALL_HORIZONTAL,
2756     EL_EXPANDABLE_STEELWALL_VERTICAL,
2757     EL_EXPANDABLE_STEELWALL_ANY,
2758
2759     -1
2760   };
2761
2762   static int ep_slippery[] =
2763   {
2764     EL_WALL_SLIPPERY,
2765     EL_BD_WALL,
2766     EL_ROCK,
2767     EL_BD_ROCK,
2768     EL_EMERALD,
2769     EL_BD_DIAMOND,
2770     EL_EMERALD_YELLOW,
2771     EL_EMERALD_RED,
2772     EL_EMERALD_PURPLE,
2773     EL_DIAMOND,
2774     EL_BOMB,
2775     EL_NUT,
2776     EL_ROBOT_WHEEL_ACTIVE,
2777     EL_ROBOT_WHEEL,
2778     EL_TIME_ORB_FULL,
2779     EL_TIME_ORB_EMPTY,
2780     EL_LAMP_ACTIVE,
2781     EL_LAMP,
2782     EL_ACID_POOL_TOPLEFT,
2783     EL_ACID_POOL_TOPRIGHT,
2784     EL_SATELLITE,
2785     EL_SP_ZONK,
2786     EL_SP_INFOTRON,
2787     EL_SP_CHIP_SINGLE,
2788     EL_SP_CHIP_LEFT,
2789     EL_SP_CHIP_RIGHT,
2790     EL_SP_CHIP_TOP,
2791     EL_SP_CHIP_BOTTOM,
2792     EL_SPEED_PILL,
2793     EL_STEELWALL_SLIPPERY,
2794     EL_PEARL,
2795     EL_CRYSTAL,
2796     EL_EMC_WALL_SLIPPERY_1,
2797     EL_EMC_WALL_SLIPPERY_2,
2798     EL_EMC_WALL_SLIPPERY_3,
2799     EL_EMC_WALL_SLIPPERY_4,
2800     EL_EMC_MAGIC_BALL,
2801     EL_EMC_MAGIC_BALL_ACTIVE,
2802
2803     -1
2804   };
2805
2806   static int ep_can_change[] =
2807   {
2808     -1
2809   };
2810
2811   static int ep_can_move[] =
2812   {
2813     // same elements as in 'pb_can_move_into_acid'
2814     EL_BUG,
2815     EL_SPACESHIP,
2816     EL_BD_BUTTERFLY,
2817     EL_BD_FIREFLY,
2818     EL_YAMYAM,
2819     EL_DARK_YAMYAM,
2820     EL_ROBOT,
2821     EL_PACMAN,
2822     EL_MOLE,
2823     EL_PENGUIN,
2824     EL_PIG,
2825     EL_DRAGON,
2826     EL_SATELLITE,
2827     EL_SP_SNIKSNAK,
2828     EL_SP_ELECTRON,
2829     EL_BALLOON,
2830     EL_SPRING,
2831     EL_EMC_ANDROID,
2832
2833     -1
2834   };
2835
2836   static int ep_can_fall[] =
2837   {
2838     EL_ROCK,
2839     EL_BD_ROCK,
2840     EL_EMERALD,
2841     EL_BD_DIAMOND,
2842     EL_EMERALD_YELLOW,
2843     EL_EMERALD_RED,
2844     EL_EMERALD_PURPLE,
2845     EL_DIAMOND,
2846     EL_BOMB,
2847     EL_NUT,
2848     EL_AMOEBA_DROP,
2849     EL_QUICKSAND_FULL,
2850     EL_QUICKSAND_FAST_FULL,
2851     EL_MAGIC_WALL_FULL,
2852     EL_BD_MAGIC_WALL_FULL,
2853     EL_DC_MAGIC_WALL_FULL,
2854     EL_TIME_ORB_FULL,
2855     EL_TIME_ORB_EMPTY,
2856     EL_SP_ZONK,
2857     EL_SP_INFOTRON,
2858     EL_SP_DISK_ORANGE,
2859     EL_PEARL,
2860     EL_CRYSTAL,
2861     EL_SPRING,
2862     EL_DX_SUPABOMB,
2863
2864     -1
2865   };
2866
2867   static int ep_can_smash_player[] =
2868   {
2869     EL_ROCK,
2870     EL_BD_ROCK,
2871     EL_EMERALD,
2872     EL_BD_DIAMOND,
2873     EL_EMERALD_YELLOW,
2874     EL_EMERALD_RED,
2875     EL_EMERALD_PURPLE,
2876     EL_DIAMOND,
2877     EL_BOMB,
2878     EL_NUT,
2879     EL_AMOEBA_DROP,
2880     EL_TIME_ORB_FULL,
2881     EL_TIME_ORB_EMPTY,
2882     EL_SP_ZONK,
2883     EL_SP_INFOTRON,
2884     EL_SP_DISK_ORANGE,
2885     EL_PEARL,
2886     EL_CRYSTAL,
2887     EL_SPRING,
2888     EL_DX_SUPABOMB,
2889
2890     -1
2891   };
2892
2893   static int ep_can_smash_enemies[] =
2894   {
2895     EL_ROCK,
2896     EL_BD_ROCK,
2897     EL_SP_ZONK,
2898
2899     -1
2900   };
2901
2902   static int ep_can_smash_everything[] =
2903   {
2904     EL_ROCK,
2905     EL_BD_ROCK,
2906     EL_SP_ZONK,
2907
2908     -1
2909   };
2910
2911   static int ep_explodes_by_fire[] =
2912   {
2913     // same elements as in 'ep_explodes_impact'
2914     EL_BOMB,
2915     EL_SP_DISK_ORANGE,
2916     EL_DX_SUPABOMB,
2917
2918     // same elements as in 'ep_explodes_smashed'
2919     EL_SATELLITE,
2920     EL_PIG,
2921     EL_DRAGON,
2922     EL_MOLE,
2923
2924     // new elements
2925     EL_DYNAMITE,
2926     EL_DYNAMITE_ACTIVE,
2927     EL_EM_DYNAMITE,
2928     EL_EM_DYNAMITE_ACTIVE,
2929     EL_DYNABOMB_PLAYER_1_ACTIVE,
2930     EL_DYNABOMB_PLAYER_2_ACTIVE,
2931     EL_DYNABOMB_PLAYER_3_ACTIVE,
2932     EL_DYNABOMB_PLAYER_4_ACTIVE,
2933     EL_DYNABOMB_INCREASE_NUMBER,
2934     EL_DYNABOMB_INCREASE_SIZE,
2935     EL_DYNABOMB_INCREASE_POWER,
2936     EL_SP_DISK_RED_ACTIVE,
2937     EL_BUG,
2938     EL_PENGUIN,
2939     EL_SP_DISK_RED,
2940     EL_SP_DISK_YELLOW,
2941     EL_SP_SNIKSNAK,
2942     EL_SP_ELECTRON,
2943 #if 0
2944     EL_BLACK_ORB,
2945 #endif
2946
2947     -1
2948   };
2949
2950   static int ep_explodes_smashed[] =
2951   {
2952     // same elements as in 'ep_explodes_impact'
2953     EL_BOMB,
2954     EL_SP_DISK_ORANGE,
2955     EL_DX_SUPABOMB,
2956
2957     // new elements
2958     EL_SATELLITE,
2959     EL_PIG,
2960     EL_DRAGON,
2961     EL_MOLE,
2962
2963     -1
2964   };
2965
2966   static int ep_explodes_impact[] =
2967   {
2968     EL_BOMB,
2969     EL_SP_DISK_ORANGE,
2970     EL_DX_SUPABOMB,
2971
2972     -1
2973   };
2974
2975   static int ep_walkable_over[] =
2976   {
2977     EL_EMPTY_SPACE,
2978     EL_SP_EMPTY_SPACE,
2979     EL_SOKOBAN_FIELD_EMPTY,
2980     EL_EXIT_OPEN,
2981     EL_EM_EXIT_OPEN,
2982     EL_EM_EXIT_OPENING,
2983     EL_SP_EXIT_OPEN,
2984     EL_SP_EXIT_OPENING,
2985     EL_STEEL_EXIT_OPEN,
2986     EL_EM_STEEL_EXIT_OPEN,
2987     EL_EM_STEEL_EXIT_OPENING,
2988     EL_GATE_1,
2989     EL_GATE_2,
2990     EL_GATE_3,
2991     EL_GATE_4,
2992     EL_GATE_1_GRAY,
2993     EL_GATE_2_GRAY,
2994     EL_GATE_3_GRAY,
2995     EL_GATE_4_GRAY,
2996     EL_GATE_1_GRAY_ACTIVE,
2997     EL_GATE_2_GRAY_ACTIVE,
2998     EL_GATE_3_GRAY_ACTIVE,
2999     EL_GATE_4_GRAY_ACTIVE,
3000     EL_PENGUIN,
3001     EL_PIG,
3002     EL_DRAGON,
3003
3004     -1
3005   };
3006
3007   static int ep_walkable_inside[] =
3008   {
3009     EL_TUBE_ANY,
3010     EL_TUBE_VERTICAL,
3011     EL_TUBE_HORIZONTAL,
3012     EL_TUBE_VERTICAL_LEFT,
3013     EL_TUBE_VERTICAL_RIGHT,
3014     EL_TUBE_HORIZONTAL_UP,
3015     EL_TUBE_HORIZONTAL_DOWN,
3016     EL_TUBE_LEFT_UP,
3017     EL_TUBE_LEFT_DOWN,
3018     EL_TUBE_RIGHT_UP,
3019     EL_TUBE_RIGHT_DOWN,
3020
3021     -1
3022   };
3023
3024   static int ep_walkable_under[] =
3025   {
3026     -1
3027   };
3028
3029   static int ep_passable_over[] =
3030   {
3031     EL_EM_GATE_1,
3032     EL_EM_GATE_2,
3033     EL_EM_GATE_3,
3034     EL_EM_GATE_4,
3035     EL_EM_GATE_1_GRAY,
3036     EL_EM_GATE_2_GRAY,
3037     EL_EM_GATE_3_GRAY,
3038     EL_EM_GATE_4_GRAY,
3039     EL_EM_GATE_1_GRAY_ACTIVE,
3040     EL_EM_GATE_2_GRAY_ACTIVE,
3041     EL_EM_GATE_3_GRAY_ACTIVE,
3042     EL_EM_GATE_4_GRAY_ACTIVE,
3043     EL_EMC_GATE_5,
3044     EL_EMC_GATE_6,
3045     EL_EMC_GATE_7,
3046     EL_EMC_GATE_8,
3047     EL_EMC_GATE_5_GRAY,
3048     EL_EMC_GATE_6_GRAY,
3049     EL_EMC_GATE_7_GRAY,
3050     EL_EMC_GATE_8_GRAY,
3051     EL_EMC_GATE_5_GRAY_ACTIVE,
3052     EL_EMC_GATE_6_GRAY_ACTIVE,
3053     EL_EMC_GATE_7_GRAY_ACTIVE,
3054     EL_EMC_GATE_8_GRAY_ACTIVE,
3055     EL_DC_GATE_WHITE,
3056     EL_DC_GATE_WHITE_GRAY,
3057     EL_DC_GATE_WHITE_GRAY_ACTIVE,
3058     EL_SWITCHGATE_OPEN,
3059     EL_TIMEGATE_OPEN,
3060
3061     -1
3062   };
3063
3064   static int ep_passable_inside[] =
3065   {
3066     EL_SP_PORT_LEFT,
3067     EL_SP_PORT_RIGHT,
3068     EL_SP_PORT_UP,
3069     EL_SP_PORT_DOWN,
3070     EL_SP_PORT_HORIZONTAL,
3071     EL_SP_PORT_VERTICAL,
3072     EL_SP_PORT_ANY,
3073     EL_SP_GRAVITY_PORT_LEFT,
3074     EL_SP_GRAVITY_PORT_RIGHT,
3075     EL_SP_GRAVITY_PORT_UP,
3076     EL_SP_GRAVITY_PORT_DOWN,
3077     EL_SP_GRAVITY_ON_PORT_LEFT,
3078     EL_SP_GRAVITY_ON_PORT_RIGHT,
3079     EL_SP_GRAVITY_ON_PORT_UP,
3080     EL_SP_GRAVITY_ON_PORT_DOWN,
3081     EL_SP_GRAVITY_OFF_PORT_LEFT,
3082     EL_SP_GRAVITY_OFF_PORT_RIGHT,
3083     EL_SP_GRAVITY_OFF_PORT_UP,
3084     EL_SP_GRAVITY_OFF_PORT_DOWN,
3085
3086     -1
3087   };
3088
3089   static int ep_passable_under[] =
3090   {
3091     -1
3092   };
3093
3094   static int ep_droppable[] =
3095   {
3096     -1
3097   };
3098
3099   static int ep_explodes_1x1_old[] =
3100   {
3101     -1
3102   };
3103
3104   static int ep_pushable[] =
3105   {
3106     EL_ROCK,
3107     EL_BOMB,
3108     EL_DX_SUPABOMB,
3109     EL_NUT,
3110     EL_TIME_ORB_EMPTY,
3111     EL_SP_ZONK,
3112     EL_SP_DISK_ORANGE,
3113     EL_SPRING,
3114     EL_BD_ROCK,
3115     EL_SOKOBAN_OBJECT,
3116     EL_SOKOBAN_FIELD_FULL,
3117     EL_SATELLITE,
3118     EL_SP_DISK_YELLOW,
3119     EL_BALLOON,
3120     EL_EMC_ANDROID,
3121
3122     -1
3123   };
3124
3125   static int ep_explodes_cross_old[] =
3126   {
3127     -1
3128   };
3129
3130   static int ep_protected[] =
3131   {
3132     // same elements as in 'ep_walkable_inside'
3133     EL_TUBE_ANY,
3134     EL_TUBE_VERTICAL,
3135     EL_TUBE_HORIZONTAL,
3136     EL_TUBE_VERTICAL_LEFT,
3137     EL_TUBE_VERTICAL_RIGHT,
3138     EL_TUBE_HORIZONTAL_UP,
3139     EL_TUBE_HORIZONTAL_DOWN,
3140     EL_TUBE_LEFT_UP,
3141     EL_TUBE_LEFT_DOWN,
3142     EL_TUBE_RIGHT_UP,
3143     EL_TUBE_RIGHT_DOWN,
3144
3145     // same elements as in 'ep_passable_over'
3146     EL_EM_GATE_1,
3147     EL_EM_GATE_2,
3148     EL_EM_GATE_3,
3149     EL_EM_GATE_4,
3150     EL_EM_GATE_1_GRAY,
3151     EL_EM_GATE_2_GRAY,
3152     EL_EM_GATE_3_GRAY,
3153     EL_EM_GATE_4_GRAY,
3154     EL_EM_GATE_1_GRAY_ACTIVE,
3155     EL_EM_GATE_2_GRAY_ACTIVE,
3156     EL_EM_GATE_3_GRAY_ACTIVE,
3157     EL_EM_GATE_4_GRAY_ACTIVE,
3158     EL_EMC_GATE_5,
3159     EL_EMC_GATE_6,
3160     EL_EMC_GATE_7,
3161     EL_EMC_GATE_8,
3162     EL_EMC_GATE_5_GRAY,
3163     EL_EMC_GATE_6_GRAY,
3164     EL_EMC_GATE_7_GRAY,
3165     EL_EMC_GATE_8_GRAY,
3166     EL_EMC_GATE_5_GRAY_ACTIVE,
3167     EL_EMC_GATE_6_GRAY_ACTIVE,
3168     EL_EMC_GATE_7_GRAY_ACTIVE,
3169     EL_EMC_GATE_8_GRAY_ACTIVE,
3170     EL_DC_GATE_WHITE,
3171     EL_DC_GATE_WHITE_GRAY,
3172     EL_DC_GATE_WHITE_GRAY_ACTIVE,
3173     EL_SWITCHGATE_OPEN,
3174     EL_TIMEGATE_OPEN,
3175
3176     // same elements as in 'ep_passable_inside'
3177     EL_SP_PORT_LEFT,
3178     EL_SP_PORT_RIGHT,
3179     EL_SP_PORT_UP,
3180     EL_SP_PORT_DOWN,
3181     EL_SP_PORT_HORIZONTAL,
3182     EL_SP_PORT_VERTICAL,
3183     EL_SP_PORT_ANY,
3184     EL_SP_GRAVITY_PORT_LEFT,
3185     EL_SP_GRAVITY_PORT_RIGHT,
3186     EL_SP_GRAVITY_PORT_UP,
3187     EL_SP_GRAVITY_PORT_DOWN,
3188     EL_SP_GRAVITY_ON_PORT_LEFT,
3189     EL_SP_GRAVITY_ON_PORT_RIGHT,
3190     EL_SP_GRAVITY_ON_PORT_UP,
3191     EL_SP_GRAVITY_ON_PORT_DOWN,
3192     EL_SP_GRAVITY_OFF_PORT_LEFT,
3193     EL_SP_GRAVITY_OFF_PORT_RIGHT,
3194     EL_SP_GRAVITY_OFF_PORT_UP,
3195     EL_SP_GRAVITY_OFF_PORT_DOWN,
3196
3197     -1
3198   };
3199
3200   static int ep_throwable[] =
3201   {
3202     -1
3203   };
3204
3205   static int ep_can_explode[] =
3206   {
3207     // same elements as in 'ep_explodes_impact'
3208     EL_BOMB,
3209     EL_SP_DISK_ORANGE,
3210     EL_DX_SUPABOMB,
3211
3212     // same elements as in 'ep_explodes_smashed'
3213     EL_SATELLITE,
3214     EL_PIG,
3215     EL_DRAGON,
3216     EL_MOLE,
3217
3218     // elements that can explode by explosion or by dragonfire
3219     EL_DYNAMITE,
3220     EL_DYNAMITE_ACTIVE,
3221     EL_EM_DYNAMITE,
3222     EL_EM_DYNAMITE_ACTIVE,
3223     EL_DYNABOMB_PLAYER_1_ACTIVE,
3224     EL_DYNABOMB_PLAYER_2_ACTIVE,
3225     EL_DYNABOMB_PLAYER_3_ACTIVE,
3226     EL_DYNABOMB_PLAYER_4_ACTIVE,
3227     EL_DYNABOMB_INCREASE_NUMBER,
3228     EL_DYNABOMB_INCREASE_SIZE,
3229     EL_DYNABOMB_INCREASE_POWER,
3230     EL_SP_DISK_RED_ACTIVE,
3231     EL_BUG,
3232     EL_PENGUIN,
3233     EL_SP_DISK_RED,
3234     EL_SP_DISK_YELLOW,
3235     EL_SP_SNIKSNAK,
3236     EL_SP_ELECTRON,
3237
3238     // elements that can explode only by explosion
3239     EL_BLACK_ORB,
3240
3241     -1
3242   };
3243
3244   static int ep_gravity_reachable[] =
3245   {
3246     EL_SAND,
3247     EL_SP_BASE,
3248     EL_TRAP,
3249     EL_INVISIBLE_SAND,
3250     EL_INVISIBLE_SAND_ACTIVE,
3251     EL_SP_PORT_LEFT,
3252     EL_SP_PORT_RIGHT,
3253     EL_SP_PORT_UP,
3254     EL_SP_PORT_DOWN,
3255     EL_SP_PORT_HORIZONTAL,
3256     EL_SP_PORT_VERTICAL,
3257     EL_SP_PORT_ANY,
3258     EL_SP_GRAVITY_PORT_LEFT,
3259     EL_SP_GRAVITY_PORT_RIGHT,
3260     EL_SP_GRAVITY_PORT_UP,
3261     EL_SP_GRAVITY_PORT_DOWN,
3262     EL_SP_GRAVITY_ON_PORT_LEFT,
3263     EL_SP_GRAVITY_ON_PORT_RIGHT,
3264     EL_SP_GRAVITY_ON_PORT_UP,
3265     EL_SP_GRAVITY_ON_PORT_DOWN,
3266     EL_SP_GRAVITY_OFF_PORT_LEFT,
3267     EL_SP_GRAVITY_OFF_PORT_RIGHT,
3268     EL_SP_GRAVITY_OFF_PORT_UP,
3269     EL_SP_GRAVITY_OFF_PORT_DOWN,
3270     EL_EMC_GRASS,
3271
3272     -1
3273   };
3274
3275   static int ep_player[] =
3276   {
3277     EL_PLAYER_1,
3278     EL_PLAYER_2,
3279     EL_PLAYER_3,
3280     EL_PLAYER_4,
3281     EL_SP_MURPHY,
3282     EL_SOKOBAN_FIELD_PLAYER,
3283     EL_TRIGGER_PLAYER,
3284
3285     -1
3286   };
3287
3288   static int ep_can_pass_magic_wall[] =
3289   {
3290     EL_ROCK,
3291     EL_BD_ROCK,
3292     EL_EMERALD,
3293     EL_BD_DIAMOND,
3294     EL_EMERALD_YELLOW,
3295     EL_EMERALD_RED,
3296     EL_EMERALD_PURPLE,
3297     EL_DIAMOND,
3298
3299     -1
3300   };
3301
3302   static int ep_can_pass_dc_magic_wall[] =
3303   {
3304     EL_ROCK,
3305     EL_BD_ROCK,
3306     EL_EMERALD,
3307     EL_BD_DIAMOND,
3308     EL_EMERALD_YELLOW,
3309     EL_EMERALD_RED,
3310     EL_EMERALD_PURPLE,
3311     EL_DIAMOND,
3312     EL_PEARL,
3313     EL_CRYSTAL,
3314
3315     -1
3316   };
3317
3318   static int ep_switchable[] =
3319   {
3320     EL_ROBOT_WHEEL,
3321     EL_SP_TERMINAL,
3322     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3323     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3324     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3325     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3326     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3327     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3328     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3329     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3330     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3331     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3332     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3333     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3334     EL_SWITCHGATE_SWITCH_UP,
3335     EL_SWITCHGATE_SWITCH_DOWN,
3336     EL_DC_SWITCHGATE_SWITCH_UP,
3337     EL_DC_SWITCHGATE_SWITCH_DOWN,
3338     EL_LIGHT_SWITCH,
3339     EL_LIGHT_SWITCH_ACTIVE,
3340     EL_TIMEGATE_SWITCH,
3341     EL_DC_TIMEGATE_SWITCH,
3342     EL_BALLOON_SWITCH_LEFT,
3343     EL_BALLOON_SWITCH_RIGHT,
3344     EL_BALLOON_SWITCH_UP,
3345     EL_BALLOON_SWITCH_DOWN,
3346     EL_BALLOON_SWITCH_ANY,
3347     EL_BALLOON_SWITCH_NONE,
3348     EL_LAMP,
3349     EL_TIME_ORB_FULL,
3350     EL_EMC_MAGIC_BALL_SWITCH,
3351     EL_EMC_MAGIC_BALL_SWITCH_ACTIVE,
3352
3353     -1
3354   };
3355
3356   static int ep_bd_element[] =
3357   {
3358     EL_EMPTY,
3359     EL_SAND,
3360     EL_WALL_SLIPPERY,
3361     EL_BD_WALL,
3362     EL_ROCK,
3363     EL_BD_ROCK,
3364     EL_BD_DIAMOND,
3365     EL_BD_MAGIC_WALL,
3366     EL_EXIT_CLOSED,
3367     EL_EXIT_OPEN,
3368     EL_STEELWALL,
3369     EL_PLAYER_1,
3370     EL_PLAYER_2,
3371     EL_PLAYER_3,
3372     EL_PLAYER_4,
3373     EL_BD_FIREFLY,
3374     EL_BD_FIREFLY_1,
3375     EL_BD_FIREFLY_2,
3376     EL_BD_FIREFLY_3,
3377     EL_BD_FIREFLY_4,
3378     EL_BD_BUTTERFLY,
3379     EL_BD_BUTTERFLY_1,
3380     EL_BD_BUTTERFLY_2,
3381     EL_BD_BUTTERFLY_3,
3382     EL_BD_BUTTERFLY_4,
3383     EL_BD_AMOEBA,
3384     EL_CHAR_QUESTION,
3385     EL_UNKNOWN,
3386
3387     -1
3388   };
3389
3390   static int ep_sp_element[] =
3391   {
3392     // should always be valid
3393     EL_EMPTY,
3394
3395     // standard classic Supaplex elements
3396     EL_SP_EMPTY,
3397     EL_SP_ZONK,
3398     EL_SP_BASE,
3399     EL_SP_MURPHY,
3400     EL_SP_INFOTRON,
3401     EL_SP_CHIP_SINGLE,
3402     EL_SP_HARDWARE_GRAY,
3403     EL_SP_EXIT_CLOSED,
3404     EL_SP_EXIT_OPEN,
3405     EL_SP_DISK_ORANGE,
3406     EL_SP_PORT_RIGHT,
3407     EL_SP_PORT_DOWN,
3408     EL_SP_PORT_LEFT,
3409     EL_SP_PORT_UP,
3410     EL_SP_GRAVITY_PORT_RIGHT,
3411     EL_SP_GRAVITY_PORT_DOWN,
3412     EL_SP_GRAVITY_PORT_LEFT,
3413     EL_SP_GRAVITY_PORT_UP,
3414     EL_SP_SNIKSNAK,
3415     EL_SP_DISK_YELLOW,
3416     EL_SP_TERMINAL,
3417     EL_SP_DISK_RED,
3418     EL_SP_PORT_VERTICAL,
3419     EL_SP_PORT_HORIZONTAL,
3420     EL_SP_PORT_ANY,
3421     EL_SP_ELECTRON,
3422     EL_SP_BUGGY_BASE,
3423     EL_SP_CHIP_LEFT,
3424     EL_SP_CHIP_RIGHT,
3425     EL_SP_HARDWARE_BASE_1,
3426     EL_SP_HARDWARE_GREEN,
3427     EL_SP_HARDWARE_BLUE,
3428     EL_SP_HARDWARE_RED,
3429     EL_SP_HARDWARE_YELLOW,
3430     EL_SP_HARDWARE_BASE_2,
3431     EL_SP_HARDWARE_BASE_3,
3432     EL_SP_HARDWARE_BASE_4,
3433     EL_SP_HARDWARE_BASE_5,
3434     EL_SP_HARDWARE_BASE_6,
3435     EL_SP_CHIP_TOP,
3436     EL_SP_CHIP_BOTTOM,
3437
3438     // additional elements that appeared in newer Supaplex levels
3439     EL_INVISIBLE_WALL,
3440
3441     // additional gravity port elements (not switching, but setting gravity)
3442     EL_SP_GRAVITY_ON_PORT_LEFT,
3443     EL_SP_GRAVITY_ON_PORT_RIGHT,
3444     EL_SP_GRAVITY_ON_PORT_UP,
3445     EL_SP_GRAVITY_ON_PORT_DOWN,
3446     EL_SP_GRAVITY_OFF_PORT_LEFT,
3447     EL_SP_GRAVITY_OFF_PORT_RIGHT,
3448     EL_SP_GRAVITY_OFF_PORT_UP,
3449     EL_SP_GRAVITY_OFF_PORT_DOWN,
3450
3451     // more than one Murphy in a level results in an inactive clone
3452     EL_SP_MURPHY_CLONE,
3453
3454     // runtime Supaplex elements
3455     EL_SP_DISK_RED_ACTIVE,
3456     EL_SP_TERMINAL_ACTIVE,
3457     EL_SP_BUGGY_BASE_ACTIVATING,
3458     EL_SP_BUGGY_BASE_ACTIVE,
3459     EL_SP_EXIT_OPENING,
3460     EL_SP_EXIT_CLOSING,
3461
3462     -1
3463   };
3464
3465   static int ep_sb_element[] =
3466   {
3467     EL_EMPTY,
3468     EL_STEELWALL,
3469     EL_SOKOBAN_OBJECT,
3470     EL_SOKOBAN_FIELD_EMPTY,
3471     EL_SOKOBAN_FIELD_FULL,
3472     EL_SOKOBAN_FIELD_PLAYER,
3473     EL_PLAYER_1,
3474     EL_PLAYER_2,
3475     EL_PLAYER_3,
3476     EL_PLAYER_4,
3477     EL_INVISIBLE_STEELWALL,
3478
3479     -1
3480   };
3481
3482   static int ep_gem[] =
3483   {
3484     EL_BD_DIAMOND,
3485     EL_EMERALD,
3486     EL_EMERALD_YELLOW,
3487     EL_EMERALD_RED,
3488     EL_EMERALD_PURPLE,
3489     EL_DIAMOND,
3490
3491     -1
3492   };
3493
3494   static int ep_food_dark_yamyam[] =
3495   {
3496     EL_SAND,
3497     EL_BUG,
3498     EL_SPACESHIP,
3499     EL_BD_BUTTERFLY,
3500     EL_BD_FIREFLY,
3501     EL_YAMYAM,
3502     EL_ROBOT,
3503     EL_PACMAN,
3504     EL_AMOEBA_DROP,
3505     EL_AMOEBA_DEAD,
3506     EL_AMOEBA_WET,
3507     EL_AMOEBA_DRY,
3508     EL_AMOEBA_FULL,
3509     EL_BD_AMOEBA,
3510     EL_EMERALD,
3511     EL_BD_DIAMOND,
3512     EL_EMERALD_YELLOW,
3513     EL_EMERALD_RED,
3514     EL_EMERALD_PURPLE,
3515     EL_DIAMOND,
3516     EL_PEARL,
3517     EL_CRYSTAL,
3518
3519     -1
3520   };
3521
3522   static int ep_food_penguin[] =
3523   {
3524     EL_EMERALD,
3525     EL_BD_DIAMOND,
3526     EL_EMERALD_YELLOW,
3527     EL_EMERALD_RED,
3528     EL_EMERALD_PURPLE,
3529     EL_DIAMOND,
3530     EL_PEARL,
3531     EL_CRYSTAL,
3532
3533     -1
3534   };
3535
3536   static int ep_food_pig[] =
3537   {
3538     EL_EMERALD,
3539     EL_BD_DIAMOND,
3540     EL_EMERALD_YELLOW,
3541     EL_EMERALD_RED,
3542     EL_EMERALD_PURPLE,
3543     EL_DIAMOND,
3544
3545     -1
3546   };
3547
3548   static int ep_historic_wall[] =
3549   {
3550     EL_STEELWALL,
3551     EL_GATE_1,
3552     EL_GATE_2,
3553     EL_GATE_3,
3554     EL_GATE_4,
3555     EL_GATE_1_GRAY,
3556     EL_GATE_2_GRAY,
3557     EL_GATE_3_GRAY,
3558     EL_GATE_4_GRAY,
3559     EL_GATE_1_GRAY_ACTIVE,
3560     EL_GATE_2_GRAY_ACTIVE,
3561     EL_GATE_3_GRAY_ACTIVE,
3562     EL_GATE_4_GRAY_ACTIVE,
3563     EL_EM_GATE_1,
3564     EL_EM_GATE_2,
3565     EL_EM_GATE_3,
3566     EL_EM_GATE_4,
3567     EL_EM_GATE_1_GRAY,
3568     EL_EM_GATE_2_GRAY,
3569     EL_EM_GATE_3_GRAY,
3570     EL_EM_GATE_4_GRAY,
3571     EL_EM_GATE_1_GRAY_ACTIVE,
3572     EL_EM_GATE_2_GRAY_ACTIVE,
3573     EL_EM_GATE_3_GRAY_ACTIVE,
3574     EL_EM_GATE_4_GRAY_ACTIVE,
3575     EL_EXIT_CLOSED,
3576     EL_EXIT_OPENING,
3577     EL_EXIT_OPEN,
3578     EL_WALL,
3579     EL_WALL_SLIPPERY,
3580     EL_EXPANDABLE_WALL,
3581     EL_EXPANDABLE_WALL_HORIZONTAL,
3582     EL_EXPANDABLE_WALL_VERTICAL,
3583     EL_EXPANDABLE_WALL_ANY,
3584     EL_EXPANDABLE_WALL_GROWING,
3585     EL_BD_EXPANDABLE_WALL,
3586     EL_BD_WALL,
3587     EL_SP_CHIP_SINGLE,
3588     EL_SP_CHIP_LEFT,
3589     EL_SP_CHIP_RIGHT,
3590     EL_SP_CHIP_TOP,
3591     EL_SP_CHIP_BOTTOM,
3592     EL_SP_HARDWARE_GRAY,
3593     EL_SP_HARDWARE_GREEN,
3594     EL_SP_HARDWARE_BLUE,
3595     EL_SP_HARDWARE_RED,
3596     EL_SP_HARDWARE_YELLOW,
3597     EL_SP_HARDWARE_BASE_1,
3598     EL_SP_HARDWARE_BASE_2,
3599     EL_SP_HARDWARE_BASE_3,
3600     EL_SP_HARDWARE_BASE_4,
3601     EL_SP_HARDWARE_BASE_5,
3602     EL_SP_HARDWARE_BASE_6,
3603     EL_SP_TERMINAL,
3604     EL_SP_TERMINAL_ACTIVE,
3605     EL_SP_EXIT_CLOSED,
3606     EL_SP_EXIT_OPEN,
3607     EL_INVISIBLE_STEELWALL,
3608     EL_INVISIBLE_STEELWALL_ACTIVE,
3609     EL_INVISIBLE_WALL,
3610     EL_INVISIBLE_WALL_ACTIVE,
3611     EL_STEELWALL_SLIPPERY,
3612     EL_EMC_STEELWALL_1,
3613     EL_EMC_STEELWALL_2,
3614     EL_EMC_STEELWALL_3,
3615     EL_EMC_STEELWALL_4,
3616     EL_EMC_WALL_1,
3617     EL_EMC_WALL_2,
3618     EL_EMC_WALL_3,
3619     EL_EMC_WALL_4,
3620     EL_EMC_WALL_5,
3621     EL_EMC_WALL_6,
3622     EL_EMC_WALL_7,
3623     EL_EMC_WALL_8,
3624
3625     -1
3626   };
3627
3628   static int ep_historic_solid[] =
3629   {
3630     EL_WALL,
3631     EL_EXPANDABLE_WALL,
3632     EL_EXPANDABLE_WALL_HORIZONTAL,
3633     EL_EXPANDABLE_WALL_VERTICAL,
3634     EL_EXPANDABLE_WALL_ANY,
3635     EL_BD_EXPANDABLE_WALL,
3636     EL_BD_WALL,
3637     EL_WALL_SLIPPERY,
3638     EL_EXIT_CLOSED,
3639     EL_EXIT_OPENING,
3640     EL_EXIT_OPEN,
3641     EL_AMOEBA_DEAD,
3642     EL_AMOEBA_WET,
3643     EL_AMOEBA_DRY,
3644     EL_AMOEBA_FULL,
3645     EL_BD_AMOEBA,
3646     EL_QUICKSAND_EMPTY,
3647     EL_QUICKSAND_FULL,
3648     EL_QUICKSAND_FILLING,
3649     EL_QUICKSAND_EMPTYING,
3650     EL_MAGIC_WALL,
3651     EL_MAGIC_WALL_ACTIVE,
3652     EL_MAGIC_WALL_EMPTYING,
3653     EL_MAGIC_WALL_FILLING,
3654     EL_MAGIC_WALL_FULL,
3655     EL_MAGIC_WALL_DEAD,
3656     EL_BD_MAGIC_WALL,
3657     EL_BD_MAGIC_WALL_ACTIVE,
3658     EL_BD_MAGIC_WALL_EMPTYING,
3659     EL_BD_MAGIC_WALL_FULL,
3660     EL_BD_MAGIC_WALL_FILLING,
3661     EL_BD_MAGIC_WALL_DEAD,
3662     EL_GAME_OF_LIFE,
3663     EL_BIOMAZE,
3664     EL_SP_CHIP_SINGLE,
3665     EL_SP_CHIP_LEFT,
3666     EL_SP_CHIP_RIGHT,
3667     EL_SP_CHIP_TOP,
3668     EL_SP_CHIP_BOTTOM,
3669     EL_SP_TERMINAL,
3670     EL_SP_TERMINAL_ACTIVE,
3671     EL_SP_EXIT_CLOSED,
3672     EL_SP_EXIT_OPEN,
3673     EL_INVISIBLE_WALL,
3674     EL_INVISIBLE_WALL_ACTIVE,
3675     EL_SWITCHGATE_SWITCH_UP,
3676     EL_SWITCHGATE_SWITCH_DOWN,
3677     EL_TIMEGATE_SWITCH,
3678     EL_TIMEGATE_SWITCH_ACTIVE,
3679     EL_EMC_WALL_1,
3680     EL_EMC_WALL_2,
3681     EL_EMC_WALL_3,
3682     EL_EMC_WALL_4,
3683     EL_EMC_WALL_5,
3684     EL_EMC_WALL_6,
3685     EL_EMC_WALL_7,
3686     EL_EMC_WALL_8,
3687     EL_WALL_PEARL,
3688     EL_WALL_CRYSTAL,
3689
3690     // the following elements are a direct copy of "indestructible" elements,
3691     // except "EL_ACID", which is "indestructible", but not "solid"!
3692 #if 0
3693     EL_ACID,
3694 #endif
3695     EL_STEELWALL,
3696     EL_ACID_POOL_TOPLEFT,
3697     EL_ACID_POOL_TOPRIGHT,
3698     EL_ACID_POOL_BOTTOMLEFT,
3699     EL_ACID_POOL_BOTTOM,
3700     EL_ACID_POOL_BOTTOMRIGHT,
3701     EL_SP_HARDWARE_GRAY,
3702     EL_SP_HARDWARE_GREEN,
3703     EL_SP_HARDWARE_BLUE,
3704     EL_SP_HARDWARE_RED,
3705     EL_SP_HARDWARE_YELLOW,
3706     EL_SP_HARDWARE_BASE_1,
3707     EL_SP_HARDWARE_BASE_2,
3708     EL_SP_HARDWARE_BASE_3,
3709     EL_SP_HARDWARE_BASE_4,
3710     EL_SP_HARDWARE_BASE_5,
3711     EL_SP_HARDWARE_BASE_6,
3712     EL_INVISIBLE_STEELWALL,
3713     EL_INVISIBLE_STEELWALL_ACTIVE,
3714     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3715     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3716     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3717     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3718     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3719     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3720     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3721     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3722     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3723     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3724     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3725     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3726     EL_LIGHT_SWITCH,
3727     EL_LIGHT_SWITCH_ACTIVE,
3728     EL_SIGN_EXCLAMATION,
3729     EL_SIGN_RADIOACTIVITY,
3730     EL_SIGN_STOP,
3731     EL_SIGN_WHEELCHAIR,
3732     EL_SIGN_PARKING,
3733     EL_SIGN_NO_ENTRY,
3734     EL_SIGN_UNUSED_1,
3735     EL_SIGN_GIVE_WAY,
3736     EL_SIGN_ENTRY_FORBIDDEN,
3737     EL_SIGN_EMERGENCY_EXIT,
3738     EL_SIGN_YIN_YANG,
3739     EL_SIGN_UNUSED_2,
3740     EL_SIGN_SPERMS,
3741     EL_SIGN_BULLET,
3742     EL_SIGN_HEART,
3743     EL_SIGN_CROSS,
3744     EL_SIGN_FRANKIE,
3745     EL_STEEL_EXIT_CLOSED,
3746     EL_STEEL_EXIT_OPEN,
3747     EL_STEEL_EXIT_OPENING,
3748     EL_STEEL_EXIT_CLOSING,
3749     EL_EM_STEEL_EXIT_CLOSED,
3750     EL_EM_STEEL_EXIT_OPEN,
3751     EL_EM_STEEL_EXIT_OPENING,
3752     EL_EM_STEEL_EXIT_CLOSING,
3753     EL_DC_STEELWALL_1_LEFT,
3754     EL_DC_STEELWALL_1_RIGHT,
3755     EL_DC_STEELWALL_1_TOP,
3756     EL_DC_STEELWALL_1_BOTTOM,
3757     EL_DC_STEELWALL_1_HORIZONTAL,
3758     EL_DC_STEELWALL_1_VERTICAL,
3759     EL_DC_STEELWALL_1_TOPLEFT,
3760     EL_DC_STEELWALL_1_TOPRIGHT,
3761     EL_DC_STEELWALL_1_BOTTOMLEFT,
3762     EL_DC_STEELWALL_1_BOTTOMRIGHT,
3763     EL_DC_STEELWALL_1_TOPLEFT_2,
3764     EL_DC_STEELWALL_1_TOPRIGHT_2,
3765     EL_DC_STEELWALL_1_BOTTOMLEFT_2,
3766     EL_DC_STEELWALL_1_BOTTOMRIGHT_2,
3767     EL_DC_STEELWALL_2_LEFT,
3768     EL_DC_STEELWALL_2_RIGHT,
3769     EL_DC_STEELWALL_2_TOP,
3770     EL_DC_STEELWALL_2_BOTTOM,
3771     EL_DC_STEELWALL_2_HORIZONTAL,
3772     EL_DC_STEELWALL_2_VERTICAL,
3773     EL_DC_STEELWALL_2_MIDDLE,
3774     EL_DC_STEELWALL_2_SINGLE,
3775     EL_STEELWALL_SLIPPERY,
3776     EL_EMC_STEELWALL_1,
3777     EL_EMC_STEELWALL_2,
3778     EL_EMC_STEELWALL_3,
3779     EL_EMC_STEELWALL_4,
3780     EL_CRYSTAL,
3781     EL_GATE_1,
3782     EL_GATE_2,
3783     EL_GATE_3,
3784     EL_GATE_4,
3785     EL_GATE_1_GRAY,
3786     EL_GATE_2_GRAY,
3787     EL_GATE_3_GRAY,
3788     EL_GATE_4_GRAY,
3789     EL_GATE_1_GRAY_ACTIVE,
3790     EL_GATE_2_GRAY_ACTIVE,
3791     EL_GATE_3_GRAY_ACTIVE,
3792     EL_GATE_4_GRAY_ACTIVE,
3793     EL_EM_GATE_1,
3794     EL_EM_GATE_2,
3795     EL_EM_GATE_3,
3796     EL_EM_GATE_4,
3797     EL_EM_GATE_1_GRAY,
3798     EL_EM_GATE_2_GRAY,
3799     EL_EM_GATE_3_GRAY,
3800     EL_EM_GATE_4_GRAY,
3801     EL_EM_GATE_1_GRAY_ACTIVE,
3802     EL_EM_GATE_2_GRAY_ACTIVE,
3803     EL_EM_GATE_3_GRAY_ACTIVE,
3804     EL_EM_GATE_4_GRAY_ACTIVE,
3805     EL_EMC_GATE_5,
3806     EL_EMC_GATE_6,
3807     EL_EMC_GATE_7,
3808     EL_EMC_GATE_8,
3809     EL_EMC_GATE_5_GRAY,
3810     EL_EMC_GATE_6_GRAY,
3811     EL_EMC_GATE_7_GRAY,
3812     EL_EMC_GATE_8_GRAY,
3813     EL_EMC_GATE_5_GRAY_ACTIVE,
3814     EL_EMC_GATE_6_GRAY_ACTIVE,
3815     EL_EMC_GATE_7_GRAY_ACTIVE,
3816     EL_EMC_GATE_8_GRAY_ACTIVE,
3817     EL_DC_GATE_WHITE,
3818     EL_DC_GATE_WHITE_GRAY,
3819     EL_DC_GATE_WHITE_GRAY_ACTIVE,
3820     EL_DC_GATE_FAKE_GRAY,
3821     EL_SWITCHGATE_OPEN,
3822     EL_SWITCHGATE_OPENING,
3823     EL_SWITCHGATE_CLOSED,
3824     EL_SWITCHGATE_CLOSING,
3825     EL_DC_SWITCHGATE_SWITCH_UP,
3826     EL_DC_SWITCHGATE_SWITCH_DOWN,
3827     EL_TIMEGATE_OPEN,
3828     EL_TIMEGATE_OPENING,
3829     EL_TIMEGATE_CLOSED,
3830     EL_TIMEGATE_CLOSING,
3831     EL_DC_TIMEGATE_SWITCH,
3832     EL_DC_TIMEGATE_SWITCH_ACTIVE,
3833     EL_TUBE_ANY,
3834     EL_TUBE_VERTICAL,
3835     EL_TUBE_HORIZONTAL,
3836     EL_TUBE_VERTICAL_LEFT,
3837     EL_TUBE_VERTICAL_RIGHT,
3838     EL_TUBE_HORIZONTAL_UP,
3839     EL_TUBE_HORIZONTAL_DOWN,
3840     EL_TUBE_LEFT_UP,
3841     EL_TUBE_LEFT_DOWN,
3842     EL_TUBE_RIGHT_UP,
3843     EL_TUBE_RIGHT_DOWN,
3844     EL_EXPANDABLE_STEELWALL_HORIZONTAL,
3845     EL_EXPANDABLE_STEELWALL_VERTICAL,
3846     EL_EXPANDABLE_STEELWALL_ANY,
3847
3848     -1
3849   };
3850
3851   static int ep_classic_enemy[] =
3852   {
3853     EL_BUG,
3854     EL_SPACESHIP,
3855     EL_BD_BUTTERFLY,
3856     EL_BD_FIREFLY,
3857
3858     EL_YAMYAM,
3859     EL_DARK_YAMYAM,
3860     EL_ROBOT,
3861     EL_PACMAN,
3862     EL_SP_SNIKSNAK,
3863     EL_SP_ELECTRON,
3864
3865     -1
3866   };
3867
3868   static int ep_belt[] =
3869   {
3870     EL_CONVEYOR_BELT_1_LEFT,
3871     EL_CONVEYOR_BELT_1_MIDDLE,
3872     EL_CONVEYOR_BELT_1_RIGHT,
3873     EL_CONVEYOR_BELT_2_LEFT,
3874     EL_CONVEYOR_BELT_2_MIDDLE,
3875     EL_CONVEYOR_BELT_2_RIGHT,
3876     EL_CONVEYOR_BELT_3_LEFT,
3877     EL_CONVEYOR_BELT_3_MIDDLE,
3878     EL_CONVEYOR_BELT_3_RIGHT,
3879     EL_CONVEYOR_BELT_4_LEFT,
3880     EL_CONVEYOR_BELT_4_MIDDLE,
3881     EL_CONVEYOR_BELT_4_RIGHT,
3882
3883     -1
3884   };
3885
3886   static int ep_belt_active[] =
3887   {
3888     EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
3889     EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE,
3890     EL_CONVEYOR_BELT_1_RIGHT_ACTIVE,
3891     EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
3892     EL_CONVEYOR_BELT_2_MIDDLE_ACTIVE,
3893     EL_CONVEYOR_BELT_2_RIGHT_ACTIVE,
3894     EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
3895     EL_CONVEYOR_BELT_3_MIDDLE_ACTIVE,
3896     EL_CONVEYOR_BELT_3_RIGHT_ACTIVE,
3897     EL_CONVEYOR_BELT_4_LEFT_ACTIVE,
3898     EL_CONVEYOR_BELT_4_MIDDLE_ACTIVE,
3899     EL_CONVEYOR_BELT_4_RIGHT_ACTIVE,
3900
3901     -1
3902   };
3903
3904   static int ep_belt_switch[] =
3905   {
3906     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3907     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3908     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3909     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3910     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3911     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3912     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3913     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3914     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3915     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3916     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3917     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3918
3919     -1
3920   };
3921
3922   static int ep_tube[] =
3923   {
3924     EL_TUBE_LEFT_UP,
3925     EL_TUBE_LEFT_DOWN,
3926     EL_TUBE_RIGHT_UP,
3927     EL_TUBE_RIGHT_DOWN,
3928     EL_TUBE_HORIZONTAL,
3929     EL_TUBE_HORIZONTAL_UP,
3930     EL_TUBE_HORIZONTAL_DOWN,
3931     EL_TUBE_VERTICAL,
3932     EL_TUBE_VERTICAL_LEFT,
3933     EL_TUBE_VERTICAL_RIGHT,
3934     EL_TUBE_ANY,
3935
3936     -1
3937   };
3938
3939   static int ep_acid_pool[] =
3940   {
3941     EL_ACID_POOL_TOPLEFT,
3942     EL_ACID_POOL_TOPRIGHT,
3943     EL_ACID_POOL_BOTTOMLEFT,
3944     EL_ACID_POOL_BOTTOM,
3945     EL_ACID_POOL_BOTTOMRIGHT,
3946
3947     -1
3948   };
3949
3950   static int ep_keygate[] =
3951   {
3952     EL_GATE_1,
3953     EL_GATE_2,
3954     EL_GATE_3,
3955     EL_GATE_4,
3956     EL_GATE_1_GRAY,
3957     EL_GATE_2_GRAY,
3958     EL_GATE_3_GRAY,
3959     EL_GATE_4_GRAY,
3960     EL_GATE_1_GRAY_ACTIVE,
3961     EL_GATE_2_GRAY_ACTIVE,
3962     EL_GATE_3_GRAY_ACTIVE,
3963     EL_GATE_4_GRAY_ACTIVE,
3964     EL_EM_GATE_1,
3965     EL_EM_GATE_2,
3966     EL_EM_GATE_3,
3967     EL_EM_GATE_4,
3968     EL_EM_GATE_1_GRAY,
3969     EL_EM_GATE_2_GRAY,
3970     EL_EM_GATE_3_GRAY,
3971     EL_EM_GATE_4_GRAY,
3972     EL_EM_GATE_1_GRAY_ACTIVE,
3973     EL_EM_GATE_2_GRAY_ACTIVE,
3974     EL_EM_GATE_3_GRAY_ACTIVE,
3975     EL_EM_GATE_4_GRAY_ACTIVE,
3976     EL_EMC_GATE_5,
3977     EL_EMC_GATE_6,
3978     EL_EMC_GATE_7,
3979     EL_EMC_GATE_8,
3980     EL_EMC_GATE_5_GRAY,
3981     EL_EMC_GATE_6_GRAY,
3982     EL_EMC_GATE_7_GRAY,
3983     EL_EMC_GATE_8_GRAY,
3984     EL_EMC_GATE_5_GRAY_ACTIVE,
3985     EL_EMC_GATE_6_GRAY_ACTIVE,