rnd-20100624-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       1
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 long action_delay = 0;
163   unsigned long 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 long last_counter = -1;
179     unsigned long current_counter = Counter();
180     unsigned long 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 long 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_SCORES,
1881     IMG_BACKGROUND_EDITOR,
1882     IMG_BACKGROUND_INFO,
1883     IMG_BACKGROUND_INFO_ELEMENTS,
1884     IMG_BACKGROUND_INFO_MUSIC,
1885     IMG_BACKGROUND_INFO_CREDITS,
1886     IMG_BACKGROUND_INFO_PROGRAM,
1887     IMG_BACKGROUND_INFO_LEVELSET,
1888     IMG_BACKGROUND_SETUP,
1889     IMG_BACKGROUND_DOOR,
1890     IMG_BACKGROUND_TAPE,
1891     IMG_BACKGROUND_PANEL,
1892
1893     IMG_TITLESCREEN_INITIAL_1,
1894     IMG_TITLESCREEN_INITIAL_2,
1895     IMG_TITLESCREEN_INITIAL_3,
1896     IMG_TITLESCREEN_INITIAL_4,
1897     IMG_TITLESCREEN_INITIAL_5,
1898     IMG_TITLESCREEN_1,
1899     IMG_TITLESCREEN_2,
1900     IMG_TITLESCREEN_3,
1901     IMG_TITLESCREEN_4,
1902     IMG_TITLESCREEN_5,
1903
1904     -1
1905   };
1906
1907   checked_free(graphic_info);
1908
1909   graphic_info = checked_calloc(num_images * sizeof(struct GraphicInfo));
1910
1911 #if 1
1912   /* initialize "use_image_size" flag with default value */
1913   for (i = 0; i < num_images; i++)
1914     graphic_info[i].use_image_size = FALSE;
1915
1916   /* initialize "use_image_size" flag from static configuration above */
1917   for (i = 0; full_size_graphics[i] != -1; i++)
1918     graphic_info[full_size_graphics[i]].use_image_size = TRUE;
1919 #endif
1920
1921 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1922   if (clipmasks_initialized)
1923   {
1924     for (i = 0; i < num_images; i++)
1925     {
1926       if (graphic_info[i].clip_mask)
1927         XFreePixmap(display, graphic_info[i].clip_mask);
1928       if (graphic_info[i].clip_gc)
1929         XFreeGC(display, graphic_info[i].clip_gc);
1930
1931       graphic_info[i].clip_mask = None;
1932       graphic_info[i].clip_gc = None;
1933     }
1934   }
1935 #endif
1936
1937   /* first set all graphic paramaters ... */
1938   for (i = 0; i < num_images; i++)
1939     set_graphic_parameters(i);
1940
1941   /* ... then copy these parameters for cloned graphics */
1942   for (i = 0; i < num_images; i++)
1943     if (graphic_info[i].clone_from != -1)
1944       set_cloned_graphic_parameters(i);
1945
1946   for (i = 0; i < num_images; i++)
1947   {
1948     Bitmap *src_bitmap;
1949     int src_x, src_y;
1950     int width, height;
1951     int first_frame, last_frame;
1952     int src_bitmap_width, src_bitmap_height;
1953
1954     /* now check if no animation frames are outside of the loaded image */
1955
1956     if (graphic_info[i].bitmap == NULL)
1957       continue;         /* skip check for optional images that are undefined */
1958
1959     /* get image size (this can differ from the standard element tile size!) */
1960     width  = graphic_info[i].width;
1961     height = graphic_info[i].height;
1962
1963     /* get final bitmap size (with scaling, but without small images) */
1964     src_bitmap_width  = graphic_info[i].src_image_width;
1965     src_bitmap_height = graphic_info[i].src_image_height;
1966
1967     /* check if first animation frame is inside specified bitmap */
1968
1969     first_frame = 0;
1970     getFixedGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
1971
1972 #if 1
1973     /* this avoids calculating wrong start position for out-of-bounds frame */
1974     src_x = graphic_info[i].src_x;
1975     src_y = graphic_info[i].src_y;
1976 #endif
1977
1978     if (src_x < 0 || src_y < 0 ||
1979         src_x + width  > src_bitmap_width ||
1980         src_y + height > src_bitmap_height)
1981     {
1982       Error(ERR_INFO_LINE, "-");
1983       Error(ERR_INFO, "warning: error found in config file:");
1984       Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
1985       Error(ERR_INFO, "- config token: '%s'", getTokenFromImageID(i));
1986       Error(ERR_INFO, "- image file: '%s'", src_bitmap->source_filename);
1987       Error(ERR_INFO,
1988             "error: first animation frame out of bounds (%d, %d) [%d, %d]",
1989             src_x, src_y, src_bitmap_width, src_bitmap_height);
1990       Error(ERR_INFO, "custom graphic rejected for this element/action");
1991
1992       if (i == fallback_graphic)
1993         Error(ERR_EXIT, "fatal error: no fallback graphic available");
1994
1995       Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic");
1996       Error(ERR_INFO_LINE, "-");
1997
1998       graphic_info[i] = graphic_info[fallback_graphic];
1999     }
2000
2001     /* check if last animation frame is inside specified bitmap */
2002
2003     last_frame = graphic_info[i].anim_frames - 1;
2004     getFixedGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y);
2005
2006     if (src_x < 0 || src_y < 0 ||
2007         src_x + width  > src_bitmap_width ||
2008         src_y + height > src_bitmap_height)
2009     {
2010       Error(ERR_INFO_LINE, "-");
2011       Error(ERR_INFO, "warning: error found in config file:");
2012       Error(ERR_INFO, "- config file: '%s'", getImageConfigFilename());
2013       Error(ERR_INFO, "- config token: '%s'", getTokenFromImageID(i));
2014       Error(ERR_INFO, "- image file: '%s'", src_bitmap->source_filename);
2015       Error(ERR_INFO,
2016             "error: last animation frame (%d) out of bounds (%d, %d) [%d, %d]",
2017             last_frame, src_x, src_y, src_bitmap_width, src_bitmap_height);
2018       Error(ERR_INFO, "::: %d, %d", width, height);
2019       Error(ERR_INFO, "custom graphic rejected for this element/action");
2020
2021       if (i == fallback_graphic)
2022         Error(ERR_EXIT, "fatal error: no fallback graphic available");
2023
2024       Error(ERR_INFO, "fallback done to 'char_exclam' for this graphic");
2025       Error(ERR_INFO_LINE, "-");
2026
2027       graphic_info[i] = graphic_info[fallback_graphic];
2028     }
2029
2030 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
2031     /* currently we only need a tile clip mask from the first frame */
2032     getFixedGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
2033
2034     if (copy_clipmask_gc == None)
2035     {
2036       clip_gc_values.graphics_exposures = False;
2037       clip_gc_valuemask = GCGraphicsExposures;
2038       copy_clipmask_gc = XCreateGC(display, src_bitmap->clip_mask,
2039                                    clip_gc_valuemask, &clip_gc_values);
2040     }
2041
2042     graphic_info[i].clip_mask =
2043       XCreatePixmap(display, window->drawable, TILEX, TILEY, 1);
2044
2045     src_pixmap = src_bitmap->clip_mask;
2046     XCopyArea(display, src_pixmap, graphic_info[i].clip_mask,
2047               copy_clipmask_gc, src_x, src_y, TILEX, TILEY, 0, 0);
2048
2049     clip_gc_values.graphics_exposures = False;
2050     clip_gc_values.clip_mask = graphic_info[i].clip_mask;
2051     clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
2052
2053     graphic_info[i].clip_gc =
2054       XCreateGC(display, window->drawable, clip_gc_valuemask, &clip_gc_values);
2055 #endif
2056   }
2057
2058 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
2059   if (copy_clipmask_gc)
2060     XFreeGC(display, copy_clipmask_gc);
2061
2062   clipmasks_initialized = TRUE;
2063 #endif
2064 }
2065
2066 static void InitGraphicCompatibilityInfo()
2067 {
2068   struct FileInfo *fi_global_door =
2069     getImageListEntryFromImageID(IMG_GLOBAL_DOOR);
2070   int num_images = getImageListSize();
2071   int i;
2072
2073   /* the following compatibility handling is needed for the following case:
2074      versions up to 3.3.0.0 used one large bitmap "global.door" for various
2075      graphics mainly used for door and panel graphics, like editor, tape and
2076      in-game buttons with hard-coded bitmap positions and button sizes; as
2077      these graphics now have individual definitions, redefining "global.door"
2078      to change all these graphics at once like before does not work anymore
2079      (because all those individual definitions still have their default values);
2080      to solve this, remap all those individual definitions that are not
2081      redefined to the new bitmap of "global.door" if it was redefined */
2082
2083   /* special compatibility handling if image "global.door" was redefined */
2084   if (fi_global_door->redefined)
2085   {
2086     for (i = 0; i < num_images; i++)
2087     {
2088       struct FileInfo *fi = getImageListEntryFromImageID(i);
2089
2090       /* process only those images that still use the default settings */
2091       if (!fi->redefined)
2092       {
2093         /* process all images which default to same image as "global.door" */
2094         if (strEqual(fi->default_filename, fi_global_door->default_filename))
2095         {
2096           // printf("::: special treatment needed for token '%s'\n", fi->token);
2097
2098           graphic_info[i].bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2099         }
2100       }
2101     }
2102   }
2103
2104 #if 0
2105   for (i = 0; i < num_images; i++)
2106   {
2107     struct FileInfo *fi = getImageListEntryFromImageID(i);
2108
2109     if (i == IMG_GLOBAL_DOOR)
2110     {
2111       printf("::: %s, %s, %d\n",
2112              fi->default_filename,
2113              fi->filename,
2114              fi->redefined);
2115     }
2116   }
2117 #endif
2118 }
2119
2120 static void InitElementSoundInfo()
2121 {
2122   struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
2123   int num_property_mappings = getSoundListPropertyMappingSize();
2124   int i, j, act;
2125
2126   /* set values to -1 to identify later as "uninitialized" values */
2127   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2128     for (act = 0; act < NUM_ACTIONS; act++)
2129       element_info[i].sound[act] = -1;
2130
2131   /* initialize element/sound mapping from static configuration */
2132   for (i = 0; element_to_sound[i].element > -1; i++)
2133   {
2134     int element      = element_to_sound[i].element;
2135     int action       = element_to_sound[i].action;
2136     int sound        = element_to_sound[i].sound;
2137     boolean is_class = element_to_sound[i].is_class;
2138
2139     if (action < 0)
2140       action = ACTION_DEFAULT;
2141
2142     if (!is_class)
2143       element_info[element].sound[action] = sound;
2144     else
2145       for (j = 0; j < MAX_NUM_ELEMENTS; j++)
2146         if (strEqual(element_info[j].class_name,
2147                      element_info[element].class_name))
2148           element_info[j].sound[action] = sound;
2149   }
2150
2151   /* initialize element class/sound mapping from dynamic configuration */
2152   for (i = 0; i < num_property_mappings; i++)
2153   {
2154     int element_class = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
2155     int action        = property_mapping[i].ext1_index;
2156     int sound         = property_mapping[i].artwork_index;
2157
2158     if (element_class < 0 || element_class >= MAX_NUM_ELEMENTS)
2159       continue;
2160
2161     if (action < 0)
2162       action = ACTION_DEFAULT;
2163
2164     for (j = 0; j < MAX_NUM_ELEMENTS; j++)
2165       if (strEqual(element_info[j].class_name,
2166                    element_info[element_class].class_name))
2167         element_info[j].sound[action] = sound;
2168   }
2169
2170   /* initialize element/sound mapping from dynamic configuration */
2171   for (i = 0; i < num_property_mappings; i++)
2172   {
2173     int element = property_mapping[i].base_index;
2174     int action  = property_mapping[i].ext1_index;
2175     int sound   = property_mapping[i].artwork_index;
2176
2177     if (element >= MAX_NUM_ELEMENTS)
2178       continue;
2179
2180     if (action < 0)
2181       action = ACTION_DEFAULT;
2182
2183     element_info[element].sound[action] = sound;
2184   }
2185
2186   /* now set all '-1' values to element specific default values */
2187   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2188   {
2189     for (act = 0; act < NUM_ACTIONS; act++)
2190     {
2191       /* generic default action sound (defined by "[default]" directive) */
2192       int default_action_sound = element_info[EL_DEFAULT].sound[act];
2193
2194       /* look for special default action sound (classic game specific) */
2195       if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].sound[act] != -1)
2196         default_action_sound = element_info[EL_BD_DEFAULT].sound[act];
2197       if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].sound[act] != -1)
2198         default_action_sound = element_info[EL_SP_DEFAULT].sound[act];
2199       if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].sound[act] != -1)
2200         default_action_sound = element_info[EL_SB_DEFAULT].sound[act];
2201
2202       /* !!! there's no such thing as a "default action sound" !!! */
2203 #if 0
2204       /* look for element specific default sound (independent from action) */
2205       if (element_info[i].sound[ACTION_DEFAULT] != -1)
2206         default_action_sound = element_info[i].sound[ACTION_DEFAULT];
2207 #endif
2208
2209 #if 1
2210       /* !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!! */
2211       /* !!! make this better !!! */
2212       if (i == EL_EMPTY_SPACE)
2213         default_action_sound = element_info[EL_DEFAULT].sound[act];
2214 #endif
2215
2216       /* no sound for this specific action -- use default action sound */
2217       if (element_info[i].sound[act] == -1)
2218         element_info[i].sound[act] = default_action_sound;
2219     }
2220   }
2221
2222   /* copy sound settings to some elements that are only stored in level file
2223      in native R'n'D levels, but are used by game engine in native EM levels */
2224   for (i = 0; copy_properties[i][0] != -1; i++)
2225     for (j = 1; j <= 4; j++)
2226       for (act = 0; act < NUM_ACTIONS; act++)
2227         element_info[copy_properties[i][j]].sound[act] =
2228           element_info[copy_properties[i][0]].sound[act];
2229 }
2230
2231 static void InitGameModeSoundInfo()
2232 {
2233   int i;
2234
2235   /* set values to -1 to identify later as "uninitialized" values */
2236   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
2237     menu.sound[i] = -1;
2238
2239   /* initialize gamemode/sound mapping from static configuration */
2240   for (i = 0; gamemode_to_sound[i].sound > -1; i++)
2241   {
2242     int gamemode = gamemode_to_sound[i].gamemode;
2243     int sound    = gamemode_to_sound[i].sound;
2244
2245     if (gamemode < 0)
2246       gamemode = GAME_MODE_DEFAULT;
2247
2248     menu.sound[gamemode] = sound;
2249   }
2250
2251   /* now set all '-1' values to levelset specific default values */
2252   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
2253     if (menu.sound[i] == -1)
2254       menu.sound[i] = menu.sound[GAME_MODE_DEFAULT];
2255
2256 #if 0
2257   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
2258     if (menu.sound[i] != -1)
2259       printf("::: menu.sound[%d] == %d\n", i, menu.sound[i]);
2260 #endif
2261 }
2262
2263 static void set_sound_parameters(int sound, char **parameter_raw)
2264 {
2265   int parameter[NUM_SND_ARGS];
2266   int i;
2267
2268   /* get integer values from string parameters */
2269   for (i = 0; i < NUM_SND_ARGS; i++)
2270     parameter[i] =
2271       get_parameter_value(parameter_raw[i],
2272                           sound_config_suffix[i].token,
2273                           sound_config_suffix[i].type);
2274
2275   /* explicit loop mode setting in configuration overrides default value */
2276   if (parameter[SND_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
2277     sound_info[sound].loop = parameter[SND_ARG_MODE_LOOP];
2278
2279   /* sound volume to change the original volume when loading the sound file */
2280   sound_info[sound].volume = parameter[SND_ARG_VOLUME];
2281
2282   /* sound priority to give certain sounds a higher or lower priority */
2283   sound_info[sound].priority = parameter[SND_ARG_PRIORITY];
2284 }
2285
2286 static void InitSoundInfo()
2287 {
2288   int *sound_effect_properties;
2289   int num_sounds = getSoundListSize();
2290   int i, j;
2291
2292   checked_free(sound_info);
2293
2294   sound_effect_properties = checked_calloc(num_sounds * sizeof(int));
2295   sound_info = checked_calloc(num_sounds * sizeof(struct SoundInfo));
2296
2297   /* initialize sound effect for all elements to "no sound" */
2298   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2299     for (j = 0; j < NUM_ACTIONS; j++)
2300       element_info[i].sound[j] = SND_UNDEFINED;
2301
2302   for (i = 0; i < num_sounds; i++)
2303   {
2304     struct FileInfo *sound = getSoundListEntry(i);
2305     int len_effect_text = strlen(sound->token);
2306
2307     sound_effect_properties[i] = ACTION_OTHER;
2308     sound_info[i].loop = FALSE;         /* default: play sound only once */
2309
2310 #if 0
2311     printf("::: sound %d: '%s'\n", i, sound->token);
2312 #endif
2313
2314     /* determine all loop sounds and identify certain sound classes */
2315
2316     for (j = 0; element_action_info[j].suffix; j++)
2317     {
2318       int len_action_text = strlen(element_action_info[j].suffix);
2319
2320       if (len_action_text < len_effect_text &&
2321           strEqual(&sound->token[len_effect_text - len_action_text],
2322                    element_action_info[j].suffix))
2323       {
2324         sound_effect_properties[i] = element_action_info[j].value;
2325         sound_info[i].loop = element_action_info[j].is_loop_sound;
2326
2327         break;
2328       }
2329     }
2330
2331     /* associate elements and some selected sound actions */
2332
2333     for (j = 0; j < MAX_NUM_ELEMENTS; j++)
2334     {
2335       if (element_info[j].class_name)
2336       {
2337         int len_class_text = strlen(element_info[j].class_name);
2338
2339         if (len_class_text + 1 < len_effect_text &&
2340             strncmp(sound->token,
2341                     element_info[j].class_name, len_class_text) == 0 &&
2342             sound->token[len_class_text] == '.')
2343         {
2344           int sound_action_value = sound_effect_properties[i];
2345
2346           element_info[j].sound[sound_action_value] = i;
2347         }
2348       }
2349     }
2350
2351     set_sound_parameters(i, sound->parameter);
2352   }
2353
2354   free(sound_effect_properties);
2355 }
2356
2357 static void InitGameModeMusicInfo()
2358 {
2359   struct PropertyMapping *property_mapping = getMusicListPropertyMapping();
2360   int num_property_mappings = getMusicListPropertyMappingSize();
2361   int default_levelset_music = -1;
2362   int i;
2363
2364   /* set values to -1 to identify later as "uninitialized" values */
2365   for (i = 0; i < MAX_LEVELS; i++)
2366     levelset.music[i] = -1;
2367   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
2368     menu.music[i] = -1;
2369
2370   /* initialize gamemode/music mapping from static configuration */
2371   for (i = 0; gamemode_to_music[i].music > -1; i++)
2372   {
2373     int gamemode = gamemode_to_music[i].gamemode;
2374     int music    = gamemode_to_music[i].music;
2375
2376 #if 0
2377     printf("::: gamemode == %d, music == %d\n", gamemode, music);
2378 #endif
2379
2380     if (gamemode < 0)
2381       gamemode = GAME_MODE_DEFAULT;
2382
2383     menu.music[gamemode] = music;
2384   }
2385
2386   /* initialize gamemode/music mapping from dynamic configuration */
2387   for (i = 0; i < num_property_mappings; i++)
2388   {
2389     int prefix   = property_mapping[i].base_index;
2390     int gamemode = property_mapping[i].ext1_index;
2391     int level    = property_mapping[i].ext2_index;
2392     int music    = property_mapping[i].artwork_index;
2393
2394 #if 0
2395     printf("::: prefix == %d, gamemode == %d, level == %d, music == %d\n",
2396            prefix, gamemode, level, music);
2397 #endif
2398
2399     if (prefix < 0 || prefix >= NUM_MUSIC_PREFIXES)
2400       continue;
2401
2402     if (gamemode < 0)
2403       gamemode = GAME_MODE_DEFAULT;
2404
2405     /* level specific music only allowed for in-game music */
2406     if (level != -1 && gamemode == GAME_MODE_DEFAULT)
2407       gamemode = GAME_MODE_PLAYING;
2408
2409     if (level == -1)
2410     {
2411       level = 0;
2412       default_levelset_music = music;
2413     }
2414
2415     if (gamemode == GAME_MODE_PLAYING || gamemode == GAME_MODE_DEFAULT)
2416       levelset.music[level] = music;
2417     if (gamemode != GAME_MODE_PLAYING)
2418       menu.music[gamemode] = music;
2419   }
2420
2421   /* now set all '-1' values to menu specific default values */
2422   /* (undefined values of "levelset.music[]" might stay at "-1" to
2423      allow dynamic selection of music files from music directory!) */
2424   for (i = 0; i < MAX_LEVELS; i++)
2425     if (levelset.music[i] == -1)
2426       levelset.music[i] = default_levelset_music;
2427   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
2428     if (menu.music[i] == -1)
2429       menu.music[i] = menu.music[GAME_MODE_DEFAULT];
2430
2431 #if 0
2432   for (i = 0; i < MAX_LEVELS; i++)
2433     if (levelset.music[i] != -1)
2434       printf("::: levelset.music[%d] == %d\n", i, levelset.music[i]);
2435   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
2436     if (menu.music[i] != -1)
2437       printf("::: menu.music[%d] == %d\n", i, menu.music[i]);
2438 #endif
2439 }
2440
2441 static void set_music_parameters(int music, char **parameter_raw)
2442 {
2443   int parameter[NUM_MUS_ARGS];
2444   int i;
2445
2446   /* get integer values from string parameters */
2447   for (i = 0; i < NUM_MUS_ARGS; i++)
2448     parameter[i] =
2449       get_parameter_value(parameter_raw[i],
2450                           music_config_suffix[i].token,
2451                           music_config_suffix[i].type);
2452
2453   /* explicit loop mode setting in configuration overrides default value */
2454   if (parameter[MUS_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
2455     music_info[music].loop = parameter[MUS_ARG_MODE_LOOP];
2456 }
2457
2458 static void InitMusicInfo()
2459 {
2460   int num_music = getMusicListSize();
2461   int i, j;
2462
2463   checked_free(music_info);
2464
2465   music_info = checked_calloc(num_music * sizeof(struct MusicInfo));
2466
2467   for (i = 0; i < num_music; i++)
2468   {
2469     struct FileInfo *music = getMusicListEntry(i);
2470     int len_music_text = strlen(music->token);
2471
2472     music_info[i].loop = TRUE;          /* default: play music in loop mode */
2473
2474     /* determine all loop music */
2475
2476     for (j = 0; music_prefix_info[j].prefix; j++)
2477     {
2478       int len_prefix_text = strlen(music_prefix_info[j].prefix);
2479
2480       if (len_prefix_text < len_music_text &&
2481           strncmp(music->token,
2482                   music_prefix_info[j].prefix, len_prefix_text) == 0)
2483       {
2484         music_info[i].loop = music_prefix_info[j].is_loop_music;
2485
2486         break;
2487       }
2488     }
2489
2490     set_music_parameters(i, music->parameter);
2491   }
2492 }
2493
2494 static void ReinitializeGraphics()
2495 {
2496   print_timestamp_init("ReinitializeGraphics");
2497
2498   InitGraphicInfo();                    /* graphic properties mapping */
2499   print_timestamp_time("InitGraphicInfo");
2500   InitElementGraphicInfo();             /* element game graphic mapping */
2501   print_timestamp_time("InitElementGraphicInfo");
2502   InitElementSpecialGraphicInfo();      /* element special graphic mapping */
2503   print_timestamp_time("InitElementSpecialGraphicInfo");
2504
2505   InitElementSmallImages();             /* scale elements to all needed sizes */
2506   print_timestamp_time("InitElementSmallImages");
2507   InitScaledImages();                   /* scale all other images, if needed */
2508   print_timestamp_time("InitScaledImages");
2509   InitFontGraphicInfo();                /* initialize text drawing functions */
2510   print_timestamp_time("InitFontGraphicInfo");
2511
2512   InitGraphicInfo_EM();                 /* graphic mapping for EM engine */
2513   print_timestamp_time("InitGraphicInfo_EM");
2514
2515   InitGraphicCompatibilityInfo();
2516   print_timestamp_time("InitGraphicCompatibilityInfo");
2517
2518   SetMainBackgroundImage(IMG_BACKGROUND);
2519   print_timestamp_time("SetMainBackgroundImage");
2520   SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
2521   print_timestamp_time("SetDoorBackgroundImage");
2522
2523   InitGadgets();
2524   print_timestamp_time("InitGadgets");
2525   InitToons();
2526   print_timestamp_time("InitToons");
2527
2528   print_timestamp_done("ReinitializeGraphics");
2529 }
2530
2531 static void ReinitializeSounds()
2532 {
2533   InitSoundInfo();              /* sound properties mapping */
2534   InitElementSoundInfo();       /* element game sound mapping */
2535   InitGameModeSoundInfo();      /* game mode sound mapping */
2536
2537   InitPlayLevelSound();         /* internal game sound settings */
2538 }
2539
2540 static void ReinitializeMusic()
2541 {
2542   InitMusicInfo();              /* music properties mapping */
2543   InitGameModeMusicInfo();      /* game mode music mapping */
2544 }
2545
2546 static int get_special_property_bit(int element, int property_bit_nr)
2547 {
2548   struct PropertyBitInfo
2549   {
2550     int element;
2551     int bit_nr;
2552   };
2553
2554   static struct PropertyBitInfo pb_can_move_into_acid[] =
2555   {
2556     /* the player may be able fall into acid when gravity is activated */
2557     { EL_PLAYER_1,              0       },
2558     { EL_PLAYER_2,              0       },
2559     { EL_PLAYER_3,              0       },
2560     { EL_PLAYER_4,              0       },
2561     { EL_SP_MURPHY,             0       },
2562     { EL_SOKOBAN_FIELD_PLAYER,  0       },
2563
2564     /* all elements that can move may be able to also move into acid */
2565     { EL_BUG,                   1       },
2566     { EL_BUG_LEFT,              1       },
2567     { EL_BUG_RIGHT,             1       },
2568     { EL_BUG_UP,                1       },
2569     { EL_BUG_DOWN,              1       },
2570     { EL_SPACESHIP,             2       },
2571     { EL_SPACESHIP_LEFT,        2       },
2572     { EL_SPACESHIP_RIGHT,       2       },
2573     { EL_SPACESHIP_UP,          2       },
2574     { EL_SPACESHIP_DOWN,        2       },
2575     { EL_BD_BUTTERFLY,          3       },
2576     { EL_BD_BUTTERFLY_LEFT,     3       },
2577     { EL_BD_BUTTERFLY_RIGHT,    3       },
2578     { EL_BD_BUTTERFLY_UP,       3       },
2579     { EL_BD_BUTTERFLY_DOWN,     3       },
2580     { EL_BD_FIREFLY,            4       },
2581     { EL_BD_FIREFLY_LEFT,       4       },
2582     { EL_BD_FIREFLY_RIGHT,      4       },
2583     { EL_BD_FIREFLY_UP,         4       },
2584     { EL_BD_FIREFLY_DOWN,       4       },
2585     { EL_YAMYAM,                5       },
2586     { EL_YAMYAM_LEFT,           5       },
2587     { EL_YAMYAM_RIGHT,          5       },
2588     { EL_YAMYAM_UP,             5       },
2589     { EL_YAMYAM_DOWN,           5       },
2590     { EL_DARK_YAMYAM,           6       },
2591     { EL_ROBOT,                 7       },
2592     { EL_PACMAN,                8       },
2593     { EL_PACMAN_LEFT,           8       },
2594     { EL_PACMAN_RIGHT,          8       },
2595     { EL_PACMAN_UP,             8       },
2596     { EL_PACMAN_DOWN,           8       },
2597     { EL_MOLE,                  9       },
2598     { EL_MOLE_LEFT,             9       },
2599     { EL_MOLE_RIGHT,            9       },
2600     { EL_MOLE_UP,               9       },
2601     { EL_MOLE_DOWN,             9       },
2602     { EL_PENGUIN,               10      },
2603     { EL_PIG,                   11      },
2604     { EL_DRAGON,                12      },
2605     { EL_SATELLITE,             13      },
2606     { EL_SP_SNIKSNAK,           14      },
2607     { EL_SP_ELECTRON,           15      },
2608     { EL_BALLOON,               16      },
2609     { EL_SPRING,                17      },
2610     { EL_EMC_ANDROID,           18      },
2611
2612     { -1,                       -1      },
2613   };
2614
2615   static struct PropertyBitInfo pb_dont_collide_with[] =
2616   {
2617     { EL_SP_SNIKSNAK,           0       },
2618     { EL_SP_ELECTRON,           1       },
2619
2620     { -1,                       -1      },
2621   };
2622
2623   static struct
2624   {
2625     int bit_nr;
2626     struct PropertyBitInfo *pb_info;
2627   } pb_definition[] =
2628   {
2629     { EP_CAN_MOVE_INTO_ACID,    pb_can_move_into_acid   },
2630     { EP_DONT_COLLIDE_WITH,     pb_dont_collide_with    },
2631
2632     { -1,                       NULL                    },
2633   };
2634
2635   struct PropertyBitInfo *pb_info = NULL;
2636   int i;
2637
2638   for (i = 0; pb_definition[i].bit_nr != -1; i++)
2639     if (pb_definition[i].bit_nr == property_bit_nr)
2640       pb_info = pb_definition[i].pb_info;
2641
2642   if (pb_info == NULL)
2643     return -1;
2644
2645   for (i = 0; pb_info[i].element != -1; i++)
2646     if (pb_info[i].element == element)
2647       return pb_info[i].bit_nr;
2648
2649   return -1;
2650 }
2651
2652 void setBitfieldProperty(int *bitfield, int property_bit_nr, int element,
2653                          boolean property_value)
2654 {
2655   int bit_nr = get_special_property_bit(element, property_bit_nr);
2656
2657   if (bit_nr > -1)
2658   {
2659     if (property_value)
2660       *bitfield |=  (1 << bit_nr);
2661     else
2662       *bitfield &= ~(1 << bit_nr);
2663   }
2664 }
2665
2666 boolean getBitfieldProperty(int *bitfield, int property_bit_nr, int element)
2667 {
2668   int bit_nr = get_special_property_bit(element, property_bit_nr);
2669
2670   if (bit_nr > -1)
2671     return ((*bitfield & (1 << bit_nr)) != 0);
2672
2673   return FALSE;
2674 }
2675
2676 static void ResolveGroupElementExt(int group_element, int recursion_depth)
2677 {
2678   static int group_nr;
2679   static struct ElementGroupInfo *group;
2680   struct ElementGroupInfo *actual_group = element_info[group_element].group;
2681   int i;
2682
2683   if (actual_group == NULL)                     /* not yet initialized */
2684     return;
2685
2686   if (recursion_depth > NUM_GROUP_ELEMENTS)     /* recursion too deep */
2687   {
2688     Error(ERR_WARN, "recursion too deep when resolving group element %d",
2689           group_element - EL_GROUP_START + 1);
2690
2691     /* replace element which caused too deep recursion by question mark */
2692     group->element_resolved[group->num_elements_resolved++] = EL_UNKNOWN;
2693
2694     return;
2695   }
2696
2697   if (recursion_depth == 0)                     /* initialization */
2698   {
2699     group = actual_group;
2700     group_nr = GROUP_NR(group_element);
2701
2702     group->num_elements_resolved = 0;
2703     group->choice_pos = 0;
2704
2705     for (i = 0; i < MAX_NUM_ELEMENTS; i++)
2706       element_info[i].in_group[group_nr] = FALSE;
2707   }
2708
2709   for (i = 0; i < actual_group->num_elements; i++)
2710   {
2711     int element = actual_group->element[i];
2712
2713     if (group->num_elements_resolved == NUM_FILE_ELEMENTS)
2714       break;
2715
2716     if (IS_GROUP_ELEMENT(element))
2717       ResolveGroupElementExt(element, recursion_depth + 1);
2718     else
2719     {
2720       group->element_resolved[group->num_elements_resolved++] = element;
2721       element_info[element].in_group[group_nr] = TRUE;
2722     }
2723   }
2724 }
2725
2726 void ResolveGroupElement(int group_element)
2727 {
2728   ResolveGroupElementExt(group_element, 0);
2729 }
2730
2731 void InitElementPropertiesStatic()
2732 {
2733   static boolean clipboard_elements_initialized = FALSE;
2734
2735   static int ep_diggable[] =
2736   {
2737     EL_SAND,
2738     EL_SP_BASE,
2739     EL_SP_BUGGY_BASE,
2740     EL_SP_BUGGY_BASE_ACTIVATING,
2741     EL_TRAP,
2742     EL_INVISIBLE_SAND,
2743     EL_INVISIBLE_SAND_ACTIVE,
2744     EL_EMC_GRASS,
2745
2746     /* !!! currently not diggable, but handled by 'ep_dont_run_into' !!! */
2747     /* (if amoeba can grow into anything diggable, maybe keep these out) */
2748 #if 0
2749     EL_LANDMINE,
2750     EL_DC_LANDMINE,
2751     EL_TRAP_ACTIVE,
2752     EL_SP_BUGGY_BASE_ACTIVE,
2753     EL_EMC_PLANT,
2754 #endif
2755
2756     -1
2757   };
2758
2759   static int ep_collectible_only[] =
2760   {
2761     EL_BD_DIAMOND,
2762     EL_EMERALD,
2763     EL_DIAMOND,
2764     EL_EMERALD_YELLOW,
2765     EL_EMERALD_RED,
2766     EL_EMERALD_PURPLE,
2767     EL_KEY_1,
2768     EL_KEY_2,
2769     EL_KEY_3,
2770     EL_KEY_4,
2771     EL_EM_KEY_1,
2772     EL_EM_KEY_2,
2773     EL_EM_KEY_3,
2774     EL_EM_KEY_4,
2775     EL_EMC_KEY_5,
2776     EL_EMC_KEY_6,
2777     EL_EMC_KEY_7,
2778     EL_EMC_KEY_8,
2779     EL_DYNAMITE,
2780     EL_EM_DYNAMITE,
2781     EL_DYNABOMB_INCREASE_NUMBER,
2782     EL_DYNABOMB_INCREASE_SIZE,
2783     EL_DYNABOMB_INCREASE_POWER,
2784     EL_SP_INFOTRON,
2785     EL_SP_DISK_RED,
2786     EL_PEARL,
2787     EL_CRYSTAL,
2788     EL_DC_KEY_WHITE,
2789     EL_SHIELD_NORMAL,
2790     EL_SHIELD_DEADLY,
2791     EL_EXTRA_TIME,
2792     EL_ENVELOPE_1,
2793     EL_ENVELOPE_2,
2794     EL_ENVELOPE_3,
2795     EL_ENVELOPE_4,
2796     EL_SPEED_PILL,
2797     EL_EMC_LENSES,
2798     EL_EMC_MAGNIFIER,
2799
2800 #if 0
2801     /* !!! handle separately !!! */
2802     EL_DC_LANDMINE,     /* deadly when running into, but can be snapped */
2803 #endif
2804
2805     -1
2806   };
2807
2808   static int ep_dont_run_into[] =
2809   {
2810     /* same elements as in 'ep_dont_touch' */
2811     EL_BUG,
2812     EL_SPACESHIP,
2813     EL_BD_BUTTERFLY,
2814     EL_BD_FIREFLY,
2815
2816     /* same elements as in 'ep_dont_collide_with' */
2817     EL_YAMYAM,
2818     EL_DARK_YAMYAM,
2819     EL_ROBOT,
2820     EL_PACMAN,
2821     EL_SP_SNIKSNAK,
2822     EL_SP_ELECTRON,
2823
2824     /* new elements */
2825     EL_AMOEBA_DROP,
2826     EL_ACID,
2827
2828     /* !!! maybe this should better be handled by 'ep_diggable' !!! */
2829 #if 1
2830     EL_LANDMINE,
2831     EL_DC_LANDMINE,
2832     EL_TRAP_ACTIVE,
2833     EL_SP_BUGGY_BASE_ACTIVE,
2834     EL_EMC_PLANT,
2835 #endif
2836
2837     -1
2838   };
2839
2840   static int ep_dont_collide_with[] =
2841   {
2842     /* same elements as in 'ep_dont_touch' */
2843     EL_BUG,
2844     EL_SPACESHIP,
2845     EL_BD_BUTTERFLY,
2846     EL_BD_FIREFLY,
2847
2848     /* new elements */
2849     EL_YAMYAM,
2850     EL_DARK_YAMYAM,
2851     EL_ROBOT,
2852     EL_PACMAN,
2853     EL_SP_SNIKSNAK,
2854     EL_SP_ELECTRON,
2855
2856     -1
2857   };
2858
2859   static int ep_dont_touch[] =
2860   {
2861     EL_BUG,
2862     EL_SPACESHIP,
2863     EL_BD_BUTTERFLY,
2864     EL_BD_FIREFLY,
2865
2866     -1
2867   };
2868
2869   static int ep_indestructible[] =
2870   {
2871     EL_STEELWALL,
2872     EL_ACID,
2873     EL_ACID_POOL_TOPLEFT,
2874     EL_ACID_POOL_TOPRIGHT,
2875     EL_ACID_POOL_BOTTOMLEFT,
2876     EL_ACID_POOL_BOTTOM,
2877     EL_ACID_POOL_BOTTOMRIGHT,
2878     EL_SP_HARDWARE_GRAY,
2879     EL_SP_HARDWARE_GREEN,
2880     EL_SP_HARDWARE_BLUE,
2881     EL_SP_HARDWARE_RED,
2882     EL_SP_HARDWARE_YELLOW,
2883     EL_SP_HARDWARE_BASE_1,
2884     EL_SP_HARDWARE_BASE_2,
2885     EL_SP_HARDWARE_BASE_3,
2886     EL_SP_HARDWARE_BASE_4,
2887     EL_SP_HARDWARE_BASE_5,
2888     EL_SP_HARDWARE_BASE_6,
2889     EL_INVISIBLE_STEELWALL,
2890     EL_INVISIBLE_STEELWALL_ACTIVE,
2891     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2892     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2893     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2894     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2895     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2896     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2897     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2898     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2899     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2900     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2901     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2902     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2903     EL_LIGHT_SWITCH,
2904     EL_LIGHT_SWITCH_ACTIVE,
2905     EL_SIGN_EXCLAMATION,
2906     EL_SIGN_RADIOACTIVITY,
2907     EL_SIGN_STOP,
2908     EL_SIGN_WHEELCHAIR,
2909     EL_SIGN_PARKING,
2910     EL_SIGN_NO_ENTRY,
2911     EL_SIGN_UNUSED_1,
2912     EL_SIGN_GIVE_WAY,
2913     EL_SIGN_ENTRY_FORBIDDEN,
2914     EL_SIGN_EMERGENCY_EXIT,
2915     EL_SIGN_YIN_YANG,
2916     EL_SIGN_UNUSED_2,
2917     EL_SIGN_SPERMS,
2918     EL_SIGN_BULLET,
2919     EL_SIGN_HEART,
2920     EL_SIGN_CROSS,
2921     EL_SIGN_FRANKIE,
2922     EL_STEEL_EXIT_CLOSED,
2923     EL_STEEL_EXIT_OPEN,
2924     EL_STEEL_EXIT_OPENING,
2925     EL_STEEL_EXIT_CLOSING,
2926     EL_EM_STEEL_EXIT_CLOSED,
2927     EL_EM_STEEL_EXIT_OPEN,
2928     EL_EM_STEEL_EXIT_OPENING,
2929     EL_EM_STEEL_EXIT_CLOSING,
2930     EL_DC_STEELWALL_1_LEFT,
2931     EL_DC_STEELWALL_1_RIGHT,
2932     EL_DC_STEELWALL_1_TOP,
2933     EL_DC_STEELWALL_1_BOTTOM,
2934     EL_DC_STEELWALL_1_HORIZONTAL,
2935     EL_DC_STEELWALL_1_VERTICAL,
2936     EL_DC_STEELWALL_1_TOPLEFT,
2937     EL_DC_STEELWALL_1_TOPRIGHT,
2938     EL_DC_STEELWALL_1_BOTTOMLEFT,
2939     EL_DC_STEELWALL_1_BOTTOMRIGHT,
2940     EL_DC_STEELWALL_1_TOPLEFT_2,
2941     EL_DC_STEELWALL_1_TOPRIGHT_2,
2942     EL_DC_STEELWALL_1_BOTTOMLEFT_2,
2943     EL_DC_STEELWALL_1_BOTTOMRIGHT_2,
2944     EL_DC_STEELWALL_2_LEFT,
2945     EL_DC_STEELWALL_2_RIGHT,
2946     EL_DC_STEELWALL_2_TOP,
2947     EL_DC_STEELWALL_2_BOTTOM,
2948     EL_DC_STEELWALL_2_HORIZONTAL,
2949     EL_DC_STEELWALL_2_VERTICAL,
2950     EL_DC_STEELWALL_2_MIDDLE,
2951     EL_DC_STEELWALL_2_SINGLE,
2952     EL_STEELWALL_SLIPPERY,
2953     EL_EMC_STEELWALL_1,
2954     EL_EMC_STEELWALL_2,
2955     EL_EMC_STEELWALL_3,
2956     EL_EMC_STEELWALL_4,
2957     EL_CRYSTAL,
2958     EL_GATE_1,
2959     EL_GATE_2,
2960     EL_GATE_3,
2961     EL_GATE_4,
2962     EL_GATE_1_GRAY,
2963     EL_GATE_2_GRAY,
2964     EL_GATE_3_GRAY,
2965     EL_GATE_4_GRAY,
2966     EL_GATE_1_GRAY_ACTIVE,
2967     EL_GATE_2_GRAY_ACTIVE,
2968     EL_GATE_3_GRAY_ACTIVE,
2969     EL_GATE_4_GRAY_ACTIVE,
2970     EL_EM_GATE_1,
2971     EL_EM_GATE_2,
2972     EL_EM_GATE_3,
2973     EL_EM_GATE_4,
2974     EL_EM_GATE_1_GRAY,
2975     EL_EM_GATE_2_GRAY,
2976     EL_EM_GATE_3_GRAY,
2977     EL_EM_GATE_4_GRAY,
2978     EL_EM_GATE_1_GRAY_ACTIVE,
2979     EL_EM_GATE_2_GRAY_ACTIVE,
2980     EL_EM_GATE_3_GRAY_ACTIVE,
2981     EL_EM_GATE_4_GRAY_ACTIVE,
2982     EL_EMC_GATE_5,
2983     EL_EMC_GATE_6,
2984     EL_EMC_GATE_7,
2985     EL_EMC_GATE_8,
2986     EL_EMC_GATE_5_GRAY,
2987     EL_EMC_GATE_6_GRAY,
2988     EL_EMC_GATE_7_GRAY,
2989     EL_EMC_GATE_8_GRAY,
2990     EL_EMC_GATE_5_GRAY_ACTIVE,
2991     EL_EMC_GATE_6_GRAY_ACTIVE,
2992     EL_EMC_GATE_7_GRAY_ACTIVE,
2993     EL_EMC_GATE_8_GRAY_ACTIVE,
2994     EL_DC_GATE_WHITE,
2995     EL_DC_GATE_WHITE_GRAY,
2996     EL_DC_GATE_WHITE_GRAY_ACTIVE,
2997     EL_DC_GATE_FAKE_GRAY,
2998     EL_SWITCHGATE_OPEN,
2999     EL_SWITCHGATE_OPENING,
3000     EL_SWITCHGATE_CLOSED,
3001     EL_SWITCHGATE_CLOSING,
3002 #if 1
3003     EL_DC_SWITCHGATE_SWITCH_UP,
3004     EL_DC_SWITCHGATE_SWITCH_DOWN,
3005 #endif
3006     EL_TIMEGATE_OPEN,
3007     EL_TIMEGATE_OPENING,
3008     EL_TIMEGATE_CLOSED,
3009     EL_TIMEGATE_CLOSING,
3010 #if 1
3011     EL_DC_TIMEGATE_SWITCH,
3012     EL_DC_TIMEGATE_SWITCH_ACTIVE,
3013 #endif
3014     EL_TUBE_ANY,
3015     EL_TUBE_VERTICAL,
3016     EL_TUBE_HORIZONTAL,
3017     EL_TUBE_VERTICAL_LEFT,
3018     EL_TUBE_VERTICAL_RIGHT,
3019     EL_TUBE_HORIZONTAL_UP,
3020     EL_TUBE_HORIZONTAL_DOWN,
3021     EL_TUBE_LEFT_UP,
3022     EL_TUBE_LEFT_DOWN,
3023     EL_TUBE_RIGHT_UP,
3024     EL_TUBE_RIGHT_DOWN,
3025     EL_EXPANDABLE_STEELWALL_HORIZONTAL,
3026     EL_EXPANDABLE_STEELWALL_VERTICAL,
3027     EL_EXPANDABLE_STEELWALL_ANY,
3028
3029     -1
3030   };
3031
3032   static int ep_slippery[] =
3033   {
3034     EL_WALL_SLIPPERY,
3035     EL_BD_WALL,
3036     EL_ROCK,
3037     EL_BD_ROCK,
3038     EL_EMERALD,
3039     EL_BD_DIAMOND,
3040     EL_EMERALD_YELLOW,
3041     EL_EMERALD_RED,
3042     EL_EMERALD_PURPLE,
3043     EL_DIAMOND,
3044     EL_BOMB,
3045     EL_NUT,
3046     EL_ROBOT_WHEEL_ACTIVE,
3047     EL_ROBOT_WHEEL,
3048     EL_TIME_ORB_FULL,
3049     EL_TIME_ORB_EMPTY,
3050     EL_LAMP_ACTIVE,
3051     EL_LAMP,
3052     EL_ACID_POOL_TOPLEFT,
3053     EL_ACID_POOL_TOPRIGHT,
3054     EL_SATELLITE,
3055     EL_SP_ZONK,
3056     EL_SP_INFOTRON,
3057     EL_SP_CHIP_SINGLE,
3058     EL_SP_CHIP_LEFT,
3059     EL_SP_CHIP_RIGHT,
3060     EL_SP_CHIP_TOP,
3061     EL_SP_CHIP_BOTTOM,
3062     EL_SPEED_PILL,
3063     EL_STEELWALL_SLIPPERY,
3064     EL_PEARL,
3065     EL_CRYSTAL,
3066     EL_EMC_WALL_SLIPPERY_1,
3067     EL_EMC_WALL_SLIPPERY_2,
3068     EL_EMC_WALL_SLIPPERY_3,
3069     EL_EMC_WALL_SLIPPERY_4,
3070     EL_EMC_MAGIC_BALL,
3071     EL_EMC_MAGIC_BALL_ACTIVE,
3072
3073     -1
3074   };
3075
3076   static int ep_can_change[] =
3077   {
3078     -1
3079   };
3080
3081   static int ep_can_move[] =
3082   {
3083     /* same elements as in 'pb_can_move_into_acid' */
3084     EL_BUG,
3085     EL_SPACESHIP,
3086     EL_BD_BUTTERFLY,
3087     EL_BD_FIREFLY,
3088     EL_YAMYAM,
3089     EL_DARK_YAMYAM,
3090     EL_ROBOT,
3091     EL_PACMAN,
3092     EL_MOLE,
3093     EL_PENGUIN,
3094     EL_PIG,
3095     EL_DRAGON,
3096     EL_SATELLITE,
3097     EL_SP_SNIKSNAK,
3098     EL_SP_ELECTRON,
3099     EL_BALLOON,
3100     EL_SPRING,
3101     EL_EMC_ANDROID,
3102
3103     -1
3104   };
3105
3106   static int ep_can_fall[] =
3107   {
3108     EL_ROCK,
3109     EL_BD_ROCK,
3110     EL_EMERALD,
3111     EL_BD_DIAMOND,
3112     EL_EMERALD_YELLOW,
3113     EL_EMERALD_RED,
3114     EL_EMERALD_PURPLE,
3115     EL_DIAMOND,
3116     EL_BOMB,
3117     EL_NUT,
3118     EL_AMOEBA_DROP,
3119     EL_QUICKSAND_FULL,
3120     EL_QUICKSAND_FAST_FULL,
3121     EL_MAGIC_WALL_FULL,
3122     EL_BD_MAGIC_WALL_FULL,
3123     EL_DC_MAGIC_WALL_FULL,
3124     EL_TIME_ORB_FULL,
3125     EL_TIME_ORB_EMPTY,
3126     EL_SP_ZONK,
3127     EL_SP_INFOTRON,
3128     EL_SP_DISK_ORANGE,
3129     EL_PEARL,
3130     EL_CRYSTAL,
3131     EL_SPRING,
3132     EL_DX_SUPABOMB,
3133
3134     -1
3135   };
3136
3137   static int ep_can_smash_player[] =
3138   {
3139     EL_ROCK,
3140     EL_BD_ROCK,
3141     EL_EMERALD,
3142     EL_BD_DIAMOND,
3143     EL_EMERALD_YELLOW,
3144     EL_EMERALD_RED,
3145     EL_EMERALD_PURPLE,
3146     EL_DIAMOND,
3147     EL_BOMB,
3148     EL_NUT,
3149     EL_AMOEBA_DROP,
3150     EL_TIME_ORB_FULL,
3151     EL_TIME_ORB_EMPTY,
3152     EL_SP_ZONK,
3153     EL_SP_INFOTRON,
3154     EL_SP_DISK_ORANGE,
3155     EL_PEARL,
3156     EL_CRYSTAL,
3157     EL_SPRING,
3158     EL_DX_SUPABOMB,
3159
3160     -1
3161   };
3162
3163   static int ep_can_smash_enemies[] =
3164   {
3165     EL_ROCK,
3166     EL_BD_ROCK,
3167     EL_SP_ZONK,
3168
3169     -1
3170   };
3171
3172   static int ep_can_smash_everything[] =
3173   {
3174     EL_ROCK,
3175     EL_BD_ROCK,
3176     EL_SP_ZONK,
3177
3178     -1
3179   };
3180
3181   static int ep_explodes_by_fire[] =
3182   {
3183     /* same elements as in 'ep_explodes_impact' */
3184     EL_BOMB,
3185     EL_SP_DISK_ORANGE,
3186     EL_DX_SUPABOMB,
3187
3188     /* same elements as in 'ep_explodes_smashed' */
3189     EL_SATELLITE,
3190     EL_PIG,
3191     EL_DRAGON,
3192     EL_MOLE,
3193
3194     /* new elements */
3195     EL_DYNAMITE,
3196     EL_DYNAMITE_ACTIVE,
3197     EL_EM_DYNAMITE,
3198     EL_EM_DYNAMITE_ACTIVE,
3199     EL_DYNABOMB_PLAYER_1_ACTIVE,
3200     EL_DYNABOMB_PLAYER_2_ACTIVE,
3201     EL_DYNABOMB_PLAYER_3_ACTIVE,
3202     EL_DYNABOMB_PLAYER_4_ACTIVE,
3203     EL_DYNABOMB_INCREASE_NUMBER,
3204     EL_DYNABOMB_INCREASE_SIZE,
3205     EL_DYNABOMB_INCREASE_POWER,
3206     EL_SP_DISK_RED_ACTIVE,
3207     EL_BUG,
3208     EL_PENGUIN,
3209     EL_SP_DISK_RED,
3210     EL_SP_DISK_YELLOW,
3211     EL_SP_SNIKSNAK,
3212     EL_SP_ELECTRON,
3213 #if 0
3214     EL_BLACK_ORB,
3215 #endif
3216
3217     -1
3218   };
3219
3220   static int ep_explodes_smashed[] =
3221   {
3222     /* same elements as in 'ep_explodes_impact' */
3223     EL_BOMB,
3224     EL_SP_DISK_ORANGE,
3225     EL_DX_SUPABOMB,
3226
3227     /* new elements */
3228     EL_SATELLITE,
3229     EL_PIG,
3230     EL_DRAGON,
3231     EL_MOLE,
3232
3233     -1
3234   };
3235
3236   static int ep_explodes_impact[] =
3237   {
3238     EL_BOMB,
3239     EL_SP_DISK_ORANGE,
3240     EL_DX_SUPABOMB,
3241
3242     -1
3243   };
3244
3245   static int ep_walkable_over[] =
3246   {
3247     EL_EMPTY_SPACE,
3248     EL_SP_EMPTY_SPACE,
3249     EL_SOKOBAN_FIELD_EMPTY,
3250     EL_EXIT_OPEN,
3251     EL_EM_EXIT_OPEN,
3252 #if 1
3253     EL_EM_EXIT_OPENING,
3254 #endif
3255     EL_SP_EXIT_OPEN,
3256     EL_SP_EXIT_OPENING,
3257     EL_STEEL_EXIT_OPEN,
3258     EL_EM_STEEL_EXIT_OPEN,
3259 #if 1
3260     EL_EM_STEEL_EXIT_OPENING,
3261 #endif
3262     EL_GATE_1,
3263     EL_GATE_2,
3264     EL_GATE_3,
3265     EL_GATE_4,
3266     EL_GATE_1_GRAY,
3267     EL_GATE_2_GRAY,
3268     EL_GATE_3_GRAY,
3269     EL_GATE_4_GRAY,
3270     EL_GATE_1_GRAY_ACTIVE,
3271     EL_GATE_2_GRAY_ACTIVE,
3272     EL_GATE_3_GRAY_ACTIVE,
3273     EL_GATE_4_GRAY_ACTIVE,
3274     EL_PENGUIN,
3275     EL_PIG,
3276     EL_DRAGON,
3277
3278     -1
3279   };
3280
3281   static int ep_walkable_inside[] =
3282   {
3283     EL_TUBE_ANY,
3284     EL_TUBE_VERTICAL,
3285     EL_TUBE_HORIZONTAL,
3286     EL_TUBE_VERTICAL_LEFT,
3287     EL_TUBE_VERTICAL_RIGHT,
3288     EL_TUBE_HORIZONTAL_UP,
3289     EL_TUBE_HORIZONTAL_DOWN,
3290     EL_TUBE_LEFT_UP,
3291     EL_TUBE_LEFT_DOWN,
3292     EL_TUBE_RIGHT_UP,
3293     EL_TUBE_RIGHT_DOWN,
3294
3295     -1
3296   };
3297
3298   static int ep_walkable_under[] =
3299   {
3300     -1
3301   };
3302
3303   static int ep_passable_over[] =
3304   {
3305     EL_EM_GATE_1,
3306     EL_EM_GATE_2,
3307     EL_EM_GATE_3,
3308     EL_EM_GATE_4,
3309     EL_EM_GATE_1_GRAY,
3310     EL_EM_GATE_2_GRAY,
3311     EL_EM_GATE_3_GRAY,
3312     EL_EM_GATE_4_GRAY,
3313     EL_EM_GATE_1_GRAY_ACTIVE,
3314     EL_EM_GATE_2_GRAY_ACTIVE,
3315     EL_EM_GATE_3_GRAY_ACTIVE,
3316     EL_EM_GATE_4_GRAY_ACTIVE,
3317     EL_EMC_GATE_5,
3318     EL_EMC_GATE_6,
3319     EL_EMC_GATE_7,
3320     EL_EMC_GATE_8,
3321     EL_EMC_GATE_5_GRAY,
3322     EL_EMC_GATE_6_GRAY,
3323     EL_EMC_GATE_7_GRAY,
3324     EL_EMC_GATE_8_GRAY,
3325     EL_EMC_GATE_5_GRAY_ACTIVE,
3326     EL_EMC_GATE_6_GRAY_ACTIVE,
3327     EL_EMC_GATE_7_GRAY_ACTIVE,
3328     EL_EMC_GATE_8_GRAY_ACTIVE,
3329     EL_DC_GATE_WHITE,
3330     EL_DC_GATE_WHITE_GRAY,
3331     EL_DC_GATE_WHITE_GRAY_ACTIVE,
3332     EL_SWITCHGATE_OPEN,
3333     EL_TIMEGATE_OPEN,
3334
3335     -1
3336   };
3337
3338   static int ep_passable_inside[] =
3339   {
3340     EL_SP_PORT_LEFT,
3341     EL_SP_PORT_RIGHT,
3342     EL_SP_PORT_UP,
3343     EL_SP_PORT_DOWN,
3344     EL_SP_PORT_HORIZONTAL,
3345     EL_SP_PORT_VERTICAL,
3346     EL_SP_PORT_ANY,
3347     EL_SP_GRAVITY_PORT_LEFT,
3348     EL_SP_GRAVITY_PORT_RIGHT,
3349     EL_SP_GRAVITY_PORT_UP,
3350     EL_SP_GRAVITY_PORT_DOWN,
3351     EL_SP_GRAVITY_ON_PORT_LEFT,
3352     EL_SP_GRAVITY_ON_PORT_RIGHT,
3353     EL_SP_GRAVITY_ON_PORT_UP,
3354     EL_SP_GRAVITY_ON_PORT_DOWN,
3355     EL_SP_GRAVITY_OFF_PORT_LEFT,
3356     EL_SP_GRAVITY_OFF_PORT_RIGHT,
3357     EL_SP_GRAVITY_OFF_PORT_UP,
3358     EL_SP_GRAVITY_OFF_PORT_DOWN,
3359
3360     -1
3361   };
3362
3363   static int ep_passable_under[] =
3364   {
3365     -1
3366   };
3367
3368   static int ep_droppable[] =
3369   {
3370     -1
3371   };
3372
3373   static int ep_explodes_1x1_old[] =
3374   {
3375     -1
3376   };
3377
3378   static int ep_pushable[] =
3379   {
3380     EL_ROCK,
3381     EL_BOMB,
3382     EL_DX_SUPABOMB,
3383     EL_NUT,
3384     EL_TIME_ORB_EMPTY,
3385     EL_SP_ZONK,
3386     EL_SP_DISK_ORANGE,
3387     EL_SPRING,
3388     EL_BD_ROCK,
3389     EL_SOKOBAN_OBJECT,
3390     EL_SOKOBAN_FIELD_FULL,
3391     EL_SATELLITE,
3392     EL_SP_DISK_YELLOW,
3393     EL_BALLOON,
3394     EL_EMC_ANDROID,
3395
3396     -1
3397   };
3398
3399   static int ep_explodes_cross_old[] =
3400   {
3401     -1
3402   };
3403
3404   static int ep_protected[] =
3405   {
3406     /* same elements as in 'ep_walkable_inside' */
3407     EL_TUBE_ANY,
3408     EL_TUBE_VERTICAL,
3409     EL_TUBE_HORIZONTAL,
3410     EL_TUBE_VERTICAL_LEFT,
3411     EL_TUBE_VERTICAL_RIGHT,
3412     EL_TUBE_HORIZONTAL_UP,
3413     EL_TUBE_HORIZONTAL_DOWN,
3414     EL_TUBE_LEFT_UP,
3415     EL_TUBE_LEFT_DOWN,
3416     EL_TUBE_RIGHT_UP,
3417     EL_TUBE_RIGHT_DOWN,
3418
3419     /* same elements as in 'ep_passable_over' */
3420     EL_EM_GATE_1,
3421     EL_EM_GATE_2,
3422     EL_EM_GATE_3,
3423     EL_EM_GATE_4,
3424     EL_EM_GATE_1_GRAY,
3425     EL_EM_GATE_2_GRAY,
3426     EL_EM_GATE_3_GRAY,
3427     EL_EM_GATE_4_GRAY,
3428     EL_EM_GATE_1_GRAY_ACTIVE,
3429     EL_EM_GATE_2_GRAY_ACTIVE,
3430     EL_EM_GATE_3_GRAY_ACTIVE,
3431     EL_EM_GATE_4_GRAY_ACTIVE,
3432     EL_EMC_GATE_5,
3433     EL_EMC_GATE_6,
3434     EL_EMC_GATE_7,
3435     EL_EMC_GATE_8,
3436     EL_EMC_GATE_5_GRAY,
3437     EL_EMC_GATE_6_GRAY,
3438     EL_EMC_GATE_7_GRAY,
3439     EL_EMC_GATE_8_GRAY,
3440     EL_EMC_GATE_5_GRAY_ACTIVE,
3441     EL_EMC_GATE_6_GRAY_ACTIVE,
3442     EL_EMC_GATE_7_GRAY_ACTIVE,
3443     EL_EMC_GATE_8_GRAY_ACTIVE,
3444     EL_DC_GATE_WHITE,
3445     EL_DC_GATE_WHITE_GRAY,
3446     EL_DC_GATE_WHITE_GRAY_ACTIVE,
3447     EL_SWITCHGATE_OPEN,
3448     EL_TIMEGATE_OPEN,
3449
3450     /* same elements as in 'ep_passable_inside' */
3451     EL_SP_PORT_LEFT,
3452     EL_SP_PORT_RIGHT,
3453     EL_SP_PORT_UP,
3454     EL_SP_PORT_DOWN,
3455     EL_SP_PORT_HORIZONTAL,
3456     EL_SP_PORT_VERTICAL,
3457     EL_SP_PORT_ANY,
3458     EL_SP_GRAVITY_PORT_LEFT,
3459     EL_SP_GRAVITY_PORT_RIGHT,
3460     EL_SP_GRAVITY_PORT_UP,
3461     EL_SP_GRAVITY_PORT_DOWN,
3462     EL_SP_GRAVITY_ON_PORT_LEFT,
3463     EL_SP_GRAVITY_ON_PORT_RIGHT,
3464     EL_SP_GRAVITY_ON_PORT_UP,
3465     EL_SP_GRAVITY_ON_PORT_DOWN,
3466     EL_SP_GRAVITY_OFF_PORT_LEFT,
3467     EL_SP_GRAVITY_OFF_PORT_RIGHT,
3468     EL_SP_GRAVITY_OFF_PORT_UP,
3469     EL_SP_GRAVITY_OFF_PORT_DOWN,
3470
3471     -1
3472   };
3473
3474   static int ep_throwable[] =
3475   {
3476     -1
3477   };
3478
3479   static int ep_can_explode[] =
3480   {
3481     /* same elements as in 'ep_explodes_impact' */
3482     EL_BOMB,
3483     EL_SP_DISK_ORANGE,
3484     EL_DX_SUPABOMB,
3485
3486     /* same elements as in 'ep_explodes_smashed' */
3487     EL_SATELLITE,
3488     EL_PIG,
3489     EL_DRAGON,
3490     EL_MOLE,
3491
3492     /* elements that can explode by explosion or by dragonfire */
3493     EL_DYNAMITE,
3494     EL_DYNAMITE_ACTIVE,
3495     EL_EM_DYNAMITE,
3496     EL_EM_DYNAMITE_ACTIVE,
3497     EL_DYNABOMB_PLAYER_1_ACTIVE,
3498     EL_DYNABOMB_PLAYER_2_ACTIVE,
3499     EL_DYNABOMB_PLAYER_3_ACTIVE,
3500     EL_DYNABOMB_PLAYER_4_ACTIVE,
3501     EL_DYNABOMB_INCREASE_NUMBER,
3502     EL_DYNABOMB_INCREASE_SIZE,
3503     EL_DYNABOMB_INCREASE_POWER,
3504     EL_SP_DISK_RED_ACTIVE,
3505     EL_BUG,
3506     EL_PENGUIN,
3507     EL_SP_DISK_RED,
3508     EL_SP_DISK_YELLOW,
3509     EL_SP_SNIKSNAK,
3510     EL_SP_ELECTRON,
3511
3512     /* elements that can explode only by explosion */
3513     EL_BLACK_ORB,
3514
3515     -1
3516   };
3517
3518   static int ep_gravity_reachable[] =
3519   {
3520     EL_SAND,
3521     EL_SP_BASE,
3522     EL_TRAP,
3523     EL_INVISIBLE_SAND,
3524     EL_INVISIBLE_SAND_ACTIVE,
3525     EL_SP_PORT_LEFT,
3526     EL_SP_PORT_RIGHT,
3527     EL_SP_PORT_UP,
3528     EL_SP_PORT_DOWN,
3529     EL_SP_PORT_HORIZONTAL,
3530     EL_SP_PORT_VERTICAL,
3531     EL_SP_PORT_ANY,
3532     EL_SP_GRAVITY_PORT_LEFT,
3533     EL_SP_GRAVITY_PORT_RIGHT,
3534     EL_SP_GRAVITY_PORT_UP,
3535     EL_SP_GRAVITY_PORT_DOWN,
3536     EL_SP_GRAVITY_ON_PORT_LEFT,
3537     EL_SP_GRAVITY_ON_PORT_RIGHT,
3538     EL_SP_GRAVITY_ON_PORT_UP,
3539     EL_SP_GRAVITY_ON_PORT_DOWN,
3540     EL_SP_GRAVITY_OFF_PORT_LEFT,
3541     EL_SP_GRAVITY_OFF_PORT_RIGHT,
3542     EL_SP_GRAVITY_OFF_PORT_UP,
3543     EL_SP_GRAVITY_OFF_PORT_DOWN,
3544     EL_EMC_GRASS,
3545
3546     -1
3547   };
3548
3549   static int ep_player[] =
3550   {
3551     EL_PLAYER_1,
3552     EL_PLAYER_2,
3553     EL_PLAYER_3,
3554     EL_PLAYER_4,
3555     EL_SP_MURPHY,
3556     EL_SOKOBAN_FIELD_PLAYER,
3557     EL_TRIGGER_PLAYER,
3558
3559     -1
3560   };
3561
3562   static int ep_can_pass_magic_wall[] =
3563   {
3564     EL_ROCK,
3565     EL_BD_ROCK,
3566     EL_EMERALD,
3567     EL_BD_DIAMOND,
3568     EL_EMERALD_YELLOW,
3569     EL_EMERALD_RED,
3570     EL_EMERALD_PURPLE,
3571     EL_DIAMOND,
3572
3573     -1
3574   };
3575
3576   static int ep_can_pass_dc_magic_wall[] =
3577   {
3578     EL_ROCK,
3579     EL_BD_ROCK,
3580     EL_EMERALD,
3581     EL_BD_DIAMOND,
3582     EL_EMERALD_YELLOW,
3583     EL_EMERALD_RED,
3584     EL_EMERALD_PURPLE,
3585     EL_DIAMOND,
3586     EL_PEARL,
3587     EL_CRYSTAL,
3588
3589     -1
3590   };
3591
3592   static int ep_switchable[] =
3593   {
3594     EL_ROBOT_WHEEL,
3595     EL_SP_TERMINAL,
3596     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3597     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3598     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3599     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3600     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3601     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3602     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3603     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3604     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3605     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3606     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3607     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3608     EL_SWITCHGATE_SWITCH_UP,
3609     EL_SWITCHGATE_SWITCH_DOWN,
3610     EL_DC_SWITCHGATE_SWITCH_UP,
3611     EL_DC_SWITCHGATE_SWITCH_DOWN,
3612     EL_LIGHT_SWITCH,
3613     EL_LIGHT_SWITCH_ACTIVE,
3614     EL_TIMEGATE_SWITCH,
3615     EL_DC_TIMEGATE_SWITCH,
3616     EL_BALLOON_SWITCH_LEFT,
3617     EL_BALLOON_SWITCH_RIGHT,
3618     EL_BALLOON_SWITCH_UP,
3619     EL_BALLOON_SWITCH_DOWN,
3620     EL_BALLOON_SWITCH_ANY,
3621     EL_BALLOON_SWITCH_NONE,
3622     EL_LAMP,
3623     EL_TIME_ORB_FULL,
3624     EL_EMC_MAGIC_BALL_SWITCH,
3625     EL_EMC_MAGIC_BALL_SWITCH_ACTIVE,
3626
3627     -1
3628   };
3629
3630   static int ep_bd_element[] =
3631   {
3632     EL_EMPTY,
3633     EL_SAND,
3634     EL_WALL_SLIPPERY,
3635     EL_BD_WALL,
3636     EL_ROCK,
3637     EL_BD_ROCK,
3638     EL_BD_DIAMOND,
3639     EL_BD_MAGIC_WALL,
3640     EL_EXIT_CLOSED,
3641     EL_EXIT_OPEN,
3642     EL_STEELWALL,
3643     EL_PLAYER_1,
3644     EL_PLAYER_2,
3645     EL_PLAYER_3,
3646     EL_PLAYER_4,
3647     EL_BD_FIREFLY,
3648     EL_BD_FIREFLY_1,
3649     EL_BD_FIREFLY_2,
3650     EL_BD_FIREFLY_3,
3651     EL_BD_FIREFLY_4,
3652     EL_BD_BUTTERFLY,
3653     EL_BD_BUTTERFLY_1,
3654     EL_BD_BUTTERFLY_2,
3655     EL_BD_BUTTERFLY_3,
3656     EL_BD_BUTTERFLY_4,
3657     EL_BD_AMOEBA,
3658     EL_CHAR_QUESTION,
3659     EL_UNKNOWN,
3660
3661     -1
3662   };
3663
3664   static int ep_sp_element[] =
3665   {
3666     /* should always be valid */
3667     EL_EMPTY,
3668
3669     /* standard classic Supaplex elements */
3670     EL_SP_EMPTY,
3671     EL_SP_ZONK,
3672     EL_SP_BASE,
3673     EL_SP_MURPHY,
3674     EL_SP_INFOTRON,
3675     EL_SP_CHIP_SINGLE,
3676     EL_SP_HARDWARE_GRAY,
3677     EL_SP_EXIT_CLOSED,
3678     EL_SP_EXIT_OPEN,
3679     EL_SP_DISK_ORANGE,
3680     EL_SP_PORT_RIGHT,
3681     EL_SP_PORT_DOWN,
3682     EL_SP_PORT_LEFT,
3683     EL_SP_PORT_UP,
3684     EL_SP_GRAVITY_PORT_RIGHT,
3685     EL_SP_GRAVITY_PORT_DOWN,
3686     EL_SP_GRAVITY_PORT_LEFT,
3687     EL_SP_GRAVITY_PORT_UP,
3688     EL_SP_SNIKSNAK,
3689     EL_SP_DISK_YELLOW,
3690     EL_SP_TERMINAL,
3691     EL_SP_DISK_RED,
3692     EL_SP_PORT_VERTICAL,
3693     EL_SP_PORT_HORIZONTAL,
3694     EL_SP_PORT_ANY,
3695     EL_SP_ELECTRON,
3696     EL_SP_BUGGY_BASE,
3697     EL_SP_CHIP_LEFT,
3698     EL_SP_CHIP_RIGHT,
3699     EL_SP_HARDWARE_BASE_1,
3700     EL_SP_HARDWARE_GREEN,
3701     EL_SP_HARDWARE_BLUE,
3702     EL_SP_HARDWARE_RED,
3703     EL_SP_HARDWARE_YELLOW,
3704     EL_SP_HARDWARE_BASE_2,
3705     EL_SP_HARDWARE_BASE_3,
3706     EL_SP_HARDWARE_BASE_4,
3707     EL_SP_HARDWARE_BASE_5,
3708     EL_SP_HARDWARE_BASE_6,
3709     EL_SP_CHIP_TOP,
3710     EL_SP_CHIP_BOTTOM,
3711
3712     /* additional elements that appeared in newer Supaplex levels */
3713     EL_INVISIBLE_WALL,
3714
3715     /* additional gravity port elements (not switching, but setting gravity) */
3716     EL_SP_GRAVITY_ON_PORT_LEFT,
3717     EL_SP_GRAVITY_ON_PORT_RIGHT,
3718     EL_SP_GRAVITY_ON_PORT_UP,
3719     EL_SP_GRAVITY_ON_PORT_DOWN,
3720     EL_SP_GRAVITY_OFF_PORT_LEFT,
3721     EL_SP_GRAVITY_OFF_PORT_RIGHT,
3722     EL_SP_GRAVITY_OFF_PORT_UP,
3723     EL_SP_GRAVITY_OFF_PORT_DOWN,
3724
3725     /* more than one Murphy in a level results in an inactive clone */
3726     EL_SP_MURPHY_CLONE,
3727
3728     /* runtime Supaplex elements */
3729     EL_SP_DISK_RED_ACTIVE,
3730     EL_SP_TERMINAL_ACTIVE,
3731     EL_SP_BUGGY_BASE_ACTIVATING,
3732     EL_SP_BUGGY_BASE_ACTIVE,
3733     EL_SP_EXIT_OPENING,
3734     EL_SP_EXIT_CLOSING,
3735
3736     -1
3737   };
3738
3739   static int ep_sb_element[] =
3740   {
3741     EL_EMPTY,
3742     EL_STEELWALL,
3743     EL_SOKOBAN_OBJECT,
3744     EL_SOKOBAN_FIELD_EMPTY,
3745     EL_SOKOBAN_FIELD_FULL,
3746     EL_SOKOBAN_FIELD_PLAYER,
3747     EL_PLAYER_1,
3748     EL_PLAYER_2,
3749     EL_PLAYER_3,
3750     EL_PLAYER_4,
3751     EL_INVISIBLE_STEELWALL,
3752
3753     -1
3754   };
3755
3756   static int ep_gem[] =
3757   {
3758     EL_BD_DIAMOND,
3759     EL_EMERALD,
3760     EL_EMERALD_YELLOW,
3761     EL_EMERALD_RED,
3762     EL_EMERALD_PURPLE,
3763     EL_DIAMOND,
3764
3765     -1
3766   };
3767
3768   static int ep_food_dark_yamyam[] =
3769   {
3770     EL_SAND,
3771     EL_BUG,
3772     EL_SPACESHIP,
3773     EL_BD_BUTTERFLY,
3774     EL_BD_FIREFLY,
3775     EL_YAMYAM,
3776     EL_ROBOT,
3777     EL_PACMAN,
3778     EL_AMOEBA_DROP,
3779     EL_AMOEBA_DEAD,
3780     EL_AMOEBA_WET,
3781     EL_AMOEBA_DRY,
3782     EL_AMOEBA_FULL,
3783     EL_BD_AMOEBA,
3784     EL_EMERALD,
3785     EL_BD_DIAMOND,
3786     EL_EMERALD_YELLOW,
3787     EL_EMERALD_RED,
3788     EL_EMERALD_PURPLE,
3789     EL_DIAMOND,
3790     EL_PEARL,
3791     EL_CRYSTAL,
3792
3793     -1
3794   };
3795
3796   static int ep_food_penguin[] =
3797   {
3798     EL_EMERALD,
3799     EL_BD_DIAMOND,
3800     EL_EMERALD_YELLOW,
3801     EL_EMERALD_RED,
3802     EL_EMERALD_PURPLE,
3803     EL_DIAMOND,
3804     EL_PEARL,
3805     EL_CRYSTAL,
3806
3807     -1
3808   };
3809
3810   static int ep_food_pig[] =
3811   {
3812     EL_EMERALD,
3813     EL_BD_DIAMOND,
3814     EL_EMERALD_YELLOW,
3815     EL_EMERALD_RED,
3816     EL_EMERALD_PURPLE,
3817     EL_DIAMOND,
3818
3819     -1
3820   };
3821
3822   static int ep_historic_wall[] =
3823   {
3824     EL_STEELWALL,
3825     EL_GATE_1,
3826     EL_GATE_2,
3827     EL_GATE_3,
3828     EL_GATE_4,
3829     EL_GATE_1_GRAY,
3830     EL_GATE_2_GRAY,
3831     EL_GATE_3_GRAY,
3832     EL_GATE_4_GRAY,
3833     EL_GATE_1_GRAY_ACTIVE,
3834     EL_GATE_2_GRAY_ACTIVE,
3835     EL_GATE_3_GRAY_ACTIVE,
3836     EL_GATE_4_GRAY_ACTIVE,
3837     EL_EM_GATE_1,
3838     EL_EM_GATE_2,
3839     EL_EM_GATE_3,
3840     EL_EM_GATE_4,
3841     EL_EM_GATE_1_GRAY,
3842     EL_EM_GATE_2_GRAY,
3843     EL_EM_GATE_3_GRAY,
3844     EL_EM_GATE_4_GRAY,
3845     EL_EM_GATE_1_GRAY_ACTIVE,
3846     EL_EM_GATE_2_GRAY_ACTIVE,
3847     EL_EM_GATE_3_GRAY_ACTIVE,
3848     EL_EM_GATE_4_GRAY_ACTIVE,
3849     EL_EXIT_CLOSED,
3850     EL_EXIT_OPENING,
3851     EL_EXIT_OPEN,
3852     EL_WALL,
3853     EL_WALL_SLIPPERY,
3854     EL_EXPANDABLE_WALL,
3855     EL_EXPANDABLE_WALL_HORIZONTAL,
3856     EL_EXPANDABLE_WALL_VERTICAL,
3857     EL_EXPANDABLE_WALL_ANY,
3858     EL_EXPANDABLE_WALL_GROWING,
3859     EL_BD_EXPANDABLE_WALL,
3860     EL_BD_WALL,
3861     EL_SP_CHIP_SINGLE,
3862     EL_SP_CHIP_LEFT,
3863     EL_SP_CHIP_RIGHT,
3864     EL_SP_CHIP_TOP,
3865     EL_SP_CHIP_BOTTOM,
3866     EL_SP_HARDWARE_GRAY,
3867     EL_SP_HARDWARE_GREEN,
3868     EL_SP_HARDWARE_BLUE,
3869     EL_SP_HARDWARE_RED,
3870     EL_SP_HARDWARE_YELLOW,
3871     EL_SP_HARDWARE_BASE_1,
3872     EL_SP_HARDWARE_BASE_2,
3873     EL_SP_HARDWARE_BASE_3,
3874     EL_SP_HARDWARE_BASE_4,
3875     EL_SP_HARDWARE_BASE_5,
3876     EL_SP_HARDWARE_BASE_6,
3877     EL_SP_TERMINAL,
3878     EL_SP_TERMINAL_ACTIVE,
3879     EL_SP_EXIT_CLOSED,
3880     EL_SP_EXIT_OPEN,
3881     EL_INVISIBLE_STEELWALL,
3882     EL_INVISIBLE_STEELWALL_ACTIVE,
3883     EL_INVISIBLE_WALL,
3884     EL_INVISIBLE_WALL_ACTIVE,
3885     EL_STEELWALL_SLIPPERY,
3886     EL_EMC_STEELWALL_1,
3887     EL_EMC_STEELWALL_2,
3888     EL_EMC_STEELWALL_3,
3889     EL_EMC_STEELWALL_4,
3890     EL_EMC_WALL_1,
3891     EL_EMC_WALL_2,
3892     EL_EMC_WALL_3,
3893     EL_EMC_WALL_4,
3894     EL_EMC_WALL_5,
3895     EL_EMC_WALL_6,
3896     EL_EMC_WALL_7,
3897     EL_EMC_WALL_8,
3898
3899     -1
3900   };
3901
3902   static int ep_historic_solid[] =
3903   {
3904     EL_WALL,
3905     EL_EXPANDABLE_WALL,
3906     EL_EXPANDABLE_WALL_HORIZONTAL,
3907     EL_EXPANDABLE_WALL_VERTICAL,
3908     EL_EXPANDABLE_WALL_ANY,
3909     EL_BD_EXPANDABLE_WALL,
3910     EL_BD_WALL,
3911     EL_WALL_SLIPPERY,
3912     EL_EXIT_CLOSED,
3913     EL_EXIT_OPENING,
3914     EL_EXIT_OPEN,
3915     EL_AMOEBA_DEAD,
3916     EL_AMOEBA_WET,
3917     EL_AMOEBA_DRY,
3918     EL_AMOEBA_FULL,
3919     EL_BD_AMOEBA,
3920     EL_QUICKSAND_EMPTY,
3921     EL_QUICKSAND_FULL,
3922     EL_QUICKSAND_FILLING,
3923     EL_QUICKSAND_EMPTYING,
3924     EL_MAGIC_WALL,
3925     EL_MAGIC_WALL_ACTIVE,
3926     EL_MAGIC_WALL_EMPTYING,
3927     EL_MAGIC_WALL_FILLING,
3928     EL_MAGIC_WALL_FULL,
3929     EL_MAGIC_WALL_DEAD,
3930     EL_BD_MAGIC_WALL,
3931     EL_BD_MAGIC_WALL_ACTIVE,
3932     EL_BD_MAGIC_WALL_EMPTYING,
3933     EL_BD_MAGIC_WALL_FULL,
3934     EL_BD_MAGIC_WALL_FILLING,
3935     EL_BD_MAGIC_WALL_DEAD,
3936     EL_GAME_OF_LIFE,
3937     EL_BIOMAZE,
3938     EL_SP_CHIP_SINGLE,
3939     EL_SP_CHIP_LEFT,
3940     EL_SP_CHIP_RIGHT,
3941     EL_SP_CHIP_TOP,
3942     EL_SP_CHIP_BOTTOM,
3943     EL_SP_TERMINAL,
3944     EL_SP_TERMINAL_ACTIVE,
3945     EL_SP_EXIT_CLOSED,
3946     EL_SP_EXIT_OPEN,
3947     EL_INVISIBLE_WALL,
3948     EL_INVISIBLE_WALL_ACTIVE,
3949     EL_SWITCHGATE_SWITCH_UP,
3950     EL_SWITCHGATE_SWITCH_DOWN,
3951     EL_DC_SWITCHGATE_SWITCH_UP,
3952     EL_DC_SWITCHGATE_SWITCH_DOWN,
3953     EL_TIMEGATE_SWITCH,
3954     EL_TIMEGATE_SWITCH_ACTIVE,
3955     EL_DC_TIMEGATE_SWITCH,
3956     EL_DC_TIMEGATE_SWITCH_ACTIVE,
3957     EL_EMC_WALL_1,
3958     EL_EMC_WALL_2,
3959     EL_EMC_WALL_3,
3960     EL_EMC_WALL_4,
3961     EL_EMC_WALL_5,
3962     EL_EMC_WALL_6,
3963     EL_EMC_WALL_7,
3964     EL_EMC_WALL_8,
3965     EL_WALL_PEARL,
3966     EL_WALL_CRYSTAL,
3967
3968     /* the following elements are a direct copy of "indestructible" elements,
3969        except "EL_ACID", which is "indestructible", but not "solid"! */
3970 #if 0
3971     EL_ACID,
3972 #endif
3973     EL_STEELWALL,
3974     EL_ACID_POOL_TOPLEFT,
3975     EL_ACID_POOL_TOPRIGHT,
3976     EL_ACID_POOL_BOTTOMLEFT,
3977     EL_ACID_POOL_BOTTOM,
3978     EL_ACID_POOL_BOTTOMRIGHT,
3979     EL_SP_HARDWARE_GRAY,
3980     EL_SP_HARDWARE_GREEN,
3981     EL_SP_HARDWARE_BLUE,
3982     EL_SP_HARDWARE_RED,
3983     EL_SP_HARDWARE_YELLOW,
3984     EL_SP_HARDWARE_BASE_1,
3985     EL_SP_HARDWARE_BASE_2,
3986     EL_SP_HARDWARE_BASE_3,
3987     EL_SP_HARDWARE_BASE_4,
3988     EL_SP_HARDWARE_BASE_5,
3989     EL_SP_HARDWARE_BASE_6,
3990     EL_INVISIBLE_STEELWALL,
3991     EL_INVISIBLE_STEELWALL_ACTIVE,
3992     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3993     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3994     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3995     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3996     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3997     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3998     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3999     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
4000     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
4001     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
4002     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
4003     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
4004     EL_LIGHT_SWITCH,
4005     EL_LIGHT_SWITCH_ACTIVE,
4006     EL_SIGN_EXCLAMATION,
4007     EL_SIGN_RADIOACTIVITY,
4008     EL_SIGN_STOP,
4009     EL_SIGN_WHEELCHAIR,
4010     EL_SIGN_PARKING,
4011     EL_SIGN_NO_ENTRY,
4012     EL_SIGN_UNUSED_1,
4013     EL_SIGN_GIVE_WAY,
4014     EL_SIGN_ENTRY_FORBIDDEN,
4015     EL_SIGN_EMERGENCY_EXIT,
4016     EL_SIGN_YIN_YANG,
4017     EL_SIGN_UNUSED_2,
4018     EL_SIGN_SPERMS,
4019     EL_SIGN_BULLET,
4020     EL_SIGN_HEART,
4021     EL_SIGN_CROSS,
4022     EL_SIGN_FRANKIE,
4023     EL_STEEL_EXIT_CLOSED,
4024     EL_STEEL_EXIT_OPEN,
4025     EL_DC_STEELWALL_1_LEFT,
4026     EL_DC_STEELWALL_1_RIGHT,
4027     EL_DC_STEELWALL_1_TOP,
4028     EL_DC_STEELWALL_1_BOTTOM,
4029     EL_DC_STEELWALL_1_HORIZONTAL,
4030     EL_DC_STEELWALL_1_VERTICAL,
4031     EL_DC_STEELWALL_1_TOPLEFT,
4032     EL_DC_STEELWALL_1_TOPRIGHT,
4033     EL_DC_STEELWALL_1_BOTTOMLEFT,
4034     EL_DC_STEELWALL_1_BOTTOMRIGHT,
4035     EL_DC_STEELWALL_1_TOPLEFT_2,
4036     EL_DC_STEELWALL_1_TOPRIGHT_2,
4037     EL_DC_STEELWALL_1_BOTTOMLEFT_2,
4038     EL_DC_STEELWALL_1_BOTTOMRIGHT_2,
4039     EL_DC_STEELWALL_2_LEFT,
4040     EL_DC_STEELWALL_2_RIGHT,
4041     EL_DC_STEELWALL_2_TOP,
4042     EL_DC_STEELWALL_2_BOTTOM,
4043     EL_DC_STEELWALL_2_HORIZONTAL,
4044     EL_DC_STEELWALL_2_VERTICAL,
4045     EL_DC_STEELWALL_2_MIDDLE,
4046     EL_DC_STEELWALL_2_SINGLE,
4047     EL_STEELWALL_SLIPPERY,
4048     EL_EMC_STEELWALL_1,
4049     EL_EMC_STEELWALL_2,
4050     EL_EMC_STEELWALL_3,
4051     EL_EMC_STEELWALL_4,
4052     EL_CRYSTAL,
4053     EL_GATE_1,
4054     EL_GATE_2,
4055     EL_GATE_3,
4056     EL_GATE_4,
4057     EL_GATE_1_GRAY,
4058     EL_GATE_2_GRAY,
4059     EL_GATE_3_GRAY,
4060     EL_GATE_4_GRAY,
4061     EL_GATE_1_GRAY_ACTIVE,
4062     EL_GATE_2_GRAY_ACTIVE,
4063     EL_GATE_3_GRAY_ACTIVE,
4064     EL_GATE_4_GRAY_ACTIVE,
4065     EL_EM_GATE_1,
4066     EL_EM_GATE_2,
4067     EL_EM_GATE_3,
4068     EL_EM_GATE_4,
4069     EL_EM_GATE_1_GRAY,
4070     EL_EM_GATE_2_GRAY,
4071     EL_EM_GATE_3_GRAY,
4072     EL_EM_GATE_4_GRAY,
4073     EL_EM_GATE_1_GRAY_ACTIVE,
4074     EL_EM_GATE_2_GRAY_ACTIVE,
4075     EL_EM_GATE_3_GRAY_ACTIVE,
4076     EL_EM_GATE_4_GRAY_ACTIVE,
4077     EL_SWITCHGATE_OPEN,
4078     EL_SWITCHGATE_OPENING,
4079     EL_SWITCHGATE_CLOSED,
4080     EL_SWITCHGATE_CLOSING,
4081     EL_TIMEGATE_OPEN,
4082     EL_TIMEGATE_OPENING,
4083     EL_TIMEGATE_CLOSED,
4084     EL_TIMEGATE_CLOSING,
4085     EL_TUBE_ANY,
4086     EL_TUBE_VERTICAL,
4087     EL_TUBE_HORIZONTAL,
4088     EL_TUBE_VERTICAL_LEFT,
4089     EL_TUBE_VERTICAL_RIGHT,
4090     EL_TUBE_HORIZONTAL_UP,
4091     EL_TUBE_HORIZONTAL_DOWN,
4092     EL_TUBE_LEFT_UP,
4093     EL_TUBE_LEFT_DOWN,
4094     EL_TUBE_RIGHT_UP,
4095     EL_TUBE_RIGHT_DOWN,
4096
4097     -1
4098   };
4099
4100   static int ep_classic_enemy[] =
4101   {
4102     EL_BUG,
4103     EL_SPACESHIP,
4104     EL_BD_BUTTERFLY,
4105     EL_BD_FIREFLY,
4106
4107     EL_YAMYAM,
4108     EL_DARK_YAMYAM,
4109     EL_ROBOT,
4110     EL_PACMAN,
4111     EL_SP_SNIKSNAK,
4112     EL_SP_ELECTRON,
4113
4114     -1
4115   };
4116
4117   static int ep_belt[] =
4118   {
4119     EL_CONVEYOR_BELT_1_LEFT,
4120     EL_CONVEYOR_BELT_1_MIDDLE,
4121     EL_CONVEYOR_BELT_1_RIGHT,
4122     EL_CONVEYOR_BELT_2_LEFT,
4123     EL_CONVEYOR_BELT_2_MIDDLE,
4124     EL_CONVEYOR_BELT_2_RIGHT,
4125     EL_CONVEYOR_BELT_3_LEFT,
4126     EL_CONVEYOR_BELT_3_MIDDLE,
4127     EL_CONVEYOR_BELT_3_RIGHT,
4128     EL_CONVEYOR_BELT_4_LEFT,
4129     EL_CONVEYOR_BELT_4_MIDDLE,
4130     EL_CONVEYOR_BELT_4_RIGHT,
4131
4132     -1
4133   };
4134
4135   static int ep_belt_active[] =
4136   {
4137     EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
4138     EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE,
4139     EL_CONVEYOR_BELT_1_RIGHT_ACTIVE,
4140     EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
4141     EL_CONVEYOR_BELT_2_MIDDLE_ACTIVE,
4142     EL_CONVEYOR_BELT_2_RIGHT_ACTIVE,
4143     EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
4144     EL_CONVEYOR_BELT_3_MIDDLE_ACTIVE,
4145     EL_CONVEYOR_BELT_3_RIGHT_ACTIVE,
4146     EL_CONVEYOR_BELT_4_LEFT_ACTIVE,
4147     EL_CONVEYOR_BELT_4_MIDDLE_ACTIVE,
4148     EL_CONVEYOR_BELT_4_RIGHT_ACTIVE,
4149
4150     -1
4151   };
4152
4153   static int ep_belt_switch[] =
4154   {
4155     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
4156     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
4157     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
4158     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
4159     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
4160     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
4161     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
4162     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
4163     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
4164     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
4165     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
4166     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
4167
4168     -1
4169   };
4170
4171   static int ep_tube[] =
4172   {
4173     EL_TUBE_LEFT_UP,
4174     EL_TUBE_LEFT_DOWN,
4175     EL_TUBE_RIGHT_UP,
4176     EL_TUBE_RIGHT_DOWN,
4177     EL_TUBE_HORIZONTAL,
4178     EL_TUBE_HORIZONTAL_UP,
4179     EL_TUBE_HORIZONTAL_DOWN,
4180     EL_TUBE_VERTICAL,
4181     EL_TUBE_VERTICAL_LEFT,
4182     EL_TUBE_VERTICAL_RIGHT,
4183     EL_TUBE_ANY,
4184
4185     -1
4186   };
4187
4188   static int ep_acid_pool[] =
4189   {
4190     EL_ACID_POOL_TOPLEFT,
4191     EL_ACID_POOL_TOPRIGHT,
4192     EL_ACID_POOL_BOTTOMLEFT,
4193     EL_ACID_POOL_BOTTOM,
4194     EL_ACID_POOL_BOTTOMRIGHT,
4195
4196     -1
4197   };
4198
4199   static int ep_keygate[] =
4200   {
4201     EL_GATE_1,
4202     EL_GATE_2,
4203     EL_GATE_3,
4204     EL_GATE_4,
4205     EL_GATE_1_GRAY,
4206     EL_GATE_2_GRAY,
4207     EL_GATE_3_GRAY,
4208     EL_GATE_4_GRAY,
4209     EL_GATE_1_GRAY_ACTIVE,
4210     EL_GATE_2_GRAY_ACTIVE,
4211     EL_GATE_3_GRAY_ACTIVE,
4212     EL_GATE_4_GRAY_ACTIVE,
4213     EL_EM_GATE_1,
4214     EL_EM_GATE_2,
4215     EL_EM_GATE_3,
4216     EL_EM_GATE_4,
4217     EL_EM_GATE_1_GRAY,
4218     EL_EM_GATE_2_GRAY,
4219     EL_EM_GATE_3_GRAY,
4220     EL_EM_GATE_4_GRAY,
4221     EL_EM_GATE_1_GRAY_ACTIVE,
4222     EL_EM_GATE_2_GRAY_ACTIVE,
4223     EL_EM_GATE_3_GRAY_ACTIVE,
4224     EL_EM_GATE_4_GRAY_ACTIVE,
4225     EL_EMC_GATE_5,
4226     EL_EMC_GATE_6,
4227     EL_EMC_GATE_7,
4228     EL_EMC_GATE_8,
4229     EL_EMC_GATE_5_GRAY,
4230     EL_EMC_GATE_6_GRAY,
4231     EL_EMC_GATE_7_GRAY,
4232     EL_EMC_GATE_8_GRAY,
4233     EL_EMC_GATE_5_GRAY_ACTIVE,
4234     EL_EMC_GATE_6_GRAY_ACTIVE,
4235     EL_EMC_GATE_7_GRAY_ACTIVE,
4236     EL_EMC_GATE_8_GRAY_ACTIVE,
4237     EL_DC_GATE_WHITE,
4238     EL_DC_GATE_WHITE_GRAY,
4239     EL_DC_GATE_WHITE_GRAY_ACTIVE,
4240
4241     -1
4242   };
4243
4244   static int ep_amoeboid[] =
4245   {
4246     EL_AMOEBA_DEAD,
4247     EL_AMOEBA_WET,
4248     EL_AMOEBA_DRY,
4249     EL_AMOEBA_FULL,
4250     EL_BD_AMOEBA,
4251     EL_EMC_DRIPPER,
4252
4253     -1
4254   };
4255
4256   static int ep_amoebalive[] =
4257   {
4258     EL_AMOEBA_WET,
4259     EL_AMOEBA_DRY,
4260     EL_AMOEBA_FULL,
4261     EL_BD_AMOEBA,
4262     EL_EMC_DRIPPER,
4263
4264     -1
4265   };
4266
4267   static int ep_has_editor_content[] =
4268   {
4269     EL_PLAYER_1,
4270     EL_PLAYER_2,
4271     EL_PLAYER_3,
4272     EL_PLAYER_4,
4273     EL_SOKOBAN_FIELD_PLAYER,
4274     EL_SP_MURPHY,
4275     EL_YAMYAM,
4276     EL_YAMYAM_LEFT,
4277     EL_YAMYAM_RIGHT,
4278     EL_YAMYAM_UP,
4279     EL_YAMYAM_DOWN,
4280     EL_AMOEBA_WET,
4281     EL_AMOEBA_DRY,
4282     EL_AMOEBA_FULL,
4283     EL_BD_AMOEBA,
4284     EL_EMC_MAGIC_BALL,
4285     EL_EMC_ANDROID,
4286
4287     -1
4288   };
4289
4290   static int ep_can_turn_each_move[] =
4291   {
4292     /* !!! do something with this one !!! */
4293     -1
4294   };
4295
4296   static int ep_can_grow[] =
4297   {
4298     EL_BD_AMOEBA,
4299     EL_AMOEBA_DROP,
4300     EL_AMOEBA_WET,
4301     EL_AMOEBA_DRY,
4302     EL_AMOEBA_FULL,
4303     EL_GAME_OF_LIFE,
4304     EL_BIOMAZE,
4305     EL_EMC_DRIPPER,
4306
4307     -1
4308   };
4309
4310   static int ep_active_bomb[] =
4311   {
4312     EL_DYNAMITE_ACTIVE,
4313     EL_EM_DYNAMITE_ACTIVE,
4314     EL_DYNABOMB_PLAYER_1_ACTIVE,
4315     EL_DYNABOMB_PLAYER_2_ACTIVE,
4316     EL_DYNABOMB_PLAYER_3_ACTIVE,
4317     EL_DYNABOMB_PLAYER_4_ACTIVE,
4318     EL_SP_DISK_RED_ACTIVE,
4319
4320     -1
4321   };
4322
4323   static int ep_inactive[] =
4324   {
4325     EL_EMPTY,
4326     EL_SAND,
4327     EL_WALL,
4328     EL_BD_WALL,
4329     EL_WALL_SLIPPERY,
4330     EL_STEELWALL,
4331     EL_AMOEBA_DEAD,
4332     EL_QUICKSAND_EMPTY,
4333     EL_QUICKSAND_FAST_EMPTY,
4334     EL_STONEBLOCK,
4335     EL_ROBOT_WHEEL,
4336     EL_KEY_1,
4337     EL_KEY_2,
4338     EL_KEY_3,
4339     EL_KEY_4,
4340     EL_EM_KEY_1,
4341     EL_EM_KEY_2,
4342     EL_EM_KEY_3,
4343     EL_EM_KEY_4,
4344     EL_EMC_KEY_5,
4345     EL_EMC_KEY_6,
4346     EL_EMC_KEY_7,
4347     EL_EMC_KEY_8,
4348     EL_GATE_1,
4349     EL_GATE_2,
4350     EL_GATE_3,
4351     EL_GATE_4,
4352     EL_GATE_1_GRAY,
4353     EL_GATE_2_GRAY,
4354     EL_GATE_3_GRAY,
4355     EL_GATE_4_GRAY,
4356     EL_GATE_1_GRAY_ACTIVE,
4357     EL_GATE_2_GRAY_ACTIVE,
4358     EL_GATE_3_GRAY_ACTIVE,
4359     EL_GATE_4_GRAY_ACTIVE,
4360     EL_EM_GATE_1,
4361     EL_EM_GATE_2,
4362     EL_EM_GATE_3,
4363     EL_EM_GATE_4,
4364     EL_EM_GATE_1_GRAY,
4365     EL_EM_GATE_2_GRAY,
4366     EL_EM_GATE_3_GRAY,
4367     EL_EM_GATE_4_GRAY,
4368     EL_EM_GATE_1_GRAY_ACTIVE,
4369     EL_EM_GATE_2_GRAY_ACTIVE,
4370     EL_EM_GATE_3_GRAY_ACTIVE,
4371     EL_EM_GATE_4_GRAY_ACTIVE,
4372     EL_EMC_GATE_5,
4373     EL_EMC_GATE_6,
4374     EL_EMC_GATE_7,
4375     EL_EMC_GATE_8,
4376     EL_EMC_GATE_5_GRAY,
4377     EL_EMC_GATE_6_GRAY,
4378     EL_EMC_GATE_7_GRAY,
4379     EL_EMC_GATE_8_GRAY,
4380     EL_EMC_GATE_5_GRAY_ACTIVE,
4381     EL_EMC_GATE_6_GRAY_ACTIVE,
4382     EL_EMC_GATE_7_GRAY_ACTIVE,
4383     EL_EMC_GATE_8_GRAY_ACTIVE,
4384     EL_DC_GATE_WHITE,
4385     EL_DC_GATE_WHITE_GRAY,
4386     EL_DC_GATE_WHITE_GRAY_ACTIVE,
4387     EL_DC_GATE_FAKE_GRAY,
4388     EL_DYNAMITE,
4389     EL_EM_DYNAMITE,
4390     EL_INVISIBLE_STEELWALL,
4391     EL_INVISIBLE_WALL,
4392     EL_INVISIBLE_SAND,
4393     EL_LAMP,
4394     EL_LAMP_ACTIVE,
4395     EL_WALL_EMERALD,
4396     EL_WALL_DIAMOND,
4397     EL_WALL_BD_DIAMOND,
4398     EL_WALL_EMERALD_YELLOW,
4399     EL_DYNABOMB_INCREASE_NUMBER,
4400     EL_DYNABOMB_INCREASE_SIZE,
4401     EL_DYNABOMB_INCREASE_POWER,
4402 #if 0
4403     EL_SOKOBAN_OBJECT,
4404 #endif
4405     EL_SOKOBAN_FIELD_EMPTY,
4406     EL_SOKOBAN_FIELD_FULL,
4407     EL_WALL_EMERALD_RED,
4408     EL_WALL_EMERALD_PURPLE,
4409     EL_ACID_POOL_TOPLEFT,
4410     EL_ACID_POOL_TOPRIGHT,
4411     EL_ACID_POOL_BOTTOMLEFT,
4412     EL_ACID_POOL_BOTTOM,
4413     EL_ACID_POOL_BOTTOMRIGHT,
4414     EL_MAGIC_WALL,
4415     EL_MAGIC_WALL_DEAD,
4416     EL_BD_MAGIC_WALL,
4417     EL_BD_MAGIC_WALL_DEAD,
4418     EL_DC_MAGIC_WALL,
4419     EL_DC_MAGIC_WALL_DEAD,
4420     EL_AMOEBA_TO_DIAMOND,
4421     EL_BLOCKED,
4422     EL_SP_EMPTY,
4423     EL_SP_BASE,
4424     EL_SP_PORT_RIGHT,
4425     EL_SP_PORT_DOWN,
4426     EL_SP_PORT_LEFT,
4427     EL_SP_PORT_UP,
4428     EL_SP_GRAVITY_PORT_RIGHT,
4429     EL_SP_GRAVITY_PORT_DOWN,
4430     EL_SP_GRAVITY_PORT_LEFT,
4431     EL_SP_GRAVITY_PORT_UP,
4432     EL_SP_PORT_HORIZONTAL,
4433     EL_SP_PORT_VERTICAL,
4434     EL_SP_PORT_ANY,
4435     EL_SP_DISK_RED,
4436 #if 0
4437     EL_SP_DISK_YELLOW,
4438 #endif
4439     EL_SP_CHIP_SINGLE,
4440     EL_SP_CHIP_LEFT,
4441     EL_SP_CHIP_RIGHT,
4442     EL_SP_CHIP_TOP,
4443     EL_SP_CHIP_BOTTOM,
4444     EL_SP_HARDWARE_GRAY,
4445     EL_SP_HARDWARE_GREEN,
4446     EL_SP_HARDWARE_BLUE,
4447     EL_SP_HARDWARE_RED,
4448     EL_SP_HARDWARE_YELLOW,
4449     EL_SP_HARDWARE_BASE_1,
4450     EL_SP_HARDWARE_BASE_2,
4451     EL_SP_HARDWARE_BASE_3,
4452     EL_SP_HARDWARE_BASE_4,
4453     EL_SP_HARDWARE_BASE_5,
4454     EL_SP_HARDWARE_BASE_6,
4455     EL_SP_GRAVITY_ON_PORT_LEFT,
4456     EL_SP_GRAVITY_ON_PORT_RIGHT,
4457     EL_SP_GRAVITY_ON_PORT_UP,
4458     EL_SP_GRAVITY_ON_PORT_DOWN,
4459     EL_SP_GRAVITY_OFF_PORT_LEFT,
4460     EL_SP_GRAVITY_OFF_PORT_RIGHT,
4461     EL_SP_GRAVITY_OFF_PORT_UP,
4462     EL_SP_GRAVITY_OFF_PORT_DOWN,
4463     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
4464     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
4465     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
4466     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
4467     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
4468     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
4469     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
4470     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
4471     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
4472     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
4473     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
4474     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
4475     EL_SIGN_EXCLAMATION,
4476     EL_SIGN_RADIOACTIVITY,
4477     EL_SIGN_STOP,
4478     EL_SIGN_WHEELCHAIR,
4479     EL_SIGN_PARKING,
4480     EL_SIGN_NO_ENTRY,
4481     EL_SIGN_UNUSED_1,
4482     EL_SIGN_GIVE_WAY,
4483     EL_SIGN_ENTRY_FORBIDDEN,
4484     EL_SIGN_EMERGENCY_EXIT,
4485     EL_SIGN_YIN_YANG,
4486     EL_SIGN_UNUSED_2,
4487     EL_SIGN_SPERMS,
4488     EL_SIGN_BULLET,
4489     EL_SIGN_HEART,
4490     EL_SIGN_CROSS,
4491     EL_SIGN_FRANKIE,
4492     EL_DC_STEELWALL_1_LEFT,
4493     EL_DC_STEELWALL_1_RIGHT,
4494     EL_DC_STEELWALL_1_TOP,
4495     EL_DC_STEELWALL_1_BOTTOM,
4496     EL_DC_STEELWALL_1_HORIZONTAL,
4497     EL_DC_STEELWALL_1_VERTICAL,
4498     EL_DC_STEELWALL_1_TOPLEFT,
4499     EL_DC_STEELWALL_1_TOPRIGHT,
4500     EL_DC_STEELWALL_1_BOTTOMLEFT,
4501     EL_DC_STEELWALL_1_BOTTOMRIGHT,
4502     EL_DC_STEELWALL_1_TOPLEFT_2,
4503     EL_DC_STEELWALL_1_TOPRIGHT_2,
4504     EL_DC_STEELWALL_1_BOTTOMLEFT_2,
4505     EL_DC_STEELWALL_1_BOTTOMRIGHT_2,
4506     EL_DC_STEELWALL_2_LEFT,
4507     EL_DC_STEELWALL_2_RIGHT,
4508     EL_DC_STEELWALL_2_TOP,
4509     EL_DC_STEELWALL_2_BOTTOM,
4510     EL_DC_STEELWALL_2_HORIZONTAL,
4511     EL_DC_STEELWALL_2_VERTICAL,
4512     EL_DC_STEELWALL_2_MIDDLE,
4513     EL_DC_STEELWALL_2_SINGLE,
4514     EL_STEELWALL_SLIPPERY,
4515     EL_EMC_STEELWALL_1,
4516     EL_EMC_STEELWALL_2,
4517     EL_EMC_STEELWALL_3,
4518     EL_EMC_STEELWALL_4,
4519     EL_EMC_WALL_SLIPPERY_1,
4520     EL_EMC_WALL_SLIPPERY_2,
4521     EL_EMC_WALL_SLIPPERY_3,
4522     EL_EMC_WALL_SLIPPERY_4,
4523     EL_EMC_WALL_1,
4524     EL_EMC_WALL_2,
4525     EL_EMC_WALL_3,
4526     EL_EMC_WALL_4,
4527     EL_EMC_WALL_5,
4528     EL_EMC_WALL_6,
4529     EL_EMC_WALL_7,
4530     EL_EMC_WALL_8,
4531     EL_EMC_WALL_9,
4532     EL_EMC_WALL_10,
4533     EL_EMC_WALL_11,
4534     EL_EMC_WALL_12,
4535     EL_EMC_WALL_13,
4536     EL_EMC_WALL_14,
4537     EL_EMC_WALL_15,
4538     EL_EMC_WALL_16,
4539
4540     -1
4541   };
4542
4543   static int ep_em_slippery_wall[] =
4544   {
4545     -1
4546   };
4547
4548   static int ep_gfx_crumbled[] =
4549   {
4550     EL_SAND,
4551     EL_LANDMINE,
4552     EL_DC_LANDMINE,
4553     EL_TRAP,
4554     EL_TRAP_ACTIVE,
4555
4556     -1
4557   };
4558
4559   static int ep_editor_cascade_active[] =
4560   {
4561     EL_INTERNAL_CASCADE_BD_ACTIVE,
4562     EL_INTERNAL_CASCADE_EM_ACTIVE,
4563     EL_INTERNAL_CASCADE_EMC_ACTIVE,
4564     EL_INTERNAL_CASCADE_RND_ACTIVE,
4565     EL_INTERNAL_CASCADE_SB_ACTIVE,
4566     EL_INTERNAL_CASCADE_SP_ACTIVE,
4567     EL_INTERNAL_CASCADE_DC_ACTIVE,
4568     EL_INTERNAL_CASCADE_DX_ACTIVE,
4569     EL_INTERNAL_CASCADE_CHARS_ACTIVE,
4570     EL_INTERNAL_CASCADE_STEEL_CHARS_ACTIVE,
4571     EL_INTERNAL_CASCADE_CE_ACTIVE,
4572     EL_INTERNAL_CASCADE_GE_ACTIVE,
4573     EL_INTERNAL_CASCADE_REF_ACTIVE,
4574     EL_INTERNAL_CASCADE_USER_ACTIVE,
4575     EL_INTERNAL_CASCADE_DYNAMIC_ACTIVE,
4576
4577     -1
4578   };
4579
4580   static int ep_editor_cascade_inactive[] =
4581   {
4582     EL_INTERNAL_CASCADE_BD,
4583     EL_INTERNAL_CASCADE_EM,
4584     EL_INTERNAL_CASCADE_EMC,
4585     EL_INTERNAL_CASCADE_RND,
4586     EL_INTERNAL_CASCADE_SB,
4587     EL_INTERNAL_CASCADE_SP,
4588     EL_INTERNAL_CASCADE_DC,
4589     EL_INTERNAL_CASCADE_DX,
4590     EL_INTERNAL_CASCADE_CHARS,
4591     EL_INTERNAL_CASCADE_STEEL_CHARS,
4592     EL_INTERNAL_CASCADE_CE,
4593     EL_INTERNAL_CASCADE_GE,
4594     EL_INTERNAL_CASCADE_REF,
4595     EL_INTERNAL_CASCADE_USER,
4596     EL_INTERNAL_CASCADE_DYNAMIC,
4597
4598     -1
4599   };
4600
4601   static int ep_obsolete[] =
4602   {
4603     EL_PLAYER_OBSOLETE,
4604     EL_KEY_OBSOLETE,
4605     EL_EM_KEY_1_FILE_OBSOLETE,
4606     EL_EM_KEY_2_FILE_OBSOLETE,
4607     EL_EM_KEY_3_FILE_OBSOLETE,
4608     EL_EM_KEY_4_FILE_OBSOLETE,
4609     EL_ENVELOPE_OBSOLETE,
4610
4611     -1
4612   };
4613
4614   static struct
4615   {
4616     int *elements;
4617     int property;
4618   } element_properties[] =
4619   {
4620     { ep_diggable,                      EP_DIGGABLE                     },
4621     { ep_collectible_only,              EP_COLLECTIBLE_ONLY             },
4622     { ep_dont_run_into,                 EP_DONT_RUN_INTO                },
4623     { ep_dont_collide_with,             EP_DONT_COLLIDE_WITH            },
4624     { ep_dont_touch,                    EP_DONT_TOUCH                   },
4625     { ep_indestructible,                EP_INDESTRUCTIBLE               },
4626     { ep_slippery,                      EP_SLIPPERY                     },
4627     { ep_can_change,                    EP_CAN_CHANGE                   },
4628     { ep_can_move,                      EP_CAN_MOVE                     },
4629     { ep_can_fall,                      EP_CAN_FALL                     },
4630     { ep_can_smash_player,              EP_CAN_SMASH_PLAYER             },
4631     { ep_can_smash_enemies,             EP_CAN_SMASH_ENEMIES            },
4632     { ep_can_smash_everything,          EP_CAN_SMASH_EVERYTHING         },
4633     { ep_explodes_by_fire,              EP_EXPLODES_BY_FIRE             },
4634     { ep_explodes_smashed,              EP_EXPLODES_SMASHED             },
4635     { ep_explodes_impact,               EP_EXPLODES_IMPACT              },
4636     { ep_walkable_over,                 EP_WALKABLE_OVER                },
4637     { ep_walkable_inside,               EP_WALKABLE_INSIDE              },
4638     { ep_walkable_under,                EP_WALKABLE_UNDER               },
4639     { ep_passable_over,                 EP_PASSABLE_OVER                },
4640     { ep_passable_inside,               EP_PASSABLE_INSIDE              },
4641     { ep_passable_under,                EP_PASSABLE_UNDER               },
4642     { ep_droppable,                     EP_DROPPABLE                    },
4643     { ep_explodes_1x1_old,              EP_EXPLODES_1X1_OLD             },
4644     { ep_pushable,                      EP_PUSHABLE                     },
4645     { ep_explodes_cross_old,            EP_EXPLODES_CROSS_OLD           },
4646     { ep_protected,                     EP_PROTECTED                    },
4647     { ep_throwable,                     EP_THROWABLE                    },
4648     { ep_can_explode,                   EP_CAN_EXPLODE                  },
4649     { ep_gravity_reachable,             EP_GRAVITY_REACHABLE            },
4650
4651     { ep_player,                        EP_PLAYER                       },
4652     { ep_can_pass_magic_wall,           EP_CAN_PASS_MAGIC_WALL          },
4653     { ep_can_pass_dc_magic_wall,        EP_CAN_PASS_DC_MAGIC_WALL       },
4654     { ep_switchable,                    EP_SWITCHABLE                   },
4655     { ep_bd_element,                    EP_BD_ELEMENT                   },
4656     { ep_sp_element,                    EP_SP_ELEMENT                   },
4657     { ep_sb_element,                    EP_SB_ELEMENT                   },
4658     { ep_gem,                           EP_GEM                          },
4659     { ep_food_dark_yamyam,              EP_FOOD_DARK_YAMYAM             },
4660     { ep_food_penguin,                  EP_FOOD_PENGUIN                 },
4661     { ep_food_pig,                      EP_FOOD_PIG                     },
4662     { ep_historic_wall,                 EP_HISTORIC_WALL                },
4663     { ep_historic_solid,                EP_HISTORIC_SOLID               },
4664     { ep_classic_enemy,                 EP_CLASSIC_ENEMY                },
4665     { ep_belt,                          EP_BELT                         },
4666     { ep_belt_active,                   EP_BELT_ACTIVE                  },
4667     { ep_belt_switch,                   EP_BELT_SWITCH                  },
4668     { ep_tube,                          EP_TUBE                         },
4669     { ep_acid_pool,                     EP_ACID_POOL                    },
4670     { ep_keygate,                       EP_KEYGATE                      },
4671     { ep_amoeboid,                      EP_AMOEBOID                     },
4672     { ep_amoebalive,                    EP_AMOEBALIVE                   },
4673     { ep_has_editor_content,            EP_HAS_EDITOR_CONTENT           },
4674     { ep_can_turn_each_move,            EP_CAN_TURN_EACH_MOVE           },
4675     { ep_can_grow,                      EP_CAN_GROW                     },
4676     { ep_active_bomb,                   EP_ACTIVE_BOMB                  },
4677     { ep_inactive,                      EP_INACTIVE                     },
4678
4679     { ep_em_slippery_wall,              EP_EM_SLIPPERY_WALL             },
4680
4681     { ep_gfx_crumbled,                  EP_GFX_CRUMBLED                 },
4682
4683     { ep_editor_cascade_active,         EP_EDITOR_CASCADE_ACTIVE        },
4684     { ep_editor_cascade_inactive,       EP_EDITOR_CASCADE_INACTIVE      },
4685
4686     { ep_obsolete,                      EP_OBSOLETE                     },
4687
4688     { NULL,                             -1                              }
4689   };
4690
4691   int i, j, k;
4692
4693   /* always start with reliable default values (element has no properties) */
4694   /* (but never initialize clipboard elements after the very first time) */
4695   /* (to be able to use clipboard elements between several levels) */
4696   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4697     if (!IS_CLIPBOARD_ELEMENT(i) || !clipboard_elements_initialized)
4698       for (j = 0; j < NUM_ELEMENT_PROPERTIES; j++)
4699         SET_PROPERTY(i, j, FALSE);
4700
4701   /* set all base element properties from above array definitions */
4702   for (i = 0; element_properties[i].elements != NULL; i++)
4703     for (j = 0; (element_properties[i].elements)[j] != -1; j++)
4704       SET_PROPERTY((element_properties[i].elements)[j],
4705                    element_properties[i].property, TRUE);
4706
4707   /* copy properties to some elements that are only stored in level file */
4708   for (i = 0; i < NUM_ELEMENT_PROPERTIES; i++)
4709     for (j = 0; copy_properties[j][0] != -1; j++)
4710       if (HAS_PROPERTY(copy_properties[j][0], i))
4711         for (k = 1; k <= 4; k++)
4712           SET_PROPERTY(copy_properties[j][k], i, TRUE);
4713
4714   /* set static element properties that are not listed in array definitions */
4715   for (i = EL_STEEL_CHAR_START; i <= EL_STEEL_CHAR_END; i++)
4716     SET_PROPERTY(i, EP_INDESTRUCTIBLE, TRUE);
4717
4718   clipboard_elements_initialized = TRUE;
4719 }
4720
4721 void InitElementPropertiesEngine(int engine_version)
4722 {
4723   static int no_wall_properties[] =
4724   {
4725     EP_DIGGABLE,
4726     EP_COLLECTIBLE_ONLY,
4727     EP_DONT_RUN_INTO,
4728     EP_DONT_COLLIDE_WITH,
4729     EP_CAN_MOVE,
4730     EP_CAN_FALL,
4731     EP_CAN_SMASH_PLAYER,
4732     EP_CAN_SMASH_ENEMIES,
4733     EP_CAN_SMASH_EVERYTHING,
4734     EP_PUSHABLE,
4735
4736     EP_PLAYER,
4737     EP_GEM,
4738     EP_FOOD_DARK_YAMYAM,
4739     EP_FOOD_PENGUIN,
4740     EP_BELT,
4741     EP_BELT_ACTIVE,
4742     EP_TUBE,
4743     EP_AMOEBOID,
4744     EP_AMOEBALIVE,
4745     EP_ACTIVE_BOMB,
4746
4747     EP_ACCESSIBLE,
4748
4749     -1
4750   };
4751
4752   int i, j;
4753
4754   /* important: after initialization in InitElementPropertiesStatic(), the
4755      elements are not again initialized to a default value; therefore all
4756      changes have to make sure that they leave the element with a defined
4757      property (which means that conditional property changes must be set to
4758      a reliable default value before) */
4759
4760   /* resolve group elements */
4761   for (i = 0; i < NUM_GROUP_ELEMENTS; i++)
4762     ResolveGroupElement(EL_GROUP_START + i);
4763
4764   /* set all special, combined or engine dependent element properties */
4765   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4766   {
4767     /* do not change (already initialized) clipboard elements here */
4768     if (IS_CLIPBOARD_ELEMENT(i))
4769       continue;
4770
4771     /* ---------- INACTIVE ------------------------------------------------- */
4772     SET_PROPERTY(i, EP_INACTIVE, ((i >= EL_CHAR_START &&
4773                                    i <= EL_CHAR_END) ||
4774                                   (i >= EL_STEEL_CHAR_START &&
4775                                    i <= EL_STEEL_CHAR_END)));
4776
4777     /* ---------- WALKABLE, PASSABLE, ACCESSIBLE --------------------------- */
4778     SET_PROPERTY(i, EP_WALKABLE, (IS_WALKABLE_OVER(i) ||
4779                                   IS_WALKABLE_INSIDE(i) ||
4780                                   IS_WALKABLE_UNDER(i)));
4781
4782     SET_PROPERTY(i, EP_PASSABLE, (IS_PASSABLE_OVER(i) ||
4783                                   IS_PASSABLE_INSIDE(i) ||
4784                                   IS_PASSABLE_UNDER(i)));
4785
4786     SET_PROPERTY(i, EP_ACCESSIBLE_OVER, (IS_WALKABLE_OVER(i) ||
4787                                          IS_PASSABLE_OVER(i)));
4788
4789     SET_PROPERTY(i, EP_ACCESSIBLE_INSIDE, (IS_WALKABLE_INSIDE(i) ||
4790                                            IS_PASSABLE_INSIDE(i)));
4791
4792     SET_PROPERTY(i, EP_ACCESSIBLE_UNDER, (IS_WALKABLE_UNDER(i) ||
4793                                           IS_PASSABLE_UNDER(i)));
4794
4795     SET_PROPERTY(i, EP_ACCESSIBLE, (IS_WALKABLE(i) ||
4796                                     IS_PASSABLE(i)));
4797
4798     /* ---------- COLLECTIBLE ---------------------------------------------- */
4799     SET_PROPERTY(i, EP_COLLECTIBLE, (IS_COLLECTIBLE_ONLY(i) ||
4800                                      IS_DROPPABLE(i) ||
4801                                      IS_THROWABLE(i)));
4802
4803     /* ---------- SNAPPABLE ------------------------------------------------ */
4804     SET_PROPERTY(i, EP_SNAPPABLE, (IS_DIGGABLE(i) ||
4805                                    IS_COLLECTIBLE(i) ||
4806                                    IS_SWITCHABLE(i) ||
4807                                    i == EL_BD_ROCK));
4808
4809     /* ---------- WALL ----------------------------------------------------- */
4810     SET_PROPERTY(i, EP_WALL, TRUE);     /* default: element is wall */
4811
4812     for (j = 0; no_wall_properties[j] != -1; j++)
4813       if (HAS_PROPERTY(i, no_wall_properties[j]) ||
4814           i >= EL_FIRST_RUNTIME_UNREAL)
4815         SET_PROPERTY(i, EP_WALL, FALSE);
4816
4817     if (IS_HISTORIC_WALL(i))
4818       SET_PROPERTY(i, EP_WALL, TRUE);
4819
4820     /* ---------- SOLID_FOR_PUSHING ---------------------------------------- */
4821     if (engine_version < VERSION_IDENT(2,2,0,0))
4822       SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, IS_HISTORIC_SOLID(i));
4823     else
4824       SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, (!IS_WALKABLE(i) &&
4825                                              !IS_DIGGABLE(i) &&
4826                                              !IS_COLLECTIBLE(i)));
4827
4828     /* ---------- DRAGONFIRE_PROOF ----------------------------------------- */
4829     if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
4830       SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE);
4831     else
4832       SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_CUSTOM_ELEMENT(i) &&
4833                                             IS_INDESTRUCTIBLE(i)));
4834
4835     /* ---------- EXPLOSION_PROOF ------------------------------------------ */
4836     if (i == EL_FLAMES)
4837       SET_PROPERTY(i, EP_EXPLOSION_PROOF, TRUE);
4838     else if (engine_version < VERSION_IDENT(2,2,0,0))
4839       SET_PROPERTY(i, EP_EXPLOSION_PROOF, IS_INDESTRUCTIBLE(i));
4840     else
4841       SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
4842                                            (!IS_WALKABLE(i) ||
4843                                             IS_PROTECTED(i))));
4844
4845     if (IS_CUSTOM_ELEMENT(i))
4846     {
4847       /* these are additional properties which are initially false when set */
4848
4849       /* ---------- DONT_COLLIDE_WITH / DONT_RUN_INTO ---------------------- */
4850       if (DONT_TOUCH(i))
4851         SET_PROPERTY(i, EP_DONT_COLLIDE_WITH, TRUE);
4852       if (DONT_COLLIDE_WITH(i))
4853         SET_PROPERTY(i, EP_DONT_RUN_INTO, TRUE);
4854
4855       /* ---------- CAN_SMASH_ENEMIES / CAN_SMASH_PLAYER ------------------- */
4856       if (CAN_SMASH_EVERYTHING(i))
4857         SET_PROPERTY(i, EP_CAN_SMASH_ENEMIES, TRUE);
4858       if (CAN_SMASH_ENEMIES(i))
4859         SET_PROPERTY(i, EP_CAN_SMASH_PLAYER, TRUE);
4860     }
4861
4862     /* ---------- CAN_SMASH ------------------------------------------------ */
4863     SET_PROPERTY(i, EP_CAN_SMASH, (CAN_SMASH_PLAYER(i) ||
4864                                    CAN_SMASH_ENEMIES(i) ||
4865                                    CAN_SMASH_EVERYTHING(i)));
4866
4867     /* ---------- CAN_EXPLODE_BY_FIRE -------------------------------------- */
4868     SET_PROPERTY(i, EP_CAN_EXPLODE_BY_FIRE, (CAN_EXPLODE(i) &&
4869                                              EXPLODES_BY_FIRE(i)));
4870
4871     /* ---------- CAN_EXPLODE_SMASHED -------------------------------------- */
4872     SET_PROPERTY(i, EP_CAN_EXPLODE_SMASHED, (CAN_EXPLODE(i) &&
4873                                              EXPLODES_SMASHED(i)));
4874
4875     /* ---------- CAN_EXPLODE_IMPACT --------------------------------------- */
4876     SET_PROPERTY(i, EP_CAN_EXPLODE_IMPACT, (CAN_EXPLODE(i) &&
4877                                             EXPLODES_IMPACT(i)));
4878
4879     /* ---------- CAN_EXPLODE_BY_DRAGONFIRE -------------------------------- */
4880     SET_PROPERTY(i, EP_CAN_EXPLODE_BY_DRAGONFIRE, CAN_EXPLODE_BY_FIRE(i));
4881
4882     /* ---------- CAN_EXPLODE_BY_EXPLOSION --------------------------------- */
4883     SET_PROPERTY(i, EP_CAN_EXPLODE_BY_EXPLOSION, (CAN_EXPLODE_BY_FIRE(i) ||
4884                                                   i == EL_BLACK_ORB));
4885
4886     /* ---------- COULD_MOVE_INTO_ACID ------------------------------------- */
4887     SET_PROPERTY(i, EP_COULD_MOVE_INTO_ACID, (ELEM_IS_PLAYER(i) ||
4888                                               CAN_MOVE(i) ||
4889                                               IS_CUSTOM_ELEMENT(i)));
4890
4891     /* ---------- MAYBE_DONT_COLLIDE_WITH ---------------------------------- */
4892     SET_PROPERTY(i, EP_MAYBE_DONT_COLLIDE_WITH, (i == EL_SP_SNIKSNAK ||
4893                                                  i == EL_SP_ELECTRON));
4894
4895     /* ---------- CAN_MOVE_INTO_ACID --------------------------------------- */
4896     if (COULD_MOVE_INTO_ACID(i) && !IS_CUSTOM_ELEMENT(i))
4897       SET_PROPERTY(i, EP_CAN_MOVE_INTO_ACID,
4898                    getMoveIntoAcidProperty(&level, i));
4899
4900     /* ---------- DONT_COLLIDE_WITH ---------------------------------------- */
4901     if (MAYBE_DONT_COLLIDE_WITH(i))
4902       SET_PROPERTY(i, EP_DONT_COLLIDE_WITH,
4903                    getDontCollideWithProperty(&level, i));
4904
4905     /* ---------- SP_PORT -------------------------------------------------- */
4906     SET_PROPERTY(i, EP_SP_PORT, (IS_SP_ELEMENT(i) &&
4907                                  IS_PASSABLE_INSIDE(i)));
4908
4909     /* ---------- CAN_BE_CLONED_BY_ANDROID --------------------------------- */
4910     for (j = 0; j < level.num_android_clone_elements; j++)
4911       SET_PROPERTY(i, EP_CAN_BE_CLONED_BY_ANDROID,
4912                    (i != EL_EMPTY &&
4913                     IS_EQUAL_OR_IN_GROUP(i, level.android_clone_element[j])));
4914
4915     /* ---------- CAN_CHANGE ----------------------------------------------- */
4916     SET_PROPERTY(i, EP_CAN_CHANGE, FALSE);      /* default: cannot change */
4917     for (j = 0; j < element_info[i].num_change_pages; j++)
4918       if (element_info[i].change_page[j].can_change)
4919         SET_PROPERTY(i, EP_CAN_CHANGE, TRUE);
4920
4921     /* ---------- HAS_ACTION ----------------------------------------------- */
4922     SET_PROPERTY(i, EP_HAS_ACTION, FALSE);      /* default: has no action */
4923     for (j = 0; j < element_info[i].num_change_pages; j++)
4924       if (element_info[i].change_page[j].has_action)
4925         SET_PROPERTY(i, EP_HAS_ACTION, TRUE);
4926
4927     /* ---------- CAN_CHANGE_OR_HAS_ACTION --------------------------------- */
4928     SET_PROPERTY(i, EP_CAN_CHANGE_OR_HAS_ACTION, (CAN_CHANGE(i) ||
4929                                                   HAS_ACTION(i)));
4930
4931     /* ---------- GFX_CRUMBLED --------------------------------------------- */
4932 #if 1
4933     SET_PROPERTY(i, EP_GFX_CRUMBLED,
4934                  element_info[i].crumbled[ACTION_DEFAULT] !=
4935                  element_info[i].graphic[ACTION_DEFAULT]);
4936 #else
4937     /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
4938     SET_PROPERTY(i, EP_GFX_CRUMBLED,
4939                  element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
4940 #endif
4941
4942     /* ---------- EDITOR_CASCADE ------------------------------------------- */
4943     SET_PROPERTY(i, EP_EDITOR_CASCADE, (IS_EDITOR_CASCADE_ACTIVE(i) ||
4944                                         IS_EDITOR_CASCADE_INACTIVE(i)));
4945   }
4946
4947   /* dynamically adjust element properties according to game engine version */
4948   {
4949     static int ep_em_slippery_wall[] =
4950     {
4951       EL_WALL,
4952       EL_STEELWALL,
4953       EL_EXPANDABLE_WALL,
4954       EL_EXPANDABLE_WALL_HORIZONTAL,
4955       EL_EXPANDABLE_WALL_VERTICAL,
4956       EL_EXPANDABLE_WALL_ANY,
4957       EL_EXPANDABLE_STEELWALL_HORIZONTAL,
4958       EL_EXPANDABLE_STEELWALL_VERTICAL,
4959       EL_EXPANDABLE_STEELWALL_ANY,
4960       EL_EXPANDABLE_STEELWALL_GROWING,
4961       -1
4962     };
4963
4964     static int ep_em_explodes_by_fire[] =
4965     {
4966       EL_EM_DYNAMITE,
4967       EL_EM_DYNAMITE_ACTIVE,
4968       EL_MOLE,
4969       -1
4970     };
4971
4972     /* special EM style gems behaviour */
4973     for (i = 0; ep_em_slippery_wall[i] != -1; i++)
4974       SET_PROPERTY(ep_em_slippery_wall[i], EP_EM_SLIPPERY_WALL,
4975                    level.em_slippery_gems);
4976
4977     /* "EL_EXPANDABLE_WALL_GROWING" wasn't slippery for EM gems in 2.0.1 */
4978     SET_PROPERTY(EL_EXPANDABLE_WALL_GROWING, EP_EM_SLIPPERY_WALL,
4979                  (level.em_slippery_gems &&
4980                   engine_version > VERSION_IDENT(2,0,1,0)));
4981
4982     /* special EM style explosion behaviour regarding chain reactions */
4983     for (i = 0; ep_em_explodes_by_fire[i] != -1; i++)
4984       SET_PROPERTY(ep_em_explodes_by_fire[i], EP_EXPLODES_BY_FIRE,
4985                    level.em_explodes_by_fire);
4986   }
4987
4988   /* this is needed because some graphics depend on element properties */
4989   if (game_status == GAME_MODE_PLAYING)
4990     InitElementGraphicInfo();
4991 }
4992
4993 void InitElementPropertiesAfterLoading(int engine_version)
4994 {
4995   int i;
4996
4997   /* set some other uninitialized values of custom elements in older levels */
4998   if (engine_version < VERSION_IDENT(3,1,0,0))
4999   {
5000     for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
5001     {
5002       int element = EL_CUSTOM_START + i;
5003
5004       element_info[element].access_direction = MV_ALL_DIRECTIONS;
5005
5006       element_info[element].explosion_delay = 17;
5007       element_info[element].ignition_delay = 8;
5008     }
5009   }
5010 }
5011
5012 void InitElementPropertiesGfxElement()
5013 {
5014   int i;
5015
5016   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
5017   {
5018     struct ElementInfo *ei = &element_info[i];
5019
5020     ei->gfx_element = (ei->use_gfx_element ? ei->gfx_element_initial : i);
5021   }
5022 }
5023
5024 static void InitGlobal()
5025 {
5026   int graphic;
5027   int i;
5028
5029   for (i = 0; i < MAX_NUM_ELEMENTS + 1; i++)
5030   {
5031     /* check if element_name_info entry defined for each element in "main.h" */
5032     if (i < MAX_NUM_ELEMENTS && element_name_info[i].token_name == NULL)
5033       Error(ERR_EXIT, "undefined 'element_name_info' entry for element %d", i);
5034
5035     element_info[i].token_name = element_name_info[i].token_name;
5036     element_info[i].class_name = element_name_info[i].class_name;
5037     element_info[i].editor_description= element_name_info[i].editor_description;
5038
5039 #if 0
5040     printf("%04d: %s\n", i, element_name_info[i].token_name);
5041 #endif
5042   }
5043
5044   /* create hash from image config list */
5045   image_config_hash = newSetupFileHash();
5046   for (i = 0; image_config[i].token != NULL; i++)
5047     setHashEntry(image_config_hash,
5048                  image_config[i].token,
5049                  image_config[i].value);
5050
5051   /* create hash from element token list */
5052   element_token_hash = newSetupFileHash();
5053   for (i = 0; element_name_info[i].token_name != NULL; i++)
5054     setHashEntry(element_token_hash,
5055                  element_name_info[i].token_name,
5056                  int2str(i, 0));
5057
5058   /* create hash from graphic token list */
5059   graphic_token_hash = newSetupFileHash();
5060   for (graphic = 0, i = 0; image_config[i].token != NULL; i++)
5061     if (strSuffix(image_config[i].value, ".pcx") ||
5062         strSuffix(image_config[i].value, ".wav") ||
5063         strEqual(image_config[i].value, UNDEFINED_FILENAME))
5064       setHashEntry(graphic_token_hash,
5065                    image_config[i].token,
5066                    int2str(graphic++, 0));
5067
5068   /* create hash from font token list */
5069   font_token_hash = newSetupFileHash();
5070   for (i = 0; font_info[i].token_name != NULL; i++)
5071     setHashEntry(font_token_hash,
5072                  font_info[i].token_name,
5073                  int2str(i, 0));
5074
5075   /* always start with reliable default values (all elements) */
5076   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
5077     ActiveElement[i] = i;
5078
5079   /* now add all entries that have an active state (active elements) */
5080   for (i = 0; element_with_active_state[i].element != -1; i++)
5081   {
5082     int element = element_with_active_state[i].element;
5083     int element_active = element_with_active_state[i].element_active;
5084
5085     ActiveElement[element] = element_active;
5086   }
5087
5088   /* always start with reliable default values (all buttons) */
5089   for (i = 0; i < NUM_IMAGE_FILES; i++)
5090     ActiveButton[i] = i;
5091
5092   /* now add all entries that have an active state (active buttons) */
5093   for (i = 0; button_with_active_state[i].button != -1; i++)
5094   {
5095     int button = button_with_active_state[i].button;
5096     int button_active = button_with_active_state[i].button_active;
5097
5098     ActiveButton[button] = button_active;
5099   }
5100
5101   /* always start with reliable default values (all fonts) */
5102   for (i = 0; i < NUM_FONTS; i++)
5103     ActiveFont[i] = i;
5104
5105   /* now add all entries that have an active state (active fonts) */
5106   for (i = 0; font_with_active_state[i].font_nr != -1; i++)
5107   {
5108     int font = font_with_active_state[i].font_nr;
5109     int font_active = font_with_active_state[i].font_nr_active;
5110
5111     ActiveFont[font] = font_active;
5112   }
5113
5114   global.autoplay_leveldir = NULL;
5115   global.convert_leveldir = NULL;
5116   global.create_images_dir = NULL;
5117
5118   global.frames_per_second = 0;
5119   global.fps_slowdown = FALSE;
5120   global.fps_slowdown_factor = 1;
5121
5122   global.border_status = GAME_MODE_MAIN;
5123 #if 0
5124   global.fading_status = GAME_MODE_MAIN;
5125   global.fading_type = TYPE_ENTER_MENU;
5126 #endif
5127
5128   global.use_envelope_request = FALSE;  /* !!! MOVE TO ARTWORK CONFIG !!! */
5129 }
5130
5131 void Execute_Command(char *command)
5132 {
5133   int i;
5134
5135   if (strEqual(command, "print graphicsinfo.conf"))
5136   {
5137     printf("# You can configure additional/alternative image files here.\n");
5138     printf("# (The entries below are default and therefore commented out.)\n");
5139     printf("\n");
5140     printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
5141     printf("\n");
5142     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
5143     printf("\n");
5144
5145     for (i = 0; image_config[i].token != NULL; i++)
5146       printf("# %s\n", getFormattedSetupEntry(image_config[i].token,
5147                                               image_config[i].value));
5148
5149     exit(0);
5150   }
5151   else if (strEqual(command, "print soundsinfo.conf"))
5152   {
5153     printf("# You can configure additional/alternative sound files here.\n");
5154     printf("# (The entries below are default and therefore commented out.)\n");
5155     printf("\n");
5156     printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
5157     printf("\n");
5158     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
5159     printf("\n");
5160
5161     for (i = 0; sound_config[i].token != NULL; i++)
5162       printf("# %s\n", getFormattedSetupEntry(sound_config[i].token,
5163                                               sound_config[i].value));
5164
5165     exit(0);
5166   }
5167   else if (strEqual(command, "print musicinfo.conf"))
5168   {
5169     printf("# You can configure additional/alternative music files here.\n");
5170     printf("# (The entries below are default and therefore commented out.)\n");
5171     printf("\n");
5172     printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
5173     printf("\n");
5174     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
5175     printf("\n");
5176
5177     for (i = 0; music_config[i].token != NULL; i++)
5178       printf("# %s\n", getFormattedSetupEntry(music_config[i].token,
5179                                               music_config[i].value));
5180
5181     exit(0);
5182   }
5183   else if (strEqual(command, "print editorsetup.conf"))
5184   {
5185     printf("# You can configure your personal editor element list here.\n");
5186     printf("# (The entries below are default and therefore commented out.)\n");
5187     printf("\n");
5188
5189     /* this is needed to be able to check element list for cascade elements */
5190     InitElementPropertiesStatic();
5191     InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
5192
5193     PrintEditorElementList();
5194
5195     exit(0);
5196   }
5197   else if (strEqual(command, "print helpanim.conf"))
5198   {
5199     printf("# You can configure different element help animations here.\n");
5200     printf("# (The entries below are default and therefore commented out.)\n");
5201     printf("\n");
5202
5203     for (i = 0; helpanim_config[i].token != NULL; i++)
5204     {
5205       printf("# %s\n", getFormattedSetupEntry(helpanim_config[i].token,
5206                                               helpanim_config[i].value));
5207
5208       if (strEqual(helpanim_config[i].token, "end"))
5209         printf("#\n");
5210     }
5211
5212     exit(0);
5213   }
5214   else if (strEqual(command, "print helptext.conf"))
5215   {
5216     printf("# You can configure different element help text here.\n");
5217     printf("# (The entries below are default and therefore commented out.)\n");
5218     printf("\n");
5219
5220     for (i = 0; helptext_config[i].token != NULL; i++)
5221       printf("# %s\n", getFormattedSetupEntry(helptext_config[i].token,
5222                                               helptext_config[i].value));
5223
5224     exit(0);
5225   }
5226   else if (strPrefix(command, "dump level "))
5227   {
5228     char *filename = &command[11];
5229
5230     if (!fileExists(filename))
5231       Error(ERR_EXIT, "cannot open file '%s'", filename);
5232
5233     LoadLevelFromFilename(&level, filename);
5234     DumpLevel(&level);
5235
5236     exit(0);
5237   }
5238   else if (strPrefix(command, "dump tape "))
5239   {
5240     char *filename = &command[10];
5241
5242     if (!fileExists(filename))
5243       Error(ERR_EXIT, "cannot open file '%s'", filename);
5244
5245     LoadTapeFromFilename(filename);
5246     DumpTape(&tape);
5247
5248     exit(0);
5249   }
5250   else if (strPrefix(command, "autoplay "))
5251   {
5252     char *str_ptr = getStringCopy(&command[9]); /* read command parameters */
5253
5254     while (*str_ptr != '\0')                    /* continue parsing string */
5255     {
5256       /* cut leading whitespace from string, replace it by string terminator */
5257       while (*str_ptr == ' ' || *str_ptr == '\t')
5258         *str_ptr++ = '\0';
5259
5260       if (*str_ptr == '\0')                     /* end of string reached */
5261         break;
5262
5263       if (global.autoplay_leveldir == NULL)     /* read level set string */
5264       {
5265         global.autoplay_leveldir = str_ptr;
5266         global.autoplay_all = TRUE;             /* default: play all tapes */
5267
5268         for (i = 0; i < MAX_TAPES_PER_SET; i++)
5269           global.autoplay_level[i] = FALSE;
5270       }
5271       else                                      /* read level number string */
5272       {
5273         int level_nr = atoi(str_ptr);           /* get level_nr value */
5274
5275         if (level_nr >= 0 && level_nr < MAX_TAPES_PER_SET)
5276           global.autoplay_level[level_nr] = TRUE;
5277
5278         global.autoplay_all = FALSE;
5279       }
5280
5281       /* advance string pointer to the next whitespace (or end of string) */
5282       while (*str_ptr != ' ' && *str_ptr != '\t' && *str_ptr != '\0')
5283         str_ptr++;
5284     }
5285   }
5286   else if (strPrefix(command, "convert "))
5287   {
5288     char *str_copy = getStringCopy(strchr(command, ' ') + 1);
5289     char *str_ptr = strchr(str_copy, ' ');
5290
5291     global.convert_leveldir = str_copy;
5292     global.convert_level_nr = -1;
5293
5294     if (str_ptr != NULL)                        /* level number follows */
5295     {
5296       *str_ptr++ = '\0';                        /* terminate leveldir string */
5297       global.convert_level_nr = atoi(str_ptr);  /* get level_nr value */
5298     }
5299   }
5300   else if (strPrefix(command, "create images "))
5301   {
5302 #if defined(TARGET_SDL)
5303     global.create_images_dir = getStringCopy(&command[14]);
5304
5305     if (access(global.create_images_dir, W_OK) != 0)
5306       Error(ERR_EXIT, "image target directory '%s' not found or not writable",
5307             global.create_images_dir);
5308 #else
5309     Error(ERR_EXIT, "command only available for SDL target");
5310 #endif
5311   }
5312
5313 #if DEBUG
5314 #if defined(TARGET_SDL)
5315   else if (strEqual(command, "SDL_ListModes"))
5316   {
5317     SDL_Rect **modes;
5318     int i;
5319
5320     SDL_Init(SDL_INIT_VIDEO);
5321
5322     /* get available fullscreen/hardware modes */
5323     modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
5324
5325     /* check if there are any modes available */
5326     if (modes == NULL)
5327     {
5328       printf("No modes available!\n");
5329
5330       exit(-1);
5331     }
5332
5333     /* check if our resolution is restricted */
5334     if (modes == (SDL_Rect **)-1)
5335     {
5336       printf("All resolutions available.\n");
5337     }
5338     else
5339     {
5340       printf("Available Modes:\n");
5341
5342       for(i = 0; modes[i]; i++)
5343         printf("  %d x %d\n", modes[i]->w, modes[i]->h);
5344     }
5345
5346     exit(0);
5347   }
5348 #endif
5349 #endif
5350
5351   else
5352   {
5353     Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
5354   }
5355 }
5356
5357 static void InitSetup()
5358 {
5359   LoadSetup();                                  /* global setup info */
5360
5361   /* set some options from setup file */
5362
5363   if (setup.options.verbose)
5364     options.verbose = TRUE;
5365 }
5366
5367 static void InitGameInfo()
5368 {
5369   game.restart_level = FALSE;
5370 }
5371
5372 static void InitPlayerInfo()
5373 {
5374   int i;
5375
5376   /* choose default local player */
5377   local_player = &stored_player[0];
5378
5379   for (i = 0; i < MAX_PLAYERS; i++)
5380     stored_player[i].connected = FALSE;
5381
5382   local_player->connected = TRUE;
5383 }
5384
5385 static void InitArtworkInfo()
5386 {
5387   LoadArtworkInfo();
5388 }
5389
5390 static char *get_string_in_brackets(char *string)
5391 {
5392   char *string_in_brackets = checked_malloc(strlen(string) + 3);
5393
5394   sprintf(string_in_brackets, "[%s]", string);
5395
5396   return string_in_brackets;
5397 }
5398
5399 static char *get_level_id_suffix(int id_nr)
5400 {
5401   char *id_suffix = checked_malloc(1 + 3 + 1);
5402
5403   if (id_nr < 0 || id_nr > 999)
5404     id_nr = 0;
5405
5406   sprintf(id_suffix, ".%03d", id_nr);
5407
5408   return id_suffix;
5409 }
5410
5411 #if 0
5412 static char *get_element_class_token(int element)
5413 {
5414   char *element_class_name = element_info[element].class_name;
5415   char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
5416
5417   sprintf(element_class_token, "[%s]", element_class_name);
5418
5419   return element_class_token;
5420 }
5421
5422 static char *get_action_class_token(int action)
5423 {
5424   char *action_class_name = &element_action_info[action].suffix[1];
5425   char *action_class_token = checked_malloc(strlen(action_class_name) + 3);
5426
5427   sprintf(action_class_token, "[%s]", action_class_name);
5428
5429   return action_class_token;
5430 }
5431 #endif
5432
5433 static void InitArtworkConfig()
5434 {
5435   static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
5436   static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + 1];
5437   static char *music_id_prefix[NUM_MUSIC_PREFIXES + 1];
5438   static char *action_id_suffix[NUM_ACTIONS + 1];
5439   static char *direction_id_suffix[NUM_DIRECTIONS_FULL + 1];
5440   static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
5441   static char *level_id_suffix[MAX_LEVELS + 1];
5442   static char *dummy[1] = { NULL };
5443   static char *ignore_generic_tokens[] =
5444   {
5445     "name",
5446     "sort_priority",
5447     NULL
5448   };
5449   static char **ignore_image_tokens;
5450   static char **ignore_sound_tokens;
5451   static char **ignore_music_tokens;
5452   int num_ignore_generic_tokens;
5453   int num_ignore_image_tokens;
5454   int num_ignore_sound_tokens;
5455   int num_ignore_music_tokens;
5456   int i;
5457
5458   /* dynamically determine list of generic tokens to be ignored */
5459   num_ignore_generic_tokens = 0;
5460   for (i = 0; ignore_generic_tokens[i] != NULL; i++)
5461     num_ignore_generic_tokens++;
5462
5463   /* dynamically determine list of image tokens to be ignored */
5464   num_ignore_image_tokens = num_ignore_generic_tokens;
5465   for (i = 0; image_config_vars[i].token != NULL; i++)
5466     num_ignore_image_tokens++;
5467   ignore_image_tokens =
5468     checked_malloc((num_ignore_image_tokens + 1) * sizeof(char *));
5469   for (i = 0; i < num_ignore_generic_tokens; i++)
5470     ignore_image_tokens[i] = ignore_generic_tokens[i];
5471   for (i = 0; i < num_ignore_image_tokens - num_ignore_generic_tokens; i++)
5472     ignore_image_tokens[num_ignore_generic_tokens + i] =
5473       image_config_vars[i].token;
5474   ignore_image_tokens[num_ignore_image_tokens] = NULL;
5475
5476   /* dynamically determine list of sound tokens to be ignored */
5477   num_ignore_sound_tokens = num_ignore_generic_tokens;
5478   ignore_sound_tokens =
5479     checked_malloc((num_ignore_sound_tokens + 1) * sizeof(char *));
5480   for (i = 0; i < num_ignore_generic_tokens; i++)
5481     ignore_sound_tokens[i] = ignore_generic_tokens[i];
5482   ignore_sound_tokens[num_ignore_sound_tokens] = NULL;
5483
5484   /* dynamically determine list of music tokens to be ignored */
5485   num_ignore_music_tokens = num_ignore_generic_tokens;
5486   ignore_music_tokens =
5487     checked_malloc((num_ignore_music_tokens + 1) * sizeof(char *));
5488   for (i = 0; i < num_ignore_generic_tokens; i++)
5489     ignore_music_tokens[i] = ignore_generic_tokens[i];
5490   ignore_music_tokens[num_ignore_music_tokens] = NULL;
5491
5492   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
5493     image_id_prefix[i] = element_info[i].token_name;
5494   for (i = 0; i < NUM_FONTS; i++)
5495     image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
5496   image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
5497
5498   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
5499     sound_id_prefix[i] = element_info[i].token_name;
5500   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
5501     sound_id_prefix[MAX_NUM_ELEMENTS + i] =
5502       get_string_in_brackets(element_info[i].class_name);
5503   sound_id_prefix[2 * MAX_NUM_ELEMENTS] = NULL;
5504
5505   for (i = 0; i < NUM_MUSIC_PREFIXES; i++)
5506     music_id_prefix[i] = music_prefix_info[i].prefix;
5507   music_id_prefix[NUM_MUSIC_PREFIXES] = NULL;
5508
5509   for (i = 0; i < NUM_ACTIONS; i++)
5510     action_id_suffix[i] = element_action_info[i].suffix;
5511   action_id_suffix[NUM_ACTIONS] = NULL;
5512
5513   for (i = 0; i < NUM_DIRECTIONS_FULL; i++)
5514     direction_id_suffix[i] = element_direction_info[i].suffix;
5515   direction_id_suffix[NUM_DIRECTIONS_FULL] = NULL;
5516
5517   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
5518     special_id_suffix[i] = special_suffix_info[i].suffix;
5519   special_id_suffix[NUM_SPECIAL_GFX_ARGS] = NULL;
5520
5521   for (i = 0; i < MAX_LEVELS; i++)
5522     level_id_suffix[i] = get_level_id_suffix(i);
5523   level_id_suffix[MAX_LEVELS] = NULL;
5524
5525   InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
5526                 image_id_prefix, action_id_suffix, direction_id_suffix,
5527                 special_id_suffix, ignore_image_tokens);
5528   InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
5529                 sound_id_prefix, action_id_suffix, dummy,
5530                 special_id_suffix, ignore_sound_tokens);
5531   InitMusicList(music_config, NUM_MUSIC_FILES, music_config_suffix,
5532                 music_id_prefix, special_id_suffix, level_id_suffix,
5533                 dummy, ignore_music_tokens);
5534 }
5535
5536 static void InitMixer()
5537 {
5538   OpenAudio();
5539
5540   StartMixer();
5541 }
5542
5543 void InitGfxBuffers()
5544 {
5545   ReCreateBitmap(&bitmap_db_store, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
5546   ReCreateBitmap(&bitmap_db_cross, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
5547   ReCreateBitmap(&bitmap_db_field, FXSIZE, FYSIZE, DEFAULT_DEPTH);
5548   ReCreateBitmap(&bitmap_db_panel, DXSIZE, DYSIZE, DEFAULT_DEPTH);
5549   ReCreateBitmap(&bitmap_db_door, 3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
5550   ReCreateBitmap(&bitmap_db_toons, FULL_SXSIZE, FULL_SYSIZE, DEFAULT_DEPTH);
5551
5552   /* initialize screen properties */
5553   InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
5554                    REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
5555                    bitmap_db_field);
5556   InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
5557   InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
5558   InitGfxWindowInfo(WIN_XSIZE, WIN_YSIZE);
5559   InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
5560   InitGfxClipRegion(FALSE, -1, -1, -1, -1);
5561
5562   InitGfxBuffers_SP();
5563 }
5564
5565 void InitGfx()
5566 {
5567   struct GraphicInfo *graphic_info_last = graphic_info;
5568   char *filename_font_initial = NULL;
5569   char *filename_anim_initial = NULL;
5570   Bitmap *bitmap_font_initial = NULL;
5571   int font_height;
5572   int i, j;
5573
5574   /* determine settings for initial font (for displaying startup messages) */
5575   for (i = 0; image_config[i].token != NULL; i++)
5576   {
5577     for (j = 0; j < NUM_INITIAL_FONTS; j++)
5578     {
5579       char font_token[128];
5580       int len_font_token;
5581
5582       sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1);
5583       len_font_token = strlen(font_token);
5584
5585       if (strEqual(image_config[i].token, font_token))
5586         filename_font_initial = image_config[i].value;
5587       else if (strlen(image_config[i].token) > len_font_token &&
5588                strncmp(image_config[i].token, font_token, len_font_token) == 0)
5589       {
5590         if (strEqual(&image_config[i].token[len_font_token], ".x"))
5591           font_initial[j].src_x = atoi(image_config[i].value);
5592         else if (strEqual(&image_config[i].token[len_font_token], ".y"))
5593           font_initial[j].src_y = atoi(image_config[i].value);
5594         else if (strEqual(&image_config[i].token[len_font_token], ".width"))
5595           font_initial[j].width = atoi(image_config[i].value);
5596         else if (strEqual(&image_config[i].token[len_font_token], ".height"))
5597           font_initial[j].height = atoi(image_config[i].value);
5598       }
5599     }
5600   }
5601
5602   for (j = 0; j < NUM_INITIAL_FONTS; j++)
5603   {
5604     font_initial[j].num_chars = DEFAULT_NUM_CHARS_PER_FONT;
5605     font_initial[j].num_chars_per_line = DEFAULT_NUM_CHARS_PER_LINE;
5606   }
5607
5608   if (filename_font_initial == NULL)    /* should not happen */
5609     Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
5610
5611 #if 1
5612   InitGfxBuffers();
5613 #else
5614   /* create additional image buffers for double-buffering and cross-fading */
5615   bitmap_db_store = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
5616   bitmap_db_cross = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
5617   bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
5618   bitmap_db_panel = CreateBitmap(DXSIZE, DYSIZE, DEFAULT_DEPTH);
5619   bitmap_db_door  = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
5620   bitmap_db_toons = CreateBitmap(FULL_SXSIZE, FULL_SYSIZE, DEFAULT_DEPTH);
5621
5622   /* initialize screen properties */
5623   InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
5624                    REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
5625                    bitmap_db_field);
5626   InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
5627   InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
5628   InitGfxWindowInfo(WIN_XSIZE, WIN_YSIZE);
5629   InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
5630 #endif
5631
5632   InitGfxCustomArtworkInfo();
5633
5634   bitmap_font_initial = LoadCustomImage(filename_font_initial);
5635
5636   for (j = 0; j < NUM_INITIAL_FONTS; j++)
5637     font_initial[j].bitmap = bitmap_font_initial;
5638
5639   InitFontGraphicInfo();
5640
5641   font_height = getFontHeight(FC_RED);
5642
5643 #if 1
5644   DrawInitText(getWindowTitleString(), 20, FC_YELLOW);
5645 #else
5646   DrawInitText(getProgramInitString(), 20, FC_YELLOW);
5647 #endif
5648   DrawInitText(PROGRAM_COPYRIGHT_STRING, 50, FC_RED);
5649   DrawInitText(PROGRAM_WEBSITE_STRING, WIN_YSIZE - 20 - font_height, FC_RED);
5650
5651   DrawInitText("Loading graphics", 120, FC_GREEN);
5652
5653 #if 1
5654 #if 1
5655   /* initialize busy animation with default values */
5656   int parameter[NUM_GFX_ARGS];
5657   for (i = 0; i < NUM_GFX_ARGS; i++)
5658     parameter[i] = get_graphic_parameter_value(image_config_suffix[i].value,
5659                                                image_config_suffix[i].token,
5660                                                image_config_suffix[i].type);
5661 #if 0
5662   for (i = 0; i < NUM_GFX_ARGS; i++)
5663     printf("::: '%s' => %d\n", image_config_suffix[i].token, parameter[i]);
5664 #endif
5665 #endif
5666
5667   /* determine settings for busy animation (when displaying startup messages) */
5668   for (i = 0; image_config[i].token != NULL; i++)
5669   {
5670     char *anim_token = CONFIG_TOKEN_GLOBAL_BUSY;
5671     int len_anim_token = strlen(anim_token);
5672
5673     if (strEqual(image_config[i].token, anim_token))
5674       filename_anim_initial = image_config[i].value;
5675     else if (strlen(image_config[i].token) > len_anim_token &&
5676              strncmp(image_config[i].token, anim_token, len_anim_token) == 0)
5677     {
5678 #if 1
5679       for (j = 0; image_config_suffix[j].token != NULL; j++)
5680       {
5681         if (strEqual(&image_config[i].token[len_anim_token],
5682                      image_config_suffix[j].token))
5683           parameter[j] =
5684             get_graphic_parameter_value(image_config[i].value,
5685                                         image_config_suffix[j].token,
5686                                         image_config_suffix[j].type);
5687       }
5688 #else
5689       if (strEqual(&image_config[i].token[len_anim_token], ".x"))
5690         anim_initial.src_x = atoi(image_config[i].value);
5691       else if (strEqual(&image_config[i].token[len_anim_token], ".y"))
5692         anim_initial.src_y = atoi(image_config[i].value);
5693       else if (strEqual(&image_config[i].token[len_anim_token], ".width"))
5694         anim_initial.width = atoi(image_config[i].value);
5695       else if (strEqual(&image_config[i].token[len_anim_token], ".height"))
5696         anim_initial.height = atoi(image_config[i].value);
5697       else if (strEqual(&image_config[i].token[len_anim_token], ".frames"))
5698         anim_initial.anim_frames = atoi(image_config[i].value);
5699       else if (strEqual(&image_config[i].token[len_anim_token],
5700                         ".frames_per_line"))
5701         anim_initial.anim_frames_per_line = atoi(image_config[i].value);
5702       else if (strEqual(&image_config[i].token[len_anim_token], ".delay"))
5703         anim_initial.anim_delay = atoi(image_config[i].value);
5704 #endif
5705     }
5706   }
5707
5708 #if defined(CREATE_SPECIAL_EDITION_RND_JUE)
5709   filename_anim_initial = "loading.pcx";
5710
5711   parameter[GFX_ARG_X] = 0;
5712   parameter[GFX_ARG_Y] = 0;
5713   parameter[GFX_ARG_WIDTH] = 128;
5714   parameter[GFX_ARG_HEIGHT] = 40;
5715   parameter[GFX_ARG_FRAMES] = 32;
5716   parameter[GFX_ARG_DELAY] = 4;
5717   parameter[GFX_ARG_FRAMES_PER_LINE] = ARG_UNDEFINED_VALUE;
5718 #endif
5719
5720   if (filename_anim_initial == NULL)    /* should not happen */
5721     Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_GLOBAL_BUSY);
5722
5723   anim_initial.bitmap = LoadCustomImage(filename_anim_initial);
5724
5725   graphic_info = &anim_initial;         /* graphic == 0 => anim_initial */
5726
5727   set_graphic_parameters_ext(0, parameter, anim_initial.bitmap);
5728
5729 #if 0
5730   printf("::: INIT_GFX: anim_frames_per_line == %d [%d / %d] [%d, %d]\n",
5731          graphic_info[0].anim_frames_per_line,
5732          get_scaled_graphic_width(0),
5733          graphic_info[0].width,
5734          getOriginalImageWidthFromImageID(0),
5735          graphic_info[0].scale_up_factor);
5736 #endif
5737
5738   graphic_info = graphic_info_last;
5739
5740   init.busy.width  = anim_initial.width;
5741   init.busy.height = anim_initial.height;
5742
5743   InitMenuDesignSettings_Static();
5744   InitGfxDrawBusyAnimFunction(DrawInitAnim);
5745
5746   /* use copy of busy animation to prevent change while reloading artwork */
5747   init_last = init;
5748 #endif
5749 }
5750
5751 void RedrawBackground()
5752 {
5753   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
5754              0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
5755
5756   redraw_mask = REDRAW_ALL;
5757 }
5758
5759 void InitGfxBackground()
5760 {
5761   int x, y;
5762
5763   fieldbuffer = bitmap_db_field;
5764   SetDrawtoField(DRAW_BACKBUFFER);
5765
5766 #if 1
5767   ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE);
5768 #else
5769   RedrawBackground();
5770
5771   ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
5772   ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
5773 #endif
5774
5775   for (x = 0; x < MAX_BUF_XSIZE; x++)
5776     for (y = 0; y < MAX_BUF_YSIZE; y++)
5777       redraw[x][y] = 0;
5778   redraw_tiles = 0;
5779   redraw_mask = REDRAW_ALL;
5780 }
5781
5782 static void InitLevelInfo()
5783 {
5784   LoadLevelInfo();                              /* global level info */
5785   LoadLevelSetup_LastSeries();                  /* last played series info */
5786   LoadLevelSetup_SeriesInfo();                  /* last played level info */
5787 }
5788
5789 static void InitLevelArtworkInfo()
5790 {
5791   LoadLevelArtworkInfo();
5792 }
5793
5794 static void InitImages()
5795 {
5796   print_timestamp_init("InitImages");
5797
5798 #if 0
5799   printf("::: leveldir_current->identifier == '%s'\n",
5800          leveldir_current == NULL ? "[NULL]" : leveldir_current->identifier);
5801   printf("::: leveldir_current->graphics_path == '%s'\n",
5802          leveldir_current == NULL ? "[NULL]" : leveldir_current->graphics_path);
5803   printf("::: leveldir_current->graphics_set == '%s'\n",
5804          leveldir_current == NULL ? "[NULL]" : leveldir_current->graphics_set);
5805   printf("::: getLevelArtworkSet(ARTWORK_TYPE_GRAPHICS) == '%s'\n",
5806          leveldir_current == NULL ? "[NULL]" : LEVELDIR_ARTWORK_SET(leveldir_current, ARTWORK_TYPE_GRAPHICS));
5807 #endif
5808
5809   setLevelArtworkDir(artwork.gfx_first);
5810
5811 #if 0
5812   printf("::: leveldir_current->identifier == '%s'\n",
5813          leveldir_current == NULL ? "[NULL]" : leveldir_current->identifier);
5814   printf("::: leveldir_current->graphics_path == '%s'\n",
5815          leveldir_current == NULL ? "[NULL]" : leveldir_current->graphics_path);
5816   printf("::: leveldir_current->graphics_set == '%s'\n",
5817          leveldir_current == NULL ? "[NULL]" : leveldir_current->graphics_set);
5818   printf("::: getLevelArtworkSet(ARTWORK_TYPE_GRAPHICS) == '%s'\n",
5819          leveldir_current == NULL ? "[NULL]" : LEVELDIR_ARTWORK_SET(leveldir_current, ARTWORK_TYPE_GRAPHICS));
5820 #endif
5821
5822 #if 0
5823   printf("::: InitImages for '%s' ['%s', '%s'] ['%s', '%s']\n",
5824          leveldir_current->identifier,
5825          artwork.gfx_current_identifier,
5826          artwork.gfx_current->identifier,
5827          leveldir_current->graphics_set,
5828          leveldir_current->graphics_path);
5829 #endif
5830
5831   UPDATE_BUSY_STATE();
5832
5833   ReloadCustomImages();
5834   print_timestamp_time("ReloadCustomImages");
5835
5836   UPDATE_BUSY_STATE();
5837
5838   LoadCustomElementDescriptions();
5839   print_timestamp_time("LoadCustomElementDescriptions");
5840
5841   UPDATE_BUSY_STATE();
5842
5843   LoadMenuDesignSettings();
5844   print_timestamp_time("LoadMenuDesignSettings");
5845
5846   UPDATE_BUSY_STATE();
5847
5848   ReinitializeGraphics();
5849   print_timestamp_time("ReinitializeGraphics");
5850
5851   UPDATE_BUSY_STATE();
5852
5853   print_timestamp_done("InitImages");
5854 }
5855
5856 static void InitSound(char *identifier)
5857 {
5858   print_timestamp_init("InitSound");
5859
5860   if (identifier == NULL)
5861     identifier = artwork.snd_current->identifier;
5862
5863   /* set artwork path to send it to the sound server process */
5864   setLevelArtworkDir(artwork.snd_first);
5865
5866   InitReloadCustomSounds(identifier);
5867   print_timestamp_time("InitReloadCustomSounds");
5868
5869   ReinitializeSounds();
5870   print_timestamp_time("ReinitializeSounds");
5871
5872   print_timestamp_done("InitSound");
5873 }
5874
5875 static void InitMusic(char *identifier)
5876 {
5877   print_timestamp_init("InitMusic");
5878
5879   if (identifier == NULL)
5880     identifier = artwork.mus_current->identifier;
5881
5882   /* set artwork path to send it to the sound server process */
5883   setLevelArtworkDir(artwork.mus_first);
5884
5885   InitReloadCustomMusic(identifier);
5886   print_timestamp_time("InitReloadCustomMusic");
5887
5888   ReinitializeMusic();
5889   print_timestamp_time("ReinitializeMusic");
5890
5891   print_timestamp_done("InitMusic");
5892 }
5893
5894 void InitNetworkServer()
5895 {
5896 #if defined(NETWORK_AVALIABLE)
5897   int nr_wanted;
5898 #endif
5899
5900   if (!options.network)
5901     return;
5902
5903 #if defined(NETWORK_AVALIABLE)
5904   nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
5905
5906   if (!ConnectToServer(options.server_host, options.server_port))
5907     Error(ERR_EXIT, "cannot connect to network game server");
5908
5909   SendToServer_PlayerName(setup.player_name);
5910   SendToServer_ProtocolVersion();
5911
5912   if (nr_wanted)
5913     SendToServer_NrWanted(nr_wanted);
5914 #endif
5915 }
5916
5917 static boolean CheckArtworkConfigForCustomElements(char *filename)
5918 {
5919   SetupFileHash *setup_file_hash;
5920   boolean redefined_ce_found = FALSE;
5921
5922   /* !!! CACHE THIS BY USING HASH 'filename' => 'true/false' !!! */
5923
5924   if ((setup_file_hash = loadSetupFileHash(filename)) != NULL)
5925   {
5926     BEGIN_HASH_ITERATION(setup_file_hash, itr)
5927     {
5928       char *token = HASH_ITERATION_TOKEN(itr);
5929
5930       if (strPrefix(token, "custom_"))
5931       {
5932         redefined_ce_found = TRUE;
5933
5934         break;
5935       }
5936     }
5937     END_HASH_ITERATION(setup_file_hash, itr)
5938
5939     freeSetupFileHash(setup_file_hash);
5940   }
5941
5942   return redefined_ce_found;
5943 }
5944
5945 static boolean CheckArtworkTypeForRedefinedCustomElements(int type)
5946 {
5947   char *filename_base, *filename_local;
5948   boolean redefined_ce_found = FALSE;
5949
5950   setLevelArtworkDir(ARTWORK_FIRST_NODE(artwork, type));
5951
5952 #if 0
5953   printf("::: leveldir_current->identifier == '%s'\n",
5954          leveldir_current == NULL ? "[NULL]" : leveldir_current->identifier);
5955   printf("::: leveldir_current->graphics_path == '%s'\n",
5956          leveldir_current == NULL ? "[NULL]" : leveldir_current->graphics_path);
5957   printf("::: leveldir_current->graphics_set == '%s'\n",
5958          leveldir_current == NULL ? "[NULL]" : leveldir_current->graphics_set);
5959   printf("::: getLevelArtworkSet(ARTWORK_TYPE_GRAPHICS) == '%s'\n",
5960          leveldir_current == NULL ? "[NULL]" :
5961          LEVELDIR_ARTWORK_SET(leveldir_current, type));
5962 #endif
5963
5964   /* first look for special artwork configured in level series config */
5965   filename_base = getCustomArtworkLevelConfigFilename(type);
5966
5967 #if 0
5968   printf("::: filename_base == '%s'\n", filename_base);
5969 #endif
5970
5971   if (fileExists(filename_base))
5972     redefined_ce_found |= CheckArtworkConfigForCustomElements(filename_base);
5973
5974   filename_local = getCustomArtworkConfigFilename(type);
5975
5976 #if 0
5977   printf("::: filename_local == '%s'\n", filename_local);
5978 #endif
5979
5980   if (filename_local != NULL && !strEqual(filename_base, filename_local))
5981     redefined_ce_found |= CheckArtworkConfigForCustomElements(filename_local);
5982
5983 #if 0
5984   printf("::: redefined_ce_found == %d\n", redefined_ce_found);
5985 #endif
5986
5987   return redefined_ce_found;
5988 }
5989
5990 static void InitOverrideArtwork()
5991 {
5992   boolean redefined_ce_found = FALSE;
5993
5994   /* to check if this level set redefines any CEs, do not use overriding */
5995   gfx.override_level_graphics = FALSE;
5996   gfx.override_level_sounds   = FALSE;
5997   gfx.override_level_music    = FALSE;
5998
5999   /* now check if this level set has definitions for custom elements */
6000   if (setup.override_level_graphics == AUTO ||
6001       setup.override_level_sounds   == AUTO ||
6002       setup.override_level_music    == AUTO)
6003     redefined_ce_found =
6004       (CheckArtworkTypeForRedefinedCustomElements(ARTWORK_TYPE_GRAPHICS) |
6005        CheckArtworkTypeForRedefinedCustomElements(ARTWORK_TYPE_SOUNDS) |
6006        CheckArtworkTypeForRedefinedCustomElements(ARTWORK_TYPE_MUSIC));
6007
6008 #if 0
6009   printf("::: redefined_ce_found == %d\n", redefined_ce_found);
6010 #endif
6011
6012   if (redefined_ce_found)
6013   {
6014     /* this level set has CE definitions: change "AUTO" to "FALSE" */
6015     gfx.override_level_graphics = (setup.override_level_graphics == TRUE);
6016     gfx.override_level_sounds   = (setup.override_level_sounds   == TRUE);
6017     gfx.override_level_music    = (setup.override_level_music    == TRUE);
6018   }
6019   else
6020   {
6021     /* this level set has no CE definitions: change "AUTO" to "TRUE" */
6022     gfx.override_level_graphics = (setup.override_level_graphics != FALSE);
6023     gfx.override_level_sounds   = (setup.override_level_sounds   != FALSE);
6024     gfx.override_level_music    = (setup.override_level_music    != FALSE);
6025   }
6026
6027 #if 0
6028   printf("::: => %d, %d, %d\n",
6029          gfx.override_level_graphics,
6030          gfx.override_level_sounds,
6031          gfx.override_level_music);
6032 #endif
6033 }
6034
6035 static char *getNewArtworkIdentifier(int type)
6036 {
6037   static char *leveldir_current_identifier[3] = { NULL, NULL, NULL };
6038   static boolean last_override_level_artwork[3] = { FALSE, FALSE, FALSE };
6039   static boolean last_has_level_artwork_set[3] = { FALSE, FALSE, FALSE };
6040   static boolean initialized[3] = { FALSE, FALSE, FALSE };
6041   TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
6042 #if 1
6043   boolean setup_override_artwork = GFX_OVERRIDE_ARTWORK(type);
6044 #else
6045   boolean setup_override_artwork = SETUP_OVERRIDE_ARTWORK(setup, type);
6046 #endif
6047   char *setup_artwork_set = SETUP_ARTWORK_SET(setup, type);
6048   char *leveldir_identifier = leveldir_current->identifier;
6049 #if 1
6050   /* !!! setLevelArtworkDir() should be moved to an earlier stage !!! */
6051   char *leveldir_artwork_set = setLevelArtworkDir(artwork_first_node);
6052 #else
6053   char *leveldir_artwork_set = LEVELDIR_ARTWORK_SET(leveldir_current, type);
6054 #endif
6055   boolean has_level_artwork_set = (leveldir_artwork_set != NULL);
6056   char *artwork_current_identifier;
6057   char *artwork_new_identifier = NULL;  /* default: nothing has changed */
6058
6059   /* leveldir_current may be invalid (level group, parent link) */
6060   if (!validLevelSeries(leveldir_current))
6061     return NULL;
6062
6063   /* 1st step: determine artwork set to be activated in descending order:
6064      --------------------------------------------------------------------
6065      1. setup artwork (when configured to override everything else)
6066      2. artwork set configured in "levelinfo.conf" of current level set
6067         (artwork in level directory will have priority when loading later)
6068      3. artwork in level directory (stored in artwork sub-directory)
6069      4. setup artwork (currently configured in setup menu) */
6070
6071   if (setup_override_artwork)
6072     artwork_current_identifier = setup_artwork_set;
6073   else if (leveldir_artwork_set != NULL)
6074     artwork_current_identifier = leveldir_artwork_set;
6075   else if (getTreeInfoFromIdentifier(artwork_first_node, leveldir_identifier))
6076     artwork_current_identifier = leveldir_identifier;
6077   else
6078     artwork_current_identifier = setup_artwork_set;
6079
6080
6081   /* 2nd step: check if it is really needed to reload artwork set
6082      ------------------------------------------------------------ */
6083
6084 #if 0
6085   if (type == ARTWORK_TYPE_GRAPHICS)
6086     printf("::: 0: '%s' ['%s', '%s'] ['%s' ('%s')]\n",
6087            artwork_new_identifier,
6088            ARTWORK_CURRENT_IDENTIFIER(artwork, type),
6089            artwork_current_identifier,
6090            leveldir_current->graphics_set,
6091            leveldir_current->identifier);
6092 #endif
6093
6094   /* ---------- reload if level set and also artwork set has changed ------- */
6095   if (leveldir_current_identifier[type] != leveldir_identifier &&
6096       (last_has_level_artwork_set[type] || has_level_artwork_set))
6097     artwork_new_identifier = artwork_current_identifier;
6098
6099   leveldir_current_identifier[type] = leveldir_identifier;
6100   last_has_level_artwork_set[type] = has_level_artwork_set;
6101
6102 #if 0
6103   if (type == ARTWORK_TYPE_GRAPHICS)
6104     printf("::: 1: '%s'\n", artwork_new_identifier);
6105 #endif
6106
6107   /* ---------- reload if "override artwork" setting has changed ----------- */
6108   if (last_override_level_artwork[type] != setup_override_artwork)
6109     artwork_new_identifier = artwork_current_identifier;
6110
6111   last_override_level_artwork[type] = setup_override_artwork;
6112
6113 #if 0
6114   if (type == ARTWORK_TYPE_GRAPHICS)
6115     printf("::: 2: '%s'\n", artwork_new_identifier);
6116 #endif
6117
6118   /* ---------- reload if current artwork identifier has changed ----------- */
6119   if (!strEqual(ARTWORK_CURRENT_IDENTIFIER(artwork, type),
6120                 artwork_current_identifier))
6121     artwork_new_identifier = artwork_current_identifier;
6122
6123   *(ARTWORK_CURRENT_IDENTIFIER_PTR(artwork, type))= artwork_current_identifier;
6124
6125 #if 0
6126   if (type == ARTWORK_TYPE_GRAPHICS)
6127     printf("::: 3: '%s'\n", artwork_new_identifier);
6128 #endif
6129
6130   /* ---------- do not reload directly after starting ---------------------- */
6131   if (!initialized[type])
6132     artwork_new_identifier = NULL;
6133
6134   initialized[type] = TRUE;
6135
6136 #if 0
6137   if (type == ARTWORK_TYPE_GRAPHICS)
6138     printf("::: 4: '%s'\n", artwork_new_identifier);
6139 #endif
6140
6141 #if 0
6142   if (type == ARTWORK_TYPE_GRAPHICS)
6143     printf("CHECKING OLD/NEW GFX:\n- OLD: %s\n- NEW: %s ['%s', '%s'] ['%s']\n",
6144            artwork.gfx_current_identifier, artwork_current_identifier,
6145            artwork.gfx_current->identifier, leveldir_current->graphics_set,
6146            artwork_new_identifier);
6147 #endif
6148
6149   return artwork_new_identifier;
6150 }
6151
6152 void ReloadCustomArtwork(int force_reload)
6153 {
6154   int last_game_status = game_status;   /* save current game status */
6155   char *gfx_new_identifier;
6156   char *snd_new_identifier;
6157   char *mus_new_identifier;
6158   boolean force_reload_gfx = (force_reload & (1 << ARTWORK_TYPE_GRAPHICS));
6159   boolean force_reload_snd = (force_reload & (1 << ARTWORK_TYPE_SOUNDS));
6160   boolean force_reload_mus = (force_reload & (1 << ARTWORK_TYPE_MUSIC));
6161   boolean reload_needed;
6162
6163   InitOverrideArtwork();
6164
6165   force_reload_gfx |= AdjustGraphicsForEMC();
6166
6167   gfx_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_GRAPHICS);
6168   snd_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_SOUNDS);
6169   mus_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_MUSIC);
6170
6171   reload_needed = (gfx_new_identifier != NULL || force_reload_gfx ||
6172                    snd_new_identifier != NULL || force_reload_snd ||
6173                    mus_new_identifier != NULL || force_reload_mus);
6174
6175   if (!reload_needed)
6176     return;
6177
6178   print_timestamp_init("ReloadCustomArtwork");
6179
6180   game_status = GAME_MODE_LOADING;
6181
6182   FadeOut(REDRAW_ALL);
6183
6184 #if 1
6185   ClearRectangle(drawto, 0, 0, WIN_XSIZE, WIN_YSIZE);
6186 #else
6187   ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
6188 #endif
6189   print_timestamp_time("ClearRectangle");
6190
6191 #if 0
6192   printf("::: fading in ... %d\n", fading.fade_mode);
6193 #endif
6194   FadeIn(REDRAW_ALL);
6195 #if 0
6196   printf("::: done\n");
6197 #endif
6198
6199   if (gfx_new_identifier != NULL || force_reload_gfx)
6200   {
6201 #if 0
6202     printf("RELOADING GRAPHICS '%s' -> '%s' ['%s', '%s']\n",
6203            artwork.gfx_current_identifier,
6204            gfx_new_identifier,
6205            artwork.gfx_current->identifier,
6206            leveldir_current->graphics_set);
6207 #endif
6208
6209     InitImages();
6210     print_timestamp_time("InitImages");
6211   }
6212
6213   if (snd_new_identifier != NULL || force_reload_snd)
6214   {
6215     InitSound(snd_new_identifier);
6216     print_timestamp_time("InitSound");
6217   }
6218
6219   if (mus_new_identifier != NULL || force_reload_mus)
6220   {
6221     InitMusic(mus_new_identifier);
6222     print_timestamp_time("InitMusic");
6223   }
6224
6225   game_status = last_game_status;       /* restore current game status */
6226
6227   init_last = init;                     /* switch to new busy animation */
6228
6229 #if 0
6230   printf("::: ----------------DELAY 1 ...\n");
6231   Delay(3000);
6232 #endif
6233
6234 #if 0
6235   printf("::: FadeOut @ ReloadCustomArtwork ...\n");
6236 #endif
6237   FadeOut(REDRAW_ALL);
6238 #if 0
6239   printf("::: FadeOut @ ReloadCustomArtwork done\n");
6240 #endif
6241
6242   RedrawBackground();
6243
6244   /* force redraw of (open or closed) door graphics */
6245   SetDoorState(DOOR_OPEN_ALL);
6246   CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
6247
6248 #if 1
6249 #if 1
6250 #if 1
6251   FadeSetEnterScreen();
6252   FadeSkipNextFadeOut();
6253   // FadeSetDisabled();
6254 #else
6255   FadeSkipNext();
6256 #endif
6257 #else
6258   fading = fading_none;
6259 #endif
6260 #endif
6261
6262 #if 0
6263   redraw_mask = REDRAW_ALL;
6264 #endif
6265
6266   print_timestamp_done("ReloadCustomArtwork");
6267 }
6268
6269 void KeyboardAutoRepeatOffUnlessAutoplay()
6270 {
6271   if (global.autoplay_leveldir == NULL)
6272     KeyboardAutoRepeatOff();
6273 }
6274
6275
6276 /* ========================================================================= */
6277 /* OpenAll()                                                                 */
6278 /* ========================================================================= */
6279
6280 void OpenAll()
6281 {
6282   print_timestamp_init("OpenAll");
6283
6284   game_status = GAME_MODE_LOADING;
6285
6286 #if 1
6287   InitCounter();
6288 #endif
6289
6290   InitGlobal();                 /* initialize some global variables */
6291
6292   print_timestamp_time("[init global stuff]");
6293
6294   if (options.execute_command)
6295     Execute_Command(options.execute_command);
6296
6297   if (options.serveronly)
6298   {
6299 #if defined(PLATFORM_UNIX)
6300     NetworkServer(options.server_port, options.serveronly);
6301 #else
6302     Error(ERR_WARN, "networking only supported in Unix version");
6303 #endif
6304
6305     exit(0);                    /* never reached, server loops forever */
6306   }
6307
6308   InitSetup();
6309
6310   print_timestamp_time("[init setup/config stuff (1)]");
6311
6312   InitGameInfo();
6313   print_timestamp_time("[init setup/config stuff (2)]");
6314   InitPlayerInfo();
6315   print_timestamp_time("[init setup/config stuff (3)]");
6316   InitArtworkInfo();            /* needed before loading gfx, sound & music */
6317   print_timestamp_time("[init setup/config stuff (4)]");
6318   InitArtworkConfig();          /* needed before forking sound child process */
6319   print_timestamp_time("[init setup/config stuff (5)]");
6320   InitMixer();
6321   print_timestamp_time("[init setup/config stuff (6)]");
6322
6323 #if 0
6324   InitCounter();
6325 #endif
6326
6327   InitRND(NEW_RANDOMIZE);
6328   InitSimpleRandom(NEW_RANDOMIZE);
6329
6330   InitJoysticks();
6331
6332   print_timestamp_time("[init setup/config stuff]");
6333
6334   InitVideoDisplay();
6335   InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
6336
6337   InitEventFilter(FilterMouseMotionEvents);
6338
6339   print_timestamp_time("[init video stuff]");
6340
6341   InitElementPropertiesStatic();
6342   InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
6343   InitElementPropertiesGfxElement();
6344
6345   print_timestamp_time("[init element properties stuff]");
6346
6347   InitGfx();
6348
6349   print_timestamp_time("InitGfx");
6350
6351   InitLevelInfo();
6352   print_timestamp_time("InitLevelInfo");
6353
6354   InitLevelArtworkInfo();
6355   print_timestamp_time("InitLevelArtworkInfo");
6356
6357   InitOverrideArtwork();        /* needs to know current level directory */
6358   print_timestamp_time("InitOverrideArtwork");
6359
6360   InitImages();                 /* needs to know current level directory */
6361   print_timestamp_time("InitImages");
6362
6363   InitSound(NULL);              /* needs to know current level directory */
6364   print_timestamp_time("InitSound");
6365
6366   InitMusic(NULL);              /* needs to know current level directory */
6367   print_timestamp_time("InitMusic");
6368
6369   InitGfxBackground();
6370
6371 #if 1
6372   em_open_all();
6373 #endif
6374
6375 #if 1
6376   sp_open_all();
6377 #endif
6378
6379   if (global.autoplay_leveldir)
6380   {
6381     AutoPlayTape();
6382     return;
6383   }
6384   else if (global.convert_leveldir)
6385   {
6386     ConvertLevels();
6387     return;
6388   }
6389   else if (global.create_images_dir)
6390   {
6391     CreateLevelSketchImages();
6392     return;
6393   }
6394
6395   game_status = GAME_MODE_MAIN;
6396
6397 #if 1
6398   FadeSetEnterScreen();
6399   if (!(fading.fade_mode & FADE_TYPE_TRANSFORM))
6400     FadeSkipNextFadeOut();
6401   // FadeSetDisabled();
6402 #else
6403   fading = fading_none;
6404 #endif
6405
6406   print_timestamp_time("[post-artwork]");
6407
6408   print_timestamp_done("OpenAll");
6409
6410   DrawMainMenu();
6411
6412   InitNetworkServer();
6413 }
6414
6415 void CloseAllAndExit(int exit_value)
6416 {
6417   StopSounds();
6418   FreeAllSounds();
6419   FreeAllMusic();
6420   CloseAudio();         /* called after freeing sounds (needed for SDL) */
6421
6422 #if 1
6423   em_close_all();
6424 #endif
6425
6426 #if 1
6427   sp_close_all();
6428 #endif
6429
6430   FreeAllImages();
6431
6432 #if defined(TARGET_SDL)
6433   if (network_server)   /* terminate network server */
6434     SDL_KillThread(server_thread);
6435 #endif
6436
6437   CloseVideoDisplay();
6438   ClosePlatformDependentStuff();
6439
6440   if (exit_value != 0)
6441     NotifyUserAboutErrorFile();
6442
6443   exit(exit_value);
6444 }