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