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