c7a199118fea2390f170d8c2bbdc212910a0a1a8
[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_GATE_1,
1762     EL_GATE_2,
1763     EL_GATE_3,
1764     EL_GATE_4,
1765     EL_GATE_1_GRAY,
1766     EL_GATE_2_GRAY,
1767     EL_GATE_3_GRAY,
1768     EL_GATE_4_GRAY,
1769     EL_PENGUIN,
1770     EL_PIG,
1771     EL_DRAGON,
1772     -1
1773   };
1774
1775   static int ep_walkable_inside[] =
1776   {
1777     EL_TUBE_ANY,
1778     EL_TUBE_VERTICAL,
1779     EL_TUBE_HORIZONTAL,
1780     EL_TUBE_VERTICAL_LEFT,
1781     EL_TUBE_VERTICAL_RIGHT,
1782     EL_TUBE_HORIZONTAL_UP,
1783     EL_TUBE_HORIZONTAL_DOWN,
1784     EL_TUBE_LEFT_UP,
1785     EL_TUBE_LEFT_DOWN,
1786     EL_TUBE_RIGHT_UP,
1787     EL_TUBE_RIGHT_DOWN,
1788     -1
1789   };
1790
1791   static int ep_walkable_under[] =
1792   {
1793     -1
1794   };
1795
1796   static int ep_passable_over[] =
1797   {
1798     EL_EM_GATE_1,
1799     EL_EM_GATE_2,
1800     EL_EM_GATE_3,
1801     EL_EM_GATE_4,
1802     EL_EM_GATE_1_GRAY,
1803     EL_EM_GATE_2_GRAY,
1804     EL_EM_GATE_3_GRAY,
1805     EL_EM_GATE_4_GRAY,
1806     EL_SWITCHGATE_OPEN,
1807     EL_TIMEGATE_OPEN,
1808     -1
1809   };
1810
1811   static int ep_passable_inside[] =
1812   {
1813     EL_SP_PORT_LEFT,
1814     EL_SP_PORT_RIGHT,
1815     EL_SP_PORT_UP,
1816     EL_SP_PORT_DOWN,
1817     EL_SP_PORT_HORIZONTAL,
1818     EL_SP_PORT_VERTICAL,
1819     EL_SP_PORT_ANY,
1820     EL_SP_GRAVITY_PORT_LEFT,
1821     EL_SP_GRAVITY_PORT_RIGHT,
1822     EL_SP_GRAVITY_PORT_UP,
1823     EL_SP_GRAVITY_PORT_DOWN,
1824     -1
1825   };
1826
1827   static int ep_passable_under[] =
1828   {
1829     -1
1830   };
1831
1832   static int ep_droppable[] =
1833   {
1834     -1
1835   };
1836
1837   static int ep_can_explode_1x1[] =
1838   {
1839     -1
1840   };
1841
1842   static int ep_pushable[] =
1843   {
1844     EL_ROCK,
1845     EL_BOMB,
1846     EL_DX_SUPABOMB,
1847     EL_NUT,
1848     EL_TIME_ORB_EMPTY,
1849     EL_SP_ZONK,
1850     EL_SP_DISK_ORANGE,
1851     EL_SPRING,
1852     EL_BD_ROCK,
1853     EL_SOKOBAN_OBJECT,
1854     EL_SOKOBAN_FIELD_FULL,
1855     EL_SATELLITE,
1856     EL_SP_DISK_YELLOW,
1857     EL_BALLOON,
1858     -1
1859   };
1860
1861   static int ep_player[] =
1862   {
1863     EL_PLAYER_1,
1864     EL_PLAYER_2,
1865     EL_PLAYER_3,
1866     EL_PLAYER_4,
1867     EL_SP_MURPHY,
1868     -1
1869   };
1870
1871   static int ep_can_pass_magic_wall[] =
1872   {
1873     EL_ROCK,
1874     EL_BD_ROCK,
1875     EL_EMERALD,
1876     EL_BD_DIAMOND,
1877     EL_EMERALD_YELLOW,
1878     EL_EMERALD_RED,
1879     EL_EMERALD_PURPLE,
1880     EL_DIAMOND,
1881     -1
1882   };
1883
1884   static int ep_switchable[] =
1885   {
1886     EL_ROBOT_WHEEL,
1887     EL_SP_TERMINAL,
1888     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
1889     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
1890     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
1891     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
1892     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
1893     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
1894     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
1895     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
1896     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
1897     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
1898     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
1899     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
1900     EL_SWITCHGATE_SWITCH_UP,
1901     EL_SWITCHGATE_SWITCH_DOWN,
1902     EL_LIGHT_SWITCH,
1903     EL_LIGHT_SWITCH_ACTIVE,
1904     EL_TIMEGATE_SWITCH,
1905     EL_BALLOON_SWITCH_LEFT,
1906     EL_BALLOON_SWITCH_RIGHT,
1907     EL_BALLOON_SWITCH_UP,
1908     EL_BALLOON_SWITCH_DOWN,
1909     EL_BALLOON_SWITCH_ANY,
1910     EL_LAMP,
1911     EL_TIME_ORB_FULL,
1912     -1
1913   };
1914
1915   static int ep_bd_element[] =
1916   {
1917     EL_EMPTY,
1918     EL_SAND,
1919     EL_WALL_SLIPPERY,
1920     EL_BD_WALL,
1921     EL_ROCK,
1922     EL_BD_ROCK,
1923     EL_BD_DIAMOND,
1924     EL_BD_MAGIC_WALL,
1925     EL_EXIT_CLOSED,
1926     EL_EXIT_OPEN,
1927     EL_STEELWALL,
1928     EL_PLAYER_1,
1929     EL_BD_FIREFLY,
1930     EL_BD_FIREFLY_1,
1931     EL_BD_FIREFLY_2,
1932     EL_BD_FIREFLY_3,
1933     EL_BD_FIREFLY_4,
1934     EL_BD_BUTTERFLY,
1935     EL_BD_BUTTERFLY_1,
1936     EL_BD_BUTTERFLY_2,
1937     EL_BD_BUTTERFLY_3,
1938     EL_BD_BUTTERFLY_4,
1939     EL_BD_AMOEBA,
1940     EL_CHAR_QUESTION,
1941     -1
1942   };
1943
1944   static int ep_sp_element[] =
1945   {
1946     /* should always be valid */
1947     EL_EMPTY,
1948
1949     EL_SP_EMPTY,
1950     EL_SP_ZONK,
1951     EL_SP_BASE,
1952     EL_SP_MURPHY,
1953     EL_SP_INFOTRON,
1954     EL_SP_CHIP_SINGLE,
1955     EL_SP_HARDWARE_GRAY,
1956     EL_SP_EXIT_CLOSED,
1957     EL_SP_EXIT_OPEN,
1958     EL_SP_DISK_ORANGE,
1959     EL_SP_PORT_RIGHT,
1960     EL_SP_PORT_DOWN,
1961     EL_SP_PORT_LEFT,
1962     EL_SP_PORT_UP,
1963     EL_SP_GRAVITY_PORT_RIGHT,
1964     EL_SP_GRAVITY_PORT_DOWN,
1965     EL_SP_GRAVITY_PORT_LEFT,
1966     EL_SP_GRAVITY_PORT_UP,
1967     EL_SP_SNIKSNAK,
1968     EL_SP_DISK_YELLOW,
1969     EL_SP_TERMINAL,
1970     EL_SP_DISK_RED,
1971     EL_SP_PORT_VERTICAL,
1972     EL_SP_PORT_HORIZONTAL,
1973     EL_SP_PORT_ANY,
1974     EL_SP_ELECTRON,
1975     EL_SP_BUGGY_BASE,
1976     EL_SP_CHIP_LEFT,
1977     EL_SP_CHIP_RIGHT,
1978     EL_SP_HARDWARE_BASE_1,
1979     EL_SP_HARDWARE_GREEN,
1980     EL_SP_HARDWARE_BLUE,
1981     EL_SP_HARDWARE_RED,
1982     EL_SP_HARDWARE_YELLOW,
1983     EL_SP_HARDWARE_BASE_2,
1984     EL_SP_HARDWARE_BASE_3,
1985     EL_SP_HARDWARE_BASE_4,
1986     EL_SP_HARDWARE_BASE_5,
1987     EL_SP_HARDWARE_BASE_6,
1988     EL_SP_CHIP_TOP,
1989     EL_SP_CHIP_BOTTOM,
1990     /* additional elements that appeared in newer Supaplex levels */
1991     EL_INVISIBLE_WALL,
1992     /* more than one murphy in a level results in an inactive clone */
1993     EL_SP_MURPHY_CLONE,
1994     /* runtime elements*/
1995     EL_SP_DISK_RED_ACTIVE,
1996     EL_SP_TERMINAL_ACTIVE,
1997     EL_SP_BUGGY_BASE_ACTIVATING,
1998     EL_SP_BUGGY_BASE_ACTIVE,
1999     -1
2000   };
2001
2002   static int ep_sb_element[] =
2003   {
2004     EL_EMPTY,
2005     EL_STEELWALL,
2006     EL_SOKOBAN_OBJECT,
2007     EL_SOKOBAN_FIELD_EMPTY,
2008     EL_SOKOBAN_FIELD_FULL,
2009     EL_PLAYER_1,
2010     EL_INVISIBLE_STEELWALL,
2011     -1
2012   };
2013
2014   static int ep_gem[] =
2015   {
2016     EL_BD_DIAMOND,
2017     EL_EMERALD,
2018     EL_EMERALD_YELLOW,
2019     EL_EMERALD_RED,
2020     EL_EMERALD_PURPLE,
2021     EL_DIAMOND,
2022     -1
2023   };
2024
2025   static int ep_food_dark_yamyam[] =
2026   {
2027     EL_SAND,
2028     EL_BUG,
2029     EL_SPACESHIP,
2030     EL_BD_BUTTERFLY,
2031     EL_BD_FIREFLY,
2032     EL_YAMYAM,
2033     EL_ROBOT,
2034     EL_PACMAN,
2035     EL_AMOEBA_DROP,
2036     EL_AMOEBA_DEAD,
2037     EL_AMOEBA_WET,
2038     EL_AMOEBA_DRY,
2039     EL_AMOEBA_FULL,
2040     EL_BD_AMOEBA,
2041     EL_EMERALD,
2042     EL_BD_DIAMOND,
2043     EL_EMERALD_YELLOW,
2044     EL_EMERALD_RED,
2045     EL_EMERALD_PURPLE,
2046     EL_DIAMOND,
2047     EL_PEARL,
2048     EL_CRYSTAL,
2049     -1
2050   };
2051
2052   static int ep_food_penguin[] =
2053   {
2054     EL_EMERALD,
2055     EL_BD_DIAMOND,
2056     EL_EMERALD_YELLOW,
2057     EL_EMERALD_RED,
2058     EL_EMERALD_PURPLE,
2059     EL_DIAMOND,
2060     EL_PEARL,
2061     EL_CRYSTAL,
2062     -1
2063   };
2064
2065   static int ep_food_pig[] =
2066   {
2067     EL_EMERALD,
2068     EL_BD_DIAMOND,
2069     EL_EMERALD_YELLOW,
2070     EL_EMERALD_RED,
2071     EL_EMERALD_PURPLE,
2072     EL_DIAMOND,
2073     -1
2074   };
2075
2076   static int ep_historic_wall[] =
2077   {
2078     EL_STEELWALL,
2079     EL_GATE_1,
2080     EL_GATE_2,
2081     EL_GATE_3,
2082     EL_GATE_4,
2083     EL_GATE_1_GRAY,
2084     EL_GATE_2_GRAY,
2085     EL_GATE_3_GRAY,
2086     EL_GATE_4_GRAY,
2087     EL_EM_GATE_1,
2088     EL_EM_GATE_2,
2089     EL_EM_GATE_3,
2090     EL_EM_GATE_4,
2091     EL_EM_GATE_1_GRAY,
2092     EL_EM_GATE_2_GRAY,
2093     EL_EM_GATE_3_GRAY,
2094     EL_EM_GATE_4_GRAY,
2095     EL_EXIT_CLOSED,
2096     EL_EXIT_OPENING,
2097     EL_EXIT_OPEN,
2098     EL_WALL,
2099     EL_WALL_SLIPPERY,
2100     EL_EXPANDABLE_WALL,
2101     EL_EXPANDABLE_WALL_HORIZONTAL,
2102     EL_EXPANDABLE_WALL_VERTICAL,
2103     EL_EXPANDABLE_WALL_ANY,
2104     EL_EXPANDABLE_WALL_GROWING,
2105     EL_BD_WALL,
2106     EL_SP_CHIP_SINGLE,
2107     EL_SP_CHIP_LEFT,
2108     EL_SP_CHIP_RIGHT,
2109     EL_SP_CHIP_TOP,
2110     EL_SP_CHIP_BOTTOM,
2111     EL_SP_HARDWARE_GRAY,
2112     EL_SP_HARDWARE_GREEN,
2113     EL_SP_HARDWARE_BLUE,
2114     EL_SP_HARDWARE_RED,
2115     EL_SP_HARDWARE_YELLOW,
2116     EL_SP_HARDWARE_BASE_1,
2117     EL_SP_HARDWARE_BASE_2,
2118     EL_SP_HARDWARE_BASE_3,
2119     EL_SP_HARDWARE_BASE_4,
2120     EL_SP_HARDWARE_BASE_5,
2121     EL_SP_HARDWARE_BASE_6,
2122     EL_SP_TERMINAL,
2123     EL_SP_TERMINAL_ACTIVE,
2124     EL_SP_EXIT_CLOSED,
2125     EL_SP_EXIT_OPEN,
2126     EL_INVISIBLE_STEELWALL,
2127     EL_INVISIBLE_STEELWALL_ACTIVE,
2128     EL_INVISIBLE_WALL,
2129     EL_INVISIBLE_WALL_ACTIVE,
2130     EL_STEELWALL_SLIPPERY,
2131     EL_EMC_STEELWALL_1,
2132     EL_EMC_STEELWALL_2,
2133     EL_EMC_STEELWALL_3,
2134     EL_EMC_STEELWALL_4,
2135     EL_EMC_WALL_1,
2136     EL_EMC_WALL_2,
2137     EL_EMC_WALL_3,
2138     EL_EMC_WALL_4,
2139     EL_EMC_WALL_5,
2140     EL_EMC_WALL_6,
2141     EL_EMC_WALL_7,
2142     EL_EMC_WALL_8,
2143     -1
2144   };
2145
2146   static int ep_historic_solid[] =
2147   {
2148     EL_WALL,
2149     EL_EXPANDABLE_WALL,
2150     EL_EXPANDABLE_WALL_HORIZONTAL,
2151     EL_EXPANDABLE_WALL_VERTICAL,
2152     EL_EXPANDABLE_WALL_ANY,
2153     EL_BD_WALL,
2154     EL_WALL_SLIPPERY,
2155     EL_EXIT_CLOSED,
2156     EL_EXIT_OPENING,
2157     EL_EXIT_OPEN,
2158     EL_AMOEBA_DEAD,
2159     EL_AMOEBA_WET,
2160     EL_AMOEBA_DRY,
2161     EL_AMOEBA_FULL,
2162     EL_BD_AMOEBA,
2163     EL_QUICKSAND_EMPTY,
2164     EL_QUICKSAND_FULL,
2165     EL_QUICKSAND_FILLING,
2166     EL_QUICKSAND_EMPTYING,
2167     EL_MAGIC_WALL,
2168     EL_MAGIC_WALL_ACTIVE,
2169     EL_MAGIC_WALL_EMPTYING,
2170     EL_MAGIC_WALL_FILLING,
2171     EL_MAGIC_WALL_FULL,
2172     EL_MAGIC_WALL_DEAD,
2173     EL_BD_MAGIC_WALL,
2174     EL_BD_MAGIC_WALL_ACTIVE,
2175     EL_BD_MAGIC_WALL_EMPTYING,
2176     EL_BD_MAGIC_WALL_FULL,
2177     EL_BD_MAGIC_WALL_FILLING,
2178     EL_BD_MAGIC_WALL_DEAD,
2179     EL_GAME_OF_LIFE,
2180     EL_BIOMAZE,
2181     EL_SP_CHIP_SINGLE,
2182     EL_SP_CHIP_LEFT,
2183     EL_SP_CHIP_RIGHT,
2184     EL_SP_CHIP_TOP,
2185     EL_SP_CHIP_BOTTOM,
2186     EL_SP_TERMINAL,
2187     EL_SP_TERMINAL_ACTIVE,
2188     EL_SP_EXIT_CLOSED,
2189     EL_SP_EXIT_OPEN,
2190     EL_INVISIBLE_WALL,
2191     EL_INVISIBLE_WALL_ACTIVE,
2192     EL_SWITCHGATE_SWITCH_UP,
2193     EL_SWITCHGATE_SWITCH_DOWN,
2194     EL_TIMEGATE_SWITCH,
2195     EL_TIMEGATE_SWITCH_ACTIVE,
2196     EL_EMC_WALL_1,
2197     EL_EMC_WALL_2,
2198     EL_EMC_WALL_3,
2199     EL_EMC_WALL_4,
2200     EL_EMC_WALL_5,
2201     EL_EMC_WALL_6,
2202     EL_EMC_WALL_7,
2203     EL_EMC_WALL_8,
2204     EL_WALL_PEARL,
2205     EL_WALL_CRYSTAL,
2206
2207     /* the following elements are a direct copy of "indestructible" elements,
2208        except "EL_ACID", which is "indestructible", but not "solid"! */
2209 #if 0
2210     EL_ACID,
2211 #endif
2212     EL_STEELWALL,
2213     EL_ACID_POOL_TOPLEFT,
2214     EL_ACID_POOL_TOPRIGHT,
2215     EL_ACID_POOL_BOTTOMLEFT,
2216     EL_ACID_POOL_BOTTOM,
2217     EL_ACID_POOL_BOTTOMRIGHT,
2218     EL_SP_HARDWARE_GRAY,
2219     EL_SP_HARDWARE_GREEN,
2220     EL_SP_HARDWARE_BLUE,
2221     EL_SP_HARDWARE_RED,
2222     EL_SP_HARDWARE_YELLOW,
2223     EL_SP_HARDWARE_BASE_1,
2224     EL_SP_HARDWARE_BASE_2,
2225     EL_SP_HARDWARE_BASE_3,
2226     EL_SP_HARDWARE_BASE_4,
2227     EL_SP_HARDWARE_BASE_5,
2228     EL_SP_HARDWARE_BASE_6,
2229     EL_INVISIBLE_STEELWALL,
2230     EL_INVISIBLE_STEELWALL_ACTIVE,
2231     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2232     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2233     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2234     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2235     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2236     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2237     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2238     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2239     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2240     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2241     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2242     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2243     EL_LIGHT_SWITCH,
2244     EL_LIGHT_SWITCH_ACTIVE,
2245     EL_SIGN_EXCLAMATION,
2246     EL_SIGN_RADIOACTIVITY,
2247     EL_SIGN_STOP,
2248     EL_SIGN_WHEELCHAIR,
2249     EL_SIGN_PARKING,
2250     EL_SIGN_ONEWAY,
2251     EL_SIGN_HEART,
2252     EL_SIGN_TRIANGLE,
2253     EL_SIGN_ROUND,
2254     EL_SIGN_EXIT,
2255     EL_SIGN_YINYANG,
2256     EL_SIGN_OTHER,
2257     EL_STEELWALL_SLIPPERY,
2258     EL_EMC_STEELWALL_1,
2259     EL_EMC_STEELWALL_2,
2260     EL_EMC_STEELWALL_3,
2261     EL_EMC_STEELWALL_4,
2262     EL_CRYSTAL,
2263     EL_GATE_1,
2264     EL_GATE_2,
2265     EL_GATE_3,
2266     EL_GATE_4,
2267     EL_GATE_1_GRAY,
2268     EL_GATE_2_GRAY,
2269     EL_GATE_3_GRAY,
2270     EL_GATE_4_GRAY,
2271     EL_EM_GATE_1,
2272     EL_EM_GATE_2,
2273     EL_EM_GATE_3,
2274     EL_EM_GATE_4,
2275     EL_EM_GATE_1_GRAY,
2276     EL_EM_GATE_2_GRAY,
2277     EL_EM_GATE_3_GRAY,
2278     EL_EM_GATE_4_GRAY,
2279     EL_SWITCHGATE_OPEN,
2280     EL_SWITCHGATE_OPENING,
2281     EL_SWITCHGATE_CLOSED,
2282     EL_SWITCHGATE_CLOSING,
2283     EL_TIMEGATE_OPEN,
2284     EL_TIMEGATE_OPENING,
2285     EL_TIMEGATE_CLOSED,
2286     EL_TIMEGATE_CLOSING,
2287     EL_TUBE_ANY,
2288     EL_TUBE_VERTICAL,
2289     EL_TUBE_HORIZONTAL,
2290     EL_TUBE_VERTICAL_LEFT,
2291     EL_TUBE_VERTICAL_RIGHT,
2292     EL_TUBE_HORIZONTAL_UP,
2293     EL_TUBE_HORIZONTAL_DOWN,
2294     EL_TUBE_LEFT_UP,
2295     EL_TUBE_LEFT_DOWN,
2296     EL_TUBE_RIGHT_UP,
2297     EL_TUBE_RIGHT_DOWN,
2298     -1
2299   };
2300
2301   static int ep_classic_enemy[] =
2302   {
2303     EL_BUG,
2304     EL_SPACESHIP,
2305     EL_BD_BUTTERFLY,
2306     EL_BD_FIREFLY,
2307
2308     EL_YAMYAM,
2309     EL_DARK_YAMYAM,
2310     EL_ROBOT,
2311     EL_PACMAN,
2312     EL_SP_SNIKSNAK,
2313     EL_SP_ELECTRON,
2314     -1
2315   };
2316
2317   static int ep_belt[] =
2318   {
2319     EL_CONVEYOR_BELT_1_LEFT,
2320     EL_CONVEYOR_BELT_1_MIDDLE,
2321     EL_CONVEYOR_BELT_1_RIGHT,
2322     EL_CONVEYOR_BELT_2_LEFT,
2323     EL_CONVEYOR_BELT_2_MIDDLE,
2324     EL_CONVEYOR_BELT_2_RIGHT,
2325     EL_CONVEYOR_BELT_3_LEFT,
2326     EL_CONVEYOR_BELT_3_MIDDLE,
2327     EL_CONVEYOR_BELT_3_RIGHT,
2328     EL_CONVEYOR_BELT_4_LEFT,
2329     EL_CONVEYOR_BELT_4_MIDDLE,
2330     EL_CONVEYOR_BELT_4_RIGHT,
2331     -1
2332   };
2333
2334   static int ep_belt_active[] =
2335   {
2336     EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
2337     EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE,
2338     EL_CONVEYOR_BELT_1_RIGHT_ACTIVE,
2339     EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
2340     EL_CONVEYOR_BELT_2_MIDDLE_ACTIVE,
2341     EL_CONVEYOR_BELT_2_RIGHT_ACTIVE,
2342     EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
2343     EL_CONVEYOR_BELT_3_MIDDLE_ACTIVE,
2344     EL_CONVEYOR_BELT_3_RIGHT_ACTIVE,
2345     EL_CONVEYOR_BELT_4_LEFT_ACTIVE,
2346     EL_CONVEYOR_BELT_4_MIDDLE_ACTIVE,
2347     EL_CONVEYOR_BELT_4_RIGHT_ACTIVE,
2348     -1
2349   };
2350
2351   static int ep_belt_switch[] =
2352   {
2353     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2354     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2355     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2356     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2357     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2358     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2359     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2360     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2361     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2362     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2363     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2364     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2365     -1
2366   };
2367
2368   static int ep_tube[] =
2369   {
2370     EL_TUBE_LEFT_UP,
2371     EL_TUBE_LEFT_DOWN,
2372     EL_TUBE_RIGHT_UP,
2373     EL_TUBE_RIGHT_DOWN,
2374     EL_TUBE_HORIZONTAL,
2375     EL_TUBE_HORIZONTAL_UP,
2376     EL_TUBE_HORIZONTAL_DOWN,
2377     EL_TUBE_VERTICAL,
2378     EL_TUBE_VERTICAL_LEFT,
2379     EL_TUBE_VERTICAL_RIGHT,
2380     EL_TUBE_ANY,
2381     -1
2382   };
2383
2384   static int ep_keygate[] =
2385   {
2386     EL_GATE_1,
2387     EL_GATE_2,
2388     EL_GATE_3,
2389     EL_GATE_4,
2390     EL_GATE_1_GRAY,
2391     EL_GATE_2_GRAY,
2392     EL_GATE_3_GRAY,
2393     EL_GATE_4_GRAY,
2394     EL_EM_GATE_1,
2395     EL_EM_GATE_2,
2396     EL_EM_GATE_3,
2397     EL_EM_GATE_4,
2398     EL_EM_GATE_1_GRAY,
2399     EL_EM_GATE_2_GRAY,
2400     EL_EM_GATE_3_GRAY,
2401     EL_EM_GATE_4_GRAY,
2402     -1
2403   };
2404
2405   static int ep_amoeboid[] =
2406   {
2407     EL_AMOEBA_DEAD,
2408     EL_AMOEBA_WET,
2409     EL_AMOEBA_DRY,
2410     EL_AMOEBA_FULL,
2411     EL_BD_AMOEBA,
2412     -1
2413   };
2414
2415   static int ep_amoebalive[] =
2416   {
2417     EL_AMOEBA_WET,
2418     EL_AMOEBA_DRY,
2419     EL_AMOEBA_FULL,
2420     EL_BD_AMOEBA,
2421     -1
2422   };
2423
2424   static int ep_has_content[] =
2425   {
2426     EL_YAMYAM,
2427     EL_AMOEBA_WET,
2428     EL_AMOEBA_DRY,
2429     EL_AMOEBA_FULL,
2430     EL_BD_AMOEBA,
2431     -1
2432   };
2433
2434   static int ep_active_bomb[] =
2435   {
2436     EL_DYNAMITE_ACTIVE,
2437     EL_DYNABOMB_PLAYER_1_ACTIVE,
2438     EL_DYNABOMB_PLAYER_2_ACTIVE,
2439     EL_DYNABOMB_PLAYER_3_ACTIVE,
2440     EL_DYNABOMB_PLAYER_4_ACTIVE,
2441     EL_SP_DISK_RED_ACTIVE,
2442     -1
2443   };
2444
2445   static int ep_inactive[] =
2446   {
2447     EL_EMPTY,
2448     EL_SAND,
2449     EL_WALL,
2450     EL_BD_WALL,
2451     EL_WALL_SLIPPERY,
2452     EL_STEELWALL,
2453     EL_AMOEBA_DEAD,
2454     EL_QUICKSAND_EMPTY,
2455     EL_STONEBLOCK,
2456     EL_ROBOT_WHEEL,
2457     EL_KEY_1,
2458     EL_KEY_2,
2459     EL_KEY_3,
2460     EL_KEY_4,
2461     EL_EM_KEY_1,
2462     EL_EM_KEY_2,
2463     EL_EM_KEY_3,
2464     EL_EM_KEY_4,
2465     EL_GATE_1,
2466     EL_GATE_2,
2467     EL_GATE_3,
2468     EL_GATE_4,
2469     EL_GATE_1_GRAY,
2470     EL_GATE_2_GRAY,
2471     EL_GATE_3_GRAY,
2472     EL_GATE_4_GRAY,
2473     EL_EM_GATE_1,
2474     EL_EM_GATE_2,
2475     EL_EM_GATE_3,
2476     EL_EM_GATE_4,
2477     EL_EM_GATE_1_GRAY,
2478     EL_EM_GATE_2_GRAY,
2479     EL_EM_GATE_3_GRAY,
2480     EL_EM_GATE_4_GRAY,
2481     EL_DYNAMITE,
2482     EL_INVISIBLE_STEELWALL,
2483     EL_INVISIBLE_WALL,
2484     EL_INVISIBLE_SAND,
2485     EL_LAMP,
2486     EL_LAMP_ACTIVE,
2487     EL_WALL_EMERALD,
2488     EL_WALL_DIAMOND,
2489     EL_WALL_BD_DIAMOND,
2490     EL_WALL_EMERALD_YELLOW,
2491     EL_DYNABOMB_INCREASE_NUMBER,
2492     EL_DYNABOMB_INCREASE_SIZE,
2493     EL_DYNABOMB_INCREASE_POWER,
2494 #if 0
2495     EL_SOKOBAN_OBJECT,
2496 #endif
2497     EL_SOKOBAN_FIELD_EMPTY,
2498     EL_SOKOBAN_FIELD_FULL,
2499     EL_WALL_EMERALD_RED,
2500     EL_WALL_EMERALD_PURPLE,
2501     EL_ACID_POOL_TOPLEFT,
2502     EL_ACID_POOL_TOPRIGHT,
2503     EL_ACID_POOL_BOTTOMLEFT,
2504     EL_ACID_POOL_BOTTOM,
2505     EL_ACID_POOL_BOTTOMRIGHT,
2506     EL_MAGIC_WALL,
2507     EL_MAGIC_WALL_DEAD,
2508     EL_BD_MAGIC_WALL,
2509     EL_BD_MAGIC_WALL_DEAD,
2510     EL_AMOEBA_TO_DIAMOND,
2511     EL_BLOCKED,
2512     EL_SP_EMPTY,
2513     EL_SP_BASE,
2514     EL_SP_PORT_RIGHT,
2515     EL_SP_PORT_DOWN,
2516     EL_SP_PORT_LEFT,
2517     EL_SP_PORT_UP,
2518     EL_SP_GRAVITY_PORT_RIGHT,
2519     EL_SP_GRAVITY_PORT_DOWN,
2520     EL_SP_GRAVITY_PORT_LEFT,
2521     EL_SP_GRAVITY_PORT_UP,
2522     EL_SP_PORT_HORIZONTAL,
2523     EL_SP_PORT_VERTICAL,
2524     EL_SP_PORT_ANY,
2525     EL_SP_DISK_RED,
2526 #if 0
2527     EL_SP_DISK_YELLOW,
2528 #endif
2529     EL_SP_CHIP_SINGLE,
2530     EL_SP_CHIP_LEFT,
2531     EL_SP_CHIP_RIGHT,
2532     EL_SP_CHIP_TOP,
2533     EL_SP_CHIP_BOTTOM,
2534     EL_SP_HARDWARE_GRAY,
2535     EL_SP_HARDWARE_GREEN,
2536     EL_SP_HARDWARE_BLUE,
2537     EL_SP_HARDWARE_RED,
2538     EL_SP_HARDWARE_YELLOW,
2539     EL_SP_HARDWARE_BASE_1,
2540     EL_SP_HARDWARE_BASE_2,
2541     EL_SP_HARDWARE_BASE_3,
2542     EL_SP_HARDWARE_BASE_4,
2543     EL_SP_HARDWARE_BASE_5,
2544     EL_SP_HARDWARE_BASE_6,
2545     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2546     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2547     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2548     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2549     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2550     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2551     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2552     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2553     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2554     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2555     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2556     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2557     EL_SIGN_EXCLAMATION,
2558     EL_SIGN_RADIOACTIVITY,
2559     EL_SIGN_STOP,
2560     EL_SIGN_WHEELCHAIR,
2561     EL_SIGN_PARKING,
2562     EL_SIGN_ONEWAY,
2563     EL_SIGN_HEART,
2564     EL_SIGN_TRIANGLE,
2565     EL_SIGN_ROUND,
2566     EL_SIGN_EXIT,
2567     EL_SIGN_YINYANG,
2568     EL_SIGN_OTHER,
2569     EL_STEELWALL_SLIPPERY,
2570     EL_EMC_STEELWALL_1,
2571     EL_EMC_STEELWALL_2,
2572     EL_EMC_STEELWALL_3,
2573     EL_EMC_STEELWALL_4,
2574     EL_EMC_WALL_1,
2575     EL_EMC_WALL_2,
2576     EL_EMC_WALL_3,
2577     EL_EMC_WALL_4,
2578     EL_EMC_WALL_5,
2579     EL_EMC_WALL_6,
2580     EL_EMC_WALL_7,
2581     EL_EMC_WALL_8,
2582     -1
2583   };
2584
2585   static int ep_em_slippery_wall[] =
2586   {
2587     -1
2588   };
2589
2590   static int ep_gfx_crumbled[] =
2591   {
2592     EL_SAND,
2593     EL_LANDMINE,
2594     EL_TRAP,
2595     EL_TRAP_ACTIVE,
2596     -1
2597   };
2598
2599   static struct
2600   {
2601     int *elements;
2602     int property;
2603   } element_properties[] =
2604   {
2605     { ep_diggable,              EP_DIGGABLE             },
2606     { ep_collectible_only,      EP_COLLECTIBLE_ONLY     },
2607     { ep_dont_run_into,         EP_DONT_RUN_INTO        },
2608     { ep_dont_collide_with,     EP_DONT_COLLIDE_WITH    },
2609     { ep_dont_touch,            EP_DONT_TOUCH           },
2610     { ep_indestructible,        EP_INDESTRUCTIBLE       },
2611     { ep_slippery,              EP_SLIPPERY             },
2612     { ep_can_change,            EP_CAN_CHANGE           },
2613     { ep_can_move,              EP_CAN_MOVE             },
2614     { ep_can_fall,              EP_CAN_FALL             },
2615     { ep_can_smash_player,      EP_CAN_SMASH_PLAYER     },
2616     { ep_can_smash_enemies,     EP_CAN_SMASH_ENEMIES    },
2617     { ep_can_smash_everything,  EP_CAN_SMASH_EVERYTHING },
2618     { ep_can_explode_by_fire,   EP_CAN_EXPLODE_BY_FIRE  },
2619     { ep_can_explode_smashed,   EP_CAN_EXPLODE_SMASHED  },
2620     { ep_can_explode_impact,    EP_CAN_EXPLODE_IMPACT   },
2621     { ep_walkable_over,         EP_WALKABLE_OVER        },
2622     { ep_walkable_inside,       EP_WALKABLE_INSIDE      },
2623     { ep_walkable_under,        EP_WALKABLE_UNDER       },
2624     { ep_passable_over,         EP_PASSABLE_OVER        },
2625     { ep_passable_inside,       EP_PASSABLE_INSIDE      },
2626     { ep_passable_under,        EP_PASSABLE_UNDER       },
2627     { ep_droppable,             EP_DROPPABLE            },
2628     { ep_can_explode_1x1,       EP_CAN_EXPLODE_1X1      },
2629     { ep_pushable,              EP_PUSHABLE             },
2630
2631     { ep_player,                EP_PLAYER               },
2632     { ep_can_pass_magic_wall,   EP_CAN_PASS_MAGIC_WALL  },
2633     { ep_switchable,            EP_SWITCHABLE           },
2634     { ep_bd_element,            EP_BD_ELEMENT           },
2635     { ep_sp_element,            EP_SP_ELEMENT           },
2636     { ep_sb_element,            EP_SB_ELEMENT           },
2637     { ep_gem,                   EP_GEM                  },
2638     { ep_food_dark_yamyam,      EP_FOOD_DARK_YAMYAM     },
2639     { ep_food_penguin,          EP_FOOD_PENGUIN         },
2640     { ep_food_pig,              EP_FOOD_PIG             },
2641     { ep_historic_wall,         EP_HISTORIC_WALL        },
2642     { ep_historic_solid,        EP_HISTORIC_SOLID       },
2643     { ep_classic_enemy,         EP_CLASSIC_ENEMY        },
2644     { ep_belt,                  EP_BELT                 },
2645     { ep_belt_active,           EP_BELT_ACTIVE          },
2646     { ep_belt_switch,           EP_BELT_SWITCH          },
2647     { ep_tube,                  EP_TUBE                 },
2648     { ep_keygate,               EP_KEYGATE              },
2649     { ep_amoeboid,              EP_AMOEBOID             },
2650     { ep_amoebalive,            EP_AMOEBALIVE           },
2651     { ep_has_content,           EP_HAS_CONTENT          },
2652     { ep_active_bomb,           EP_ACTIVE_BOMB          },
2653     { ep_inactive,              EP_INACTIVE             },
2654
2655     { ep_em_slippery_wall,      EP_EM_SLIPPERY_WALL     },
2656
2657     { ep_gfx_crumbled,          EP_GFX_CRUMBLED         },
2658
2659     { NULL,                     -1                      }
2660   };
2661
2662   static int copy_properties[][5] =
2663   {
2664     {
2665       EL_BUG,
2666       EL_BUG_LEFT,              EL_BUG_RIGHT,
2667       EL_BUG_UP,                EL_BUG_DOWN
2668     },
2669     {
2670       EL_SPACESHIP,
2671       EL_SPACESHIP_LEFT,        EL_SPACESHIP_RIGHT,
2672       EL_SPACESHIP_UP,          EL_SPACESHIP_DOWN
2673     },
2674     {
2675       EL_BD_BUTTERFLY,
2676       EL_BD_BUTTERFLY_LEFT,     EL_BD_BUTTERFLY_RIGHT,
2677       EL_BD_BUTTERFLY_UP,       EL_BD_BUTTERFLY_DOWN
2678     },
2679     {
2680       EL_BD_FIREFLY,
2681       EL_BD_FIREFLY_LEFT,       EL_BD_FIREFLY_RIGHT,
2682       EL_BD_FIREFLY_UP,         EL_BD_FIREFLY_DOWN
2683     },
2684     {
2685       EL_PACMAN,
2686       EL_PACMAN_LEFT,           EL_PACMAN_RIGHT,
2687       EL_PACMAN_UP,             EL_PACMAN_DOWN
2688     },
2689     {
2690       -1,
2691       -1, -1, -1, -1
2692     }
2693   };
2694
2695   int i, j, k;
2696
2697   /* always start with reliable default values (element has no properties) */
2698   for (i=0; i < MAX_NUM_ELEMENTS; i++)
2699     for (j=0; j < NUM_ELEMENT_PROPERTIES; j++)
2700       SET_PROPERTY(i, j, FALSE);
2701
2702   /* set all base element properties from above array definitions */
2703   for (i=0; element_properties[i].elements != NULL; i++)
2704     for (j=0; (element_properties[i].elements)[j] != -1; j++)
2705       SET_PROPERTY((element_properties[i].elements)[j],
2706                    element_properties[i].property, TRUE);
2707
2708   /* copy properties to some elements that are only stored in level file */
2709   for (i=0; i < NUM_ELEMENT_PROPERTIES; i++)
2710     for (j=0; copy_properties[j][0] != -1; j++)
2711       if (HAS_PROPERTY(copy_properties[j][0], i))
2712         for (k=1; k<=4; k++)
2713           SET_PROPERTY(copy_properties[j][k], i, TRUE);
2714 }
2715
2716 void InitElementPropertiesEngine(int engine_version)
2717 {
2718 #if 0
2719   static int active_properties[] =
2720   {
2721     EP_AMOEBALIVE,
2722     EP_AMOEBOID,
2723     EP_PFORTE,
2724     EP_DONT_COLLIDE_WITH,
2725     EP_MAUER,
2726     EP_CAN_FALL,
2727     EP_CAN_SMASH,
2728     EP_CAN_PASS_MAGIC_WALL,
2729     EP_CAN_MOVE,
2730     EP_DONT_TOUCH,
2731     EP_DONT_RUN_INTO,
2732     EP_GEM,
2733     EP_CAN_EXPLODE_BY_FIRE,
2734     EP_PUSHABLE,
2735     EP_PLAYER,
2736     EP_HAS_CONTENT,
2737     EP_DIGGABLE,
2738     EP_PASSABLE_INSIDE,
2739     EP_OVER_PLAYER,
2740     EP_ACTIVE_BOMB,
2741
2742     EP_BELT,
2743     EP_BELT_ACTIVE,
2744     EP_BELT_SWITCH,
2745     EP_WALKABLE_UNDER,
2746     EP_EM_SLIPPERY_WALL,
2747   };
2748 #endif
2749
2750   static int no_wall_properties[] =
2751   {
2752     EP_DIGGABLE,
2753     EP_COLLECTIBLE_ONLY,
2754     EP_DONT_RUN_INTO,
2755     EP_DONT_COLLIDE_WITH,
2756     EP_CAN_MOVE,
2757     EP_CAN_FALL,
2758     EP_CAN_SMASH_PLAYER,
2759     EP_CAN_SMASH_ENEMIES,
2760     EP_CAN_SMASH_EVERYTHING,
2761     EP_PUSHABLE,
2762
2763     EP_PLAYER,
2764     EP_GEM,
2765     EP_FOOD_DARK_YAMYAM,
2766     EP_FOOD_PENGUIN,
2767     EP_BELT,
2768     EP_BELT_ACTIVE,
2769     EP_TUBE,
2770     EP_AMOEBOID,
2771     EP_AMOEBALIVE,
2772     EP_ACTIVE_BOMB,
2773
2774     EP_ACCESSIBLE,
2775     -1
2776   };
2777
2778   int i, j;
2779
2780 #if 0
2781   InitElementPropertiesStatic();
2782 #endif
2783
2784   /* set all special, combined or engine dependent element properties */
2785   for (i=0; i < MAX_NUM_ELEMENTS; i++)
2786   {
2787 #if 0
2788     for (j=EP_ACCESSIBLE_OVER; j < NUM_ELEMENT_PROPERTIES; j++)
2789       SET_PROPERTY(i, j, FALSE);
2790 #endif
2791
2792     /* ---------- INACTIVE ------------------------------------------------- */
2793     if (i >= EL_CHAR_START && i <= EL_CHAR_END)
2794       SET_PROPERTY(i, EP_INACTIVE, TRUE);
2795
2796     /* ---------- WALKABLE, PASSABLE, ACCESSIBLE --------------------------- */
2797     SET_PROPERTY(i, EP_WALKABLE, (IS_WALKABLE_OVER(i) ||
2798                                   IS_WALKABLE_INSIDE(i) ||
2799                                   IS_WALKABLE_UNDER(i)));
2800
2801     SET_PROPERTY(i, EP_PASSABLE, (IS_PASSABLE_OVER(i) ||
2802                                   IS_PASSABLE_INSIDE(i) ||
2803                                   IS_PASSABLE_UNDER(i)));
2804
2805     SET_PROPERTY(i, EP_ACCESSIBLE_OVER, (IS_WALKABLE_OVER(i) ||
2806                                          IS_PASSABLE_OVER(i)));
2807
2808     SET_PROPERTY(i, EP_ACCESSIBLE_INSIDE, (IS_WALKABLE_INSIDE(i) ||
2809                                            IS_PASSABLE_INSIDE(i)));
2810
2811     SET_PROPERTY(i, EP_ACCESSIBLE_UNDER, (IS_WALKABLE_UNDER(i) ||
2812                                           IS_PASSABLE_UNDER(i)));
2813
2814     SET_PROPERTY(i, EP_ACCESSIBLE, (IS_WALKABLE(i) ||
2815                                     IS_PASSABLE(i)));
2816
2817     /* ---------- COLLECTIBLE ---------------------------------------------- */
2818     SET_PROPERTY(i, EP_COLLECTIBLE, (IS_COLLECTIBLE_ONLY(i) ||
2819                                      IS_DROPPABLE(i)));
2820
2821     /* ---------- SNAPPABLE ------------------------------------------------ */
2822     SET_PROPERTY(i, EP_SNAPPABLE, (IS_DIGGABLE(i) ||
2823                                    IS_COLLECTIBLE(i) ||
2824                                    IS_SWITCHABLE(i) ||
2825                                    i == EL_BD_ROCK));
2826
2827     /* ---------- WALL ----------------------------------------------------- */
2828     SET_PROPERTY(i, EP_WALL, TRUE);     /* default: element is wall */
2829
2830     for (j=0; no_wall_properties[j] != -1; j++)
2831       if (HAS_PROPERTY(i, no_wall_properties[j]) ||
2832           i >= EL_FIRST_RUNTIME_UNREAL)
2833         SET_PROPERTY(i, EP_WALL, FALSE);
2834
2835     if (IS_HISTORIC_WALL(i))
2836       SET_PROPERTY(i, EP_WALL, TRUE);
2837
2838     /* ---------- SOLID_FOR_PUSHING ---------------------------------------- */
2839     if (engine_version < VERSION_IDENT(2,2,0))
2840       SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, IS_HISTORIC_SOLID(i));
2841     else
2842       SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, (!IS_WALKABLE(i) &&
2843                                              !IS_DIGGABLE(i) &&
2844                                              !IS_COLLECTIBLE(i)));
2845
2846     /* ---------- DRAGONFIRE_PROOF ----------------------------------------- */
2847
2848     if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
2849       SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE);
2850     else
2851       SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_CUSTOM_ELEMENT(i) &&
2852                                             IS_INDESTRUCTIBLE(i)));
2853
2854     /* ---------- EXPLOSION_PROOF ------------------------------------------ */
2855     if (i == EL_FLAMES)
2856       SET_PROPERTY(i, EP_EXPLOSION_PROOF, TRUE);
2857     else if (engine_version < VERSION_IDENT(2,2,0))
2858       SET_PROPERTY(i, EP_EXPLOSION_PROOF, IS_INDESTRUCTIBLE(i));
2859     else
2860       SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
2861                                            !IS_WALKABLE_OVER(i) &&
2862                                            !IS_WALKABLE_UNDER(i)));
2863
2864     if (IS_CUSTOM_ELEMENT(i))
2865     {
2866       /* ---------- DONT_COLLIDE_WITH / DONT_RUN_INTO ---------------------- */
2867       if (DONT_TOUCH(i))
2868         SET_PROPERTY(i, EP_DONT_COLLIDE_WITH, TRUE);
2869       if (DONT_COLLIDE_WITH(i))
2870         SET_PROPERTY(i, EP_DONT_RUN_INTO, TRUE);
2871
2872       /* ---------- CAN_SMASH_ENEMIES / CAN_SMASH_PLAYER ------------------- */
2873       if (CAN_SMASH_EVERYTHING(i))
2874         SET_PROPERTY(i, EP_CAN_SMASH_ENEMIES, TRUE);
2875       if (CAN_SMASH_ENEMIES(i))
2876         SET_PROPERTY(i, EP_CAN_SMASH_PLAYER, TRUE);
2877     }
2878
2879     /* ---------- CAN_SMASH ------------------------------------------------ */
2880     SET_PROPERTY(i, EP_CAN_SMASH, (CAN_SMASH_PLAYER(i) ||
2881                                    CAN_SMASH_ENEMIES(i) ||
2882                                    CAN_SMASH_EVERYTHING(i)));
2883
2884     /* ---------- CAN_EXPLODE ---------------------------------------------- */
2885     SET_PROPERTY(i, EP_CAN_EXPLODE, (CAN_EXPLODE_BY_FIRE(i) ||
2886                                      CAN_EXPLODE_SMASHED(i) ||
2887                                      CAN_EXPLODE_IMPACT(i)));
2888
2889     /* ---------- CAN_EXPLODE_3X3 ------------------------------------------ */
2890     SET_PROPERTY(i, EP_CAN_EXPLODE_3X3, (CAN_EXPLODE(i) &&
2891                                          !CAN_EXPLODE_1X1(i)));
2892
2893     /* ---------- CAN_CHANGE ----------------------------------------------- */
2894     SET_PROPERTY(i, EP_CAN_CHANGE, FALSE);      /* default: cannot change */
2895     for (j=0; j < element_info[i].num_change_pages; j++)
2896       if (element_info[i].change_page[j].can_change)
2897         SET_PROPERTY(i, EP_CAN_CHANGE, TRUE);
2898
2899     /* ---------- GFX_CRUMBLED --------------------------------------------- */
2900     SET_PROPERTY(i, EP_GFX_CRUMBLED,
2901                  element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
2902   }
2903
2904 #if 0
2905   /* determine inactive elements (used for engine main loop optimization) */
2906   for (i=0; i < MAX_NUM_ELEMENTS; i++)
2907   {
2908     boolean active = FALSE;
2909
2910     for (j=0; i < NUM_ELEMENT_PROPERTIES; j++)
2911     {
2912       if (HAS_PROPERTY(i, j))
2913         active = TRUE;
2914     }
2915
2916 #if 0
2917     if (!active)
2918       SET_PROPERTY(i, EP_INACTIVE, TRUE);
2919 #endif
2920   }
2921 #endif
2922
2923   /* dynamically adjust element properties according to game engine version */
2924   {
2925     static int ep_em_slippery_wall[] =
2926     {
2927       EL_STEELWALL,
2928       EL_WALL,
2929       EL_EXPANDABLE_WALL,
2930       EL_EXPANDABLE_WALL_HORIZONTAL,
2931       EL_EXPANDABLE_WALL_VERTICAL,
2932       EL_EXPANDABLE_WALL_ANY,
2933       -1
2934     };
2935
2936     /* special EM style gems behaviour */
2937     for (i=0; ep_em_slippery_wall[i] != -1; i++)
2938       SET_PROPERTY(ep_em_slippery_wall[i], EP_EM_SLIPPERY_WALL,
2939                    level.em_slippery_gems);
2940
2941     /* "EL_EXPANDABLE_WALL_GROWING" wasn't slippery for EM gems in 2.0.1 */
2942     SET_PROPERTY(EL_EXPANDABLE_WALL_GROWING, EP_EM_SLIPPERY_WALL,
2943                  (level.em_slippery_gems &&
2944                   engine_version > VERSION_IDENT(2,0,1)));
2945   }
2946
2947 #if 0
2948   /* dynamically adjust element properties according to game engine version */
2949 #if 0
2950   if (engine_version < RELEASE_IDENT(2,2,0,7))
2951 #endif
2952   {
2953     for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
2954     {
2955       int element = EL_CUSTOM_START + i;
2956
2957       element_info[element].push_delay_fixed = 2;
2958       element_info[element].push_delay_random = 8;
2959     }
2960   }
2961 #endif
2962 }
2963
2964 static void InitGlobal()
2965 {
2966   global.autoplay_leveldir = NULL;
2967
2968   global.frames_per_second = 0;
2969   global.fps_slowdown = FALSE;
2970   global.fps_slowdown_factor = 1;
2971 }
2972
2973 void Execute_Command(char *command)
2974 {
2975   if (strcmp(command, "print graphicsinfo.conf") == 0)
2976   {
2977     int i;
2978
2979     printf("# You can configure additional/alternative image files here.\n");
2980     printf("# (The images below are default and therefore commented out.)\n");
2981     printf("\n");
2982     printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
2983     printf("\n");
2984     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2985     printf("\n");
2986
2987     for (i=0; image_config[i].token != NULL; i++)
2988       printf("# %s\n",
2989              getFormattedSetupEntry(image_config[i].token,
2990                                     image_config[i].value));
2991
2992     exit(0);
2993   }
2994   else if (strcmp(command, "print soundsinfo.conf") == 0)
2995   {
2996     int i;
2997
2998     printf("# You can configure additional/alternative sound files here.\n");
2999     printf("# (The sounds below are default and therefore commented out.)\n");
3000     printf("\n");
3001     printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
3002     printf("\n");
3003     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
3004     printf("\n");
3005
3006     for (i=0; sound_config[i].token != NULL; i++)
3007       printf("# %s\n",
3008              getFormattedSetupEntry(sound_config[i].token,
3009                                     sound_config[i].value));
3010
3011     exit(0);
3012   }
3013   else if (strcmp(command, "print musicinfo.conf") == 0)
3014   {
3015     printf("# (Currently only \"name\" and \"sort_priority\" recognized.)\n");
3016     printf("\n");
3017     printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
3018     printf("\n");
3019     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
3020
3021     exit(0);
3022   }
3023   else if (strncmp(command, "dump level ", 11) == 0)
3024   {
3025     char *filename = &command[11];
3026
3027     if (access(filename, F_OK) != 0)
3028       Error(ERR_EXIT, "cannot open file '%s'", filename);
3029
3030     LoadLevelFromFilename(&level, filename);
3031     DumpLevel(&level);
3032
3033     exit(0);
3034   }
3035   else if (strncmp(command, "dump tape ", 10) == 0)
3036   {
3037     char *filename = &command[10];
3038
3039     if (access(filename, F_OK) != 0)
3040       Error(ERR_EXIT, "cannot open file '%s'", filename);
3041
3042     LoadTapeFromFilename(filename);
3043     DumpTape(&tape);
3044
3045     exit(0);
3046   }
3047   else if (strncmp(command, "autoplay ", 9) == 0)
3048   {
3049     char *str_copy = getStringCopy(&command[9]);
3050     char *str_ptr = strchr(str_copy, ' ');
3051
3052     global.autoplay_leveldir = str_copy;
3053     global.autoplay_level_nr = -1;
3054
3055     if (str_ptr != NULL)
3056     {
3057       *str_ptr++ = '\0';                        /* terminate leveldir string */
3058       global.autoplay_level_nr = atoi(str_ptr); /* get level_nr value */
3059     }
3060   }
3061   else
3062   {
3063     Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
3064   }
3065 }
3066
3067 static void InitSetup()
3068 {
3069   LoadSetup();                                  /* global setup info */
3070
3071   /* set some options from setup file */
3072
3073   if (setup.options.verbose)
3074     options.verbose = TRUE;
3075 }
3076
3077 static void InitPlayerInfo()
3078 {
3079   int i;
3080
3081   /* choose default local player */
3082   local_player = &stored_player[0];
3083
3084   for (i=0; i<MAX_PLAYERS; i++)
3085     stored_player[i].connected = FALSE;
3086
3087   local_player->connected = TRUE;
3088 }
3089
3090 static void InitArtworkInfo()
3091 {
3092   LoadArtworkInfo();
3093 }
3094
3095 static char *get_string_in_brackets(char *string)
3096 {
3097   char *string_in_brackets = checked_malloc(strlen(string) + 3);
3098
3099   sprintf(string_in_brackets, "[%s]", string);
3100
3101   return string_in_brackets;
3102 }
3103
3104 #if 0
3105 static char *get_element_class_token(int element)
3106 {
3107   char *element_class_name = element_info[element].class_name;
3108   char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
3109
3110   sprintf(element_class_token, "[%s]", element_class_name);
3111
3112   return element_class_token;
3113 }
3114
3115 static char *get_action_class_token(int action)
3116 {
3117   char *action_class_name = &element_action_info[action].suffix[1];
3118   char *action_class_token = checked_malloc(strlen(action_class_name) + 3);
3119
3120   sprintf(action_class_token, "[%s]", action_class_name);
3121
3122   return action_class_token;
3123 }
3124 #endif
3125
3126 static void InitArtworkConfig()
3127 {
3128   static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
3129   static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + 1];
3130   static char *action_id_suffix[NUM_ACTIONS + 1];
3131   static char *direction_id_suffix[NUM_DIRECTIONS + 1];
3132   static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
3133   static char *dummy[1] = { NULL };
3134   static char *ignore_generic_tokens[] =
3135   {
3136     "name",
3137     "sort_priority",
3138     NULL
3139   };
3140   static char **ignore_image_tokens, **ignore_sound_tokens;
3141   int num_ignore_generic_tokens;
3142   int num_ignore_image_tokens, num_ignore_sound_tokens;
3143   int i;
3144
3145   /* dynamically determine list of generic tokens to be ignored */
3146   num_ignore_generic_tokens = 0;
3147   for (i=0; ignore_generic_tokens[i] != NULL; i++)
3148     num_ignore_generic_tokens++;
3149
3150   /* dynamically determine list of image tokens to be ignored */
3151   num_ignore_image_tokens = num_ignore_generic_tokens;
3152   for (i=0; image_config_vars[i].token != NULL; i++)
3153     num_ignore_image_tokens++;
3154   ignore_image_tokens =
3155     checked_malloc((num_ignore_image_tokens + 1) * sizeof(char *));
3156   for (i=0; i < num_ignore_generic_tokens; i++)
3157     ignore_image_tokens[i] = ignore_generic_tokens[i];
3158   for (i=0; i < num_ignore_image_tokens - num_ignore_generic_tokens; i++)
3159     ignore_image_tokens[num_ignore_generic_tokens + i] =
3160       image_config_vars[i].token;
3161   ignore_image_tokens[num_ignore_image_tokens] = NULL;
3162
3163   /* dynamically determine list of sound tokens to be ignored */
3164   num_ignore_sound_tokens = num_ignore_generic_tokens;
3165   ignore_sound_tokens =
3166     checked_malloc((num_ignore_sound_tokens + 1) * sizeof(char *));
3167   for (i=0; i < num_ignore_generic_tokens; i++)
3168     ignore_sound_tokens[i] = ignore_generic_tokens[i];
3169   ignore_sound_tokens[num_ignore_sound_tokens] = NULL;
3170
3171   for (i=0; i<MAX_NUM_ELEMENTS; i++)
3172     image_id_prefix[i] = element_info[i].token_name;
3173   for (i=0; i<NUM_FONTS; i++)
3174     image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
3175   image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
3176
3177   for (i=0; i<MAX_NUM_ELEMENTS; i++)
3178     sound_id_prefix[i] = element_info[i].token_name;
3179   for (i=0; i<MAX_NUM_ELEMENTS; i++)
3180     sound_id_prefix[MAX_NUM_ELEMENTS + i] =
3181       get_string_in_brackets(element_info[i].class_name);
3182   sound_id_prefix[2 * MAX_NUM_ELEMENTS] = NULL;
3183
3184   for (i=0; i<NUM_ACTIONS; i++)
3185     action_id_suffix[i] = element_action_info[i].suffix;
3186   action_id_suffix[NUM_ACTIONS] = NULL;
3187
3188   for (i=0; i<NUM_DIRECTIONS; i++)
3189     direction_id_suffix[i] = element_direction_info[i].suffix;
3190   direction_id_suffix[NUM_DIRECTIONS] = NULL;
3191
3192   for (i=0; i<NUM_SPECIAL_GFX_ARGS; i++)
3193     special_id_suffix[i] = special_suffix_info[i].suffix;
3194   special_id_suffix[NUM_SPECIAL_GFX_ARGS] = NULL;
3195
3196   InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
3197                 image_id_prefix, action_id_suffix, direction_id_suffix,
3198                 special_id_suffix, ignore_image_tokens);
3199   InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
3200                 sound_id_prefix, action_id_suffix, dummy,
3201                 special_id_suffix, ignore_sound_tokens);
3202 }
3203
3204 static void InitMixer()
3205 {
3206   OpenAudio();
3207   StartMixer();
3208 }
3209
3210 void InitGfx()
3211 {
3212   char *filename_font_initial = NULL;
3213   Bitmap *bitmap_font_initial = NULL;
3214   int i, j;
3215
3216   /* determine settings for initial font (for displaying startup messages) */
3217   for (i=0; image_config[i].token != NULL; i++)
3218   {
3219     for (j=0; j < NUM_INITIAL_FONTS; j++)
3220     {
3221       char font_token[128];
3222       int len_font_token;
3223
3224       sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1);
3225       len_font_token = strlen(font_token);
3226
3227       if (strcmp(image_config[i].token, font_token) == 0)
3228         filename_font_initial = image_config[i].value;
3229       else if (strlen(image_config[i].token) > len_font_token &&
3230                strncmp(image_config[i].token, font_token, len_font_token) == 0)
3231       {
3232         if (strcmp(&image_config[i].token[len_font_token], ".x") == 0)
3233           font_initial[j].src_x = atoi(image_config[i].value);
3234         else if (strcmp(&image_config[i].token[len_font_token], ".y") == 0)
3235           font_initial[j].src_y = atoi(image_config[i].value);
3236         else if (strcmp(&image_config[i].token[len_font_token], ".width") == 0)
3237           font_initial[j].width = atoi(image_config[i].value);
3238         else if (strcmp(&image_config[i].token[len_font_token],".height") == 0)
3239           font_initial[j].height = atoi(image_config[i].value);
3240       }
3241     }
3242   }
3243
3244   for (j=0; j < NUM_INITIAL_FONTS; j++)
3245   {
3246     font_initial[j].num_chars = DEFAULT_NUM_CHARS_PER_FONT;
3247     font_initial[j].num_chars_per_line = DEFAULT_NUM_CHARS_PER_LINE;
3248   }
3249
3250   if (filename_font_initial == NULL)    /* should not happen */
3251     Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
3252
3253   /* create additional image buffers for double-buffering */
3254   bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
3255   bitmap_db_door  = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
3256
3257   /* initialize screen properties */
3258   InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
3259                    REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
3260                    bitmap_db_field);
3261   InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
3262   InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
3263   InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
3264
3265   bitmap_font_initial = LoadCustomImage(filename_font_initial);
3266
3267   for (j=0; j < NUM_INITIAL_FONTS; j++)
3268     font_initial[j].bitmap = bitmap_font_initial;
3269
3270   InitFontGraphicInfo();
3271
3272   DrawInitText(WINDOW_TITLE_STRING, 20, FC_YELLOW);
3273   DrawInitText(WINDOW_SUBTITLE_STRING, 50, FC_RED);
3274
3275   DrawInitText("Loading graphics:", 120, FC_GREEN);
3276
3277   InitTileClipmasks();
3278 }
3279
3280 void InitGfxBackground()
3281 {
3282   int x, y;
3283
3284   drawto = backbuffer;
3285   fieldbuffer = bitmap_db_field;
3286   SetDrawtoField(DRAW_BACKBUFFER);
3287
3288   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
3289              0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3290   ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
3291   ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
3292
3293   for (x=0; x<MAX_BUF_XSIZE; x++)
3294     for (y=0; y<MAX_BUF_YSIZE; y++)
3295       redraw[x][y] = 0;
3296   redraw_tiles = 0;
3297   redraw_mask = REDRAW_ALL;
3298 }
3299
3300 static void InitLevelInfo()
3301 {
3302   LoadLevelInfo();                              /* global level info */
3303   LoadLevelSetup_LastSeries();                  /* last played series info */
3304   LoadLevelSetup_SeriesInfo();                  /* last played level info */
3305 }
3306
3307 void InitLevelArtworkInfo()
3308 {
3309   LoadLevelArtworkInfo();
3310 }
3311
3312 static void InitImages()
3313 {
3314 #if 1
3315   setLevelArtworkDir(artwork.gfx_first);
3316 #endif
3317
3318 #if 0
3319   printf("::: InitImages for '%s' ['%s', '%s'] ['%s', '%s']\n",
3320          leveldir_current->identifier,
3321          artwork.gfx_current_identifier,
3322          artwork.gfx_current->identifier,
3323          leveldir_current->graphics_set,
3324          leveldir_current->graphics_path);
3325 #endif
3326
3327   ReloadCustomImages();
3328
3329   LoadCustomElementDescriptions();
3330   LoadSpecialMenuDesignSettings();
3331
3332   ReinitializeGraphics();
3333 }
3334
3335 static void InitSound(char *identifier)
3336 {
3337   if (identifier == NULL)
3338     identifier = artwork.snd_current->identifier;
3339
3340 #if 1
3341   /* set artwork path to send it to the sound server process */
3342   setLevelArtworkDir(artwork.snd_first);
3343 #endif
3344
3345   InitReloadCustomSounds(identifier);
3346   ReinitializeSounds();
3347 }
3348
3349 static void InitMusic(char *identifier)
3350 {
3351   if (identifier == NULL)
3352     identifier = artwork.mus_current->identifier;
3353
3354 #if 1
3355   /* set artwork path to send it to the sound server process */
3356   setLevelArtworkDir(artwork.mus_first);
3357 #endif
3358
3359   InitReloadCustomMusic(identifier);
3360   ReinitializeMusic();
3361 }
3362
3363 void InitNetworkServer()
3364 {
3365 #if defined(PLATFORM_UNIX)
3366   int nr_wanted;
3367 #endif
3368
3369   if (!options.network)
3370     return;
3371
3372 #if defined(PLATFORM_UNIX)
3373   nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
3374
3375   if (!ConnectToServer(options.server_host, options.server_port))
3376     Error(ERR_EXIT, "cannot connect to network game server");
3377
3378   SendToServer_PlayerName(setup.player_name);
3379   SendToServer_ProtocolVersion();
3380
3381   if (nr_wanted)
3382     SendToServer_NrWanted(nr_wanted);
3383 #endif
3384 }
3385
3386 static char *getNewArtworkIdentifier(int type)
3387 {
3388   static char *leveldir_current_identifier[3] = { NULL, NULL, NULL };
3389   static boolean last_override_level_artwork[3] = { FALSE, FALSE, FALSE };
3390   static boolean last_has_level_artwork_set[3] = { FALSE, FALSE, FALSE };
3391   static boolean initialized[3] = { FALSE, FALSE, FALSE };
3392   TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
3393   boolean setup_override_artwork = SETUP_OVERRIDE_ARTWORK(setup, type);
3394   char *setup_artwork_set = SETUP_ARTWORK_SET(setup, type);
3395   char *leveldir_identifier = leveldir_current->identifier;
3396 #if 1
3397   /* !!! setLevelArtworkDir() should be moved to an earlier stage !!! */
3398   char *leveldir_artwork_set = setLevelArtworkDir(artwork_first_node);
3399 #else
3400   char *leveldir_artwork_set = LEVELDIR_ARTWORK_SET(leveldir_current, type);
3401 #endif
3402   boolean has_level_artwork_set = (leveldir_artwork_set != NULL);
3403   char *artwork_current_identifier;
3404   char *artwork_new_identifier = NULL;  /* default: nothing has changed */
3405
3406   /* leveldir_current may be invalid (level group, parent link) */
3407   if (!validLevelSeries(leveldir_current))
3408     return NULL;
3409
3410   /* 1st step: determine artwork set to be activated in descending order:
3411      --------------------------------------------------------------------
3412      1. setup artwork (when configured to override everything else)
3413      2. artwork set configured in "levelinfo.conf" of current level set
3414         (artwork in level directory will have priority when loading later)
3415      3. artwork in level directory (stored in artwork sub-directory)
3416      4. setup artwork (currently configured in setup menu) */
3417
3418   if (setup_override_artwork)
3419     artwork_current_identifier = setup_artwork_set;
3420   else if (leveldir_artwork_set != NULL)
3421     artwork_current_identifier = leveldir_artwork_set;
3422   else if (getTreeInfoFromIdentifier(artwork_first_node, leveldir_identifier))
3423     artwork_current_identifier = leveldir_identifier;
3424   else
3425     artwork_current_identifier = setup_artwork_set;
3426
3427
3428   /* 2nd step: check if it is really needed to reload artwork set
3429      ------------------------------------------------------------ */
3430
3431 #if 0
3432   if (type == ARTWORK_TYPE_GRAPHICS)
3433     printf("::: 0: '%s' ['%s', '%s'] ['%s' ('%s')]\n",
3434            artwork_new_identifier,
3435            ARTWORK_CURRENT_IDENTIFIER(artwork, type),
3436            artwork_current_identifier,
3437            leveldir_current->graphics_set,
3438            leveldir_current->identifier);
3439 #endif
3440
3441   /* ---------- reload if level set and also artwork set has changed ------- */
3442   if (leveldir_current_identifier[type] != leveldir_identifier &&
3443       (last_has_level_artwork_set[type] || has_level_artwork_set))
3444     artwork_new_identifier = artwork_current_identifier;
3445
3446   leveldir_current_identifier[type] = leveldir_identifier;
3447   last_has_level_artwork_set[type] = has_level_artwork_set;
3448
3449 #if 0
3450   if (type == ARTWORK_TYPE_GRAPHICS)
3451     printf("::: 1: '%s'\n", artwork_new_identifier);
3452 #endif
3453
3454   /* ---------- reload if "override artwork" setting has changed ----------- */
3455   if (last_override_level_artwork[type] != setup_override_artwork)
3456     artwork_new_identifier = artwork_current_identifier;
3457
3458   last_override_level_artwork[type] = setup_override_artwork;
3459
3460 #if 0
3461   if (type == ARTWORK_TYPE_GRAPHICS)
3462     printf("::: 2: '%s'\n", artwork_new_identifier);
3463 #endif
3464
3465   /* ---------- reload if current artwork identifier has changed ----------- */
3466   if (strcmp(ARTWORK_CURRENT_IDENTIFIER(artwork, type),
3467              artwork_current_identifier) != 0)
3468     artwork_new_identifier = artwork_current_identifier;
3469
3470   *(&(ARTWORK_CURRENT_IDENTIFIER(artwork, type))) = artwork_current_identifier;
3471
3472 #if 0
3473   if (type == ARTWORK_TYPE_GRAPHICS)
3474     printf("::: 3: '%s'\n", artwork_new_identifier);
3475 #endif
3476
3477   /* ---------- do not reload directly after starting ---------------------- */
3478   if (!initialized[type])
3479     artwork_new_identifier = NULL;
3480
3481   initialized[type] = TRUE;
3482
3483 #if 0
3484   if (type == ARTWORK_TYPE_GRAPHICS)
3485     printf("::: 4: '%s'\n", artwork_new_identifier);
3486 #endif
3487
3488 #if 0
3489   if (type == ARTWORK_TYPE_GRAPHICS)
3490     printf("CHECKING OLD/NEW GFX:\n- OLD: %s\n- NEW: %s ['%s', '%s'] ['%s']\n",
3491            artwork.gfx_current_identifier, artwork_current_identifier,
3492            artwork.gfx_current->identifier, leveldir_current->graphics_set,
3493            artwork_new_identifier);
3494 #endif
3495
3496   return artwork_new_identifier;
3497 }
3498
3499 void ReloadCustomArtwork()
3500 {
3501   char *gfx_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_GRAPHICS);
3502   char *snd_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_SOUNDS);
3503   char *mus_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_MUSIC);
3504   boolean redraw_screen = FALSE;
3505
3506   if (gfx_new_identifier != NULL)
3507   {
3508 #if 0
3509     printf("RELOADING GRAPHICS '%s' -> '%s' ['%s', '%s']\n",
3510            artwork.gfx_current_identifier,
3511            gfx_new_identifier,
3512            artwork.gfx_current->identifier,
3513            leveldir_current->graphics_set);
3514 #endif
3515
3516     ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3517
3518     InitImages();
3519
3520 #if 0
3521     printf("... '%s'\n",
3522            leveldir_current->graphics_set);
3523 #endif
3524
3525     FreeTileClipmasks();
3526     InitTileClipmasks();
3527
3528     redraw_screen = TRUE;
3529   }
3530
3531   if (snd_new_identifier != NULL)
3532   {
3533     ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3534
3535     InitSound(snd_new_identifier);
3536
3537     redraw_screen = TRUE;
3538   }
3539
3540   if (mus_new_identifier != NULL)
3541   {
3542     ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
3543
3544     InitMusic(mus_new_identifier);
3545
3546     redraw_screen = TRUE;
3547   }
3548
3549   if (redraw_screen)
3550   {
3551     InitGfxBackground();
3552
3553     /* force redraw of (open or closed) door graphics */
3554     SetDoorState(DOOR_OPEN_ALL);
3555     CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
3556   }
3557 }
3558
3559 void KeyboardAutoRepeatOffUnlessAutoplay()
3560 {
3561   if (global.autoplay_leveldir == NULL)
3562     KeyboardAutoRepeatOff();
3563 }
3564
3565
3566 /* ========================================================================= */
3567 /* OpenAll()                                                                 */
3568 /* ========================================================================= */
3569
3570 void OpenAll()
3571 {
3572   InitGlobal();         /* initialize some global variables */
3573
3574   if (options.execute_command)
3575     Execute_Command(options.execute_command);
3576
3577   if (options.serveronly)
3578   {
3579 #if defined(PLATFORM_UNIX)
3580     NetworkServer(options.server_port, options.serveronly);
3581 #else
3582     Error(ERR_WARN, "networking only supported in Unix version");
3583 #endif
3584     exit(0);    /* never reached */
3585   }
3586
3587   InitSetup();
3588
3589   InitPlayerInfo();
3590   InitArtworkInfo();            /* needed before loading gfx, sound & music */
3591   InitArtworkConfig();          /* needed before forking sound child process */
3592   InitMixer();
3593
3594   InitCounter();
3595
3596   InitRND(NEW_RANDOMIZE);
3597   InitSimpleRND(NEW_RANDOMIZE);
3598
3599   InitJoysticks();
3600
3601   InitVideoDisplay();
3602   InitVideoBuffer(&backbuffer, &window, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH,
3603                   setup.fullscreen);
3604
3605   InitEventFilter(FilterMouseMotionEvents);
3606
3607   InitElementPropertiesStatic();
3608   InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
3609
3610   InitGfx();
3611
3612   InitLevelInfo();
3613   InitLevelArtworkInfo();
3614
3615   InitImages();                 /* needs to know current level directory */
3616   InitSound(NULL);              /* needs to know current level directory */
3617   InitMusic(NULL);              /* needs to know current level directory */
3618
3619   InitGfxBackground();
3620
3621   if (global.autoplay_leveldir)
3622   {
3623     AutoPlayTape();
3624     return;
3625   }
3626
3627   game_status = GAME_MODE_MAIN;
3628
3629   DrawMainMenu();
3630
3631   InitNetworkServer();
3632 }
3633
3634 void CloseAllAndExit(int exit_value)
3635 {
3636   StopSounds();
3637   FreeAllSounds();
3638   FreeAllMusic();
3639   CloseAudio();         /* called after freeing sounds (needed for SDL) */
3640
3641   FreeAllImages();
3642   FreeTileClipmasks();
3643
3644   CloseVideoDisplay();
3645   ClosePlatformDependentStuff();
3646
3647   exit(exit_value);
3648 }