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