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