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