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