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