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