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