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