rnd-20100202-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_STEEL_EXIT_OPENING,
2841     EL_STEEL_EXIT_CLOSING,
2842     EL_EM_STEEL_EXIT_CLOSED,
2843     EL_EM_STEEL_EXIT_OPEN,
2844     EL_EM_STEEL_EXIT_OPENING,
2845     EL_EM_STEEL_EXIT_CLOSING,
2846     EL_DC_STEELWALL_1_LEFT,
2847     EL_DC_STEELWALL_1_RIGHT,
2848     EL_DC_STEELWALL_1_TOP,
2849     EL_DC_STEELWALL_1_BOTTOM,
2850     EL_DC_STEELWALL_1_HORIZONTAL,
2851     EL_DC_STEELWALL_1_VERTICAL,
2852     EL_DC_STEELWALL_1_TOPLEFT,
2853     EL_DC_STEELWALL_1_TOPRIGHT,
2854     EL_DC_STEELWALL_1_BOTTOMLEFT,
2855     EL_DC_STEELWALL_1_BOTTOMRIGHT,
2856     EL_DC_STEELWALL_1_TOPLEFT_2,
2857     EL_DC_STEELWALL_1_TOPRIGHT_2,
2858     EL_DC_STEELWALL_1_BOTTOMLEFT_2,
2859     EL_DC_STEELWALL_1_BOTTOMRIGHT_2,
2860     EL_DC_STEELWALL_2_LEFT,
2861     EL_DC_STEELWALL_2_RIGHT,
2862     EL_DC_STEELWALL_2_TOP,
2863     EL_DC_STEELWALL_2_BOTTOM,
2864     EL_DC_STEELWALL_2_HORIZONTAL,
2865     EL_DC_STEELWALL_2_VERTICAL,
2866     EL_DC_STEELWALL_2_MIDDLE,
2867     EL_DC_STEELWALL_2_SINGLE,
2868     EL_STEELWALL_SLIPPERY,
2869     EL_EMC_STEELWALL_1,
2870     EL_EMC_STEELWALL_2,
2871     EL_EMC_STEELWALL_3,
2872     EL_EMC_STEELWALL_4,
2873     EL_CRYSTAL,
2874     EL_GATE_1,
2875     EL_GATE_2,
2876     EL_GATE_3,
2877     EL_GATE_4,
2878     EL_GATE_1_GRAY,
2879     EL_GATE_2_GRAY,
2880     EL_GATE_3_GRAY,
2881     EL_GATE_4_GRAY,
2882     EL_GATE_1_GRAY_ACTIVE,
2883     EL_GATE_2_GRAY_ACTIVE,
2884     EL_GATE_3_GRAY_ACTIVE,
2885     EL_GATE_4_GRAY_ACTIVE,
2886     EL_EM_GATE_1,
2887     EL_EM_GATE_2,
2888     EL_EM_GATE_3,
2889     EL_EM_GATE_4,
2890     EL_EM_GATE_1_GRAY,
2891     EL_EM_GATE_2_GRAY,
2892     EL_EM_GATE_3_GRAY,
2893     EL_EM_GATE_4_GRAY,
2894     EL_EM_GATE_1_GRAY_ACTIVE,
2895     EL_EM_GATE_2_GRAY_ACTIVE,
2896     EL_EM_GATE_3_GRAY_ACTIVE,
2897     EL_EM_GATE_4_GRAY_ACTIVE,
2898     EL_EMC_GATE_5,
2899     EL_EMC_GATE_6,
2900     EL_EMC_GATE_7,
2901     EL_EMC_GATE_8,
2902     EL_EMC_GATE_5_GRAY,
2903     EL_EMC_GATE_6_GRAY,
2904     EL_EMC_GATE_7_GRAY,
2905     EL_EMC_GATE_8_GRAY,
2906     EL_EMC_GATE_5_GRAY_ACTIVE,
2907     EL_EMC_GATE_6_GRAY_ACTIVE,
2908     EL_EMC_GATE_7_GRAY_ACTIVE,
2909     EL_EMC_GATE_8_GRAY_ACTIVE,
2910     EL_DC_GATE_WHITE,
2911     EL_DC_GATE_WHITE_GRAY,
2912     EL_DC_GATE_WHITE_GRAY_ACTIVE,
2913     EL_DC_GATE_FAKE_GRAY,
2914     EL_SWITCHGATE_OPEN,
2915     EL_SWITCHGATE_OPENING,
2916     EL_SWITCHGATE_CLOSED,
2917     EL_SWITCHGATE_CLOSING,
2918 #if 1
2919     EL_DC_SWITCHGATE_SWITCH_UP,
2920     EL_DC_SWITCHGATE_SWITCH_DOWN,
2921 #endif
2922     EL_TIMEGATE_OPEN,
2923     EL_TIMEGATE_OPENING,
2924     EL_TIMEGATE_CLOSED,
2925     EL_TIMEGATE_CLOSING,
2926 #if 1
2927     EL_DC_TIMEGATE_SWITCH,
2928     EL_DC_TIMEGATE_SWITCH_ACTIVE,
2929 #endif
2930     EL_TUBE_ANY,
2931     EL_TUBE_VERTICAL,
2932     EL_TUBE_HORIZONTAL,
2933     EL_TUBE_VERTICAL_LEFT,
2934     EL_TUBE_VERTICAL_RIGHT,
2935     EL_TUBE_HORIZONTAL_UP,
2936     EL_TUBE_HORIZONTAL_DOWN,
2937     EL_TUBE_LEFT_UP,
2938     EL_TUBE_LEFT_DOWN,
2939     EL_TUBE_RIGHT_UP,
2940     EL_TUBE_RIGHT_DOWN,
2941     EL_EXPANDABLE_STEELWALL_HORIZONTAL,
2942     EL_EXPANDABLE_STEELWALL_VERTICAL,
2943     EL_EXPANDABLE_STEELWALL_ANY,
2944
2945     -1
2946   };
2947
2948   static int ep_slippery[] =
2949   {
2950     EL_WALL_SLIPPERY,
2951     EL_BD_WALL,
2952     EL_ROCK,
2953     EL_BD_ROCK,
2954     EL_EMERALD,
2955     EL_BD_DIAMOND,
2956     EL_EMERALD_YELLOW,
2957     EL_EMERALD_RED,
2958     EL_EMERALD_PURPLE,
2959     EL_DIAMOND,
2960     EL_BOMB,
2961     EL_NUT,
2962     EL_ROBOT_WHEEL_ACTIVE,
2963     EL_ROBOT_WHEEL,
2964     EL_TIME_ORB_FULL,
2965     EL_TIME_ORB_EMPTY,
2966     EL_LAMP_ACTIVE,
2967     EL_LAMP,
2968     EL_ACID_POOL_TOPLEFT,
2969     EL_ACID_POOL_TOPRIGHT,
2970     EL_SATELLITE,
2971     EL_SP_ZONK,
2972     EL_SP_INFOTRON,
2973     EL_SP_CHIP_SINGLE,
2974     EL_SP_CHIP_LEFT,
2975     EL_SP_CHIP_RIGHT,
2976     EL_SP_CHIP_TOP,
2977     EL_SP_CHIP_BOTTOM,
2978     EL_SPEED_PILL,
2979     EL_STEELWALL_SLIPPERY,
2980     EL_PEARL,
2981     EL_CRYSTAL,
2982     EL_EMC_WALL_SLIPPERY_1,
2983     EL_EMC_WALL_SLIPPERY_2,
2984     EL_EMC_WALL_SLIPPERY_3,
2985     EL_EMC_WALL_SLIPPERY_4,
2986     EL_EMC_MAGIC_BALL,
2987     EL_EMC_MAGIC_BALL_ACTIVE,
2988
2989     -1
2990   };
2991
2992   static int ep_can_change[] =
2993   {
2994     -1
2995   };
2996
2997   static int ep_can_move[] =
2998   {
2999     /* same elements as in 'pb_can_move_into_acid' */
3000     EL_BUG,
3001     EL_SPACESHIP,
3002     EL_BD_BUTTERFLY,
3003     EL_BD_FIREFLY,
3004     EL_YAMYAM,
3005     EL_DARK_YAMYAM,
3006     EL_ROBOT,
3007     EL_PACMAN,
3008     EL_MOLE,
3009     EL_PENGUIN,
3010     EL_PIG,
3011     EL_DRAGON,
3012     EL_SATELLITE,
3013     EL_SP_SNIKSNAK,
3014     EL_SP_ELECTRON,
3015     EL_BALLOON,
3016     EL_SPRING,
3017     EL_EMC_ANDROID,
3018
3019     -1
3020   };
3021
3022   static int ep_can_fall[] =
3023   {
3024     EL_ROCK,
3025     EL_BD_ROCK,
3026     EL_EMERALD,
3027     EL_BD_DIAMOND,
3028     EL_EMERALD_YELLOW,
3029     EL_EMERALD_RED,
3030     EL_EMERALD_PURPLE,
3031     EL_DIAMOND,
3032     EL_BOMB,
3033     EL_NUT,
3034     EL_AMOEBA_DROP,
3035     EL_QUICKSAND_FULL,
3036     EL_QUICKSAND_FAST_FULL,
3037     EL_MAGIC_WALL_FULL,
3038     EL_BD_MAGIC_WALL_FULL,
3039     EL_DC_MAGIC_WALL_FULL,
3040     EL_TIME_ORB_FULL,
3041     EL_TIME_ORB_EMPTY,
3042     EL_SP_ZONK,
3043     EL_SP_INFOTRON,
3044     EL_SP_DISK_ORANGE,
3045     EL_PEARL,
3046     EL_CRYSTAL,
3047     EL_SPRING,
3048     EL_DX_SUPABOMB,
3049
3050     -1
3051   };
3052
3053   static int ep_can_smash_player[] =
3054   {
3055     EL_ROCK,
3056     EL_BD_ROCK,
3057     EL_EMERALD,
3058     EL_BD_DIAMOND,
3059     EL_EMERALD_YELLOW,
3060     EL_EMERALD_RED,
3061     EL_EMERALD_PURPLE,
3062     EL_DIAMOND,
3063     EL_BOMB,
3064     EL_NUT,
3065     EL_AMOEBA_DROP,
3066     EL_TIME_ORB_FULL,
3067     EL_TIME_ORB_EMPTY,
3068     EL_SP_ZONK,
3069     EL_SP_INFOTRON,
3070     EL_SP_DISK_ORANGE,
3071     EL_PEARL,
3072     EL_CRYSTAL,
3073     EL_SPRING,
3074     EL_DX_SUPABOMB,
3075
3076     -1
3077   };
3078
3079   static int ep_can_smash_enemies[] =
3080   {
3081     EL_ROCK,
3082     EL_BD_ROCK,
3083     EL_SP_ZONK,
3084
3085     -1
3086   };
3087
3088   static int ep_can_smash_everything[] =
3089   {
3090     EL_ROCK,
3091     EL_BD_ROCK,
3092     EL_SP_ZONK,
3093
3094     -1
3095   };
3096
3097   static int ep_explodes_by_fire[] =
3098   {
3099     /* same elements as in 'ep_explodes_impact' */
3100     EL_BOMB,
3101     EL_SP_DISK_ORANGE,
3102     EL_DX_SUPABOMB,
3103
3104     /* same elements as in 'ep_explodes_smashed' */
3105     EL_SATELLITE,
3106     EL_PIG,
3107     EL_DRAGON,
3108     EL_MOLE,
3109
3110     /* new elements */
3111     EL_DYNAMITE,
3112     EL_DYNAMITE_ACTIVE,
3113     EL_EM_DYNAMITE,
3114     EL_EM_DYNAMITE_ACTIVE,
3115     EL_DYNABOMB_PLAYER_1_ACTIVE,
3116     EL_DYNABOMB_PLAYER_2_ACTIVE,
3117     EL_DYNABOMB_PLAYER_3_ACTIVE,
3118     EL_DYNABOMB_PLAYER_4_ACTIVE,
3119     EL_DYNABOMB_INCREASE_NUMBER,
3120     EL_DYNABOMB_INCREASE_SIZE,
3121     EL_DYNABOMB_INCREASE_POWER,
3122     EL_SP_DISK_RED_ACTIVE,
3123     EL_BUG,
3124     EL_PENGUIN,
3125     EL_SP_DISK_RED,
3126     EL_SP_DISK_YELLOW,
3127     EL_SP_SNIKSNAK,
3128     EL_SP_ELECTRON,
3129 #if 0
3130     EL_BLACK_ORB,
3131 #endif
3132
3133     -1
3134   };
3135
3136   static int ep_explodes_smashed[] =
3137   {
3138     /* same elements as in 'ep_explodes_impact' */
3139     EL_BOMB,
3140     EL_SP_DISK_ORANGE,
3141     EL_DX_SUPABOMB,
3142
3143     /* new elements */
3144     EL_SATELLITE,
3145     EL_PIG,
3146     EL_DRAGON,
3147     EL_MOLE,
3148
3149     -1
3150   };
3151
3152   static int ep_explodes_impact[] =
3153   {
3154     EL_BOMB,
3155     EL_SP_DISK_ORANGE,
3156     EL_DX_SUPABOMB,
3157
3158     -1
3159   };
3160
3161   static int ep_walkable_over[] =
3162   {
3163     EL_EMPTY_SPACE,
3164     EL_SP_EMPTY_SPACE,
3165     EL_SOKOBAN_FIELD_EMPTY,
3166     EL_EXIT_OPEN,
3167     EL_EM_EXIT_OPEN,
3168 #if 1
3169     EL_EM_EXIT_OPENING,
3170 #endif
3171     EL_SP_EXIT_OPEN,
3172     EL_SP_EXIT_OPENING,
3173     EL_STEEL_EXIT_OPEN,
3174     EL_EM_STEEL_EXIT_OPEN,
3175 #if 1
3176     EL_EM_STEEL_EXIT_OPENING,
3177 #endif
3178     EL_GATE_1,
3179     EL_GATE_2,
3180     EL_GATE_3,
3181     EL_GATE_4,
3182     EL_GATE_1_GRAY,
3183     EL_GATE_2_GRAY,
3184     EL_GATE_3_GRAY,
3185     EL_GATE_4_GRAY,
3186     EL_GATE_1_GRAY_ACTIVE,
3187     EL_GATE_2_GRAY_ACTIVE,
3188     EL_GATE_3_GRAY_ACTIVE,
3189     EL_GATE_4_GRAY_ACTIVE,
3190     EL_PENGUIN,
3191     EL_PIG,
3192     EL_DRAGON,
3193
3194     -1
3195   };
3196
3197   static int ep_walkable_inside[] =
3198   {
3199     EL_TUBE_ANY,
3200     EL_TUBE_VERTICAL,
3201     EL_TUBE_HORIZONTAL,
3202     EL_TUBE_VERTICAL_LEFT,
3203     EL_TUBE_VERTICAL_RIGHT,
3204     EL_TUBE_HORIZONTAL_UP,
3205     EL_TUBE_HORIZONTAL_DOWN,
3206     EL_TUBE_LEFT_UP,
3207     EL_TUBE_LEFT_DOWN,
3208     EL_TUBE_RIGHT_UP,
3209     EL_TUBE_RIGHT_DOWN,
3210
3211     -1
3212   };
3213
3214   static int ep_walkable_under[] =
3215   {
3216     -1
3217   };
3218
3219   static int ep_passable_over[] =
3220   {
3221     EL_EM_GATE_1,
3222     EL_EM_GATE_2,
3223     EL_EM_GATE_3,
3224     EL_EM_GATE_4,
3225     EL_EM_GATE_1_GRAY,
3226     EL_EM_GATE_2_GRAY,
3227     EL_EM_GATE_3_GRAY,
3228     EL_EM_GATE_4_GRAY,
3229     EL_EM_GATE_1_GRAY_ACTIVE,
3230     EL_EM_GATE_2_GRAY_ACTIVE,
3231     EL_EM_GATE_3_GRAY_ACTIVE,
3232     EL_EM_GATE_4_GRAY_ACTIVE,
3233     EL_EMC_GATE_5,
3234     EL_EMC_GATE_6,
3235     EL_EMC_GATE_7,
3236     EL_EMC_GATE_8,
3237     EL_EMC_GATE_5_GRAY,
3238     EL_EMC_GATE_6_GRAY,
3239     EL_EMC_GATE_7_GRAY,
3240     EL_EMC_GATE_8_GRAY,
3241     EL_EMC_GATE_5_GRAY_ACTIVE,
3242     EL_EMC_GATE_6_GRAY_ACTIVE,
3243     EL_EMC_GATE_7_GRAY_ACTIVE,
3244     EL_EMC_GATE_8_GRAY_ACTIVE,
3245     EL_DC_GATE_WHITE,
3246     EL_DC_GATE_WHITE_GRAY,
3247     EL_DC_GATE_WHITE_GRAY_ACTIVE,
3248     EL_SWITCHGATE_OPEN,
3249     EL_TIMEGATE_OPEN,
3250
3251     -1
3252   };
3253
3254   static int ep_passable_inside[] =
3255   {
3256     EL_SP_PORT_LEFT,
3257     EL_SP_PORT_RIGHT,
3258     EL_SP_PORT_UP,
3259     EL_SP_PORT_DOWN,
3260     EL_SP_PORT_HORIZONTAL,
3261     EL_SP_PORT_VERTICAL,
3262     EL_SP_PORT_ANY,
3263     EL_SP_GRAVITY_PORT_LEFT,
3264     EL_SP_GRAVITY_PORT_RIGHT,
3265     EL_SP_GRAVITY_PORT_UP,
3266     EL_SP_GRAVITY_PORT_DOWN,
3267     EL_SP_GRAVITY_ON_PORT_LEFT,
3268     EL_SP_GRAVITY_ON_PORT_RIGHT,
3269     EL_SP_GRAVITY_ON_PORT_UP,
3270     EL_SP_GRAVITY_ON_PORT_DOWN,
3271     EL_SP_GRAVITY_OFF_PORT_LEFT,
3272     EL_SP_GRAVITY_OFF_PORT_RIGHT,
3273     EL_SP_GRAVITY_OFF_PORT_UP,
3274     EL_SP_GRAVITY_OFF_PORT_DOWN,
3275
3276     -1
3277   };
3278
3279   static int ep_passable_under[] =
3280   {
3281     -1
3282   };
3283
3284   static int ep_droppable[] =
3285   {
3286     -1
3287   };
3288
3289   static int ep_explodes_1x1_old[] =
3290   {
3291     -1
3292   };
3293
3294   static int ep_pushable[] =
3295   {
3296     EL_ROCK,
3297     EL_BOMB,
3298     EL_DX_SUPABOMB,
3299     EL_NUT,
3300     EL_TIME_ORB_EMPTY,
3301     EL_SP_ZONK,
3302     EL_SP_DISK_ORANGE,
3303     EL_SPRING,
3304     EL_BD_ROCK,
3305     EL_SOKOBAN_OBJECT,
3306     EL_SOKOBAN_FIELD_FULL,
3307     EL_SATELLITE,
3308     EL_SP_DISK_YELLOW,
3309     EL_BALLOON,
3310     EL_EMC_ANDROID,
3311
3312     -1
3313   };
3314
3315   static int ep_explodes_cross_old[] =
3316   {
3317     -1
3318   };
3319
3320   static int ep_protected[] =
3321   {
3322     /* same elements as in 'ep_walkable_inside' */
3323     EL_TUBE_ANY,
3324     EL_TUBE_VERTICAL,
3325     EL_TUBE_HORIZONTAL,
3326     EL_TUBE_VERTICAL_LEFT,
3327     EL_TUBE_VERTICAL_RIGHT,
3328     EL_TUBE_HORIZONTAL_UP,
3329     EL_TUBE_HORIZONTAL_DOWN,
3330     EL_TUBE_LEFT_UP,
3331     EL_TUBE_LEFT_DOWN,
3332     EL_TUBE_RIGHT_UP,
3333     EL_TUBE_RIGHT_DOWN,
3334
3335     /* same elements as in 'ep_passable_over' */
3336     EL_EM_GATE_1,
3337     EL_EM_GATE_2,
3338     EL_EM_GATE_3,
3339     EL_EM_GATE_4,
3340     EL_EM_GATE_1_GRAY,
3341     EL_EM_GATE_2_GRAY,
3342     EL_EM_GATE_3_GRAY,
3343     EL_EM_GATE_4_GRAY,
3344     EL_EM_GATE_1_GRAY_ACTIVE,
3345     EL_EM_GATE_2_GRAY_ACTIVE,
3346     EL_EM_GATE_3_GRAY_ACTIVE,
3347     EL_EM_GATE_4_GRAY_ACTIVE,
3348     EL_EMC_GATE_5,
3349     EL_EMC_GATE_6,
3350     EL_EMC_GATE_7,
3351     EL_EMC_GATE_8,
3352     EL_EMC_GATE_5_GRAY,
3353     EL_EMC_GATE_6_GRAY,
3354     EL_EMC_GATE_7_GRAY,
3355     EL_EMC_GATE_8_GRAY,
3356     EL_EMC_GATE_5_GRAY_ACTIVE,
3357     EL_EMC_GATE_6_GRAY_ACTIVE,
3358     EL_EMC_GATE_7_GRAY_ACTIVE,
3359     EL_EMC_GATE_8_GRAY_ACTIVE,
3360     EL_DC_GATE_WHITE,
3361     EL_DC_GATE_WHITE_GRAY,
3362     EL_DC_GATE_WHITE_GRAY_ACTIVE,
3363     EL_SWITCHGATE_OPEN,
3364     EL_TIMEGATE_OPEN,
3365
3366     /* same elements as in 'ep_passable_inside' */
3367     EL_SP_PORT_LEFT,
3368     EL_SP_PORT_RIGHT,
3369     EL_SP_PORT_UP,
3370     EL_SP_PORT_DOWN,
3371     EL_SP_PORT_HORIZONTAL,
3372     EL_SP_PORT_VERTICAL,
3373     EL_SP_PORT_ANY,
3374     EL_SP_GRAVITY_PORT_LEFT,
3375     EL_SP_GRAVITY_PORT_RIGHT,
3376     EL_SP_GRAVITY_PORT_UP,
3377     EL_SP_GRAVITY_PORT_DOWN,
3378     EL_SP_GRAVITY_ON_PORT_LEFT,
3379     EL_SP_GRAVITY_ON_PORT_RIGHT,
3380     EL_SP_GRAVITY_ON_PORT_UP,
3381     EL_SP_GRAVITY_ON_PORT_DOWN,
3382     EL_SP_GRAVITY_OFF_PORT_LEFT,
3383     EL_SP_GRAVITY_OFF_PORT_RIGHT,
3384     EL_SP_GRAVITY_OFF_PORT_UP,
3385     EL_SP_GRAVITY_OFF_PORT_DOWN,
3386
3387     -1
3388   };
3389
3390   static int ep_throwable[] =
3391   {
3392     -1
3393   };
3394
3395   static int ep_can_explode[] =
3396   {
3397     /* same elements as in 'ep_explodes_impact' */
3398     EL_BOMB,
3399     EL_SP_DISK_ORANGE,
3400     EL_DX_SUPABOMB,
3401
3402     /* same elements as in 'ep_explodes_smashed' */
3403     EL_SATELLITE,
3404     EL_PIG,
3405     EL_DRAGON,
3406     EL_MOLE,
3407
3408     /* elements that can explode by explosion or by dragonfire */
3409     EL_DYNAMITE,
3410     EL_DYNAMITE_ACTIVE,
3411     EL_EM_DYNAMITE,
3412     EL_EM_DYNAMITE_ACTIVE,
3413     EL_DYNABOMB_PLAYER_1_ACTIVE,
3414     EL_DYNABOMB_PLAYER_2_ACTIVE,
3415     EL_DYNABOMB_PLAYER_3_ACTIVE,
3416     EL_DYNABOMB_PLAYER_4_ACTIVE,
3417     EL_DYNABOMB_INCREASE_NUMBER,
3418     EL_DYNABOMB_INCREASE_SIZE,
3419     EL_DYNABOMB_INCREASE_POWER,
3420     EL_SP_DISK_RED_ACTIVE,
3421     EL_BUG,
3422     EL_PENGUIN,
3423     EL_SP_DISK_RED,
3424     EL_SP_DISK_YELLOW,
3425     EL_SP_SNIKSNAK,
3426     EL_SP_ELECTRON,
3427
3428     /* elements that can explode only by explosion */
3429     EL_BLACK_ORB,
3430
3431     -1
3432   };
3433
3434   static int ep_gravity_reachable[] =
3435   {
3436     EL_SAND,
3437     EL_SP_BASE,
3438     EL_TRAP,
3439     EL_INVISIBLE_SAND,
3440     EL_INVISIBLE_SAND_ACTIVE,
3441     EL_SP_PORT_LEFT,
3442     EL_SP_PORT_RIGHT,
3443     EL_SP_PORT_UP,
3444     EL_SP_PORT_DOWN,
3445     EL_SP_PORT_HORIZONTAL,
3446     EL_SP_PORT_VERTICAL,
3447     EL_SP_PORT_ANY,
3448     EL_SP_GRAVITY_PORT_LEFT,
3449     EL_SP_GRAVITY_PORT_RIGHT,
3450     EL_SP_GRAVITY_PORT_UP,
3451     EL_SP_GRAVITY_PORT_DOWN,
3452     EL_SP_GRAVITY_ON_PORT_LEFT,
3453     EL_SP_GRAVITY_ON_PORT_RIGHT,
3454     EL_SP_GRAVITY_ON_PORT_UP,
3455     EL_SP_GRAVITY_ON_PORT_DOWN,
3456     EL_SP_GRAVITY_OFF_PORT_LEFT,
3457     EL_SP_GRAVITY_OFF_PORT_RIGHT,
3458     EL_SP_GRAVITY_OFF_PORT_UP,
3459     EL_SP_GRAVITY_OFF_PORT_DOWN,
3460     EL_EMC_GRASS,
3461
3462     -1
3463   };
3464
3465   static int ep_player[] =
3466   {
3467     EL_PLAYER_1,
3468     EL_PLAYER_2,
3469     EL_PLAYER_3,
3470     EL_PLAYER_4,
3471     EL_SP_MURPHY,
3472     EL_SOKOBAN_FIELD_PLAYER,
3473     EL_TRIGGER_PLAYER,
3474
3475     -1
3476   };
3477
3478   static int ep_can_pass_magic_wall[] =
3479   {
3480     EL_ROCK,
3481     EL_BD_ROCK,
3482     EL_EMERALD,
3483     EL_BD_DIAMOND,
3484     EL_EMERALD_YELLOW,
3485     EL_EMERALD_RED,
3486     EL_EMERALD_PURPLE,
3487     EL_DIAMOND,
3488
3489     -1
3490   };
3491
3492   static int ep_can_pass_dc_magic_wall[] =
3493   {
3494     EL_ROCK,
3495     EL_BD_ROCK,
3496     EL_EMERALD,
3497     EL_BD_DIAMOND,
3498     EL_EMERALD_YELLOW,
3499     EL_EMERALD_RED,
3500     EL_EMERALD_PURPLE,
3501     EL_DIAMOND,
3502     EL_PEARL,
3503     EL_CRYSTAL,
3504
3505     -1
3506   };
3507
3508   static int ep_switchable[] =
3509   {
3510     EL_ROBOT_WHEEL,
3511     EL_SP_TERMINAL,
3512     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3513     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3514     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3515     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3516     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3517     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3518     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3519     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3520     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3521     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3522     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3523     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3524     EL_SWITCHGATE_SWITCH_UP,
3525     EL_SWITCHGATE_SWITCH_DOWN,
3526     EL_DC_SWITCHGATE_SWITCH_UP,
3527     EL_DC_SWITCHGATE_SWITCH_DOWN,
3528     EL_LIGHT_SWITCH,
3529     EL_LIGHT_SWITCH_ACTIVE,
3530     EL_TIMEGATE_SWITCH,
3531     EL_DC_TIMEGATE_SWITCH,
3532     EL_BALLOON_SWITCH_LEFT,
3533     EL_BALLOON_SWITCH_RIGHT,
3534     EL_BALLOON_SWITCH_UP,
3535     EL_BALLOON_SWITCH_DOWN,
3536     EL_BALLOON_SWITCH_ANY,
3537     EL_BALLOON_SWITCH_NONE,
3538     EL_LAMP,
3539     EL_TIME_ORB_FULL,
3540     EL_EMC_MAGIC_BALL_SWITCH,
3541     EL_EMC_MAGIC_BALL_SWITCH_ACTIVE,
3542
3543     -1
3544   };
3545
3546   static int ep_bd_element[] =
3547   {
3548     EL_EMPTY,
3549     EL_SAND,
3550     EL_WALL_SLIPPERY,
3551     EL_BD_WALL,
3552     EL_ROCK,
3553     EL_BD_ROCK,
3554     EL_BD_DIAMOND,
3555     EL_BD_MAGIC_WALL,
3556     EL_EXIT_CLOSED,
3557     EL_EXIT_OPEN,
3558     EL_STEELWALL,
3559     EL_PLAYER_1,
3560     EL_PLAYER_2,
3561     EL_PLAYER_3,
3562     EL_PLAYER_4,
3563     EL_BD_FIREFLY,
3564     EL_BD_FIREFLY_1,
3565     EL_BD_FIREFLY_2,
3566     EL_BD_FIREFLY_3,
3567     EL_BD_FIREFLY_4,
3568     EL_BD_BUTTERFLY,
3569     EL_BD_BUTTERFLY_1,
3570     EL_BD_BUTTERFLY_2,
3571     EL_BD_BUTTERFLY_3,
3572     EL_BD_BUTTERFLY_4,
3573     EL_BD_AMOEBA,
3574     EL_CHAR_QUESTION,
3575     EL_UNKNOWN,
3576
3577     -1
3578   };
3579
3580   static int ep_sp_element[] =
3581   {
3582     /* should always be valid */
3583     EL_EMPTY,
3584
3585     /* standard classic Supaplex elements */
3586     EL_SP_EMPTY,
3587     EL_SP_ZONK,
3588     EL_SP_BASE,
3589     EL_SP_MURPHY,
3590     EL_SP_INFOTRON,
3591     EL_SP_CHIP_SINGLE,
3592     EL_SP_HARDWARE_GRAY,
3593     EL_SP_EXIT_CLOSED,
3594     EL_SP_EXIT_OPEN,
3595     EL_SP_DISK_ORANGE,
3596     EL_SP_PORT_RIGHT,
3597     EL_SP_PORT_DOWN,
3598     EL_SP_PORT_LEFT,
3599     EL_SP_PORT_UP,
3600     EL_SP_GRAVITY_PORT_RIGHT,
3601     EL_SP_GRAVITY_PORT_DOWN,
3602     EL_SP_GRAVITY_PORT_LEFT,
3603     EL_SP_GRAVITY_PORT_UP,
3604     EL_SP_SNIKSNAK,
3605     EL_SP_DISK_YELLOW,
3606     EL_SP_TERMINAL,
3607     EL_SP_DISK_RED,
3608     EL_SP_PORT_VERTICAL,
3609     EL_SP_PORT_HORIZONTAL,
3610     EL_SP_PORT_ANY,
3611     EL_SP_ELECTRON,
3612     EL_SP_BUGGY_BASE,
3613     EL_SP_CHIP_LEFT,
3614     EL_SP_CHIP_RIGHT,
3615     EL_SP_HARDWARE_BASE_1,
3616     EL_SP_HARDWARE_GREEN,
3617     EL_SP_HARDWARE_BLUE,
3618     EL_SP_HARDWARE_RED,
3619     EL_SP_HARDWARE_YELLOW,
3620     EL_SP_HARDWARE_BASE_2,
3621     EL_SP_HARDWARE_BASE_3,
3622     EL_SP_HARDWARE_BASE_4,
3623     EL_SP_HARDWARE_BASE_5,
3624     EL_SP_HARDWARE_BASE_6,
3625     EL_SP_CHIP_TOP,
3626     EL_SP_CHIP_BOTTOM,
3627
3628     /* additional elements that appeared in newer Supaplex levels */
3629     EL_INVISIBLE_WALL,
3630
3631     /* additional gravity port elements (not switching, but setting gravity) */
3632     EL_SP_GRAVITY_ON_PORT_LEFT,
3633     EL_SP_GRAVITY_ON_PORT_RIGHT,
3634     EL_SP_GRAVITY_ON_PORT_UP,
3635     EL_SP_GRAVITY_ON_PORT_DOWN,
3636     EL_SP_GRAVITY_OFF_PORT_LEFT,
3637     EL_SP_GRAVITY_OFF_PORT_RIGHT,
3638     EL_SP_GRAVITY_OFF_PORT_UP,
3639     EL_SP_GRAVITY_OFF_PORT_DOWN,
3640
3641     /* more than one Murphy in a level results in an inactive clone */
3642     EL_SP_MURPHY_CLONE,
3643
3644     /* runtime Supaplex elements */
3645     EL_SP_DISK_RED_ACTIVE,
3646     EL_SP_TERMINAL_ACTIVE,
3647     EL_SP_BUGGY_BASE_ACTIVATING,
3648     EL_SP_BUGGY_BASE_ACTIVE,
3649     EL_SP_EXIT_OPENING,
3650     EL_SP_EXIT_CLOSING,
3651
3652     -1
3653   };
3654
3655   static int ep_sb_element[] =
3656   {
3657     EL_EMPTY,
3658     EL_STEELWALL,
3659     EL_SOKOBAN_OBJECT,
3660     EL_SOKOBAN_FIELD_EMPTY,
3661     EL_SOKOBAN_FIELD_FULL,
3662     EL_SOKOBAN_FIELD_PLAYER,
3663     EL_PLAYER_1,
3664     EL_PLAYER_2,
3665     EL_PLAYER_3,
3666     EL_PLAYER_4,
3667     EL_INVISIBLE_STEELWALL,
3668
3669     -1
3670   };
3671
3672   static int ep_gem[] =
3673   {
3674     EL_BD_DIAMOND,
3675     EL_EMERALD,
3676     EL_EMERALD_YELLOW,
3677     EL_EMERALD_RED,
3678     EL_EMERALD_PURPLE,
3679     EL_DIAMOND,
3680
3681     -1
3682   };
3683
3684   static int ep_food_dark_yamyam[] =
3685   {
3686     EL_SAND,
3687     EL_BUG,
3688     EL_SPACESHIP,
3689     EL_BD_BUTTERFLY,
3690     EL_BD_FIREFLY,
3691     EL_YAMYAM,
3692     EL_ROBOT,
3693     EL_PACMAN,
3694     EL_AMOEBA_DROP,
3695     EL_AMOEBA_DEAD,
3696     EL_AMOEBA_WET,
3697     EL_AMOEBA_DRY,
3698     EL_AMOEBA_FULL,
3699     EL_BD_AMOEBA,
3700     EL_EMERALD,
3701     EL_BD_DIAMOND,
3702     EL_EMERALD_YELLOW,
3703     EL_EMERALD_RED,
3704     EL_EMERALD_PURPLE,
3705     EL_DIAMOND,
3706     EL_PEARL,
3707     EL_CRYSTAL,
3708
3709     -1
3710   };
3711
3712   static int ep_food_penguin[] =
3713   {
3714     EL_EMERALD,
3715     EL_BD_DIAMOND,
3716     EL_EMERALD_YELLOW,
3717     EL_EMERALD_RED,
3718     EL_EMERALD_PURPLE,
3719     EL_DIAMOND,
3720     EL_PEARL,
3721     EL_CRYSTAL,
3722
3723     -1
3724   };
3725
3726   static int ep_food_pig[] =
3727   {
3728     EL_EMERALD,
3729     EL_BD_DIAMOND,
3730     EL_EMERALD_YELLOW,
3731     EL_EMERALD_RED,
3732     EL_EMERALD_PURPLE,
3733     EL_DIAMOND,
3734
3735     -1
3736   };
3737
3738   static int ep_historic_wall[] =
3739   {
3740     EL_STEELWALL,
3741     EL_GATE_1,
3742     EL_GATE_2,
3743     EL_GATE_3,
3744     EL_GATE_4,
3745     EL_GATE_1_GRAY,
3746     EL_GATE_2_GRAY,
3747     EL_GATE_3_GRAY,
3748     EL_GATE_4_GRAY,
3749     EL_GATE_1_GRAY_ACTIVE,
3750     EL_GATE_2_GRAY_ACTIVE,
3751     EL_GATE_3_GRAY_ACTIVE,
3752     EL_GATE_4_GRAY_ACTIVE,
3753     EL_EM_GATE_1,
3754     EL_EM_GATE_2,
3755     EL_EM_GATE_3,
3756     EL_EM_GATE_4,
3757     EL_EM_GATE_1_GRAY,
3758     EL_EM_GATE_2_GRAY,
3759     EL_EM_GATE_3_GRAY,
3760     EL_EM_GATE_4_GRAY,
3761     EL_EM_GATE_1_GRAY_ACTIVE,
3762     EL_EM_GATE_2_GRAY_ACTIVE,
3763     EL_EM_GATE_3_GRAY_ACTIVE,
3764     EL_EM_GATE_4_GRAY_ACTIVE,
3765     EL_EXIT_CLOSED,
3766     EL_EXIT_OPENING,
3767     EL_EXIT_OPEN,
3768     EL_WALL,
3769     EL_WALL_SLIPPERY,
3770     EL_EXPANDABLE_WALL,
3771     EL_EXPANDABLE_WALL_HORIZONTAL,
3772     EL_EXPANDABLE_WALL_VERTICAL,
3773     EL_EXPANDABLE_WALL_ANY,
3774     EL_EXPANDABLE_WALL_GROWING,
3775     EL_BD_EXPANDABLE_WALL,
3776     EL_BD_WALL,
3777     EL_SP_CHIP_SINGLE,
3778     EL_SP_CHIP_LEFT,
3779     EL_SP_CHIP_RIGHT,
3780     EL_SP_CHIP_TOP,
3781     EL_SP_CHIP_BOTTOM,
3782     EL_SP_HARDWARE_GRAY,
3783     EL_SP_HARDWARE_GREEN,
3784     EL_SP_HARDWARE_BLUE,
3785     EL_SP_HARDWARE_RED,
3786     EL_SP_HARDWARE_YELLOW,
3787     EL_SP_HARDWARE_BASE_1,
3788     EL_SP_HARDWARE_BASE_2,
3789     EL_SP_HARDWARE_BASE_3,
3790     EL_SP_HARDWARE_BASE_4,
3791     EL_SP_HARDWARE_BASE_5,
3792     EL_SP_HARDWARE_BASE_6,
3793     EL_SP_TERMINAL,
3794     EL_SP_TERMINAL_ACTIVE,
3795     EL_SP_EXIT_CLOSED,
3796     EL_SP_EXIT_OPEN,
3797     EL_INVISIBLE_STEELWALL,
3798     EL_INVISIBLE_STEELWALL_ACTIVE,
3799     EL_INVISIBLE_WALL,
3800     EL_INVISIBLE_WALL_ACTIVE,
3801     EL_STEELWALL_SLIPPERY,
3802     EL_EMC_STEELWALL_1,
3803     EL_EMC_STEELWALL_2,
3804     EL_EMC_STEELWALL_3,
3805     EL_EMC_STEELWALL_4,
3806     EL_EMC_WALL_1,
3807     EL_EMC_WALL_2,
3808     EL_EMC_WALL_3,
3809     EL_EMC_WALL_4,
3810     EL_EMC_WALL_5,
3811     EL_EMC_WALL_6,
3812     EL_EMC_WALL_7,
3813     EL_EMC_WALL_8,
3814
3815     -1
3816   };
3817
3818   static int ep_historic_solid[] =
3819   {
3820     EL_WALL,
3821     EL_EXPANDABLE_WALL,
3822     EL_EXPANDABLE_WALL_HORIZONTAL,
3823     EL_EXPANDABLE_WALL_VERTICAL,
3824     EL_EXPANDABLE_WALL_ANY,
3825     EL_BD_EXPANDABLE_WALL,
3826     EL_BD_WALL,
3827     EL_WALL_SLIPPERY,
3828     EL_EXIT_CLOSED,
3829     EL_EXIT_OPENING,
3830     EL_EXIT_OPEN,
3831     EL_AMOEBA_DEAD,
3832     EL_AMOEBA_WET,
3833     EL_AMOEBA_DRY,
3834     EL_AMOEBA_FULL,
3835     EL_BD_AMOEBA,
3836     EL_QUICKSAND_EMPTY,
3837     EL_QUICKSAND_FULL,
3838     EL_QUICKSAND_FILLING,
3839     EL_QUICKSAND_EMPTYING,
3840     EL_MAGIC_WALL,
3841     EL_MAGIC_WALL_ACTIVE,
3842     EL_MAGIC_WALL_EMPTYING,
3843     EL_MAGIC_WALL_FILLING,
3844     EL_MAGIC_WALL_FULL,
3845     EL_MAGIC_WALL_DEAD,
3846     EL_BD_MAGIC_WALL,
3847     EL_BD_MAGIC_WALL_ACTIVE,
3848     EL_BD_MAGIC_WALL_EMPTYING,
3849     EL_BD_MAGIC_WALL_FULL,
3850     EL_BD_MAGIC_WALL_FILLING,
3851     EL_BD_MAGIC_WALL_DEAD,
3852     EL_GAME_OF_LIFE,
3853     EL_BIOMAZE,
3854     EL_SP_CHIP_SINGLE,
3855     EL_SP_CHIP_LEFT,
3856     EL_SP_CHIP_RIGHT,
3857     EL_SP_CHIP_TOP,
3858     EL_SP_CHIP_BOTTOM,
3859     EL_SP_TERMINAL,
3860     EL_SP_TERMINAL_ACTIVE,
3861     EL_SP_EXIT_CLOSED,
3862     EL_SP_EXIT_OPEN,
3863     EL_INVISIBLE_WALL,
3864     EL_INVISIBLE_WALL_ACTIVE,
3865     EL_SWITCHGATE_SWITCH_UP,
3866     EL_SWITCHGATE_SWITCH_DOWN,
3867     EL_DC_SWITCHGATE_SWITCH_UP,
3868     EL_DC_SWITCHGATE_SWITCH_DOWN,
3869     EL_TIMEGATE_SWITCH,
3870     EL_TIMEGATE_SWITCH_ACTIVE,
3871     EL_DC_TIMEGATE_SWITCH,
3872     EL_DC_TIMEGATE_SWITCH_ACTIVE,
3873     EL_EMC_WALL_1,
3874     EL_EMC_WALL_2,
3875     EL_EMC_WALL_3,
3876     EL_EMC_WALL_4,
3877     EL_EMC_WALL_5,
3878     EL_EMC_WALL_6,
3879     EL_EMC_WALL_7,
3880     EL_EMC_WALL_8,
3881     EL_WALL_PEARL,
3882     EL_WALL_CRYSTAL,
3883
3884     /* the following elements are a direct copy of "indestructible" elements,
3885        except "EL_ACID", which is "indestructible", but not "solid"! */
3886 #if 0
3887     EL_ACID,
3888 #endif
3889     EL_STEELWALL,
3890     EL_ACID_POOL_TOPLEFT,
3891     EL_ACID_POOL_TOPRIGHT,
3892     EL_ACID_POOL_BOTTOMLEFT,
3893     EL_ACID_POOL_BOTTOM,
3894     EL_ACID_POOL_BOTTOMRIGHT,
3895     EL_SP_HARDWARE_GRAY,
3896     EL_SP_HARDWARE_GREEN,
3897     EL_SP_HARDWARE_BLUE,
3898     EL_SP_HARDWARE_RED,
3899     EL_SP_HARDWARE_YELLOW,
3900     EL_SP_HARDWARE_BASE_1,
3901     EL_SP_HARDWARE_BASE_2,
3902     EL_SP_HARDWARE_BASE_3,
3903     EL_SP_HARDWARE_BASE_4,
3904     EL_SP_HARDWARE_BASE_5,
3905     EL_SP_HARDWARE_BASE_6,
3906     EL_INVISIBLE_STEELWALL,
3907     EL_INVISIBLE_STEELWALL_ACTIVE,
3908     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3909     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3910     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3911     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3912     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3913     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3914     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3915     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3916     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3917     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3918     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3919     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3920     EL_LIGHT_SWITCH,
3921     EL_LIGHT_SWITCH_ACTIVE,
3922     EL_SIGN_EXCLAMATION,
3923     EL_SIGN_RADIOACTIVITY,
3924     EL_SIGN_STOP,
3925     EL_SIGN_WHEELCHAIR,
3926     EL_SIGN_PARKING,
3927     EL_SIGN_NO_ENTRY,
3928     EL_SIGN_UNUSED_1,
3929     EL_SIGN_GIVE_WAY,
3930     EL_SIGN_ENTRY_FORBIDDEN,
3931     EL_SIGN_EMERGENCY_EXIT,
3932     EL_SIGN_YIN_YANG,
3933     EL_SIGN_UNUSED_2,
3934     EL_SIGN_SPERMS,
3935     EL_SIGN_BULLET,
3936     EL_SIGN_HEART,
3937     EL_SIGN_CROSS,
3938     EL_SIGN_FRANKIE,
3939     EL_STEEL_EXIT_CLOSED,
3940     EL_STEEL_EXIT_OPEN,
3941     EL_DC_STEELWALL_1_LEFT,
3942     EL_DC_STEELWALL_1_RIGHT,
3943     EL_DC_STEELWALL_1_TOP,
3944     EL_DC_STEELWALL_1_BOTTOM,
3945     EL_DC_STEELWALL_1_HORIZONTAL,
3946     EL_DC_STEELWALL_1_VERTICAL,
3947     EL_DC_STEELWALL_1_TOPLEFT,
3948     EL_DC_STEELWALL_1_TOPRIGHT,
3949     EL_DC_STEELWALL_1_BOTTOMLEFT,
3950     EL_DC_STEELWALL_1_BOTTOMRIGHT,
3951     EL_DC_STEELWALL_1_TOPLEFT_2,
3952     EL_DC_STEELWALL_1_TOPRIGHT_2,
3953     EL_DC_STEELWALL_1_BOTTOMLEFT_2,
3954     EL_DC_STEELWALL_1_BOTTOMRIGHT_2,
3955     EL_DC_STEELWALL_2_LEFT,
3956     EL_DC_STEELWALL_2_RIGHT,
3957     EL_DC_STEELWALL_2_TOP,
3958     EL_DC_STEELWALL_2_BOTTOM,
3959     EL_DC_STEELWALL_2_HORIZONTAL,
3960     EL_DC_STEELWALL_2_VERTICAL,
3961     EL_DC_STEELWALL_2_MIDDLE,
3962     EL_DC_STEELWALL_2_SINGLE,
3963     EL_STEELWALL_SLIPPERY,
3964     EL_EMC_STEELWALL_1,
3965     EL_EMC_STEELWALL_2,
3966     EL_EMC_STEELWALL_3,
3967     EL_EMC_STEELWALL_4,
3968     EL_CRYSTAL,
3969     EL_GATE_1,
3970     EL_GATE_2,
3971     EL_GATE_3,
3972     EL_GATE_4,
3973     EL_GATE_1_GRAY,
3974     EL_GATE_2_GRAY,
3975     EL_GATE_3_GRAY,
3976     EL_GATE_4_GRAY,
3977     EL_GATE_1_GRAY_ACTIVE,
3978     EL_GATE_2_GRAY_ACTIVE,
3979     EL_GATE_3_GRAY_ACTIVE,
3980     EL_GATE_4_GRAY_ACTIVE,
3981     EL_EM_GATE_1,
3982     EL_EM_GATE_2,
3983     EL_EM_GATE_3,
3984     EL_EM_GATE_4,
3985     EL_EM_GATE_1_GRAY,
3986     EL_EM_GATE_2_GRAY,
3987     EL_EM_GATE_3_GRAY,
3988     EL_EM_GATE_4_GRAY,
3989     EL_EM_GATE_1_GRAY_ACTIVE,
3990     EL_EM_GATE_2_GRAY_ACTIVE,
3991     EL_EM_GATE_3_GRAY_ACTIVE,
3992     EL_EM_GATE_4_GRAY_ACTIVE,
3993     EL_SWITCHGATE_OPEN,
3994     EL_SWITCHGATE_OPENING,
3995     EL_SWITCHGATE_CLOSED,
3996     EL_SWITCHGATE_CLOSING,
3997     EL_TIMEGATE_OPEN,
3998     EL_TIMEGATE_OPENING,
3999     EL_TIMEGATE_CLOSED,
4000     EL_TIMEGATE_CLOSING,
4001     EL_TUBE_ANY,
4002     EL_TUBE_VERTICAL,
4003     EL_TUBE_HORIZONTAL,
4004     EL_TUBE_VERTICAL_LEFT,
4005     EL_TUBE_VERTICAL_RIGHT,
4006     EL_TUBE_HORIZONTAL_UP,
4007     EL_TUBE_HORIZONTAL_DOWN,
4008     EL_TUBE_LEFT_UP,
4009     EL_TUBE_LEFT_DOWN,
4010     EL_TUBE_RIGHT_UP,
4011     EL_TUBE_RIGHT_DOWN,
4012
4013     -1
4014   };
4015
4016   static int ep_classic_enemy[] =
4017   {
4018     EL_BUG,
4019     EL_SPACESHIP,
4020     EL_BD_BUTTERFLY,
4021     EL_BD_FIREFLY,
4022
4023     EL_YAMYAM,
4024     EL_DARK_YAMYAM,
4025     EL_ROBOT,
4026     EL_PACMAN,
4027     EL_SP_SNIKSNAK,
4028     EL_SP_ELECTRON,
4029
4030     -1
4031   };
4032
4033   static int ep_belt[] =
4034   {
4035     EL_CONVEYOR_BELT_1_LEFT,
4036     EL_CONVEYOR_BELT_1_MIDDLE,
4037     EL_CONVEYOR_BELT_1_RIGHT,
4038     EL_CONVEYOR_BELT_2_LEFT,
4039     EL_CONVEYOR_BELT_2_MIDDLE,
4040     EL_CONVEYOR_BELT_2_RIGHT,
4041     EL_CONVEYOR_BELT_3_LEFT,
4042     EL_CONVEYOR_BELT_3_MIDDLE,
4043     EL_CONVEYOR_BELT_3_RIGHT,
4044     EL_CONVEYOR_BELT_4_LEFT,
4045     EL_CONVEYOR_BELT_4_MIDDLE,
4046     EL_CONVEYOR_BELT_4_RIGHT,
4047
4048     -1
4049   };
4050
4051   static int ep_belt_active[] =
4052   {
4053     EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
4054     EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE,
4055     EL_CONVEYOR_BELT_1_RIGHT_ACTIVE,
4056     EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
4057     EL_CONVEYOR_BELT_2_MIDDLE_ACTIVE,
4058     EL_CONVEYOR_BELT_2_RIGHT_ACTIVE,
4059     EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
4060     EL_CONVEYOR_BELT_3_MIDDLE_ACTIVE,
4061     EL_CONVEYOR_BELT_3_RIGHT_ACTIVE,
4062     EL_CONVEYOR_BELT_4_LEFT_ACTIVE,
4063     EL_CONVEYOR_BELT_4_MIDDLE_ACTIVE,
4064     EL_CONVEYOR_BELT_4_RIGHT_ACTIVE,
4065
4066     -1
4067   };
4068
4069   static int ep_belt_switch[] =
4070   {
4071     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
4072     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
4073     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
4074     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
4075     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
4076     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
4077     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
4078     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
4079     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
4080     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
4081     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
4082     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
4083
4084     -1
4085   };
4086
4087   static int ep_tube[] =
4088   {
4089     EL_TUBE_LEFT_UP,
4090     EL_TUBE_LEFT_DOWN,
4091     EL_TUBE_RIGHT_UP,
4092     EL_TUBE_RIGHT_DOWN,
4093     EL_TUBE_HORIZONTAL,
4094     EL_TUBE_HORIZONTAL_UP,
4095     EL_TUBE_HORIZONTAL_DOWN,
4096     EL_TUBE_VERTICAL,
4097     EL_TUBE_VERTICAL_LEFT,
4098     EL_TUBE_VERTICAL_RIGHT,
4099     EL_TUBE_ANY,
4100
4101     -1
4102   };
4103
4104   static int ep_acid_pool[] =
4105   {
4106     EL_ACID_POOL_TOPLEFT,
4107     EL_ACID_POOL_TOPRIGHT,
4108     EL_ACID_POOL_BOTTOMLEFT,
4109     EL_ACID_POOL_BOTTOM,
4110     EL_ACID_POOL_BOTTOMRIGHT,
4111
4112     -1
4113   };
4114
4115   static int ep_keygate[] =
4116   {
4117     EL_GATE_1,
4118     EL_GATE_2,
4119     EL_GATE_3,
4120     EL_GATE_4,
4121     EL_GATE_1_GRAY,
4122     EL_GATE_2_GRAY,
4123     EL_GATE_3_GRAY,
4124     EL_GATE_4_GRAY,
4125     EL_GATE_1_GRAY_ACTIVE,
4126     EL_GATE_2_GRAY_ACTIVE,
4127     EL_GATE_3_GRAY_ACTIVE,
4128     EL_GATE_4_GRAY_ACTIVE,
4129     EL_EM_GATE_1,
4130     EL_EM_GATE_2,
4131     EL_EM_GATE_3,
4132     EL_EM_GATE_4,
4133     EL_EM_GATE_1_GRAY,
4134     EL_EM_GATE_2_GRAY,
4135     EL_EM_GATE_3_GRAY,
4136     EL_EM_GATE_4_GRAY,
4137     EL_EM_GATE_1_GRAY_ACTIVE,
4138     EL_EM_GATE_2_GRAY_ACTIVE,
4139     EL_EM_GATE_3_GRAY_ACTIVE,
4140     EL_EM_GATE_4_GRAY_ACTIVE,
4141     EL_EMC_GATE_5,
4142     EL_EMC_GATE_6,
4143     EL_EMC_GATE_7,
4144     EL_EMC_GATE_8,
4145     EL_EMC_GATE_5_GRAY,
4146     EL_EMC_GATE_6_GRAY,
4147     EL_EMC_GATE_7_GRAY,
4148     EL_EMC_GATE_8_GRAY,
4149     EL_EMC_GATE_5_GRAY_ACTIVE,
4150     EL_EMC_GATE_6_GRAY_ACTIVE,
4151     EL_EMC_GATE_7_GRAY_ACTIVE,
4152     EL_EMC_GATE_8_GRAY_ACTIVE,
4153     EL_DC_GATE_WHITE,
4154     EL_DC_GATE_WHITE_GRAY,
4155     EL_DC_GATE_WHITE_GRAY_ACTIVE,
4156
4157     -1
4158   };
4159
4160   static int ep_amoeboid[] =
4161   {
4162     EL_AMOEBA_DEAD,
4163     EL_AMOEBA_WET,
4164     EL_AMOEBA_DRY,
4165     EL_AMOEBA_FULL,
4166     EL_BD_AMOEBA,
4167     EL_EMC_DRIPPER,
4168
4169     -1
4170   };
4171
4172   static int ep_amoebalive[] =
4173   {
4174     EL_AMOEBA_WET,
4175     EL_AMOEBA_DRY,
4176     EL_AMOEBA_FULL,
4177     EL_BD_AMOEBA,
4178     EL_EMC_DRIPPER,
4179
4180     -1
4181   };
4182
4183   static int ep_has_editor_content[] =
4184   {
4185     EL_PLAYER_1,
4186     EL_PLAYER_2,
4187     EL_PLAYER_3,
4188     EL_PLAYER_4,
4189     EL_SOKOBAN_FIELD_PLAYER,
4190     EL_SP_MURPHY,
4191     EL_YAMYAM,
4192     EL_YAMYAM_LEFT,
4193     EL_YAMYAM_RIGHT,
4194     EL_YAMYAM_UP,
4195     EL_YAMYAM_DOWN,
4196     EL_AMOEBA_WET,
4197     EL_AMOEBA_DRY,
4198     EL_AMOEBA_FULL,
4199     EL_BD_AMOEBA,
4200     EL_EMC_MAGIC_BALL,
4201     EL_EMC_ANDROID,
4202
4203     -1
4204   };
4205
4206   static int ep_can_turn_each_move[] =
4207   {
4208     /* !!! do something with this one !!! */
4209     -1
4210   };
4211
4212   static int ep_can_grow[] =
4213   {
4214     EL_BD_AMOEBA,
4215     EL_AMOEBA_DROP,
4216     EL_AMOEBA_WET,
4217     EL_AMOEBA_DRY,
4218     EL_AMOEBA_FULL,
4219     EL_GAME_OF_LIFE,
4220     EL_BIOMAZE,
4221     EL_EMC_DRIPPER,
4222
4223     -1
4224   };
4225
4226   static int ep_active_bomb[] =
4227   {
4228     EL_DYNAMITE_ACTIVE,
4229     EL_EM_DYNAMITE_ACTIVE,
4230     EL_DYNABOMB_PLAYER_1_ACTIVE,
4231     EL_DYNABOMB_PLAYER_2_ACTIVE,
4232     EL_DYNABOMB_PLAYER_3_ACTIVE,
4233     EL_DYNABOMB_PLAYER_4_ACTIVE,
4234     EL_SP_DISK_RED_ACTIVE,
4235
4236     -1
4237   };
4238
4239   static int ep_inactive[] =
4240   {
4241     EL_EMPTY,
4242     EL_SAND,
4243     EL_WALL,
4244     EL_BD_WALL,
4245     EL_WALL_SLIPPERY,
4246     EL_STEELWALL,
4247     EL_AMOEBA_DEAD,
4248     EL_QUICKSAND_EMPTY,
4249     EL_QUICKSAND_FAST_EMPTY,
4250     EL_STONEBLOCK,
4251     EL_ROBOT_WHEEL,
4252     EL_KEY_1,
4253     EL_KEY_2,
4254     EL_KEY_3,
4255     EL_KEY_4,
4256     EL_EM_KEY_1,
4257     EL_EM_KEY_2,
4258     EL_EM_KEY_3,
4259     EL_EM_KEY_4,
4260     EL_EMC_KEY_5,
4261     EL_EMC_KEY_6,
4262     EL_EMC_KEY_7,
4263     EL_EMC_KEY_8,
4264     EL_GATE_1,
4265     EL_GATE_2,
4266     EL_GATE_3,
4267     EL_GATE_4,
4268     EL_GATE_1_GRAY,
4269     EL_GATE_2_GRAY,
4270     EL_GATE_3_GRAY,
4271     EL_GATE_4_GRAY,
4272     EL_GATE_1_GRAY_ACTIVE,
4273     EL_GATE_2_GRAY_ACTIVE,
4274     EL_GATE_3_GRAY_ACTIVE,
4275     EL_GATE_4_GRAY_ACTIVE,
4276     EL_EM_GATE_1,
4277     EL_EM_GATE_2,
4278     EL_EM_GATE_3,
4279     EL_EM_GATE_4,
4280     EL_EM_GATE_1_GRAY,
4281     EL_EM_GATE_2_GRAY,
4282     EL_EM_GATE_3_GRAY,
4283     EL_EM_GATE_4_GRAY,
4284     EL_EM_GATE_1_GRAY_ACTIVE,
4285     EL_EM_GATE_2_GRAY_ACTIVE,
4286     EL_EM_GATE_3_GRAY_ACTIVE,
4287     EL_EM_GATE_4_GRAY_ACTIVE,
4288     EL_EMC_GATE_5,
4289     EL_EMC_GATE_6,
4290     EL_EMC_GATE_7,
4291     EL_EMC_GATE_8,
4292     EL_EMC_GATE_5_GRAY,
4293     EL_EMC_GATE_6_GRAY,
4294     EL_EMC_GATE_7_GRAY,
4295     EL_EMC_GATE_8_GRAY,
4296     EL_EMC_GATE_5_GRAY_ACTIVE,
4297     EL_EMC_GATE_6_GRAY_ACTIVE,
4298     EL_EMC_GATE_7_GRAY_ACTIVE,
4299     EL_EMC_GATE_8_GRAY_ACTIVE,
4300     EL_DC_GATE_WHITE,
4301     EL_DC_GATE_WHITE_GRAY,
4302     EL_DC_GATE_WHITE_GRAY_ACTIVE,
4303     EL_DC_GATE_FAKE_GRAY,
4304     EL_DYNAMITE,
4305     EL_EM_DYNAMITE,
4306     EL_INVISIBLE_STEELWALL,
4307     EL_INVISIBLE_WALL,
4308     EL_INVISIBLE_SAND,
4309     EL_LAMP,
4310     EL_LAMP_ACTIVE,
4311     EL_WALL_EMERALD,
4312     EL_WALL_DIAMOND,
4313     EL_WALL_BD_DIAMOND,
4314     EL_WALL_EMERALD_YELLOW,
4315     EL_DYNABOMB_INCREASE_NUMBER,
4316     EL_DYNABOMB_INCREASE_SIZE,
4317     EL_DYNABOMB_INCREASE_POWER,
4318 #if 0
4319     EL_SOKOBAN_OBJECT,
4320 #endif
4321     EL_SOKOBAN_FIELD_EMPTY,
4322     EL_SOKOBAN_FIELD_FULL,
4323     EL_WALL_EMERALD_RED,
4324     EL_WALL_EMERALD_PURPLE,
4325     EL_ACID_POOL_TOPLEFT,
4326     EL_ACID_POOL_TOPRIGHT,
4327     EL_ACID_POOL_BOTTOMLEFT,
4328     EL_ACID_POOL_BOTTOM,
4329     EL_ACID_POOL_BOTTOMRIGHT,
4330     EL_MAGIC_WALL,
4331     EL_MAGIC_WALL_DEAD,
4332     EL_BD_MAGIC_WALL,
4333     EL_BD_MAGIC_WALL_DEAD,
4334     EL_DC_MAGIC_WALL,
4335     EL_DC_MAGIC_WALL_DEAD,
4336     EL_AMOEBA_TO_DIAMOND,
4337     EL_BLOCKED,
4338     EL_SP_EMPTY,
4339     EL_SP_BASE,
4340     EL_SP_PORT_RIGHT,
4341     EL_SP_PORT_DOWN,
4342     EL_SP_PORT_LEFT,
4343     EL_SP_PORT_UP,
4344     EL_SP_GRAVITY_PORT_RIGHT,
4345     EL_SP_GRAVITY_PORT_DOWN,
4346     EL_SP_GRAVITY_PORT_LEFT,
4347     EL_SP_GRAVITY_PORT_UP,
4348     EL_SP_PORT_HORIZONTAL,
4349     EL_SP_PORT_VERTICAL,
4350     EL_SP_PORT_ANY,
4351     EL_SP_DISK_RED,
4352 #if 0
4353     EL_SP_DISK_YELLOW,
4354 #endif
4355     EL_SP_CHIP_SINGLE,
4356     EL_SP_CHIP_LEFT,
4357     EL_SP_CHIP_RIGHT,
4358     EL_SP_CHIP_TOP,
4359     EL_SP_CHIP_BOTTOM,
4360     EL_SP_HARDWARE_GRAY,
4361     EL_SP_HARDWARE_GREEN,
4362     EL_SP_HARDWARE_BLUE,
4363     EL_SP_HARDWARE_RED,
4364     EL_SP_HARDWARE_YELLOW,
4365     EL_SP_HARDWARE_BASE_1,
4366     EL_SP_HARDWARE_BASE_2,
4367     EL_SP_HARDWARE_BASE_3,
4368     EL_SP_HARDWARE_BASE_4,
4369     EL_SP_HARDWARE_BASE_5,
4370     EL_SP_HARDWARE_BASE_6,
4371     EL_SP_GRAVITY_ON_PORT_LEFT,
4372     EL_SP_GRAVITY_ON_PORT_RIGHT,
4373     EL_SP_GRAVITY_ON_PORT_UP,
4374     EL_SP_GRAVITY_ON_PORT_DOWN,
4375     EL_SP_GRAVITY_OFF_PORT_LEFT,
4376     EL_SP_GRAVITY_OFF_PORT_RIGHT,
4377     EL_SP_GRAVITY_OFF_PORT_UP,
4378     EL_SP_GRAVITY_OFF_PORT_DOWN,
4379     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
4380     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
4381     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
4382     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
4383     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
4384     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
4385     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
4386     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
4387     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
4388     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
4389     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
4390     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
4391     EL_SIGN_EXCLAMATION,
4392     EL_SIGN_RADIOACTIVITY,
4393     EL_SIGN_STOP,
4394     EL_SIGN_WHEELCHAIR,
4395     EL_SIGN_PARKING,
4396     EL_SIGN_NO_ENTRY,
4397     EL_SIGN_UNUSED_1,
4398     EL_SIGN_GIVE_WAY,
4399     EL_SIGN_ENTRY_FORBIDDEN,
4400     EL_SIGN_EMERGENCY_EXIT,
4401     EL_SIGN_YIN_YANG,
4402     EL_SIGN_UNUSED_2,
4403     EL_SIGN_SPERMS,
4404     EL_SIGN_BULLET,
4405     EL_SIGN_HEART,
4406     EL_SIGN_CROSS,
4407     EL_SIGN_FRANKIE,
4408     EL_DC_STEELWALL_1_LEFT,
4409     EL_DC_STEELWALL_1_RIGHT,
4410     EL_DC_STEELWALL_1_TOP,
4411     EL_DC_STEELWALL_1_BOTTOM,
4412     EL_DC_STEELWALL_1_HORIZONTAL,
4413     EL_DC_STEELWALL_1_VERTICAL,
4414     EL_DC_STEELWALL_1_TOPLEFT,
4415     EL_DC_STEELWALL_1_TOPRIGHT,
4416     EL_DC_STEELWALL_1_BOTTOMLEFT,
4417     EL_DC_STEELWALL_1_BOTTOMRIGHT,
4418     EL_DC_STEELWALL_1_TOPLEFT_2,
4419     EL_DC_STEELWALL_1_TOPRIGHT_2,
4420     EL_DC_STEELWALL_1_BOTTOMLEFT_2,
4421     EL_DC_STEELWALL_1_BOTTOMRIGHT_2,
4422     EL_DC_STEELWALL_2_LEFT,
4423     EL_DC_STEELWALL_2_RIGHT,
4424     EL_DC_STEELWALL_2_TOP,
4425     EL_DC_STEELWALL_2_BOTTOM,
4426     EL_DC_STEELWALL_2_HORIZONTAL,
4427     EL_DC_STEELWALL_2_VERTICAL,
4428     EL_DC_STEELWALL_2_MIDDLE,
4429     EL_DC_STEELWALL_2_SINGLE,
4430     EL_STEELWALL_SLIPPERY,
4431     EL_EMC_STEELWALL_1,
4432     EL_EMC_STEELWALL_2,
4433     EL_EMC_STEELWALL_3,
4434     EL_EMC_STEELWALL_4,
4435     EL_EMC_WALL_SLIPPERY_1,
4436     EL_EMC_WALL_SLIPPERY_2,
4437     EL_EMC_WALL_SLIPPERY_3,
4438     EL_EMC_WALL_SLIPPERY_4,
4439     EL_EMC_WALL_1,
4440     EL_EMC_WALL_2,
4441     EL_EMC_WALL_3,
4442     EL_EMC_WALL_4,
4443     EL_EMC_WALL_5,
4444     EL_EMC_WALL_6,
4445     EL_EMC_WALL_7,
4446     EL_EMC_WALL_8,
4447     EL_EMC_WALL_9,
4448     EL_EMC_WALL_10,
4449     EL_EMC_WALL_11,
4450     EL_EMC_WALL_12,
4451     EL_EMC_WALL_13,
4452     EL_EMC_WALL_14,
4453     EL_EMC_WALL_15,
4454     EL_EMC_WALL_16,
4455
4456     -1
4457   };
4458
4459   static int ep_em_slippery_wall[] =
4460   {
4461     -1
4462   };
4463
4464   static int ep_gfx_crumbled[] =
4465   {
4466     EL_SAND,
4467     EL_LANDMINE,
4468     EL_DC_LANDMINE,
4469     EL_TRAP,
4470     EL_TRAP_ACTIVE,
4471
4472     -1
4473   };
4474
4475   static int ep_editor_cascade_active[] =
4476   {
4477     EL_INTERNAL_CASCADE_BD_ACTIVE,
4478     EL_INTERNAL_CASCADE_EM_ACTIVE,
4479     EL_INTERNAL_CASCADE_EMC_ACTIVE,
4480     EL_INTERNAL_CASCADE_RND_ACTIVE,
4481     EL_INTERNAL_CASCADE_SB_ACTIVE,
4482     EL_INTERNAL_CASCADE_SP_ACTIVE,
4483     EL_INTERNAL_CASCADE_DC_ACTIVE,
4484     EL_INTERNAL_CASCADE_DX_ACTIVE,
4485     EL_INTERNAL_CASCADE_CHARS_ACTIVE,
4486     EL_INTERNAL_CASCADE_STEEL_CHARS_ACTIVE,
4487     EL_INTERNAL_CASCADE_CE_ACTIVE,
4488     EL_INTERNAL_CASCADE_GE_ACTIVE,
4489     EL_INTERNAL_CASCADE_REF_ACTIVE,
4490     EL_INTERNAL_CASCADE_USER_ACTIVE,
4491     EL_INTERNAL_CASCADE_DYNAMIC_ACTIVE,
4492
4493     -1
4494   };
4495
4496   static int ep_editor_cascade_inactive[] =
4497   {
4498     EL_INTERNAL_CASCADE_BD,
4499     EL_INTERNAL_CASCADE_EM,
4500     EL_INTERNAL_CASCADE_EMC,
4501     EL_INTERNAL_CASCADE_RND,
4502     EL_INTERNAL_CASCADE_SB,
4503     EL_INTERNAL_CASCADE_SP,
4504     EL_INTERNAL_CASCADE_DC,
4505     EL_INTERNAL_CASCADE_DX,
4506     EL_INTERNAL_CASCADE_CHARS,
4507     EL_INTERNAL_CASCADE_STEEL_CHARS,
4508     EL_INTERNAL_CASCADE_CE,
4509     EL_INTERNAL_CASCADE_GE,
4510     EL_INTERNAL_CASCADE_REF,
4511     EL_INTERNAL_CASCADE_USER,
4512     EL_INTERNAL_CASCADE_DYNAMIC,
4513
4514     -1
4515   };
4516
4517   static int ep_obsolete[] =
4518   {
4519     EL_PLAYER_OBSOLETE,
4520     EL_KEY_OBSOLETE,
4521     EL_EM_KEY_1_FILE_OBSOLETE,
4522     EL_EM_KEY_2_FILE_OBSOLETE,
4523     EL_EM_KEY_3_FILE_OBSOLETE,
4524     EL_EM_KEY_4_FILE_OBSOLETE,
4525     EL_ENVELOPE_OBSOLETE,
4526
4527     -1
4528   };
4529
4530   static struct
4531   {
4532     int *elements;
4533     int property;
4534   } element_properties[] =
4535   {
4536     { ep_diggable,                      EP_DIGGABLE                     },
4537     { ep_collectible_only,              EP_COLLECTIBLE_ONLY             },
4538     { ep_dont_run_into,                 EP_DONT_RUN_INTO                },
4539     { ep_dont_collide_with,             EP_DONT_COLLIDE_WITH            },
4540     { ep_dont_touch,                    EP_DONT_TOUCH                   },
4541     { ep_indestructible,                EP_INDESTRUCTIBLE               },
4542     { ep_slippery,                      EP_SLIPPERY                     },
4543     { ep_can_change,                    EP_CAN_CHANGE                   },
4544     { ep_can_move,                      EP_CAN_MOVE                     },
4545     { ep_can_fall,                      EP_CAN_FALL                     },
4546     { ep_can_smash_player,              EP_CAN_SMASH_PLAYER             },
4547     { ep_can_smash_enemies,             EP_CAN_SMASH_ENEMIES            },
4548     { ep_can_smash_everything,          EP_CAN_SMASH_EVERYTHING         },
4549     { ep_explodes_by_fire,              EP_EXPLODES_BY_FIRE             },
4550     { ep_explodes_smashed,              EP_EXPLODES_SMASHED             },
4551     { ep_explodes_impact,               EP_EXPLODES_IMPACT              },
4552     { ep_walkable_over,                 EP_WALKABLE_OVER                },
4553     { ep_walkable_inside,               EP_WALKABLE_INSIDE              },
4554     { ep_walkable_under,                EP_WALKABLE_UNDER               },
4555     { ep_passable_over,                 EP_PASSABLE_OVER                },
4556     { ep_passable_inside,               EP_PASSABLE_INSIDE              },
4557     { ep_passable_under,                EP_PASSABLE_UNDER               },
4558     { ep_droppable,                     EP_DROPPABLE                    },
4559     { ep_explodes_1x1_old,              EP_EXPLODES_1X1_OLD             },
4560     { ep_pushable,                      EP_PUSHABLE                     },
4561     { ep_explodes_cross_old,            EP_EXPLODES_CROSS_OLD           },
4562     { ep_protected,                     EP_PROTECTED                    },
4563     { ep_throwable,                     EP_THROWABLE                    },
4564     { ep_can_explode,                   EP_CAN_EXPLODE                  },
4565     { ep_gravity_reachable,             EP_GRAVITY_REACHABLE            },
4566
4567     { ep_player,                        EP_PLAYER                       },
4568     { ep_can_pass_magic_wall,           EP_CAN_PASS_MAGIC_WALL          },
4569     { ep_can_pass_dc_magic_wall,        EP_CAN_PASS_DC_MAGIC_WALL       },
4570     { ep_switchable,                    EP_SWITCHABLE                   },
4571     { ep_bd_element,                    EP_BD_ELEMENT                   },
4572     { ep_sp_element,                    EP_SP_ELEMENT                   },
4573     { ep_sb_element,                    EP_SB_ELEMENT                   },
4574     { ep_gem,                           EP_GEM                          },
4575     { ep_food_dark_yamyam,              EP_FOOD_DARK_YAMYAM             },
4576     { ep_food_penguin,                  EP_FOOD_PENGUIN                 },
4577     { ep_food_pig,                      EP_FOOD_PIG                     },
4578     { ep_historic_wall,                 EP_HISTORIC_WALL                },
4579     { ep_historic_solid,                EP_HISTORIC_SOLID               },
4580     { ep_classic_enemy,                 EP_CLASSIC_ENEMY                },
4581     { ep_belt,                          EP_BELT                         },
4582     { ep_belt_active,                   EP_BELT_ACTIVE                  },
4583     { ep_belt_switch,                   EP_BELT_SWITCH                  },
4584     { ep_tube,                          EP_TUBE                         },
4585     { ep_acid_pool,                     EP_ACID_POOL                    },
4586     { ep_keygate,                       EP_KEYGATE                      },
4587     { ep_amoeboid,                      EP_AMOEBOID                     },
4588     { ep_amoebalive,                    EP_AMOEBALIVE                   },
4589     { ep_has_editor_content,            EP_HAS_EDITOR_CONTENT           },
4590     { ep_can_turn_each_move,            EP_CAN_TURN_EACH_MOVE           },
4591     { ep_can_grow,                      EP_CAN_GROW                     },
4592     { ep_active_bomb,                   EP_ACTIVE_BOMB                  },
4593     { ep_inactive,                      EP_INACTIVE                     },
4594
4595     { ep_em_slippery_wall,              EP_EM_SLIPPERY_WALL             },
4596
4597     { ep_gfx_crumbled,                  EP_GFX_CRUMBLED                 },
4598
4599     { ep_editor_cascade_active,         EP_EDITOR_CASCADE_ACTIVE        },
4600     { ep_editor_cascade_inactive,       EP_EDITOR_CASCADE_INACTIVE      },
4601
4602     { ep_obsolete,                      EP_OBSOLETE                     },
4603
4604     { NULL,                             -1                              }
4605   };
4606
4607   int i, j, k;
4608
4609   /* always start with reliable default values (element has no properties) */
4610   /* (but never initialize clipboard elements after the very first time) */
4611   /* (to be able to use clipboard elements between several levels) */
4612   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4613     if (!IS_CLIPBOARD_ELEMENT(i) || !clipboard_elements_initialized)
4614       for (j = 0; j < NUM_ELEMENT_PROPERTIES; j++)
4615         SET_PROPERTY(i, j, FALSE);
4616
4617   /* set all base element properties from above array definitions */
4618   for (i = 0; element_properties[i].elements != NULL; i++)
4619     for (j = 0; (element_properties[i].elements)[j] != -1; j++)
4620       SET_PROPERTY((element_properties[i].elements)[j],
4621                    element_properties[i].property, TRUE);
4622
4623   /* copy properties to some elements that are only stored in level file */
4624   for (i = 0; i < NUM_ELEMENT_PROPERTIES; i++)
4625     for (j = 0; copy_properties[j][0] != -1; j++)
4626       if (HAS_PROPERTY(copy_properties[j][0], i))
4627         for (k = 1; k <= 4; k++)
4628           SET_PROPERTY(copy_properties[j][k], i, TRUE);
4629
4630   /* set static element properties that are not listed in array definitions */
4631   for (i = EL_STEEL_CHAR_START; i <= EL_STEEL_CHAR_END; i++)
4632     SET_PROPERTY(i, EP_INDESTRUCTIBLE, TRUE);
4633
4634   clipboard_elements_initialized = TRUE;
4635 }
4636
4637 void InitElementPropertiesEngine(int engine_version)
4638 {
4639   static int no_wall_properties[] =
4640   {
4641     EP_DIGGABLE,
4642     EP_COLLECTIBLE_ONLY,
4643     EP_DONT_RUN_INTO,
4644     EP_DONT_COLLIDE_WITH,
4645     EP_CAN_MOVE,
4646     EP_CAN_FALL,
4647     EP_CAN_SMASH_PLAYER,
4648     EP_CAN_SMASH_ENEMIES,
4649     EP_CAN_SMASH_EVERYTHING,
4650     EP_PUSHABLE,
4651
4652     EP_PLAYER,
4653     EP_GEM,
4654     EP_FOOD_DARK_YAMYAM,
4655     EP_FOOD_PENGUIN,
4656     EP_BELT,
4657     EP_BELT_ACTIVE,
4658     EP_TUBE,
4659     EP_AMOEBOID,
4660     EP_AMOEBALIVE,
4661     EP_ACTIVE_BOMB,
4662
4663     EP_ACCESSIBLE,
4664
4665     -1
4666   };
4667
4668   int i, j;
4669
4670   /* important: after initialization in InitElementPropertiesStatic(), the
4671      elements are not again initialized to a default value; therefore all
4672      changes have to make sure that they leave the element with a defined
4673      property (which means that conditional property changes must be set to
4674      a reliable default value before) */
4675
4676   /* resolve group elements */
4677   for (i = 0; i < NUM_GROUP_ELEMENTS; i++)
4678     ResolveGroupElement(EL_GROUP_START + i);
4679
4680   /* set all special, combined or engine dependent element properties */
4681   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4682   {
4683     /* do not change (already initialized) clipboard elements here */
4684     if (IS_CLIPBOARD_ELEMENT(i))
4685       continue;
4686
4687     /* ---------- INACTIVE ------------------------------------------------- */
4688     SET_PROPERTY(i, EP_INACTIVE, ((i >= EL_CHAR_START &&
4689                                    i <= EL_CHAR_END) ||
4690                                   (i >= EL_STEEL_CHAR_START &&
4691                                    i <= EL_STEEL_CHAR_END)));
4692
4693     /* ---------- WALKABLE, PASSABLE, ACCESSIBLE --------------------------- */
4694     SET_PROPERTY(i, EP_WALKABLE, (IS_WALKABLE_OVER(i) ||
4695                                   IS_WALKABLE_INSIDE(i) ||
4696                                   IS_WALKABLE_UNDER(i)));
4697
4698     SET_PROPERTY(i, EP_PASSABLE, (IS_PASSABLE_OVER(i) ||
4699                                   IS_PASSABLE_INSIDE(i) ||
4700                                   IS_PASSABLE_UNDER(i)));
4701
4702     SET_PROPERTY(i, EP_ACCESSIBLE_OVER, (IS_WALKABLE_OVER(i) ||
4703                                          IS_PASSABLE_OVER(i)));
4704
4705     SET_PROPERTY(i, EP_ACCESSIBLE_INSIDE, (IS_WALKABLE_INSIDE(i) ||
4706                                            IS_PASSABLE_INSIDE(i)));
4707
4708     SET_PROPERTY(i, EP_ACCESSIBLE_UNDER, (IS_WALKABLE_UNDER(i) ||
4709                                           IS_PASSABLE_UNDER(i)));
4710
4711     SET_PROPERTY(i, EP_ACCESSIBLE, (IS_WALKABLE(i) ||
4712                                     IS_PASSABLE(i)));
4713
4714     /* ---------- COLLECTIBLE ---------------------------------------------- */
4715     SET_PROPERTY(i, EP_COLLECTIBLE, (IS_COLLECTIBLE_ONLY(i) ||
4716                                      IS_DROPPABLE(i) ||
4717                                      IS_THROWABLE(i)));
4718
4719     /* ---------- SNAPPABLE ------------------------------------------------ */
4720     SET_PROPERTY(i, EP_SNAPPABLE, (IS_DIGGABLE(i) ||
4721                                    IS_COLLECTIBLE(i) ||
4722                                    IS_SWITCHABLE(i) ||
4723                                    i == EL_BD_ROCK));
4724
4725     /* ---------- WALL ----------------------------------------------------- */
4726     SET_PROPERTY(i, EP_WALL, TRUE);     /* default: element is wall */
4727
4728     for (j = 0; no_wall_properties[j] != -1; j++)
4729       if (HAS_PROPERTY(i, no_wall_properties[j]) ||
4730           i >= EL_FIRST_RUNTIME_UNREAL)
4731         SET_PROPERTY(i, EP_WALL, FALSE);
4732
4733     if (IS_HISTORIC_WALL(i))
4734       SET_PROPERTY(i, EP_WALL, TRUE);
4735
4736     /* ---------- SOLID_FOR_PUSHING ---------------------------------------- */
4737     if (engine_version < VERSION_IDENT(2,2,0,0))
4738       SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, IS_HISTORIC_SOLID(i));
4739     else
4740       SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, (!IS_WALKABLE(i) &&
4741                                              !IS_DIGGABLE(i) &&
4742                                              !IS_COLLECTIBLE(i)));
4743
4744     /* ---------- DRAGONFIRE_PROOF ----------------------------------------- */
4745     if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
4746       SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE);
4747     else
4748       SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_CUSTOM_ELEMENT(i) &&
4749                                             IS_INDESTRUCTIBLE(i)));
4750
4751     /* ---------- EXPLOSION_PROOF ------------------------------------------ */
4752     if (i == EL_FLAMES)
4753       SET_PROPERTY(i, EP_EXPLOSION_PROOF, TRUE);
4754     else if (engine_version < VERSION_IDENT(2,2,0,0))
4755       SET_PROPERTY(i, EP_EXPLOSION_PROOF, IS_INDESTRUCTIBLE(i));
4756     else
4757       SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
4758                                            (!IS_WALKABLE(i) ||
4759                                             IS_PROTECTED(i))));
4760
4761     if (IS_CUSTOM_ELEMENT(i))
4762     {
4763       /* these are additional properties which are initially false when set */
4764
4765       /* ---------- DONT_COLLIDE_WITH / DONT_RUN_INTO ---------------------- */
4766       if (DONT_TOUCH(i))
4767         SET_PROPERTY(i, EP_DONT_COLLIDE_WITH, TRUE);
4768       if (DONT_COLLIDE_WITH(i))
4769         SET_PROPERTY(i, EP_DONT_RUN_INTO, TRUE);
4770
4771       /* ---------- CAN_SMASH_ENEMIES / CAN_SMASH_PLAYER ------------------- */
4772       if (CAN_SMASH_EVERYTHING(i))
4773         SET_PROPERTY(i, EP_CAN_SMASH_ENEMIES, TRUE);
4774       if (CAN_SMASH_ENEMIES(i))
4775         SET_PROPERTY(i, EP_CAN_SMASH_PLAYER, TRUE);
4776     }
4777
4778     /* ---------- CAN_SMASH ------------------------------------------------ */
4779     SET_PROPERTY(i, EP_CAN_SMASH, (CAN_SMASH_PLAYER(i) ||
4780                                    CAN_SMASH_ENEMIES(i) ||
4781                                    CAN_SMASH_EVERYTHING(i)));
4782
4783     /* ---------- CAN_EXPLODE_BY_FIRE -------------------------------------- */
4784     SET_PROPERTY(i, EP_CAN_EXPLODE_BY_FIRE, (CAN_EXPLODE(i) &&
4785                                              EXPLODES_BY_FIRE(i)));
4786
4787     /* ---------- CAN_EXPLODE_SMASHED -------------------------------------- */
4788     SET_PROPERTY(i, EP_CAN_EXPLODE_SMASHED, (CAN_EXPLODE(i) &&
4789                                              EXPLODES_SMASHED(i)));
4790
4791     /* ---------- CAN_EXPLODE_IMPACT --------------------------------------- */
4792     SET_PROPERTY(i, EP_CAN_EXPLODE_IMPACT, (CAN_EXPLODE(i) &&
4793                                             EXPLODES_IMPACT(i)));
4794
4795     /* ---------- CAN_EXPLODE_BY_DRAGONFIRE -------------------------------- */
4796     SET_PROPERTY(i, EP_CAN_EXPLODE_BY_DRAGONFIRE, CAN_EXPLODE_BY_FIRE(i));
4797
4798     /* ---------- CAN_EXPLODE_BY_EXPLOSION --------------------------------- */
4799     SET_PROPERTY(i, EP_CAN_EXPLODE_BY_EXPLOSION, (CAN_EXPLODE_BY_FIRE(i) ||
4800                                                   i == EL_BLACK_ORB));
4801
4802     /* ---------- COULD_MOVE_INTO_ACID ------------------------------------- */
4803     SET_PROPERTY(i, EP_COULD_MOVE_INTO_ACID, (ELEM_IS_PLAYER(i) ||
4804                                               CAN_MOVE(i) ||
4805                                               IS_CUSTOM_ELEMENT(i)));
4806
4807     /* ---------- MAYBE_DONT_COLLIDE_WITH ---------------------------------- */
4808     SET_PROPERTY(i, EP_MAYBE_DONT_COLLIDE_WITH, (i == EL_SP_SNIKSNAK ||
4809                                                  i == EL_SP_ELECTRON));
4810
4811     /* ---------- CAN_MOVE_INTO_ACID --------------------------------------- */
4812     if (COULD_MOVE_INTO_ACID(i) && !IS_CUSTOM_ELEMENT(i))
4813       SET_PROPERTY(i, EP_CAN_MOVE_INTO_ACID,
4814                    getMoveIntoAcidProperty(&level, i));
4815
4816     /* ---------- DONT_COLLIDE_WITH ---------------------------------------- */
4817     if (MAYBE_DONT_COLLIDE_WITH(i))
4818       SET_PROPERTY(i, EP_DONT_COLLIDE_WITH,
4819                    getDontCollideWithProperty(&level, i));
4820
4821     /* ---------- SP_PORT -------------------------------------------------- */
4822     SET_PROPERTY(i, EP_SP_PORT, (IS_SP_ELEMENT(i) &&
4823                                  IS_PASSABLE_INSIDE(i)));
4824
4825     /* ---------- CAN_BE_CLONED_BY_ANDROID --------------------------------- */
4826     for (j = 0; j < level.num_android_clone_elements; j++)
4827       SET_PROPERTY(i, EP_CAN_BE_CLONED_BY_ANDROID,
4828                    (i != EL_EMPTY &&
4829                     IS_EQUAL_OR_IN_GROUP(i, level.android_clone_element[j])));
4830
4831     /* ---------- CAN_CHANGE ----------------------------------------------- */
4832     SET_PROPERTY(i, EP_CAN_CHANGE, FALSE);      /* default: cannot change */
4833     for (j = 0; j < element_info[i].num_change_pages; j++)
4834       if (element_info[i].change_page[j].can_change)
4835         SET_PROPERTY(i, EP_CAN_CHANGE, TRUE);
4836
4837     /* ---------- HAS_ACTION ----------------------------------------------- */
4838     SET_PROPERTY(i, EP_HAS_ACTION, FALSE);      /* default: has no action */
4839     for (j = 0; j < element_info[i].num_change_pages; j++)
4840       if (element_info[i].change_page[j].has_action)
4841         SET_PROPERTY(i, EP_HAS_ACTION, TRUE);
4842
4843     /* ---------- CAN_CHANGE_OR_HAS_ACTION --------------------------------- */
4844     SET_PROPERTY(i, EP_CAN_CHANGE_OR_HAS_ACTION, (CAN_CHANGE(i) ||
4845                                                   HAS_ACTION(i)));
4846
4847     /* ---------- GFX_CRUMBLED --------------------------------------------- */
4848 #if 1
4849     SET_PROPERTY(i, EP_GFX_CRUMBLED,
4850                  element_info[i].crumbled[ACTION_DEFAULT] !=
4851                  element_info[i].graphic[ACTION_DEFAULT]);
4852 #else
4853     /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
4854     SET_PROPERTY(i, EP_GFX_CRUMBLED,
4855                  element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
4856 #endif
4857
4858     /* ---------- EDITOR_CASCADE ------------------------------------------- */
4859     SET_PROPERTY(i, EP_EDITOR_CASCADE, (IS_EDITOR_CASCADE_ACTIVE(i) ||
4860                                         IS_EDITOR_CASCADE_INACTIVE(i)));
4861   }
4862
4863   /* dynamically adjust element properties according to game engine version */
4864   {
4865     static int ep_em_slippery_wall[] =
4866     {
4867       EL_WALL,
4868       EL_STEELWALL,
4869       EL_EXPANDABLE_WALL,
4870       EL_EXPANDABLE_WALL_HORIZONTAL,
4871       EL_EXPANDABLE_WALL_VERTICAL,
4872       EL_EXPANDABLE_WALL_ANY,
4873       EL_EXPANDABLE_STEELWALL_HORIZONTAL,
4874       EL_EXPANDABLE_STEELWALL_VERTICAL,
4875       EL_EXPANDABLE_STEELWALL_ANY,
4876       EL_EXPANDABLE_STEELWALL_GROWING,
4877       -1
4878     };
4879
4880     static int ep_em_explodes_by_fire[] =
4881     {
4882       EL_EM_DYNAMITE,
4883       EL_EM_DYNAMITE_ACTIVE,
4884       EL_MOLE,
4885       -1
4886     };
4887
4888     /* special EM style gems behaviour */
4889     for (i = 0; ep_em_slippery_wall[i] != -1; i++)
4890       SET_PROPERTY(ep_em_slippery_wall[i], EP_EM_SLIPPERY_WALL,
4891                    level.em_slippery_gems);
4892
4893     /* "EL_EXPANDABLE_WALL_GROWING" wasn't slippery for EM gems in 2.0.1 */
4894     SET_PROPERTY(EL_EXPANDABLE_WALL_GROWING, EP_EM_SLIPPERY_WALL,
4895                  (level.em_slippery_gems &&
4896                   engine_version > VERSION_IDENT(2,0,1,0)));
4897
4898     /* special EM style explosion behaviour regarding chain reactions */
4899     for (i = 0; ep_em_explodes_by_fire[i] != -1; i++)
4900       SET_PROPERTY(ep_em_explodes_by_fire[i], EP_EXPLODES_BY_FIRE,
4901                    level.em_explodes_by_fire);
4902   }
4903
4904   /* this is needed because some graphics depend on element properties */
4905   if (game_status == GAME_MODE_PLAYING)
4906     InitElementGraphicInfo();
4907 }
4908
4909 void InitElementPropertiesAfterLoading(int engine_version)
4910 {
4911   int i;
4912
4913   /* set some other uninitialized values of custom elements in older levels */
4914   if (engine_version < VERSION_IDENT(3,1,0,0))
4915   {
4916     for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
4917     {
4918       int element = EL_CUSTOM_START + i;
4919
4920       element_info[element].access_direction = MV_ALL_DIRECTIONS;
4921
4922       element_info[element].explosion_delay = 17;
4923       element_info[element].ignition_delay = 8;
4924     }
4925   }
4926 }
4927
4928 void InitElementPropertiesGfxElement()
4929 {
4930   int i;
4931
4932   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4933   {
4934     struct ElementInfo *ei = &element_info[i];
4935
4936     ei->gfx_element = (ei->use_gfx_element ? ei->gfx_element_initial : i);
4937   }
4938 }
4939
4940 static void InitGlobal()
4941 {
4942   int graphic;
4943   int i;
4944
4945   for (i = 0; i < MAX_NUM_ELEMENTS + 1; i++)
4946   {
4947     /* check if element_name_info entry defined for each element in "main.h" */
4948     if (i < MAX_NUM_ELEMENTS && element_name_info[i].token_name == NULL)
4949       Error(ERR_EXIT, "undefined 'element_name_info' entry for element %d", i);
4950
4951     element_info[i].token_name = element_name_info[i].token_name;
4952     element_info[i].class_name = element_name_info[i].class_name;
4953     element_info[i].editor_description= element_name_info[i].editor_description;
4954
4955 #if 0
4956     printf("%04d: %s\n", i, element_name_info[i].token_name);
4957 #endif
4958   }
4959
4960   /* create hash from image config list */
4961   image_config_hash = newSetupFileHash();
4962   for (i = 0; image_config[i].token != NULL; i++)
4963     setHashEntry(image_config_hash,
4964                  image_config[i].token,
4965                  image_config[i].value);
4966
4967   /* create hash from element token list */
4968   element_token_hash = newSetupFileHash();
4969   for (i = 0; element_name_info[i].token_name != NULL; i++)
4970     setHashEntry(element_token_hash,
4971                  element_name_info[i].token_name,
4972                  int2str(i, 0));
4973
4974   /* create hash from graphic token list */
4975   graphic_token_hash = newSetupFileHash();
4976   for (graphic = 0, i = 0; image_config[i].token != NULL; i++)
4977     if (strSuffix(image_config[i].value, ".pcx") ||
4978         strSuffix(image_config[i].value, ".wav") ||
4979         strEqual(image_config[i].value, UNDEFINED_FILENAME))
4980       setHashEntry(graphic_token_hash,
4981                    image_config[i].token,
4982                    int2str(graphic++, 0));
4983
4984   /* create hash from font token list */
4985   font_token_hash = newSetupFileHash();
4986   for (i = 0; font_info[i].token_name != NULL; i++)
4987     setHashEntry(font_token_hash,
4988                  font_info[i].token_name,
4989                  int2str(i, 0));
4990
4991   /* always start with reliable default values (all elements) */
4992   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4993     ActiveElement[i] = i;
4994
4995   /* now add all entries that have an active state (active elements) */
4996   for (i = 0; element_with_active_state[i].element != -1; i++)
4997   {
4998     int element = element_with_active_state[i].element;
4999     int element_active = element_with_active_state[i].element_active;
5000
5001     ActiveElement[element] = element_active;
5002   }
5003
5004   /* always start with reliable default values (all buttons) */
5005   for (i = 0; i < NUM_IMAGE_FILES; i++)
5006     ActiveButton[i] = i;
5007
5008   /* now add all entries that have an active state (active buttons) */
5009   for (i = 0; button_with_active_state[i].button != -1; i++)
5010   {
5011     int button = button_with_active_state[i].button;
5012     int button_active = button_with_active_state[i].button_active;
5013
5014     ActiveButton[button] = button_active;
5015   }
5016
5017   /* always start with reliable default values (all fonts) */
5018   for (i = 0; i < NUM_FONTS; i++)
5019     ActiveFont[i] = i;
5020
5021   /* now add all entries that have an active state (active fonts) */
5022   for (i = 0; font_with_active_state[i].font_nr != -1; i++)
5023   {
5024     int font = font_with_active_state[i].font_nr;
5025     int font_active = font_with_active_state[i].font_nr_active;
5026
5027     ActiveFont[font] = font_active;
5028   }
5029
5030   global.autoplay_leveldir = NULL;
5031   global.convert_leveldir = NULL;
5032   global.create_images_dir = NULL;
5033
5034   global.frames_per_second = 0;
5035   global.fps_slowdown = FALSE;
5036   global.fps_slowdown_factor = 1;
5037
5038   global.border_status = GAME_MODE_MAIN;
5039 #if 0
5040   global.fading_status = GAME_MODE_MAIN;
5041   global.fading_type = TYPE_ENTER_MENU;
5042 #endif
5043 }
5044
5045 void Execute_Command(char *command)
5046 {
5047   int i;
5048
5049   if (strEqual(command, "print graphicsinfo.conf"))
5050   {
5051     printf("# You can configure additional/alternative image files here.\n");
5052     printf("# (The entries below are default and therefore commented out.)\n");
5053     printf("\n");
5054     printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
5055     printf("\n");
5056     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
5057     printf("\n");
5058
5059     for (i = 0; image_config[i].token != NULL; i++)
5060       printf("# %s\n", getFormattedSetupEntry(image_config[i].token,
5061                                               image_config[i].value));
5062
5063     exit(0);
5064   }
5065   else if (strEqual(command, "print soundsinfo.conf"))
5066   {
5067     printf("# You can configure additional/alternative sound files here.\n");
5068     printf("# (The entries below are default and therefore commented out.)\n");
5069     printf("\n");
5070     printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
5071     printf("\n");
5072     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
5073     printf("\n");
5074
5075     for (i = 0; sound_config[i].token != NULL; i++)
5076       printf("# %s\n", getFormattedSetupEntry(sound_config[i].token,
5077                                               sound_config[i].value));
5078
5079     exit(0);
5080   }
5081   else if (strEqual(command, "print musicinfo.conf"))
5082   {
5083     printf("# You can configure additional/alternative music files here.\n");
5084     printf("# (The entries below are default and therefore commented out.)\n");
5085     printf("\n");
5086     printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
5087     printf("\n");
5088     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
5089     printf("\n");
5090
5091     for (i = 0; music_config[i].token != NULL; i++)
5092       printf("# %s\n", getFormattedSetupEntry(music_config[i].token,
5093                                               music_config[i].value));
5094
5095     exit(0);
5096   }
5097   else if (strEqual(command, "print editorsetup.conf"))
5098   {
5099     printf("# You can configure your personal editor element list here.\n");
5100     printf("# (The entries below are default and therefore commented out.)\n");
5101     printf("\n");
5102
5103     /* this is needed to be able to check element list for cascade elements */
5104     InitElementPropertiesStatic();
5105     InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
5106
5107     PrintEditorElementList();
5108
5109     exit(0);
5110   }
5111   else if (strEqual(command, "print helpanim.conf"))
5112   {
5113     printf("# You can configure different element help animations here.\n");
5114     printf("# (The entries below are default and therefore commented out.)\n");
5115     printf("\n");
5116
5117     for (i = 0; helpanim_config[i].token != NULL; i++)
5118     {
5119       printf("# %s\n", getFormattedSetupEntry(helpanim_config[i].token,
5120                                               helpanim_config[i].value));
5121
5122       if (strEqual(helpanim_config[i].token, "end"))
5123         printf("#\n");
5124     }
5125
5126     exit(0);
5127   }
5128   else if (strEqual(command, "print helptext.conf"))
5129   {
5130     printf("# You can configure different element help text here.\n");
5131     printf("# (The entries below are default and therefore commented out.)\n");
5132     printf("\n");
5133
5134     for (i = 0; helptext_config[i].token != NULL; i++)
5135       printf("# %s\n", getFormattedSetupEntry(helptext_config[i].token,
5136                                               helptext_config[i].value));
5137
5138     exit(0);
5139   }
5140   else if (strPrefix(command, "dump level "))
5141   {
5142     char *filename = &command[11];
5143
5144     if (!fileExists(filename))
5145       Error(ERR_EXIT, "cannot open file '%s'", filename);
5146
5147     LoadLevelFromFilename(&level, filename);
5148     DumpLevel(&level);
5149
5150     exit(0);
5151   }
5152   else if (strPrefix(command, "dump tape "))
5153   {
5154     char *filename = &command[10];
5155
5156     if (!fileExists(filename))
5157       Error(ERR_EXIT, "cannot open file '%s'", filename);
5158
5159     LoadTapeFromFilename(filename);
5160     DumpTape(&tape);
5161
5162     exit(0);
5163   }
5164   else if (strPrefix(command, "autoplay "))
5165   {
5166     char *str_ptr = getStringCopy(&command[9]); /* read command parameters */
5167
5168     while (*str_ptr != '\0')                    /* continue parsing string */
5169     {
5170       /* cut leading whitespace from string, replace it by string terminator */
5171       while (*str_ptr == ' ' || *str_ptr == '\t')
5172         *str_ptr++ = '\0';
5173
5174       if (*str_ptr == '\0')                     /* end of string reached */
5175         break;
5176
5177       if (global.autoplay_leveldir == NULL)     /* read level set string */
5178       {
5179         global.autoplay_leveldir = str_ptr;
5180         global.autoplay_all = TRUE;             /* default: play all tapes */
5181
5182         for (i = 0; i < MAX_TAPES_PER_SET; i++)
5183           global.autoplay_level[i] = FALSE;
5184       }
5185       else                                      /* read level number string */
5186       {
5187         int level_nr = atoi(str_ptr);           /* get level_nr value */
5188
5189         if (level_nr >= 0 && level_nr < MAX_TAPES_PER_SET)
5190           global.autoplay_level[level_nr] = TRUE;
5191
5192         global.autoplay_all = FALSE;
5193       }
5194
5195       /* advance string pointer to the next whitespace (or end of string) */
5196       while (*str_ptr != ' ' && *str_ptr != '\t' && *str_ptr != '\0')
5197         str_ptr++;
5198     }
5199   }
5200   else if (strPrefix(command, "convert "))
5201   {
5202     char *str_copy = getStringCopy(strchr(command, ' ') + 1);
5203     char *str_ptr = strchr(str_copy, ' ');
5204
5205     global.convert_leveldir = str_copy;
5206     global.convert_level_nr = -1;
5207
5208     if (str_ptr != NULL)                        /* level number follows */
5209     {
5210       *str_ptr++ = '\0';                        /* terminate leveldir string */
5211       global.convert_level_nr = atoi(str_ptr);  /* get level_nr value */
5212     }
5213   }
5214   else if (strPrefix(command, "create images "))
5215   {
5216 #if defined(TARGET_SDL)
5217     global.create_images_dir = getStringCopy(&command[14]);
5218
5219     if (access(global.create_images_dir, W_OK) != 0)
5220       Error(ERR_EXIT, "image target directory '%s' not found or not writable",
5221             global.create_images_dir);
5222 #else
5223     Error(ERR_EXIT, "command only available for SDL target");
5224 #endif
5225   }
5226
5227 #if DEBUG
5228 #if defined(TARGET_SDL)
5229   else if (strEqual(command, "SDL_ListModes"))
5230   {
5231     SDL_Rect **modes;
5232     int i;
5233
5234     SDL_Init(SDL_INIT_VIDEO);
5235
5236     /* get available fullscreen/hardware modes */
5237     modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
5238
5239     /* check if there are any modes available */
5240     if (modes == NULL)
5241     {
5242       printf("No modes available!\n");
5243
5244       exit(-1);
5245     }
5246
5247     /* check if our resolution is restricted */
5248     if (modes == (SDL_Rect **)-1)
5249     {
5250       printf("All resolutions available.\n");
5251     }
5252     else
5253     {
5254       printf("Available Modes:\n");
5255
5256       for(i = 0; modes[i]; i++)
5257         printf("  %d x %d\n", modes[i]->w, modes[i]->h);
5258     }
5259
5260     exit(0);
5261   }
5262 #endif
5263 #endif
5264
5265   else
5266   {
5267     Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
5268   }
5269 }
5270
5271 static void InitSetup()
5272 {
5273   LoadSetup();                                  /* global setup info */
5274
5275   /* set some options from setup file */
5276
5277   if (setup.options.verbose)
5278     options.verbose = TRUE;
5279 }
5280
5281 static void InitGameInfo()
5282 {
5283   game.restart_level = FALSE;
5284 }
5285
5286 static void InitPlayerInfo()
5287 {
5288   int i;
5289
5290   /* choose default local player */
5291   local_player = &stored_player[0];
5292
5293   for (i = 0; i < MAX_PLAYERS; i++)
5294     stored_player[i].connected = FALSE;
5295
5296   local_player->connected = TRUE;
5297 }
5298
5299 static void InitArtworkInfo()
5300 {
5301   LoadArtworkInfo();
5302 }
5303
5304 static char *get_string_in_brackets(char *string)
5305 {
5306   char *string_in_brackets = checked_malloc(strlen(string) + 3);
5307
5308   sprintf(string_in_brackets, "[%s]", string);
5309
5310   return string_in_brackets;
5311 }
5312
5313 static char *get_level_id_suffix(int id_nr)
5314 {
5315   char *id_suffix = checked_malloc(1 + 3 + 1);
5316
5317   if (id_nr < 0 || id_nr > 999)
5318     id_nr = 0;
5319
5320   sprintf(id_suffix, ".%03d", id_nr);
5321
5322   return id_suffix;
5323 }
5324
5325 #if 0
5326 static char *get_element_class_token(int element)
5327 {
5328   char *element_class_name = element_info[element].class_name;
5329   char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
5330
5331   sprintf(element_class_token, "[%s]", element_class_name);
5332
5333   return element_class_token;
5334 }
5335
5336 static char *get_action_class_token(int action)
5337 {
5338   char *action_class_name = &element_action_info[action].suffix[1];
5339   char *action_class_token = checked_malloc(strlen(action_class_name) + 3);
5340
5341   sprintf(action_class_token, "[%s]", action_class_name);
5342
5343   return action_class_token;
5344 }
5345 #endif
5346
5347 static void InitArtworkConfig()
5348 {
5349   static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
5350   static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + 1];
5351   static char *music_id_prefix[NUM_MUSIC_PREFIXES + 1];
5352   static char *action_id_suffix[NUM_ACTIONS + 1];
5353   static char *direction_id_suffix[NUM_DIRECTIONS_FULL + 1];
5354   static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
5355   static char *level_id_suffix[MAX_LEVELS + 1];
5356   static char *dummy[1] = { NULL };
5357   static char *ignore_generic_tokens[] =
5358   {
5359     "name",
5360     "sort_priority",
5361     NULL
5362   };
5363   static char **ignore_image_tokens;
5364   static char **ignore_sound_tokens;
5365   static char **ignore_music_tokens;
5366   int num_ignore_generic_tokens;
5367   int num_ignore_image_tokens;
5368   int num_ignore_sound_tokens;
5369   int num_ignore_music_tokens;
5370   int i;
5371
5372   /* dynamically determine list of generic tokens to be ignored */
5373   num_ignore_generic_tokens = 0;
5374   for (i = 0; ignore_generic_tokens[i] != NULL; i++)
5375     num_ignore_generic_tokens++;
5376
5377   /* dynamically determine list of image tokens to be ignored */
5378   num_ignore_image_tokens = num_ignore_generic_tokens;
5379   for (i = 0; image_config_vars[i].token != NULL; i++)
5380     num_ignore_image_tokens++;
5381   ignore_image_tokens =
5382     checked_malloc((num_ignore_image_tokens + 1) * sizeof(char *));
5383   for (i = 0; i < num_ignore_generic_tokens; i++)
5384     ignore_image_tokens[i] = ignore_generic_tokens[i];
5385   for (i = 0; i < num_ignore_image_tokens - num_ignore_generic_tokens; i++)
5386     ignore_image_tokens[num_ignore_generic_tokens + i] =
5387       image_config_vars[i].token;
5388   ignore_image_tokens[num_ignore_image_tokens] = NULL;
5389
5390   /* dynamically determine list of sound tokens to be ignored */
5391   num_ignore_sound_tokens = num_ignore_generic_tokens;
5392   ignore_sound_tokens =
5393     checked_malloc((num_ignore_sound_tokens + 1) * sizeof(char *));
5394   for (i = 0; i < num_ignore_generic_tokens; i++)
5395     ignore_sound_tokens[i] = ignore_generic_tokens[i];
5396   ignore_sound_tokens[num_ignore_sound_tokens] = NULL;
5397
5398   /* dynamically determine list of music tokens to be ignored */
5399   num_ignore_music_tokens = num_ignore_generic_tokens;
5400   ignore_music_tokens =
5401     checked_malloc((num_ignore_music_tokens + 1) * sizeof(char *));
5402   for (i = 0; i < num_ignore_generic_tokens; i++)
5403     ignore_music_tokens[i] = ignore_generic_tokens[i];
5404   ignore_music_tokens[num_ignore_music_tokens] = NULL;
5405
5406   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
5407     image_id_prefix[i] = element_info[i].token_name;
5408   for (i = 0; i < NUM_FONTS; i++)
5409     image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
5410   image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
5411
5412   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
5413     sound_id_prefix[i] = element_info[i].token_name;
5414   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
5415     sound_id_prefix[MAX_NUM_ELEMENTS + i] =
5416       get_string_in_brackets(element_info[i].class_name);
5417   sound_id_prefix[2 * MAX_NUM_ELEMENTS] = NULL;
5418
5419   for (i = 0; i < NUM_MUSIC_PREFIXES; i++)
5420     music_id_prefix[i] = music_prefix_info[i].prefix;
5421   music_id_prefix[NUM_MUSIC_PREFIXES] = NULL;
5422
5423   for (i = 0; i < NUM_ACTIONS; i++)
5424     action_id_suffix[i] = element_action_info[i].suffix;
5425   action_id_suffix[NUM_ACTIONS] = NULL;
5426
5427   for (i = 0; i < NUM_DIRECTIONS_FULL; i++)
5428     direction_id_suffix[i] = element_direction_info[i].suffix;
5429   direction_id_suffix[NUM_DIRECTIONS_FULL] = NULL;
5430
5431   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
5432     special_id_suffix[i] = special_suffix_info[i].suffix;
5433   special_id_suffix[NUM_SPECIAL_GFX_ARGS] = NULL;
5434
5435   for (i = 0; i < MAX_LEVELS; i++)
5436     level_id_suffix[i] = get_level_id_suffix(i);
5437   level_id_suffix[MAX_LEVELS] = NULL;
5438
5439   InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
5440                 image_id_prefix, action_id_suffix, direction_id_suffix,
5441                 special_id_suffix, ignore_image_tokens);
5442   InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
5443                 sound_id_prefix, action_id_suffix, dummy,
5444                 special_id_suffix, ignore_sound_tokens);
5445   InitMusicList(music_config, NUM_MUSIC_FILES, music_config_suffix,
5446                 music_id_prefix, special_id_suffix, level_id_suffix,
5447                 dummy, ignore_music_tokens);
5448 }
5449
5450 static void InitMixer()
5451 {
5452   OpenAudio();
5453
5454   StartMixer();
5455 }
5456
5457 void InitGfx()
5458 {
5459   struct GraphicInfo *graphic_info_last = graphic_info;
5460   char *filename_font_initial = NULL;
5461   char *filename_anim_initial = NULL;
5462   Bitmap *bitmap_font_initial = NULL;
5463   int font_height;
5464   int i, j;
5465
5466   /* determine settings for initial font (for displaying startup messages) */
5467   for (i = 0; image_config[i].token != NULL; i++)
5468   {
5469     for (j = 0; j < NUM_INITIAL_FONTS; j++)
5470     {
5471       char font_token[128];
5472       int len_font_token;
5473
5474       sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1);
5475       len_font_token = strlen(font_token);
5476
5477       if (strEqual(image_config[i].token, font_token))
5478         filename_font_initial = image_config[i].value;
5479       else if (strlen(image_config[i].token) > len_font_token &&
5480                strncmp(image_config[i].token, font_token, len_font_token) == 0)
5481       {
5482         if (strEqual(&image_config[i].token[len_font_token], ".x"))
5483           font_initial[j].src_x = atoi(image_config[i].value);
5484         else if (strEqual(&image_config[i].token[len_font_token], ".y"))
5485           font_initial[j].src_y = atoi(image_config[i].value);
5486         else if (strEqual(&image_config[i].token[len_font_token], ".width"))
5487           font_initial[j].width = atoi(image_config[i].value);
5488         else if (strEqual(&image_config[i].token[len_font_token], ".height"))
5489           font_initial[j].height = atoi(image_config[i].value);
5490       }
5491     }
5492   }
5493
5494   for (j = 0; j < NUM_INITIAL_FONTS; j++)
5495   {
5496     font_initial[j].num_chars = DEFAULT_NUM_CHARS_PER_FONT;
5497     font_initial[j].num_chars_per_line = DEFAULT_NUM_CHARS_PER_LINE;
5498   }
5499
5500   if (filename_font_initial == NULL)    /* should not happen */
5501     Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
5502
5503   /* create additional image buffers for double-buffering and cross-fading */
5504   bitmap_db_cross = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
5505   bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
5506   bitmap_db_panel = CreateBitmap(DXSIZE, DYSIZE, DEFAULT_DEPTH);
5507   bitmap_db_door  = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
5508   bitmap_db_toons = CreateBitmap(FULL_SXSIZE, FULL_SYSIZE, DEFAULT_DEPTH);
5509
5510   /* initialize screen properties */
5511   InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
5512                    REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
5513                    bitmap_db_field);
5514   InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
5515   InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
5516   InitGfxWindowInfo(WIN_XSIZE, WIN_YSIZE);
5517   InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
5518   InitGfxCustomArtworkInfo();
5519
5520   bitmap_font_initial = LoadCustomImage(filename_font_initial);
5521
5522   for (j = 0; j < NUM_INITIAL_FONTS; j++)
5523     font_initial[j].bitmap = bitmap_font_initial;
5524
5525   InitFontGraphicInfo();
5526
5527   font_height = getFontHeight(FC_RED);
5528
5529 #if 1
5530   DrawInitText(getWindowTitleString(), 20, FC_YELLOW);
5531 #else
5532   DrawInitText(getProgramInitString(), 20, FC_YELLOW);
5533 #endif
5534   DrawInitText(PROGRAM_COPYRIGHT_STRING, 50, FC_RED);
5535   DrawInitText(PROGRAM_WEBSITE_STRING, WIN_YSIZE - 20 - font_height, FC_RED);
5536
5537   DrawInitText("Loading graphics", 120, FC_GREEN);
5538
5539 #if 1
5540 #if 1
5541   /* initialize busy animation with default values */
5542   int parameter[NUM_GFX_ARGS];
5543   for (i = 0; i < NUM_GFX_ARGS; i++)
5544     parameter[i] = get_graphic_parameter_value(image_config_suffix[i].value,
5545                                                image_config_suffix[i].token,
5546                                                image_config_suffix[i].type);
5547 #if 0
5548   for (i = 0; i < NUM_GFX_ARGS; i++)
5549     printf("::: '%s' => %d\n", image_config_suffix[i].token, parameter[i]);
5550 #endif
5551 #endif
5552
5553   /* determine settings for busy animation (when displaying startup messages) */
5554   for (i = 0; image_config[i].token != NULL; i++)
5555   {
5556     char *anim_token = CONFIG_TOKEN_GLOBAL_BUSY;
5557     int len_anim_token = strlen(anim_token);
5558
5559     if (strEqual(image_config[i].token, anim_token))
5560       filename_anim_initial = image_config[i].value;
5561     else if (strlen(image_config[i].token) > len_anim_token &&
5562              strncmp(image_config[i].token, anim_token, len_anim_token) == 0)
5563     {
5564 #if 1
5565       for (j = 0; image_config_suffix[j].token != NULL; j++)
5566       {
5567         if (strEqual(&image_config[i].token[len_anim_token],
5568                      image_config_suffix[j].token))
5569           parameter[j] =
5570             get_graphic_parameter_value(image_config[i].value,
5571                                         image_config_suffix[j].token,
5572                                         image_config_suffix[j].type);
5573       }
5574 #else
5575       if (strEqual(&image_config[i].token[len_anim_token], ".x"))
5576         anim_initial.src_x = atoi(image_config[i].value);
5577       else if (strEqual(&image_config[i].token[len_anim_token], ".y"))
5578         anim_initial.src_y = atoi(image_config[i].value);
5579       else if (strEqual(&image_config[i].token[len_anim_token], ".width"))
5580         anim_initial.width = atoi(image_config[i].value);
5581       else if (strEqual(&image_config[i].token[len_anim_token], ".height"))
5582         anim_initial.height = atoi(image_config[i].value);
5583       else if (strEqual(&image_config[i].token[len_anim_token], ".frames"))
5584         anim_initial.anim_frames = atoi(image_config[i].value);
5585       else if (strEqual(&image_config[i].token[len_anim_token],
5586                         ".frames_per_line"))
5587         anim_initial.anim_frames_per_line = atoi(image_config[i].value);
5588       else if (strEqual(&image_config[i].token[len_anim_token], ".delay"))
5589         anim_initial.anim_delay = atoi(image_config[i].value);
5590 #endif
5591     }
5592   }
5593
5594 #if defined(CREATE_SPECIAL_EDITION_RND_JUE)
5595   filename_anim_initial = "loading.pcx";
5596
5597   parameter[GFX_ARG_X] = 0;
5598   parameter[GFX_ARG_Y] = 0;
5599   parameter[GFX_ARG_WIDTH] = 128;
5600   parameter[GFX_ARG_HEIGHT] = 40;
5601   parameter[GFX_ARG_FRAMES] = 32;
5602   parameter[GFX_ARG_DELAY] = 4;
5603   parameter[GFX_ARG_FRAMES_PER_LINE] = ARG_UNDEFINED_VALUE;
5604 #endif
5605
5606   if (filename_anim_initial == NULL)    /* should not happen */
5607     Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_GLOBAL_BUSY);
5608
5609   anim_initial.bitmap = LoadCustomImage(filename_anim_initial);
5610
5611   graphic_info = &anim_initial;         /* graphic == 0 => anim_initial */
5612
5613   set_graphic_parameters_ext(0, parameter, anim_initial.bitmap);
5614
5615 #if 0
5616   printf("::: INIT_GFX: anim_frames_per_line == %d [%d / %d] [%d, %d]\n",
5617          graphic_info[0].anim_frames_per_line,
5618          get_scaled_graphic_width(0),
5619          graphic_info[0].width,
5620          getOriginalImageWidthFromImageID(0),
5621          graphic_info[0].scale_up_factor);
5622 #endif
5623
5624   graphic_info = graphic_info_last;
5625
5626   init.busy.width  = anim_initial.width;
5627   init.busy.height = anim_initial.height;
5628
5629   InitMenuDesignSettings_Static();
5630   InitGfxDrawBusyAnimFunction(DrawInitAnim);
5631 #endif
5632 }
5633
5634 void RedrawBackground()
5635 {
5636   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
5637              0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
5638
5639   redraw_mask = REDRAW_ALL;
5640 }
5641
5642 void InitGfxBackground()
5643 {
5644   int x, y;
5645
5646   fieldbuffer = bitmap_db_field;
5647   SetDrawtoField(DRAW_BACKBUFFER);
5648
5649 #if 1
5650   ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE);
5651 #else
5652   RedrawBackground();
5653
5654   ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
5655   ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
5656 #endif
5657
5658   for (x = 0; x < MAX_BUF_XSIZE; x++)
5659     for (y = 0; y < MAX_BUF_YSIZE; y++)
5660       redraw[x][y] = 0;
5661   redraw_tiles = 0;
5662   redraw_mask = REDRAW_ALL;
5663 }
5664
5665 static void InitLevelInfo()
5666 {
5667   LoadLevelInfo();                              /* global level info */
5668   LoadLevelSetup_LastSeries();                  /* last played series info */
5669   LoadLevelSetup_SeriesInfo();                  /* last played level info */
5670 }
5671
5672 static void InitLevelArtworkInfo()
5673 {
5674   LoadLevelArtworkInfo();
5675 }
5676
5677 static void InitImages()
5678 {
5679   print_timestamp_init("InitImages");
5680
5681 #if 0
5682   printf("::: leveldir_current->identifier == '%s'\n",
5683          leveldir_current == NULL ? "[NULL]" : leveldir_current->identifier);
5684   printf("::: leveldir_current->graphics_path == '%s'\n",
5685          leveldir_current == NULL ? "[NULL]" : leveldir_current->graphics_path);
5686   printf("::: leveldir_current->graphics_set == '%s'\n",
5687          leveldir_current == NULL ? "[NULL]" : leveldir_current->graphics_set);
5688   printf("::: getLevelArtworkSet(ARTWORK_TYPE_GRAPHICS) == '%s'\n",
5689          leveldir_current == NULL ? "[NULL]" : LEVELDIR_ARTWORK_SET(leveldir_current, ARTWORK_TYPE_GRAPHICS));
5690 #endif
5691
5692   setLevelArtworkDir(artwork.gfx_first);
5693
5694 #if 0
5695   printf("::: leveldir_current->identifier == '%s'\n",
5696          leveldir_current == NULL ? "[NULL]" : leveldir_current->identifier);
5697   printf("::: leveldir_current->graphics_path == '%s'\n",
5698          leveldir_current == NULL ? "[NULL]" : leveldir_current->graphics_path);
5699   printf("::: leveldir_current->graphics_set == '%s'\n",
5700          leveldir_current == NULL ? "[NULL]" : leveldir_current->graphics_set);
5701   printf("::: getLevelArtworkSet(ARTWORK_TYPE_GRAPHICS) == '%s'\n",
5702          leveldir_current == NULL ? "[NULL]" : LEVELDIR_ARTWORK_SET(leveldir_current, ARTWORK_TYPE_GRAPHICS));
5703 #endif
5704
5705 #if 0
5706   printf("::: InitImages for '%s' ['%s', '%s'] ['%s', '%s']\n",
5707          leveldir_current->identifier,
5708          artwork.gfx_current_identifier,
5709          artwork.gfx_current->identifier,
5710          leveldir_current->graphics_set,
5711          leveldir_current->graphics_path);
5712 #endif
5713
5714   UPDATE_BUSY_STATE();
5715
5716   ReloadCustomImages();
5717   print_timestamp_time("ReloadCustomImages");
5718
5719   UPDATE_BUSY_STATE();
5720
5721   LoadCustomElementDescriptions();
5722   print_timestamp_time("LoadCustomElementDescriptions");
5723
5724   UPDATE_BUSY_STATE();
5725
5726   LoadMenuDesignSettings();
5727   print_timestamp_time("LoadMenuDesignSettings");
5728
5729   UPDATE_BUSY_STATE();
5730
5731   ReinitializeGraphics();
5732   print_timestamp_time("ReinitializeGraphics");
5733
5734   UPDATE_BUSY_STATE();
5735
5736   print_timestamp_done("InitImages");
5737 }
5738
5739 static void InitSound(char *identifier)
5740 {
5741   print_timestamp_init("InitSound");
5742
5743   if (identifier == NULL)
5744     identifier = artwork.snd_current->identifier;
5745
5746   /* set artwork path to send it to the sound server process */
5747   setLevelArtworkDir(artwork.snd_first);
5748
5749   InitReloadCustomSounds(identifier);
5750   print_timestamp_time("InitReloadCustomSounds");
5751
5752   ReinitializeSounds();
5753   print_timestamp_time("ReinitializeSounds");
5754
5755   print_timestamp_done("InitSound");
5756 }
5757
5758 static void InitMusic(char *identifier)
5759 {
5760   print_timestamp_init("InitMusic");
5761
5762   if (identifier == NULL)
5763     identifier = artwork.mus_current->identifier;
5764
5765   /* set artwork path to send it to the sound server process */
5766   setLevelArtworkDir(artwork.mus_first);
5767
5768   InitReloadCustomMusic(identifier);
5769   print_timestamp_time("InitReloadCustomMusic");
5770
5771   ReinitializeMusic();
5772   print_timestamp_time("ReinitializeMusic");
5773
5774   print_timestamp_done("InitMusic");
5775 }
5776
5777 void InitNetworkServer()
5778 {
5779 #if defined(NETWORK_AVALIABLE)
5780   int nr_wanted;
5781 #endif
5782
5783   if (!options.network)
5784     return;
5785
5786 #if defined(NETWORK_AVALIABLE)
5787   nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
5788
5789   if (!ConnectToServer(options.server_host, options.server_port))
5790     Error(ERR_EXIT, "cannot connect to network game server");
5791
5792   SendToServer_PlayerName(setup.player_name);
5793   SendToServer_ProtocolVersion();
5794
5795   if (nr_wanted)
5796     SendToServer_NrWanted(nr_wanted);
5797 #endif
5798 }
5799
5800 static boolean CheckArtworkConfigForCustomElements(char *filename)
5801 {
5802   SetupFileHash *setup_file_hash;
5803   boolean redefined_ce_found = FALSE;
5804
5805   /* !!! CACHE THIS BY USING HASH 'filename' => 'true/false' !!! */
5806
5807   if ((setup_file_hash = loadSetupFileHash(filename)) != NULL)
5808   {
5809     BEGIN_HASH_ITERATION(setup_file_hash, itr)
5810     {
5811       char *token = HASH_ITERATION_TOKEN(itr);
5812
5813       if (strPrefix(token, "custom_"))
5814       {
5815         redefined_ce_found = TRUE;
5816
5817         break;
5818       }
5819     }
5820     END_HASH_ITERATION(setup_file_hash, itr)
5821
5822     freeSetupFileHash(setup_file_hash);
5823   }
5824
5825   return redefined_ce_found;
5826 }
5827
5828 static boolean CheckArtworkTypeForRedefinedCustomElements(int type)
5829 {
5830   char *filename_base, *filename_local;
5831   boolean redefined_ce_found = FALSE;
5832
5833   setLevelArtworkDir(ARTWORK_FIRST_NODE(artwork, type));
5834
5835 #if 0
5836   printf("::: leveldir_current->identifier == '%s'\n",
5837          leveldir_current == NULL ? "[NULL]" : leveldir_current->identifier);
5838   printf("::: leveldir_current->graphics_path == '%s'\n",
5839          leveldir_current == NULL ? "[NULL]" : leveldir_current->graphics_path);
5840   printf("::: leveldir_current->graphics_set == '%s'\n",
5841          leveldir_current == NULL ? "[NULL]" : leveldir_current->graphics_set);
5842   printf("::: getLevelArtworkSet(ARTWORK_TYPE_GRAPHICS) == '%s'\n",
5843          leveldir_current == NULL ? "[NULL]" :
5844          LEVELDIR_ARTWORK_SET(leveldir_current, type));
5845 #endif
5846
5847   /* first look for special artwork configured in level series config */
5848   filename_base = getCustomArtworkLevelConfigFilename(type);
5849
5850 #if 0
5851   printf("::: filename_base == '%s'\n", filename_base);
5852 #endif
5853
5854   if (fileExists(filename_base))
5855     redefined_ce_found |= CheckArtworkConfigForCustomElements(filename_base);
5856
5857   filename_local = getCustomArtworkConfigFilename(type);
5858
5859 #if 0
5860   printf("::: filename_local == '%s'\n", filename_local);
5861 #endif
5862
5863   if (filename_local != NULL && !strEqual(filename_base, filename_local))
5864     redefined_ce_found |= CheckArtworkConfigForCustomElements(filename_local);
5865
5866 #if 0
5867   printf("::: redefined_ce_found == %d\n", redefined_ce_found);
5868 #endif
5869
5870   return redefined_ce_found;
5871 }
5872
5873 static void InitOverrideArtwork()
5874 {
5875   boolean redefined_ce_found = FALSE;
5876
5877   /* to check if this level set redefines any CEs, do not use overriding */
5878   gfx.override_level_graphics = FALSE;
5879   gfx.override_level_sounds   = FALSE;
5880   gfx.override_level_music    = FALSE;
5881
5882   /* now check if this level set has definitions for custom elements */
5883   if (setup.override_level_graphics == AUTO ||
5884       setup.override_level_sounds   == AUTO ||
5885       setup.override_level_music    == AUTO)
5886     redefined_ce_found =
5887       (CheckArtworkTypeForRedefinedCustomElements(ARTWORK_TYPE_GRAPHICS) |
5888        CheckArtworkTypeForRedefinedCustomElements(ARTWORK_TYPE_SOUNDS) |
5889        CheckArtworkTypeForRedefinedCustomElements(ARTWORK_TYPE_MUSIC));
5890
5891 #if 0
5892   printf("::: redefined_ce_found == %d\n", redefined_ce_found);
5893 #endif
5894
5895   if (redefined_ce_found)
5896   {
5897     /* this level set has CE definitions: change "AUTO" to "FALSE" */
5898     gfx.override_level_graphics = (setup.override_level_graphics == TRUE);
5899     gfx.override_level_sounds   = (setup.override_level_sounds   == TRUE);
5900     gfx.override_level_music    = (setup.override_level_music    == TRUE);
5901   }
5902   else
5903   {
5904     /* this level set has no CE definitions: change "AUTO" to "TRUE" */
5905     gfx.override_level_graphics = (setup.override_level_graphics != FALSE);
5906     gfx.override_level_sounds   = (setup.override_level_sounds   != FALSE);
5907     gfx.override_level_music    = (setup.override_level_music    != FALSE);
5908   }
5909
5910 #if 0
5911   printf("::: => %d, %d, %d\n",
5912          gfx.override_level_graphics,
5913          gfx.override_level_sounds,
5914          gfx.override_level_music);
5915 #endif
5916 }
5917
5918 static char *getNewArtworkIdentifier(int type)
5919 {
5920   static char *leveldir_current_identifier[3] = { NULL, NULL, NULL };
5921   static boolean last_override_level_artwork[3] = { FALSE, FALSE, FALSE };
5922   static boolean last_has_level_artwork_set[3] = { FALSE, FALSE, FALSE };
5923   static boolean initialized[3] = { FALSE, FALSE, FALSE };
5924   TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
5925 #if 1
5926   boolean setup_override_artwork = GFX_OVERRIDE_ARTWORK(type);
5927 #else
5928   boolean setup_override_artwork = SETUP_OVERRIDE_ARTWORK(setup, type);
5929 #endif
5930   char *setup_artwork_set = SETUP_ARTWORK_SET(setup, type);
5931   char *leveldir_identifier = leveldir_current->identifier;
5932 #if 1
5933   /* !!! setLevelArtworkDir() should be moved to an earlier stage !!! */
5934   char *leveldir_artwork_set = setLevelArtworkDir(artwork_first_node);
5935 #else
5936   char *leveldir_artwork_set = LEVELDIR_ARTWORK_SET(leveldir_current, type);
5937 #endif
5938   boolean has_level_artwork_set = (leveldir_artwork_set != NULL);
5939   char *artwork_current_identifier;
5940   char *artwork_new_identifier = NULL;  /* default: nothing has changed */
5941
5942   /* leveldir_current may be invalid (level group, parent link) */
5943   if (!validLevelSeries(leveldir_current))
5944     return NULL;
5945
5946   /* 1st step: determine artwork set to be activated in descending order:
5947      --------------------------------------------------------------------
5948      1. setup artwork (when configured to override everything else)
5949      2. artwork set configured in "levelinfo.conf" of current level set
5950         (artwork in level directory will have priority when loading later)
5951      3. artwork in level directory (stored in artwork sub-directory)
5952      4. setup artwork (currently configured in setup menu) */
5953
5954   if (setup_override_artwork)
5955     artwork_current_identifier = setup_artwork_set;
5956   else if (leveldir_artwork_set != NULL)
5957     artwork_current_identifier = leveldir_artwork_set;
5958   else if (getTreeInfoFromIdentifier(artwork_first_node, leveldir_identifier))
5959     artwork_current_identifier = leveldir_identifier;
5960   else
5961     artwork_current_identifier = setup_artwork_set;
5962
5963
5964   /* 2nd step: check if it is really needed to reload artwork set
5965      ------------------------------------------------------------ */
5966
5967 #if 0
5968   if (type == ARTWORK_TYPE_GRAPHICS)
5969     printf("::: 0: '%s' ['%s', '%s'] ['%s' ('%s')]\n",
5970            artwork_new_identifier,
5971            ARTWORK_CURRENT_IDENTIFIER(artwork, type),
5972            artwork_current_identifier,
5973            leveldir_current->graphics_set,
5974            leveldir_current->identifier);
5975 #endif
5976
5977   /* ---------- reload if level set and also artwork set has changed ------- */
5978   if (leveldir_current_identifier[type] != leveldir_identifier &&
5979       (last_has_level_artwork_set[type] || has_level_artwork_set))
5980     artwork_new_identifier = artwork_current_identifier;
5981
5982   leveldir_current_identifier[type] = leveldir_identifier;
5983   last_has_level_artwork_set[type] = has_level_artwork_set;
5984
5985 #if 0
5986   if (type == ARTWORK_TYPE_GRAPHICS)
5987     printf("::: 1: '%s'\n", artwork_new_identifier);
5988 #endif
5989
5990   /* ---------- reload if "override artwork" setting has changed ----------- */
5991   if (last_override_level_artwork[type] != setup_override_artwork)
5992     artwork_new_identifier = artwork_current_identifier;
5993
5994   last_override_level_artwork[type] = setup_override_artwork;
5995
5996 #if 0
5997   if (type == ARTWORK_TYPE_GRAPHICS)
5998     printf("::: 2: '%s'\n", artwork_new_identifier);
5999 #endif
6000
6001   /* ---------- reload if current artwork identifier has changed ----------- */
6002   if (!strEqual(ARTWORK_CURRENT_IDENTIFIER(artwork, type),
6003                 artwork_current_identifier))
6004     artwork_new_identifier = artwork_current_identifier;
6005
6006   *(ARTWORK_CURRENT_IDENTIFIER_PTR(artwork, type))= artwork_current_identifier;
6007
6008 #if 0
6009   if (type == ARTWORK_TYPE_GRAPHICS)
6010     printf("::: 3: '%s'\n", artwork_new_identifier);
6011 #endif
6012
6013   /* ---------- do not reload directly after starting ---------------------- */
6014   if (!initialized[type])
6015     artwork_new_identifier = NULL;
6016
6017   initialized[type] = TRUE;
6018
6019 #if 0
6020   if (type == ARTWORK_TYPE_GRAPHICS)
6021     printf("::: 4: '%s'\n", artwork_new_identifier);
6022 #endif
6023
6024 #if 0
6025   if (type == ARTWORK_TYPE_GRAPHICS)
6026     printf("CHECKING OLD/NEW GFX:\n- OLD: %s\n- NEW: %s ['%s', '%s'] ['%s']\n",
6027            artwork.gfx_current_identifier, artwork_current_identifier,
6028            artwork.gfx_current->identifier, leveldir_current->graphics_set,
6029            artwork_new_identifier);
6030 #endif
6031
6032   return artwork_new_identifier;
6033 }
6034
6035 void ReloadCustomArtwork(int force_reload)
6036 {
6037   int last_game_status = game_status;   /* save current game status */
6038   char *gfx_new_identifier;
6039   char *snd_new_identifier;
6040   char *mus_new_identifier;
6041   boolean force_reload_gfx = (force_reload & (1 << ARTWORK_TYPE_GRAPHICS));
6042   boolean force_reload_snd = (force_reload & (1 << ARTWORK_TYPE_SOUNDS));
6043   boolean force_reload_mus = (force_reload & (1 << ARTWORK_TYPE_MUSIC));
6044   boolean reload_needed;
6045
6046   InitOverrideArtwork();
6047
6048   force_reload_gfx |= AdjustGraphicsForEMC();
6049
6050   gfx_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_GRAPHICS);
6051   snd_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_SOUNDS);
6052   mus_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_MUSIC);
6053
6054   reload_needed = (gfx_new_identifier != NULL || force_reload_gfx ||
6055                    snd_new_identifier != NULL || force_reload_snd ||
6056                    mus_new_identifier != NULL || force_reload_mus);
6057
6058   if (!reload_needed)
6059     return;
6060
6061   print_timestamp_init("ReloadCustomArtwork");
6062
6063   game_status = GAME_MODE_LOADING;
6064
6065   FadeOut(REDRAW_ALL);
6066
6067 #if 1
6068   ClearRectangle(drawto, 0, 0, WIN_XSIZE, WIN_YSIZE);
6069 #else
6070   ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
6071 #endif
6072   print_timestamp_time("ClearRectangle");
6073
6074 #if 0
6075   printf("::: fading in ... %d\n", fading.fade_mode);
6076 #endif
6077   FadeIn(REDRAW_ALL);
6078 #if 0
6079   printf("::: done\n");
6080 #endif
6081
6082   if (gfx_new_identifier != NULL || force_reload_gfx)
6083   {
6084 #if 0
6085     printf("RELOADING GRAPHICS '%s' -> '%s' ['%s', '%s']\n",
6086            artwork.gfx_current_identifier,
6087            gfx_new_identifier,
6088            artwork.gfx_current->identifier,
6089            leveldir_current->graphics_set);
6090 #endif
6091
6092     InitImages();
6093     print_timestamp_time("InitImages");
6094   }
6095
6096   if (snd_new_identifier != NULL || force_reload_snd)
6097   {
6098     InitSound(snd_new_identifier);
6099     print_timestamp_time("InitSound");
6100   }
6101
6102   if (mus_new_identifier != NULL || force_reload_mus)
6103   {
6104     InitMusic(mus_new_identifier);
6105     print_timestamp_time("InitMusic");
6106   }
6107
6108   game_status = last_game_status;       /* restore current game status */
6109
6110 #if 0
6111   printf("::: ----------------DELAY 1 ...\n");
6112   Delay(3000);
6113 #endif
6114
6115 #if 0
6116   printf("::: FadeOut @ ReloadCustomArtwork ...\n");
6117 #endif
6118   FadeOut(REDRAW_ALL);
6119 #if 0
6120   printf("::: FadeOut @ ReloadCustomArtwork done\n");
6121 #endif
6122
6123   RedrawBackground();
6124
6125   /* force redraw of (open or closed) door graphics */
6126   SetDoorState(DOOR_OPEN_ALL);
6127   CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
6128
6129 #if 1
6130 #if 1
6131 #if 1
6132   FadeSetEnterScreen();
6133   FadeSkipNextFadeOut();
6134   // FadeSetDisabled();
6135 #else
6136   FadeSkipNext();
6137 #endif
6138 #else
6139   fading = fading_none;
6140 #endif
6141 #endif
6142
6143 #if 0
6144   redraw_mask = REDRAW_ALL;
6145 #endif
6146
6147   print_timestamp_done("ReloadCustomArtwork");
6148 }
6149
6150 void KeyboardAutoRepeatOffUnlessAutoplay()
6151 {
6152   if (global.autoplay_leveldir == NULL)
6153     KeyboardAutoRepeatOff();
6154 }
6155
6156
6157 /* ========================================================================= */
6158 /* OpenAll()                                                                 */
6159 /* ========================================================================= */
6160
6161 void OpenAll()
6162 {
6163   print_timestamp_init("OpenAll");
6164
6165   game_status = GAME_MODE_LOADING;
6166
6167   InitGlobal();                 /* initialize some global variables */
6168
6169   if (options.execute_command)
6170     Execute_Command(options.execute_command);
6171
6172   if (options.serveronly)
6173   {
6174 #if defined(PLATFORM_UNIX)
6175     NetworkServer(options.server_port, options.serveronly);
6176 #else
6177     Error(ERR_WARN, "networking only supported in Unix version");
6178 #endif
6179
6180     exit(0);                    /* never reached, server loops forever */
6181   }
6182
6183   InitSetup();
6184
6185   InitGameInfo();
6186   InitPlayerInfo();
6187   InitArtworkInfo();            /* needed before loading gfx, sound & music */
6188   InitArtworkConfig();          /* needed before forking sound child process */
6189   InitMixer();
6190
6191   InitCounter();
6192
6193   InitRND(NEW_RANDOMIZE);
6194   InitSimpleRandom(NEW_RANDOMIZE);
6195
6196   InitJoysticks();
6197
6198   print_timestamp_time("[pre-video]");
6199
6200   InitVideoDisplay();
6201   InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
6202
6203   InitEventFilter(FilterMouseMotionEvents);
6204
6205   InitElementPropertiesStatic();
6206   InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
6207   InitElementPropertiesGfxElement();
6208
6209   print_timestamp_time("[post-video]");
6210
6211   InitGfx();
6212
6213   print_timestamp_time("InitGfx");
6214
6215   InitLevelInfo();
6216   print_timestamp_time("InitLevelInfo");
6217
6218   InitLevelArtworkInfo();
6219   print_timestamp_time("InitLevelArtworkInfo");
6220
6221   InitOverrideArtwork();        /* needs to know current level directory */
6222   print_timestamp_time("InitOverrideArtwork");
6223
6224   InitImages();                 /* needs to know current level directory */
6225   print_timestamp_time("InitImages");
6226
6227   InitSound(NULL);              /* needs to know current level directory */
6228   print_timestamp_time("InitSound");
6229
6230   InitMusic(NULL);              /* needs to know current level directory */
6231   print_timestamp_time("InitMusic");
6232
6233   InitGfxBackground();
6234
6235 #if 1
6236   em_open_all();
6237 #endif
6238
6239 #if 1
6240   sp_open_all();
6241 #endif
6242
6243   if (global.autoplay_leveldir)
6244   {
6245     AutoPlayTape();
6246     return;
6247   }
6248   else if (global.convert_leveldir)
6249   {
6250     ConvertLevels();
6251     return;
6252   }
6253   else if (global.create_images_dir)
6254   {
6255     CreateLevelSketchImages();
6256     return;
6257   }
6258
6259   game_status = GAME_MODE_MAIN;
6260
6261 #if 1
6262   FadeSetEnterScreen();
6263   if (!(fading.fade_mode & FADE_TYPE_TRANSFORM))
6264     FadeSkipNextFadeOut();
6265   // FadeSetDisabled();
6266 #else
6267   fading = fading_none;
6268 #endif
6269
6270   print_timestamp_time("[post-artwork]");
6271
6272   print_timestamp_done("OpenAll");
6273
6274   DrawMainMenu();
6275
6276   InitNetworkServer();
6277 }
6278
6279 void CloseAllAndExit(int exit_value)
6280 {
6281   StopSounds();
6282   FreeAllSounds();
6283   FreeAllMusic();
6284   CloseAudio();         /* called after freeing sounds (needed for SDL) */
6285
6286 #if 1
6287   em_close_all();
6288 #endif
6289
6290 #if 1
6291   sp_close_all();
6292 #endif
6293
6294   FreeAllImages();
6295
6296 #if defined(TARGET_SDL)
6297   if (network_server)   /* terminate network server */
6298     SDL_KillThread(server_thread);
6299 #endif
6300
6301   CloseVideoDisplay();
6302   ClosePlatformDependentStuff();
6303
6304   if (exit_value != 0)
6305     NotifyUserAboutErrorFile();
6306
6307   exit(exit_value);
6308 }