rnd-20100623-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   global.use_envelope_request = FALSE;  /* !!! MOVE TO ARTWORK CONFIG !!! */
5128 }
5129
5130 void Execute_Command(char *command)
5131 {
5132   int i;
5133
5134   if (strEqual(command, "print graphicsinfo.conf"))
5135   {
5136     printf("# You can configure additional/alternative image files here.\n");
5137     printf("# (The entries below are default and therefore commented out.)\n");
5138     printf("\n");
5139     printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
5140     printf("\n");
5141     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
5142     printf("\n");
5143
5144     for (i = 0; image_config[i].token != NULL; i++)
5145       printf("# %s\n", getFormattedSetupEntry(image_config[i].token,
5146                                               image_config[i].value));
5147
5148     exit(0);
5149   }
5150   else if (strEqual(command, "print soundsinfo.conf"))
5151   {
5152     printf("# You can configure additional/alternative sound files here.\n");
5153     printf("# (The entries below are default and therefore commented out.)\n");
5154     printf("\n");
5155     printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
5156     printf("\n");
5157     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
5158     printf("\n");
5159
5160     for (i = 0; sound_config[i].token != NULL; i++)
5161       printf("# %s\n", getFormattedSetupEntry(sound_config[i].token,
5162                                               sound_config[i].value));
5163
5164     exit(0);
5165   }
5166   else if (strEqual(command, "print musicinfo.conf"))
5167   {
5168     printf("# You can configure additional/alternative music files here.\n");
5169     printf("# (The entries below are default and therefore commented out.)\n");
5170     printf("\n");
5171     printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
5172     printf("\n");
5173     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
5174     printf("\n");
5175
5176     for (i = 0; music_config[i].token != NULL; i++)
5177       printf("# %s\n", getFormattedSetupEntry(music_config[i].token,
5178                                               music_config[i].value));
5179
5180     exit(0);
5181   }
5182   else if (strEqual(command, "print editorsetup.conf"))
5183   {
5184     printf("# You can configure your personal editor element list here.\n");
5185     printf("# (The entries below are default and therefore commented out.)\n");
5186     printf("\n");
5187
5188     /* this is needed to be able to check element list for cascade elements */
5189     InitElementPropertiesStatic();
5190     InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
5191
5192     PrintEditorElementList();
5193
5194     exit(0);
5195   }
5196   else if (strEqual(command, "print helpanim.conf"))
5197   {
5198     printf("# You can configure different element help animations here.\n");
5199     printf("# (The entries below are default and therefore commented out.)\n");
5200     printf("\n");
5201
5202     for (i = 0; helpanim_config[i].token != NULL; i++)
5203     {
5204       printf("# %s\n", getFormattedSetupEntry(helpanim_config[i].token,
5205                                               helpanim_config[i].value));
5206
5207       if (strEqual(helpanim_config[i].token, "end"))
5208         printf("#\n");
5209     }
5210
5211     exit(0);
5212   }
5213   else if (strEqual(command, "print helptext.conf"))
5214   {
5215     printf("# You can configure different element help text here.\n");
5216     printf("# (The entries below are default and therefore commented out.)\n");
5217     printf("\n");
5218
5219     for (i = 0; helptext_config[i].token != NULL; i++)
5220       printf("# %s\n", getFormattedSetupEntry(helptext_config[i].token,
5221                                               helptext_config[i].value));
5222
5223     exit(0);
5224   }
5225   else if (strPrefix(command, "dump level "))
5226   {
5227     char *filename = &command[11];
5228
5229     if (!fileExists(filename))
5230       Error(ERR_EXIT, "cannot open file '%s'", filename);
5231
5232     LoadLevelFromFilename(&level, filename);
5233     DumpLevel(&level);
5234
5235     exit(0);
5236   }
5237   else if (strPrefix(command, "dump tape "))
5238   {
5239     char *filename = &command[10];
5240
5241     if (!fileExists(filename))
5242       Error(ERR_EXIT, "cannot open file '%s'", filename);
5243
5244     LoadTapeFromFilename(filename);
5245     DumpTape(&tape);
5246
5247     exit(0);
5248   }
5249   else if (strPrefix(command, "autoplay "))
5250   {
5251     char *str_ptr = getStringCopy(&command[9]); /* read command parameters */
5252
5253     while (*str_ptr != '\0')                    /* continue parsing string */
5254     {
5255       /* cut leading whitespace from string, replace it by string terminator */
5256       while (*str_ptr == ' ' || *str_ptr == '\t')
5257         *str_ptr++ = '\0';
5258
5259       if (*str_ptr == '\0')                     /* end of string reached */
5260         break;
5261
5262       if (global.autoplay_leveldir == NULL)     /* read level set string */
5263       {
5264         global.autoplay_leveldir = str_ptr;
5265         global.autoplay_all = TRUE;             /* default: play all tapes */
5266
5267         for (i = 0; i < MAX_TAPES_PER_SET; i++)
5268           global.autoplay_level[i] = FALSE;
5269       }
5270       else                                      /* read level number string */
5271       {
5272         int level_nr = atoi(str_ptr);           /* get level_nr value */
5273
5274         if (level_nr >= 0 && level_nr < MAX_TAPES_PER_SET)
5275           global.autoplay_level[level_nr] = TRUE;
5276
5277         global.autoplay_all = FALSE;
5278       }
5279
5280       /* advance string pointer to the next whitespace (or end of string) */
5281       while (*str_ptr != ' ' && *str_ptr != '\t' && *str_ptr != '\0')
5282         str_ptr++;
5283     }
5284   }
5285   else if (strPrefix(command, "convert "))
5286   {
5287     char *str_copy = getStringCopy(strchr(command, ' ') + 1);
5288     char *str_ptr = strchr(str_copy, ' ');
5289
5290     global.convert_leveldir = str_copy;
5291     global.convert_level_nr = -1;
5292
5293     if (str_ptr != NULL)                        /* level number follows */
5294     {
5295       *str_ptr++ = '\0';                        /* terminate leveldir string */
5296       global.convert_level_nr = atoi(str_ptr);  /* get level_nr value */
5297     }
5298   }
5299   else if (strPrefix(command, "create images "))
5300   {
5301 #if defined(TARGET_SDL)
5302     global.create_images_dir = getStringCopy(&command[14]);
5303
5304     if (access(global.create_images_dir, W_OK) != 0)
5305       Error(ERR_EXIT, "image target directory '%s' not found or not writable",
5306             global.create_images_dir);
5307 #else
5308     Error(ERR_EXIT, "command only available for SDL target");
5309 #endif
5310   }
5311
5312 #if DEBUG
5313 #if defined(TARGET_SDL)
5314   else if (strEqual(command, "SDL_ListModes"))
5315   {
5316     SDL_Rect **modes;
5317     int i;
5318
5319     SDL_Init(SDL_INIT_VIDEO);
5320
5321     /* get available fullscreen/hardware modes */
5322     modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);
5323
5324     /* check if there are any modes available */
5325     if (modes == NULL)
5326     {
5327       printf("No modes available!\n");
5328
5329       exit(-1);
5330     }
5331
5332     /* check if our resolution is restricted */
5333     if (modes == (SDL_Rect **)-1)
5334     {
5335       printf("All resolutions available.\n");
5336     }
5337     else
5338     {
5339       printf("Available Modes:\n");
5340
5341       for(i = 0; modes[i]; i++)
5342         printf("  %d x %d\n", modes[i]->w, modes[i]->h);
5343     }
5344
5345     exit(0);
5346   }
5347 #endif
5348 #endif
5349
5350   else
5351   {
5352     Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
5353   }
5354 }
5355
5356 static void InitSetup()
5357 {
5358   LoadSetup();                                  /* global setup info */
5359
5360   /* set some options from setup file */
5361
5362   if (setup.options.verbose)
5363     options.verbose = TRUE;
5364 }
5365
5366 static void InitGameInfo()
5367 {
5368   game.restart_level = FALSE;
5369 }
5370
5371 static void InitPlayerInfo()
5372 {
5373   int i;
5374
5375   /* choose default local player */
5376   local_player = &stored_player[0];
5377
5378   for (i = 0; i < MAX_PLAYERS; i++)
5379     stored_player[i].connected = FALSE;
5380
5381   local_player->connected = TRUE;
5382 }
5383
5384 static void InitArtworkInfo()
5385 {
5386   LoadArtworkInfo();
5387 }
5388
5389 static char *get_string_in_brackets(char *string)
5390 {
5391   char *string_in_brackets = checked_malloc(strlen(string) + 3);
5392
5393   sprintf(string_in_brackets, "[%s]", string);
5394
5395   return string_in_brackets;
5396 }
5397
5398 static char *get_level_id_suffix(int id_nr)
5399 {
5400   char *id_suffix = checked_malloc(1 + 3 + 1);
5401
5402   if (id_nr < 0 || id_nr > 999)
5403     id_nr = 0;
5404
5405   sprintf(id_suffix, ".%03d", id_nr);
5406
5407   return id_suffix;
5408 }
5409
5410 #if 0
5411 static char *get_element_class_token(int element)
5412 {
5413   char *element_class_name = element_info[element].class_name;
5414   char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
5415
5416   sprintf(element_class_token, "[%s]", element_class_name);
5417
5418   return element_class_token;
5419 }
5420
5421 static char *get_action_class_token(int action)
5422 {
5423   char *action_class_name = &element_action_info[action].suffix[1];
5424   char *action_class_token = checked_malloc(strlen(action_class_name) + 3);
5425
5426   sprintf(action_class_token, "[%s]", action_class_name);
5427
5428   return action_class_token;
5429 }
5430 #endif
5431
5432 static void InitArtworkConfig()
5433 {
5434   static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
5435   static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + 1];
5436   static char *music_id_prefix[NUM_MUSIC_PREFIXES + 1];
5437   static char *action_id_suffix[NUM_ACTIONS + 1];
5438   static char *direction_id_suffix[NUM_DIRECTIONS_FULL + 1];
5439   static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
5440   static char *level_id_suffix[MAX_LEVELS + 1];
5441   static char *dummy[1] = { NULL };
5442   static char *ignore_generic_tokens[] =
5443   {
5444     "name",
5445     "sort_priority",
5446     NULL
5447   };
5448   static char **ignore_image_tokens;
5449   static char **ignore_sound_tokens;
5450   static char **ignore_music_tokens;
5451   int num_ignore_generic_tokens;
5452   int num_ignore_image_tokens;
5453   int num_ignore_sound_tokens;
5454   int num_ignore_music_tokens;
5455   int i;
5456
5457   /* dynamically determine list of generic tokens to be ignored */
5458   num_ignore_generic_tokens = 0;
5459   for (i = 0; ignore_generic_tokens[i] != NULL; i++)
5460     num_ignore_generic_tokens++;
5461
5462   /* dynamically determine list of image tokens to be ignored */
5463   num_ignore_image_tokens = num_ignore_generic_tokens;
5464   for (i = 0; image_config_vars[i].token != NULL; i++)
5465     num_ignore_image_tokens++;
5466   ignore_image_tokens =
5467     checked_malloc((num_ignore_image_tokens + 1) * sizeof(char *));
5468   for (i = 0; i < num_ignore_generic_tokens; i++)
5469     ignore_image_tokens[i] = ignore_generic_tokens[i];
5470   for (i = 0; i < num_ignore_image_tokens - num_ignore_generic_tokens; i++)
5471     ignore_image_tokens[num_ignore_generic_tokens + i] =
5472       image_config_vars[i].token;
5473   ignore_image_tokens[num_ignore_image_tokens] = NULL;
5474
5475   /* dynamically determine list of sound tokens to be ignored */
5476   num_ignore_sound_tokens = num_ignore_generic_tokens;
5477   ignore_sound_tokens =
5478     checked_malloc((num_ignore_sound_tokens + 1) * sizeof(char *));
5479   for (i = 0; i < num_ignore_generic_tokens; i++)
5480     ignore_sound_tokens[i] = ignore_generic_tokens[i];
5481   ignore_sound_tokens[num_ignore_sound_tokens] = NULL;
5482
5483   /* dynamically determine list of music tokens to be ignored */
5484   num_ignore_music_tokens = num_ignore_generic_tokens;
5485   ignore_music_tokens =
5486     checked_malloc((num_ignore_music_tokens + 1) * sizeof(char *));
5487   for (i = 0; i < num_ignore_generic_tokens; i++)
5488     ignore_music_tokens[i] = ignore_generic_tokens[i];
5489   ignore_music_tokens[num_ignore_music_tokens] = NULL;
5490
5491   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
5492     image_id_prefix[i] = element_info[i].token_name;
5493   for (i = 0; i < NUM_FONTS; i++)
5494     image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
5495   image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
5496
5497   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
5498     sound_id_prefix[i] = element_info[i].token_name;
5499   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
5500     sound_id_prefix[MAX_NUM_ELEMENTS + i] =
5501       get_string_in_brackets(element_info[i].class_name);
5502   sound_id_prefix[2 * MAX_NUM_ELEMENTS] = NULL;
5503
5504   for (i = 0; i < NUM_MUSIC_PREFIXES; i++)
5505     music_id_prefix[i] = music_prefix_info[i].prefix;
5506   music_id_prefix[NUM_MUSIC_PREFIXES] = NULL;
5507
5508   for (i = 0; i < NUM_ACTIONS; i++)
5509     action_id_suffix[i] = element_action_info[i].suffix;
5510   action_id_suffix[NUM_ACTIONS] = NULL;
5511
5512   for (i = 0; i < NUM_DIRECTIONS_FULL; i++)
5513     direction_id_suffix[i] = element_direction_info[i].suffix;
5514   direction_id_suffix[NUM_DIRECTIONS_FULL] = NULL;
5515
5516   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
5517     special_id_suffix[i] = special_suffix_info[i].suffix;
5518   special_id_suffix[NUM_SPECIAL_GFX_ARGS] = NULL;
5519
5520   for (i = 0; i < MAX_LEVELS; i++)
5521     level_id_suffix[i] = get_level_id_suffix(i);
5522   level_id_suffix[MAX_LEVELS] = NULL;
5523
5524   InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
5525                 image_id_prefix, action_id_suffix, direction_id_suffix,
5526                 special_id_suffix, ignore_image_tokens);
5527   InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
5528                 sound_id_prefix, action_id_suffix, dummy,
5529                 special_id_suffix, ignore_sound_tokens);
5530   InitMusicList(music_config, NUM_MUSIC_FILES, music_config_suffix,
5531                 music_id_prefix, special_id_suffix, level_id_suffix,
5532                 dummy, ignore_music_tokens);
5533 }
5534
5535 static void InitMixer()
5536 {
5537   OpenAudio();
5538
5539   StartMixer();
5540 }
5541
5542 void InitGfxBuffers()
5543 {
5544   ReCreateBitmap(&bitmap_db_store, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
5545   ReCreateBitmap(&bitmap_db_cross, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
5546   ReCreateBitmap(&bitmap_db_field, FXSIZE, FYSIZE, DEFAULT_DEPTH);
5547   ReCreateBitmap(&bitmap_db_panel, DXSIZE, DYSIZE, DEFAULT_DEPTH);
5548   ReCreateBitmap(&bitmap_db_door, 3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
5549   ReCreateBitmap(&bitmap_db_toons, FULL_SXSIZE, FULL_SYSIZE, DEFAULT_DEPTH);
5550
5551   /* initialize screen properties */
5552   InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
5553                    REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
5554                    bitmap_db_field);
5555   InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
5556   InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
5557   InitGfxWindowInfo(WIN_XSIZE, WIN_YSIZE);
5558   InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
5559   InitGfxClipRegion(FALSE, -1, -1, -1, -1);
5560
5561   InitGfxBuffers_SP();
5562 }
5563
5564 void InitGfx()
5565 {
5566   struct GraphicInfo *graphic_info_last = graphic_info;
5567   char *filename_font_initial = NULL;
5568   char *filename_anim_initial = NULL;
5569   Bitmap *bitmap_font_initial = NULL;
5570   int font_height;
5571   int i, j;
5572
5573   /* determine settings for initial font (for displaying startup messages) */
5574   for (i = 0; image_config[i].token != NULL; i++)
5575   {
5576     for (j = 0; j < NUM_INITIAL_FONTS; j++)
5577     {
5578       char font_token[128];
5579       int len_font_token;
5580
5581       sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1);
5582       len_font_token = strlen(font_token);
5583
5584       if (strEqual(image_config[i].token, font_token))
5585         filename_font_initial = image_config[i].value;
5586       else if (strlen(image_config[i].token) > len_font_token &&
5587                strncmp(image_config[i].token, font_token, len_font_token) == 0)
5588       {
5589         if (strEqual(&image_config[i].token[len_font_token], ".x"))
5590           font_initial[j].src_x = atoi(image_config[i].value);
5591         else if (strEqual(&image_config[i].token[len_font_token], ".y"))
5592           font_initial[j].src_y = atoi(image_config[i].value);
5593         else if (strEqual(&image_config[i].token[len_font_token], ".width"))
5594           font_initial[j].width = atoi(image_config[i].value);
5595         else if (strEqual(&image_config[i].token[len_font_token], ".height"))
5596           font_initial[j].height = atoi(image_config[i].value);
5597       }
5598     }
5599   }
5600
5601   for (j = 0; j < NUM_INITIAL_FONTS; j++)
5602   {
5603     font_initial[j].num_chars = DEFAULT_NUM_CHARS_PER_FONT;
5604     font_initial[j].num_chars_per_line = DEFAULT_NUM_CHARS_PER_LINE;
5605   }
5606
5607   if (filename_font_initial == NULL)    /* should not happen */
5608     Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
5609
5610 #if 1
5611   InitGfxBuffers();
5612 #else
5613   /* create additional image buffers for double-buffering and cross-fading */
5614   bitmap_db_store = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
5615   bitmap_db_cross = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
5616   bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
5617   bitmap_db_panel = CreateBitmap(DXSIZE, DYSIZE, DEFAULT_DEPTH);
5618   bitmap_db_door  = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
5619   bitmap_db_toons = CreateBitmap(FULL_SXSIZE, FULL_SYSIZE, DEFAULT_DEPTH);
5620
5621   /* initialize screen properties */
5622   InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
5623                    REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
5624                    bitmap_db_field);
5625   InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
5626   InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
5627   InitGfxWindowInfo(WIN_XSIZE, WIN_YSIZE);
5628   InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
5629 #endif
5630
5631   InitGfxCustomArtworkInfo();
5632
5633   bitmap_font_initial = LoadCustomImage(filename_font_initial);
5634
5635   for (j = 0; j < NUM_INITIAL_FONTS; j++)
5636     font_initial[j].bitmap = bitmap_font_initial;
5637
5638   InitFontGraphicInfo();
5639
5640   font_height = getFontHeight(FC_RED);
5641
5642 #if 1
5643   DrawInitText(getWindowTitleString(), 20, FC_YELLOW);
5644 #else
5645   DrawInitText(getProgramInitString(), 20, FC_YELLOW);
5646 #endif
5647   DrawInitText(PROGRAM_COPYRIGHT_STRING, 50, FC_RED);
5648   DrawInitText(PROGRAM_WEBSITE_STRING, WIN_YSIZE - 20 - font_height, FC_RED);
5649
5650   DrawInitText("Loading graphics", 120, FC_GREEN);
5651
5652 #if 1
5653 #if 1
5654   /* initialize busy animation with default values */
5655   int parameter[NUM_GFX_ARGS];
5656   for (i = 0; i < NUM_GFX_ARGS; i++)
5657     parameter[i] = get_graphic_parameter_value(image_config_suffix[i].value,
5658                                                image_config_suffix[i].token,
5659                                                image_config_suffix[i].type);
5660 #if 0
5661   for (i = 0; i < NUM_GFX_ARGS; i++)
5662     printf("::: '%s' => %d\n", image_config_suffix[i].token, parameter[i]);
5663 #endif
5664 #endif
5665
5666   /* determine settings for busy animation (when displaying startup messages) */
5667   for (i = 0; image_config[i].token != NULL; i++)
5668   {
5669     char *anim_token = CONFIG_TOKEN_GLOBAL_BUSY;
5670     int len_anim_token = strlen(anim_token);
5671
5672     if (strEqual(image_config[i].token, anim_token))
5673       filename_anim_initial = image_config[i].value;
5674     else if (strlen(image_config[i].token) > len_anim_token &&
5675              strncmp(image_config[i].token, anim_token, len_anim_token) == 0)
5676     {
5677 #if 1
5678       for (j = 0; image_config_suffix[j].token != NULL; j++)
5679       {
5680         if (strEqual(&image_config[i].token[len_anim_token],
5681                      image_config_suffix[j].token))
5682           parameter[j] =
5683             get_graphic_parameter_value(image_config[i].value,
5684                                         image_config_suffix[j].token,
5685                                         image_config_suffix[j].type);
5686       }
5687 #else
5688       if (strEqual(&image_config[i].token[len_anim_token], ".x"))
5689         anim_initial.src_x = atoi(image_config[i].value);
5690       else if (strEqual(&image_config[i].token[len_anim_token], ".y"))
5691         anim_initial.src_y = atoi(image_config[i].value);
5692       else if (strEqual(&image_config[i].token[len_anim_token], ".width"))
5693         anim_initial.width = atoi(image_config[i].value);
5694       else if (strEqual(&image_config[i].token[len_anim_token], ".height"))
5695         anim_initial.height = atoi(image_config[i].value);
5696       else if (strEqual(&image_config[i].token[len_anim_token], ".frames"))
5697         anim_initial.anim_frames = atoi(image_config[i].value);
5698       else if (strEqual(&image_config[i].token[len_anim_token],
5699                         ".frames_per_line"))
5700         anim_initial.anim_frames_per_line = atoi(image_config[i].value);
5701       else if (strEqual(&image_config[i].token[len_anim_token], ".delay"))
5702         anim_initial.anim_delay = atoi(image_config[i].value);
5703 #endif
5704     }
5705   }
5706
5707 #if defined(CREATE_SPECIAL_EDITION_RND_JUE)
5708   filename_anim_initial = "loading.pcx";
5709
5710   parameter[GFX_ARG_X] = 0;
5711   parameter[GFX_ARG_Y] = 0;
5712   parameter[GFX_ARG_WIDTH] = 128;
5713   parameter[GFX_ARG_HEIGHT] = 40;
5714   parameter[GFX_ARG_FRAMES] = 32;
5715   parameter[GFX_ARG_DELAY] = 4;
5716   parameter[GFX_ARG_FRAMES_PER_LINE] = ARG_UNDEFINED_VALUE;
5717 #endif
5718
5719   if (filename_anim_initial == NULL)    /* should not happen */
5720     Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_GLOBAL_BUSY);
5721
5722   anim_initial.bitmap = LoadCustomImage(filename_anim_initial);
5723
5724   graphic_info = &anim_initial;         /* graphic == 0 => anim_initial */
5725
5726   set_graphic_parameters_ext(0, parameter, anim_initial.bitmap);
5727
5728 #if 0
5729   printf("::: INIT_GFX: anim_frames_per_line == %d [%d / %d] [%d, %d]\n",
5730          graphic_info[0].anim_frames_per_line,
5731          get_scaled_graphic_width(0),
5732          graphic_info[0].width,
5733          getOriginalImageWidthFromImageID(0),
5734          graphic_info[0].scale_up_factor);
5735 #endif
5736
5737   graphic_info = graphic_info_last;
5738
5739   init.busy.width  = anim_initial.width;
5740   init.busy.height = anim_initial.height;
5741
5742   InitMenuDesignSettings_Static();
5743   InitGfxDrawBusyAnimFunction(DrawInitAnim);
5744
5745   /* use copy of busy animation to prevent change while reloading artwork */
5746   init_last = init;
5747 #endif
5748 }
5749
5750 void RedrawBackground()
5751 {
5752   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
5753              0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
5754
5755   redraw_mask = REDRAW_ALL;
5756 }
5757
5758 void InitGfxBackground()
5759 {
5760   int x, y;
5761
5762   fieldbuffer = bitmap_db_field;
5763   SetDrawtoField(DRAW_BACKBUFFER);
5764
5765 #if 1
5766   ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE);
5767 #else
5768   RedrawBackground();
5769
5770   ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
5771   ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
5772 #endif
5773
5774   for (x = 0; x < MAX_BUF_XSIZE; x++)
5775     for (y = 0; y < MAX_BUF_YSIZE; y++)
5776       redraw[x][y] = 0;
5777   redraw_tiles = 0;
5778   redraw_mask = REDRAW_ALL;
5779 }
5780
5781 static void InitLevelInfo()
5782 {
5783   LoadLevelInfo();                              /* global level info */
5784   LoadLevelSetup_LastSeries();                  /* last played series info */
5785   LoadLevelSetup_SeriesInfo();                  /* last played level info */
5786 }
5787
5788 static void InitLevelArtworkInfo()
5789 {
5790   LoadLevelArtworkInfo();
5791 }
5792
5793 static void InitImages()
5794 {
5795   print_timestamp_init("InitImages");
5796
5797 #if 0
5798   printf("::: leveldir_current->identifier == '%s'\n",
5799          leveldir_current == NULL ? "[NULL]" : leveldir_current->identifier);
5800   printf("::: leveldir_current->graphics_path == '%s'\n",
5801          leveldir_current == NULL ? "[NULL]" : leveldir_current->graphics_path);
5802   printf("::: leveldir_current->graphics_set == '%s'\n",
5803          leveldir_current == NULL ? "[NULL]" : leveldir_current->graphics_set);
5804   printf("::: getLevelArtworkSet(ARTWORK_TYPE_GRAPHICS) == '%s'\n",
5805          leveldir_current == NULL ? "[NULL]" : LEVELDIR_ARTWORK_SET(leveldir_current, ARTWORK_TYPE_GRAPHICS));
5806 #endif
5807
5808   setLevelArtworkDir(artwork.gfx_first);
5809
5810 #if 0
5811   printf("::: leveldir_current->identifier == '%s'\n",
5812          leveldir_current == NULL ? "[NULL]" : leveldir_current->identifier);
5813   printf("::: leveldir_current->graphics_path == '%s'\n",
5814          leveldir_current == NULL ? "[NULL]" : leveldir_current->graphics_path);
5815   printf("::: leveldir_current->graphics_set == '%s'\n",
5816          leveldir_current == NULL ? "[NULL]" : leveldir_current->graphics_set);
5817   printf("::: getLevelArtworkSet(ARTWORK_TYPE_GRAPHICS) == '%s'\n",
5818          leveldir_current == NULL ? "[NULL]" : LEVELDIR_ARTWORK_SET(leveldir_current, ARTWORK_TYPE_GRAPHICS));
5819 #endif
5820
5821 #if 0
5822   printf("::: InitImages for '%s' ['%s', '%s'] ['%s', '%s']\n",
5823          leveldir_current->identifier,
5824          artwork.gfx_current_identifier,
5825          artwork.gfx_current->identifier,
5826          leveldir_current->graphics_set,
5827          leveldir_current->graphics_path);
5828 #endif
5829
5830   UPDATE_BUSY_STATE();
5831
5832   ReloadCustomImages();
5833   print_timestamp_time("ReloadCustomImages");
5834
5835   UPDATE_BUSY_STATE();
5836
5837   LoadCustomElementDescriptions();
5838   print_timestamp_time("LoadCustomElementDescriptions");
5839
5840   UPDATE_BUSY_STATE();
5841
5842   LoadMenuDesignSettings();
5843   print_timestamp_time("LoadMenuDesignSettings");
5844
5845   UPDATE_BUSY_STATE();
5846
5847   ReinitializeGraphics();
5848   print_timestamp_time("ReinitializeGraphics");
5849
5850   UPDATE_BUSY_STATE();
5851
5852   print_timestamp_done("InitImages");
5853 }
5854
5855 static void InitSound(char *identifier)
5856 {
5857   print_timestamp_init("InitSound");
5858
5859   if (identifier == NULL)
5860     identifier = artwork.snd_current->identifier;
5861
5862   /* set artwork path to send it to the sound server process */
5863   setLevelArtworkDir(artwork.snd_first);
5864
5865   InitReloadCustomSounds(identifier);
5866   print_timestamp_time("InitReloadCustomSounds");
5867
5868   ReinitializeSounds();
5869   print_timestamp_time("ReinitializeSounds");
5870
5871   print_timestamp_done("InitSound");
5872 }
5873
5874 static void InitMusic(char *identifier)
5875 {
5876   print_timestamp_init("InitMusic");
5877
5878   if (identifier == NULL)
5879     identifier = artwork.mus_current->identifier;
5880
5881   /* set artwork path to send it to the sound server process */
5882   setLevelArtworkDir(artwork.mus_first);
5883
5884   InitReloadCustomMusic(identifier);
5885   print_timestamp_time("InitReloadCustomMusic");
5886
5887   ReinitializeMusic();
5888   print_timestamp_time("ReinitializeMusic");
5889
5890   print_timestamp_done("InitMusic");
5891 }
5892
5893 void InitNetworkServer()
5894 {
5895 #if defined(NETWORK_AVALIABLE)
5896   int nr_wanted;
5897 #endif
5898
5899   if (!options.network)
5900     return;
5901
5902 #if defined(NETWORK_AVALIABLE)
5903   nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
5904
5905   if (!ConnectToServer(options.server_host, options.server_port))
5906     Error(ERR_EXIT, "cannot connect to network game server");
5907
5908   SendToServer_PlayerName(setup.player_name);
5909   SendToServer_ProtocolVersion();
5910
5911   if (nr_wanted)
5912     SendToServer_NrWanted(nr_wanted);
5913 #endif
5914 }
5915
5916 static boolean CheckArtworkConfigForCustomElements(char *filename)
5917 {
5918   SetupFileHash *setup_file_hash;
5919   boolean redefined_ce_found = FALSE;
5920
5921   /* !!! CACHE THIS BY USING HASH 'filename' => 'true/false' !!! */
5922
5923   if ((setup_file_hash = loadSetupFileHash(filename)) != NULL)
5924   {
5925     BEGIN_HASH_ITERATION(setup_file_hash, itr)
5926     {
5927       char *token = HASH_ITERATION_TOKEN(itr);
5928
5929       if (strPrefix(token, "custom_"))
5930       {
5931         redefined_ce_found = TRUE;
5932
5933         break;
5934       }
5935     }
5936     END_HASH_ITERATION(setup_file_hash, itr)
5937
5938     freeSetupFileHash(setup_file_hash);
5939   }
5940
5941   return redefined_ce_found;
5942 }
5943
5944 static boolean CheckArtworkTypeForRedefinedCustomElements(int type)
5945 {
5946   char *filename_base, *filename_local;
5947   boolean redefined_ce_found = FALSE;
5948
5949   setLevelArtworkDir(ARTWORK_FIRST_NODE(artwork, type));
5950
5951 #if 0
5952   printf("::: leveldir_current->identifier == '%s'\n",
5953          leveldir_current == NULL ? "[NULL]" : leveldir_current->identifier);
5954   printf("::: leveldir_current->graphics_path == '%s'\n",
5955          leveldir_current == NULL ? "[NULL]" : leveldir_current->graphics_path);
5956   printf("::: leveldir_current->graphics_set == '%s'\n",
5957          leveldir_current == NULL ? "[NULL]" : leveldir_current->graphics_set);
5958   printf("::: getLevelArtworkSet(ARTWORK_TYPE_GRAPHICS) == '%s'\n",
5959          leveldir_current == NULL ? "[NULL]" :
5960          LEVELDIR_ARTWORK_SET(leveldir_current, type));
5961 #endif
5962
5963   /* first look for special artwork configured in level series config */
5964   filename_base = getCustomArtworkLevelConfigFilename(type);
5965
5966 #if 0
5967   printf("::: filename_base == '%s'\n", filename_base);
5968 #endif
5969
5970   if (fileExists(filename_base))
5971     redefined_ce_found |= CheckArtworkConfigForCustomElements(filename_base);
5972
5973   filename_local = getCustomArtworkConfigFilename(type);
5974
5975 #if 0
5976   printf("::: filename_local == '%s'\n", filename_local);
5977 #endif
5978
5979   if (filename_local != NULL && !strEqual(filename_base, filename_local))
5980     redefined_ce_found |= CheckArtworkConfigForCustomElements(filename_local);
5981
5982 #if 0
5983   printf("::: redefined_ce_found == %d\n", redefined_ce_found);
5984 #endif
5985
5986   return redefined_ce_found;
5987 }
5988
5989 static void InitOverrideArtwork()
5990 {
5991   boolean redefined_ce_found = FALSE;
5992
5993   /* to check if this level set redefines any CEs, do not use overriding */
5994   gfx.override_level_graphics = FALSE;
5995   gfx.override_level_sounds   = FALSE;
5996   gfx.override_level_music    = FALSE;
5997
5998   /* now check if this level set has definitions for custom elements */
5999   if (setup.override_level_graphics == AUTO ||
6000       setup.override_level_sounds   == AUTO ||
6001       setup.override_level_music    == AUTO)
6002     redefined_ce_found =
6003       (CheckArtworkTypeForRedefinedCustomElements(ARTWORK_TYPE_GRAPHICS) |
6004        CheckArtworkTypeForRedefinedCustomElements(ARTWORK_TYPE_SOUNDS) |
6005        CheckArtworkTypeForRedefinedCustomElements(ARTWORK_TYPE_MUSIC));
6006
6007 #if 0
6008   printf("::: redefined_ce_found == %d\n", redefined_ce_found);
6009 #endif
6010
6011   if (redefined_ce_found)
6012   {
6013     /* this level set has CE definitions: change "AUTO" to "FALSE" */
6014     gfx.override_level_graphics = (setup.override_level_graphics == TRUE);
6015     gfx.override_level_sounds   = (setup.override_level_sounds   == TRUE);
6016     gfx.override_level_music    = (setup.override_level_music    == TRUE);
6017   }
6018   else
6019   {
6020     /* this level set has no CE definitions: change "AUTO" to "TRUE" */
6021     gfx.override_level_graphics = (setup.override_level_graphics != FALSE);
6022     gfx.override_level_sounds   = (setup.override_level_sounds   != FALSE);
6023     gfx.override_level_music    = (setup.override_level_music    != FALSE);
6024   }
6025
6026 #if 0
6027   printf("::: => %d, %d, %d\n",
6028          gfx.override_level_graphics,
6029          gfx.override_level_sounds,
6030          gfx.override_level_music);
6031 #endif
6032 }
6033
6034 static char *getNewArtworkIdentifier(int type)
6035 {
6036   static char *leveldir_current_identifier[3] = { NULL, NULL, NULL };
6037   static boolean last_override_level_artwork[3] = { FALSE, FALSE, FALSE };
6038   static boolean last_has_level_artwork_set[3] = { FALSE, FALSE, FALSE };
6039   static boolean initialized[3] = { FALSE, FALSE, FALSE };
6040   TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
6041 #if 1
6042   boolean setup_override_artwork = GFX_OVERRIDE_ARTWORK(type);
6043 #else
6044   boolean setup_override_artwork = SETUP_OVERRIDE_ARTWORK(setup, type);
6045 #endif
6046   char *setup_artwork_set = SETUP_ARTWORK_SET(setup, type);
6047   char *leveldir_identifier = leveldir_current->identifier;
6048 #if 1
6049   /* !!! setLevelArtworkDir() should be moved to an earlier stage !!! */
6050   char *leveldir_artwork_set = setLevelArtworkDir(artwork_first_node);
6051 #else
6052   char *leveldir_artwork_set = LEVELDIR_ARTWORK_SET(leveldir_current, type);
6053 #endif
6054   boolean has_level_artwork_set = (leveldir_artwork_set != NULL);
6055   char *artwork_current_identifier;
6056   char *artwork_new_identifier = NULL;  /* default: nothing has changed */
6057
6058   /* leveldir_current may be invalid (level group, parent link) */
6059   if (!validLevelSeries(leveldir_current))
6060     return NULL;
6061
6062   /* 1st step: determine artwork set to be activated in descending order:
6063      --------------------------------------------------------------------
6064      1. setup artwork (when configured to override everything else)
6065      2. artwork set configured in "levelinfo.conf" of current level set
6066         (artwork in level directory will have priority when loading later)
6067      3. artwork in level directory (stored in artwork sub-directory)
6068      4. setup artwork (currently configured in setup menu) */
6069
6070   if (setup_override_artwork)
6071     artwork_current_identifier = setup_artwork_set;
6072   else if (leveldir_artwork_set != NULL)
6073     artwork_current_identifier = leveldir_artwork_set;
6074   else if (getTreeInfoFromIdentifier(artwork_first_node, leveldir_identifier))
6075     artwork_current_identifier = leveldir_identifier;
6076   else
6077     artwork_current_identifier = setup_artwork_set;
6078
6079
6080   /* 2nd step: check if it is really needed to reload artwork set
6081      ------------------------------------------------------------ */
6082
6083 #if 0
6084   if (type == ARTWORK_TYPE_GRAPHICS)
6085     printf("::: 0: '%s' ['%s', '%s'] ['%s' ('%s')]\n",
6086            artwork_new_identifier,
6087            ARTWORK_CURRENT_IDENTIFIER(artwork, type),
6088            artwork_current_identifier,
6089            leveldir_current->graphics_set,
6090            leveldir_current->identifier);
6091 #endif
6092
6093   /* ---------- reload if level set and also artwork set has changed ------- */
6094   if (leveldir_current_identifier[type] != leveldir_identifier &&
6095       (last_has_level_artwork_set[type] || has_level_artwork_set))
6096     artwork_new_identifier = artwork_current_identifier;
6097
6098   leveldir_current_identifier[type] = leveldir_identifier;
6099   last_has_level_artwork_set[type] = has_level_artwork_set;
6100
6101 #if 0
6102   if (type == ARTWORK_TYPE_GRAPHICS)
6103     printf("::: 1: '%s'\n", artwork_new_identifier);
6104 #endif
6105
6106   /* ---------- reload if "override artwork" setting has changed ----------- */
6107   if (last_override_level_artwork[type] != setup_override_artwork)
6108     artwork_new_identifier = artwork_current_identifier;
6109
6110   last_override_level_artwork[type] = setup_override_artwork;
6111
6112 #if 0
6113   if (type == ARTWORK_TYPE_GRAPHICS)
6114     printf("::: 2: '%s'\n", artwork_new_identifier);
6115 #endif
6116
6117   /* ---------- reload if current artwork identifier has changed ----------- */
6118   if (!strEqual(ARTWORK_CURRENT_IDENTIFIER(artwork, type),
6119                 artwork_current_identifier))
6120     artwork_new_identifier = artwork_current_identifier;
6121
6122   *(ARTWORK_CURRENT_IDENTIFIER_PTR(artwork, type))= artwork_current_identifier;
6123
6124 #if 0
6125   if (type == ARTWORK_TYPE_GRAPHICS)
6126     printf("::: 3: '%s'\n", artwork_new_identifier);
6127 #endif
6128
6129   /* ---------- do not reload directly after starting ---------------------- */
6130   if (!initialized[type])
6131     artwork_new_identifier = NULL;
6132
6133   initialized[type] = TRUE;
6134
6135 #if 0
6136   if (type == ARTWORK_TYPE_GRAPHICS)
6137     printf("::: 4: '%s'\n", artwork_new_identifier);
6138 #endif
6139
6140 #if 0
6141   if (type == ARTWORK_TYPE_GRAPHICS)
6142     printf("CHECKING OLD/NEW GFX:\n- OLD: %s\n- NEW: %s ['%s', '%s'] ['%s']\n",
6143            artwork.gfx_current_identifier, artwork_current_identifier,
6144            artwork.gfx_current->identifier, leveldir_current->graphics_set,
6145            artwork_new_identifier);
6146 #endif
6147
6148   return artwork_new_identifier;
6149 }
6150
6151 void ReloadCustomArtwork(int force_reload)
6152 {
6153   int last_game_status = game_status;   /* save current game status */
6154   char *gfx_new_identifier;
6155   char *snd_new_identifier;
6156   char *mus_new_identifier;
6157   boolean force_reload_gfx = (force_reload & (1 << ARTWORK_TYPE_GRAPHICS));
6158   boolean force_reload_snd = (force_reload & (1 << ARTWORK_TYPE_SOUNDS));
6159   boolean force_reload_mus = (force_reload & (1 << ARTWORK_TYPE_MUSIC));
6160   boolean reload_needed;
6161
6162   InitOverrideArtwork();
6163
6164   force_reload_gfx |= AdjustGraphicsForEMC();
6165
6166   gfx_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_GRAPHICS);
6167   snd_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_SOUNDS);
6168   mus_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_MUSIC);
6169
6170   reload_needed = (gfx_new_identifier != NULL || force_reload_gfx ||
6171                    snd_new_identifier != NULL || force_reload_snd ||
6172                    mus_new_identifier != NULL || force_reload_mus);
6173
6174   if (!reload_needed)
6175     return;
6176
6177   print_timestamp_init("ReloadCustomArtwork");
6178
6179   game_status = GAME_MODE_LOADING;
6180
6181   FadeOut(REDRAW_ALL);
6182
6183 #if 1
6184   ClearRectangle(drawto, 0, 0, WIN_XSIZE, WIN_YSIZE);
6185 #else
6186   ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
6187 #endif
6188   print_timestamp_time("ClearRectangle");
6189
6190 #if 0
6191   printf("::: fading in ... %d\n", fading.fade_mode);
6192 #endif
6193   FadeIn(REDRAW_ALL);
6194 #if 0
6195   printf("::: done\n");
6196 #endif
6197
6198   if (gfx_new_identifier != NULL || force_reload_gfx)
6199   {
6200 #if 0
6201     printf("RELOADING GRAPHICS '%s' -> '%s' ['%s', '%s']\n",
6202            artwork.gfx_current_identifier,
6203            gfx_new_identifier,
6204            artwork.gfx_current->identifier,
6205            leveldir_current->graphics_set);
6206 #endif
6207
6208     InitImages();
6209     print_timestamp_time("InitImages");
6210   }
6211
6212   if (snd_new_identifier != NULL || force_reload_snd)
6213   {
6214     InitSound(snd_new_identifier);
6215     print_timestamp_time("InitSound");
6216   }
6217
6218   if (mus_new_identifier != NULL || force_reload_mus)
6219   {
6220     InitMusic(mus_new_identifier);
6221     print_timestamp_time("InitMusic");
6222   }
6223
6224   game_status = last_game_status;       /* restore current game status */
6225
6226   init_last = init;                     /* switch to new busy animation */
6227
6228 #if 0
6229   printf("::: ----------------DELAY 1 ...\n");
6230   Delay(3000);
6231 #endif
6232
6233 #if 0
6234   printf("::: FadeOut @ ReloadCustomArtwork ...\n");
6235 #endif
6236   FadeOut(REDRAW_ALL);
6237 #if 0
6238   printf("::: FadeOut @ ReloadCustomArtwork done\n");
6239 #endif
6240
6241   RedrawBackground();
6242
6243   /* force redraw of (open or closed) door graphics */
6244   SetDoorState(DOOR_OPEN_ALL);
6245   CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
6246
6247 #if 1
6248 #if 1
6249 #if 1
6250   FadeSetEnterScreen();
6251   FadeSkipNextFadeOut();
6252   // FadeSetDisabled();
6253 #else
6254   FadeSkipNext();
6255 #endif
6256 #else
6257   fading = fading_none;
6258 #endif
6259 #endif
6260
6261 #if 0
6262   redraw_mask = REDRAW_ALL;
6263 #endif
6264
6265   print_timestamp_done("ReloadCustomArtwork");
6266 }
6267
6268 void KeyboardAutoRepeatOffUnlessAutoplay()
6269 {
6270   if (global.autoplay_leveldir == NULL)
6271     KeyboardAutoRepeatOff();
6272 }
6273
6274
6275 /* ========================================================================= */
6276 /* OpenAll()                                                                 */
6277 /* ========================================================================= */
6278
6279 void OpenAll()
6280 {
6281   print_timestamp_init("OpenAll");
6282
6283   game_status = GAME_MODE_LOADING;
6284
6285 #if 1
6286   InitCounter();
6287 #endif
6288
6289   InitGlobal();                 /* initialize some global variables */
6290
6291   print_timestamp_time("[init global stuff]");
6292
6293   if (options.execute_command)
6294     Execute_Command(options.execute_command);
6295
6296   if (options.serveronly)
6297   {
6298 #if defined(PLATFORM_UNIX)
6299     NetworkServer(options.server_port, options.serveronly);
6300 #else
6301     Error(ERR_WARN, "networking only supported in Unix version");
6302 #endif
6303
6304     exit(0);                    /* never reached, server loops forever */
6305   }
6306
6307   InitSetup();
6308
6309   print_timestamp_time("[init setup/config stuff (1)]");
6310
6311   InitGameInfo();
6312   print_timestamp_time("[init setup/config stuff (2)]");
6313   InitPlayerInfo();
6314   print_timestamp_time("[init setup/config stuff (3)]");
6315   InitArtworkInfo();            /* needed before loading gfx, sound & music */
6316   print_timestamp_time("[init setup/config stuff (4)]");
6317   InitArtworkConfig();          /* needed before forking sound child process */
6318   print_timestamp_time("[init setup/config stuff (5)]");
6319   InitMixer();
6320   print_timestamp_time("[init setup/config stuff (6)]");
6321
6322 #if 0
6323   InitCounter();
6324 #endif
6325
6326   InitRND(NEW_RANDOMIZE);
6327   InitSimpleRandom(NEW_RANDOMIZE);
6328
6329   InitJoysticks();
6330
6331   print_timestamp_time("[init setup/config stuff]");
6332
6333   InitVideoDisplay();
6334   InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen);
6335
6336   InitEventFilter(FilterMouseMotionEvents);
6337
6338   print_timestamp_time("[init video stuff]");
6339
6340   InitElementPropertiesStatic();
6341   InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
6342   InitElementPropertiesGfxElement();
6343
6344   print_timestamp_time("[init element properties stuff]");
6345
6346   InitGfx();
6347
6348   print_timestamp_time("InitGfx");
6349
6350   InitLevelInfo();
6351   print_timestamp_time("InitLevelInfo");
6352
6353   InitLevelArtworkInfo();
6354   print_timestamp_time("InitLevelArtworkInfo");
6355
6356   InitOverrideArtwork();        /* needs to know current level directory */
6357   print_timestamp_time("InitOverrideArtwork");
6358
6359   InitImages();                 /* needs to know current level directory */
6360   print_timestamp_time("InitImages");
6361
6362   InitSound(NULL);              /* needs to know current level directory */
6363   print_timestamp_time("InitSound");
6364
6365   InitMusic(NULL);              /* needs to know current level directory */
6366   print_timestamp_time("InitMusic");
6367
6368   InitGfxBackground();
6369
6370 #if 1
6371   em_open_all();
6372 #endif
6373
6374 #if 1
6375   sp_open_all();
6376 #endif
6377
6378   if (global.autoplay_leveldir)
6379   {
6380     AutoPlayTape();
6381     return;
6382   }
6383   else if (global.convert_leveldir)
6384   {
6385     ConvertLevels();
6386     return;
6387   }
6388   else if (global.create_images_dir)
6389   {
6390     CreateLevelSketchImages();
6391     return;
6392   }
6393
6394   game_status = GAME_MODE_MAIN;
6395
6396 #if 1
6397   FadeSetEnterScreen();
6398   if (!(fading.fade_mode & FADE_TYPE_TRANSFORM))
6399     FadeSkipNextFadeOut();
6400   // FadeSetDisabled();
6401 #else
6402   fading = fading_none;
6403 #endif
6404
6405   print_timestamp_time("[post-artwork]");
6406
6407   print_timestamp_done("OpenAll");
6408
6409   DrawMainMenu();
6410
6411   InitNetworkServer();
6412 }
6413
6414 void CloseAllAndExit(int exit_value)
6415 {
6416   StopSounds();
6417   FreeAllSounds();
6418   FreeAllMusic();
6419   CloseAudio();         /* called after freeing sounds (needed for SDL) */
6420
6421 #if 1
6422   em_close_all();
6423 #endif
6424
6425 #if 1
6426   sp_close_all();
6427 #endif
6428
6429   FreeAllImages();
6430
6431 #if defined(TARGET_SDL)
6432   if (network_server)   /* terminate network server */
6433     SDL_KillThread(server_thread);
6434 #endif
6435
6436   CloseVideoDisplay();
6437   ClosePlatformDependentStuff();
6438
6439   if (exit_value != 0)
6440     NotifyUserAboutErrorFile();
6441
6442   exit(exit_value);
6443 }