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