rnd-20041129-2-src
[rocksndiamonds.git] / src / init.c
1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back!               *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 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
36
37 #define CONFIG_TOKEN_FONT_INITIAL               "font.initial"
38
39
40 struct FontBitmapInfo font_initial[NUM_INITIAL_FONTS];
41
42
43 static void InitTileClipmasks()
44 {
45 #if 0
46 #if defined(TARGET_X11)
47   XGCValues clip_gc_values;
48   unsigned long clip_gc_valuemask;
49
50 #if defined(TARGET_X11_NATIVE)
51
52 #if 0
53   GC copy_clipmask_gc;
54
55   static struct
56   {
57     int start;
58     int count;
59   }
60   tile_needs_clipping[] =
61   {
62     { GFX_SPIELER1_UP, 4 },
63     { GFX_SPIELER1_DOWN, 4 },
64     { GFX_SPIELER1_LEFT, 4 },
65     { GFX_SPIELER1_RIGHT, 4 },
66     { GFX_SPIELER1_PUSH_LEFT, 4 },
67     { GFX_SPIELER1_PUSH_RIGHT, 4 },
68     { GFX_SPIELER2_UP, 4 },
69     { GFX_SPIELER2_DOWN, 4 },
70     { GFX_SPIELER2_LEFT, 4 },
71     { GFX_SPIELER2_RIGHT, 4 },
72     { GFX_SPIELER2_PUSH_LEFT, 4 },
73     { GFX_SPIELER2_PUSH_RIGHT, 4 },
74     { GFX_SPIELER3_UP, 4 },
75     { GFX_SPIELER3_DOWN, 4 },
76     { GFX_SPIELER3_LEFT, 4 },
77     { GFX_SPIELER3_RIGHT, 4 },
78     { GFX_SPIELER3_PUSH_LEFT, 4 },
79     { GFX_SPIELER3_PUSH_RIGHT, 4 },
80     { GFX_SPIELER4_UP, 4 },
81     { GFX_SPIELER4_DOWN, 4 },
82     { GFX_SPIELER4_LEFT, 4 },
83     { GFX_SPIELER4_RIGHT, 4 },
84     { GFX_SPIELER4_PUSH_LEFT, 4 },
85     { GFX_SPIELER4_PUSH_RIGHT, 4 },
86     { GFX_SP_MURPHY, 1 },
87     { GFX_MURPHY_GO_LEFT, 3 },
88     { GFX_MURPHY_GO_RIGHT, 3 },
89     { GFX_MURPHY_SNAP_UP, 1 },
90     { GFX_MURPHY_SNAP_DOWN, 1 },
91     { GFX_MURPHY_SNAP_RIGHT, 1 },
92     { GFX_MURPHY_SNAP_LEFT, 1 },
93     { GFX_MURPHY_PUSH_RIGHT, 1 },
94     { GFX_MURPHY_PUSH_LEFT, 1 },
95     { GFX_GEBLUBBER, 4 },
96     { GFX_DYNAMIT, 7 },
97     { GFX_DYNABOMB, 4 },
98     { GFX_EXPLOSION, 8 },
99     { GFX_SOKOBAN_OBJEKT, 1 },
100     { GFX_FUNKELN_BLAU, 3 },
101     { GFX_FUNKELN_WEISS, 3 },
102     { GFX2_SHIELD_PASSIVE, 3 },
103     { GFX2_SHIELD_ACTIVE, 3 },
104     { -1, 0 }
105   };
106 #endif
107
108 #endif /* TARGET_X11_NATIVE */
109 #endif /* TARGET_X11 */
110
111   int i;
112
113   /* initialize pixmap array for special X11 tile clipping to Pixmap 'None' */
114   for (i = 0; i < NUM_TILES; i++)
115     tile_clipmask[i] = None;
116
117 #if defined(TARGET_X11)
118   /* This stuff is needed because X11 (XSetClipOrigin(), to be precise) is
119      often very slow when preparing a masked XCopyArea() for big Pixmaps.
120      To prevent this, create small (tile-sized) mask Pixmaps which will then
121      be set much faster with XSetClipOrigin() and speed things up a lot. */
122
123   clip_gc_values.graphics_exposures = False;
124   clip_gc_valuemask = GCGraphicsExposures;
125   tile_clip_gc = XCreateGC(display, window->drawable,
126                            clip_gc_valuemask, &clip_gc_values);
127
128 #if 0
129   for (i = 0; i < NUM_BITMAPS; i++)
130   {
131     if (pix[i]->clip_mask)
132     {
133       clip_gc_values.graphics_exposures = False;
134       clip_gc_values.clip_mask = pix[i]->clip_mask;
135       clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
136       pix[i]->stored_clip_gc = XCreateGC(display, window->drawable,
137                                          clip_gc_valuemask, &clip_gc_values);
138     }
139   }
140 #endif
141
142 #if defined(TARGET_X11_NATIVE)
143
144 #if 0
145   /* create graphic context structures needed for clipping */
146   clip_gc_values.graphics_exposures = False;
147   clip_gc_valuemask = GCGraphicsExposures;
148   copy_clipmask_gc = XCreateGC(display, pix[PIX_BACK]->clip_mask,
149                                clip_gc_valuemask, &clip_gc_values);
150
151   /* create only those clipping Pixmaps we really need */
152   for (i = 0; tile_needs_clipping[i].start >= 0; i++)
153   {
154     int j;
155
156     for (j = 0; j < tile_needs_clipping[i].count; j++)
157     {
158       int tile = tile_needs_clipping[i].start + j;
159       int graphic = tile;
160       int src_x, src_y;
161       Bitmap *src_bitmap;
162       Pixmap src_pixmap;
163
164       getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
165       src_pixmap = src_bitmap->clip_mask;
166
167       tile_clipmask[tile] = XCreatePixmap(display, window->drawable,
168                                           TILEX, TILEY, 1);
169
170       XCopyArea(display, src_pixmap, tile_clipmask[tile], copy_clipmask_gc,
171                 src_x, src_y, TILEX, TILEY, 0, 0);
172     }
173   }
174
175   XFreeGC(display, copy_clipmask_gc);
176 #endif
177
178 #endif /* TARGET_X11_NATIVE */
179 #endif /* TARGET_X11 */
180 #endif
181 }
182
183 void FreeTileClipmasks()
184 {
185 #if 0
186 #if defined(TARGET_X11)
187   int i;
188
189   for (i = 0; i < NUM_TILES; i++)
190   {
191     if (tile_clipmask[i] != None)
192     {
193       XFreePixmap(display, tile_clipmask[i]);
194       tile_clipmask[i] = None;
195     }
196   }
197
198   if (tile_clip_gc)
199     XFreeGC(display, tile_clip_gc);
200   tile_clip_gc = None;
201
202 #if 0
203   for (i = 0; i < NUM_BITMAPS; i++)
204   {
205     if (pix[i] != NULL && pix[i]->stored_clip_gc)
206     {
207       XFreeGC(display, pix[i]->stored_clip_gc);
208       pix[i]->stored_clip_gc = None;
209     }
210   }
211 #endif
212
213 #endif /* TARGET_X11 */
214 #endif
215 }
216
217 void FreeGadgets()
218 {
219   FreeLevelEditorGadgets();
220   FreeGameButtons();
221   FreeTapeButtons();
222   FreeToolButtons();
223   FreeScreenGadgets();
224 }
225
226 void InitGadgets()
227 {
228   static boolean gadgets_initialized = FALSE;
229
230   if (gadgets_initialized)
231     FreeGadgets();
232
233   CreateLevelEditorGadgets();
234   CreateGameButtons();
235   CreateTapeButtons();
236   CreateToolButtons();
237   CreateScreenGadgets();
238
239   gadgets_initialized = TRUE;
240 }
241
242 inline void InitElementSmallImagesScaledUp(int graphic)
243 {
244   CreateImageWithSmallImages(graphic, graphic_info[graphic].scale_up_factor);
245 }
246
247 void InitElementSmallImages()
248 {
249   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
250   int num_property_mappings = getImageListPropertyMappingSize();
251   int i;
252
253   /* initialize normal images from static configuration */
254   for (i = 0; element_to_graphic[i].element > -1; i++)
255     InitElementSmallImagesScaledUp(element_to_graphic[i].graphic);
256
257   /* initialize special images from static configuration */
258   for (i = 0; element_to_special_graphic[i].element > -1; i++)
259     InitElementSmallImagesScaledUp(element_to_special_graphic[i].graphic);
260
261   /* initialize images from dynamic configuration (may be elements or other) */
262 #if 1
263   for (i = 0; i < num_property_mappings; i++)
264     InitElementSmallImagesScaledUp(property_mapping[i].artwork_index);
265 #else
266   /* !!! THIS DOES NOT WORK -- "artwork_index" is graphic, not element !!! */
267   /* !!! ALSO, non-element graphics might need scaling-up !!! */
268   for (i = 0; i < num_property_mappings; i++)
269     if (property_mapping[i].artwork_index < MAX_NUM_ELEMENTS)
270       InitElementSmallImagesScaledUp(property_mapping[i].artwork_index);
271 #endif
272
273 #if 0
274   /* !!! FIX THIS (CHANGE TO USING NORMAL ELEMENT GRAPHIC DEFINITIONS) !!! */
275   for (i = IMG_EMC_OBJECT; i <= IMG_EMC_SPRITE; i++)
276     InitElementSmallImagesScaledUp(i);
277 #endif
278 }
279
280 #if 1
281 /* !!! FIX THIS (CHANGE TO USING NORMAL ELEMENT GRAPHIC DEFINITIONS) !!! */
282 void SetBitmaps_EM(Bitmap **em_bitmap)
283 {
284   em_bitmap[0] = graphic_info[IMG_EMC_OBJECT].bitmap;
285   em_bitmap[1] = graphic_info[IMG_EMC_SPRITE].bitmap;
286 }
287 #endif
288
289 static int getFontBitmapID(int font_nr)
290 {
291   int special = -1;
292
293   if (game_status >= GAME_MODE_MAIN && game_status <= GAME_MODE_PSEUDO_PREVIEW)
294     special = game_status;
295   else if (game_status == GAME_MODE_PSEUDO_TYPENAME)
296     special = GFX_SPECIAL_ARG_MAIN;
297   else if (game_status == GAME_MODE_PLAYING)
298     special = GFX_SPECIAL_ARG_DOOR;
299
300   if (special != -1)
301     return font_info[font_nr].special_bitmap_id[special];
302   else
303     return font_nr;
304 }
305
306 void InitFontGraphicInfo()
307 {
308   static struct FontBitmapInfo *font_bitmap_info = NULL;
309   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
310   int num_property_mappings = getImageListPropertyMappingSize();
311   int num_font_bitmaps = NUM_FONTS;
312   int i, j;
313
314   if (graphic_info == NULL)             /* still at startup phase */
315   {
316     InitFontInfo(font_initial, NUM_INITIAL_FONTS, getFontBitmapID);
317
318     return;
319   }
320
321   /* ---------- initialize font graphic definitions ---------- */
322
323   /* always start with reliable default values (normal font graphics) */
324 #if 1
325   for (i = 0; i < NUM_FONTS; i++)
326     font_info[i].graphic = IMG_FONT_INITIAL_1;
327 #else
328   for (i = 0; i < NUM_FONTS; i++)
329     font_info[i].graphic = FONT_INITIAL_1;
330 #endif
331
332   /* initialize normal font/graphic mapping from static configuration */
333   for (i = 0; font_to_graphic[i].font_nr > -1; i++)
334   {
335     int font_nr = font_to_graphic[i].font_nr;
336     int special = font_to_graphic[i].special;
337     int graphic = font_to_graphic[i].graphic;
338
339     if (special != -1)
340       continue;
341
342     font_info[font_nr].graphic = graphic;
343   }
344
345   /* always start with reliable default values (special font graphics) */
346   for (i = 0; i < NUM_FONTS; i++)
347   {
348     for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
349     {
350       font_info[i].special_graphic[j] = font_info[i].graphic;
351       font_info[i].special_bitmap_id[j] = i;
352     }
353   }
354
355   /* initialize special font/graphic mapping from static configuration */
356   for (i = 0; font_to_graphic[i].font_nr > -1; i++)
357   {
358     int font_nr = font_to_graphic[i].font_nr;
359     int special = font_to_graphic[i].special;
360     int graphic = font_to_graphic[i].graphic;
361
362     if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
363     {
364       font_info[font_nr].special_graphic[special] = graphic;
365       font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
366       num_font_bitmaps++;
367     }
368   }
369
370   /* initialize special element/graphic mapping from dynamic configuration */
371   for (i = 0; i < num_property_mappings; i++)
372   {
373     int font_nr = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
374     int special = property_mapping[i].ext3_index;
375     int graphic = property_mapping[i].artwork_index;
376
377     if (font_nr < 0)
378       continue;
379
380     if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
381     {
382       font_info[font_nr].special_graphic[special] = graphic;
383       font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
384       num_font_bitmaps++;
385     }
386   }
387
388   /* ---------- initialize font bitmap array ---------- */
389
390   if (font_bitmap_info != NULL)
391     FreeFontInfo(font_bitmap_info);
392
393   font_bitmap_info =
394     checked_calloc(num_font_bitmaps * sizeof(struct FontBitmapInfo));
395
396   /* ---------- initialize font bitmap definitions ---------- */
397
398   for (i = 0; i < NUM_FONTS; i++)
399   {
400     if (i < NUM_INITIAL_FONTS)
401     {
402       font_bitmap_info[i] = font_initial[i];
403       continue;
404     }
405
406     for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
407     {
408       int font_bitmap_id = font_info[i].special_bitmap_id[j];
409       int graphic = font_info[i].special_graphic[j];
410
411       /* set 'graphic_info' for font entries, if uninitialized (guessed) */
412       if (graphic_info[graphic].anim_frames < MIN_NUM_CHARS_PER_FONT)
413       {
414         graphic_info[graphic].anim_frames = DEFAULT_NUM_CHARS_PER_FONT;
415         graphic_info[graphic].anim_frames_per_line= DEFAULT_NUM_CHARS_PER_LINE;
416       }
417
418       /* copy font relevant information from graphics information */
419       font_bitmap_info[font_bitmap_id].bitmap = graphic_info[graphic].bitmap;
420       font_bitmap_info[font_bitmap_id].src_x  = graphic_info[graphic].src_x;
421       font_bitmap_info[font_bitmap_id].src_y  = graphic_info[graphic].src_y;
422       font_bitmap_info[font_bitmap_id].width  = graphic_info[graphic].width;
423       font_bitmap_info[font_bitmap_id].height = graphic_info[graphic].height;
424       font_bitmap_info[font_bitmap_id].draw_x = graphic_info[graphic].draw_x;
425       font_bitmap_info[font_bitmap_id].draw_y = graphic_info[graphic].draw_y;
426
427       font_bitmap_info[font_bitmap_id].num_chars =
428         graphic_info[graphic].anim_frames;
429       font_bitmap_info[font_bitmap_id].num_chars_per_line =
430         graphic_info[graphic].anim_frames_per_line;
431     }
432   }
433
434   InitFontInfo(font_bitmap_info, num_font_bitmaps, getFontBitmapID);
435 }
436
437 void InitElementGraphicInfo()
438 {
439   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
440   int num_property_mappings = getImageListPropertyMappingSize();
441   int i, act, dir;
442
443   if (graphic_info == NULL)             /* still at startup phase */
444     return;
445
446   /* set values to -1 to identify later as "uninitialized" values */
447   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
448   {
449     for (act = 0; act < NUM_ACTIONS; act++)
450     {
451       element_info[i].graphic[act] = -1;
452       element_info[i].crumbled[act] = -1;
453
454       for (dir = 0; dir < NUM_DIRECTIONS; dir++)
455       {
456         element_info[i].direction_graphic[act][dir] = -1;
457         element_info[i].direction_crumbled[act][dir] = -1;
458       }
459     }
460   }
461
462   /* initialize normal element/graphic mapping from static configuration */
463   for (i = 0; element_to_graphic[i].element > -1; i++)
464   {
465     int element      = element_to_graphic[i].element;
466     int action       = element_to_graphic[i].action;
467     int direction    = element_to_graphic[i].direction;
468     boolean crumbled = element_to_graphic[i].crumbled;
469     int graphic      = element_to_graphic[i].graphic;
470     int base_graphic = el2baseimg(element);
471
472     if (graphic_info[graphic].bitmap == NULL)
473       continue;
474
475     if ((action > -1 || direction > -1 || crumbled == TRUE) &&
476         base_graphic != -1)
477     {
478       boolean base_redefined =
479         getImageListEntryFromImageID(base_graphic)->redefined;
480       boolean act_dir_redefined =
481         getImageListEntryFromImageID(graphic)->redefined;
482
483       /* if the base graphic ("emerald", for example) has been redefined,
484          but not the action graphic ("emerald.falling", for example), do not
485          use an existing (in this case considered obsolete) action graphic
486          anymore, but use the automatically determined default graphic */
487       if (base_redefined && !act_dir_redefined)
488         continue;
489     }
490
491     if (action < 0)
492       action = ACTION_DEFAULT;
493
494     if (crumbled)
495     {
496       if (direction > -1)
497         element_info[element].direction_crumbled[action][direction] = graphic;
498       else
499         element_info[element].crumbled[action] = graphic;
500     }
501     else
502     {
503       if (direction > -1)
504         element_info[element].direction_graphic[action][direction] = graphic;
505       else
506         element_info[element].graphic[action] = graphic;
507     }
508   }
509
510   /* initialize normal element/graphic mapping from dynamic configuration */
511   for (i = 0; i < num_property_mappings; i++)
512   {
513     int element   = property_mapping[i].base_index;
514     int action    = property_mapping[i].ext1_index;
515     int direction = property_mapping[i].ext2_index;
516     int special   = property_mapping[i].ext3_index;
517     int graphic   = property_mapping[i].artwork_index;
518     boolean crumbled = FALSE;
519
520     if (special == GFX_SPECIAL_ARG_CRUMBLED)
521     {
522       special = -1;
523       crumbled = TRUE;
524     }
525
526     if (graphic_info[graphic].bitmap == NULL)
527       continue;
528
529     if (element >= MAX_NUM_ELEMENTS || special != -1)
530       continue;
531
532     if (action < 0)
533       action = ACTION_DEFAULT;
534
535     if (crumbled)
536     {
537       if (direction < 0)
538         for (dir = 0; dir < NUM_DIRECTIONS; dir++)
539           element_info[element].direction_crumbled[action][dir] = -1;
540
541       if (direction > -1)
542         element_info[element].direction_crumbled[action][direction] = graphic;
543       else
544         element_info[element].crumbled[action] = graphic;
545     }
546     else
547     {
548       if (direction < 0)
549         for (dir = 0; dir < NUM_DIRECTIONS; dir++)
550           element_info[element].direction_graphic[action][dir] = -1;
551
552       if (direction > -1)
553         element_info[element].direction_graphic[action][direction] = graphic;
554       else
555         element_info[element].graphic[action] = graphic;
556     }
557   }
558
559   /* now copy all graphics that are defined to be cloned from other graphics */
560   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
561   {
562     int graphic = element_info[i].graphic[ACTION_DEFAULT];
563     int crumbled_like, diggable_like;
564
565     if (graphic == -1)
566       continue;
567
568     crumbled_like = graphic_info[graphic].crumbled_like;
569     diggable_like = graphic_info[graphic].diggable_like;
570
571     if (crumbled_like != -1 && element_info[i].crumbled[ACTION_DEFAULT] == -1)
572     {
573       for (act = 0; act < NUM_ACTIONS; act++)
574         element_info[i].crumbled[act] =
575           element_info[crumbled_like].crumbled[act];
576       for (act = 0; act < NUM_ACTIONS; act++)
577         for (dir = 0; dir < NUM_DIRECTIONS; dir++)
578           element_info[i].direction_crumbled[act][dir] =
579             element_info[crumbled_like].direction_crumbled[act][dir];
580     }
581
582     if (diggable_like != -1 && element_info[i].graphic[ACTION_DIGGING] == -1)
583     {
584       element_info[i].graphic[ACTION_DIGGING] =
585         element_info[diggable_like].graphic[ACTION_DIGGING];
586       for (dir = 0; dir < NUM_DIRECTIONS; dir++)
587         element_info[i].direction_graphic[ACTION_DIGGING][dir] =
588           element_info[diggable_like].direction_graphic[ACTION_DIGGING][dir];
589     }
590   }
591
592 #if 1
593   /* set hardcoded definitions for some runtime elements without graphic */
594   element_info[EL_AMOEBA_TO_DIAMOND].graphic[ACTION_DEFAULT] = IMG_AMOEBA_DEAD;
595 #endif
596
597 #if 1
598   /* now set all undefined/invalid graphics to -1 to set to default after it */
599   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
600   {
601     for (act = 0; act < NUM_ACTIONS; act++)
602     {
603       int graphic;
604
605       graphic = element_info[i].graphic[act];
606       if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
607         element_info[i].graphic[act] = -1;
608
609       graphic = element_info[i].crumbled[act];
610       if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
611         element_info[i].crumbled[act] = -1;
612
613       for (dir = 0; dir < NUM_DIRECTIONS; dir++)
614       {
615         graphic = element_info[i].direction_graphic[act][dir];
616         if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
617           element_info[i].direction_graphic[act][dir] = -1;
618
619         graphic = element_info[i].direction_crumbled[act][dir];
620         if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
621           element_info[i].direction_crumbled[act][dir] = -1;
622       }
623     }
624   }
625 #endif
626
627 #if 1
628   /* adjust graphics with 2nd tile for movement according to direction
629      (do this before correcting '-1' values to minimize calculations) */
630   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
631   {
632     for (act = 0; act < NUM_ACTIONS; act++)
633     {
634       for (dir = 0; dir < NUM_DIRECTIONS; dir++)
635       {
636         int graphic = element_info[i].direction_graphic[act][dir];
637         int move_dir = (act == ACTION_FALLING ? MV_BIT_DOWN : dir);
638
639         if (act == ACTION_FALLING)      /* special case */
640           graphic = element_info[i].graphic[act];
641
642         if (graphic != -1 &&
643             graphic_info[graphic].double_movement &&
644             graphic_info[graphic].swap_double_tiles != 0)
645         {
646           struct GraphicInfo *g = &graphic_info[graphic];
647           int src_x_front = g->src_x;
648           int src_y_front = g->src_y;
649           int src_x_back = g->src_x + g->offset2_x;
650           int src_y_back = g->src_y + g->offset2_y;
651           boolean frames_are_ordered_diagonally = (g->offset_x != 0 &&
652                                                    g->offset_y != 0);
653           boolean front_is_left_or_upper = (src_x_front < src_x_back ||
654                                             src_y_front < src_y_back);
655 #if 0
656           boolean second_tile_is_back =
657             ((move_dir == MV_BIT_LEFT  && front_is_left_or_upper) ||
658              (move_dir == MV_BIT_UP    && front_is_left_or_upper));
659           boolean second_tile_is_front =
660             ((move_dir == MV_BIT_RIGHT && front_is_left_or_upper) ||
661              (move_dir == MV_BIT_DOWN  && front_is_left_or_upper));
662           boolean second_tile_should_be_front =
663             (g->second_tile_is_start == 0);
664           boolean second_tile_should_be_back =
665             (g->second_tile_is_start == 1);
666 #endif
667           boolean swap_movement_tiles_always = (g->swap_double_tiles == 1);
668           boolean swap_movement_tiles_autodetected =
669             (!frames_are_ordered_diagonally &&
670              ((move_dir == MV_BIT_LEFT  && !front_is_left_or_upper) ||
671               (move_dir == MV_BIT_UP    && !front_is_left_or_upper) ||
672               (move_dir == MV_BIT_RIGHT &&  front_is_left_or_upper) ||
673               (move_dir == MV_BIT_DOWN  &&  front_is_left_or_upper)));
674           Bitmap *dummy;
675
676 #if 0
677           printf("::: CHECKING element %d ('%s'), '%s', dir %d [(%d -> %d, %d), %d => %d]\n",
678                  i, element_info[i].token_name,
679                  element_action_info[act].suffix, move_dir,
680                  g->swap_double_tiles,
681                  swap_movement_tiles_never,
682                  swap_movement_tiles_always,
683                  swap_movement_tiles_autodetected,
684                  swap_movement_tiles);
685 #endif
686
687           /* swap frontside and backside graphic tile coordinates, if needed */
688           if (swap_movement_tiles_always || swap_movement_tiles_autodetected)
689           {
690             /* get current (wrong) backside tile coordinates */
691             getGraphicSourceExt(graphic, 0, &dummy, &src_x_back, &src_y_back,
692                                 TRUE);
693
694             /* set frontside tile coordinates to backside tile coordinates */
695             g->src_x = src_x_back;
696             g->src_y = src_y_back;
697
698             /* invert tile offset to point to new backside tile coordinates */
699             g->offset2_x *= -1;
700             g->offset2_y *= -1;
701
702             /* do not swap front and backside tiles again after correction */
703             g->swap_double_tiles = 0;
704
705 #if 0
706             printf("    CORRECTED\n");
707 #endif
708           }
709         }
710       }
711     }
712   }
713 #endif
714
715   /* now set all '-1' values to element specific default values */
716   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
717   {
718     int default_graphic = element_info[i].graphic[ACTION_DEFAULT];
719     int default_crumbled = element_info[i].crumbled[ACTION_DEFAULT];
720     int default_direction_graphic[NUM_DIRECTIONS];
721     int default_direction_crumbled[NUM_DIRECTIONS];
722
723     if (default_graphic == -1)
724       default_graphic = IMG_UNKNOWN;
725 #if 1
726     if (default_crumbled == -1)
727       default_crumbled = default_graphic;
728 #else
729     /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
730     if (default_crumbled == -1)
731       default_crumbled = IMG_EMPTY;
732 #endif
733
734     for (dir = 0; dir < NUM_DIRECTIONS; dir++)
735     {
736       default_direction_graphic[dir] =
737         element_info[i].direction_graphic[ACTION_DEFAULT][dir];
738       default_direction_crumbled[dir] =
739         element_info[i].direction_crumbled[ACTION_DEFAULT][dir];
740
741       if (default_direction_graphic[dir] == -1)
742         default_direction_graphic[dir] = default_graphic;
743 #if 1
744       if (default_direction_crumbled[dir] == -1)
745         default_direction_crumbled[dir] = default_direction_graphic[dir];
746 #else
747       /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
748       if (default_direction_crumbled[dir] == -1)
749         default_direction_crumbled[dir] = default_crumbled;
750 #endif
751     }
752
753     for (act = 0; act < NUM_ACTIONS; act++)
754     {
755       boolean act_remove = ((IS_DIGGABLE(i)    && act == ACTION_DIGGING)  ||
756                             (IS_SNAPPABLE(i)   && act == ACTION_SNAPPING) ||
757                             (IS_COLLECTIBLE(i) && act == ACTION_COLLECTING));
758       boolean act_turning = (act == ACTION_TURNING_FROM_LEFT ||
759                              act == ACTION_TURNING_FROM_RIGHT ||
760                              act == ACTION_TURNING_FROM_UP ||
761                              act == ACTION_TURNING_FROM_DOWN);
762
763       /* generic default action graphic (defined by "[default]" directive) */
764       int default_action_graphic = element_info[EL_DEFAULT].graphic[act];
765       int default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
766       int default_remove_graphic = IMG_EMPTY;
767
768       if (act_remove && default_action_graphic != -1)
769         default_remove_graphic = default_action_graphic;
770
771       /* look for special default action graphic (classic game specific) */
772       if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].graphic[act] != -1)
773         default_action_graphic = element_info[EL_BD_DEFAULT].graphic[act];
774       if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].graphic[act] != -1)
775         default_action_graphic = element_info[EL_SP_DEFAULT].graphic[act];
776       if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].graphic[act] != -1)
777         default_action_graphic = element_info[EL_SB_DEFAULT].graphic[act];
778
779       if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].crumbled[act] != -1)
780         default_action_crumbled = element_info[EL_BD_DEFAULT].crumbled[act];
781       if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].crumbled[act] != -1)
782         default_action_crumbled = element_info[EL_SP_DEFAULT].crumbled[act];
783       if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].crumbled[act] != -1)
784         default_action_crumbled = element_info[EL_SB_DEFAULT].crumbled[act];
785
786 #if 1
787       /* !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!! */
788       /* !!! make this better !!! */
789       if (i == EL_EMPTY_SPACE)
790       {
791         default_action_graphic = element_info[EL_DEFAULT].graphic[act];
792         default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
793       }
794 #endif
795
796       if (default_action_graphic == -1)
797         default_action_graphic = default_graphic;
798 #if 1
799       if (default_action_crumbled == -1)
800         default_action_crumbled = default_action_graphic;
801 #else
802       /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
803       if (default_action_crumbled == -1)
804         default_action_crumbled = default_crumbled;
805 #endif
806
807       for (dir = 0; dir < NUM_DIRECTIONS; dir++)
808       {
809         int default_action_direction_graphic = element_info[i].graphic[act];
810         int default_action_direction_crumbled = element_info[i].crumbled[act];
811
812         /* no graphic for current action -- use default direction graphic */
813         /* !!! maybe it's better to use default _action_ graphic here !!! */
814         if (default_action_direction_graphic == -1)
815           default_action_direction_graphic =
816             (act_remove ? default_remove_graphic :
817              act_turning ?
818              element_info[i].direction_graphic[ACTION_TURNING][dir] :
819              default_direction_graphic[dir]);
820 #if 1
821         if (default_action_direction_crumbled == -1)
822           default_action_direction_crumbled = default_action_direction_graphic;
823 #else
824         if (default_action_direction_crumbled == -1)
825           default_action_direction_crumbled =
826             (act_remove ? default_remove_graphic :
827              act_turning ?
828              element_info[i].direction_crumbled[ACTION_TURNING][dir] :
829              default_direction_crumbled[dir]);
830 #endif
831
832         if (element_info[i].direction_graphic[act][dir] == -1)
833           element_info[i].direction_graphic[act][dir] =
834             default_action_direction_graphic;
835 #if 1
836         if (element_info[i].direction_crumbled[act][dir] == -1)
837           element_info[i].direction_crumbled[act][dir] =
838             element_info[i].direction_graphic[act][dir];
839 #else
840         if (element_info[i].direction_crumbled[act][dir] == -1)
841           element_info[i].direction_crumbled[act][dir] =
842             default_action_direction_crumbled;
843 #endif
844       }
845
846       /* no graphic for this specific action -- use default action graphic */
847       if (element_info[i].graphic[act] == -1)
848         element_info[i].graphic[act] =
849           (act_remove ? default_remove_graphic :
850            act_turning ? element_info[i].graphic[ACTION_TURNING] :
851            default_action_graphic);
852 #if 1
853       if (element_info[i].crumbled[act] == -1)
854         element_info[i].crumbled[act] = element_info[i].graphic[act];
855 #else
856       if (element_info[i].crumbled[act] == -1)
857         element_info[i].crumbled[act] =
858           (act_remove ? default_remove_graphic :
859            act_turning ? element_info[i].crumbled[ACTION_TURNING] :
860            default_action_crumbled);
861 #endif
862     }
863   }
864
865 #if 1
866   /* set animation mode to "none" for each graphic with only 1 frame */
867   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
868   {
869     for (act = 0; act < NUM_ACTIONS; act++)
870     {
871       int graphic = element_info[i].graphic[act];
872       int crumbled = element_info[i].crumbled[act];
873
874       if (graphic_info[graphic].anim_frames == 1)
875         graphic_info[graphic].anim_mode = ANIM_NONE;
876       if (graphic_info[crumbled].anim_frames == 1)
877         graphic_info[crumbled].anim_mode = ANIM_NONE;
878
879       for (dir = 0; dir < NUM_DIRECTIONS; dir++)
880       {
881         graphic = element_info[i].direction_graphic[act][dir];
882         crumbled = element_info[i].direction_crumbled[act][dir];
883
884         if (graphic_info[graphic].anim_frames == 1)
885           graphic_info[graphic].anim_mode = ANIM_NONE;
886         if (graphic_info[crumbled].anim_frames == 1)
887           graphic_info[crumbled].anim_mode = ANIM_NONE;
888       }
889     }
890   }
891 #endif
892
893 #if 0
894 #if DEBUG
895   if (options.verbose)
896   {
897     for (i = 0; i < MAX_NUM_ELEMENTS; i++)
898       if (element_info[i].graphic[ACTION_DEFAULT] == IMG_UNKNOWN &&
899           i != EL_UNKNOWN)
900         Error(ERR_RETURN, "warning: no graphic for element '%s' (%d)",
901               element_info[i].token_name, i);
902   }
903 #endif
904 #endif
905 }
906
907 void InitElementSpecialGraphicInfo()
908 {
909   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
910   int num_property_mappings = getImageListPropertyMappingSize();
911   int i, j;
912
913   /* always start with reliable default values */
914   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
915     for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
916       element_info[i].special_graphic[j] =
917         element_info[i].graphic[ACTION_DEFAULT];
918
919   /* initialize special element/graphic mapping from static configuration */
920   for (i = 0; element_to_special_graphic[i].element > -1; i++)
921   {
922     int element = element_to_special_graphic[i].element;
923     int special = element_to_special_graphic[i].special;
924     int graphic = element_to_special_graphic[i].graphic;
925     int base_graphic = el2baseimg(element);
926     boolean base_redefined =
927       getImageListEntryFromImageID(base_graphic)->redefined;
928     boolean special_redefined =
929       getImageListEntryFromImageID(graphic)->redefined;
930
931     /* if the base graphic ("emerald", for example) has been redefined,
932        but not the special graphic ("emerald.EDITOR", for example), do not
933        use an existing (in this case considered obsolete) special graphic
934        anymore, but use the automatically created (down-scaled) graphic */
935     if (base_redefined && !special_redefined)
936       continue;
937
938     element_info[element].special_graphic[special] = graphic;
939   }
940
941   /* initialize special element/graphic mapping from dynamic configuration */
942   for (i = 0; i < num_property_mappings; i++)
943   {
944     int element = property_mapping[i].base_index;
945     int special = property_mapping[i].ext3_index;
946     int graphic = property_mapping[i].artwork_index;
947
948     if (element >= MAX_NUM_ELEMENTS)
949       continue;
950
951     if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
952       element_info[element].special_graphic[special] = graphic;
953   }
954
955 #if 1
956   /* now set all undefined/invalid graphics to default */
957   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
958     for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
959       if (graphic_info[element_info[i].special_graphic[j]].bitmap == NULL)
960         element_info[i].special_graphic[j] =
961           element_info[i].graphic[ACTION_DEFAULT];
962 #endif
963 }
964
965 static int get_element_from_token(char *token)
966 {
967   int i;
968
969   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
970     if (strcmp(element_info[i].token_name, token) == 0)
971       return i;
972
973   return -1;
974 }
975
976 static int get_scaled_graphic_width(int graphic)
977 {
978   int original_width = getOriginalImageWidthFromImageID(graphic);
979   int scale_up_factor = graphic_info[graphic].scale_up_factor;
980
981   return original_width * scale_up_factor;
982 }
983
984 static int get_scaled_graphic_height(int graphic)
985 {
986   int original_height = getOriginalImageHeightFromImageID(graphic);
987   int scale_up_factor = graphic_info[graphic].scale_up_factor;
988
989   return original_height * scale_up_factor;
990 }
991
992 static void set_graphic_parameters(int graphic, int graphic_copy_from)
993 {
994   struct FileInfo *image = getImageListEntryFromImageID(graphic_copy_from);
995   char **parameter_raw = image->parameter;
996   Bitmap *src_bitmap = getBitmapFromImageID(graphic_copy_from);
997   int parameter[NUM_GFX_ARGS];
998   int anim_frames_per_row = 1, anim_frames_per_col = 1;
999   int anim_frames_per_line = 1;
1000   int i;
1001
1002   /* get integer values from string parameters */
1003   for (i = 0; i < NUM_GFX_ARGS; i++)
1004   {
1005     parameter[i] =
1006       get_parameter_value(image_config_suffix[i].token, parameter_raw[i],
1007                           image_config_suffix[i].type);
1008
1009     if (image_config_suffix[i].type == TYPE_TOKEN)
1010       parameter[i] = get_element_from_token(parameter_raw[i]);
1011   }
1012
1013   graphic_info[graphic].bitmap = src_bitmap;
1014
1015   /* start with reliable default values */
1016   graphic_info[graphic].src_x = 0;
1017   graphic_info[graphic].src_y = 0;
1018   graphic_info[graphic].width = TILEX;
1019   graphic_info[graphic].height = TILEY;
1020   graphic_info[graphic].offset_x = 0;   /* one or both of these values ... */
1021   graphic_info[graphic].offset_y = 0;   /* ... will be corrected later */
1022   graphic_info[graphic].offset2_x = 0;  /* one or both of these values ... */
1023   graphic_info[graphic].offset2_y = 0;  /* ... will be corrected later */
1024   graphic_info[graphic].swap_double_tiles = -1; /* auto-detect tile swapping */
1025   graphic_info[graphic].crumbled_like = -1;     /* do not use clone element */
1026   graphic_info[graphic].diggable_like = -1;     /* do not use clone element */
1027   graphic_info[graphic].border_size = TILEX / 8;  /* "CRUMBLED" border size */
1028   graphic_info[graphic].scale_up_factor = 1;    /* default: no scaling up */
1029   graphic_info[graphic].anim_delay_fixed = 0;
1030   graphic_info[graphic].anim_delay_random = 0;
1031   graphic_info[graphic].post_delay_fixed = 0;
1032   graphic_info[graphic].post_delay_random = 0;
1033
1034   /* optional x and y tile position of animation frame sequence */
1035   if (parameter[GFX_ARG_XPOS] != ARG_UNDEFINED_VALUE)
1036     graphic_info[graphic].src_x = parameter[GFX_ARG_XPOS] * TILEX;
1037   if (parameter[GFX_ARG_YPOS] != ARG_UNDEFINED_VALUE)
1038     graphic_info[graphic].src_y = parameter[GFX_ARG_YPOS] * TILEY;
1039
1040   /* optional x and y pixel position of animation frame sequence */
1041   if (parameter[GFX_ARG_X] != ARG_UNDEFINED_VALUE)
1042     graphic_info[graphic].src_x = parameter[GFX_ARG_X];
1043   if (parameter[GFX_ARG_Y] != ARG_UNDEFINED_VALUE)
1044     graphic_info[graphic].src_y = parameter[GFX_ARG_Y];
1045
1046   /* optional width and height of each animation frame */
1047   if (parameter[GFX_ARG_WIDTH] != ARG_UNDEFINED_VALUE)
1048     graphic_info[graphic].width = parameter[GFX_ARG_WIDTH];
1049   if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE)
1050     graphic_info[graphic].height = parameter[GFX_ARG_HEIGHT];
1051
1052   /* optional zoom factor for scaling up the image to a larger size */
1053   if (parameter[GFX_ARG_SCALE_UP_FACTOR] != ARG_UNDEFINED_VALUE)
1054     graphic_info[graphic].scale_up_factor = parameter[GFX_ARG_SCALE_UP_FACTOR];
1055   if (graphic_info[graphic].scale_up_factor < 1)
1056     graphic_info[graphic].scale_up_factor = 1;          /* no scaling */
1057
1058   if (src_bitmap)
1059   {
1060     /* get final bitmap size (with scaling, but without small images) */
1061     int src_bitmap_width  = get_scaled_graphic_width(graphic);
1062     int src_bitmap_height = get_scaled_graphic_height(graphic);
1063
1064     anim_frames_per_row = src_bitmap_width  / graphic_info[graphic].width;
1065     anim_frames_per_col = src_bitmap_height / graphic_info[graphic].height;
1066   }
1067
1068   /* correct x or y offset dependent of vertical or horizontal frame order */
1069   if (parameter[GFX_ARG_VERTICAL])      /* frames are ordered vertically */
1070   {
1071     graphic_info[graphic].offset_y =
1072       (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
1073        parameter[GFX_ARG_OFFSET] : graphic_info[graphic].height);
1074     anim_frames_per_line = anim_frames_per_col;
1075   }
1076   else                                  /* frames are ordered horizontally */
1077   {
1078     graphic_info[graphic].offset_x =
1079       (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
1080        parameter[GFX_ARG_OFFSET] : graphic_info[graphic].width);
1081     anim_frames_per_line = anim_frames_per_row;
1082   }
1083
1084   /* optionally, the x and y offset of frames can be specified directly */
1085   if (parameter[GFX_ARG_XOFFSET] != ARG_UNDEFINED_VALUE)
1086     graphic_info[graphic].offset_x = parameter[GFX_ARG_XOFFSET];
1087   if (parameter[GFX_ARG_YOFFSET] != ARG_UNDEFINED_VALUE)
1088     graphic_info[graphic].offset_y = parameter[GFX_ARG_YOFFSET];
1089
1090   /* optionally, moving animations may have separate start and end graphics */
1091   graphic_info[graphic].double_movement = parameter[GFX_ARG_2ND_MOVEMENT_TILE];
1092
1093   if (parameter[GFX_ARG_2ND_VERTICAL] == ARG_UNDEFINED_VALUE)
1094     parameter[GFX_ARG_2ND_VERTICAL] = !parameter[GFX_ARG_VERTICAL];
1095
1096   /* correct x or y offset2 dependent of vertical or horizontal frame order */
1097   if (parameter[GFX_ARG_2ND_VERTICAL])  /* frames are ordered vertically */
1098     graphic_info[graphic].offset2_y =
1099       (parameter[GFX_ARG_2ND_OFFSET] != ARG_UNDEFINED_VALUE ?
1100        parameter[GFX_ARG_2ND_OFFSET] : graphic_info[graphic].height);
1101   else                                  /* frames are ordered horizontally */
1102     graphic_info[graphic].offset2_x =
1103       (parameter[GFX_ARG_2ND_OFFSET] != ARG_UNDEFINED_VALUE ?
1104        parameter[GFX_ARG_2ND_OFFSET] : graphic_info[graphic].width);
1105
1106   /* optionally, the x and y offset of 2nd graphic can be specified directly */
1107   if (parameter[GFX_ARG_2ND_XOFFSET] != ARG_UNDEFINED_VALUE)
1108     graphic_info[graphic].offset2_x = parameter[GFX_ARG_2ND_XOFFSET];
1109   if (parameter[GFX_ARG_2ND_YOFFSET] != ARG_UNDEFINED_VALUE)
1110     graphic_info[graphic].offset2_y = parameter[GFX_ARG_2ND_YOFFSET];
1111
1112   /* optionally, the second movement tile can be specified as start tile */
1113   if (parameter[GFX_ARG_2ND_SWAP_TILES] != ARG_UNDEFINED_VALUE)
1114     graphic_info[graphic].swap_double_tiles= parameter[GFX_ARG_2ND_SWAP_TILES];
1115
1116   /* automatically determine correct number of frames, if not defined */
1117   if (parameter[GFX_ARG_FRAMES] != ARG_UNDEFINED_VALUE)
1118     graphic_info[graphic].anim_frames = parameter[GFX_ARG_FRAMES];
1119   else if (parameter[GFX_ARG_XPOS] == 0 && !parameter[GFX_ARG_VERTICAL])
1120     graphic_info[graphic].anim_frames = anim_frames_per_row;
1121   else if (parameter[GFX_ARG_YPOS] == 0 && parameter[GFX_ARG_VERTICAL])
1122     graphic_info[graphic].anim_frames = anim_frames_per_col;
1123   else
1124     graphic_info[graphic].anim_frames = 1;
1125
1126   graphic_info[graphic].anim_frames_per_line =
1127     (parameter[GFX_ARG_FRAMES_PER_LINE] != ARG_UNDEFINED_VALUE ?
1128      parameter[GFX_ARG_FRAMES_PER_LINE] : anim_frames_per_line);
1129
1130   graphic_info[graphic].anim_delay = parameter[GFX_ARG_DELAY];
1131   if (graphic_info[graphic].anim_delay == 0)    /* delay must be at least 1 */
1132     graphic_info[graphic].anim_delay = 1;
1133
1134   graphic_info[graphic].anim_mode = parameter[GFX_ARG_ANIM_MODE];
1135 #if 0
1136   if (graphic_info[graphic].anim_frames == 1)
1137     graphic_info[graphic].anim_mode = ANIM_NONE;
1138 #endif
1139
1140   /* automatically determine correct start frame, if not defined */
1141   if (parameter[GFX_ARG_START_FRAME] == ARG_UNDEFINED_VALUE)
1142     graphic_info[graphic].anim_start_frame = 0;
1143   else if (graphic_info[graphic].anim_mode & ANIM_REVERSE)
1144     graphic_info[graphic].anim_start_frame =
1145       graphic_info[graphic].anim_frames - parameter[GFX_ARG_START_FRAME] - 1;
1146   else
1147     graphic_info[graphic].anim_start_frame = parameter[GFX_ARG_START_FRAME];
1148
1149   /* animation synchronized with global frame counter, not move position */
1150   graphic_info[graphic].anim_global_sync = parameter[GFX_ARG_GLOBAL_SYNC];
1151
1152   /* optional element for cloning crumble graphics */
1153   if (parameter[GFX_ARG_CRUMBLED_LIKE] != ARG_UNDEFINED_VALUE)
1154     graphic_info[graphic].crumbled_like = parameter[GFX_ARG_CRUMBLED_LIKE];
1155
1156   /* optional element for cloning digging graphics */
1157   if (parameter[GFX_ARG_DIGGABLE_LIKE] != ARG_UNDEFINED_VALUE)
1158     graphic_info[graphic].diggable_like = parameter[GFX_ARG_DIGGABLE_LIKE];
1159
1160   /* optional border size for "crumbling" diggable graphics */
1161   if (parameter[GFX_ARG_BORDER_SIZE] != ARG_UNDEFINED_VALUE)
1162     graphic_info[graphic].border_size = parameter[GFX_ARG_BORDER_SIZE];
1163
1164   /* this is only used for player "boring" and "sleeping" actions */
1165   if (parameter[GFX_ARG_ANIM_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
1166     graphic_info[graphic].anim_delay_fixed =
1167       parameter[GFX_ARG_ANIM_DELAY_FIXED];
1168   if (parameter[GFX_ARG_ANIM_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
1169     graphic_info[graphic].anim_delay_random =
1170       parameter[GFX_ARG_ANIM_DELAY_RANDOM];
1171   if (parameter[GFX_ARG_POST_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
1172     graphic_info[graphic].post_delay_fixed =
1173       parameter[GFX_ARG_POST_DELAY_FIXED];
1174   if (parameter[GFX_ARG_POST_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
1175     graphic_info[graphic].post_delay_random =
1176       parameter[GFX_ARG_POST_DELAY_RANDOM];
1177
1178   /* this is only used for toon animations */
1179   graphic_info[graphic].step_offset = parameter[GFX_ARG_STEP_OFFSET];
1180   graphic_info[graphic].step_delay  = parameter[GFX_ARG_STEP_DELAY];
1181
1182   /* this is only used for drawing font characters */
1183   graphic_info[graphic].draw_x = parameter[GFX_ARG_DRAW_XOFFSET];
1184   graphic_info[graphic].draw_y = parameter[GFX_ARG_DRAW_YOFFSET];
1185
1186   /* this is only used for drawing envelope graphics */
1187   graphic_info[graphic].draw_masked = parameter[GFX_ARG_DRAW_MASKED];
1188 }
1189
1190 static void InitGraphicInfo()
1191 {
1192   int fallback_graphic = IMG_CHAR_EXCLAM;
1193   int num_images = getImageListSize();
1194   int i;
1195
1196 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1197   static boolean clipmasks_initialized = FALSE;
1198   Pixmap src_pixmap;
1199   XGCValues clip_gc_values;
1200   unsigned long clip_gc_valuemask;
1201   GC copy_clipmask_gc = None;
1202 #endif
1203
1204   checked_free(graphic_info);
1205
1206   graphic_info = checked_calloc(num_images * sizeof(struct GraphicInfo));
1207
1208 #if 0
1209   printf("::: graphic_info: %d entries\n", num_images);
1210 #endif
1211
1212 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1213   if (clipmasks_initialized)
1214   {
1215     for (i = 0; i < num_images; i++)
1216     {
1217       if (graphic_info[i].clip_mask)
1218         XFreePixmap(display, graphic_info[i].clip_mask);
1219       if (graphic_info[i].clip_gc)
1220         XFreeGC(display, graphic_info[i].clip_gc);
1221
1222       graphic_info[i].clip_mask = None;
1223       graphic_info[i].clip_gc = None;
1224     }
1225   }
1226 #endif
1227
1228   for (i = 0; i < num_images; i++)
1229   {
1230     Bitmap *src_bitmap;
1231     int src_x, src_y;
1232     int first_frame, last_frame;
1233     int src_bitmap_width, src_bitmap_height;
1234
1235 #if 0
1236     printf("::: image: '%s' [%d]\n", image->token, i);
1237 #endif
1238
1239 #if 0
1240     printf("::: image # %d: '%s' ['%s']\n",
1241            i, image->token,
1242            getTokenFromImageID(i));
1243 #endif
1244
1245     set_graphic_parameters(i, i);
1246
1247     /* now check if no animation frames are outside of the loaded image */
1248
1249     if (graphic_info[i].bitmap == NULL)
1250       continue;         /* skip check for optional images that are undefined */
1251
1252     /* get final bitmap size (with scaling, but without small images) */
1253     src_bitmap_width  = get_scaled_graphic_width(i);
1254     src_bitmap_height = get_scaled_graphic_height(i);
1255
1256     first_frame = 0;
1257     getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
1258     if (src_x < 0 || src_y < 0 ||
1259         src_x + TILEX > src_bitmap_width ||
1260         src_y + TILEY > src_bitmap_height)
1261     {
1262       Error(ERR_RETURN_LINE, "-");
1263       Error(ERR_RETURN, "warning: error found in config file:");
1264       Error(ERR_RETURN, "- config file: '%s'",
1265             getImageConfigFilename());
1266       Error(ERR_RETURN, "- config token: '%s'",
1267             getTokenFromImageID(i));
1268       Error(ERR_RETURN, "- image file: '%s'",
1269             src_bitmap->source_filename);
1270       Error(ERR_RETURN,
1271             "error: first animation frame out of bounds (%d, %d)",
1272             src_x, src_y);
1273       Error(ERR_RETURN, "custom graphic rejected for this element/action");
1274
1275 #if 0
1276       Error(ERR_RETURN, "scale_up_factor == %d", scale_up_factor);
1277 #endif
1278
1279       if (i == fallback_graphic)
1280         Error(ERR_EXIT, "fatal error: no fallback graphic available");
1281
1282       Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
1283       Error(ERR_RETURN_LINE, "-");
1284
1285       set_graphic_parameters(i, fallback_graphic);
1286     }
1287
1288     last_frame = graphic_info[i].anim_frames - 1;
1289     getGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y);
1290     if (src_x < 0 || src_y < 0 ||
1291         src_x + TILEX > src_bitmap_width ||
1292         src_y + TILEY > src_bitmap_height)
1293     {
1294       Error(ERR_RETURN_LINE, "-");
1295       Error(ERR_RETURN, "warning: error found in config file:");
1296       Error(ERR_RETURN, "- config file: '%s'",
1297             getImageConfigFilename());
1298       Error(ERR_RETURN, "- config token: '%s'",
1299             getTokenFromImageID(i));
1300       Error(ERR_RETURN, "- image file: '%s'",
1301             src_bitmap->source_filename);
1302       Error(ERR_RETURN,
1303             "error: last animation frame (%d) out of bounds (%d, %d)",
1304             last_frame, src_x, src_y);
1305       Error(ERR_RETURN, "custom graphic rejected for this element/action");
1306
1307       if (i == fallback_graphic)
1308         Error(ERR_EXIT, "fatal error: no fallback graphic available");
1309
1310       Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
1311       Error(ERR_RETURN_LINE, "-");
1312
1313       set_graphic_parameters(i, fallback_graphic);
1314     }
1315
1316 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1317     /* currently we only need a tile clip mask from the first frame */
1318     getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
1319
1320     if (copy_clipmask_gc == None)
1321     {
1322       clip_gc_values.graphics_exposures = False;
1323       clip_gc_valuemask = GCGraphicsExposures;
1324       copy_clipmask_gc = XCreateGC(display, src_bitmap->clip_mask,
1325                                    clip_gc_valuemask, &clip_gc_values);
1326     }
1327
1328     graphic_info[i].clip_mask =
1329       XCreatePixmap(display, window->drawable, TILEX, TILEY, 1);
1330
1331     src_pixmap = src_bitmap->clip_mask;
1332     XCopyArea(display, src_pixmap, graphic_info[i].clip_mask,
1333               copy_clipmask_gc, src_x, src_y, TILEX, TILEY, 0, 0);
1334
1335     clip_gc_values.graphics_exposures = False;
1336     clip_gc_values.clip_mask = graphic_info[i].clip_mask;
1337     clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
1338
1339     graphic_info[i].clip_gc =
1340       XCreateGC(display, window->drawable, clip_gc_valuemask, &clip_gc_values);
1341 #endif
1342   }
1343
1344 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1345   if (copy_clipmask_gc)
1346     XFreeGC(display, copy_clipmask_gc);
1347
1348   clipmasks_initialized = TRUE;
1349 #endif
1350 }
1351
1352 static void InitElementSoundInfo()
1353 {
1354   struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1355   int num_property_mappings = getSoundListPropertyMappingSize();
1356   int i, j, act;
1357
1358   /* set values to -1 to identify later as "uninitialized" values */
1359   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1360     for (act = 0; act < NUM_ACTIONS; act++)
1361       element_info[i].sound[act] = -1;
1362
1363   /* initialize element/sound mapping from static configuration */
1364   for (i = 0; element_to_sound[i].element > -1; i++)
1365   {
1366     int element      = element_to_sound[i].element;
1367     int action       = element_to_sound[i].action;
1368     int sound        = element_to_sound[i].sound;
1369     boolean is_class = element_to_sound[i].is_class;
1370
1371     if (action < 0)
1372       action = ACTION_DEFAULT;
1373
1374     if (!is_class)
1375       element_info[element].sound[action] = sound;
1376     else
1377       for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1378         if (strcmp(element_info[j].class_name,
1379                    element_info[element].class_name) == 0)
1380           element_info[j].sound[action] = sound;
1381   }
1382
1383   /* initialize element class/sound mapping from dynamic configuration */
1384   for (i = 0; i < num_property_mappings; i++)
1385   {
1386     int element_class = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
1387     int action        = property_mapping[i].ext1_index;
1388     int sound         = property_mapping[i].artwork_index;
1389
1390     if (element_class < 0 || element_class >= MAX_NUM_ELEMENTS)
1391       continue;
1392
1393     if (action < 0)
1394       action = ACTION_DEFAULT;
1395
1396     for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1397       if (strcmp(element_info[j].class_name,
1398                  element_info[element_class].class_name) == 0)
1399         element_info[j].sound[action] = sound;
1400   }
1401
1402   /* initialize element/sound mapping from dynamic configuration */
1403   for (i = 0; i < num_property_mappings; i++)
1404   {
1405     int element = property_mapping[i].base_index;
1406     int action  = property_mapping[i].ext1_index;
1407     int sound   = property_mapping[i].artwork_index;
1408
1409     if (element >= MAX_NUM_ELEMENTS)
1410       continue;
1411
1412     if (action < 0)
1413       action = ACTION_DEFAULT;
1414
1415     element_info[element].sound[action] = sound;
1416   }
1417
1418   /* now set all '-1' values to element specific default values */
1419   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1420   {
1421     for (act = 0; act < NUM_ACTIONS; act++)
1422     {
1423       /* generic default action sound (defined by "[default]" directive) */
1424       int default_action_sound = element_info[EL_DEFAULT].sound[act];
1425
1426       /* look for special default action sound (classic game specific) */
1427       if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].sound[act] != -1)
1428         default_action_sound = element_info[EL_BD_DEFAULT].sound[act];
1429       if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].sound[act] != -1)
1430         default_action_sound = element_info[EL_SP_DEFAULT].sound[act];
1431       if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].sound[act] != -1)
1432         default_action_sound = element_info[EL_SB_DEFAULT].sound[act];
1433
1434       /* !!! there's no such thing as a "default action sound" !!! */
1435 #if 0
1436       /* look for element specific default sound (independent from action) */
1437       if (element_info[i].sound[ACTION_DEFAULT] != -1)
1438         default_action_sound = element_info[i].sound[ACTION_DEFAULT];
1439 #endif
1440
1441 #if 1
1442       /* !!! needed because EL_EMPTY_SPACE treated as IS_SP_ELEMENT !!! */
1443       /* !!! make this better !!! */
1444       if (i == EL_EMPTY_SPACE)
1445         default_action_sound = element_info[EL_DEFAULT].sound[act];
1446 #endif
1447
1448       /* no sound for this specific action -- use default action sound */
1449       if (element_info[i].sound[act] == -1)
1450         element_info[i].sound[act] = default_action_sound;
1451     }
1452   }
1453 }
1454
1455 static void InitGameModeSoundInfo()
1456 {
1457   int i;
1458
1459   /* set values to -1 to identify later as "uninitialized" values */
1460   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1461     menu.sound[i] = -1;
1462
1463   /* initialize gamemode/sound mapping from static configuration */
1464   for (i = 0; gamemode_to_sound[i].sound > -1; i++)
1465   {
1466     int gamemode = gamemode_to_sound[i].gamemode;
1467     int sound    = gamemode_to_sound[i].sound;
1468
1469     if (gamemode < 0)
1470       gamemode = GAME_MODE_DEFAULT;
1471
1472     menu.sound[gamemode] = sound;
1473   }
1474
1475   /* now set all '-1' values to levelset specific default values */
1476   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1477     if (menu.sound[i] == -1)
1478       menu.sound[i] = menu.sound[GAME_MODE_DEFAULT];
1479
1480 #if 0
1481   /* TEST ONLY */
1482   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1483     if (menu.sound[i] != -1)
1484       printf("::: menu.sound[%d] == %d\n", i, menu.sound[i]);
1485 #endif
1486 }
1487
1488 static void set_sound_parameters(int sound, char **parameter_raw)
1489 {
1490   int parameter[NUM_SND_ARGS];
1491   int i;
1492
1493   /* get integer values from string parameters */
1494   for (i = 0; i < NUM_SND_ARGS; i++)
1495     parameter[i] =
1496       get_parameter_value(sound_config_suffix[i].token, parameter_raw[i],
1497                           sound_config_suffix[i].type);
1498
1499   /* explicit loop mode setting in configuration overrides default value */
1500   if (parameter[SND_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
1501     sound_info[sound].loop = parameter[SND_ARG_MODE_LOOP];
1502
1503   /* sound volume to change the original volume when loading the sound file */
1504   sound_info[sound].volume = parameter[SND_ARG_VOLUME];
1505
1506   /* sound priority to give certain sounds a higher or lower priority */
1507   sound_info[sound].volume = parameter[SND_ARG_VOLUME];
1508 }
1509
1510 static void InitSoundInfo()
1511 {
1512 #if 0
1513   struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1514   int num_property_mappings = getSoundListPropertyMappingSize();
1515 #endif
1516   int *sound_effect_properties;
1517   int num_sounds = getSoundListSize();
1518   int i, j;
1519
1520   checked_free(sound_info);
1521
1522   sound_effect_properties = checked_calloc(num_sounds * sizeof(int));
1523   sound_info = checked_calloc(num_sounds * sizeof(struct SoundInfo));
1524
1525   /* initialize sound effect for all elements to "no sound" */
1526   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1527     for (j = 0; j < NUM_ACTIONS; j++)
1528       element_info[i].sound[j] = SND_UNDEFINED;
1529
1530   for (i = 0; i < num_sounds; i++)
1531   {
1532     struct FileInfo *sound = getSoundListEntry(i);
1533     int len_effect_text = strlen(sound->token);
1534
1535     sound_effect_properties[i] = ACTION_OTHER;
1536     sound_info[i].loop = FALSE;         /* default: play sound only once */
1537
1538 #if 0
1539     printf("::: sound %d: '%s'\n", i, sound->token);
1540 #endif
1541
1542     /* determine all loop sounds and identify certain sound classes */
1543
1544     for (j = 0; element_action_info[j].suffix; j++)
1545     {
1546       int len_action_text = strlen(element_action_info[j].suffix);
1547
1548       if (len_action_text < len_effect_text &&
1549           strcmp(&sound->token[len_effect_text - len_action_text],
1550                  element_action_info[j].suffix) == 0)
1551       {
1552         sound_effect_properties[i] = element_action_info[j].value;
1553         sound_info[i].loop = element_action_info[j].is_loop_sound;
1554
1555         break;
1556       }
1557     }
1558
1559 #if 0
1560     if (strcmp(sound->token, "custom_42") == 0)
1561       printf("::: '%s' -> %d\n", sound->token, sound_info[i].loop);
1562 #endif
1563
1564     /* associate elements and some selected sound actions */
1565
1566     for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1567     {
1568       if (element_info[j].class_name)
1569       {
1570         int len_class_text = strlen(element_info[j].class_name);
1571
1572         if (len_class_text + 1 < len_effect_text &&
1573             strncmp(sound->token,
1574                     element_info[j].class_name, len_class_text) == 0 &&
1575             sound->token[len_class_text] == '.')
1576         {
1577           int sound_action_value = sound_effect_properties[i];
1578
1579           element_info[j].sound[sound_action_value] = i;
1580         }
1581       }
1582     }
1583
1584     set_sound_parameters(i, sound->parameter);
1585   }
1586
1587   free(sound_effect_properties);
1588
1589 #if 0
1590   /* !!! now handled in InitElementSoundInfo() !!! */
1591   /* initialize element/sound mapping from dynamic configuration */
1592   for (i = 0; i < num_property_mappings; i++)
1593   {
1594     int element   = property_mapping[i].base_index;
1595     int action    = property_mapping[i].ext1_index;
1596     int sound     = property_mapping[i].artwork_index;
1597
1598     if (action < 0)
1599       action = ACTION_DEFAULT;
1600
1601     printf("::: %d: %d, %d, %d ['%s']\n",
1602            i, element, action, sound, element_info[element].token_name);
1603
1604     element_info[element].sound[action] = sound;
1605   }
1606 #endif
1607
1608 #if 0
1609   /* TEST ONLY */
1610   {
1611     int element = EL_CUSTOM_11;
1612     int j = 0;
1613
1614     while (element_action_info[j].suffix)
1615     {
1616       printf("element %d, sound action '%s'  == %d\n",
1617              element, element_action_info[j].suffix,
1618              element_info[element].sound[j]);
1619       j++;
1620     }
1621   }
1622
1623   PlaySoundLevelElementAction(0,0, EL_CUSTOM_11, ACTION_PUSHING);
1624 #endif
1625
1626 #if 0
1627   /* TEST ONLY */
1628   {
1629     int element = EL_SAND;
1630     int sound_action = ACTION_DIGGING;
1631     int j = 0;
1632
1633     while (element_action_info[j].suffix)
1634     {
1635       if (element_action_info[j].value == sound_action)
1636         printf("element %d, sound action '%s'  == %d\n",
1637                element, element_action_info[j].suffix,
1638                element_info[element].sound[sound_action]);
1639       j++;
1640     }
1641   }
1642 #endif
1643 }
1644
1645 static void InitGameModeMusicInfo()
1646 {
1647   struct PropertyMapping *property_mapping = getMusicListPropertyMapping();
1648   int num_property_mappings = getMusicListPropertyMappingSize();
1649   int default_levelset_music = -1;
1650   int i;
1651
1652   /* set values to -1 to identify later as "uninitialized" values */
1653   for (i = 0; i < MAX_LEVELS; i++)
1654     levelset.music[i] = -1;
1655   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1656     menu.music[i] = -1;
1657
1658   /* initialize gamemode/music mapping from static configuration */
1659   for (i = 0; gamemode_to_music[i].music > -1; i++)
1660   {
1661     int gamemode = gamemode_to_music[i].gamemode;
1662     int music    = gamemode_to_music[i].music;
1663
1664 #if 0
1665     printf("::: gamemode == %d, music == %d\n", gamemode, music);
1666 #endif
1667
1668     if (gamemode < 0)
1669       gamemode = GAME_MODE_DEFAULT;
1670
1671     menu.music[gamemode] = music;
1672   }
1673
1674   /* initialize gamemode/music mapping from dynamic configuration */
1675   for (i = 0; i < num_property_mappings; i++)
1676   {
1677     int prefix   = property_mapping[i].base_index;
1678     int gamemode = property_mapping[i].ext1_index;
1679     int level    = property_mapping[i].ext2_index;
1680     int music    = property_mapping[i].artwork_index;
1681
1682 #if 0
1683     printf("::: prefix == %d, gamemode == %d, level == %d, music == %d\n",
1684            prefix, gamemode, level, music);
1685 #endif
1686
1687     if (prefix < 0 || prefix >= NUM_MUSIC_PREFIXES)
1688       continue;
1689
1690     if (gamemode < 0)
1691       gamemode = GAME_MODE_DEFAULT;
1692
1693     /* level specific music only allowed for in-game music */
1694     if (level != -1 && gamemode == GAME_MODE_DEFAULT)
1695       gamemode = GAME_MODE_PLAYING;
1696
1697     if (level == -1)
1698     {
1699       level = 0;
1700       default_levelset_music = music;
1701     }
1702
1703     if (gamemode == GAME_MODE_PLAYING || gamemode == GAME_MODE_DEFAULT)
1704       levelset.music[level] = music;
1705     if (gamemode != GAME_MODE_PLAYING)
1706       menu.music[gamemode] = music;
1707   }
1708
1709   /* now set all '-1' values to menu specific default values */
1710   /* (undefined values of "levelset.music[]" might stay at "-1" to
1711      allow dynamic selection of music files from music directory!) */
1712   for (i = 0; i < MAX_LEVELS; i++)
1713     if (levelset.music[i] == -1)
1714       levelset.music[i] = default_levelset_music;
1715   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1716     if (menu.music[i] == -1)
1717       menu.music[i] = menu.music[GAME_MODE_DEFAULT];
1718
1719 #if 0
1720   /* TEST ONLY */
1721   for (i = 0; i < MAX_LEVELS; i++)
1722     if (levelset.music[i] != -1)
1723       printf("::: levelset.music[%d] == %d\n", i, levelset.music[i]);
1724   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1725     if (menu.music[i] != -1)
1726       printf("::: menu.music[%d] == %d\n", i, menu.music[i]);
1727 #endif
1728 }
1729
1730 static void set_music_parameters(int music, char **parameter_raw)
1731 {
1732   int parameter[NUM_MUS_ARGS];
1733   int i;
1734
1735   /* get integer values from string parameters */
1736   for (i = 0; i < NUM_MUS_ARGS; i++)
1737     parameter[i] =
1738       get_parameter_value(music_config_suffix[i].token, parameter_raw[i],
1739                           music_config_suffix[i].type);
1740
1741   /* explicit loop mode setting in configuration overrides default value */
1742   if (parameter[MUS_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
1743     music_info[music].loop = parameter[MUS_ARG_MODE_LOOP];
1744 }
1745
1746 static void InitMusicInfo()
1747 {
1748   int num_music = getMusicListSize();
1749   int i, j;
1750
1751   checked_free(music_info);
1752
1753   music_info = checked_calloc(num_music * sizeof(struct MusicInfo));
1754
1755   for (i = 0; i < num_music; i++)
1756   {
1757     struct FileInfo *music = getMusicListEntry(i);
1758     int len_music_text = strlen(music->token);
1759
1760     music_info[i].loop = TRUE;          /* default: play music in loop mode */
1761
1762     /* determine all loop music */
1763
1764     for (j = 0; music_prefix_info[j].prefix; j++)
1765     {
1766       int len_prefix_text = strlen(music_prefix_info[j].prefix);
1767
1768       if (len_prefix_text < len_music_text &&
1769           strncmp(music->token,
1770                   music_prefix_info[j].prefix, len_prefix_text) == 0)
1771       {
1772         music_info[i].loop = music_prefix_info[j].is_loop_music;
1773
1774         break;
1775       }
1776     }
1777
1778     set_music_parameters(i, music->parameter);
1779   }
1780 }
1781
1782 static void ReinitializeGraphics()
1783 {
1784   InitGraphicInfo();                    /* graphic properties mapping */
1785   InitElementGraphicInfo();             /* element game graphic mapping */
1786   InitElementSpecialGraphicInfo();      /* element special graphic mapping */
1787
1788   InitElementSmallImages();             /* scale images to all needed sizes */
1789   InitFontGraphicInfo();                /* initialize text drawing functions */
1790
1791   InitGraphicInfo_EM();                 /* graphic mapping for EM engine */
1792
1793   SetMainBackgroundImage(IMG_BACKGROUND);
1794   SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
1795
1796   InitGadgets();
1797   InitToons();
1798 }
1799
1800 static void ReinitializeSounds()
1801 {
1802   InitSoundInfo();              /* sound properties mapping */
1803   InitElementSoundInfo();       /* element game sound mapping */
1804   InitGameModeSoundInfo();      /* game mode sound mapping */
1805
1806   InitPlayLevelSound();         /* internal game sound settings */
1807 }
1808
1809 static void ReinitializeMusic()
1810 {
1811   InitMusicInfo();              /* music properties mapping */
1812   InitGameModeMusicInfo();      /* game mode music mapping */
1813 }
1814
1815 static int get_special_property_bit(int element, int property_bit_nr)
1816 {
1817   struct PropertyBitInfo
1818   {
1819     int element;
1820     int bit_nr;
1821   };
1822
1823   static struct PropertyBitInfo pb_can_move_into_acid[] =
1824   {
1825     /* the player may be able fall into acid when gravity is activated */
1826     { EL_PLAYER_1,              0       },
1827     { EL_PLAYER_2,              0       },
1828     { EL_PLAYER_3,              0       },
1829     { EL_PLAYER_4,              0       },
1830     { EL_SP_MURPHY,             0       },
1831     { EL_SOKOBAN_FIELD_PLAYER,  0       },
1832
1833     /* all element that can move may be able to also move into acid */
1834     { EL_BUG,                   1       },
1835     { EL_BUG_LEFT,              1       },
1836     { EL_BUG_RIGHT,             1       },
1837     { EL_BUG_UP,                1       },
1838     { EL_BUG_DOWN,              1       },
1839     { EL_SPACESHIP,             2       },
1840     { EL_SPACESHIP_LEFT,        2       },
1841     { EL_SPACESHIP_RIGHT,       2       },
1842     { EL_SPACESHIP_UP,          2       },
1843     { EL_SPACESHIP_DOWN,        2       },
1844     { EL_BD_BUTTERFLY,          3       },
1845     { EL_BD_BUTTERFLY_LEFT,     3       },
1846     { EL_BD_BUTTERFLY_RIGHT,    3       },
1847     { EL_BD_BUTTERFLY_UP,       3       },
1848     { EL_BD_BUTTERFLY_DOWN,     3       },
1849     { EL_BD_FIREFLY,            4       },
1850     { EL_BD_FIREFLY_LEFT,       4       },
1851     { EL_BD_FIREFLY_RIGHT,      4       },
1852     { EL_BD_FIREFLY_UP,         4       },
1853     { EL_BD_FIREFLY_DOWN,       4       },
1854     { EL_YAMYAM,                5       },
1855     { EL_DARK_YAMYAM,           6       },
1856     { EL_ROBOT,                 7       },
1857     { EL_PACMAN,                8       },
1858     { EL_PACMAN_LEFT,           8       },
1859     { EL_PACMAN_RIGHT,          8       },
1860     { EL_PACMAN_UP,             8       },
1861     { EL_PACMAN_DOWN,           8       },
1862     { EL_MOLE,                  9       },
1863     { EL_MOLE_LEFT,             9       },
1864     { EL_MOLE_RIGHT,            9       },
1865     { EL_MOLE_UP,               9       },
1866     { EL_MOLE_DOWN,             9       },
1867     { EL_PENGUIN,               10      },
1868     { EL_PIG,                   11      },
1869     { EL_DRAGON,                12      },
1870     { EL_SATELLITE,             13      },
1871     { EL_SP_SNIKSNAK,           14      },
1872     { EL_SP_ELECTRON,           15      },
1873     { EL_BALLOON,               16      },
1874     { EL_SPRING,                17      },
1875
1876     { -1,                       -1      },
1877   };
1878
1879   static struct PropertyBitInfo pb_dont_collide_with[] =
1880   {
1881     { EL_SP_SNIKSNAK,           0       },
1882     { EL_SP_ELECTRON,           1       },
1883
1884     { -1,                       -1      },
1885   };
1886
1887   static struct
1888   {
1889     int bit_nr;
1890     struct PropertyBitInfo *pb_info;
1891   } pb_definition[] =
1892   {
1893     { EP_CAN_MOVE_INTO_ACID,    pb_can_move_into_acid   },
1894     { EP_DONT_COLLIDE_WITH,     pb_dont_collide_with    },
1895
1896     { -1,                       NULL                    },
1897   };
1898
1899   struct PropertyBitInfo *pb_info = NULL;
1900   int i;
1901
1902   for (i = 0; pb_definition[i].bit_nr != -1; i++)
1903     if (pb_definition[i].bit_nr == property_bit_nr)
1904       pb_info = pb_definition[i].pb_info;
1905
1906   if (pb_info == NULL)
1907     return -1;
1908
1909   for (i = 0; pb_info[i].element != -1; i++)
1910     if (pb_info[i].element == element)
1911       return pb_info[i].bit_nr;
1912
1913   return -1;
1914 }
1915
1916 #if 1
1917 void setBitfieldProperty(int *bitfield, int property_bit_nr, int element,
1918                          boolean property_value)
1919 {
1920   int bit_nr = get_special_property_bit(element, property_bit_nr);
1921
1922   if (bit_nr > -1)
1923   {
1924     if (property_value)
1925       *bitfield |=  (1 << bit_nr);
1926     else
1927       *bitfield &= ~(1 << bit_nr);
1928   }
1929 }
1930
1931 boolean getBitfieldProperty(int *bitfield, int property_bit_nr, int element)
1932 {
1933   int bit_nr = get_special_property_bit(element, property_bit_nr);
1934
1935   if (bit_nr > -1)
1936     return ((*bitfield & (1 << bit_nr)) != 0);
1937
1938   return FALSE;
1939 }
1940
1941 #else
1942
1943 void setMoveIntoAcidProperty(struct LevelInfo *level, int element, boolean set)
1944 {
1945   int bit_nr = get_special_property_bit(element, EP_CAN_MOVE_INTO_ACID);
1946
1947   if (bit_nr > -1)
1948   {
1949     level->can_move_into_acid_bits &= ~(1 << bit_nr);
1950
1951     if (set)
1952       level->can_move_into_acid_bits |= (1 << bit_nr);
1953   }
1954 }
1955
1956 boolean getMoveIntoAcidProperty(struct LevelInfo *level, int element)
1957 {
1958   int bit_nr = get_special_property_bit(element, EP_CAN_MOVE_INTO_ACID);
1959
1960   if (bit_nr > -1)
1961     return ((level->can_move_into_acid_bits & (1 << bit_nr)) != 0);
1962
1963   return FALSE;
1964 }
1965 #endif
1966
1967 void InitElementPropertiesStatic()
1968 {
1969   static int ep_diggable[] =
1970   {
1971     EL_SAND,
1972     EL_SP_BASE,
1973     EL_SP_BUGGY_BASE,
1974     EL_SP_BUGGY_BASE_ACTIVATING,
1975     EL_TRAP,
1976     EL_INVISIBLE_SAND,
1977     EL_INVISIBLE_SAND_ACTIVE,
1978     EL_EMC_GRASS,
1979
1980     /* !!! currently not diggable, but handled by 'ep_dont_run_into' !!! */
1981     /* (if amoeba can grow into anything diggable, maybe keep these out) */
1982 #if 0
1983     EL_LANDMINE,
1984     EL_TRAP_ACTIVE,
1985     EL_SP_BUGGY_BASE_ACTIVE,
1986     EL_EMC_PLANT,
1987 #endif
1988     -1
1989   };
1990
1991   static int ep_collectible_only[] =
1992   {
1993     EL_BD_DIAMOND,
1994     EL_EMERALD,
1995     EL_DIAMOND,
1996     EL_EMERALD_YELLOW,
1997     EL_EMERALD_RED,
1998     EL_EMERALD_PURPLE,
1999     EL_KEY_1,
2000     EL_KEY_2,
2001     EL_KEY_3,
2002     EL_KEY_4,
2003     EL_EM_KEY_1,
2004     EL_EM_KEY_2,
2005     EL_EM_KEY_3,
2006     EL_EM_KEY_4,
2007     EL_EM_KEY_5,
2008     EL_EM_KEY_6,
2009     EL_EM_KEY_7,
2010     EL_EM_KEY_8,
2011     EL_DYNAMITE,
2012     EL_DYNABOMB_INCREASE_NUMBER,
2013     EL_DYNABOMB_INCREASE_SIZE,
2014     EL_DYNABOMB_INCREASE_POWER,
2015     EL_SP_INFOTRON,
2016     EL_SP_DISK_RED,
2017     EL_PEARL,
2018     EL_CRYSTAL,
2019     EL_KEY_WHITE,
2020     EL_SHIELD_NORMAL,
2021     EL_SHIELD_DEADLY,
2022     EL_EXTRA_TIME,
2023     EL_ENVELOPE_1,
2024     EL_ENVELOPE_2,
2025     EL_ENVELOPE_3,
2026     EL_ENVELOPE_4,
2027     EL_SPEED_PILL,
2028     EL_EMC_LENSES,
2029     EL_EMC_MAGNIFIER,
2030     -1
2031   };
2032
2033   static int ep_dont_run_into[] =
2034   {
2035     /* same elements as in 'ep_dont_touch' */
2036     EL_BUG,
2037     EL_SPACESHIP,
2038     EL_BD_BUTTERFLY,
2039     EL_BD_FIREFLY,
2040
2041     /* same elements as in 'ep_dont_collide_with' */
2042     EL_YAMYAM,
2043     EL_DARK_YAMYAM,
2044     EL_ROBOT,
2045     EL_PACMAN,
2046     EL_SP_SNIKSNAK,
2047     EL_SP_ELECTRON,
2048
2049     /* new elements */
2050     EL_AMOEBA_DROP,
2051     EL_ACID,
2052
2053     /* !!! maybe this should better be handled by 'ep_diggable' !!! */
2054 #if 1
2055     EL_LANDMINE,
2056     EL_TRAP_ACTIVE,
2057     EL_SP_BUGGY_BASE_ACTIVE,
2058     EL_EMC_PLANT,
2059 #endif
2060     -1
2061   };
2062
2063   static int ep_dont_collide_with[] =
2064   {
2065     /* same elements as in 'ep_dont_touch' */
2066     EL_BUG,
2067     EL_SPACESHIP,
2068     EL_BD_BUTTERFLY,
2069     EL_BD_FIREFLY,
2070
2071     /* new elements */
2072     EL_YAMYAM,
2073     EL_DARK_YAMYAM,
2074     EL_ROBOT,
2075     EL_PACMAN,
2076     EL_SP_SNIKSNAK,
2077     EL_SP_ELECTRON,
2078     -1
2079   };
2080
2081   static int ep_dont_touch[] =
2082   {
2083     EL_BUG,
2084     EL_SPACESHIP,
2085     EL_BD_BUTTERFLY,
2086     EL_BD_FIREFLY,
2087     -1
2088   };
2089
2090   static int ep_indestructible[] =
2091   {
2092     EL_STEELWALL,
2093     EL_ACID,
2094     EL_ACID_POOL_TOPLEFT,
2095     EL_ACID_POOL_TOPRIGHT,
2096     EL_ACID_POOL_BOTTOMLEFT,
2097     EL_ACID_POOL_BOTTOM,
2098     EL_ACID_POOL_BOTTOMRIGHT,
2099     EL_SP_HARDWARE_GRAY,
2100     EL_SP_HARDWARE_GREEN,
2101     EL_SP_HARDWARE_BLUE,
2102     EL_SP_HARDWARE_RED,
2103     EL_SP_HARDWARE_YELLOW,
2104     EL_SP_HARDWARE_BASE_1,
2105     EL_SP_HARDWARE_BASE_2,
2106     EL_SP_HARDWARE_BASE_3,
2107     EL_SP_HARDWARE_BASE_4,
2108     EL_SP_HARDWARE_BASE_5,
2109     EL_SP_HARDWARE_BASE_6,
2110     EL_INVISIBLE_STEELWALL,
2111     EL_INVISIBLE_STEELWALL_ACTIVE,
2112     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2113     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2114     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2115     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2116     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2117     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2118     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2119     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2120     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2121     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2122     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2123     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2124     EL_LIGHT_SWITCH,
2125     EL_LIGHT_SWITCH_ACTIVE,
2126     EL_SIGN_EXCLAMATION,
2127     EL_SIGN_RADIOACTIVITY,
2128     EL_SIGN_STOP,
2129     EL_SIGN_WHEELCHAIR,
2130     EL_SIGN_PARKING,
2131     EL_SIGN_ONEWAY,
2132     EL_SIGN_HEART,
2133     EL_SIGN_TRIANGLE,
2134     EL_SIGN_ROUND,
2135     EL_SIGN_EXIT,
2136     EL_SIGN_YINYANG,
2137     EL_SIGN_OTHER,
2138     EL_STEELWALL_SLIPPERY,
2139     EL_EMC_STEELWALL_1,
2140     EL_EMC_STEELWALL_2,
2141     EL_EMC_STEELWALL_3,
2142     EL_EMC_STEELWALL_4,
2143     EL_CRYSTAL,
2144     EL_GATE_1,
2145     EL_GATE_2,
2146     EL_GATE_3,
2147     EL_GATE_4,
2148     EL_GATE_1_GRAY,
2149     EL_GATE_2_GRAY,
2150     EL_GATE_3_GRAY,
2151     EL_GATE_4_GRAY,
2152     EL_EM_GATE_1,
2153     EL_EM_GATE_2,
2154     EL_EM_GATE_3,
2155     EL_EM_GATE_4,
2156     EL_EM_GATE_1_GRAY,
2157     EL_EM_GATE_2_GRAY,
2158     EL_EM_GATE_3_GRAY,
2159     EL_EM_GATE_4_GRAY,
2160     EL_SWITCHGATE_OPEN,
2161     EL_SWITCHGATE_OPENING,
2162     EL_SWITCHGATE_CLOSED,
2163     EL_SWITCHGATE_CLOSING,
2164 #if 0
2165     EL_SWITCHGATE_SWITCH_UP,
2166     EL_SWITCHGATE_SWITCH_DOWN,
2167 #endif
2168     EL_TIMEGATE_OPEN,
2169     EL_TIMEGATE_OPENING,
2170     EL_TIMEGATE_CLOSED,
2171     EL_TIMEGATE_CLOSING,
2172 #if 0
2173     EL_TIMEGATE_SWITCH,
2174     EL_TIMEGATE_SWITCH_ACTIVE,
2175 #endif
2176     EL_TUBE_ANY,
2177     EL_TUBE_VERTICAL,
2178     EL_TUBE_HORIZONTAL,
2179     EL_TUBE_VERTICAL_LEFT,
2180     EL_TUBE_VERTICAL_RIGHT,
2181     EL_TUBE_HORIZONTAL_UP,
2182     EL_TUBE_HORIZONTAL_DOWN,
2183     EL_TUBE_LEFT_UP,
2184     EL_TUBE_LEFT_DOWN,
2185     EL_TUBE_RIGHT_UP,
2186     EL_TUBE_RIGHT_DOWN,
2187     -1
2188   };
2189
2190   static int ep_slippery[] =
2191   {
2192     EL_WALL_SLIPPERY,
2193     EL_BD_WALL,
2194     EL_ROCK,
2195     EL_BD_ROCK,
2196     EL_EMERALD,
2197     EL_BD_DIAMOND,
2198     EL_EMERALD_YELLOW,
2199     EL_EMERALD_RED,
2200     EL_EMERALD_PURPLE,
2201     EL_DIAMOND,
2202     EL_BOMB,
2203     EL_NUT,
2204     EL_ROBOT_WHEEL_ACTIVE,
2205     EL_ROBOT_WHEEL,
2206     EL_TIME_ORB_FULL,
2207     EL_TIME_ORB_EMPTY,
2208     EL_LAMP_ACTIVE,
2209     EL_LAMP,
2210     EL_ACID_POOL_TOPLEFT,
2211     EL_ACID_POOL_TOPRIGHT,
2212     EL_SATELLITE,
2213     EL_SP_ZONK,
2214     EL_SP_INFOTRON,
2215     EL_SP_CHIP_SINGLE,
2216     EL_SP_CHIP_LEFT,
2217     EL_SP_CHIP_RIGHT,
2218     EL_SP_CHIP_TOP,
2219     EL_SP_CHIP_BOTTOM,
2220     EL_SPEED_PILL,
2221     EL_STEELWALL_SLIPPERY,
2222     EL_PEARL,
2223     EL_CRYSTAL,
2224     EL_EMC_WALL_SLIPPERY_1,
2225     EL_EMC_WALL_SLIPPERY_2,
2226     EL_EMC_WALL_SLIPPERY_3,
2227     EL_EMC_WALL_SLIPPERY_4,
2228     -1
2229   };
2230
2231   static int ep_can_change[] =
2232   {
2233     -1
2234   };
2235
2236   static int ep_can_move[] =
2237   {
2238     /* same elements as in 'pb_can_move_into_acid' */
2239     EL_BUG,
2240     EL_SPACESHIP,
2241     EL_BD_BUTTERFLY,
2242     EL_BD_FIREFLY,
2243     EL_YAMYAM,
2244     EL_DARK_YAMYAM,
2245     EL_ROBOT,
2246     EL_PACMAN,
2247     EL_MOLE,
2248     EL_PENGUIN,
2249     EL_PIG,
2250     EL_DRAGON,
2251     EL_SATELLITE,
2252     EL_SP_SNIKSNAK,
2253     EL_SP_ELECTRON,
2254     EL_BALLOON,
2255     EL_SPRING,
2256     EL_EMC_ANDROID,
2257     -1
2258   };
2259
2260   static int ep_can_fall[] =
2261   {
2262     EL_ROCK,
2263     EL_BD_ROCK,
2264     EL_EMERALD,
2265     EL_BD_DIAMOND,
2266     EL_EMERALD_YELLOW,
2267     EL_EMERALD_RED,
2268     EL_EMERALD_PURPLE,
2269     EL_DIAMOND,
2270     EL_BOMB,
2271     EL_NUT,
2272     EL_AMOEBA_DROP,
2273     EL_QUICKSAND_FULL,
2274     EL_MAGIC_WALL_FULL,
2275     EL_BD_MAGIC_WALL_FULL,
2276     EL_TIME_ORB_FULL,
2277     EL_TIME_ORB_EMPTY,
2278     EL_SP_ZONK,
2279     EL_SP_INFOTRON,
2280     EL_SP_DISK_ORANGE,
2281     EL_PEARL,
2282     EL_CRYSTAL,
2283     EL_SPRING,
2284     EL_DX_SUPABOMB,
2285     -1
2286   };
2287
2288   static int ep_can_smash_player[] =
2289   {
2290     EL_ROCK,
2291     EL_BD_ROCK,
2292     EL_EMERALD,
2293     EL_BD_DIAMOND,
2294     EL_EMERALD_YELLOW,
2295     EL_EMERALD_RED,
2296     EL_EMERALD_PURPLE,
2297     EL_DIAMOND,
2298     EL_BOMB,
2299     EL_NUT,
2300     EL_AMOEBA_DROP,
2301     EL_TIME_ORB_FULL,
2302     EL_TIME_ORB_EMPTY,
2303     EL_SP_ZONK,
2304     EL_SP_INFOTRON,
2305     EL_SP_DISK_ORANGE,
2306     EL_PEARL,
2307     EL_CRYSTAL,
2308     EL_SPRING,
2309     EL_DX_SUPABOMB,
2310     -1
2311   };
2312
2313   static int ep_can_smash_enemies[] =
2314   {
2315     EL_ROCK,
2316     EL_BD_ROCK,
2317     EL_SP_ZONK,
2318     -1
2319   };
2320
2321   static int ep_can_smash_everything[] =
2322   {
2323     EL_ROCK,
2324     EL_BD_ROCK,
2325     EL_SP_ZONK,
2326     -1
2327   };
2328
2329   static int ep_explodes_by_fire[] =
2330   {
2331     /* same elements as in 'ep_explodes_impact' */
2332     EL_BOMB,
2333     EL_SP_DISK_ORANGE,
2334     EL_DX_SUPABOMB,
2335
2336     /* same elements as in 'ep_explodes_smashed' */
2337     EL_SATELLITE,
2338     EL_PIG,
2339     EL_DRAGON,
2340     EL_MOLE,
2341
2342     /* new elements */
2343     EL_DYNAMITE_ACTIVE,
2344     EL_DYNAMITE,
2345     EL_DYNABOMB_PLAYER_1_ACTIVE,
2346     EL_DYNABOMB_PLAYER_2_ACTIVE,
2347     EL_DYNABOMB_PLAYER_3_ACTIVE,
2348     EL_DYNABOMB_PLAYER_4_ACTIVE,
2349     EL_DYNABOMB_INCREASE_NUMBER,
2350     EL_DYNABOMB_INCREASE_SIZE,
2351     EL_DYNABOMB_INCREASE_POWER,
2352     EL_SP_DISK_RED_ACTIVE,
2353     EL_BUG,
2354     EL_PENGUIN,
2355     EL_SP_DISK_RED,
2356     EL_SP_DISK_YELLOW,
2357     EL_SP_SNIKSNAK,
2358     EL_SP_ELECTRON,
2359 #if 0
2360     EL_BLACK_ORB,
2361 #endif
2362     -1
2363   };
2364
2365   static int ep_explodes_smashed[] =
2366   {
2367     /* same elements as in 'ep_explodes_impact' */
2368     EL_BOMB,
2369     EL_SP_DISK_ORANGE,
2370     EL_DX_SUPABOMB,
2371
2372     /* new elements */
2373     EL_SATELLITE,
2374     EL_PIG,
2375     EL_DRAGON,
2376     EL_MOLE,
2377     -1
2378   };
2379
2380   static int ep_explodes_impact[] =
2381   {
2382     EL_BOMB,
2383     EL_SP_DISK_ORANGE,
2384     EL_DX_SUPABOMB,
2385     -1
2386   };
2387
2388   static int ep_walkable_over[] =
2389   {
2390     EL_EMPTY_SPACE,
2391     EL_SP_EMPTY_SPACE,
2392     EL_SOKOBAN_FIELD_EMPTY,
2393     EL_EXIT_OPEN,
2394     EL_SP_EXIT_OPEN,
2395     EL_SP_EXIT_OPENING,
2396     EL_GATE_1,
2397     EL_GATE_2,
2398     EL_GATE_3,
2399     EL_GATE_4,
2400     EL_GATE_1_GRAY,
2401     EL_GATE_2_GRAY,
2402     EL_GATE_3_GRAY,
2403     EL_GATE_4_GRAY,
2404     EL_PENGUIN,
2405     EL_PIG,
2406     EL_DRAGON,
2407     -1
2408   };
2409
2410   static int ep_walkable_inside[] =
2411   {
2412     EL_TUBE_ANY,
2413     EL_TUBE_VERTICAL,
2414     EL_TUBE_HORIZONTAL,
2415     EL_TUBE_VERTICAL_LEFT,
2416     EL_TUBE_VERTICAL_RIGHT,
2417     EL_TUBE_HORIZONTAL_UP,
2418     EL_TUBE_HORIZONTAL_DOWN,
2419     EL_TUBE_LEFT_UP,
2420     EL_TUBE_LEFT_DOWN,
2421     EL_TUBE_RIGHT_UP,
2422     EL_TUBE_RIGHT_DOWN,
2423     -1
2424   };
2425
2426   static int ep_walkable_under[] =
2427   {
2428     -1
2429   };
2430
2431   static int ep_passable_over[] =
2432   {
2433     EL_EM_GATE_1,
2434     EL_EM_GATE_2,
2435     EL_EM_GATE_3,
2436     EL_EM_GATE_4,
2437     EL_EM_GATE_5,
2438     EL_EM_GATE_6,
2439     EL_EM_GATE_7,
2440     EL_EM_GATE_8,
2441     EL_EM_GATE_1_GRAY,
2442     EL_EM_GATE_2_GRAY,
2443     EL_EM_GATE_3_GRAY,
2444     EL_EM_GATE_4_GRAY,
2445     EL_EM_GATE_5_GRAY,
2446     EL_EM_GATE_6_GRAY,
2447     EL_EM_GATE_7_GRAY,
2448     EL_EM_GATE_8_GRAY,
2449     EL_SWITCHGATE_OPEN,
2450     EL_TIMEGATE_OPEN,
2451     -1
2452   };
2453
2454   static int ep_passable_inside[] =
2455   {
2456     EL_SP_PORT_LEFT,
2457     EL_SP_PORT_RIGHT,
2458     EL_SP_PORT_UP,
2459     EL_SP_PORT_DOWN,
2460     EL_SP_PORT_HORIZONTAL,
2461     EL_SP_PORT_VERTICAL,
2462     EL_SP_PORT_ANY,
2463     EL_SP_GRAVITY_PORT_LEFT,
2464     EL_SP_GRAVITY_PORT_RIGHT,
2465     EL_SP_GRAVITY_PORT_UP,
2466     EL_SP_GRAVITY_PORT_DOWN,
2467     EL_SP_GRAVITY_ON_PORT_LEFT,
2468     EL_SP_GRAVITY_ON_PORT_RIGHT,
2469     EL_SP_GRAVITY_ON_PORT_UP,
2470     EL_SP_GRAVITY_ON_PORT_DOWN,
2471     EL_SP_GRAVITY_OFF_PORT_LEFT,
2472     EL_SP_GRAVITY_OFF_PORT_RIGHT,
2473     EL_SP_GRAVITY_OFF_PORT_UP,
2474     EL_SP_GRAVITY_OFF_PORT_DOWN,
2475     -1
2476   };
2477
2478   static int ep_passable_under[] =
2479   {
2480     -1
2481   };
2482
2483   static int ep_droppable[] =
2484   {
2485     -1
2486   };
2487
2488   static int ep_explodes_1x1_old[] =
2489   {
2490     -1
2491   };
2492
2493   static int ep_pushable[] =
2494   {
2495     EL_ROCK,
2496     EL_BOMB,
2497     EL_DX_SUPABOMB,
2498     EL_NUT,
2499     EL_TIME_ORB_EMPTY,
2500     EL_SP_ZONK,
2501     EL_SP_DISK_ORANGE,
2502     EL_SPRING,
2503     EL_BD_ROCK,
2504     EL_SOKOBAN_OBJECT,
2505     EL_SOKOBAN_FIELD_FULL,
2506     EL_SATELLITE,
2507     EL_SP_DISK_YELLOW,
2508     EL_BALLOON,
2509     EL_EMC_ANDROID,
2510     -1
2511   };
2512
2513   static int ep_explodes_cross_old[] =
2514   {
2515     -1
2516   };
2517
2518   static int ep_protected[] =
2519   {
2520     /* same elements as in 'ep_walkable_inside' */
2521     EL_TUBE_ANY,
2522     EL_TUBE_VERTICAL,
2523     EL_TUBE_HORIZONTAL,
2524     EL_TUBE_VERTICAL_LEFT,
2525     EL_TUBE_VERTICAL_RIGHT,
2526     EL_TUBE_HORIZONTAL_UP,
2527     EL_TUBE_HORIZONTAL_DOWN,
2528     EL_TUBE_LEFT_UP,
2529     EL_TUBE_LEFT_DOWN,
2530     EL_TUBE_RIGHT_UP,
2531     EL_TUBE_RIGHT_DOWN,
2532
2533     /* same elements as in 'ep_passable_over' */
2534     EL_EM_GATE_1,
2535     EL_EM_GATE_2,
2536     EL_EM_GATE_3,
2537     EL_EM_GATE_4,
2538     EL_EM_GATE_5,
2539     EL_EM_GATE_6,
2540     EL_EM_GATE_7,
2541     EL_EM_GATE_8,
2542     EL_EM_GATE_1_GRAY,
2543     EL_EM_GATE_2_GRAY,
2544     EL_EM_GATE_3_GRAY,
2545     EL_EM_GATE_4_GRAY,
2546     EL_EM_GATE_5_GRAY,
2547     EL_EM_GATE_6_GRAY,
2548     EL_EM_GATE_7_GRAY,
2549     EL_EM_GATE_8_GRAY,
2550     EL_SWITCHGATE_OPEN,
2551     EL_TIMEGATE_OPEN,
2552
2553     /* same elements as in 'ep_passable_inside' */
2554     EL_SP_PORT_LEFT,
2555     EL_SP_PORT_RIGHT,
2556     EL_SP_PORT_UP,
2557     EL_SP_PORT_DOWN,
2558     EL_SP_PORT_HORIZONTAL,
2559     EL_SP_PORT_VERTICAL,
2560     EL_SP_PORT_ANY,
2561     EL_SP_GRAVITY_PORT_LEFT,
2562     EL_SP_GRAVITY_PORT_RIGHT,
2563     EL_SP_GRAVITY_PORT_UP,
2564     EL_SP_GRAVITY_PORT_DOWN,
2565     EL_SP_GRAVITY_ON_PORT_LEFT,
2566     EL_SP_GRAVITY_ON_PORT_RIGHT,
2567     EL_SP_GRAVITY_ON_PORT_UP,
2568     EL_SP_GRAVITY_ON_PORT_DOWN,
2569     EL_SP_GRAVITY_OFF_PORT_LEFT,
2570     EL_SP_GRAVITY_OFF_PORT_RIGHT,
2571     EL_SP_GRAVITY_OFF_PORT_UP,
2572     EL_SP_GRAVITY_OFF_PORT_DOWN,
2573     -1
2574   };
2575
2576   static int ep_throwable[] =
2577   {
2578     -1
2579   };
2580
2581   static int ep_can_explode[] =
2582   {
2583     /* same elements as in 'ep_explodes_impact' */
2584     EL_BOMB,
2585     EL_SP_DISK_ORANGE,
2586     EL_DX_SUPABOMB,
2587
2588     /* same elements as in 'ep_explodes_smashed' */
2589     EL_SATELLITE,
2590     EL_PIG,
2591     EL_DRAGON,
2592     EL_MOLE,
2593
2594     /* elements that can explode by explosion or by dragonfire */
2595     EL_DYNAMITE_ACTIVE,
2596     EL_DYNAMITE,
2597     EL_DYNABOMB_PLAYER_1_ACTIVE,
2598     EL_DYNABOMB_PLAYER_2_ACTIVE,
2599     EL_DYNABOMB_PLAYER_3_ACTIVE,
2600     EL_DYNABOMB_PLAYER_4_ACTIVE,
2601     EL_DYNABOMB_INCREASE_NUMBER,
2602     EL_DYNABOMB_INCREASE_SIZE,
2603     EL_DYNABOMB_INCREASE_POWER,
2604     EL_SP_DISK_RED_ACTIVE,
2605     EL_BUG,
2606     EL_PENGUIN,
2607     EL_SP_DISK_RED,
2608     EL_SP_DISK_YELLOW,
2609     EL_SP_SNIKSNAK,
2610     EL_SP_ELECTRON,
2611
2612     /* elements that can explode only by explosion */
2613     EL_BLACK_ORB,
2614     -1
2615   };
2616
2617   static int ep_gravity_reachable[] =
2618   {
2619     EL_SAND,
2620     EL_SP_BASE,
2621     EL_TRAP,
2622     EL_INVISIBLE_SAND,
2623     EL_INVISIBLE_SAND_ACTIVE,
2624     EL_SP_PORT_LEFT,
2625     EL_SP_PORT_RIGHT,
2626     EL_SP_PORT_UP,
2627     EL_SP_PORT_DOWN,
2628     EL_SP_PORT_HORIZONTAL,
2629     EL_SP_PORT_VERTICAL,
2630     EL_SP_PORT_ANY,
2631     EL_SP_GRAVITY_PORT_LEFT,
2632     EL_SP_GRAVITY_PORT_RIGHT,
2633     EL_SP_GRAVITY_PORT_UP,
2634     EL_SP_GRAVITY_PORT_DOWN,
2635     EL_SP_GRAVITY_ON_PORT_LEFT,
2636     EL_SP_GRAVITY_ON_PORT_RIGHT,
2637     EL_SP_GRAVITY_ON_PORT_UP,
2638     EL_SP_GRAVITY_ON_PORT_DOWN,
2639     EL_SP_GRAVITY_OFF_PORT_LEFT,
2640     EL_SP_GRAVITY_OFF_PORT_RIGHT,
2641     EL_SP_GRAVITY_OFF_PORT_UP,
2642     EL_SP_GRAVITY_OFF_PORT_DOWN,
2643     EL_EMC_GRASS,
2644     -1
2645   };
2646
2647   static int ep_player[] =
2648   {
2649     EL_PLAYER_1,
2650     EL_PLAYER_2,
2651     EL_PLAYER_3,
2652     EL_PLAYER_4,
2653     EL_SP_MURPHY,
2654     EL_SOKOBAN_FIELD_PLAYER,
2655     EL_TRIGGER_PLAYER,
2656     -1
2657   };
2658
2659   static int ep_can_pass_magic_wall[] =
2660   {
2661     EL_ROCK,
2662     EL_BD_ROCK,
2663     EL_EMERALD,
2664     EL_BD_DIAMOND,
2665     EL_EMERALD_YELLOW,
2666     EL_EMERALD_RED,
2667     EL_EMERALD_PURPLE,
2668     EL_DIAMOND,
2669     -1
2670   };
2671
2672   static int ep_switchable[] =
2673   {
2674     EL_ROBOT_WHEEL,
2675     EL_SP_TERMINAL,
2676     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2677     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2678     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2679     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2680     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2681     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2682     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2683     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2684     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2685     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2686     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2687     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2688     EL_SWITCHGATE_SWITCH_UP,
2689     EL_SWITCHGATE_SWITCH_DOWN,
2690     EL_LIGHT_SWITCH,
2691     EL_LIGHT_SWITCH_ACTIVE,
2692     EL_TIMEGATE_SWITCH,
2693     EL_BALLOON_SWITCH_LEFT,
2694     EL_BALLOON_SWITCH_RIGHT,
2695     EL_BALLOON_SWITCH_UP,
2696     EL_BALLOON_SWITCH_DOWN,
2697     EL_BALLOON_SWITCH_ANY,
2698     EL_LAMP,
2699     EL_TIME_ORB_FULL,
2700     EL_EMC_MAGIC_BALL_SWITCH,
2701     -1
2702   };
2703
2704   static int ep_bd_element[] =
2705   {
2706     EL_EMPTY,
2707     EL_SAND,
2708     EL_WALL_SLIPPERY,
2709     EL_BD_WALL,
2710     EL_ROCK,
2711     EL_BD_ROCK,
2712     EL_BD_DIAMOND,
2713     EL_BD_MAGIC_WALL,
2714     EL_EXIT_CLOSED,
2715     EL_EXIT_OPEN,
2716     EL_STEELWALL,
2717     EL_PLAYER_1,
2718     EL_PLAYER_2,
2719     EL_PLAYER_3,
2720     EL_PLAYER_4,
2721     EL_BD_FIREFLY,
2722     EL_BD_FIREFLY_1,
2723     EL_BD_FIREFLY_2,
2724     EL_BD_FIREFLY_3,
2725     EL_BD_FIREFLY_4,
2726     EL_BD_BUTTERFLY,
2727     EL_BD_BUTTERFLY_1,
2728     EL_BD_BUTTERFLY_2,
2729     EL_BD_BUTTERFLY_3,
2730     EL_BD_BUTTERFLY_4,
2731     EL_BD_AMOEBA,
2732     EL_CHAR_QUESTION,
2733     EL_UNKNOWN,
2734     -1
2735   };
2736
2737   static int ep_sp_element[] =
2738   {
2739     /* should always be valid */
2740     EL_EMPTY,
2741
2742     /* standard classic Supaplex elements */
2743     EL_SP_EMPTY,
2744     EL_SP_ZONK,
2745     EL_SP_BASE,
2746     EL_SP_MURPHY,
2747     EL_SP_INFOTRON,
2748     EL_SP_CHIP_SINGLE,
2749     EL_SP_HARDWARE_GRAY,
2750     EL_SP_EXIT_CLOSED,
2751     EL_SP_EXIT_OPEN,
2752     EL_SP_DISK_ORANGE,
2753     EL_SP_PORT_RIGHT,
2754     EL_SP_PORT_DOWN,
2755     EL_SP_PORT_LEFT,
2756     EL_SP_PORT_UP,
2757     EL_SP_GRAVITY_PORT_RIGHT,
2758     EL_SP_GRAVITY_PORT_DOWN,
2759     EL_SP_GRAVITY_PORT_LEFT,
2760     EL_SP_GRAVITY_PORT_UP,
2761     EL_SP_SNIKSNAK,
2762     EL_SP_DISK_YELLOW,
2763     EL_SP_TERMINAL,
2764     EL_SP_DISK_RED,
2765     EL_SP_PORT_VERTICAL,
2766     EL_SP_PORT_HORIZONTAL,
2767     EL_SP_PORT_ANY,
2768     EL_SP_ELECTRON,
2769     EL_SP_BUGGY_BASE,
2770     EL_SP_CHIP_LEFT,
2771     EL_SP_CHIP_RIGHT,
2772     EL_SP_HARDWARE_BASE_1,
2773     EL_SP_HARDWARE_GREEN,
2774     EL_SP_HARDWARE_BLUE,
2775     EL_SP_HARDWARE_RED,
2776     EL_SP_HARDWARE_YELLOW,
2777     EL_SP_HARDWARE_BASE_2,
2778     EL_SP_HARDWARE_BASE_3,
2779     EL_SP_HARDWARE_BASE_4,
2780     EL_SP_HARDWARE_BASE_5,
2781     EL_SP_HARDWARE_BASE_6,
2782     EL_SP_CHIP_TOP,
2783     EL_SP_CHIP_BOTTOM,
2784
2785     /* additional elements that appeared in newer Supaplex levels */
2786     EL_INVISIBLE_WALL,
2787
2788     /* additional gravity port elements (not switching, but setting gravity) */
2789     EL_SP_GRAVITY_ON_PORT_LEFT,
2790     EL_SP_GRAVITY_ON_PORT_RIGHT,
2791     EL_SP_GRAVITY_ON_PORT_UP,
2792     EL_SP_GRAVITY_ON_PORT_DOWN,
2793     EL_SP_GRAVITY_OFF_PORT_LEFT,
2794     EL_SP_GRAVITY_OFF_PORT_RIGHT,
2795     EL_SP_GRAVITY_OFF_PORT_UP,
2796     EL_SP_GRAVITY_OFF_PORT_DOWN,
2797
2798     /* more than one Murphy in a level results in an inactive clone */
2799     EL_SP_MURPHY_CLONE,
2800
2801     /* runtime Supaplex elements */
2802     EL_SP_DISK_RED_ACTIVE,
2803     EL_SP_TERMINAL_ACTIVE,
2804     EL_SP_BUGGY_BASE_ACTIVATING,
2805     EL_SP_BUGGY_BASE_ACTIVE,
2806     EL_SP_EXIT_OPENING,
2807     EL_SP_EXIT_CLOSING,
2808     -1
2809   };
2810
2811   static int ep_sb_element[] =
2812   {
2813     EL_EMPTY,
2814     EL_STEELWALL,
2815     EL_SOKOBAN_OBJECT,
2816     EL_SOKOBAN_FIELD_EMPTY,
2817     EL_SOKOBAN_FIELD_FULL,
2818     EL_SOKOBAN_FIELD_PLAYER,
2819     EL_PLAYER_1,
2820     EL_PLAYER_2,
2821     EL_PLAYER_3,
2822     EL_PLAYER_4,
2823     EL_INVISIBLE_STEELWALL,
2824     -1
2825   };
2826
2827   static int ep_gem[] =
2828   {
2829     EL_BD_DIAMOND,
2830     EL_EMERALD,
2831     EL_EMERALD_YELLOW,
2832     EL_EMERALD_RED,
2833     EL_EMERALD_PURPLE,
2834     EL_DIAMOND,
2835     -1
2836   };
2837
2838   static int ep_food_dark_yamyam[] =
2839   {
2840     EL_SAND,
2841     EL_BUG,
2842     EL_SPACESHIP,
2843     EL_BD_BUTTERFLY,
2844     EL_BD_FIREFLY,
2845     EL_YAMYAM,
2846     EL_ROBOT,
2847     EL_PACMAN,
2848     EL_AMOEBA_DROP,
2849     EL_AMOEBA_DEAD,
2850     EL_AMOEBA_WET,
2851     EL_AMOEBA_DRY,
2852     EL_AMOEBA_FULL,
2853     EL_BD_AMOEBA,
2854     EL_EMERALD,
2855     EL_BD_DIAMOND,
2856     EL_EMERALD_YELLOW,
2857     EL_EMERALD_RED,
2858     EL_EMERALD_PURPLE,
2859     EL_DIAMOND,
2860     EL_PEARL,
2861     EL_CRYSTAL,
2862     -1
2863   };
2864
2865   static int ep_food_penguin[] =
2866   {
2867     EL_EMERALD,
2868     EL_BD_DIAMOND,
2869     EL_EMERALD_YELLOW,
2870     EL_EMERALD_RED,
2871     EL_EMERALD_PURPLE,
2872     EL_DIAMOND,
2873     EL_PEARL,
2874     EL_CRYSTAL,
2875     -1
2876   };
2877
2878   static int ep_food_pig[] =
2879   {
2880     EL_EMERALD,
2881     EL_BD_DIAMOND,
2882     EL_EMERALD_YELLOW,
2883     EL_EMERALD_RED,
2884     EL_EMERALD_PURPLE,
2885     EL_DIAMOND,
2886     -1
2887   };
2888
2889   static int ep_historic_wall[] =
2890   {
2891     EL_STEELWALL,
2892     EL_GATE_1,
2893     EL_GATE_2,
2894     EL_GATE_3,
2895     EL_GATE_4,
2896     EL_GATE_1_GRAY,
2897     EL_GATE_2_GRAY,
2898     EL_GATE_3_GRAY,
2899     EL_GATE_4_GRAY,
2900     EL_EM_GATE_1,
2901     EL_EM_GATE_2,
2902     EL_EM_GATE_3,
2903     EL_EM_GATE_4,
2904     EL_EM_GATE_1_GRAY,
2905     EL_EM_GATE_2_GRAY,
2906     EL_EM_GATE_3_GRAY,
2907     EL_EM_GATE_4_GRAY,
2908     EL_EXIT_CLOSED,
2909     EL_EXIT_OPENING,
2910     EL_EXIT_OPEN,
2911     EL_WALL,
2912     EL_WALL_SLIPPERY,
2913     EL_EXPANDABLE_WALL,
2914     EL_EXPANDABLE_WALL_HORIZONTAL,
2915     EL_EXPANDABLE_WALL_VERTICAL,
2916     EL_EXPANDABLE_WALL_ANY,
2917     EL_EXPANDABLE_WALL_GROWING,
2918     EL_BD_WALL,
2919     EL_SP_CHIP_SINGLE,
2920     EL_SP_CHIP_LEFT,
2921     EL_SP_CHIP_RIGHT,
2922     EL_SP_CHIP_TOP,
2923     EL_SP_CHIP_BOTTOM,
2924     EL_SP_HARDWARE_GRAY,
2925     EL_SP_HARDWARE_GREEN,
2926     EL_SP_HARDWARE_BLUE,
2927     EL_SP_HARDWARE_RED,
2928     EL_SP_HARDWARE_YELLOW,
2929     EL_SP_HARDWARE_BASE_1,
2930     EL_SP_HARDWARE_BASE_2,
2931     EL_SP_HARDWARE_BASE_3,
2932     EL_SP_HARDWARE_BASE_4,
2933     EL_SP_HARDWARE_BASE_5,
2934     EL_SP_HARDWARE_BASE_6,
2935     EL_SP_TERMINAL,
2936     EL_SP_TERMINAL_ACTIVE,
2937     EL_SP_EXIT_CLOSED,
2938     EL_SP_EXIT_OPEN,
2939     EL_INVISIBLE_STEELWALL,
2940     EL_INVISIBLE_STEELWALL_ACTIVE,
2941     EL_INVISIBLE_WALL,
2942     EL_INVISIBLE_WALL_ACTIVE,
2943     EL_STEELWALL_SLIPPERY,
2944     EL_EMC_STEELWALL_1,
2945     EL_EMC_STEELWALL_2,
2946     EL_EMC_STEELWALL_3,
2947     EL_EMC_STEELWALL_4,
2948     EL_EMC_WALL_1,
2949     EL_EMC_WALL_2,
2950     EL_EMC_WALL_3,
2951     EL_EMC_WALL_4,
2952     EL_EMC_WALL_5,
2953     EL_EMC_WALL_6,
2954     EL_EMC_WALL_7,
2955     EL_EMC_WALL_8,
2956     -1
2957   };
2958
2959   static int ep_historic_solid[] =
2960   {
2961     EL_WALL,
2962     EL_EXPANDABLE_WALL,
2963     EL_EXPANDABLE_WALL_HORIZONTAL,
2964     EL_EXPANDABLE_WALL_VERTICAL,
2965     EL_EXPANDABLE_WALL_ANY,
2966     EL_BD_WALL,
2967     EL_WALL_SLIPPERY,
2968     EL_EXIT_CLOSED,
2969     EL_EXIT_OPENING,
2970     EL_EXIT_OPEN,
2971     EL_AMOEBA_DEAD,
2972     EL_AMOEBA_WET,
2973     EL_AMOEBA_DRY,
2974     EL_AMOEBA_FULL,
2975     EL_BD_AMOEBA,
2976     EL_QUICKSAND_EMPTY,
2977     EL_QUICKSAND_FULL,
2978     EL_QUICKSAND_FILLING,
2979     EL_QUICKSAND_EMPTYING,
2980     EL_MAGIC_WALL,
2981     EL_MAGIC_WALL_ACTIVE,
2982     EL_MAGIC_WALL_EMPTYING,
2983     EL_MAGIC_WALL_FILLING,
2984     EL_MAGIC_WALL_FULL,
2985     EL_MAGIC_WALL_DEAD,
2986     EL_BD_MAGIC_WALL,
2987     EL_BD_MAGIC_WALL_ACTIVE,
2988     EL_BD_MAGIC_WALL_EMPTYING,
2989     EL_BD_MAGIC_WALL_FULL,
2990     EL_BD_MAGIC_WALL_FILLING,
2991     EL_BD_MAGIC_WALL_DEAD,
2992     EL_GAME_OF_LIFE,
2993     EL_BIOMAZE,
2994     EL_SP_CHIP_SINGLE,
2995     EL_SP_CHIP_LEFT,
2996     EL_SP_CHIP_RIGHT,
2997     EL_SP_CHIP_TOP,
2998     EL_SP_CHIP_BOTTOM,
2999     EL_SP_TERMINAL,
3000     EL_SP_TERMINAL_ACTIVE,
3001     EL_SP_EXIT_CLOSED,
3002     EL_SP_EXIT_OPEN,
3003     EL_INVISIBLE_WALL,
3004     EL_INVISIBLE_WALL_ACTIVE,
3005     EL_SWITCHGATE_SWITCH_UP,
3006     EL_SWITCHGATE_SWITCH_DOWN,
3007     EL_TIMEGATE_SWITCH,
3008     EL_TIMEGATE_SWITCH_ACTIVE,
3009     EL_EMC_WALL_1,
3010     EL_EMC_WALL_2,
3011     EL_EMC_WALL_3,
3012     EL_EMC_WALL_4,
3013     EL_EMC_WALL_5,
3014     EL_EMC_WALL_6,
3015     EL_EMC_WALL_7,
3016     EL_EMC_WALL_8,
3017     EL_WALL_PEARL,
3018     EL_WALL_CRYSTAL,
3019
3020     /* the following elements are a direct copy of "indestructible" elements,
3021        except "EL_ACID", which is "indestructible", but not "solid"! */
3022 #if 0
3023     EL_ACID,
3024 #endif
3025     EL_STEELWALL,
3026     EL_ACID_POOL_TOPLEFT,
3027     EL_ACID_POOL_TOPRIGHT,
3028     EL_ACID_POOL_BOTTOMLEFT,
3029     EL_ACID_POOL_BOTTOM,
3030     EL_ACID_POOL_BOTTOMRIGHT,
3031     EL_SP_HARDWARE_GRAY,
3032     EL_SP_HARDWARE_GREEN,
3033     EL_SP_HARDWARE_BLUE,
3034     EL_SP_HARDWARE_RED,
3035     EL_SP_HARDWARE_YELLOW,
3036     EL_SP_HARDWARE_BASE_1,
3037     EL_SP_HARDWARE_BASE_2,
3038     EL_SP_HARDWARE_BASE_3,
3039     EL_SP_HARDWARE_BASE_4,
3040     EL_SP_HARDWARE_BASE_5,
3041     EL_SP_HARDWARE_BASE_6,
3042     EL_INVISIBLE_STEELWALL,
3043     EL_INVISIBLE_STEELWALL_ACTIVE,
3044     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3045     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3046     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3047     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3048     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3049     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3050     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3051     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3052     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3053     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3054     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3055     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3056     EL_LIGHT_SWITCH,
3057     EL_LIGHT_SWITCH_ACTIVE,
3058     EL_SIGN_EXCLAMATION,
3059     EL_SIGN_RADIOACTIVITY,
3060     EL_SIGN_STOP,
3061     EL_SIGN_WHEELCHAIR,
3062     EL_SIGN_PARKING,
3063     EL_SIGN_ONEWAY,
3064     EL_SIGN_HEART,
3065     EL_SIGN_TRIANGLE,
3066     EL_SIGN_ROUND,
3067     EL_SIGN_EXIT,
3068     EL_SIGN_YINYANG,
3069     EL_SIGN_OTHER,
3070     EL_STEELWALL_SLIPPERY,
3071     EL_EMC_STEELWALL_1,
3072     EL_EMC_STEELWALL_2,
3073     EL_EMC_STEELWALL_3,
3074     EL_EMC_STEELWALL_4,
3075     EL_CRYSTAL,
3076     EL_GATE_1,
3077     EL_GATE_2,
3078     EL_GATE_3,
3079     EL_GATE_4,
3080     EL_GATE_1_GRAY,
3081     EL_GATE_2_GRAY,
3082     EL_GATE_3_GRAY,
3083     EL_GATE_4_GRAY,
3084     EL_EM_GATE_1,
3085     EL_EM_GATE_2,
3086     EL_EM_GATE_3,
3087     EL_EM_GATE_4,
3088     EL_EM_GATE_1_GRAY,
3089     EL_EM_GATE_2_GRAY,
3090     EL_EM_GATE_3_GRAY,
3091     EL_EM_GATE_4_GRAY,
3092     EL_SWITCHGATE_OPEN,
3093     EL_SWITCHGATE_OPENING,
3094     EL_SWITCHGATE_CLOSED,
3095     EL_SWITCHGATE_CLOSING,
3096     EL_TIMEGATE_OPEN,
3097     EL_TIMEGATE_OPENING,
3098     EL_TIMEGATE_CLOSED,
3099     EL_TIMEGATE_CLOSING,
3100     EL_TUBE_ANY,
3101     EL_TUBE_VERTICAL,
3102     EL_TUBE_HORIZONTAL,
3103     EL_TUBE_VERTICAL_LEFT,
3104     EL_TUBE_VERTICAL_RIGHT,
3105     EL_TUBE_HORIZONTAL_UP,
3106     EL_TUBE_HORIZONTAL_DOWN,
3107     EL_TUBE_LEFT_UP,
3108     EL_TUBE_LEFT_DOWN,
3109     EL_TUBE_RIGHT_UP,
3110     EL_TUBE_RIGHT_DOWN,
3111     -1
3112   };
3113
3114   static int ep_classic_enemy[] =
3115   {
3116     EL_BUG,
3117     EL_SPACESHIP,
3118     EL_BD_BUTTERFLY,
3119     EL_BD_FIREFLY,
3120
3121     EL_YAMYAM,
3122     EL_DARK_YAMYAM,
3123     EL_ROBOT,
3124     EL_PACMAN,
3125     EL_SP_SNIKSNAK,
3126     EL_SP_ELECTRON,
3127     -1
3128   };
3129
3130   static int ep_belt[] =
3131   {
3132     EL_CONVEYOR_BELT_1_LEFT,
3133     EL_CONVEYOR_BELT_1_MIDDLE,
3134     EL_CONVEYOR_BELT_1_RIGHT,
3135     EL_CONVEYOR_BELT_2_LEFT,
3136     EL_CONVEYOR_BELT_2_MIDDLE,
3137     EL_CONVEYOR_BELT_2_RIGHT,
3138     EL_CONVEYOR_BELT_3_LEFT,
3139     EL_CONVEYOR_BELT_3_MIDDLE,
3140     EL_CONVEYOR_BELT_3_RIGHT,
3141     EL_CONVEYOR_BELT_4_LEFT,
3142     EL_CONVEYOR_BELT_4_MIDDLE,
3143     EL_CONVEYOR_BELT_4_RIGHT,
3144     -1
3145   };
3146
3147   static int ep_belt_active[] =
3148   {
3149     EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
3150     EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE,
3151     EL_CONVEYOR_BELT_1_RIGHT_ACTIVE,
3152     EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
3153     EL_CONVEYOR_BELT_2_MIDDLE_ACTIVE,
3154     EL_CONVEYOR_BELT_2_RIGHT_ACTIVE,
3155     EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
3156     EL_CONVEYOR_BELT_3_MIDDLE_ACTIVE,
3157     EL_CONVEYOR_BELT_3_RIGHT_ACTIVE,
3158     EL_CONVEYOR_BELT_4_LEFT_ACTIVE,
3159     EL_CONVEYOR_BELT_4_MIDDLE_ACTIVE,
3160     EL_CONVEYOR_BELT_4_RIGHT_ACTIVE,
3161     -1
3162   };
3163
3164   static int ep_belt_switch[] =
3165   {
3166     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3167     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3168     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3169     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3170     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3171     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3172     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3173     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3174     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3175     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3176     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3177     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3178     -1
3179   };
3180
3181   static int ep_tube[] =
3182   {
3183     EL_TUBE_LEFT_UP,
3184     EL_TUBE_LEFT_DOWN,
3185     EL_TUBE_RIGHT_UP,
3186     EL_TUBE_RIGHT_DOWN,
3187     EL_TUBE_HORIZONTAL,
3188     EL_TUBE_HORIZONTAL_UP,
3189     EL_TUBE_HORIZONTAL_DOWN,
3190     EL_TUBE_VERTICAL,
3191     EL_TUBE_VERTICAL_LEFT,
3192     EL_TUBE_VERTICAL_RIGHT,
3193     EL_TUBE_ANY,
3194     -1
3195   };
3196
3197   static int ep_keygate[] =
3198   {
3199     EL_GATE_1,
3200     EL_GATE_2,
3201     EL_GATE_3,
3202     EL_GATE_4,
3203     EL_GATE_1_GRAY,
3204     EL_GATE_2_GRAY,
3205     EL_GATE_3_GRAY,
3206     EL_GATE_4_GRAY,
3207     EL_EM_GATE_1,
3208     EL_EM_GATE_2,
3209     EL_EM_GATE_3,
3210     EL_EM_GATE_4,
3211     EL_EM_GATE_5,
3212     EL_EM_GATE_6,
3213     EL_EM_GATE_7,
3214     EL_EM_GATE_8,
3215     EL_EM_GATE_1_GRAY,
3216     EL_EM_GATE_2_GRAY,
3217     EL_EM_GATE_3_GRAY,
3218     EL_EM_GATE_4_GRAY,
3219     EL_EM_GATE_5_GRAY,
3220     EL_EM_GATE_6_GRAY,
3221     EL_EM_GATE_7_GRAY,
3222     EL_EM_GATE_8_GRAY,
3223     -1
3224   };
3225
3226   static int ep_amoeboid[] =
3227   {
3228     EL_AMOEBA_DEAD,
3229     EL_AMOEBA_WET,
3230     EL_AMOEBA_DRY,
3231     EL_AMOEBA_FULL,
3232     EL_BD_AMOEBA,
3233     -1
3234   };
3235
3236   static int ep_amoebalive[] =
3237   {
3238     EL_AMOEBA_WET,
3239     EL_AMOEBA_DRY,
3240     EL_AMOEBA_FULL,
3241     EL_BD_AMOEBA,
3242     -1
3243   };
3244
3245   static int ep_has_content[] =
3246   {
3247     EL_YAMYAM,
3248     EL_AMOEBA_WET,
3249     EL_AMOEBA_DRY,
3250     EL_AMOEBA_FULL,
3251     EL_BD_AMOEBA,
3252     -1
3253   };
3254
3255   static int ep_can_turn_each_move[] =
3256   {
3257     /* !!! do something with this one !!! */
3258     -1
3259   };
3260
3261   static int ep_can_grow[] =
3262   {
3263     EL_BD_AMOEBA,
3264     EL_AMOEBA_DROP,
3265     EL_AMOEBA_WET,
3266     EL_AMOEBA_DRY,
3267     EL_AMOEBA_FULL,
3268     EL_GAME_OF_LIFE,
3269     EL_BIOMAZE,
3270     -1
3271   };
3272
3273   static int ep_active_bomb[] =
3274   {
3275     EL_DYNAMITE_ACTIVE,
3276     EL_DYNABOMB_PLAYER_1_ACTIVE,
3277     EL_DYNABOMB_PLAYER_2_ACTIVE,
3278     EL_DYNABOMB_PLAYER_3_ACTIVE,
3279     EL_DYNABOMB_PLAYER_4_ACTIVE,
3280     EL_SP_DISK_RED_ACTIVE,
3281     -1
3282   };
3283
3284   static int ep_inactive[] =
3285   {
3286     EL_EMPTY,
3287     EL_SAND,
3288     EL_WALL,
3289     EL_BD_WALL,
3290     EL_WALL_SLIPPERY,
3291     EL_STEELWALL,
3292     EL_AMOEBA_DEAD,
3293     EL_QUICKSAND_EMPTY,
3294     EL_STONEBLOCK,
3295     EL_ROBOT_WHEEL,
3296     EL_KEY_1,
3297     EL_KEY_2,
3298     EL_KEY_3,
3299     EL_KEY_4,
3300     EL_EM_KEY_1,
3301     EL_EM_KEY_2,
3302     EL_EM_KEY_3,
3303     EL_EM_KEY_4,
3304     EL_EM_KEY_5,
3305     EL_EM_KEY_6,
3306     EL_EM_KEY_7,
3307     EL_EM_KEY_8,
3308     EL_GATE_1,
3309     EL_GATE_2,
3310     EL_GATE_3,
3311     EL_GATE_4,
3312     EL_GATE_1_GRAY,
3313     EL_GATE_2_GRAY,
3314     EL_GATE_3_GRAY,
3315     EL_GATE_4_GRAY,
3316     EL_EM_GATE_1,
3317     EL_EM_GATE_2,
3318     EL_EM_GATE_3,
3319     EL_EM_GATE_4,
3320     EL_EM_GATE_5,
3321     EL_EM_GATE_6,
3322     EL_EM_GATE_7,
3323     EL_EM_GATE_8,
3324     EL_EM_GATE_1_GRAY,
3325     EL_EM_GATE_2_GRAY,
3326     EL_EM_GATE_3_GRAY,
3327     EL_EM_GATE_4_GRAY,
3328     EL_EM_GATE_5_GRAY,
3329     EL_EM_GATE_6_GRAY,
3330     EL_EM_GATE_7_GRAY,
3331     EL_EM_GATE_8_GRAY,
3332     EL_DYNAMITE,
3333     EL_INVISIBLE_STEELWALL,
3334     EL_INVISIBLE_WALL,
3335     EL_INVISIBLE_SAND,
3336     EL_LAMP,
3337     EL_LAMP_ACTIVE,
3338     EL_WALL_EMERALD,
3339     EL_WALL_DIAMOND,
3340     EL_WALL_BD_DIAMOND,
3341     EL_WALL_EMERALD_YELLOW,
3342     EL_DYNABOMB_INCREASE_NUMBER,
3343     EL_DYNABOMB_INCREASE_SIZE,
3344     EL_DYNABOMB_INCREASE_POWER,
3345 #if 0
3346     EL_SOKOBAN_OBJECT,
3347 #endif
3348     EL_SOKOBAN_FIELD_EMPTY,
3349     EL_SOKOBAN_FIELD_FULL,
3350     EL_WALL_EMERALD_RED,
3351     EL_WALL_EMERALD_PURPLE,
3352     EL_ACID_POOL_TOPLEFT,
3353     EL_ACID_POOL_TOPRIGHT,
3354     EL_ACID_POOL_BOTTOMLEFT,
3355     EL_ACID_POOL_BOTTOM,
3356     EL_ACID_POOL_BOTTOMRIGHT,
3357     EL_MAGIC_WALL,
3358     EL_MAGIC_WALL_DEAD,
3359     EL_BD_MAGIC_WALL,
3360     EL_BD_MAGIC_WALL_DEAD,
3361     EL_AMOEBA_TO_DIAMOND,
3362     EL_BLOCKED,
3363     EL_SP_EMPTY,
3364     EL_SP_BASE,
3365     EL_SP_PORT_RIGHT,
3366     EL_SP_PORT_DOWN,
3367     EL_SP_PORT_LEFT,
3368     EL_SP_PORT_UP,
3369     EL_SP_GRAVITY_PORT_RIGHT,
3370     EL_SP_GRAVITY_PORT_DOWN,
3371     EL_SP_GRAVITY_PORT_LEFT,
3372     EL_SP_GRAVITY_PORT_UP,
3373     EL_SP_PORT_HORIZONTAL,
3374     EL_SP_PORT_VERTICAL,
3375     EL_SP_PORT_ANY,
3376     EL_SP_DISK_RED,
3377 #if 0
3378     EL_SP_DISK_YELLOW,
3379 #endif
3380     EL_SP_CHIP_SINGLE,
3381     EL_SP_CHIP_LEFT,
3382     EL_SP_CHIP_RIGHT,
3383     EL_SP_CHIP_TOP,
3384     EL_SP_CHIP_BOTTOM,
3385     EL_SP_HARDWARE_GRAY,
3386     EL_SP_HARDWARE_GREEN,
3387     EL_SP_HARDWARE_BLUE,
3388     EL_SP_HARDWARE_RED,
3389     EL_SP_HARDWARE_YELLOW,
3390     EL_SP_HARDWARE_BASE_1,
3391     EL_SP_HARDWARE_BASE_2,
3392     EL_SP_HARDWARE_BASE_3,
3393     EL_SP_HARDWARE_BASE_4,
3394     EL_SP_HARDWARE_BASE_5,
3395     EL_SP_HARDWARE_BASE_6,
3396     EL_SP_GRAVITY_ON_PORT_LEFT,
3397     EL_SP_GRAVITY_ON_PORT_RIGHT,
3398     EL_SP_GRAVITY_ON_PORT_UP,
3399     EL_SP_GRAVITY_ON_PORT_DOWN,
3400     EL_SP_GRAVITY_OFF_PORT_LEFT,
3401     EL_SP_GRAVITY_OFF_PORT_RIGHT,
3402     EL_SP_GRAVITY_OFF_PORT_UP,
3403     EL_SP_GRAVITY_OFF_PORT_DOWN,
3404     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
3405     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
3406     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
3407     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
3408     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
3409     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
3410     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
3411     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
3412     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
3413     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
3414     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
3415     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
3416     EL_SIGN_EXCLAMATION,
3417     EL_SIGN_RADIOACTIVITY,
3418     EL_SIGN_STOP,
3419     EL_SIGN_WHEELCHAIR,
3420     EL_SIGN_PARKING,
3421     EL_SIGN_ONEWAY,
3422     EL_SIGN_HEART,
3423     EL_SIGN_TRIANGLE,
3424     EL_SIGN_ROUND,
3425     EL_SIGN_EXIT,
3426     EL_SIGN_YINYANG,
3427     EL_SIGN_OTHER,
3428     EL_STEELWALL_SLIPPERY,
3429     EL_EMC_STEELWALL_1,
3430     EL_EMC_STEELWALL_2,
3431     EL_EMC_STEELWALL_3,
3432     EL_EMC_STEELWALL_4,
3433     EL_EMC_WALL_SLIPPERY_1,
3434     EL_EMC_WALL_SLIPPERY_2,
3435     EL_EMC_WALL_SLIPPERY_3,
3436     EL_EMC_WALL_SLIPPERY_4,
3437     EL_EMC_WALL_1,
3438     EL_EMC_WALL_2,
3439     EL_EMC_WALL_3,
3440     EL_EMC_WALL_4,
3441     EL_EMC_WALL_5,
3442     EL_EMC_WALL_6,
3443     EL_EMC_WALL_7,
3444     EL_EMC_WALL_8,
3445     EL_EMC_WALL_9,
3446     EL_EMC_WALL_10,
3447     EL_EMC_WALL_11,
3448     EL_EMC_WALL_12,
3449     EL_EMC_WALL_13,
3450     EL_EMC_WALL_14,
3451     EL_EMC_WALL_15,
3452     EL_EMC_WALL_16,
3453     -1
3454   };
3455
3456   static int ep_em_slippery_wall[] =
3457   {
3458     -1
3459   };
3460
3461   static int ep_gfx_crumbled[] =
3462   {
3463     EL_SAND,
3464     EL_LANDMINE,
3465     EL_TRAP,
3466     EL_TRAP_ACTIVE,
3467     -1
3468   };
3469
3470   static struct
3471   {
3472     int *elements;
3473     int property;
3474   } element_properties[] =
3475   {
3476     { ep_diggable,              EP_DIGGABLE             },
3477     { ep_collectible_only,      EP_COLLECTIBLE_ONLY     },
3478     { ep_dont_run_into,         EP_DONT_RUN_INTO        },
3479     { ep_dont_collide_with,     EP_DONT_COLLIDE_WITH    },
3480     { ep_dont_touch,            EP_DONT_TOUCH           },
3481     { ep_indestructible,        EP_INDESTRUCTIBLE       },
3482     { ep_slippery,              EP_SLIPPERY             },
3483     { ep_can_change,            EP_CAN_CHANGE           },
3484     { ep_can_move,              EP_CAN_MOVE             },
3485     { ep_can_fall,              EP_CAN_FALL             },
3486     { ep_can_smash_player,      EP_CAN_SMASH_PLAYER     },
3487     { ep_can_smash_enemies,     EP_CAN_SMASH_ENEMIES    },
3488     { ep_can_smash_everything,  EP_CAN_SMASH_EVERYTHING },
3489     { ep_explodes_by_fire,      EP_EXPLODES_BY_FIRE     },
3490     { ep_explodes_smashed,      EP_EXPLODES_SMASHED     },
3491     { ep_explodes_impact,       EP_EXPLODES_IMPACT      },
3492     { ep_walkable_over,         EP_WALKABLE_OVER        },
3493     { ep_walkable_inside,       EP_WALKABLE_INSIDE      },
3494     { ep_walkable_under,        EP_WALKABLE_UNDER       },
3495     { ep_passable_over,         EP_PASSABLE_OVER        },
3496     { ep_passable_inside,       EP_PASSABLE_INSIDE      },
3497     { ep_passable_under,        EP_PASSABLE_UNDER       },
3498     { ep_droppable,             EP_DROPPABLE            },
3499     { ep_explodes_1x1_old,      EP_EXPLODES_1X1_OLD     },
3500     { ep_pushable,              EP_PUSHABLE             },
3501     { ep_explodes_cross_old,    EP_EXPLODES_CROSS_OLD   },
3502     { ep_protected,             EP_PROTECTED            },
3503     { ep_throwable,             EP_THROWABLE            },
3504     { ep_can_explode,           EP_CAN_EXPLODE          },
3505     { ep_gravity_reachable,     EP_GRAVITY_REACHABLE    },
3506
3507     { ep_player,                EP_PLAYER               },
3508     { ep_can_pass_magic_wall,   EP_CAN_PASS_MAGIC_WALL  },
3509     { ep_switchable,            EP_SWITCHABLE           },
3510     { ep_bd_element,            EP_BD_ELEMENT           },
3511     { ep_sp_element,            EP_SP_ELEMENT           },
3512     { ep_sb_element,            EP_SB_ELEMENT           },
3513     { ep_gem,                   EP_GEM                  },
3514     { ep_food_dark_yamyam,      EP_FOOD_DARK_YAMYAM     },
3515     { ep_food_penguin,          EP_FOOD_PENGUIN         },
3516     { ep_food_pig,              EP_FOOD_PIG             },
3517     { ep_historic_wall,         EP_HISTORIC_WALL        },
3518     { ep_historic_solid,        EP_HISTORIC_SOLID       },
3519     { ep_classic_enemy,         EP_CLASSIC_ENEMY        },
3520     { ep_belt,                  EP_BELT                 },
3521     { ep_belt_active,           EP_BELT_ACTIVE          },
3522     { ep_belt_switch,           EP_BELT_SWITCH          },
3523     { ep_tube,                  EP_TUBE                 },
3524     { ep_keygate,               EP_KEYGATE              },
3525     { ep_amoeboid,              EP_AMOEBOID             },
3526     { ep_amoebalive,            EP_AMOEBALIVE           },
3527     { ep_has_content,           EP_HAS_CONTENT          },
3528     { ep_can_turn_each_move,    EP_CAN_TURN_EACH_MOVE   },
3529     { ep_can_grow,              EP_CAN_GROW             },
3530     { ep_active_bomb,           EP_ACTIVE_BOMB          },
3531     { ep_inactive,              EP_INACTIVE             },
3532
3533     { ep_em_slippery_wall,      EP_EM_SLIPPERY_WALL     },
3534
3535     { ep_gfx_crumbled,          EP_GFX_CRUMBLED         },
3536
3537     { NULL,                     -1                      }
3538   };
3539
3540   static int copy_properties[][5] =
3541   {
3542     {
3543       EL_BUG,
3544       EL_BUG_LEFT,              EL_BUG_RIGHT,
3545       EL_BUG_UP,                EL_BUG_DOWN
3546     },
3547     {
3548       EL_SPACESHIP,
3549       EL_SPACESHIP_LEFT,        EL_SPACESHIP_RIGHT,
3550       EL_SPACESHIP_UP,          EL_SPACESHIP_DOWN
3551     },
3552     {
3553       EL_BD_BUTTERFLY,
3554       EL_BD_BUTTERFLY_LEFT,     EL_BD_BUTTERFLY_RIGHT,
3555       EL_BD_BUTTERFLY_UP,       EL_BD_BUTTERFLY_DOWN
3556     },
3557     {
3558       EL_BD_FIREFLY,
3559       EL_BD_FIREFLY_LEFT,       EL_BD_FIREFLY_RIGHT,
3560       EL_BD_FIREFLY_UP,         EL_BD_FIREFLY_DOWN
3561     },
3562     {
3563       EL_PACMAN,
3564       EL_PACMAN_LEFT,           EL_PACMAN_RIGHT,
3565       EL_PACMAN_UP,             EL_PACMAN_DOWN
3566     },
3567     {
3568       EL_MOLE,
3569       EL_MOLE_LEFT,             EL_MOLE_RIGHT,
3570       EL_MOLE_UP,               EL_MOLE_DOWN
3571     },
3572     {
3573       -1,
3574       -1, -1, -1, -1
3575     }
3576   };
3577
3578   int i, j, k;
3579
3580   /* always start with reliable default values (element has no properties) */
3581   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3582     for (j = 0; j < NUM_ELEMENT_PROPERTIES; j++)
3583       SET_PROPERTY(i, j, FALSE);
3584
3585   /* set all base element properties from above array definitions */
3586   for (i = 0; element_properties[i].elements != NULL; i++)
3587     for (j = 0; (element_properties[i].elements)[j] != -1; j++)
3588       SET_PROPERTY((element_properties[i].elements)[j],
3589                    element_properties[i].property, TRUE);
3590
3591   /* copy properties to some elements that are only stored in level file */
3592   for (i = 0; i < NUM_ELEMENT_PROPERTIES; i++)
3593     for (j = 0; copy_properties[j][0] != -1; j++)
3594       if (HAS_PROPERTY(copy_properties[j][0], i))
3595         for (k = 1; k <= 4; k++)
3596           SET_PROPERTY(copy_properties[j][k], i, TRUE);
3597 }
3598
3599 void InitElementPropertiesEngine(int engine_version)
3600 {
3601 #if 0
3602   static int active_properties[] =
3603   {
3604     EP_AMOEBALIVE,
3605     EP_AMOEBOID,
3606     EP_PFORTE,
3607     EP_DONT_COLLIDE_WITH,
3608     EP_MAUER,
3609     EP_CAN_FALL,
3610     EP_CAN_SMASH,
3611     EP_CAN_PASS_MAGIC_WALL,
3612     EP_CAN_MOVE,
3613     EP_DONT_TOUCH,
3614     EP_DONT_RUN_INTO,
3615     EP_GEM,
3616     EP_EXPLODES_BY_FIRE,
3617     EP_PUSHABLE,
3618     EP_PLAYER,
3619     EP_HAS_CONTENT,
3620     EP_DIGGABLE,
3621     EP_PASSABLE_INSIDE,
3622     EP_OVER_PLAYER,
3623     EP_ACTIVE_BOMB,
3624
3625     EP_BELT,
3626     EP_BELT_ACTIVE,
3627     EP_BELT_SWITCH,
3628     EP_WALKABLE_UNDER,
3629     EP_EM_SLIPPERY_WALL,
3630   };
3631 #endif
3632
3633   static int no_wall_properties[] =
3634   {
3635     EP_DIGGABLE,
3636     EP_COLLECTIBLE_ONLY,
3637     EP_DONT_RUN_INTO,
3638     EP_DONT_COLLIDE_WITH,
3639     EP_CAN_MOVE,
3640     EP_CAN_FALL,
3641     EP_CAN_SMASH_PLAYER,
3642     EP_CAN_SMASH_ENEMIES,
3643     EP_CAN_SMASH_EVERYTHING,
3644     EP_PUSHABLE,
3645
3646     EP_PLAYER,
3647     EP_GEM,
3648     EP_FOOD_DARK_YAMYAM,
3649     EP_FOOD_PENGUIN,
3650     EP_BELT,
3651     EP_BELT_ACTIVE,
3652     EP_TUBE,
3653     EP_AMOEBOID,
3654     EP_AMOEBALIVE,
3655     EP_ACTIVE_BOMB,
3656
3657     EP_ACCESSIBLE,
3658
3659     -1
3660   };
3661
3662   int i, j;
3663
3664 #if 0
3665   InitElementPropertiesStatic();
3666 #endif
3667
3668   /* important: after initialization in InitElementPropertiesStatic(), the
3669      elements are not again initialized to a default value; therefore all
3670      changes have to make sure that they leave the element with a defined
3671      property (which means that conditional property changes must be set to
3672      a reliable default value before) */
3673
3674   /* set all special, combined or engine dependent element properties */
3675   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3676   {
3677 #if 0
3678     for (j = EP_ACCESSIBLE_OVER; j < NUM_ELEMENT_PROPERTIES; j++)
3679       SET_PROPERTY(i, j, FALSE);
3680 #endif
3681
3682     /* ---------- INACTIVE ------------------------------------------------- */
3683     SET_PROPERTY(i, EP_INACTIVE, (i >= EL_CHAR_START && i <= EL_CHAR_END));
3684
3685     /* ---------- WALKABLE, PASSABLE, ACCESSIBLE --------------------------- */
3686     SET_PROPERTY(i, EP_WALKABLE, (IS_WALKABLE_OVER(i) ||
3687                                   IS_WALKABLE_INSIDE(i) ||
3688                                   IS_WALKABLE_UNDER(i)));
3689
3690     SET_PROPERTY(i, EP_PASSABLE, (IS_PASSABLE_OVER(i) ||
3691                                   IS_PASSABLE_INSIDE(i) ||
3692                                   IS_PASSABLE_UNDER(i)));
3693
3694     SET_PROPERTY(i, EP_ACCESSIBLE_OVER, (IS_WALKABLE_OVER(i) ||
3695                                          IS_PASSABLE_OVER(i)));
3696
3697     SET_PROPERTY(i, EP_ACCESSIBLE_INSIDE, (IS_WALKABLE_INSIDE(i) ||
3698                                            IS_PASSABLE_INSIDE(i)));
3699
3700     SET_PROPERTY(i, EP_ACCESSIBLE_UNDER, (IS_WALKABLE_UNDER(i) ||
3701                                           IS_PASSABLE_UNDER(i)));
3702
3703     SET_PROPERTY(i, EP_ACCESSIBLE, (IS_WALKABLE(i) ||
3704                                     IS_PASSABLE(i)));
3705
3706     /* ---------- COLLECTIBLE ---------------------------------------------- */
3707     SET_PROPERTY(i, EP_COLLECTIBLE, (IS_COLLECTIBLE_ONLY(i) ||
3708                                      IS_DROPPABLE(i) ||
3709                                      IS_THROWABLE(i)));
3710
3711     /* ---------- SNAPPABLE ------------------------------------------------ */
3712     SET_PROPERTY(i, EP_SNAPPABLE, (IS_DIGGABLE(i) ||
3713                                    IS_COLLECTIBLE(i) ||
3714                                    IS_SWITCHABLE(i) ||
3715                                    i == EL_BD_ROCK));
3716
3717     /* ---------- WALL ----------------------------------------------------- */
3718     SET_PROPERTY(i, EP_WALL, TRUE);     /* default: element is wall */
3719
3720     for (j = 0; no_wall_properties[j] != -1; j++)
3721       if (HAS_PROPERTY(i, no_wall_properties[j]) ||
3722           i >= EL_FIRST_RUNTIME_UNREAL)
3723         SET_PROPERTY(i, EP_WALL, FALSE);
3724
3725     if (IS_HISTORIC_WALL(i))
3726       SET_PROPERTY(i, EP_WALL, TRUE);
3727
3728     /* ---------- SOLID_FOR_PUSHING ---------------------------------------- */
3729     if (engine_version < VERSION_IDENT(2,2,0,0))
3730       SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, IS_HISTORIC_SOLID(i));
3731     else
3732       SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, (!IS_WALKABLE(i) &&
3733                                              !IS_DIGGABLE(i) &&
3734                                              !IS_COLLECTIBLE(i)));
3735
3736 #if 0
3737     /* ---------- PROTECTED ------------------------------------------------ */
3738     if (IS_ACCESSIBLE_INSIDE(i))
3739       SET_PROPERTY(i, EP_PROTECTED, TRUE);
3740 #endif
3741
3742     /* ---------- DRAGONFIRE_PROOF ----------------------------------------- */
3743
3744     if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
3745       SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE);
3746     else
3747       SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_CUSTOM_ELEMENT(i) &&
3748                                             IS_INDESTRUCTIBLE(i)));
3749
3750     /* ---------- EXPLOSION_PROOF ------------------------------------------ */
3751     if (i == EL_FLAMES)
3752       SET_PROPERTY(i, EP_EXPLOSION_PROOF, TRUE);
3753     else if (engine_version < VERSION_IDENT(2,2,0,0))
3754       SET_PROPERTY(i, EP_EXPLOSION_PROOF, IS_INDESTRUCTIBLE(i));
3755     else
3756 #if 1
3757       SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
3758                                            (!IS_WALKABLE(i) ||
3759                                             IS_PROTECTED(i))));
3760 #else
3761 #if 1
3762       SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
3763                                            !IS_WALKABLE_OVER(i) &&
3764                                            !IS_WALKABLE_UNDER(i)));
3765 #else
3766       SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
3767                                            IS_PROTECTED(i)));
3768 #endif
3769 #endif
3770
3771     if (IS_CUSTOM_ELEMENT(i))
3772     {
3773       /* these are additional properties which are initially false when set */
3774
3775       /* ---------- DONT_COLLIDE_WITH / DONT_RUN_INTO ---------------------- */
3776       if (DONT_TOUCH(i))
3777         SET_PROPERTY(i, EP_DONT_COLLIDE_WITH, TRUE);
3778       if (DONT_COLLIDE_WITH(i))
3779         SET_PROPERTY(i, EP_DONT_RUN_INTO, TRUE);
3780
3781       /* ---------- CAN_SMASH_ENEMIES / CAN_SMASH_PLAYER ------------------- */
3782       if (CAN_SMASH_EVERYTHING(i))
3783         SET_PROPERTY(i, EP_CAN_SMASH_ENEMIES, TRUE);
3784       if (CAN_SMASH_ENEMIES(i))
3785         SET_PROPERTY(i, EP_CAN_SMASH_PLAYER, TRUE);
3786     }
3787
3788     /* ---------- CAN_SMASH ------------------------------------------------ */
3789     SET_PROPERTY(i, EP_CAN_SMASH, (CAN_SMASH_PLAYER(i) ||
3790                                    CAN_SMASH_ENEMIES(i) ||
3791                                    CAN_SMASH_EVERYTHING(i)));
3792
3793 #if 0
3794     /* ---------- CAN_EXPLODE ---------------------------------------------- */
3795     SET_PROPERTY(i, EP_CAN_EXPLODE, (CAN_EXPLODE_BY_FIRE(i) ||
3796                                      CAN_EXPLODE_SMASHED(i) ||
3797                                      CAN_EXPLODE_IMPACT(i)));
3798 #endif
3799
3800 #if 0
3801     /* ---------- CAN_EXPLODE_3X3 ------------------------------------------ */
3802 #if 0
3803     SET_PROPERTY(i, EP_CAN_EXPLODE_3X3, (!CAN_EXPLODE_1X1(i) &&
3804                                          !CAN_EXPLODE_CROSS(i)));
3805 #else
3806     SET_PROPERTY(i, EP_CAN_EXPLODE_3X3, (CAN_EXPLODE(i) &&
3807                                          !CAN_EXPLODE_1X1(i) &&
3808                                          !CAN_EXPLODE_CROSS(i)));
3809 #endif
3810 #endif
3811
3812     /* ---------- CAN_EXPLODE_BY_FIRE -------------------------------------- */
3813     SET_PROPERTY(i, EP_CAN_EXPLODE_BY_FIRE, (CAN_EXPLODE(i) &&
3814                                              EXPLODES_BY_FIRE(i)));
3815
3816     /* ---------- CAN_EXPLODE_SMASHED -------------------------------------- */
3817     SET_PROPERTY(i, EP_CAN_EXPLODE_SMASHED, (CAN_EXPLODE(i) &&
3818                                              EXPLODES_SMASHED(i)));
3819
3820     /* ---------- CAN_EXPLODE_IMPACT --------------------------------------- */
3821     SET_PROPERTY(i, EP_CAN_EXPLODE_IMPACT, (CAN_EXPLODE(i) &&
3822                                             EXPLODES_IMPACT(i)));
3823
3824     /* ---------- CAN_EXPLODE_BY_DRAGONFIRE -------------------------------- */
3825     SET_PROPERTY(i, EP_CAN_EXPLODE_BY_DRAGONFIRE, CAN_EXPLODE_BY_FIRE(i));
3826
3827     /* ---------- CAN_EXPLODE_BY_EXPLOSION --------------------------------- */
3828     SET_PROPERTY(i, EP_CAN_EXPLODE_BY_EXPLOSION, (CAN_EXPLODE_BY_FIRE(i) ||
3829                                                   i == EL_BLACK_ORB));
3830
3831     /* ---------- COULD_MOVE_INTO_ACID ------------------------------------- */
3832     SET_PROPERTY(i, EP_COULD_MOVE_INTO_ACID, (ELEM_IS_PLAYER(i) ||
3833                                               CAN_MOVE(i) ||
3834                                               IS_CUSTOM_ELEMENT(i)));
3835
3836     /* ---------- MAYBE_DONT_COLLIDE_WITH ---------------------------------- */
3837     SET_PROPERTY(i, EP_MAYBE_DONT_COLLIDE_WITH, (i == EL_SP_SNIKSNAK ||
3838                                                  i == EL_SP_ELECTRON));
3839
3840     /* ---------- CAN_MOVE_INTO_ACID --------------------------------------- */
3841     if (COULD_MOVE_INTO_ACID(i) && !IS_CUSTOM_ELEMENT(i))
3842       SET_PROPERTY(i, EP_CAN_MOVE_INTO_ACID,
3843                    getMoveIntoAcidProperty(&level, i));
3844
3845     /* ---------- DONT_COLLIDE_WITH ---------------------------------------- */
3846     if (MAYBE_DONT_COLLIDE_WITH(i))
3847       SET_PROPERTY(i, EP_DONT_COLLIDE_WITH,
3848                    getDontCollideWithProperty(&level, i));
3849
3850     /* ---------- SP_PORT -------------------------------------------------- */
3851     SET_PROPERTY(i, EP_SP_PORT, (IS_SP_ELEMENT(i) &&
3852                                  IS_PASSABLE_INSIDE(i)));
3853
3854     /* ---------- CAN_CHANGE ----------------------------------------------- */
3855     SET_PROPERTY(i, EP_CAN_CHANGE, FALSE);      /* default: cannot change */
3856     for (j = 0; j < element_info[i].num_change_pages; j++)
3857       if (element_info[i].change_page[j].can_change)
3858         SET_PROPERTY(i, EP_CAN_CHANGE, TRUE);
3859
3860     /* ---------- GFX_CRUMBLED --------------------------------------------- */
3861 #if 1
3862     SET_PROPERTY(i, EP_GFX_CRUMBLED,
3863                  element_info[i].crumbled[ACTION_DEFAULT] !=
3864                  element_info[i].graphic[ACTION_DEFAULT]);
3865 #else
3866     /* !!! THIS LOOKS CRAPPY FOR SAND ETC. WITHOUT CRUMBLED GRAPHICS !!! */
3867     SET_PROPERTY(i, EP_GFX_CRUMBLED,
3868                  element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
3869 #endif
3870   }
3871
3872 #if 0
3873   /* determine inactive elements (used for engine main loop optimization) */
3874   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3875   {
3876     boolean active = FALSE;
3877
3878     for (j = 0; i < NUM_ELEMENT_PROPERTIES; j++)
3879     {
3880       if (HAS_PROPERTY(i, j))
3881         active = TRUE;
3882     }
3883
3884 #if 0
3885     if (!active)
3886       SET_PROPERTY(i, EP_INACTIVE, TRUE);
3887 #endif
3888   }
3889 #endif
3890
3891   /* dynamically adjust element properties according to game engine version */
3892   {
3893     static int ep_em_slippery_wall[] =
3894     {
3895       EL_STEELWALL,
3896       EL_WALL,
3897       EL_EXPANDABLE_WALL,
3898       EL_EXPANDABLE_WALL_HORIZONTAL,
3899       EL_EXPANDABLE_WALL_VERTICAL,
3900       EL_EXPANDABLE_WALL_ANY,
3901       -1
3902     };
3903
3904     /* special EM style gems behaviour */
3905     for (i = 0; ep_em_slippery_wall[i] != -1; i++)
3906       SET_PROPERTY(ep_em_slippery_wall[i], EP_EM_SLIPPERY_WALL,
3907                    level.em_slippery_gems);
3908
3909     /* "EL_EXPANDABLE_WALL_GROWING" wasn't slippery for EM gems in 2.0.1 */
3910     SET_PROPERTY(EL_EXPANDABLE_WALL_GROWING, EP_EM_SLIPPERY_WALL,
3911                  (level.em_slippery_gems &&
3912                   engine_version > VERSION_IDENT(2,0,1,0)));
3913   }
3914
3915 #if 1
3916   /* set default push delay values (corrected since version 3.0.7-1) */
3917   if (engine_version < VERSION_IDENT(3,0,7,1))
3918   {
3919     game.default_push_delay_fixed = 2;
3920     game.default_push_delay_random = 8;
3921   }
3922   else
3923   {
3924     game.default_push_delay_fixed = 8;
3925     game.default_push_delay_random = 8;
3926   }
3927
3928   /* set uninitialized push delay values of custom elements in older levels */
3929   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
3930   {
3931     int element = EL_CUSTOM_START + i;
3932
3933     if (element_info[element].push_delay_fixed == -1)
3934       element_info[element].push_delay_fixed = game.default_push_delay_fixed;
3935     if (element_info[element].push_delay_random == -1)
3936       element_info[element].push_delay_random = game.default_push_delay_random;
3937   }
3938
3939   /* set some other uninitialized values of custom elements in older levels */
3940   if (engine_version < VERSION_IDENT(3,1,0,0))
3941   {
3942     for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
3943     {
3944       int element = EL_CUSTOM_START + i;
3945
3946       element_info[element].access_direction = MV_ALL_DIRECTIONS;
3947
3948       element_info[element].explosion_delay = 17;
3949       element_info[element].ignition_delay = 8;
3950     }
3951   }
3952
3953 #if 0
3954   /* set element properties that were handled incorrectly in older levels */
3955   if (engine_version < VERSION_IDENT(3,1,0,0))
3956   {
3957     SET_PROPERTY(EL_SP_SNIKSNAK, EP_DONT_COLLIDE_WITH, FALSE);
3958     SET_PROPERTY(EL_SP_ELECTRON, EP_DONT_COLLIDE_WITH, FALSE);
3959   }
3960 #endif
3961
3962 #endif
3963
3964   /* this is needed because some graphics depend on element properties */
3965   if (game_status == GAME_MODE_PLAYING)
3966     InitElementGraphicInfo();
3967 }
3968
3969 static void InitGlobal()
3970 {
3971   int i;
3972
3973   for (i = 0; i < MAX_NUM_ELEMENTS + 1; i++)
3974   {
3975     /* check if element_name_info entry defined for each element in "main.h" */
3976     if (i < MAX_NUM_ELEMENTS && element_name_info[i].token_name == NULL)
3977       Error(ERR_EXIT, "undefined 'element_name_info' entry for element %d", i);
3978
3979     element_info[i].token_name = element_name_info[i].token_name;
3980     element_info[i].class_name = element_name_info[i].class_name;
3981     element_info[i].editor_description=element_name_info[i].editor_description;
3982   }
3983
3984   global.autoplay_leveldir = NULL;
3985   global.convert_leveldir = NULL;
3986
3987   global.frames_per_second = 0;
3988   global.fps_slowdown = FALSE;
3989   global.fps_slowdown_factor = 1;
3990 }
3991
3992 void Execute_Command(char *command)
3993 {
3994   int i;
3995
3996   if (strcmp(command, "print graphicsinfo.conf") == 0)
3997   {
3998     printf("# You can configure additional/alternative image files here.\n");
3999     printf("# (The entries below are default and therefore commented out.)\n");
4000     printf("\n");
4001     printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
4002     printf("\n");
4003     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
4004     printf("\n");
4005
4006     for (i = 0; image_config[i].token != NULL; i++)
4007       printf("# %s\n", getFormattedSetupEntry(image_config[i].token,
4008                                               image_config[i].value));
4009
4010     exit(0);
4011   }
4012   else if (strcmp(command, "print soundsinfo.conf") == 0)
4013   {
4014     printf("# You can configure additional/alternative sound files here.\n");
4015     printf("# (The entries below are default and therefore commented out.)\n");
4016     printf("\n");
4017     printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
4018     printf("\n");
4019     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
4020     printf("\n");
4021
4022     for (i = 0; sound_config[i].token != NULL; i++)
4023       printf("# %s\n", getFormattedSetupEntry(sound_config[i].token,
4024                                               sound_config[i].value));
4025
4026     exit(0);
4027   }
4028   else if (strcmp(command, "print musicinfo.conf") == 0)
4029   {
4030     printf("# You can configure additional/alternative music files here.\n");
4031     printf("# (The entries below are default and therefore commented out.)\n");
4032     printf("\n");
4033     printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
4034     printf("\n");
4035     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
4036     printf("\n");
4037
4038     for (i = 0; music_config[i].token != NULL; i++)
4039       printf("# %s\n", getFormattedSetupEntry(music_config[i].token,
4040                                               music_config[i].value));
4041
4042     exit(0);
4043   }
4044   else if (strcmp(command, "print editorsetup.conf") == 0)
4045   {
4046     printf("# You can configure your personal editor element list here.\n");
4047     printf("# (The entries below are default and therefore commented out.)\n");
4048     printf("\n");
4049
4050     PrintEditorElementList();
4051
4052     exit(0);
4053   }
4054   else if (strcmp(command, "print helpanim.conf") == 0)
4055   {
4056     printf("# You can configure different element help animations here.\n");
4057     printf("# (The entries below are default and therefore commented out.)\n");
4058     printf("\n");
4059
4060     for (i = 0; helpanim_config[i].token != NULL; i++)
4061     {
4062       printf("# %s\n", getFormattedSetupEntry(helpanim_config[i].token,
4063                                               helpanim_config[i].value));
4064
4065       if (strcmp(helpanim_config[i].token, "end") == 0)
4066         printf("#\n");
4067     }
4068
4069     exit(0);
4070   }
4071   else if (strcmp(command, "print helptext.conf") == 0)
4072   {
4073     printf("# You can configure different element help text here.\n");
4074     printf("# (The entries below are default and therefore commented out.)\n");
4075     printf("\n");
4076
4077     for (i = 0; helptext_config[i].token != NULL; i++)
4078       printf("# %s\n", getFormattedSetupEntry(helptext_config[i].token,
4079                                               helptext_config[i].value));
4080
4081     exit(0);
4082   }
4083   else if (strncmp(command, "dump level ", 11) == 0)
4084   {
4085     char *filename = &command[11];
4086
4087     if (access(filename, F_OK) != 0)
4088       Error(ERR_EXIT, "cannot open file '%s'", filename);
4089
4090     LoadLevelFromFilename(&level, filename);
4091     DumpLevel(&level);
4092
4093     exit(0);
4094   }
4095   else if (strncmp(command, "dump tape ", 10) == 0)
4096   {
4097     char *filename = &command[10];
4098
4099     if (access(filename, F_OK) != 0)
4100       Error(ERR_EXIT, "cannot open file '%s'", filename);
4101
4102     LoadTapeFromFilename(filename);
4103     DumpTape(&tape);
4104
4105     exit(0);
4106   }
4107   else if (strncmp(command, "autoplay ", 9) == 0)
4108   {
4109     char *str_copy = getStringCopy(&command[9]);
4110     char *str_ptr = strchr(str_copy, ' ');
4111
4112     global.autoplay_leveldir = str_copy;
4113     global.autoplay_level_nr = -1;
4114
4115     if (str_ptr != NULL)
4116     {
4117       *str_ptr++ = '\0';                        /* terminate leveldir string */
4118       global.autoplay_level_nr = atoi(str_ptr); /* get level_nr value */
4119     }
4120   }
4121   else if (strncmp(command, "convert ", 8) == 0)
4122   {
4123     char *str_copy = getStringCopy(&command[8]);
4124     char *str_ptr = strchr(str_copy, ' ');
4125
4126     global.convert_leveldir = str_copy;
4127     global.convert_level_nr = -1;
4128
4129     if (str_ptr != NULL)
4130     {
4131       *str_ptr++ = '\0';                        /* terminate leveldir string */
4132       global.convert_level_nr = atoi(str_ptr);  /* get level_nr value */
4133     }
4134   }
4135   else
4136   {
4137     Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
4138   }
4139 }
4140
4141 static void InitSetup()
4142 {
4143   LoadSetup();                                  /* global setup info */
4144
4145   /* set some options from setup file */
4146
4147   if (setup.options.verbose)
4148     options.verbose = TRUE;
4149 }
4150
4151 static void InitPlayerInfo()
4152 {
4153   int i;
4154
4155   /* choose default local player */
4156   local_player = &stored_player[0];
4157
4158   for (i = 0; i < MAX_PLAYERS; i++)
4159     stored_player[i].connected = FALSE;
4160
4161   local_player->connected = TRUE;
4162 }
4163
4164 static void InitArtworkInfo()
4165 {
4166   LoadArtworkInfo();
4167 }
4168
4169 static char *get_string_in_brackets(char *string)
4170 {
4171   char *string_in_brackets = checked_malloc(strlen(string) + 3);
4172
4173   sprintf(string_in_brackets, "[%s]", string);
4174
4175   return string_in_brackets;
4176 }
4177
4178 static char *get_level_id_suffix(int id_nr)
4179 {
4180   char *id_suffix = checked_malloc(1 + 3 + 1);
4181
4182   if (id_nr < 0 || id_nr > 999)
4183     id_nr = 0;
4184
4185   sprintf(id_suffix, ".%03d", id_nr);
4186
4187   return id_suffix;
4188 }
4189
4190 #if 0
4191 static char *get_element_class_token(int element)
4192 {
4193   char *element_class_name = element_info[element].class_name;
4194   char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
4195
4196   sprintf(element_class_token, "[%s]", element_class_name);
4197
4198   return element_class_token;
4199 }
4200
4201 static char *get_action_class_token(int action)
4202 {
4203   char *action_class_name = &element_action_info[action].suffix[1];
4204   char *action_class_token = checked_malloc(strlen(action_class_name) + 3);
4205
4206   sprintf(action_class_token, "[%s]", action_class_name);
4207
4208   return action_class_token;
4209 }
4210 #endif
4211
4212 static void InitArtworkConfig()
4213 {
4214   static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
4215   static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + 1];
4216   static char *music_id_prefix[NUM_MUSIC_PREFIXES + 1];
4217   static char *action_id_suffix[NUM_ACTIONS + 1];
4218   static char *direction_id_suffix[NUM_DIRECTIONS + 1];
4219   static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
4220   static char *level_id_suffix[MAX_LEVELS + 1];
4221   static char *dummy[1] = { NULL };
4222   static char *ignore_generic_tokens[] =
4223   {
4224     "name",
4225     "sort_priority",
4226     NULL
4227   };
4228   static char **ignore_image_tokens;
4229   static char **ignore_sound_tokens;
4230   static char **ignore_music_tokens;
4231   int num_ignore_generic_tokens;
4232   int num_ignore_image_tokens;
4233   int num_ignore_sound_tokens;
4234   int num_ignore_music_tokens;
4235   int i;
4236
4237   /* dynamically determine list of generic tokens to be ignored */
4238   num_ignore_generic_tokens = 0;
4239   for (i = 0; ignore_generic_tokens[i] != NULL; i++)
4240     num_ignore_generic_tokens++;
4241
4242   /* dynamically determine list of image tokens to be ignored */
4243   num_ignore_image_tokens = num_ignore_generic_tokens;
4244   for (i = 0; image_config_vars[i].token != NULL; i++)
4245     num_ignore_image_tokens++;
4246   ignore_image_tokens =
4247     checked_malloc((num_ignore_image_tokens + 1) * sizeof(char *));
4248   for (i = 0; i < num_ignore_generic_tokens; i++)
4249     ignore_image_tokens[i] = ignore_generic_tokens[i];
4250   for (i = 0; i < num_ignore_image_tokens - num_ignore_generic_tokens; i++)
4251     ignore_image_tokens[num_ignore_generic_tokens + i] =
4252       image_config_vars[i].token;
4253   ignore_image_tokens[num_ignore_image_tokens] = NULL;
4254
4255   /* dynamically determine list of sound tokens to be ignored */
4256   num_ignore_sound_tokens = num_ignore_generic_tokens;
4257   ignore_sound_tokens =
4258     checked_malloc((num_ignore_sound_tokens + 1) * sizeof(char *));
4259   for (i = 0; i < num_ignore_generic_tokens; i++)
4260     ignore_sound_tokens[i] = ignore_generic_tokens[i];
4261   ignore_sound_tokens[num_ignore_sound_tokens] = NULL;
4262
4263   /* dynamically determine list of music tokens to be ignored */
4264   num_ignore_music_tokens = num_ignore_generic_tokens;
4265   ignore_music_tokens =
4266     checked_malloc((num_ignore_music_tokens + 1) * sizeof(char *));
4267   for (i = 0; i < num_ignore_generic_tokens; i++)
4268     ignore_music_tokens[i] = ignore_generic_tokens[i];
4269   ignore_music_tokens[num_ignore_music_tokens] = NULL;
4270
4271   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4272     image_id_prefix[i] = element_info[i].token_name;
4273   for (i = 0; i < NUM_FONTS; i++)
4274     image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
4275   image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
4276
4277   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4278     sound_id_prefix[i] = element_info[i].token_name;
4279   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
4280     sound_id_prefix[MAX_NUM_ELEMENTS + i] =
4281       get_string_in_brackets(element_info[i].class_name);
4282   sound_id_prefix[2 * MAX_NUM_ELEMENTS] = NULL;
4283
4284   for (i = 0; i < NUM_MUSIC_PREFIXES; i++)
4285     music_id_prefix[i] = music_prefix_info[i].prefix;
4286   music_id_prefix[MAX_LEVELS] = NULL;
4287
4288   for (i = 0; i < NUM_ACTIONS; i++)
4289     action_id_suffix[i] = element_action_info[i].suffix;
4290   action_id_suffix[NUM_ACTIONS] = NULL;
4291
4292   for (i = 0; i < NUM_DIRECTIONS; i++)
4293     direction_id_suffix[i] = element_direction_info[i].suffix;
4294   direction_id_suffix[NUM_DIRECTIONS] = NULL;
4295
4296   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
4297     special_id_suffix[i] = special_suffix_info[i].suffix;
4298   special_id_suffix[NUM_SPECIAL_GFX_ARGS] = NULL;
4299
4300   for (i = 0; i < MAX_LEVELS; i++)
4301     level_id_suffix[i] = get_level_id_suffix(i);
4302   level_id_suffix[MAX_LEVELS] = NULL;
4303
4304   InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
4305                 image_id_prefix, action_id_suffix, direction_id_suffix,
4306                 special_id_suffix, ignore_image_tokens);
4307   InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
4308                 sound_id_prefix, action_id_suffix, dummy,
4309                 special_id_suffix, ignore_sound_tokens);
4310   InitMusicList(music_config, NUM_MUSIC_FILES, music_config_suffix,
4311                 music_id_prefix, special_id_suffix, level_id_suffix,
4312                 dummy, ignore_music_tokens);
4313 }
4314
4315 static void InitMixer()
4316 {
4317   OpenAudio();
4318   StartMixer();
4319 }
4320
4321 void InitGfx()
4322 {
4323   char *filename_font_initial = NULL;
4324   Bitmap *bitmap_font_initial = NULL;
4325   int i, j;
4326
4327   /* determine settings for initial font (for displaying startup messages) */
4328   for (i = 0; image_config[i].token != NULL; i++)
4329   {
4330     for (j = 0; j < NUM_INITIAL_FONTS; j++)
4331     {
4332       char font_token[128];
4333       int len_font_token;
4334
4335       sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1);
4336       len_font_token = strlen(font_token);
4337
4338       if (strcmp(image_config[i].token, font_token) == 0)
4339         filename_font_initial = image_config[i].value;
4340       else if (strlen(image_config[i].token) > len_font_token &&
4341                strncmp(image_config[i].token, font_token, len_font_token) == 0)
4342       {
4343         if (strcmp(&image_config[i].token[len_font_token], ".x") == 0)
4344           font_initial[j].src_x = atoi(image_config[i].value);
4345         else if (strcmp(&image_config[i].token[len_font_token], ".y") == 0)
4346           font_initial[j].src_y = atoi(image_config[i].value);
4347         else if (strcmp(&image_config[i].token[len_font_token], ".width") == 0)
4348           font_initial[j].width = atoi(image_config[i].value);
4349         else if (strcmp(&image_config[i].token[len_font_token],".height") == 0)
4350           font_initial[j].height = atoi(image_config[i].value);
4351       }
4352     }
4353   }
4354
4355   for (j = 0; j < NUM_INITIAL_FONTS; j++)
4356   {
4357     font_initial[j].num_chars = DEFAULT_NUM_CHARS_PER_FONT;
4358     font_initial[j].num_chars_per_line = DEFAULT_NUM_CHARS_PER_LINE;
4359   }
4360
4361   if (filename_font_initial == NULL)    /* should not happen */
4362     Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
4363
4364   /* create additional image buffers for double-buffering */
4365   bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
4366   bitmap_db_door  = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
4367
4368   /* initialize screen properties */
4369   InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
4370                    REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
4371                    bitmap_db_field);
4372   InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
4373   InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
4374   InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
4375
4376   bitmap_font_initial = LoadCustomImage(filename_font_initial);
4377
4378   for (j = 0; j < NUM_INITIAL_FONTS; j++)
4379     font_initial[j].bitmap = bitmap_font_initial;
4380
4381   InitFontGraphicInfo();
4382
4383   DrawInitText(getProgramInitString(), 20, FC_YELLOW);
4384   DrawInitText(PROGRAM_COPYRIGHT_STRING, 50, FC_RED);
4385
4386   DrawInitText("Loading graphics:", 120, FC_GREEN);
4387
4388   InitTileClipmasks();
4389 }
4390
4391 void InitGfxBackground()
4392 {
4393   int x, y;
4394
4395   drawto = backbuffer;
4396   fieldbuffer = bitmap_db_field;
4397   SetDrawtoField(DRAW_BACKBUFFER);
4398
4399   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
4400              0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
4401   ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
4402   ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
4403
4404   for (x = 0; x < MAX_BUF_XSIZE; x++)
4405     for (y = 0; y < MAX_BUF_YSIZE; y++)
4406       redraw[x][y] = 0;
4407   redraw_tiles = 0;
4408   redraw_mask = REDRAW_ALL;
4409 }
4410
4411 static void InitLevelInfo()
4412 {
4413   LoadLevelInfo();                              /* global level info */
4414   LoadLevelSetup_LastSeries();                  /* last played series info */
4415   LoadLevelSetup_SeriesInfo();                  /* last played level info */
4416 }
4417
4418 void InitLevelArtworkInfo()
4419 {
4420   LoadLevelArtworkInfo();
4421 }
4422
4423 static void InitImages()
4424 {
4425 #if 1
4426   setLevelArtworkDir(artwork.gfx_first);
4427 #endif
4428
4429 #if 0
4430   printf("::: InitImages for '%s' ['%s', '%s'] ['%s', '%s']\n",
4431          leveldir_current->identifier,
4432          artwork.gfx_current_identifier,
4433          artwork.gfx_current->identifier,
4434          leveldir_current->graphics_set,
4435          leveldir_current->graphics_path);
4436 #endif
4437
4438   ReloadCustomImages();
4439
4440   LoadCustomElementDescriptions();
4441   LoadSpecialMenuDesignSettings();
4442
4443   ReinitializeGraphics();
4444 }
4445
4446 static void InitSound(char *identifier)
4447 {
4448   if (identifier == NULL)
4449     identifier = artwork.snd_current->identifier;
4450
4451 #if 1
4452   /* set artwork path to send it to the sound server process */
4453   setLevelArtworkDir(artwork.snd_first);
4454 #endif
4455
4456   InitReloadCustomSounds(identifier);
4457   ReinitializeSounds();
4458 }
4459
4460 static void InitMusic(char *identifier)
4461 {
4462   if (identifier == NULL)
4463     identifier = artwork.mus_current->identifier;
4464
4465 #if 1
4466   /* set artwork path to send it to the sound server process */
4467   setLevelArtworkDir(artwork.mus_first);
4468 #endif
4469
4470   InitReloadCustomMusic(identifier);
4471   ReinitializeMusic();
4472 }
4473
4474 void InitNetworkServer()
4475 {
4476 #if defined(NETWORK_AVALIABLE)
4477   int nr_wanted;
4478 #endif
4479
4480   if (!options.network)
4481     return;
4482
4483 #if defined(NETWORK_AVALIABLE)
4484   nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
4485
4486   if (!ConnectToServer(options.server_host, options.server_port))
4487     Error(ERR_EXIT, "cannot connect to network game server");
4488
4489   SendToServer_PlayerName(setup.player_name);
4490   SendToServer_ProtocolVersion();
4491
4492   if (nr_wanted)
4493     SendToServer_NrWanted(nr_wanted);
4494 #endif
4495 }
4496
4497 static char *getNewArtworkIdentifier(int type)
4498 {
4499   static char *leveldir_current_identifier[3] = { NULL, NULL, NULL };
4500   static boolean last_override_level_artwork[3] = { FALSE, FALSE, FALSE };
4501   static boolean last_has_level_artwork_set[3] = { FALSE, FALSE, FALSE };
4502   static boolean initialized[3] = { FALSE, FALSE, FALSE };
4503   TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
4504   boolean setup_override_artwork = SETUP_OVERRIDE_ARTWORK(setup, type);
4505   char *setup_artwork_set = SETUP_ARTWORK_SET(setup, type);
4506   char *leveldir_identifier = leveldir_current->identifier;
4507 #if 1
4508   /* !!! setLevelArtworkDir() should be moved to an earlier stage !!! */
4509   char *leveldir_artwork_set = setLevelArtworkDir(artwork_first_node);
4510 #else
4511   char *leveldir_artwork_set = LEVELDIR_ARTWORK_SET(leveldir_current, type);
4512 #endif
4513   boolean has_level_artwork_set = (leveldir_artwork_set != NULL);
4514   char *artwork_current_identifier;
4515   char *artwork_new_identifier = NULL;  /* default: nothing has changed */
4516
4517   /* leveldir_current may be invalid (level group, parent link) */
4518   if (!validLevelSeries(leveldir_current))
4519     return NULL;
4520
4521   /* 1st step: determine artwork set to be activated in descending order:
4522      --------------------------------------------------------------------
4523      1. setup artwork (when configured to override everything else)
4524      2. artwork set configured in "levelinfo.conf" of current level set
4525         (artwork in level directory will have priority when loading later)
4526      3. artwork in level directory (stored in artwork sub-directory)
4527      4. setup artwork (currently configured in setup menu) */
4528
4529   if (setup_override_artwork)
4530     artwork_current_identifier = setup_artwork_set;
4531   else if (leveldir_artwork_set != NULL)
4532     artwork_current_identifier = leveldir_artwork_set;
4533   else if (getTreeInfoFromIdentifier(artwork_first_node, leveldir_identifier))
4534     artwork_current_identifier = leveldir_identifier;
4535   else
4536     artwork_current_identifier = setup_artwork_set;
4537
4538
4539   /* 2nd step: check if it is really needed to reload artwork set
4540      ------------------------------------------------------------ */
4541
4542 #if 0
4543   if (type == ARTWORK_TYPE_GRAPHICS)
4544     printf("::: 0: '%s' ['%s', '%s'] ['%s' ('%s')]\n",
4545            artwork_new_identifier,
4546            ARTWORK_CURRENT_IDENTIFIER(artwork, type),
4547            artwork_current_identifier,
4548            leveldir_current->graphics_set,
4549            leveldir_current->identifier);
4550 #endif
4551
4552   /* ---------- reload if level set and also artwork set has changed ------- */
4553   if (leveldir_current_identifier[type] != leveldir_identifier &&
4554       (last_has_level_artwork_set[type] || has_level_artwork_set))
4555     artwork_new_identifier = artwork_current_identifier;
4556
4557   leveldir_current_identifier[type] = leveldir_identifier;
4558   last_has_level_artwork_set[type] = has_level_artwork_set;
4559
4560 #if 0
4561   if (type == ARTWORK_TYPE_GRAPHICS)
4562     printf("::: 1: '%s'\n", artwork_new_identifier);
4563 #endif
4564
4565   /* ---------- reload if "override artwork" setting has changed ----------- */
4566   if (last_override_level_artwork[type] != setup_override_artwork)
4567     artwork_new_identifier = artwork_current_identifier;
4568
4569   last_override_level_artwork[type] = setup_override_artwork;
4570
4571 #if 0
4572   if (type == ARTWORK_TYPE_GRAPHICS)
4573     printf("::: 2: '%s'\n", artwork_new_identifier);
4574 #endif
4575
4576   /* ---------- reload if current artwork identifier has changed ----------- */
4577   if (strcmp(ARTWORK_CURRENT_IDENTIFIER(artwork, type),
4578              artwork_current_identifier) != 0)
4579     artwork_new_identifier = artwork_current_identifier;
4580
4581   *(&(ARTWORK_CURRENT_IDENTIFIER(artwork, type))) = artwork_current_identifier;
4582
4583 #if 0
4584   if (type == ARTWORK_TYPE_GRAPHICS)
4585     printf("::: 3: '%s'\n", artwork_new_identifier);
4586 #endif
4587
4588   /* ---------- do not reload directly after starting ---------------------- */
4589   if (!initialized[type])
4590     artwork_new_identifier = NULL;
4591
4592   initialized[type] = TRUE;
4593
4594 #if 0
4595   if (type == ARTWORK_TYPE_GRAPHICS)
4596     printf("::: 4: '%s'\n", artwork_new_identifier);
4597 #endif
4598
4599 #if 0
4600   if (type == ARTWORK_TYPE_GRAPHICS)
4601     printf("CHECKING OLD/NEW GFX:\n- OLD: %s\n- NEW: %s ['%s', '%s'] ['%s']\n",
4602            artwork.gfx_current_identifier, artwork_current_identifier,
4603            artwork.gfx_current->identifier, leveldir_current->graphics_set,
4604            artwork_new_identifier);
4605 #endif
4606
4607   return artwork_new_identifier;
4608 }
4609
4610 void ReloadCustomArtwork(int force_reload)
4611 {
4612   char *gfx_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_GRAPHICS);
4613   char *snd_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_SOUNDS);
4614   char *mus_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_MUSIC);
4615   boolean force_reload_gfx = (force_reload & (1 << ARTWORK_TYPE_GRAPHICS));
4616   boolean force_reload_snd = (force_reload & (1 << ARTWORK_TYPE_SOUNDS));
4617   boolean force_reload_mus = (force_reload & (1 << ARTWORK_TYPE_MUSIC));
4618   boolean redraw_screen = FALSE;
4619
4620   if (gfx_new_identifier != NULL || force_reload_gfx)
4621   {
4622 #if 0
4623     printf("RELOADING GRAPHICS '%s' -> '%s' ['%s', '%s']\n",
4624            artwork.gfx_current_identifier,
4625            gfx_new_identifier,
4626            artwork.gfx_current->identifier,
4627            leveldir_current->graphics_set);
4628 #endif
4629
4630     ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
4631
4632     InitImages();
4633
4634 #if 0
4635     printf("... '%s'\n",
4636            leveldir_current->graphics_set);
4637 #endif
4638
4639     FreeTileClipmasks();
4640     InitTileClipmasks();
4641
4642     redraw_screen = TRUE;
4643   }
4644
4645   if (snd_new_identifier != NULL || force_reload_snd)
4646   {
4647     ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
4648
4649     InitSound(snd_new_identifier);
4650
4651     redraw_screen = TRUE;
4652   }
4653
4654   if (mus_new_identifier != NULL || force_reload_mus)
4655   {
4656     ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
4657
4658     InitMusic(mus_new_identifier);
4659
4660     redraw_screen = TRUE;
4661   }
4662
4663   if (redraw_screen)
4664   {
4665     InitGfxBackground();
4666
4667     /* force redraw of (open or closed) door graphics */
4668     SetDoorState(DOOR_OPEN_ALL);
4669     CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
4670   }
4671 }
4672
4673 void KeyboardAutoRepeatOffUnlessAutoplay()
4674 {
4675   if (global.autoplay_leveldir == NULL)
4676     KeyboardAutoRepeatOff();
4677 }
4678
4679
4680 /* ========================================================================= */
4681 /* OpenAll()                                                                 */
4682 /* ========================================================================= */
4683
4684 void OpenAll()
4685 {
4686   InitGlobal();         /* initialize some global variables */
4687
4688   if (options.execute_command)
4689     Execute_Command(options.execute_command);
4690
4691   if (options.serveronly)
4692   {
4693 #if defined(PLATFORM_UNIX)
4694     NetworkServer(options.server_port, options.serveronly);
4695 #else
4696     Error(ERR_WARN, "networking only supported in Unix version");
4697 #endif
4698     exit(0);    /* never reached */
4699   }
4700
4701   InitSetup();
4702
4703   InitPlayerInfo();
4704   InitArtworkInfo();            /* needed before loading gfx, sound & music */
4705   InitArtworkConfig();          /* needed before forking sound child process */
4706   InitMixer();
4707
4708   InitCounter();
4709
4710   InitRND(NEW_RANDOMIZE);
4711   InitSimpleRND(NEW_RANDOMIZE);
4712
4713   InitJoysticks();
4714
4715   InitVideoDisplay();
4716   InitVideoBuffer(&backbuffer, &window, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH,
4717                   setup.fullscreen);
4718
4719   InitEventFilter(FilterMouseMotionEvents);
4720
4721   InitElementPropertiesStatic();
4722   InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
4723
4724   InitGfx();
4725
4726   InitLevelInfo();
4727   InitLevelArtworkInfo();
4728
4729   InitImages();                 /* needs to know current level directory */
4730   InitSound(NULL);              /* needs to know current level directory */
4731   InitMusic(NULL);              /* needs to know current level directory */
4732
4733   InitGfxBackground();
4734
4735   if (global.autoplay_leveldir)
4736   {
4737     AutoPlayTape();
4738     return;
4739   }
4740   else if (global.convert_leveldir)
4741   {
4742     ConvertLevels();
4743     return;
4744   }
4745
4746   game_status = GAME_MODE_MAIN;
4747
4748 #if 1
4749   em_open_all();
4750 #endif
4751
4752   DrawMainMenu();
4753
4754   InitNetworkServer();
4755 }
4756
4757 void CloseAllAndExit(int exit_value)
4758 {
4759   StopSounds();
4760   FreeAllSounds();
4761   FreeAllMusic();
4762   CloseAudio();         /* called after freeing sounds (needed for SDL) */
4763
4764 #if 1
4765   em_close_all();
4766 #endif
4767
4768   FreeAllImages();
4769   FreeTileClipmasks();
4770
4771 #if defined(TARGET_SDL)
4772   if (network_server)   /* terminate network server */
4773     SDL_KillThread(server_thread);
4774 #endif
4775
4776   CloseVideoDisplay();
4777   ClosePlatformDependentStuff();
4778
4779   exit(exit_value);
4780 }