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