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