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