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