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