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