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