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