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