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