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