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