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