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