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