added global animation actions executed after init/anim/post delay
[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->init_delay_action = -1;
1301   g->anim_delay_fixed = 0;
1302   g->anim_delay_random = 0;
1303   g->anim_delay_action = -1;
1304   g->post_delay_fixed = 0;
1305   g->post_delay_random = 0;
1306   g->post_delay_action = -1;
1307   g->init_event = ANIM_EVENT_UNDEFINED;
1308   g->anim_event = ANIM_EVENT_UNDEFINED;
1309   g->init_event_action = -1;
1310   g->anim_event_action = -1;
1311   g->draw_masked = FALSE;
1312   g->draw_order = 0;
1313   g->fade_mode = FADE_MODE_DEFAULT;
1314   g->fade_delay = -1;
1315   g->post_delay = -1;
1316   g->auto_delay = -1;
1317   g->align = ALIGN_CENTER;              // default for title screens
1318   g->valign = VALIGN_MIDDLE;            // default for title screens
1319   g->sort_priority = 0;                 // default for title screens
1320   g->class = 0;
1321   g->style = STYLE_DEFAULT;
1322
1323   g->bitmaps = src_bitmaps;
1324   g->bitmap = src_bitmap;
1325
1326   // optional zoom factor for scaling up the image to a larger size
1327   if (parameter[GFX_ARG_SCALE_UP_FACTOR] != ARG_UNDEFINED_VALUE)
1328     g->scale_up_factor = parameter[GFX_ARG_SCALE_UP_FACTOR];
1329   if (g->scale_up_factor < 1)
1330     g->scale_up_factor = 1;             // no scaling
1331
1332   // optional tile size for using non-standard image size
1333   if (parameter[GFX_ARG_TILE_SIZE] != ARG_UNDEFINED_VALUE)
1334   {
1335     g->tile_size = parameter[GFX_ARG_TILE_SIZE];
1336
1337 #if 0
1338     // CHECK: should tile sizes less than standard tile size be allowed?
1339     if (g->tile_size < TILESIZE)
1340       g->tile_size = TILESIZE;          // standard tile size
1341 #endif
1342
1343     // when setting tile size, also set width and height accordingly
1344     g->width  = g->tile_size;
1345     g->height = g->tile_size;
1346   }
1347
1348   if (g->use_image_size)
1349   {
1350     // set new default bitmap size (with scaling, but without small images)
1351     g->width  = get_scaled_graphic_width(graphic);
1352     g->height = get_scaled_graphic_height(graphic);
1353   }
1354
1355   // optional width and height of each animation frame
1356   if (parameter[GFX_ARG_WIDTH] != ARG_UNDEFINED_VALUE)
1357     g->width = parameter[GFX_ARG_WIDTH];
1358   if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE)
1359     g->height = parameter[GFX_ARG_HEIGHT];
1360
1361   // optional x and y tile position of animation frame sequence
1362   if (parameter[GFX_ARG_XPOS] != ARG_UNDEFINED_VALUE)
1363     g->src_x = parameter[GFX_ARG_XPOS] * g->width;
1364   if (parameter[GFX_ARG_YPOS] != ARG_UNDEFINED_VALUE)
1365     g->src_y = parameter[GFX_ARG_YPOS] * g->height;
1366
1367   // optional x and y pixel position of animation frame sequence
1368   if (parameter[GFX_ARG_X] != ARG_UNDEFINED_VALUE)
1369     g->src_x = parameter[GFX_ARG_X];
1370   if (parameter[GFX_ARG_Y] != ARG_UNDEFINED_VALUE)
1371     g->src_y = parameter[GFX_ARG_Y];
1372
1373   if (src_bitmap)
1374   {
1375     if (g->width <= 0)
1376     {
1377       Error(ERR_INFO_LINE, "-");
1378       Error(ERR_WARN, "invalid value %d for '%s.width' (fallback done to %d)",
1379             g->width, getTokenFromImageID(graphic), TILEX);
1380       Error(ERR_INFO_LINE, "-");
1381
1382       g->width = TILEX;         // will be checked to be inside bitmap later
1383     }
1384
1385     if (g->height <= 0)
1386     {
1387       Error(ERR_INFO_LINE, "-");
1388       Error(ERR_WARN, "invalid value %d for '%s.height' (fallback done to %d)",
1389             g->height, getTokenFromImageID(graphic), TILEY);
1390       Error(ERR_INFO_LINE, "-");
1391
1392       g->height = TILEY;        // will be checked to be inside bitmap later
1393     }
1394   }
1395
1396   if (src_bitmap)
1397   {
1398     // get final bitmap size (with scaling, but without small images)
1399     int src_image_width  = get_scaled_graphic_width(graphic);
1400     int src_image_height = get_scaled_graphic_height(graphic);
1401
1402     if (src_image_width == 0 || src_image_height == 0)
1403     {
1404       // only happens when loaded outside artwork system (like "global.busy")
1405       src_image_width  = src_bitmap->width;
1406       src_image_height = src_bitmap->height;
1407     }
1408
1409     if (parameter[GFX_ARG_TILE_SIZE] != ARG_UNDEFINED_VALUE)
1410     {
1411       anim_frames_per_row = MAX(1, src_image_width  / g->tile_size);
1412       anim_frames_per_col = MAX(1, src_image_height / g->tile_size);
1413     }
1414     else
1415     {
1416       anim_frames_per_row = MAX(1, src_image_width  / g->width);
1417       anim_frames_per_col = MAX(1, src_image_height / g->height);
1418     }
1419
1420     g->src_image_width  = src_image_width;
1421     g->src_image_height = src_image_height;
1422   }
1423
1424   // correct x or y offset dependent of vertical or horizontal frame order
1425   if (parameter[GFX_ARG_VERTICAL])      // frames are ordered vertically
1426   {
1427     g->offset_y = (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
1428                    parameter[GFX_ARG_OFFSET] : g->height);
1429     anim_frames_per_line = anim_frames_per_col;
1430   }
1431   else                                  // frames are ordered horizontally
1432   {
1433     g->offset_x = (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
1434                    parameter[GFX_ARG_OFFSET] : g->width);
1435     anim_frames_per_line = anim_frames_per_row;
1436   }
1437
1438   // optionally, the x and y offset of frames can be specified directly
1439   if (parameter[GFX_ARG_XOFFSET] != ARG_UNDEFINED_VALUE)
1440     g->offset_x = parameter[GFX_ARG_XOFFSET];
1441   if (parameter[GFX_ARG_YOFFSET] != ARG_UNDEFINED_VALUE)
1442     g->offset_y = parameter[GFX_ARG_YOFFSET];
1443
1444   // optionally, moving animations may have separate start and end graphics
1445   g->double_movement = parameter[GFX_ARG_2ND_MOVEMENT_TILE];
1446
1447   if (parameter[GFX_ARG_2ND_VERTICAL] == ARG_UNDEFINED_VALUE)
1448     parameter[GFX_ARG_2ND_VERTICAL] = !parameter[GFX_ARG_VERTICAL];
1449
1450   // correct x or y offset2 dependent of vertical or horizontal frame order
1451   if (parameter[GFX_ARG_2ND_VERTICAL])  // frames are ordered vertically
1452     g->offset2_y = (parameter[GFX_ARG_2ND_OFFSET] != ARG_UNDEFINED_VALUE ?
1453                     parameter[GFX_ARG_2ND_OFFSET] : g->height);
1454   else                                  // frames are ordered horizontally
1455     g->offset2_x = (parameter[GFX_ARG_2ND_OFFSET] != ARG_UNDEFINED_VALUE ?
1456                     parameter[GFX_ARG_2ND_OFFSET] : g->width);
1457
1458   // optionally, the x and y offset of 2nd graphic can be specified directly
1459   if (parameter[GFX_ARG_2ND_XOFFSET] != ARG_UNDEFINED_VALUE)
1460     g->offset2_x = parameter[GFX_ARG_2ND_XOFFSET];
1461   if (parameter[GFX_ARG_2ND_YOFFSET] != ARG_UNDEFINED_VALUE)
1462     g->offset2_y = parameter[GFX_ARG_2ND_YOFFSET];
1463
1464   // optionally, the second movement tile can be specified as start tile
1465   if (parameter[GFX_ARG_2ND_SWAP_TILES] != ARG_UNDEFINED_VALUE)
1466     g->swap_double_tiles= parameter[GFX_ARG_2ND_SWAP_TILES];
1467
1468   // automatically determine correct number of frames, if not defined
1469   if (parameter[GFX_ARG_FRAMES] != ARG_UNDEFINED_VALUE)
1470     g->anim_frames = parameter[GFX_ARG_FRAMES];
1471   else if (parameter[GFX_ARG_XPOS] == 0 && !parameter[GFX_ARG_VERTICAL])
1472     g->anim_frames = anim_frames_per_row;
1473   else if (parameter[GFX_ARG_YPOS] == 0 && parameter[GFX_ARG_VERTICAL])
1474     g->anim_frames = anim_frames_per_col;
1475   else
1476     g->anim_frames = 1;
1477
1478   if (g->anim_frames == 0)              // frames must be at least 1
1479     g->anim_frames = 1;
1480
1481   g->anim_frames_per_line =
1482     (parameter[GFX_ARG_FRAMES_PER_LINE] != ARG_UNDEFINED_VALUE ?
1483      parameter[GFX_ARG_FRAMES_PER_LINE] : anim_frames_per_line);
1484
1485   g->anim_delay = parameter[GFX_ARG_DELAY];
1486   if (g->anim_delay == 0)               // delay must be at least 1
1487     g->anim_delay = 1;
1488
1489   g->anim_mode = parameter[GFX_ARG_ANIM_MODE];
1490
1491   // automatically determine correct start frame, if not defined
1492   if (parameter[GFX_ARG_START_FRAME] == ARG_UNDEFINED_VALUE)
1493     g->anim_start_frame = 0;
1494   else if (g->anim_mode & ANIM_REVERSE)
1495     g->anim_start_frame = g->anim_frames - parameter[GFX_ARG_START_FRAME] - 1;
1496   else
1497     g->anim_start_frame = parameter[GFX_ARG_START_FRAME];
1498
1499   // animation synchronized with global frame counter, not move position
1500   g->anim_global_sync = parameter[GFX_ARG_GLOBAL_SYNC];
1501
1502   // optional element for cloning crumble graphics
1503   if (parameter[GFX_ARG_CRUMBLED_LIKE] != ARG_UNDEFINED_VALUE)
1504     g->crumbled_like = parameter[GFX_ARG_CRUMBLED_LIKE];
1505
1506   // optional element for cloning digging graphics
1507   if (parameter[GFX_ARG_DIGGABLE_LIKE] != ARG_UNDEFINED_VALUE)
1508     g->diggable_like = parameter[GFX_ARG_DIGGABLE_LIKE];
1509
1510   // optional border size for "crumbling" diggable graphics
1511   if (parameter[GFX_ARG_BORDER_SIZE] != ARG_UNDEFINED_VALUE)
1512     g->border_size = parameter[GFX_ARG_BORDER_SIZE];
1513
1514   // used for global animations and player "boring" and "sleeping" actions
1515   if (parameter[GFX_ARG_INIT_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
1516     g->init_delay_fixed = parameter[GFX_ARG_INIT_DELAY_FIXED];
1517   if (parameter[GFX_ARG_INIT_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
1518     g->init_delay_random = parameter[GFX_ARG_INIT_DELAY_RANDOM];
1519   if (parameter[GFX_ARG_ANIM_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
1520     g->anim_delay_fixed = parameter[GFX_ARG_ANIM_DELAY_FIXED];
1521   if (parameter[GFX_ARG_ANIM_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
1522     g->anim_delay_random = parameter[GFX_ARG_ANIM_DELAY_RANDOM];
1523   if (parameter[GFX_ARG_POST_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
1524     g->post_delay_fixed = parameter[GFX_ARG_POST_DELAY_FIXED];
1525   if (parameter[GFX_ARG_POST_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
1526     g->post_delay_random = parameter[GFX_ARG_POST_DELAY_RANDOM];
1527
1528   // used for global animations
1529   if (parameter[GFX_ARG_INIT_EVENT] != ARG_UNDEFINED_VALUE)
1530     g->init_event = parameter[GFX_ARG_INIT_EVENT];
1531   if (parameter[GFX_ARG_ANIM_EVENT] != ARG_UNDEFINED_VALUE)
1532     g->anim_event = parameter[GFX_ARG_ANIM_EVENT];
1533   if (parameter[GFX_ARG_INIT_EVENT_ACTION] != ARG_UNDEFINED_VALUE)
1534     g->init_event_action = parameter[GFX_ARG_INIT_EVENT_ACTION];
1535   if (parameter[GFX_ARG_ANIM_EVENT_ACTION] != ARG_UNDEFINED_VALUE)
1536     g->anim_event_action = parameter[GFX_ARG_ANIM_EVENT_ACTION];
1537   if (parameter[GFX_ARG_INIT_DELAY_ACTION] != ARG_UNDEFINED_VALUE)
1538     g->init_delay_action = parameter[GFX_ARG_INIT_DELAY_ACTION];
1539   if (parameter[GFX_ARG_ANIM_DELAY_ACTION] != ARG_UNDEFINED_VALUE)
1540     g->anim_delay_action = parameter[GFX_ARG_ANIM_DELAY_ACTION];
1541   if (parameter[GFX_ARG_POST_DELAY_ACTION] != ARG_UNDEFINED_VALUE)
1542     g->post_delay_action = parameter[GFX_ARG_POST_DELAY_ACTION];
1543
1544   // used for toon animations and global animations
1545   g->step_offset  = parameter[GFX_ARG_STEP_OFFSET];
1546   g->step_xoffset = parameter[GFX_ARG_STEP_XOFFSET];
1547   g->step_yoffset = parameter[GFX_ARG_STEP_YOFFSET];
1548   g->step_delay   = parameter[GFX_ARG_STEP_DELAY];
1549   g->direction    = parameter[GFX_ARG_DIRECTION];
1550   g->position     = parameter[GFX_ARG_POSITION];
1551   g->x            = parameter[GFX_ARG_X];       // (may be uninitialized,
1552   g->y            = parameter[GFX_ARG_Y];       // unlike src_x and src_y)
1553
1554   // this is only used for drawing font characters
1555   g->draw_xoffset = parameter[GFX_ARG_DRAW_XOFFSET];
1556   g->draw_yoffset = parameter[GFX_ARG_DRAW_YOFFSET];
1557
1558   // use a different default value for global animations and toons
1559   if ((graphic >= IMG_GFX_GLOBAL_ANIM_1 && graphic <= IMG_GFX_GLOBAL_ANIM_8) ||
1560       (graphic >= IMG_TOON_1            && graphic <= IMG_TOON_20))
1561     g->draw_masked = TRUE;
1562
1563   // this is used for drawing envelopes, global animations and toons
1564   if (parameter[GFX_ARG_DRAW_MASKED] != ARG_UNDEFINED_VALUE)
1565     g->draw_masked = parameter[GFX_ARG_DRAW_MASKED];
1566
1567   // used for toon animations and global animations
1568   if (parameter[GFX_ARG_DRAW_ORDER] != ARG_UNDEFINED_VALUE)
1569     g->draw_order = parameter[GFX_ARG_DRAW_ORDER];
1570
1571   // optional graphic for cloning all graphics settings
1572   if (parameter[GFX_ARG_CLONE_FROM] != ARG_UNDEFINED_VALUE)
1573     g->clone_from = parameter[GFX_ARG_CLONE_FROM];
1574
1575   // optional settings for drawing title screens and title messages
1576   if (parameter[GFX_ARG_FADE_MODE] != ARG_UNDEFINED_VALUE)
1577     g->fade_mode = parameter[GFX_ARG_FADE_MODE];
1578   if (parameter[GFX_ARG_FADE_DELAY] != ARG_UNDEFINED_VALUE)
1579     g->fade_delay = parameter[GFX_ARG_FADE_DELAY];
1580   if (parameter[GFX_ARG_POST_DELAY] != ARG_UNDEFINED_VALUE)
1581     g->post_delay = parameter[GFX_ARG_POST_DELAY];
1582   if (parameter[GFX_ARG_AUTO_DELAY] != ARG_UNDEFINED_VALUE)
1583     g->auto_delay = parameter[GFX_ARG_AUTO_DELAY];
1584   if (parameter[GFX_ARG_ALIGN] != ARG_UNDEFINED_VALUE)
1585     g->align = parameter[GFX_ARG_ALIGN];
1586   if (parameter[GFX_ARG_VALIGN] != ARG_UNDEFINED_VALUE)
1587     g->valign = parameter[GFX_ARG_VALIGN];
1588   if (parameter[GFX_ARG_SORT_PRIORITY] != ARG_UNDEFINED_VALUE)
1589     g->sort_priority = parameter[GFX_ARG_SORT_PRIORITY];
1590
1591   if (parameter[GFX_ARG_CLASS] != ARG_UNDEFINED_VALUE)
1592     g->class = parameter[GFX_ARG_CLASS];
1593   if (parameter[GFX_ARG_STYLE] != ARG_UNDEFINED_VALUE)
1594     g->style = parameter[GFX_ARG_STYLE];
1595
1596   // this is only used for drawing menu buttons and text
1597   g->active_xoffset = parameter[GFX_ARG_ACTIVE_XOFFSET];
1598   g->active_yoffset = parameter[GFX_ARG_ACTIVE_YOFFSET];
1599   g->pressed_xoffset = parameter[GFX_ARG_PRESSED_XOFFSET];
1600   g->pressed_yoffset = parameter[GFX_ARG_PRESSED_YOFFSET];
1601 }
1602
1603 static void set_graphic_parameters(int graphic)
1604 {
1605   struct FileInfo *image = getImageListEntryFromImageID(graphic);
1606   char **parameter_raw = image->parameter;
1607   Bitmap **src_bitmaps = getBitmapsFromImageID(graphic);
1608   int parameter[NUM_GFX_ARGS];
1609   int i;
1610
1611   // if fallback to default artwork is done, also use the default parameters
1612   if (image->fallback_to_default)
1613     parameter_raw = image->default_parameter;
1614
1615   // get integer values from string parameters
1616   for (i = 0; i < NUM_GFX_ARGS; i++)
1617     parameter[i] = get_graphic_parameter_value(parameter_raw[i],
1618                                                image_config_suffix[i].token,
1619                                                image_config_suffix[i].type);
1620
1621   set_graphic_parameters_ext(graphic, parameter, src_bitmaps);
1622
1623   UPDATE_BUSY_STATE();
1624 }
1625
1626 static void set_cloned_graphic_parameters(int graphic)
1627 {
1628   int fallback_graphic = IMG_CHAR_EXCLAM;
1629   int max_num_images = getImageListSize();
1630   int clone_graphic = graphic_info[graphic].clone_from;
1631   int num_references_followed = 1;
1632
1633   while (graphic_info[clone_graphic].clone_from != -1 &&
1634          num_references_followed < max_num_images)
1635   {
1636     clone_graphic = graphic_info[clone_graphic].clone_from;
1637
1638     num_references_followed++;
1639   }
1640
1641   if (num_references_followed >= max_num_images)
1642   {
1643     Error(ERR_INFO_LINE, "-");
1644     Error(ERR_INFO, "warning: error found in config file:");
1645     Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
1646     Error(ERR_INFO, "- config token: '%s'", getTokenFromImageID(graphic));
1647     Error(ERR_INFO, "error: loop discovered when resolving cloned graphics");
1648     Error(ERR_INFO, "custom graphic rejected for this element/action");
1649
1650     if (graphic == fallback_graphic)
1651       Error(ERR_EXIT, "no fallback graphic available");
1652
1653     Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic");
1654     Error(ERR_INFO_LINE, "-");
1655
1656     graphic_info[graphic] = graphic_info[fallback_graphic];
1657   }
1658   else
1659   {
1660     graphic_info[graphic] = graphic_info[clone_graphic];
1661     graphic_info[graphic].clone_from = clone_graphic;
1662   }
1663 }
1664
1665 static void InitGraphicInfo(void)
1666 {
1667   int fallback_graphic = IMG_CHAR_EXCLAM;
1668   int num_images = getImageListSize();
1669   int i;
1670
1671   // use image size as default values for width and height for these images
1672   static int full_size_graphics[] =
1673   {
1674     IMG_GLOBAL_BORDER,
1675     IMG_GLOBAL_BORDER_MAIN,
1676     IMG_GLOBAL_BORDER_SCORES,
1677     IMG_GLOBAL_BORDER_EDITOR,
1678     IMG_GLOBAL_BORDER_PLAYING,
1679     IMG_GLOBAL_DOOR,
1680
1681     IMG_BACKGROUND_ENVELOPE_1,
1682     IMG_BACKGROUND_ENVELOPE_2,
1683     IMG_BACKGROUND_ENVELOPE_3,
1684     IMG_BACKGROUND_ENVELOPE_4,
1685     IMG_BACKGROUND_REQUEST,
1686
1687     IMG_BACKGROUND,
1688     IMG_BACKGROUND_TITLE_INITIAL,
1689     IMG_BACKGROUND_TITLE,
1690     IMG_BACKGROUND_MAIN,
1691     IMG_BACKGROUND_LEVELS,
1692     IMG_BACKGROUND_LEVELNR,
1693     IMG_BACKGROUND_SCORES,
1694     IMG_BACKGROUND_EDITOR,
1695     IMG_BACKGROUND_INFO,
1696     IMG_BACKGROUND_INFO_ELEMENTS,
1697     IMG_BACKGROUND_INFO_MUSIC,
1698     IMG_BACKGROUND_INFO_CREDITS,
1699     IMG_BACKGROUND_INFO_PROGRAM,
1700     IMG_BACKGROUND_INFO_VERSION,
1701     IMG_BACKGROUND_INFO_LEVELSET,
1702     IMG_BACKGROUND_SETUP,
1703     IMG_BACKGROUND_PLAYING,
1704     IMG_BACKGROUND_DOOR,
1705     IMG_BACKGROUND_TAPE,
1706     IMG_BACKGROUND_PANEL,
1707     IMG_BACKGROUND_PALETTE,
1708     IMG_BACKGROUND_TOOLBOX,
1709
1710     IMG_TITLESCREEN_INITIAL_1,
1711     IMG_TITLESCREEN_INITIAL_2,
1712     IMG_TITLESCREEN_INITIAL_3,
1713     IMG_TITLESCREEN_INITIAL_4,
1714     IMG_TITLESCREEN_INITIAL_5,
1715     IMG_TITLESCREEN_1,
1716     IMG_TITLESCREEN_2,
1717     IMG_TITLESCREEN_3,
1718     IMG_TITLESCREEN_4,
1719     IMG_TITLESCREEN_5,
1720
1721     IMG_BACKGROUND_TITLEMESSAGE_INITIAL_1,
1722     IMG_BACKGROUND_TITLEMESSAGE_INITIAL_2,
1723     IMG_BACKGROUND_TITLEMESSAGE_INITIAL_3,
1724     IMG_BACKGROUND_TITLEMESSAGE_INITIAL_4,
1725     IMG_BACKGROUND_TITLEMESSAGE_INITIAL_5,
1726     IMG_BACKGROUND_TITLEMESSAGE_1,
1727     IMG_BACKGROUND_TITLEMESSAGE_2,
1728     IMG_BACKGROUND_TITLEMESSAGE_3,
1729     IMG_BACKGROUND_TITLEMESSAGE_4,
1730     IMG_BACKGROUND_TITLEMESSAGE_5,
1731
1732     -1
1733   };
1734
1735   FreeGlobalAnimEventInfo();
1736
1737   checked_free(graphic_info);
1738
1739   graphic_info = checked_calloc(num_images * sizeof(struct GraphicInfo));
1740
1741   // initialize "use_image_size" flag with default value
1742   for (i = 0; i < num_images; i++)
1743     graphic_info[i].use_image_size = FALSE;
1744
1745   // initialize "use_image_size" flag from static configuration above
1746   for (i = 0; full_size_graphics[i] != -1; i++)
1747     graphic_info[full_size_graphics[i]].use_image_size = TRUE;
1748
1749   // first set all graphic paramaters ...
1750   for (i = 0; i < num_images; i++)
1751     set_graphic_parameters(i);
1752
1753   // ... then copy these parameters for cloned graphics
1754   for (i = 0; i < num_images; i++)
1755     if (graphic_info[i].clone_from != -1)
1756       set_cloned_graphic_parameters(i);
1757
1758   for (i = 0; i < num_images; i++)
1759   {
1760     Bitmap *src_bitmap = graphic_info[i].bitmap;
1761     int src_x, src_y;
1762     int width, height;
1763     int last_frame;
1764     int src_bitmap_width, src_bitmap_height;
1765
1766     // now check if no animation frames are outside of the loaded image
1767
1768     if (graphic_info[i].bitmap == NULL)
1769       continue;         // skip check for optional images that are undefined
1770
1771     // get image size (this can differ from the standard element tile size!)
1772     width  = graphic_info[i].width;
1773     height = graphic_info[i].height;
1774
1775     // get final bitmap size (with scaling, but without small images)
1776     src_bitmap_width  = graphic_info[i].src_image_width;
1777     src_bitmap_height = graphic_info[i].src_image_height;
1778
1779     // check if first animation frame is inside specified bitmap
1780
1781     // do not use getGraphicSourceXY() here to get position of first frame;
1782     // this avoids calculating wrong start position for out-of-bounds frame
1783     src_x = graphic_info[i].src_x;
1784     src_y = graphic_info[i].src_y;
1785
1786     if (program.headless)
1787       continue;
1788
1789     if (src_x < 0 || src_y < 0 ||
1790         src_x + width  > src_bitmap_width ||
1791         src_y + height > src_bitmap_height)
1792     {
1793       Error(ERR_INFO_LINE, "-");
1794       Error(ERR_INFO, "warning: error found in config file:");
1795       Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
1796       Error(ERR_INFO, "- config token: '%s'", getTokenFromImageID(i));
1797       Error(ERR_INFO, "- image file: '%s'", src_bitmap->source_filename);
1798       Error(ERR_INFO, "- frame size: %d, %d", width, height);
1799       Error(ERR_INFO,
1800             "error: first animation frame out of bounds (%d, %d) [%d, %d]",
1801             src_x, src_y, src_bitmap_width, src_bitmap_height);
1802       Error(ERR_INFO, "custom graphic rejected for this element/action");
1803
1804       if (i == fallback_graphic)
1805         Error(ERR_EXIT, "no fallback graphic available");
1806
1807       Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic");
1808       Error(ERR_INFO_LINE, "-");
1809
1810       graphic_info[i] = graphic_info[fallback_graphic];
1811
1812       // if first frame out of bounds, do not check last frame anymore
1813       continue;
1814     }
1815
1816     // check if last animation frame is inside specified bitmap
1817
1818     last_frame = graphic_info[i].anim_frames - 1;
1819     getGraphicSourceXY(i, last_frame, &src_x, &src_y, FALSE);
1820
1821     if (src_x < 0 || src_y < 0 ||
1822         src_x + width  > src_bitmap_width ||
1823         src_y + height > src_bitmap_height)
1824     {
1825       Error(ERR_INFO_LINE, "-");
1826       Error(ERR_INFO, "warning: error found in config file:");
1827       Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
1828       Error(ERR_INFO, "- config token: '%s'", getTokenFromImageID(i));
1829       Error(ERR_INFO, "- image file: '%s'", src_bitmap->source_filename);
1830       Error(ERR_INFO, "- frame size: %d, %d", width, height);
1831       Error(ERR_INFO,
1832             "error: last animation frame (%d) out of bounds (%d, %d) [%d, %d]",
1833             last_frame, src_x, src_y, src_bitmap_width, src_bitmap_height);
1834       Error(ERR_INFO, "custom graphic rejected for this element/action");
1835
1836       if (i == fallback_graphic)
1837         Error(ERR_EXIT, "no fallback graphic available");
1838
1839       Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic");
1840       Error(ERR_INFO_LINE, "-");
1841
1842       graphic_info[i] = graphic_info[fallback_graphic];
1843     }
1844   }
1845 }
1846
1847 static void InitGraphicCompatibilityInfo(void)
1848 {
1849   struct FileInfo *fi_global_door =
1850     getImageListEntryFromImageID(IMG_GLOBAL_DOOR);
1851   int num_images = getImageListSize();
1852   int i;
1853
1854   /* the following compatibility handling is needed for the following case:
1855      versions up to 3.3.0.0 used one large bitmap "global.door" for various
1856      graphics mainly used for door and panel graphics, like editor, tape and
1857      in-game buttons with hard-coded bitmap positions and button sizes; as
1858      these graphics now have individual definitions, redefining "global.door"
1859      to change all these graphics at once like before does not work anymore
1860      (because all those individual definitions still have their default values);
1861      to solve this, remap all those individual definitions that are not
1862      redefined to the new bitmap of "global.door" if it was redefined */
1863
1864   // special compatibility handling if image "global.door" was redefined
1865   if (fi_global_door->redefined)
1866   {
1867     for (i = 0; i < num_images; i++)
1868     {
1869       struct FileInfo *fi = getImageListEntryFromImageID(i);
1870
1871       // process only those images that still use the default settings
1872       if (!fi->redefined)
1873       {
1874         // process all images which default to same image as "global.door"
1875         if (strEqual(fi->default_filename, fi_global_door->default_filename))
1876         {
1877           // printf("::: special treatment needed for token '%s'\n", fi->token);
1878
1879           graphic_info[i].bitmaps = graphic_info[IMG_GLOBAL_DOOR].bitmaps;
1880           graphic_info[i].bitmap  = graphic_info[IMG_GLOBAL_DOOR].bitmap;
1881         }
1882       }
1883     }
1884   }
1885
1886   InitGraphicCompatibilityInfo_Doors();
1887 }
1888
1889 static void InitElementSoundInfo(void)
1890 {
1891   struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1892   int num_property_mappings = getSoundListPropertyMappingSize();
1893   int i, j, act;
1894
1895   // set values to -1 to identify later as "uninitialized" values
1896   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1897     for (act = 0; act < NUM_ACTIONS; act++)
1898       element_info[i].sound[act] = -1;
1899
1900   // initialize element/sound mapping from static configuration
1901   for (i = 0; element_to_sound[i].element > -1; i++)
1902   {
1903     int element      = element_to_sound[i].element;
1904     int action       = element_to_sound[i].action;
1905     int sound        = element_to_sound[i].sound;
1906     boolean is_class = element_to_sound[i].is_class;
1907
1908     if (action < 0)
1909       action = ACTION_DEFAULT;
1910
1911     if (!is_class)
1912       element_info[element].sound[action] = sound;
1913     else
1914       for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1915         if (strEqual(element_info[j].class_name,
1916                      element_info[element].class_name))
1917           element_info[j].sound[action] = sound;
1918   }
1919
1920   // initialize element class/sound mapping from dynamic configuration
1921   for (i = 0; i < num_property_mappings; i++)
1922   {
1923     int element_class = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
1924     int action        = property_mapping[i].ext1_index;
1925     int sound         = property_mapping[i].artwork_index;
1926
1927     if (element_class < 0 || element_class >= MAX_NUM_ELEMENTS)
1928       continue;
1929
1930     if (action < 0)
1931       action = ACTION_DEFAULT;
1932
1933     for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1934       if (strEqual(element_info[j].class_name,
1935                    element_info[element_class].class_name))
1936         element_info[j].sound[action] = sound;
1937   }
1938
1939   // initialize element/sound mapping from dynamic configuration
1940   for (i = 0; i < num_property_mappings; i++)
1941   {
1942     int element = property_mapping[i].base_index;
1943     int action  = property_mapping[i].ext1_index;
1944     int sound   = property_mapping[i].artwork_index;
1945
1946     if (element >= MAX_NUM_ELEMENTS)
1947       continue;
1948
1949     if (action < 0)
1950       action = ACTION_DEFAULT;
1951
1952     element_info[element].sound[action] = sound;
1953   }
1954
1955   // now set all '-1' values to element specific default values
1956   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1957   {
1958     for (act = 0; act < NUM_ACTIONS; act++)
1959     {
1960       // generic default action sound (defined by "[default]" directive)
1961       int default_action_sound = element_info[EL_DEFAULT].sound[act];
1962
1963       // look for special default action sound (classic game specific)
1964       if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].sound[act] != -1)
1965         default_action_sound = element_info[EL_BD_DEFAULT].sound[act];
1966       if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].sound[act] != -1)
1967         default_action_sound = element_info[EL_SP_DEFAULT].sound[act];
1968       if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].sound[act] != -1)
1969         default_action_sound = element_info[EL_SB_DEFAULT].sound[act];
1970       if (IS_MM_ELEMENT(i) && element_info[EL_MM_DEFAULT].sound[act] != -1)
1971         default_action_sound = element_info[EL_MM_DEFAULT].sound[act];
1972
1973       // !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!!
1974       // !!! make this better !!!
1975       if (i == EL_EMPTY_SPACE)
1976         default_action_sound = element_info[EL_DEFAULT].sound[act];
1977
1978       // no sound for this specific action -- use default action sound
1979       if (element_info[i].sound[act] == -1)
1980         element_info[i].sound[act] = default_action_sound;
1981     }
1982   }
1983
1984   // copy sound settings to some elements that are only stored in level file
1985   // in native R'n'D levels, but are used by game engine in native EM levels
1986   for (i = 0; copy_properties[i][0] != -1; i++)
1987     for (j = 1; j <= 4; j++)
1988       for (act = 0; act < NUM_ACTIONS; act++)
1989         element_info[copy_properties[i][j]].sound[act] =
1990           element_info[copy_properties[i][0]].sound[act];
1991 }
1992
1993 static void InitGameModeSoundInfo(void)
1994 {
1995   int i;
1996
1997   // set values to -1 to identify later as "uninitialized" values
1998   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1999     menu.sound[i] = -1;
2000
2001   // initialize gamemode/sound mapping from static configuration
2002   for (i = 0; gamemode_to_sound[i].sound > -1; i++)
2003   {
2004     int gamemode = gamemode_to_sound[i].gamemode;
2005     int sound    = gamemode_to_sound[i].sound;
2006
2007     if (gamemode < 0)
2008       gamemode = GAME_MODE_DEFAULT;
2009
2010     menu.sound[gamemode] = sound;
2011   }
2012
2013   // now set all '-1' values to levelset specific default values
2014   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
2015     if (menu.sound[i] == -1)
2016       menu.sound[i] = menu.sound[GAME_MODE_DEFAULT];
2017 }
2018
2019 static void set_sound_parameters(int sound, char **parameter_raw)
2020 {
2021   int parameter[NUM_SND_ARGS];
2022   int i;
2023
2024   // get integer values from string parameters
2025   for (i = 0; i < NUM_SND_ARGS; i++)
2026     parameter[i] =
2027       get_parameter_value(parameter_raw[i],
2028                           sound_config_suffix[i].token,
2029                           sound_config_suffix[i].type);
2030
2031   // explicit loop mode setting in configuration overrides default value
2032   if (parameter[SND_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
2033     sound_info[sound].loop = parameter[SND_ARG_MODE_LOOP];
2034
2035   // sound volume to change the original volume when loading the sound file
2036   sound_info[sound].volume = parameter[SND_ARG_VOLUME];
2037
2038   // sound priority to give certain sounds a higher or lower priority
2039   sound_info[sound].priority = parameter[SND_ARG_PRIORITY];
2040 }
2041
2042 static void InitSoundInfo(void)
2043 {
2044   int *sound_effect_properties;
2045   int num_sounds = getSoundListSize();
2046   int i, j;
2047
2048   checked_free(sound_info);
2049
2050   sound_effect_properties = checked_calloc(num_sounds * sizeof(int));
2051   sound_info = checked_calloc(num_sounds * sizeof(struct SoundInfo));
2052
2053   // initialize sound effect for all elements to "no sound"
2054   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2055     for (j = 0; j < NUM_ACTIONS; j++)
2056       element_info[i].sound[j] = SND_UNDEFINED;
2057
2058   for (i = 0; i < num_sounds; i++)
2059   {
2060     struct FileInfo *sound = getSoundListEntry(i);
2061     int len_effect_text = strlen(sound->token);
2062
2063     sound_effect_properties[i] = ACTION_OTHER;
2064     sound_info[i].loop = FALSE;         // default: play sound only once
2065
2066     // determine all loop sounds and identify certain sound classes
2067
2068     for (j = 0; element_action_info[j].suffix; j++)
2069     {
2070       int len_action_text = strlen(element_action_info[j].suffix);
2071
2072       if (len_action_text < len_effect_text &&
2073           strEqual(&sound->token[len_effect_text - len_action_text],
2074                    element_action_info[j].suffix))
2075       {
2076         sound_effect_properties[i] = element_action_info[j].value;
2077         sound_info[i].loop = element_action_info[j].is_loop_sound;
2078
2079         break;
2080       }
2081     }
2082
2083     // associate elements and some selected sound actions
2084
2085     for (j = 0; j < MAX_NUM_ELEMENTS; j++)
2086     {
2087       if (element_info[j].class_name)
2088       {
2089         int len_class_text = strlen(element_info[j].class_name);
2090
2091         if (len_class_text + 1 < len_effect_text &&
2092             strncmp(sound->token,
2093                     element_info[j].class_name, len_class_text) == 0 &&
2094             sound->token[len_class_text] == '.')
2095         {
2096           int sound_action_value = sound_effect_properties[i];
2097
2098           element_info[j].sound[sound_action_value] = i;
2099         }
2100       }
2101     }
2102
2103     set_sound_parameters(i, sound->parameter);
2104   }
2105
2106   free(sound_effect_properties);
2107 }
2108
2109 static void InitGameModeMusicInfo(void)
2110 {
2111   struct PropertyMapping *property_mapping = getMusicListPropertyMapping();
2112   int num_property_mappings = getMusicListPropertyMappingSize();
2113   int default_levelset_music = -1;
2114   int i;
2115
2116   // set values to -1 to identify later as "uninitialized" values
2117   for (i = 0; i < MAX_LEVELS; i++)
2118     levelset.music[i] = -1;
2119   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
2120     menu.music[i] = -1;
2121
2122   // initialize gamemode/music mapping from static configuration
2123   for (i = 0; gamemode_to_music[i].music > -1; i++)
2124   {
2125     int gamemode = gamemode_to_music[i].gamemode;
2126     int music    = gamemode_to_music[i].music;
2127
2128     if (gamemode < 0)
2129       gamemode = GAME_MODE_DEFAULT;
2130
2131     menu.music[gamemode] = music;
2132   }
2133
2134   // initialize gamemode/music mapping from dynamic configuration
2135   for (i = 0; i < num_property_mappings; i++)
2136   {
2137     int prefix   = property_mapping[i].base_index;
2138     int gamemode = property_mapping[i].ext2_index;
2139     int level    = property_mapping[i].ext3_index;
2140     int music    = property_mapping[i].artwork_index;
2141
2142     if (prefix < 0 || prefix >= NUM_MUSIC_PREFIXES)
2143       continue;
2144
2145     if (gamemode < 0)
2146       gamemode = GAME_MODE_DEFAULT;
2147
2148     // level specific music only allowed for in-game music
2149     if (level != -1 && gamemode == GAME_MODE_DEFAULT)
2150       gamemode = GAME_MODE_PLAYING;
2151
2152     if (level == -1)
2153     {
2154       level = 0;
2155       default_levelset_music = music;
2156     }
2157
2158     if (gamemode == GAME_MODE_PLAYING || gamemode == GAME_MODE_DEFAULT)
2159       levelset.music[level] = music;
2160     if (gamemode != GAME_MODE_PLAYING)
2161       menu.music[gamemode] = music;
2162   }
2163
2164   // now set all '-1' values to menu specific default values
2165   // (undefined values of "levelset.music[]" might stay at "-1" to
2166   // allow dynamic selection of music files from music directory!)
2167   for (i = 0; i < MAX_LEVELS; i++)
2168     if (levelset.music[i] == -1)
2169       levelset.music[i] = default_levelset_music;
2170   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
2171     if (menu.music[i] == -1)
2172       menu.music[i] = menu.music[GAME_MODE_DEFAULT];
2173 }
2174
2175 static void set_music_parameters(int music, char **parameter_raw)
2176 {
2177   int parameter[NUM_MUS_ARGS];
2178   int i;
2179
2180   // get integer values from string parameters
2181   for (i = 0; i < NUM_MUS_ARGS; i++)
2182     parameter[i] =
2183       get_parameter_value(parameter_raw[i],
2184                           music_config_suffix[i].token,
2185                           music_config_suffix[i].type);
2186
2187   // explicit loop mode setting in configuration overrides default value
2188   if (parameter[MUS_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
2189     music_info[music].loop = parameter[MUS_ARG_MODE_LOOP];
2190 }
2191
2192 static void InitMusicInfo(void)
2193 {
2194   int num_music = getMusicListSize();
2195   int i, j;
2196
2197   checked_free(music_info);
2198
2199   music_info = checked_calloc(num_music * sizeof(struct MusicInfo));
2200
2201   for (i = 0; i < num_music; i++)
2202   {
2203     struct FileInfo *music = getMusicListEntry(i);
2204     int len_music_text = strlen(music->token);
2205
2206     music_info[i].loop = TRUE;          // default: play music in loop mode
2207
2208     // determine all loop music
2209
2210     for (j = 0; music_prefix_info[j].prefix; j++)
2211     {
2212       int len_prefix_text = strlen(music_prefix_info[j].prefix);
2213
2214       if (len_prefix_text < len_music_text &&
2215           strncmp(music->token,
2216                   music_prefix_info[j].prefix, len_prefix_text) == 0)
2217       {
2218         music_info[i].loop = music_prefix_info[j].is_loop_music;
2219
2220         break;
2221       }
2222     }
2223
2224     set_music_parameters(i, music->parameter);
2225   }
2226 }
2227
2228 static void ReinitializeGraphics(void)
2229 {
2230   print_timestamp_init("ReinitializeGraphics");
2231
2232   InitGfxTileSizeInfo(game.tile_size, TILESIZE);
2233
2234   InitGraphicInfo();                    // graphic properties mapping
2235   print_timestamp_time("InitGraphicInfo");
2236   InitElementGraphicInfo();             // element game graphic mapping
2237   print_timestamp_time("InitElementGraphicInfo");
2238   InitElementSpecialGraphicInfo();      // element special graphic mapping
2239   print_timestamp_time("InitElementSpecialGraphicInfo");
2240
2241   InitElementSmallImages();             // scale elements to all needed sizes
2242   print_timestamp_time("InitElementSmallImages");
2243   InitScaledImages();                   // scale all other images, if needed
2244   print_timestamp_time("InitScaledImages");
2245   InitBitmapPointers();                 // set standard size bitmap pointers
2246   print_timestamp_time("InitBitmapPointers");
2247   InitFontGraphicInfo();                // initialize text drawing functions
2248   print_timestamp_time("InitFontGraphicInfo");
2249   InitGlobalAnimGraphicInfo();          // initialize global animation config
2250   print_timestamp_time("InitGlobalAnimGraphicInfo");
2251
2252   InitImageTextures();                  // create textures for certain images
2253   print_timestamp_time("InitImageTextures");
2254
2255   InitGraphicInfo_EM();                 // graphic mapping for EM engine
2256   print_timestamp_time("InitGraphicInfo_EM");
2257
2258   InitGraphicCompatibilityInfo();
2259   print_timestamp_time("InitGraphicCompatibilityInfo");
2260
2261   SetMainBackgroundImage(IMG_BACKGROUND);
2262   print_timestamp_time("SetMainBackgroundImage");
2263   SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
2264   print_timestamp_time("SetDoorBackgroundImage");
2265
2266   InitGadgets();
2267   print_timestamp_time("InitGadgets");
2268   InitDoors();
2269   print_timestamp_time("InitDoors");
2270
2271   print_timestamp_done("ReinitializeGraphics");
2272 }
2273
2274 static void ReinitializeSounds(void)
2275 {
2276   InitSoundInfo();              // sound properties mapping
2277   InitElementSoundInfo();       // element game sound mapping
2278   InitGameModeSoundInfo();      // game mode sound mapping
2279   InitGlobalAnimSoundInfo();    // global animation sound settings
2280
2281   InitPlayLevelSound();         // internal game sound settings
2282 }
2283
2284 static void ReinitializeMusic(void)
2285 {
2286   InitMusicInfo();              // music properties mapping
2287   InitGameModeMusicInfo();      // game mode music mapping
2288   InitGlobalAnimMusicInfo();    // global animation music settings
2289 }
2290
2291 static int get_special_property_bit(int element, int property_bit_nr)
2292 {
2293   struct PropertyBitInfo
2294   {
2295     int element;
2296     int bit_nr;
2297   };
2298
2299   static struct PropertyBitInfo pb_can_move_into_acid[] =
2300   {
2301     // the player may be able fall into acid when gravity is activated
2302     { EL_PLAYER_1,              0       },
2303     { EL_PLAYER_2,              0       },
2304     { EL_PLAYER_3,              0       },
2305     { EL_PLAYER_4,              0       },
2306     { EL_SP_MURPHY,             0       },
2307     { EL_SOKOBAN_FIELD_PLAYER,  0       },
2308
2309     // all elements that can move may be able to also move into acid
2310     { EL_BUG,                   1       },
2311     { EL_BUG_LEFT,              1       },
2312     { EL_BUG_RIGHT,             1       },
2313     { EL_BUG_UP,                1       },
2314     { EL_BUG_DOWN,              1       },
2315     { EL_SPACESHIP,             2       },
2316     { EL_SPACESHIP_LEFT,        2       },
2317     { EL_SPACESHIP_RIGHT,       2       },
2318     { EL_SPACESHIP_UP,          2       },
2319     { EL_SPACESHIP_DOWN,        2       },
2320     { EL_BD_BUTTERFLY,          3       },
2321     { EL_BD_BUTTERFLY_LEFT,     3       },
2322     { EL_BD_BUTTERFLY_RIGHT,    3       },
2323     { EL_BD_BUTTERFLY_UP,       3       },
2324     { EL_BD_BUTTERFLY_DOWN,     3       },
2325     { EL_BD_FIREFLY,            4       },
2326     { EL_BD_FIREFLY_LEFT,       4       },
2327     { EL_BD_FIREFLY_RIGHT,      4       },
2328     { EL_BD_FIREFLY_UP,         4       },
2329     { EL_BD_FIREFLY_DOWN,       4       },
2330     { EL_YAMYAM,                5       },
2331     { EL_YAMYAM_LEFT,           5       },
2332     { EL_YAMYAM_RIGHT,          5       },
2333     { EL_YAMYAM_UP,             5       },
2334     { EL_YAMYAM_DOWN,           5       },
2335     { EL_DARK_YAMYAM,           6       },
2336     { EL_ROBOT,                 7       },
2337     { EL_PACMAN,                8       },
2338     { EL_PACMAN_LEFT,           8       },
2339     { EL_PACMAN_RIGHT,          8       },
2340     { EL_PACMAN_UP,             8       },
2341     { EL_PACMAN_DOWN,           8       },
2342     { EL_MOLE,                  9       },
2343     { EL_MOLE_LEFT,             9       },
2344     { EL_MOLE_RIGHT,            9       },
2345     { EL_MOLE_UP,               9       },
2346     { EL_MOLE_DOWN,             9       },
2347     { EL_PENGUIN,               10      },
2348     { EL_PIG,                   11      },
2349     { EL_DRAGON,                12      },
2350     { EL_SATELLITE,             13      },
2351     { EL_SP_SNIKSNAK,           14      },
2352     { EL_SP_ELECTRON,           15      },
2353     { EL_BALLOON,               16      },
2354     { EL_SPRING,                17      },
2355     { EL_EMC_ANDROID,           18      },
2356
2357     { -1,                       -1      },
2358   };
2359
2360   static struct PropertyBitInfo pb_dont_collide_with[] =
2361   {
2362     { EL_SP_SNIKSNAK,           0       },
2363     { EL_SP_ELECTRON,           1       },
2364
2365     { -1,                       -1      },
2366   };
2367
2368   static struct
2369   {
2370     int bit_nr;
2371     struct PropertyBitInfo *pb_info;
2372   } pb_definition[] =
2373   {
2374     { EP_CAN_MOVE_INTO_ACID,    pb_can_move_into_acid   },
2375     { EP_DONT_COLLIDE_WITH,     pb_dont_collide_with    },
2376
2377     { -1,                       NULL                    },
2378   };
2379
2380   struct PropertyBitInfo *pb_info = NULL;
2381   int i;
2382
2383   for (i = 0; pb_definition[i].bit_nr != -1; i++)
2384     if (pb_definition[i].bit_nr == property_bit_nr)
2385       pb_info = pb_definition[i].pb_info;
2386
2387   if (pb_info == NULL)
2388     return -1;
2389
2390   for (i = 0; pb_info[i].element != -1; i++)
2391     if (pb_info[i].element == element)
2392       return pb_info[i].bit_nr;
2393
2394   return -1;
2395 }
2396
2397 void setBitfieldProperty(int *bitfield, int property_bit_nr, int element,
2398                          boolean property_value)
2399 {
2400   int bit_nr = get_special_property_bit(element, property_bit_nr);
2401
2402   if (bit_nr > -1)
2403   {
2404     if (property_value)
2405       *bitfield |=  (1 << bit_nr);
2406     else
2407       *bitfield &= ~(1 << bit_nr);
2408   }
2409 }
2410
2411 boolean getBitfieldProperty(int *bitfield, int property_bit_nr, int element)
2412 {
2413   int bit_nr = get_special_property_bit(element, property_bit_nr);
2414
2415   if (bit_nr > -1)
2416     return ((*bitfield & (1 << bit_nr)) != 0);
2417
2418   return FALSE;
2419 }
2420
2421 static void ResolveGroupElementExt(int group_element, int recursion_depth)
2422 {
2423   static int group_nr;
2424   static struct ElementGroupInfo *group;
2425   struct ElementGroupInfo *actual_group = element_info[group_element].group;
2426   int i;
2427
2428   if (actual_group == NULL)                     // not yet initialized
2429     return;
2430
2431   if (recursion_depth > NUM_GROUP_ELEMENTS)     // recursion too deep
2432   {
2433     Error(ERR_WARN, "recursion too deep when resolving group element %d",
2434           group_element - EL_GROUP_START + 1);
2435
2436     // replace element which caused too deep recursion by question mark
2437     group->element_resolved[group->num_elements_resolved++] = EL_UNKNOWN;
2438
2439     return;
2440   }
2441
2442   if (recursion_depth == 0)                     // initialization
2443   {
2444     group = actual_group;
2445     group_nr = GROUP_NR(group_element);
2446
2447     group->num_elements_resolved = 0;
2448     group->choice_pos = 0;
2449
2450     for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2451       element_info[i].in_group[group_nr] = FALSE;
2452   }
2453
2454   for (i = 0; i < actual_group->num_elements; i++)
2455   {
2456     int element = actual_group->element[i];
2457
2458     if (group->num_elements_resolved == NUM_FILE_ELEMENTS)
2459       break;
2460
2461     if (IS_GROUP_ELEMENT(element))
2462       ResolveGroupElementExt(element, recursion_depth + 1);
2463     else
2464     {
2465       group->element_resolved[group->num_elements_resolved++] = element;
2466       element_info[element].in_group[group_nr] = TRUE;
2467     }
2468   }
2469 }
2470
2471 void ResolveGroupElement(int group_element)
2472 {
2473   ResolveGroupElementExt(group_element, 0);
2474 }
2475
2476 void InitElementPropertiesStatic(void)
2477 {
2478   static boolean clipboard_elements_initialized = FALSE;
2479
2480   static int ep_diggable[] =
2481   {
2482     EL_SAND,
2483     EL_SP_BASE,
2484     EL_SP_BUGGY_BASE,
2485     EL_SP_BUGGY_BASE_ACTIVATING,
2486     EL_TRAP,
2487     EL_INVISIBLE_SAND,
2488     EL_INVISIBLE_SAND_ACTIVE,
2489     EL_EMC_GRASS,
2490
2491     // !!! currently not diggable, but handled by 'ep_dont_run_into' !!!
2492     // (if amoeba can grow into anything diggable, maybe keep these out)
2493 #if 0
2494     EL_LANDMINE,
2495     EL_DC_LANDMINE,
2496     EL_TRAP_ACTIVE,
2497     EL_SP_BUGGY_BASE_ACTIVE,
2498     EL_EMC_PLANT,
2499 #endif
2500
2501     -1
2502   };
2503
2504   static int ep_collectible_only[] =
2505   {
2506     EL_BD_DIAMOND,
2507     EL_EMERALD,
2508     EL_DIAMOND,
2509     EL_EMERALD_YELLOW,
2510     EL_EMERALD_RED,
2511     EL_EMERALD_PURPLE,
2512     EL_KEY_1,
2513     EL_KEY_2,
2514     EL_KEY_3,
2515     EL_KEY_4,
2516     EL_EM_KEY_1,
2517     EL_EM_KEY_2,
2518     EL_EM_KEY_3,
2519     EL_EM_KEY_4,
2520     EL_EMC_KEY_5,
2521     EL_EMC_KEY_6,
2522     EL_EMC_KEY_7,
2523     EL_EMC_KEY_8,
2524     EL_DYNAMITE,
2525     EL_EM_DYNAMITE,
2526     EL_DYNABOMB_INCREASE_NUMBER,
2527     EL_DYNABOMB_INCREASE_SIZE,
2528     EL_DYNABOMB_INCREASE_POWER,
2529     EL_SP_INFOTRON,
2530     EL_SP_DISK_RED,
2531     EL_PEARL,
2532     EL_CRYSTAL,
2533     EL_DC_KEY_WHITE,
2534     EL_SHIELD_NORMAL,
2535     EL_SHIELD_DEADLY,
2536     EL_EXTRA_TIME,
2537     EL_ENVELOPE_1,
2538     EL_ENVELOPE_2,
2539     EL_ENVELOPE_3,
2540     EL_ENVELOPE_4,
2541     EL_SPEED_PILL,
2542     EL_EMC_LENSES,
2543     EL_EMC_MAGNIFIER,
2544
2545 #if 0
2546     // !!! handle separately !!!
2547     EL_DC_LANDMINE,     // deadly when running into, but can be snapped
2548 #endif
2549
2550     -1
2551   };
2552
2553   static int ep_dont_run_into[] =
2554   {
2555     // same elements as in 'ep_dont_touch'
2556     EL_BUG,
2557     EL_SPACESHIP,
2558     EL_BD_BUTTERFLY,
2559     EL_BD_FIREFLY,
2560
2561     // same elements as in 'ep_dont_collide_with'
2562     EL_YAMYAM,
2563     EL_DARK_YAMYAM,
2564     EL_ROBOT,
2565     EL_PACMAN,
2566     EL_SP_SNIKSNAK,
2567     EL_SP_ELECTRON,
2568
2569     // new elements
2570     EL_AMOEBA_DROP,
2571     EL_ACID,
2572
2573     // !!! maybe this should better be handled by 'ep_diggable' !!!
2574 #if 1
2575     EL_LANDMINE,
2576     EL_DC_LANDMINE,
2577     EL_TRAP_ACTIVE,
2578     EL_SP_BUGGY_BASE_ACTIVE,
2579     EL_EMC_PLANT,
2580 #endif
2581
2582     -1
2583   };
2584
2585   static int ep_dont_collide_with[] =
2586   {
2587     // same elements as in 'ep_dont_touch'
2588     EL_BUG,
2589     EL_SPACESHIP,
2590     EL_BD_BUTTERFLY,
2591     EL_BD_FIREFLY,
2592
2593     // new elements
2594     EL_YAMYAM,
2595     EL_DARK_YAMYAM,
2596     EL_ROBOT,
2597     EL_PACMAN,
2598     EL_SP_SNIKSNAK,
2599     EL_SP_ELECTRON,
2600
2601     -1
2602   };
2603
2604   static int ep_dont_touch[] =
2605   {
2606     EL_BUG,
2607     EL_SPACESHIP,
2608     EL_BD_BUTTERFLY,
2609     EL_BD_FIREFLY,
2610
2611     -1
2612   };
2613
2614   static int ep_indestructible[] =
2615   {
2616     EL_STEELWALL,
2617     EL_ACID,
2618     EL_ACID_POOL_TOPLEFT,
2619     EL_ACID_POOL_TOPRIGHT,
2620     EL_ACID_POOL_BOTTOMLEFT,
2621     EL_ACID_POOL_BOTTOM,
2622     EL_ACID_POOL_BOTTOMRIGHT,
2623     EL_SP_HARDWARE_GRAY,
2624     EL_SP_HARDWARE_GREEN,
2625     EL_SP_HARDWARE_BLUE,
2626     EL_SP_HARDWARE_RED,
2627     EL_SP_HARDWARE_YELLOW,
2628     EL_SP_HARDWARE_BASE_1,
2629     EL_SP_HARDWARE_BASE_2,
2630     EL_SP_HARDWARE_BASE_3,
2631     EL_SP_HARDWARE_BASE_4,
2632     EL_SP_HARDWARE_BASE_5,
2633     EL_SP_HARDWARE_BASE_6,
2634     EL_INVISIBLE_STEELWALL,
2635     EL_INVISIBLE_STEELWALL_ACTIVE,
2636     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2637     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2638     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2639     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2640     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2641     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2642     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2643     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2644     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2645     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2646     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2647     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2648     EL_LIGHT_SWITCH,
2649     EL_LIGHT_SWITCH_ACTIVE,
2650     EL_SIGN_EXCLAMATION,
2651     EL_SIGN_RADIOACTIVITY,
2652     EL_SIGN_STOP,
2653     EL_SIGN_WHEELCHAIR,
2654     EL_SIGN_PARKING,
2655     EL_SIGN_NO_ENTRY,
2656     EL_SIGN_UNUSED_1,
2657     EL_SIGN_GIVE_WAY,
2658     EL_SIGN_ENTRY_FORBIDDEN,
2659     EL_SIGN_EMERGENCY_EXIT,
2660     EL_SIGN_YIN_YANG,
2661     EL_SIGN_UNUSED_2,
2662     EL_SIGN_SPERMS,
2663     EL_SIGN_BULLET,
2664     EL_SIGN_HEART,
2665     EL_SIGN_CROSS,
2666     EL_SIGN_FRANKIE,
2667     EL_STEEL_EXIT_CLOSED,
2668     EL_STEEL_EXIT_OPEN,
2669     EL_STEEL_EXIT_OPENING,
2670     EL_STEEL_EXIT_CLOSING,
2671     EL_EM_STEEL_EXIT_CLOSED,
2672     EL_EM_STEEL_EXIT_OPEN,
2673     EL_EM_STEEL_EXIT_OPENING,
2674     EL_EM_STEEL_EXIT_CLOSING,
2675     EL_DC_STEELWALL_1_LEFT,
2676     EL_DC_STEELWALL_1_RIGHT,
2677     EL_DC_STEELWALL_1_TOP,
2678     EL_DC_STEELWALL_1_BOTTOM,
2679     EL_DC_STEELWALL_1_HORIZONTAL,
2680     EL_DC_STEELWALL_1_VERTICAL,
2681     EL_DC_STEELWALL_1_TOPLEFT,
2682     EL_DC_STEELWALL_1_TOPRIGHT,
2683     EL_DC_STEELWALL_1_BOTTOMLEFT,
2684     EL_DC_STEELWALL_1_BOTTOMRIGHT,
2685     EL_DC_STEELWALL_1_TOPLEFT_2,
2686     EL_DC_STEELWALL_1_TOPRIGHT_2,
2687     EL_DC_STEELWALL_1_BOTTOMLEFT_2,
2688     EL_DC_STEELWALL_1_BOTTOMRIGHT_2,
2689     EL_DC_STEELWALL_2_LEFT,
2690     EL_DC_STEELWALL_2_RIGHT,
2691     EL_DC_STEELWALL_2_TOP,
2692     EL_DC_STEELWALL_2_BOTTOM,
2693     EL_DC_STEELWALL_2_HORIZONTAL,
2694     EL_DC_STEELWALL_2_VERTICAL,
2695     EL_DC_STEELWALL_2_MIDDLE,
2696     EL_DC_STEELWALL_2_SINGLE,
2697     EL_STEELWALL_SLIPPERY,
2698     EL_EMC_STEELWALL_1,
2699     EL_EMC_STEELWALL_2,
2700     EL_EMC_STEELWALL_3,
2701     EL_EMC_STEELWALL_4,
2702     EL_CRYSTAL,
2703     EL_GATE_1,
2704     EL_GATE_2,
2705     EL_GATE_3,
2706     EL_GATE_4,
2707     EL_GATE_1_GRAY,
2708     EL_GATE_2_GRAY,
2709     EL_GATE_3_GRAY,
2710     EL_GATE_4_GRAY,
2711     EL_GATE_1_GRAY_ACTIVE,
2712     EL_GATE_2_GRAY_ACTIVE,
2713     EL_GATE_3_GRAY_ACTIVE,
2714     EL_GATE_4_GRAY_ACTIVE,
2715     EL_EM_GATE_1,
2716     EL_EM_GATE_2,
2717     EL_EM_GATE_3,
2718     EL_EM_GATE_4,
2719     EL_EM_GATE_1_GRAY,
2720     EL_EM_GATE_2_GRAY,
2721     EL_EM_GATE_3_GRAY,
2722     EL_EM_GATE_4_GRAY,
2723     EL_EM_GATE_1_GRAY_ACTIVE,
2724     EL_EM_GATE_2_GRAY_ACTIVE,
2725     EL_EM_GATE_3_GRAY_ACTIVE,
2726     EL_EM_GATE_4_GRAY_ACTIVE,
2727     EL_EMC_GATE_5,
2728     EL_EMC_GATE_6,
2729     EL_EMC_GATE_7,
2730     EL_EMC_GATE_8,
2731     EL_EMC_GATE_5_GRAY,
2732     EL_EMC_GATE_6_GRAY,
2733     EL_EMC_GATE_7_GRAY,
2734     EL_EMC_GATE_8_GRAY,
2735     EL_EMC_GATE_5_GRAY_ACTIVE,
2736     EL_EMC_GATE_6_GRAY_ACTIVE,
2737     EL_EMC_GATE_7_GRAY_ACTIVE,
2738     EL_EMC_GATE_8_GRAY_ACTIVE,
2739     EL_DC_GATE_WHITE,
2740     EL_DC_GATE_WHITE_GRAY,
2741     EL_DC_GATE_WHITE_GRAY_ACTIVE,
2742     EL_DC_GATE_FAKE_GRAY,
2743     EL_SWITCHGATE_OPEN,
2744     EL_SWITCHGATE_OPENING,
2745     EL_SWITCHGATE_CLOSED,
2746     EL_SWITCHGATE_CLOSING,
2747     EL_DC_SWITCHGATE_SWITCH_UP,
2748     EL_DC_SWITCHGATE_SWITCH_DOWN,
2749     EL_TIMEGATE_OPEN,
2750     EL_TIMEGATE_OPENING,
2751     EL_TIMEGATE_CLOSED,
2752     EL_TIMEGATE_CLOSING,
2753     EL_DC_TIMEGATE_SWITCH,
2754     EL_DC_TIMEGATE_SWITCH_ACTIVE,
2755     EL_TUBE_ANY,
2756     EL_TUBE_VERTICAL,
2757     EL_TUBE_HORIZONTAL,
2758     EL_TUBE_VERTICAL_LEFT,
2759     EL_TUBE_VERTICAL_RIGHT,
2760     EL_TUBE_HORIZONTAL_UP,
2761     EL_TUBE_HORIZONTAL_DOWN,
2762     EL_TUBE_LEFT_UP,
2763     EL_TUBE_LEFT_DOWN,
2764     EL_TUBE_RIGHT_UP,
2765     EL_TUBE_RIGHT_DOWN,
2766     EL_EXPANDABLE_STEELWALL_HORIZONTAL,
2767     EL_EXPANDABLE_STEELWALL_VERTICAL,
2768     EL_EXPANDABLE_STEELWALL_ANY,
2769
2770     -1
2771   };
2772
2773   static int ep_slippery[] =
2774   {
2775     EL_WALL_SLIPPERY,
2776     EL_BD_WALL,
2777     EL_ROCK,
2778     EL_BD_ROCK,
2779     EL_EMERALD,
2780     EL_BD_DIAMOND,
2781     EL_EMERALD_YELLOW,
2782     EL_EMERALD_RED,
2783     EL_EMERALD_PURPLE,
2784     EL_DIAMOND,
2785     EL_BOMB,
2786     EL_NUT,
2787     EL_ROBOT_WHEEL_ACTIVE,
2788     EL_ROBOT_WHEEL,
2789     EL_TIME_ORB_FULL,
2790     EL_TIME_ORB_EMPTY,
2791     EL_LAMP_ACTIVE,
2792     EL_LAMP,
2793     EL_ACID_POOL_TOPLEFT,
2794     EL_ACID_POOL_TOPRIGHT,
2795     EL_SATELLITE,
2796     EL_SP_ZONK,
2797     EL_SP_INFOTRON,
2798     EL_SP_CHIP_SINGLE,
2799     EL_SP_CHIP_LEFT,
2800     EL_SP_CHIP_RIGHT,
2801     EL_SP_CHIP_TOP,
2802     EL_SP_CHIP_BOTTOM,
2803     EL_SPEED_PILL,
2804     EL_STEELWALL_SLIPPERY,
2805     EL_PEARL,
2806     EL_CRYSTAL,
2807     EL_EMC_WALL_SLIPPERY_1,
2808     EL_EMC_WALL_SLIPPERY_2,
2809     EL_EMC_WALL_SLIPPERY_3,
2810     EL_EMC_WALL_SLIPPERY_4,
2811     EL_EMC_MAGIC_BALL,
2812     EL_EMC_MAGIC_BALL_ACTIVE,
2813
2814     -1
2815   };
2816
2817   static int ep_can_change[] =
2818   {
2819     -1
2820   };
2821
2822   static int ep_can_move[] =
2823   {
2824     // same elements as in 'pb_can_move_into_acid'
2825     EL_BUG,
2826     EL_SPACESHIP,
2827     EL_BD_BUTTERFLY,
2828     EL_BD_FIREFLY,
2829     EL_YAMYAM,
2830     EL_DARK_YAMYAM,
2831     EL_ROBOT,
2832     EL_PACMAN,
2833     EL_MOLE,
2834     EL_PENGUIN,
2835     EL_PIG,
2836     EL_DRAGON,
2837     EL_SATELLITE,
2838     EL_SP_SNIKSNAK,
2839     EL_SP_ELECTRON,
2840     EL_BALLOON,
2841     EL_SPRING,
2842     EL_EMC_ANDROID,
2843
2844     -1
2845   };
2846
2847   static int ep_can_fall[] =
2848   {
2849     EL_ROCK,
2850     EL_BD_ROCK,
2851     EL_EMERALD,
2852     EL_BD_DIAMOND,
2853     EL_EMERALD_YELLOW,
2854     EL_EMERALD_RED,
2855     EL_EMERALD_PURPLE,
2856     EL_DIAMOND,
2857     EL_BOMB,
2858     EL_NUT,
2859     EL_AMOEBA_DROP,
2860     EL_QUICKSAND_FULL,
2861     EL_QUICKSAND_FAST_FULL,
2862     EL_MAGIC_WALL_FULL,
2863     EL_BD_MAGIC_WALL_FULL,
2864     EL_DC_MAGIC_WALL_FULL,
2865     EL_TIME_ORB_FULL,
2866     EL_TIME_ORB_EMPTY,
2867     EL_SP_ZONK,
2868     EL_SP_INFOTRON,
2869     EL_SP_DISK_ORANGE,
2870     EL_PEARL,
2871     EL_CRYSTAL,
2872     EL_SPRING,
2873     EL_DX_SUPABOMB,
2874
2875     -1
2876   };
2877
2878   static int ep_can_smash_player[] =
2879   {
2880     EL_ROCK,
2881     EL_BD_ROCK,
2882     EL_EMERALD,
2883     EL_BD_DIAMOND,
2884     EL_EMERALD_YELLOW,
2885     EL_EMERALD_RED,
2886     EL_EMERALD_PURPLE,
2887     EL_DIAMOND,
2888     EL_BOMB,
2889     EL_NUT,
2890     EL_AMOEBA_DROP,
2891     EL_TIME_ORB_FULL,
2892     EL_TIME_ORB_EMPTY,
2893     EL_SP_ZONK,
2894     EL_SP_INFOTRON,
2895     EL_SP_DISK_ORANGE,
2896     EL_PEARL,
2897     EL_CRYSTAL,
2898     EL_SPRING,
2899     EL_DX_SUPABOMB,
2900
2901     -1
2902   };
2903
2904   static int ep_can_smash_enemies[] =
2905   {
2906     EL_ROCK,
2907     EL_BD_ROCK,
2908     EL_SP_ZONK,
2909
2910     -1
2911   };
2912
2913   static int ep_can_smash_everything[] =
2914   {
2915     EL_ROCK,
2916     EL_BD_ROCK,
2917     EL_SP_ZONK,
2918
2919     -1
2920   };
2921
2922   static int ep_explodes_by_fire[] =
2923   {
2924     // same elements as in 'ep_explodes_impact'
2925     EL_BOMB,
2926     EL_SP_DISK_ORANGE,
2927     EL_DX_SUPABOMB,
2928
2929     // same elements as in 'ep_explodes_smashed'
2930     EL_SATELLITE,
2931     EL_PIG,
2932     EL_DRAGON,
2933     EL_MOLE,
2934
2935     // new elements
2936     EL_DYNAMITE,
2937     EL_DYNAMITE_ACTIVE,
2938     EL_EM_DYNAMITE,
2939     EL_EM_DYNAMITE_ACTIVE,
2940     EL_DYNABOMB_PLAYER_1_ACTIVE,
2941     EL_DYNABOMB_PLAYER_2_ACTIVE,
2942     EL_DYNABOMB_PLAYER_3_ACTIVE,
2943     EL_DYNABOMB_PLAYER_4_ACTIVE,
2944     EL_DYNABOMB_INCREASE_NUMBER,
2945     EL_DYNABOMB_INCREASE_SIZE,
2946     EL_DYNABOMB_INCREASE_POWER,
2947     EL_SP_DISK_RED_ACTIVE,
2948     EL_BUG,
2949     EL_PENGUIN,
2950     EL_SP_DISK_RED,
2951     EL_SP_DISK_YELLOW,
2952     EL_SP_SNIKSNAK,
2953     EL_SP_ELECTRON,
2954 #if 0
2955     EL_BLACK_ORB,
2956 #endif
2957
2958     -1
2959   };
2960
2961   static int ep_explodes_smashed[] =
2962   {
2963     // same elements as in 'ep_explodes_impact'
2964     EL_BOMB,
2965     EL_SP_DISK_ORANGE,
2966     EL_DX_SUPABOMB,
2967
2968     // new elements
2969     EL_SATELLITE,
2970     EL_PIG,
2971     EL_DRAGON,
2972     EL_MOLE,
2973
2974     -1
2975   };
2976
2977   static int ep_explodes_impact[] =
2978   {
2979     EL_BOMB,
2980     EL_SP_DISK_ORANGE,
2981     EL_DX_SUPABOMB,
2982
2983     -1
2984   };
2985
2986   static int ep_walkable_over[] =
2987   {
2988     EL_EMPTY_SPACE,
2989     EL_SP_EMPTY_SPACE,
2990     EL_SOKOBAN_FIELD_EMPTY,
2991     EL_EXIT_OPEN,
2992     EL_EM_EXIT_OPEN,
2993     EL_EM_EXIT_OPENING,
2994     EL_SP_EXIT_OPEN,
2995     EL_SP_EXIT_OPENING,
2996     EL_STEEL_EXIT_OPEN,
2997     EL_EM_STEEL_EXIT_OPEN,
2998     EL_EM_STEEL_EXIT_OPENING,
2999     EL_GATE_1,
3000     EL_GATE_2,
3001     EL_GATE_3,
3002     EL_GATE_4,
3003     EL_GATE_1_GRAY,
3004     EL_GATE_2_GRAY,
3005     EL_GATE_3_GRAY,
3006     EL_GATE_4_GRAY,
3007     EL_GATE_1_GRAY_ACTIVE,
3008     EL_GATE_2_GRAY_ACTIVE,
3009     EL_GATE_3_GRAY_ACTIVE,
3010     EL_GATE_4_GRAY_ACTIVE,
3011     EL_PENGUIN,
3012     EL_PIG,
3013     EL_DRAGON,
3014
3015     -1
3016   };
3017
3018   static int ep_walkable_inside[] =
3019   {
3020     EL_TUBE_ANY,
3021     EL_TUBE_VERTICAL,
3022     EL_TUBE_HORIZONTAL,
3023     EL_TUBE_VERTICAL_LEFT,
3024     EL_TUBE_VERTICAL_RIGHT,
3025     EL_TUBE_HORIZONTAL_UP,
3026     EL_TUBE_HORIZONTAL_DOWN,
3027     EL_TUBE_LEFT_UP,
3028     EL_TUBE_LEFT_DOWN,
3029     EL_TUBE_RIGHT_UP,
3030     EL_TUBE_RIGHT_DOWN,
3031
3032     -1
3033   };
3034
3035   static int ep_walkable_under[] =
3036   {
3037     -1
3038   };
3039
3040   static int ep_passable_over[] =
3041   {
3042     EL_EM_GATE_1,
3043     EL_EM_GATE_2,
3044     EL_EM_GATE_3,
3045     EL_EM_GATE_4,
3046     EL_EM_GATE_1_GRAY,
3047     EL_EM_GATE_2_GRAY,
3048     EL_EM_GATE_3_GRAY,
3049     EL_EM_GATE_4_GRAY,
3050     EL_EM_GATE_1_GRAY_ACTIVE,
3051     EL_EM_GATE_2_GRAY_ACTIVE,
3052     EL_EM_GATE_3_GRAY_ACTIVE,
3053     EL_EM_GATE_4_GRAY_ACTIVE,
3054     EL_EMC_GATE_5,
3055     EL_EMC_GATE_6,
3056     EL_EMC_GATE_7,
3057     EL_EMC_GATE_8,
3058     EL_EMC_GATE_5_GRAY,
3059     EL_EMC_GATE_6_GRAY,
3060     EL_EMC_GATE_7_GRAY,
3061     EL_EMC_GATE_8_GRAY,
3062     EL_EMC_GATE_5_GRAY_ACTIVE,
3063     EL_EMC_GATE_6_GRAY_ACTIVE,
3064     EL_EMC_GATE_7_GRAY_ACTIVE,
3065     EL_EMC_GATE_8_GRAY_ACTIVE,
3066     EL_DC_GATE_WHITE,
3067     EL_DC_GATE_WHITE_GRAY,
3068     EL_DC_GATE_WHITE_GRAY_ACTIVE,
3069     EL_SWITCHGATE_OPEN,
3070     EL_TIMEGATE_OPEN,
3071
3072     -1
3073   };
3074
3075   static int ep_passable_inside[] =
3076   {
3077     EL_SP_PORT_LEFT,
3078     EL_SP_PORT_RIGHT,
3079     EL_SP_PORT_UP,
3080     EL_SP_PORT_DOWN,
3081     EL_SP_PORT_HORIZONTAL,
3082     EL_SP_PORT_VERTICAL,
3083     EL_SP_PORT_ANY,
3084     EL_SP_GRAVITY_PORT_LEFT,
3085     EL_SP_GRAVITY_PORT_RIGHT,
3086     EL_SP_GRAVITY_PORT_UP,
3087     EL_SP_GRAVITY_PORT_DOWN,
3088     EL_SP_GRAVITY_ON_PORT_LEFT,
3089     EL_SP_GRAVITY_ON_PORT_RIGHT,
3090     EL_SP_GRAVITY_ON_PORT_UP,
3091     EL_SP_GRAVITY_ON_PORT_DOWN,
3092     EL_SP_GRAVITY_OFF_PORT_LEFT,
3093     EL_SP_GRAVITY_OFF_PORT_RIGHT,
3094     EL_SP_GRAVITY_OFF_PORT_UP,
3095     EL_SP_GRAVITY_OFF_PORT_DOWN,
3096
3097     -1
3098   };
3099
3100   static int ep_passable_under[] =
3101   {
3102     -1
3103   };
3104
3105   static int ep_droppable[] =
3106   {
3107     -1
3108   };
3109
3110   static int ep_explodes_1x1_old[] =
3111   {
3112     -1
3113   };
3114
3115   static int ep_pushable[] =
3116   {
3117     EL_ROCK,
3118     EL_BOMB,
3119     EL_DX_SUPABOMB,
3120     EL_NUT,
3121     EL_TIME_ORB_EMPTY,
3122     EL_SP_ZONK,
3123     EL_SP_DISK_ORANGE,
3124     EL_SPRING,
3125     EL_BD_ROCK,
3126     EL_SOKOBAN_OBJECT,
3127     EL_SOKOBAN_FIELD_FULL,
3128     EL_SATELLITE,
3129     EL_SP_DISK_YELLOW,
3130     EL_BALLOON,
3131     EL_EMC_ANDROID,
3132
3133     -1
3134   };
3135
3136   static int ep_explodes_cross_old[] =
3137   {
3138     -1
3139   };
3140
3141   static int ep_protected[] =
3142   {
3143     // same elements as in 'ep_walkable_inside'
3144     EL_TUBE_ANY,
3145     EL_TUBE_VERTICAL,
3146     EL_TUBE_HORIZONTAL,
3147     EL_TUBE_VERTICAL_LEFT,
3148     EL_TUBE_VERTICAL_RIGHT,
3149     EL_TUBE_HORIZONTAL_UP,
3150     EL_TUBE_HORIZONTAL_DOWN,
3151     EL_TUBE_LEFT_UP,
3152     EL_TUBE_LEFT_DOWN,
3153     EL_TUBE_RIGHT_UP,
3154     EL_TUBE_RIGHT_DOWN,
3155
3156     // same elements as in 'ep_passable_over'
3157     EL_EM_GATE_1,
3158     EL_EM_GATE_2,
3159     EL_EM_GATE_3,
3160     EL_EM_GATE_4,
3161     EL_EM_GATE_1_GRAY,
3162     EL_EM_GATE_2_GRAY,
3163     EL_EM_GATE_3_GRAY,
3164     EL_EM_GATE_4_GRAY,
3165     EL_EM_GATE_1_GRAY_ACTIVE,
3166     EL_EM_GATE_2_GRAY_ACTIVE,
3167     EL_EM_GATE_3_GRAY_ACTIVE,
3168     EL_EM_GATE_4_GRAY_ACTIVE,
3169     EL_EMC_GATE_5,
3170     EL_EMC_GATE_6,
3171     EL_EMC_GATE_7,
3172     EL_EMC_GATE_8,
3173     EL_EMC_GATE_5_GRAY,
3174     EL_EMC_GATE_6_GRAY,
3175     EL_EMC_GATE_7_GRAY,
3176     EL_EMC_GATE_8_GRAY,
3177     EL_EMC_GATE_5_GRAY_ACTIVE,
3178     EL_EMC_GATE_6_GRAY_ACTIVE,
3179     EL_EMC_GATE_7_GRAY_ACTIVE,
3180     EL_EMC_GATE_8_GRAY_ACTIVE,
3181     EL_DC_GATE_WHITE,
3182     EL_DC_GATE_WHITE_GRAY,
3183     EL_DC_GATE_WHITE_GRAY_ACTIVE,
3184     EL_SWITCHGATE_OPEN,
3185     EL_TIMEGATE_OPEN,
3186
3187     // same elements as in 'ep_passable_inside'
3188     EL_SP_PORT_LEFT,
3189     EL_SP_PORT_RIGHT,
3190     EL_SP_PORT_UP,
3191     EL_SP_PORT_DOWN,
3192     EL_SP_PORT_HORIZONTAL,
3193     EL_SP_PORT_VERTICAL,
3194     EL_SP_PORT_ANY,
3195     EL_SP_GRAVITY_PORT_LEFT,
3196     EL_SP_GRAVITY_PORT_RIGHT,
3197     EL_SP_GRAVITY_PORT_UP,
3198     EL_SP_GRAVITY_PORT_DOWN,
3199     EL_SP_GRAVITY_ON_PORT_LEFT,
3200     EL_SP_GRAVITY_ON_PORT_RIGHT,
3201     EL_SP_GRAVITY_ON_PORT_UP,
3202     EL_SP_GRAVITY_ON_PORT_DOWN,
3203     EL_SP_GRAVITY_OFF_PORT_LEFT,
3204     EL_SP_GRAVITY_OFF_PORT_RIGHT,
3205     EL_SP_GRAVITY_OFF_PORT_UP,
3206     EL_SP_GRAVITY_OFF_PORT_DOWN,
3207
3208     -1
3209   };
3210
3211   static int ep_throwable[] =
3212   {
3213     -1
3214   };
3215
3216   static int ep_can_explode[] =
3217   {
3218     // same elements as in 'ep_explodes_impact'
3219     EL_BOMB,
3220     EL_SP_DISK_ORANGE,
3221     EL_DX_SUPABOMB,
3222
3223     // same elements as in 'ep_explodes_smashed'
3224     EL_SATELLITE,
3225     EL_PIG,
3226     EL_DRAGON,
3227     EL_MOLE,
3228
3229     // elements that can explode by explosion or by dragonfire
3230     EL_DYNAMITE,
3231     EL_DYNAMITE_ACTIVE,
3232     EL_EM_DYNAMITE,
3233     EL_EM_DYNAMITE_ACTIVE,
3234     EL_DYNABOMB_PLAYER_1_ACTIVE,
3235     EL_DYNABOMB_PLAYER_2_ACTIVE,
3236     EL_DYNABOMB_PLAYER_3_ACTIVE,
3237     EL_DYNABOMB_PLAYER_4_ACTIVE,
3238     EL_DYNABOMB_INCREASE_NUMBER,
3239     EL_DYNABOMB_INCREASE_SIZE,
3240     EL_DYNABOMB_INCREASE_POWER,
3241     EL_SP_DISK_RED_ACTIVE,
3242     EL_BUG,
3243     EL_PENGUIN,
3244     EL_SP_DISK_RED,
3245     EL_SP_DISK_YELLOW,
3246     EL_SP_SNIKSNAK,
3247     EL_SP_ELECTRON,
3248
3249     // elements that can explode only by explosion
3250     EL_BLACK_ORB,
3251
3252     -1
3253   };
3254
3255   static int ep_gravity_reachable[] =
3256   {
3257     EL_SAND,
3258     EL_SP_BASE,
3259     EL_TRAP,
3260     EL_INVISIBLE_SAND,
3261     EL_INVISIBLE_SAND_ACTIVE,
3262     EL_SP_PORT_LEFT,
3263     EL_SP_PORT_RIGHT,
3264     EL_SP_PORT_UP,
3265     EL_SP_PORT_DOWN,
3266     EL_SP_PORT_HORIZONTAL,
3267     EL_SP_PORT_VERTICAL,
3268     EL_SP_PORT_ANY,
3269     EL_SP_GRAVITY_PORT_LEFT,
3270     EL_SP_GRAVITY_PORT_RIGHT,
3271     EL_SP_GRAVITY_PORT_UP,
3272     EL_SP_GRAVITY_PORT_DOWN,
3273     EL_SP_GRAVITY_ON_PORT_LEFT,
3274     EL_SP_GRAVITY_ON_PORT_RIGHT,
3275     EL_SP_GRAVITY_ON_PORT_UP,
3276     EL_SP_GRAVITY_ON_PORT_DOWN,
3277     EL_SP_GRAVITY_OFF_PORT_LEFT,
3278     EL_SP_GRAVITY_OFF_PORT_RIGHT,
3279     EL_SP_GRAVITY_OFF_PORT_UP,
3280     EL_SP_GRAVITY_OFF_PORT_DOWN,
3281     EL_EMC_GRASS,
3282
3283     -1
3284   };
3285
3286   static int ep_player[] =
3287   {
3288     EL_PLAYER_1,
3289     EL_PLAYER_2,
3290     EL_PLAYER_3,
3291     EL_PLAYER_4,
3292     EL_SP_MURPHY,
3293     EL_SOKOBAN_FIELD_PLAYER,
3294     EL_TRIGGER_PLAYER,
3295
3296     -1
3297   };
3298
3299   static int ep_can_pass_magic_wall[] =
3300   {
3301     EL_ROCK,
3302     EL_BD_ROCK,
3303     EL_EMERALD,
3304     EL_BD_DIAMOND,
3305     EL_EMERALD_YELLOW,
3306     EL_EMERALD_RED,
3307     EL_EMERALD_PURPLE,
3308     EL_DIAMOND,
3309
3310     -1
3311   };
3312
3313   static int ep_can_pass_dc_magic_wall[] =
3314   {
3315     EL_ROCK,
3316     EL_BD_ROCK,
3317     EL_EMERALD,
3318     EL_BD_DIAMOND,
3319     EL_EMERALD_YELLOW,
3320     EL_EMERALD_RED,
3321     EL_EMERALD_PURPLE,
3322     EL_DIAMOND,
3323     EL_PEARL,
3324     EL_CRYSTAL,
3325
3326     -1
3327   };
3328
3329   static int ep_switchable[] =
3330   {
3331     EL_ROBOT_WHEEL,
3332     EL_SP_TERMINAL,
3333     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3334     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3335     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3336     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3337     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3338     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3339     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3340     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3341     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3342     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3343     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3344     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3345     EL_SWITCHGATE_SWITCH_UP,
3346     EL_SWITCHGATE_SWITCH_DOWN,
3347     EL_DC_SWITCHGATE_SWITCH_UP,
3348     EL_DC_SWITCHGATE_SWITCH_DOWN,
3349     EL_LIGHT_SWITCH,
3350     EL_LIGHT_SWITCH_ACTIVE,
3351     EL_TIMEGATE_SWITCH,
3352     EL_DC_TIMEGATE_SWITCH,
3353     EL_BALLOON_SWITCH_LEFT,
3354     EL_BALLOON_SWITCH_RIGHT,
3355     EL_BALLOON_SWITCH_UP,
3356     EL_BALLOON_SWITCH_DOWN,
3357     EL_BALLOON_SWITCH_ANY,
3358     EL_BALLOON_SWITCH_NONE,
3359     EL_LAMP,
3360     EL_TIME_ORB_FULL,
3361     EL_EMC_MAGIC_BALL_SWITCH,
3362     EL_EMC_MAGIC_BALL_SWITCH_ACTIVE,
3363
3364     -1
3365   };
3366
3367   static int ep_bd_element[] =
3368   {
3369     EL_EMPTY,
3370     EL_SAND,
3371     EL_WALL_SLIPPERY,
3372     EL_BD_WALL,
3373     EL_ROCK,
3374     EL_BD_ROCK,
3375     EL_BD_DIAMOND,
3376     EL_BD_MAGIC_WALL,
3377     EL_EXIT_CLOSED,
3378     EL_EXIT_OPEN,
3379     EL_STEELWALL,
3380     EL_PLAYER_1,
3381     EL_PLAYER_2,
3382     EL_PLAYER_3,
3383     EL_PLAYER_4,
3384     EL_BD_FIREFLY,
3385     EL_BD_FIREFLY_1,
3386     EL_BD_FIREFLY_2,
3387     EL_BD_FIREFLY_3,
3388     EL_BD_FIREFLY_4,
3389     EL_BD_BUTTERFLY,
3390     EL_BD_BUTTERFLY_1,
3391     EL_BD_BUTTERFLY_2,
3392     EL_BD_BUTTERFLY_3,
3393     EL_BD_BUTTERFLY_4,
3394     EL_BD_AMOEBA,
3395     EL_CHAR_QUESTION,
3396     EL_UNKNOWN,
3397
3398     -1
3399   };
3400
3401   static int ep_sp_element[] =
3402   {
3403     // should always be valid
3404     EL_EMPTY,
3405
3406     // standard classic Supaplex elements
3407     EL_SP_EMPTY,
3408     EL_SP_ZONK,
3409     EL_SP_BASE,
3410     EL_SP_MURPHY,
3411     EL_SP_INFOTRON,
3412     EL_SP_CHIP_SINGLE,
3413     EL_SP_HARDWARE_GRAY,
3414     EL_SP_EXIT_CLOSED,
3415     EL_SP_EXIT_OPEN,
3416     EL_SP_DISK_ORANGE,
3417     EL_SP_PORT_RIGHT,
3418     EL_SP_PORT_DOWN,
3419     EL_SP_PORT_LEFT,
3420     EL_SP_PORT_UP,
3421     EL_SP_GRAVITY_PORT_RIGHT,
3422     EL_SP_GRAVITY_PORT_DOWN,
3423     EL_SP_GRAVITY_PORT_LEFT,
3424     EL_SP_GRAVITY_PORT_UP,
3425     EL_SP_SNIKSNAK,
3426     EL_SP_DISK_YELLOW,
3427     EL_SP_TERMINAL,
3428     EL_SP_DISK_RED,
3429     EL_SP_PORT_VERTICAL,
3430     EL_SP_PORT_HORIZONTAL,
3431     EL_SP_PORT_ANY,
3432     EL_SP_ELECTRON,
3433     EL_SP_BUGGY_BASE,
3434     EL_SP_CHIP_LEFT,
3435     EL_SP_CHIP_RIGHT,
3436     EL_SP_HARDWARE_BASE_1,
3437     EL_SP_HARDWARE_GREEN,
3438     EL_SP_HARDWARE_BLUE,
3439     EL_SP_HARDWARE_RED,
3440     EL_SP_HARDWARE_YELLOW,
3441     EL_SP_HARDWARE_BASE_2,
3442     EL_SP_HARDWARE_BASE_3,
3443     EL_SP_HARDWARE_BASE_4,
3444     EL_SP_HARDWARE_BASE_5,
3445     EL_SP_HARDWARE_BASE_6,
3446     EL_SP_CHIP_TOP,
3447     EL_SP_CHIP_BOTTOM,
3448
3449     // additional elements that appeared in newer Supaplex levels
3450     EL_INVISIBLE_WALL,
3451
3452     // additional gravity port elements (not switching, but setting gravity)
3453     EL_SP_GRAVITY_ON_PORT_LEFT,
3454     EL_SP_GRAVITY_ON_PORT_RIGHT,
3455     EL_SP_GRAVITY_ON_PORT_UP,
3456     EL_SP_GRAVITY_ON_PORT_DOWN,
3457     EL_SP_GRAVITY_OFF_PORT_LEFT,
3458     EL_SP_GRAVITY_OFF_PORT_RIGHT,
3459     EL_SP_GRAVITY_OFF_PORT_UP,
3460     EL_SP_GRAVITY_OFF_PORT_DOWN,
3461
3462     // more than one Murphy in a level results in an inactive clone
3463     EL_SP_MURPHY_CLONE,
3464
3465     // runtime Supaplex elements
3466     EL_SP_DISK_RED_ACTIVE,
3467     EL_SP_TERMINAL_ACTIVE,
3468     EL_SP_BUGGY_BASE_ACTIVATING,
3469     EL_SP_BUGGY_BASE_ACTIVE,
3470     EL_SP_EXIT_OPENING,
3471     EL_SP_EXIT_CLOSING,
3472
3473     -1
3474   };
3475
3476   static int ep_sb_element[] =
3477   {
3478     EL_EMPTY,
3479     EL_STEELWALL,
3480     EL_SOKOBAN_OBJECT,
3481     EL_SOKOBAN_FIELD_EMPTY,
3482     EL_SOKOBAN_FIELD_FULL,
3483     EL_SOKOBAN_FIELD_PLAYER,
3484     EL_PLAYER_1,
3485     EL_PLAYER_2,
3486     EL_PLAYER_3,
3487     EL_PLAYER_4,
3488     EL_INVISIBLE_STEELWALL,
3489
3490     -1
3491   };
3492
3493   static int ep_gem[] =
3494   {
3495     EL_BD_DIAMOND,
3496     EL_EMERALD,
3497     EL_EMERALD_YELLOW,
3498     EL_EMERALD_RED,
3499     EL_EMERALD_PURPLE,
3500     EL_DIAMOND,
3501
3502     -1
3503   };
3504
3505   static int ep_food_dark_yamyam[] =
3506   {
3507     EL_SAND,
3508     EL_BUG,
3509     EL_SPACESHIP,
3510     EL_BD_BUTTERFLY,
3511     EL_BD_FIREFLY,
3512     EL_YAMYAM,
3513     EL_ROBOT,
3514     EL_PACMAN,
3515     EL_AMOEBA_DROP,
3516     EL_AMOEBA_DEAD,
3517     EL_AMOEBA_WET,
3518     EL_AMOEBA_DRY,
3519     EL_AMOEBA_FULL,
3520     EL_BD_AMOEBA,
3521     EL_EMERALD,
3522     EL_BD_DIAMOND,
3523     EL_EMERALD_YELLOW,
3524     EL_EMERALD_RED,
3525     EL_EMERALD_PURPLE,
3526     EL_DIAMOND,
3527     EL_PEARL,
3528     EL_CRYSTAL,
3529
3530     -1
3531   };
3532
3533   static int ep_food_penguin[] =
3534   {
3535     EL_EMERALD,
3536     EL_BD_DIAMOND,
3537     EL_EMERALD_YELLOW,
3538     EL_EMERALD_RED,
3539     EL_EMERALD_PURPLE,
3540     EL_DIAMOND,
3541     EL_PEARL,
3542     EL_CRYSTAL,
3543
3544     -1
3545   };
3546
3547   static int ep_food_pig[] =
3548   {
3549     EL_EMERALD,
3550     EL_BD_DIAMOND,
3551     EL_EMERALD_YELLOW,
3552     EL_EMERALD_RED,
3553     EL_EMERALD_PURPLE,
3554     EL_DIAMOND,
3555
3556     -1
3557   };
3558
3559   static int ep_historic_wall[] =
3560   {
3561     EL_STEELWALL,
3562     EL_GATE_1,
3563     EL_GATE_2,
3564     EL_GATE_3,
3565     EL_GATE_4,
3566     EL_GATE_1_GRAY,
3567     EL_GATE_2_GRAY,
3568     EL_GATE_3_GRAY,
3569     EL_GATE_4_GRAY,
3570     EL_GATE_1_GRAY_ACTIVE,
3571     EL_GATE_2_GRAY_ACTIVE,
3572     EL_GATE_3_GRAY_ACTIVE,
3573     EL_GATE_4_GRAY_ACTIVE,
3574     EL_EM_GATE_1,
3575     EL_EM_GATE_2,
3576     EL_EM_GATE_3,
3577     EL_EM_GATE_4,
3578     EL_EM_GATE_1_GRAY,
3579     EL_EM_GATE_2_GRAY,
3580     EL_EM_GATE_3_GRAY,
3581     EL_EM_GATE_4_GRAY,
3582     EL_EM_GATE_1_GRAY_ACTIVE,
3583     EL_EM_GATE_2_GRAY_ACTIVE,
3584     EL_EM_GATE_3_GRAY_ACTIVE,
3585     EL_EM_GATE_4_GRAY_ACTIVE,
3586     EL_EXIT_CLOSED,
3587     EL_EXIT_OPENING,
3588     EL_EXIT_OPEN,
3589     EL_WALL,
3590     EL_WALL_SLIPPERY,
3591     EL_EXPANDABLE_WALL,
3592     EL_EXPANDABLE_WALL_HORIZONTAL,
3593     EL_EXPANDABLE_WALL_VERTICAL,
3594     EL_EXPANDABLE_WALL_ANY,
3595     EL_EXPANDABLE_WALL_GROWING,
3596     EL_BD_EXPANDABLE_WALL,
3597     EL_BD_WALL,
3598     EL_SP_CHIP_SINGLE,
3599     EL_SP_CHIP_LEFT,
3600     EL_SP_CHIP_RIGHT,
3601     EL_SP_CHIP_TOP,
3602     EL_SP_CHIP_BOTTOM,
3603     EL_SP_HARDWARE_GRAY,
3604     EL_SP_HARDWARE_GREEN,
3605     EL_SP_HARDWARE_BLUE,
3606     EL_SP_HARDWARE_RED,
3607     EL_SP_HARDWARE_YELLOW,
3608     EL_SP_HARDWARE_BASE_1,
3609     EL_SP_HARDWARE_BASE_2,
3610     EL_SP_HARDWARE_BASE_3,
3611     EL_SP_HARDWARE_BASE_4,
3612     EL_SP_HARDWARE_BASE_5,
3613     EL_SP_HARDWARE_BASE_6,
3614     EL_SP_TERMINAL,
3615     EL_SP_TERMINAL_ACTIVE,
3616     EL_SP_EXIT_CLOSED,
3617     EL_SP_EXIT_OPEN,
3618     EL_INVISIBLE_STEELWALL,
3619     EL_INVISIBLE_STEELWALL_ACTIVE,
3620     EL_INVISIBLE_WALL,
3621     EL_INVISIBLE_WALL_ACTIVE,
3622     EL_STEELWALL_SLIPPERY,
3623     EL_EMC_STEELWALL_1,
3624     EL_EMC_STEELWALL_2,
3625     EL_EMC_STEELWALL_3,
3626     EL_EMC_STEELWALL_4,
3627     EL_EMC_WALL_1,
3628     EL_EMC_WALL_2,
3629     EL_EMC_WALL_3,
3630     EL_EMC_WALL_4,
3631     EL_EMC_WALL_5,
3632     EL_EMC_WALL_6,
3633     EL_EMC_WALL_7,
3634     EL_EMC_WALL_8,
3635
3636     -1
3637   };
3638
3639   static int ep_historic_solid[] =
3640   {
3641     EL_WALL,
3642     EL_EXPANDABLE_WALL,
3643     EL_EXPANDABLE_WALL_HORIZONTAL,
3644     EL_EXPANDABLE_WALL_VERTICAL,
3645     EL_EXPANDABLE_WALL_ANY,
3646     EL_BD_EXPANDABLE_WALL,
3647     EL_BD_WALL,
3648     EL_WALL_SLIPPERY,
3649     EL_EXIT_CLOSED,
3650     EL_EXIT_OPENING,
3651     EL_EXIT_OPEN,
3652     EL_AMOEBA_DEAD,
3653     EL_AMOEBA_WET,
3654     EL_AMOEBA_DRY,
3655     EL_AMOEBA_FULL,
3656     EL_BD_AMOEBA,
3657     EL_QUICKSAND_EMPTY,
3658     EL_QUICKSAND_FULL,
3659     EL_QUICKSAND_FILLING,
3660     EL_QUICKSAND_EMPTYING,
3661     EL_MAGIC_WALL,
3662     EL_MAGIC_WALL_ACTIVE,
3663     EL_MAGIC_WALL_EMPTYING,
3664     EL_MAGIC_WALL_FILLING,
3665     EL_MAGIC_WALL_FULL,
3666     EL_MAGIC_WALL_DEAD,
3667     EL_BD_MAGIC_WALL,
3668     EL_BD_MAGIC_WALL_ACTIVE,
3669     EL_BD_MAGIC_WALL_EMPTYING,
3670     EL_BD_MAGIC_WALL_FULL,
3671     EL_BD_MAGIC_WALL_FILLING,
3672     EL_BD_MAGIC_WALL_DEAD,
3673     EL_GAME_OF_LIFE,
3674     EL_BIOMAZE,
3675     EL_SP_CHIP_SINGLE,
3676     EL_SP_CHIP_LEFT,
3677     EL_SP_CHIP_RIGHT,
3678     EL_SP_CHIP_TOP,
3679     EL_SP_CHIP_BOTTOM,
3680     EL_SP_TERMINAL,
3681     EL_SP_TERMINAL_ACTIVE,
3682     EL_SP_EXIT_CLOSED,
3683     EL_SP_EXIT_OPEN,
3684     EL_INVISIBLE_WALL,
3685     EL_INVISIBLE_WALL_ACTIVE,
3686     EL_SWITCHGATE_SWITCH_UP,
3687     EL_SWITCHGATE_SWITCH_DOWN,
3688     EL_TIMEGATE_SWITCH,
3689     EL_TIMEGATE_SWITCH_ACTIVE,
3690     EL_EMC_WALL_1,
3691     EL_EMC_WALL_2,
3692     EL_EMC_WALL_3,
3693     EL_EMC_WALL_4,
3694     EL_EMC_WALL_5,
3695     EL_EMC_WALL_6,
3696     EL_EMC_WALL_7,
3697     EL_EMC_WALL_8,
3698     EL_WALL_PEARL,
3699     EL_WALL_CRYSTAL,
3700
3701     // the following elements are a direct copy of "indestructible" elements,
3702     // except "EL_ACID", which is "indestructible", but not "solid"!
3703 #if 0
3704     EL_ACID,
3705 #endif
3706     EL_STEELWALL,
3707     EL_ACID_POOL_TOPLEFT,
3708     EL_ACID_POOL_TOPRIGHT,
3709     EL_ACID_POOL_BOTTOMLEFT,
3710     EL_ACID_POOL_BOTTOM,
3711     EL_ACID_POOL_BOTTOMRIGHT,
3712     EL_SP_HARDWARE_GRAY,
3713     EL_SP_HARDWARE_GREEN,
3714     EL_SP_HARDWARE_BLUE,
3715     EL_SP_HARDWARE_RED,
3716     EL_SP_HARDWARE_YELLOW,
3717     EL_SP_HARDWARE_BASE_1,
3718     EL_SP_HARDWARE_BASE_2,
3719     EL_SP_HARDWARE_BASE_3,
3720     EL_SP_HARDWARE_BASE_4,
3721     EL_SP_HARDWARE_BASE_5,
3722     EL_SP_HARDWARE_BASE_6,
3723     EL_INVISIBLE_STEELWALL,
3724     EL_INVISIBLE_STEELWALL_ACTIVE,
3725     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3726     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3727     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3728     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3729     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3730     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3731     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3732     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3733     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3734     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3735     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3736     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3737     EL_LIGHT_SWITCH,
3738     EL_LIGHT_SWITCH_ACTIVE,
3739     EL_SIGN_EXCLAMATION,
3740     EL_SIGN_RADIOACTIVITY,
3741     EL_SIGN_STOP,
3742     EL_SIGN_WHEELCHAIR,
3743     EL_SIGN_PARKING,
3744     EL_SIGN_NO_ENTRY,
3745     EL_SIGN_UNUSED_1,
3746     EL_SIGN_GIVE_WAY,
3747     EL_SIGN_ENTRY_FORBIDDEN,
3748     EL_SIGN_EMERGENCY_EXIT,
3749     EL_SIGN_YIN_YANG,
3750     EL_SIGN_UNUSED_2,
3751     EL_SIGN_SPERMS,
3752     EL_SIGN_BULLET,
3753     EL_SIGN_HEART,
3754     EL_SIGN_CROSS,
3755     EL_SIGN_FRANKIE,
3756     EL_STEEL_EXIT_CLOSED,
3757     EL_STEEL_EXIT_OPEN,
3758     EL_STEEL_EXIT_OPENING,
3759     EL_STEEL_EXIT_CLOSING,
3760     EL_EM_STEEL_EXIT_CLOSED,
3761     EL_EM_STEEL_EXIT_OPEN,
3762     EL_EM_STEEL_EXIT_OPENING,
3763     EL_EM_STEEL_EXIT_CLOSING,
3764     EL_DC_STEELWALL_1_LEFT,
3765     EL_DC_STEELWALL_1_RIGHT,
3766     EL_DC_STEELWALL_1_TOP,
3767     EL_DC_STEELWALL_1_BOTTOM,
3768     EL_DC_STEELWALL_1_HORIZONTAL,
3769     EL_DC_STEELWALL_1_VERTICAL,
3770     EL_DC_STEELWALL_1_TOPLEFT,
3771     EL_DC_STEELWALL_1_TOPRIGHT,
3772     EL_DC_STEELWALL_1_BOTTOMLEFT,
3773     EL_DC_STEELWALL_1_BOTTOMRIGHT,
3774     EL_DC_STEELWALL_1_TOPLEFT_2,
3775     EL_DC_STEELWALL_1_TOPRIGHT_2,
3776     EL_DC_STEELWALL_1_BOTTOMLEFT_2,
3777     EL_DC_STEELWALL_1_BOTTOMRIGHT_2,
3778     EL_DC_STEELWALL_2_LEFT,
3779     EL_DC_STEELWALL_2_RIGHT,
3780     EL_DC_STEELWALL_2_TOP,
3781     EL_DC_STEELWALL_2_BOTTOM,
3782     EL_DC_STEELWALL_2_HORIZONTAL,
3783     EL_DC_STEELWALL_2_VERTICAL,
3784     EL_DC_STEELWALL_2_MIDDLE,
3785     EL_DC_STEELWALL_2_SINGLE,
3786     EL_STEELWALL_SLIPPERY,
3787     EL_EMC_STEELWALL_1,
3788     EL_EMC_STEELWALL_2,
3789     EL_EMC_STEELWALL_3,
3790     EL_EMC_STEELWALL_4,
3791     EL_CRYSTAL,
3792     EL_GATE_1,
3793     EL_GATE_2,
3794     EL_GATE_3,
3795     EL_GATE_4,
3796     EL_GATE_1_GRAY,
3797     EL_GATE_2_GRAY,
3798     EL_GATE_3_GRAY,
3799     EL_GATE_4_GRAY,
3800     EL_GATE_1_GRAY_ACTIVE,
3801     EL_GATE_2_GRAY_ACTIVE,
3802     EL_GATE_3_GRAY_ACTIVE,
3803     EL_GATE_4_GRAY_ACTIVE,
3804     EL_EM_GATE_1,
3805     EL_EM_GATE_2,
3806     EL_EM_GATE_3,
3807     EL_EM_GATE_4,
3808     EL_EM_GATE_1_GRAY,
3809     EL_EM_GATE_2_GRAY,
3810     EL_EM_GATE_3_GRAY,
3811     EL_EM_GATE_4_GRAY,
3812     EL_EM_GATE_1_GRAY_ACTIVE,
3813     EL_EM_GATE_2_GRAY_ACTIVE,
3814     EL_EM_GATE_3_GRAY_ACTIVE,
3815     EL_EM_GATE_4_GRAY_ACTIVE,
3816     EL_EMC_GATE_5,
3817     EL_EMC_GATE_6,
3818     EL_EMC_GATE_7,
3819     EL_EMC_GATE_8,
3820     EL_EMC_GATE_5_GRAY,
3821     EL_EMC_GATE_6_GRAY,
3822     EL_EMC_GATE_7_GRAY,
3823     EL_EMC_GATE_8_GRAY,
3824     EL_EMC_GATE_5_GRAY_ACTIVE,
3825     EL_EMC_GATE_6_GRAY_ACTIVE,
3826     EL_EMC_GATE_7_GRAY_ACTIVE,
3827     EL_EMC_GATE_8_GRAY_ACTIVE,
3828     EL_DC_GATE_WHITE,
3829     EL_DC_GATE_WHITE_GRAY,
3830     EL_DC_GATE_WHITE_GRAY_ACTIVE,
3831     EL_DC_GATE_FAKE_GRAY,
3832     EL_SWITCHGATE_OPEN,
3833     EL_SWITCHGATE_OPENING,
3834     EL_SWITCHGATE_CLOSED,
3835     EL_SWITCHGATE_CLOSING,
3836     EL_DC_SWITCHGATE_SWITCH_UP,
3837     EL_DC_SWITCHGATE_SWITCH_DOWN,
3838     EL_TIMEGATE_OPEN,
3839     EL_TIMEGATE_OPENING,
3840     EL_TIMEGATE_CLOSED,
3841     EL_TIMEGATE_CLOSING,
3842     EL_DC_TIMEGATE_SWITCH,
3843     EL_DC_TIMEGATE_SWITCH_ACTIVE,
3844     EL_TUBE_ANY,
3845     EL_TUBE_VERTICAL,
3846     EL_TUBE_HORIZONTAL,
3847     EL_TUBE_VERTICAL_LEFT,
3848     EL_TUBE_VERTICAL_RIGHT,
3849     EL_TUBE_HORIZONTAL_UP,
3850     EL_TUBE_HORIZONTAL_DOWN,
3851     EL_TUBE_LEFT_UP,
3852     EL_TUBE_LEFT_DOWN,
3853     EL_TUBE_RIGHT_UP,
3854     EL_TUBE_RIGHT_DOWN,
3855     EL_EXPANDABLE_STEELWALL_HORIZONTAL,
3856     EL_EXPANDABLE_STEELWALL_VERTICAL,
3857     EL_EXPANDABLE_STEELWALL_ANY,
3858
3859     -1
3860   };
3861
3862   static int ep_classic_enemy[] =
3863   {
3864     EL_BUG,
3865     EL_SPACESHIP,
3866     EL_BD_BUTTERFLY,
3867     EL_BD_FIREFLY,
3868
3869     EL_YAMYAM,
3870     EL_DARK_YAMYAM,
3871     EL_ROBOT,
3872     EL_PACMAN,
3873     EL_SP_SNIKSNAK,
3874     EL_SP_ELECTRON,
3875
3876     -1
3877   };
3878
3879   static int ep_belt[] =
3880   {
3881     EL_CONVEYOR_BELT_1_LEFT,
3882     EL_CONVEYOR_BELT_1_MIDDLE,
3883     EL_CONVEYOR_BELT_1_RIGHT,
3884     EL_CONVEYOR_BELT_2_LEFT,
3885     EL_CONVEYOR_BELT_2_MIDDLE,
3886     EL_CONVEYOR_BELT_2_RIGHT,
3887     EL_CONVEYOR_BELT_3_LEFT,
3888     EL_CONVEYOR_BELT_3_MIDDLE,
3889     EL_CONVEYOR_BELT_3_RIGHT,
3890     EL_CONVEYOR_BELT_4_LEFT,
3891     EL_CONVEYOR_BELT_4_MIDDLE,
3892     EL_CONVEYOR_BELT_4_RIGHT,
3893
3894     -1
3895   };
3896
3897   static int ep_belt_active[] =
3898   {
3899     EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
3900     EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE,
3901     EL_CONVEYOR_BELT_1_RIGHT_ACTIVE,
3902     EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
3903     EL_CONVEYOR_BELT_2_MIDDLE_ACTIVE,
3904     EL_CONVEYOR_BELT_2_RIGHT_ACTIVE,
3905     EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
3906     EL_CONVEYOR_BELT_3_MIDDLE_ACTIVE,
3907     EL_CONVEYOR_BELT_3_RIGHT_ACTIVE,
3908     EL_CONVEYOR_BELT_4_LEFT_ACTIVE,
3909     EL_CONVEYOR_BELT_4_MIDDLE_ACTIVE,
3910     EL_CONVEYOR_BELT_4_RIGHT_ACTIVE,
3911
3912     -1
3913   };
3914
3915   static int ep_belt_switch[] =
3916   {
3917     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3918     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3919     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3920     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3921     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3922     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3923     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3924     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3925     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3926     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3927     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3928     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3929
3930     -1
3931   };
3932
3933   static int ep_tube[] =
3934   {
3935     EL_TUBE_LEFT_UP,
3936     EL_TUBE_LEFT_DOWN,
3937     EL_TUBE_RIGHT_UP,
3938     EL_TUBE_RIGHT_DOWN,
3939     EL_TUBE_HORIZONTAL,
3940     EL_TUBE_HORIZONTAL_UP,
3941     EL_TUBE_HORIZONTAL_DOWN,
3942     EL_TUBE_VERTICAL,
3943     EL_TUBE_VERTICAL_LEFT,
3944     EL_TUBE_VERTICAL_RIGHT,
3945     EL_TUBE_ANY,
3946
3947     -1
3948   };
3949
3950   static int ep_acid_pool[] =
3951   {
3952     EL_ACID_POOL_TOPLEFT,
3953     EL_ACID_POOL_TOPRIGHT,
3954     EL_ACID_POOL_BOTTOMLEFT,
3955     EL_ACID_POOL_BOTTOM,
3956     EL_ACID_POOL_BOTTOMRIGHT,
3957
3958     -1
3959   };
3960
3961   static int ep_keygate[] =
3962   {
3963     EL_GATE_1,
3964     EL_GATE_2,
3965     EL_GATE_3,
3966     EL_GATE_4,
3967     EL_GATE_1_GRAY,
3968     EL_GATE_2_GRAY,
3969     EL_GATE_3_GRAY,
3970     EL_GATE_4_GRAY,
3971     EL_GATE_1_GRAY_ACTIVE,
3972     EL_GATE_2_GRAY_ACTIVE,
3973     EL_GATE_3_GRAY_ACTIVE,
3974     EL_GATE_4_GRAY_ACTIVE,
3975     EL_EM_GATE_1,
3976     EL_EM_GATE_2,
3977     EL_EM_GATE_3,
3978     EL_EM_GATE_4,
3979     EL_EM_GATE_1_GRAY,
3980     EL_EM_GATE_2_GRAY,
3981     EL_EM_GATE_3_GRAY,
3982     EL_EM_GATE_4_GRAY,
3983     EL_EM_GATE_1_GRAY_ACTIVE,
3984     EL_EM_GATE_2_GRAY_ACTIVE,