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