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