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