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