9b2e9ea702ec7fa57275dfb29f9c05641ad8f998
[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_go_to' !!! */
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[] =
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     /* only stored in level file */
1306     EL_BUG_RIGHT,
1307     EL_BUG_UP,
1308     EL_BUG_LEFT,
1309     EL_BUG_DOWN,
1310     EL_SPACESHIP_RIGHT,
1311     EL_SPACESHIP_UP,
1312     EL_SPACESHIP_LEFT,
1313     EL_SPACESHIP_DOWN,
1314     EL_BD_BUTTERFLY_RIGHT,
1315     EL_BD_BUTTERFLY_UP,
1316     EL_BD_BUTTERFLY_LEFT,
1317     EL_BD_BUTTERFLY_DOWN,
1318     EL_BD_FIREFLY_RIGHT,
1319     EL_BD_FIREFLY_UP,
1320     EL_BD_FIREFLY_LEFT,
1321     EL_BD_FIREFLY_DOWN,
1322     EL_PACMAN_RIGHT,
1323     EL_PACMAN_UP,
1324     EL_PACMAN_LEFT,
1325     EL_PACMAN_DOWN,
1326
1327     /* level file and runtime elements */
1328     EL_BUG,
1329     EL_SPACESHIP,
1330     EL_BD_BUTTERFLY,
1331     EL_BD_FIREFLY,
1332     EL_YAMYAM,
1333     EL_DARK_YAMYAM,
1334     EL_ROBOT,
1335     EL_PACMAN,
1336     EL_MOLE,
1337     EL_PENGUIN,
1338     EL_PIG,
1339     EL_DRAGON,
1340     EL_SATELLITE,
1341     EL_SP_SNIKSNAK,
1342     EL_SP_ELECTRON,
1343     EL_BALLOON,
1344     EL_SPRING,
1345     -1
1346   };
1347
1348   static int ep_can_fall[] =
1349   {
1350     EL_ROCK,
1351     EL_BD_ROCK,
1352     EL_EMERALD,
1353     EL_BD_DIAMOND,
1354     EL_EMERALD_YELLOW,
1355     EL_EMERALD_RED,
1356     EL_EMERALD_PURPLE,
1357     EL_DIAMOND,
1358     EL_BOMB,
1359     EL_NUT,
1360     EL_AMOEBA_DROP,
1361     EL_QUICKSAND_FULL,
1362     EL_MAGIC_WALL_FULL,
1363     EL_BD_MAGIC_WALL_FULL,
1364     EL_TIME_ORB_FULL,
1365     EL_TIME_ORB_EMPTY,
1366     EL_SP_ZONK,
1367     EL_SP_INFOTRON,
1368     EL_SP_DISK_ORANGE,
1369     EL_PEARL,
1370     EL_CRYSTAL,
1371     EL_SPRING,
1372     EL_DX_SUPABOMB,
1373     -1
1374   };
1375
1376   static int ep_can_smash[] =
1377   {
1378     EL_ROCK,
1379     EL_BD_ROCK,
1380     EL_EMERALD,
1381     EL_BD_DIAMOND,
1382     EL_EMERALD_YELLOW,
1383     EL_EMERALD_RED,
1384     EL_EMERALD_PURPLE,
1385     EL_DIAMOND,
1386     EL_BOMB,
1387     EL_NUT,
1388     EL_AMOEBA_DROP,
1389     EL_TIME_ORB_FULL,
1390     EL_TIME_ORB_EMPTY,
1391     EL_SP_ZONK,
1392     EL_SP_INFOTRON,
1393     EL_SP_DISK_ORANGE,
1394     EL_PEARL,
1395     EL_CRYSTAL,
1396     EL_SPRING,
1397     EL_DX_SUPABOMB,
1398     -1
1399   };
1400
1401   static int ep_walkable_over[] =
1402   {
1403     EL_EMPTY_SPACE,
1404     EL_SP_EMPTY_SPACE,
1405     EL_SOKOBAN_FIELD_EMPTY,
1406     EL_EXIT_OPEN,
1407     EL_SP_EXIT_OPEN,
1408     EL_GATE_1,
1409     EL_GATE_2,
1410     EL_GATE_3,
1411     EL_GATE_4,
1412     EL_GATE_1_GRAY,
1413     EL_GATE_2_GRAY,
1414     EL_GATE_3_GRAY,
1415     EL_GATE_4_GRAY,
1416     -1
1417   };
1418
1419   static int ep_walkable_inside[] =
1420   {
1421     EL_TUBE_ANY,
1422     EL_TUBE_VERTICAL,
1423     EL_TUBE_HORIZONTAL,
1424     EL_TUBE_VERTICAL_LEFT,
1425     EL_TUBE_VERTICAL_RIGHT,
1426     EL_TUBE_HORIZONTAL_UP,
1427     EL_TUBE_HORIZONTAL_DOWN,
1428     EL_TUBE_LEFT_UP,
1429     EL_TUBE_LEFT_DOWN,
1430     EL_TUBE_RIGHT_UP,
1431     EL_TUBE_RIGHT_DOWN,
1432     -1
1433   };
1434
1435   static int ep_walkable_under[] =
1436   {
1437     -1
1438   };
1439
1440   static int ep_passable_over[] =
1441   {
1442     EL_EM_GATE_1,
1443     EL_EM_GATE_2,
1444     EL_EM_GATE_3,
1445     EL_EM_GATE_4,
1446     EL_EM_GATE_1_GRAY,
1447     EL_EM_GATE_2_GRAY,
1448     EL_EM_GATE_3_GRAY,
1449     EL_EM_GATE_4_GRAY,
1450     EL_SWITCHGATE_OPEN,
1451     EL_TIMEGATE_OPEN,
1452     -1
1453   };
1454
1455   static int ep_passable_inside[] =
1456   {
1457     EL_SP_PORT_LEFT,
1458     EL_SP_PORT_RIGHT,
1459     EL_SP_PORT_UP,
1460     EL_SP_PORT_DOWN,
1461     EL_SP_PORT_HORIZONTAL,
1462     EL_SP_PORT_VERTICAL,
1463     EL_SP_PORT_ANY,
1464     EL_SP_GRAVITY_PORT_LEFT,
1465     EL_SP_GRAVITY_PORT_RIGHT,
1466     EL_SP_GRAVITY_PORT_UP,
1467     EL_SP_GRAVITY_PORT_DOWN,
1468     -1
1469   };
1470
1471   static int ep_passable_under[] =
1472   {
1473     -1
1474   };
1475
1476   static int ep_pushable[] =
1477   {
1478     EL_ROCK,
1479     EL_BOMB,
1480     EL_DX_SUPABOMB,
1481     EL_NUT,
1482     EL_TIME_ORB_EMPTY,
1483     EL_SP_ZONK,
1484     EL_SP_DISK_ORANGE,
1485     EL_SPRING,
1486     EL_BD_ROCK,
1487     EL_SOKOBAN_OBJECT,
1488     EL_SOKOBAN_FIELD_FULL,
1489     EL_SATELLITE,
1490     EL_SP_DISK_YELLOW,
1491     EL_BALLOON,
1492     -1
1493   };
1494
1495   static int ep_can_be_crumbled[] =
1496   {
1497     EL_SAND,
1498     EL_LANDMINE,
1499     EL_TRAP,
1500     EL_TRAP_ACTIVE,
1501     -1
1502   };
1503
1504   static int ep_player[] =
1505   {
1506     EL_PLAYER_1,
1507     EL_PLAYER_2,
1508     EL_PLAYER_3,
1509     EL_PLAYER_4,
1510     -1
1511   };
1512
1513   static int ep_can_pass_magic_wall[] =
1514   {
1515     EL_ROCK,
1516     EL_BD_ROCK,
1517     EL_EMERALD,
1518     EL_BD_DIAMOND,
1519     EL_EMERALD_YELLOW,
1520     EL_EMERALD_RED,
1521     EL_EMERALD_PURPLE,
1522     EL_DIAMOND,
1523     -1
1524   };
1525
1526   static int ep_switchable[] =
1527   {
1528     EL_ROBOT_WHEEL,
1529     EL_SP_TERMINAL,
1530     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
1531     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
1532     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
1533     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
1534     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
1535     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
1536     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
1537     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
1538     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
1539     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
1540     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
1541     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
1542     EL_SWITCHGATE_SWITCH_UP,
1543     EL_SWITCHGATE_SWITCH_DOWN,
1544     EL_LIGHT_SWITCH,
1545     EL_LIGHT_SWITCH_ACTIVE,
1546     EL_TIMEGATE_SWITCH,
1547     EL_BALLOON_SWITCH_LEFT,
1548     EL_BALLOON_SWITCH_RIGHT,
1549     EL_BALLOON_SWITCH_UP,
1550     EL_BALLOON_SWITCH_DOWN,
1551     EL_BALLOON_SWITCH_ANY,
1552     EL_LAMP,
1553     EL_TIME_ORB_FULL,
1554     -1
1555   };
1556
1557   static int ep_dont_touch[] =
1558   {
1559     EL_BUG,
1560     EL_SPACESHIP,
1561     EL_BD_BUTTERFLY,
1562     EL_BD_FIREFLY,
1563     -1
1564   };
1565
1566   static int ep_enemy[] =
1567   {
1568     EL_BUG,
1569     EL_SPACESHIP,
1570     EL_BD_BUTTERFLY,
1571     EL_BD_FIREFLY,
1572
1573     EL_YAMYAM,
1574     EL_DARK_YAMYAM,
1575     EL_ROBOT,
1576     EL_PACMAN,
1577     EL_SP_SNIKSNAK,
1578     EL_SP_ELECTRON,
1579     -1
1580   };
1581
1582   static int ep_dont_go_to[] =
1583   {
1584     EL_BUG,
1585     EL_SPACESHIP,
1586     EL_BD_BUTTERFLY,
1587     EL_BD_FIREFLY,
1588
1589     EL_YAMYAM,
1590     EL_DARK_YAMYAM,
1591     EL_ROBOT,
1592     EL_PACMAN,
1593     EL_SP_SNIKSNAK,
1594     EL_SP_ELECTRON,
1595
1596     EL_AMOEBA_DROP,
1597     EL_ACID,
1598
1599     /* !!! maybe this should better be handled by 'ep_diggable' !!! */
1600 #if 1
1601     EL_SP_BUGGY_BASE_ACTIVE,
1602     EL_TRAP_ACTIVE,
1603     EL_LANDMINE,
1604 #endif
1605     -1
1606   };
1607
1608   static int ep_bd_element[] =
1609   {
1610     EL_EMPTY,
1611     EL_SAND,
1612     EL_WALL_CRUMBLED,
1613     EL_BD_WALL,
1614     EL_ROCK,
1615     EL_BD_ROCK,
1616     EL_BD_DIAMOND,
1617     EL_BD_MAGIC_WALL,
1618     EL_EXIT_CLOSED,
1619     EL_EXIT_OPEN,
1620     EL_STEELWALL,
1621     EL_PLAYER_1,
1622     EL_BD_FIREFLY,
1623     EL_BD_FIREFLY_1,
1624     EL_BD_FIREFLY_2,
1625     EL_BD_FIREFLY_3,
1626     EL_BD_FIREFLY_4,
1627     EL_BD_BUTTERFLY,
1628     EL_BD_BUTTERFLY_1,
1629     EL_BD_BUTTERFLY_2,
1630     EL_BD_BUTTERFLY_3,
1631     EL_BD_BUTTERFLY_4,
1632     EL_BD_AMOEBA,
1633     EL_CHAR_QUESTION,
1634     -1
1635   };
1636
1637   static int ep_sp_element[] =
1638   {
1639     EL_SP_EMPTY,
1640     EL_SP_ZONK,
1641     EL_SP_BASE,
1642     EL_SP_MURPHY,
1643     EL_SP_INFOTRON,
1644     EL_SP_CHIP_SINGLE,
1645     EL_SP_HARDWARE_GRAY,
1646     EL_SP_EXIT_CLOSED,
1647     EL_SP_EXIT_OPEN,
1648     EL_SP_DISK_ORANGE,
1649     EL_SP_PORT_RIGHT,
1650     EL_SP_PORT_DOWN,
1651     EL_SP_PORT_LEFT,
1652     EL_SP_PORT_UP,
1653     EL_SP_GRAVITY_PORT_RIGHT,
1654     EL_SP_GRAVITY_PORT_DOWN,
1655     EL_SP_GRAVITY_PORT_LEFT,
1656     EL_SP_GRAVITY_PORT_UP,
1657     EL_SP_SNIKSNAK,
1658     EL_SP_DISK_YELLOW,
1659     EL_SP_TERMINAL,
1660     EL_SP_DISK_RED,
1661     EL_SP_PORT_VERTICAL,
1662     EL_SP_PORT_HORIZONTAL,
1663     EL_SP_PORT_ANY,
1664     EL_SP_ELECTRON,
1665     EL_SP_BUGGY_BASE,
1666     EL_SP_CHIP_LEFT,
1667     EL_SP_CHIP_RIGHT,
1668     EL_SP_HARDWARE_BASE_1,
1669     EL_SP_HARDWARE_GREEN,
1670     EL_SP_HARDWARE_BLUE,
1671     EL_SP_HARDWARE_RED,
1672     EL_SP_HARDWARE_YELLOW,
1673     EL_SP_HARDWARE_BASE_2,
1674     EL_SP_HARDWARE_BASE_3,
1675     EL_SP_HARDWARE_BASE_4,
1676     EL_SP_HARDWARE_BASE_5,
1677     EL_SP_HARDWARE_BASE_6,
1678     EL_SP_CHIP_TOP,
1679     EL_SP_CHIP_BOTTOM,
1680     /* additional elements that appeared in newer Supaplex levels */
1681     EL_INVISIBLE_WALL,
1682     /* more than one murphy in a level results in an inactive clone */
1683     EL_SP_MURPHY_CLONE,
1684     -1
1685   };
1686
1687   static int ep_sb_element[] =
1688   {
1689     EL_EMPTY,
1690     EL_STEELWALL,
1691     EL_SOKOBAN_OBJECT,
1692     EL_SOKOBAN_FIELD_EMPTY,
1693     EL_SOKOBAN_FIELD_FULL,
1694     EL_PLAYER_1,
1695     EL_INVISIBLE_STEELWALL,
1696     -1
1697   };
1698
1699   static int ep_gem[] =
1700   {
1701     EL_BD_DIAMOND,
1702     EL_EMERALD,
1703     EL_EMERALD_YELLOW,
1704     EL_EMERALD_RED,
1705     EL_EMERALD_PURPLE,
1706     EL_DIAMOND,
1707     -1
1708   };
1709
1710   static int ep_food_dark_yamyam[] =
1711   {
1712     EL_SAND,
1713     EL_BUG,
1714     EL_SPACESHIP,
1715     EL_BD_BUTTERFLY,
1716     EL_BD_FIREFLY,
1717     EL_YAMYAM,
1718     EL_ROBOT,
1719     EL_PACMAN,
1720     EL_AMOEBA_DROP,
1721     EL_AMOEBA_DEAD,
1722     EL_AMOEBA_WET,
1723     EL_AMOEBA_DRY,
1724     EL_AMOEBA_FULL,
1725     EL_BD_AMOEBA,
1726     EL_EMERALD,
1727     EL_BD_DIAMOND,
1728     EL_EMERALD_YELLOW,
1729     EL_EMERALD_RED,
1730     EL_EMERALD_PURPLE,
1731     EL_DIAMOND,
1732     EL_PEARL,
1733     EL_CRYSTAL,
1734     -1
1735   };
1736
1737   static int ep_food_penguin[] =
1738   {
1739     EL_EMERALD,
1740     EL_BD_DIAMOND,
1741     EL_EMERALD_YELLOW,
1742     EL_EMERALD_RED,
1743     EL_EMERALD_PURPLE,
1744     EL_DIAMOND,
1745     EL_PEARL,
1746     EL_CRYSTAL,
1747     -1
1748   };
1749
1750   static int ep_food_pig[] =
1751   {
1752     EL_EMERALD,
1753     EL_BD_DIAMOND,
1754     EL_EMERALD_YELLOW,
1755     EL_EMERALD_RED,
1756     EL_EMERALD_PURPLE,
1757     EL_DIAMOND,
1758     -1
1759   };
1760
1761   static int ep_historic_wall[] =
1762   {
1763     EL_STEELWALL,
1764     EL_GATE_1,
1765     EL_GATE_2,
1766     EL_GATE_3,
1767     EL_GATE_4,
1768     EL_GATE_1_GRAY,
1769     EL_GATE_2_GRAY,
1770     EL_GATE_3_GRAY,
1771     EL_GATE_4_GRAY,
1772     EL_EM_GATE_1,
1773     EL_EM_GATE_2,
1774     EL_EM_GATE_3,
1775     EL_EM_GATE_4,
1776     EL_EM_GATE_1_GRAY,
1777     EL_EM_GATE_2_GRAY,
1778     EL_EM_GATE_3_GRAY,
1779     EL_EM_GATE_4_GRAY,
1780     EL_EXIT_CLOSED,
1781     EL_EXIT_OPENING,
1782     EL_EXIT_OPEN,
1783     EL_WALL,
1784     EL_WALL_CRUMBLED,
1785     EL_EXPANDABLE_WALL,
1786     EL_EXPANDABLE_WALL_HORIZONTAL,
1787     EL_EXPANDABLE_WALL_VERTICAL,
1788     EL_EXPANDABLE_WALL_ANY,
1789     EL_EXPANDABLE_WALL_GROWING,
1790     EL_BD_WALL,
1791     EL_SP_CHIP_SINGLE,
1792     EL_SP_CHIP_LEFT,
1793     EL_SP_CHIP_RIGHT,
1794     EL_SP_CHIP_TOP,
1795     EL_SP_CHIP_BOTTOM,
1796     EL_SP_HARDWARE_GRAY,
1797     EL_SP_HARDWARE_GREEN,
1798     EL_SP_HARDWARE_BLUE,
1799     EL_SP_HARDWARE_RED,
1800     EL_SP_HARDWARE_YELLOW,
1801     EL_SP_HARDWARE_BASE_1,
1802     EL_SP_HARDWARE_BASE_2,
1803     EL_SP_HARDWARE_BASE_3,
1804     EL_SP_HARDWARE_BASE_4,
1805     EL_SP_HARDWARE_BASE_5,
1806     EL_SP_HARDWARE_BASE_6,
1807     EL_SP_TERMINAL,
1808     EL_SP_TERMINAL_ACTIVE,
1809     EL_SP_EXIT_CLOSED,
1810     EL_SP_EXIT_OPEN,
1811     EL_INVISIBLE_STEELWALL,
1812     EL_INVISIBLE_STEELWALL_ACTIVE,
1813     EL_INVISIBLE_WALL,
1814     EL_INVISIBLE_WALL_ACTIVE,
1815     EL_STEELWALL_SLANTED,
1816     EL_EMC_STEELWALL_1,
1817     EL_EMC_STEELWALL_2,
1818     EL_EMC_STEELWALL_3,
1819     EL_EMC_STEELWALL_4,
1820     EL_EMC_WALL_1,
1821     EL_EMC_WALL_2,
1822     EL_EMC_WALL_3,
1823     EL_EMC_WALL_4,
1824     EL_EMC_WALL_5,
1825     EL_EMC_WALL_6,
1826     EL_EMC_WALL_7,
1827     EL_EMC_WALL_8,
1828     -1
1829   };
1830
1831   static int ep_historic_solid[] =
1832   {
1833     EL_WALL,
1834     EL_EXPANDABLE_WALL,
1835     EL_EXPANDABLE_WALL_HORIZONTAL,
1836     EL_EXPANDABLE_WALL_VERTICAL,
1837     EL_EXPANDABLE_WALL_ANY,
1838     EL_BD_WALL,
1839     EL_WALL_CRUMBLED,
1840     EL_EXIT_CLOSED,
1841     EL_EXIT_OPENING,
1842     EL_EXIT_OPEN,
1843     EL_AMOEBA_DEAD,
1844     EL_AMOEBA_WET,
1845     EL_AMOEBA_DRY,
1846     EL_AMOEBA_FULL,
1847     EL_BD_AMOEBA,
1848     EL_QUICKSAND_EMPTY,
1849     EL_QUICKSAND_FULL,
1850     EL_QUICKSAND_FILLING,
1851     EL_QUICKSAND_EMPTYING,
1852     EL_MAGIC_WALL,
1853     EL_MAGIC_WALL_ACTIVE,
1854     EL_MAGIC_WALL_EMPTYING,
1855     EL_MAGIC_WALL_FILLING,
1856     EL_MAGIC_WALL_FULL,
1857     EL_MAGIC_WALL_DEAD,
1858     EL_BD_MAGIC_WALL,
1859     EL_BD_MAGIC_WALL_ACTIVE,
1860     EL_BD_MAGIC_WALL_EMPTYING,
1861     EL_BD_MAGIC_WALL_FULL,
1862     EL_BD_MAGIC_WALL_FILLING,
1863     EL_BD_MAGIC_WALL_DEAD,
1864     EL_GAME_OF_LIFE,
1865     EL_BIOMAZE,
1866     EL_SP_CHIP_SINGLE,
1867     EL_SP_CHIP_LEFT,
1868     EL_SP_CHIP_RIGHT,
1869     EL_SP_CHIP_TOP,
1870     EL_SP_CHIP_BOTTOM,
1871     EL_SP_TERMINAL,
1872     EL_SP_TERMINAL_ACTIVE,
1873     EL_SP_EXIT_CLOSED,
1874     EL_SP_EXIT_OPEN,
1875     EL_INVISIBLE_WALL,
1876     EL_INVISIBLE_WALL_ACTIVE,
1877     EL_SWITCHGATE_SWITCH_UP,
1878     EL_SWITCHGATE_SWITCH_DOWN,
1879     EL_TIMEGATE_SWITCH,
1880     EL_TIMEGATE_SWITCH_ACTIVE,
1881     EL_EMC_WALL_1,
1882     EL_EMC_WALL_2,
1883     EL_EMC_WALL_3,
1884     EL_EMC_WALL_4,
1885     EL_EMC_WALL_5,
1886     EL_EMC_WALL_6,
1887     EL_EMC_WALL_7,
1888     EL_EMC_WALL_8,
1889     EL_WALL_PEARL,
1890     EL_WALL_CRYSTAL,
1891
1892     /* the following elements are a direct copy of "indestructible" elements,
1893        except "EL_ACID", which is "indestructible", but not "solid"! */
1894 #if 0
1895     EL_ACID,
1896 #endif
1897     EL_STEELWALL,
1898     EL_ACID_POOL_TOPLEFT,
1899     EL_ACID_POOL_TOPRIGHT,
1900     EL_ACID_POOL_BOTTOMLEFT,
1901     EL_ACID_POOL_BOTTOM,
1902     EL_ACID_POOL_BOTTOMRIGHT,
1903     EL_SP_HARDWARE_GRAY,
1904     EL_SP_HARDWARE_GREEN,
1905     EL_SP_HARDWARE_BLUE,
1906     EL_SP_HARDWARE_RED,
1907     EL_SP_HARDWARE_YELLOW,
1908     EL_SP_HARDWARE_BASE_1,
1909     EL_SP_HARDWARE_BASE_2,
1910     EL_SP_HARDWARE_BASE_3,
1911     EL_SP_HARDWARE_BASE_4,
1912     EL_SP_HARDWARE_BASE_5,
1913     EL_SP_HARDWARE_BASE_6,
1914     EL_INVISIBLE_STEELWALL,
1915     EL_INVISIBLE_STEELWALL_ACTIVE,
1916     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
1917     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
1918     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
1919     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
1920     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
1921     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
1922     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
1923     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
1924     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
1925     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
1926     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
1927     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
1928     EL_LIGHT_SWITCH,
1929     EL_LIGHT_SWITCH_ACTIVE,
1930     EL_SIGN_EXCLAMATION,
1931     EL_SIGN_RADIOACTIVITY,
1932     EL_SIGN_STOP,
1933     EL_SIGN_WHEELCHAIR,
1934     EL_SIGN_PARKING,
1935     EL_SIGN_ONEWAY,
1936     EL_SIGN_HEART,
1937     EL_SIGN_TRIANGLE,
1938     EL_SIGN_ROUND,
1939     EL_SIGN_EXIT,
1940     EL_SIGN_YINYANG,
1941     EL_SIGN_OTHER,
1942     EL_STEELWALL_SLANTED,
1943     EL_EMC_STEELWALL_1,
1944     EL_EMC_STEELWALL_2,
1945     EL_EMC_STEELWALL_3,
1946     EL_EMC_STEELWALL_4,
1947     EL_CRYSTAL,
1948     EL_GATE_1,
1949     EL_GATE_2,
1950     EL_GATE_3,
1951     EL_GATE_4,
1952     EL_GATE_1_GRAY,
1953     EL_GATE_2_GRAY,
1954     EL_GATE_3_GRAY,
1955     EL_GATE_4_GRAY,
1956     EL_EM_GATE_1,
1957     EL_EM_GATE_2,
1958     EL_EM_GATE_3,
1959     EL_EM_GATE_4,
1960     EL_EM_GATE_1_GRAY,
1961     EL_EM_GATE_2_GRAY,
1962     EL_EM_GATE_3_GRAY,
1963     EL_EM_GATE_4_GRAY,
1964     EL_SWITCHGATE_OPEN,
1965     EL_SWITCHGATE_OPENING,
1966     EL_SWITCHGATE_CLOSED,
1967     EL_SWITCHGATE_CLOSING,
1968     EL_TIMEGATE_OPEN,
1969     EL_TIMEGATE_OPENING,
1970     EL_TIMEGATE_CLOSED,
1971     EL_TIMEGATE_CLOSING,
1972     EL_TUBE_ANY,
1973     EL_TUBE_VERTICAL,
1974     EL_TUBE_HORIZONTAL,
1975     EL_TUBE_VERTICAL_LEFT,
1976     EL_TUBE_VERTICAL_RIGHT,
1977     EL_TUBE_HORIZONTAL_UP,
1978     EL_TUBE_HORIZONTAL_DOWN,
1979     EL_TUBE_LEFT_UP,
1980     EL_TUBE_LEFT_DOWN,
1981     EL_TUBE_RIGHT_UP,
1982     EL_TUBE_RIGHT_DOWN,
1983     -1
1984   };
1985
1986   static int ep_belt[] =
1987   {
1988     EL_CONVEYOR_BELT_1_LEFT,
1989     EL_CONVEYOR_BELT_1_MIDDLE,
1990     EL_CONVEYOR_BELT_1_RIGHT,
1991     EL_CONVEYOR_BELT_2_LEFT,
1992     EL_CONVEYOR_BELT_2_MIDDLE,
1993     EL_CONVEYOR_BELT_2_RIGHT,
1994     EL_CONVEYOR_BELT_3_LEFT,
1995     EL_CONVEYOR_BELT_3_MIDDLE,
1996     EL_CONVEYOR_BELT_3_RIGHT,
1997     EL_CONVEYOR_BELT_4_LEFT,
1998     EL_CONVEYOR_BELT_4_MIDDLE,
1999     EL_CONVEYOR_BELT_4_RIGHT,
2000     -1
2001   };
2002
2003   static int ep_belt_active[] =
2004   {
2005     EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
2006     EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE,
2007     EL_CONVEYOR_BELT_1_RIGHT_ACTIVE,
2008     EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
2009     EL_CONVEYOR_BELT_2_MIDDLE_ACTIVE,
2010     EL_CONVEYOR_BELT_2_RIGHT_ACTIVE,
2011     EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
2012     EL_CONVEYOR_BELT_3_MIDDLE_ACTIVE,
2013     EL_CONVEYOR_BELT_3_RIGHT_ACTIVE,
2014     EL_CONVEYOR_BELT_4_LEFT_ACTIVE,
2015     EL_CONVEYOR_BELT_4_MIDDLE_ACTIVE,
2016     EL_CONVEYOR_BELT_4_RIGHT_ACTIVE,
2017     -1
2018   };
2019
2020   static int ep_belt_switch[] =
2021   {
2022     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2023     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2024     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2025     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2026     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2027     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2028     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2029     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2030     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2031     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2032     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2033     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2034     -1
2035   };
2036
2037   static int ep_tube[] =
2038   {
2039     EL_TUBE_LEFT_UP,
2040     EL_TUBE_LEFT_DOWN,
2041     EL_TUBE_RIGHT_UP,
2042     EL_TUBE_RIGHT_DOWN,
2043     EL_TUBE_HORIZONTAL,
2044     EL_TUBE_HORIZONTAL_UP,
2045     EL_TUBE_HORIZONTAL_DOWN,
2046     EL_TUBE_VERTICAL,
2047     EL_TUBE_VERTICAL_LEFT,
2048     EL_TUBE_VERTICAL_RIGHT,
2049     EL_TUBE_ANY,
2050     -1
2051   };
2052
2053   static int ep_keygate[] =
2054   {
2055     EL_GATE_1,
2056     EL_GATE_2,
2057     EL_GATE_3,
2058     EL_GATE_4,
2059     EL_GATE_1_GRAY,
2060     EL_GATE_2_GRAY,
2061     EL_GATE_3_GRAY,
2062     EL_GATE_4_GRAY,
2063     EL_EM_GATE_1,
2064     EL_EM_GATE_2,
2065     EL_EM_GATE_3,
2066     EL_EM_GATE_4,
2067     EL_EM_GATE_1_GRAY,
2068     EL_EM_GATE_2_GRAY,
2069     EL_EM_GATE_3_GRAY,
2070     EL_EM_GATE_4_GRAY,
2071     -1
2072   };
2073
2074   static int ep_amoeboid[] =
2075   {
2076     EL_AMOEBA_DEAD,
2077     EL_AMOEBA_WET,
2078     EL_AMOEBA_DRY,
2079     EL_AMOEBA_FULL,
2080     EL_BD_AMOEBA,
2081     -1
2082   };
2083
2084   static int ep_amoebalive[] =
2085   {
2086     EL_AMOEBA_WET,
2087     EL_AMOEBA_DRY,
2088     EL_AMOEBA_FULL,
2089     EL_BD_AMOEBA,
2090     -1
2091   };
2092
2093   static int ep_has_content[] =
2094   {
2095     EL_YAMYAM,
2096     EL_AMOEBA_WET,
2097     EL_AMOEBA_DRY,
2098     EL_AMOEBA_FULL,
2099     EL_BD_AMOEBA,
2100     -1
2101   };
2102
2103   static int ep_active_bomb[] =
2104   {
2105     EL_DYNAMITE_ACTIVE,
2106     EL_DYNABOMB_PLAYER_1_ACTIVE,
2107     EL_DYNABOMB_PLAYER_2_ACTIVE,
2108     EL_DYNABOMB_PLAYER_3_ACTIVE,
2109     EL_DYNABOMB_PLAYER_4_ACTIVE,
2110     EL_SP_DISK_RED_ACTIVE,
2111     -1
2112   };
2113
2114   static int ep_inactive[] =
2115   {
2116     EL_EMPTY,
2117     EL_SAND,
2118     EL_WALL,
2119     EL_BD_WALL,
2120     EL_WALL_CRUMBLED,
2121     EL_STEELWALL,
2122     EL_AMOEBA_DEAD,
2123     EL_QUICKSAND_EMPTY,
2124     EL_STONEBLOCK,
2125     EL_ROBOT_WHEEL,
2126     EL_KEY_1,
2127     EL_KEY_2,
2128     EL_KEY_3,
2129     EL_KEY_4,
2130     EL_EM_KEY_1,
2131     EL_EM_KEY_2,
2132     EL_EM_KEY_3,
2133     EL_EM_KEY_4,
2134     EL_GATE_1,
2135     EL_GATE_2,
2136     EL_GATE_3,
2137     EL_GATE_4,
2138     EL_GATE_1_GRAY,
2139     EL_GATE_2_GRAY,
2140     EL_GATE_3_GRAY,
2141     EL_GATE_4_GRAY,
2142     EL_EM_GATE_1,
2143     EL_EM_GATE_2,
2144     EL_EM_GATE_3,
2145     EL_EM_GATE_4,
2146     EL_EM_GATE_1_GRAY,
2147     EL_EM_GATE_2_GRAY,
2148     EL_EM_GATE_3_GRAY,
2149     EL_EM_GATE_4_GRAY,
2150     EL_DYNAMITE,
2151     EL_INVISIBLE_STEELWALL,
2152     EL_INVISIBLE_WALL,
2153     EL_INVISIBLE_SAND,
2154     EL_LAMP,
2155     EL_LAMP_ACTIVE,
2156     EL_WALL_EMERALD,
2157     EL_WALL_DIAMOND,
2158     EL_WALL_BD_DIAMOND,
2159     EL_WALL_EMERALD_YELLOW,
2160     EL_DYNABOMB_INCREASE_NUMBER,
2161     EL_DYNABOMB_INCREASE_SIZE,
2162     EL_DYNABOMB_INCREASE_POWER,
2163     EL_SOKOBAN_OBJECT,
2164     EL_SOKOBAN_FIELD_EMPTY,
2165     EL_SOKOBAN_FIELD_FULL,
2166     EL_WALL_EMERALD_RED,
2167     EL_WALL_EMERALD_PURPLE,
2168     EL_ACID_POOL_TOPLEFT,
2169     EL_ACID_POOL_TOPRIGHT,
2170     EL_ACID_POOL_BOTTOMLEFT,
2171     EL_ACID_POOL_BOTTOM,
2172     EL_ACID_POOL_BOTTOMRIGHT,
2173     EL_MAGIC_WALL,
2174     EL_MAGIC_WALL_DEAD,
2175     EL_BD_MAGIC_WALL,
2176     EL_BD_MAGIC_WALL_DEAD,
2177     EL_AMOEBA_TO_DIAMOND,
2178     EL_BLOCKED,
2179     EL_SP_EMPTY,
2180     EL_SP_BASE,
2181     EL_SP_PORT_RIGHT,
2182     EL_SP_PORT_DOWN,
2183     EL_SP_PORT_LEFT,
2184     EL_SP_PORT_UP,
2185     EL_SP_GRAVITY_PORT_RIGHT,
2186     EL_SP_GRAVITY_PORT_DOWN,
2187     EL_SP_GRAVITY_PORT_LEFT,
2188     EL_SP_GRAVITY_PORT_UP,
2189     EL_SP_PORT_HORIZONTAL,
2190     EL_SP_PORT_VERTICAL,
2191     EL_SP_PORT_ANY,
2192     EL_SP_DISK_RED,
2193     EL_SP_DISK_YELLOW,
2194     EL_SP_CHIP_SINGLE,
2195     EL_SP_CHIP_LEFT,
2196     EL_SP_CHIP_RIGHT,
2197     EL_SP_CHIP_TOP,
2198     EL_SP_CHIP_BOTTOM,
2199     EL_SP_HARDWARE_GRAY,
2200     EL_SP_HARDWARE_GREEN,
2201     EL_SP_HARDWARE_BLUE,
2202     EL_SP_HARDWARE_RED,
2203     EL_SP_HARDWARE_YELLOW,
2204     EL_SP_HARDWARE_BASE_1,
2205     EL_SP_HARDWARE_BASE_2,
2206     EL_SP_HARDWARE_BASE_3,
2207     EL_SP_HARDWARE_BASE_4,
2208     EL_SP_HARDWARE_BASE_5,
2209     EL_SP_HARDWARE_BASE_6,
2210     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2211     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2212     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2213     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2214     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2215     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2216     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2217     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2218     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2219     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2220     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2221     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2222     EL_SIGN_EXCLAMATION,
2223     EL_SIGN_RADIOACTIVITY,
2224     EL_SIGN_STOP,
2225     EL_SIGN_WHEELCHAIR,
2226     EL_SIGN_PARKING,
2227     EL_SIGN_ONEWAY,
2228     EL_SIGN_HEART,
2229     EL_SIGN_TRIANGLE,
2230     EL_SIGN_ROUND,
2231     EL_SIGN_EXIT,
2232     EL_SIGN_YINYANG,
2233     EL_SIGN_OTHER,
2234     EL_STEELWALL_SLANTED,
2235     EL_EMC_STEELWALL_1,
2236     EL_EMC_STEELWALL_2,
2237     EL_EMC_STEELWALL_3,
2238     EL_EMC_STEELWALL_4,
2239     EL_EMC_WALL_1,
2240     EL_EMC_WALL_2,
2241     EL_EMC_WALL_3,
2242     EL_EMC_WALL_4,
2243     EL_EMC_WALL_5,
2244     EL_EMC_WALL_6,
2245     EL_EMC_WALL_7,
2246     EL_EMC_WALL_8,
2247     -1
2248   };
2249
2250   static struct
2251   {
2252     int *elements;
2253     int property;
2254   } element_properties[] =
2255   {
2256     { ep_diggable,              EP_DIGGABLE             },
2257     { ep_collectible,           EP_COLLECTIBLE          },
2258     { ep_indestructible,        EP_INDESTRUCTIBLE       },
2259     { ep_slippery,              EP_SLIPPERY             },
2260     { ep_can_fall,              EP_CAN_FALL             },
2261     { ep_can_smash,             EP_CAN_SMASH            },
2262     { ep_walkable_over,         EP_WALKABLE_OVER        },
2263     { ep_walkable_inside,       EP_WALKABLE_INSIDE      },
2264     { ep_walkable_under,        EP_WALKABLE_UNDER       },
2265     { ep_passable_over,         EP_PASSABLE_OVER        },
2266     { ep_passable_inside,       EP_PASSABLE_INSIDE      },
2267     { ep_passable_under,        EP_PASSABLE_UNDER       },
2268     { ep_pushable,              EP_PUSHABLE             },
2269
2270     { ep_player,                EP_PLAYER               },
2271     { ep_can_be_crumbled,       EP_CAN_BE_CRUMBLED      },
2272     { ep_can_move,              EP_CAN_MOVE             },
2273     { ep_can_pass_magic_wall,   EP_CAN_PASS_MAGIC_WALL  },
2274     { ep_switchable,            EP_SWITCHABLE           },
2275     { ep_dont_touch,            EP_DONT_TOUCH           },
2276     { ep_enemy,                 EP_ENEMY                },
2277     { ep_dont_go_to,            EP_DONT_GO_TO           },
2278     { ep_can_explode,           EP_CAN_EXPLODE          },
2279     { ep_bd_element,            EP_BD_ELEMENT           },
2280     { ep_sp_element,            EP_SP_ELEMENT           },
2281     { ep_sb_element,            EP_SB_ELEMENT           },
2282     { ep_gem,                   EP_GEM                  },
2283     { ep_food_dark_yamyam,      EP_FOOD_DARK_YAMYAM     },
2284     { ep_food_penguin,          EP_FOOD_PENGUIN         },
2285     { ep_food_pig,              EP_FOOD_PIG             },
2286     { ep_historic_wall,         EP_HISTORIC_WALL        },
2287     { ep_historic_solid,        EP_HISTORIC_SOLID       },
2288     { ep_belt,                  EP_BELT                 },
2289     { ep_belt_active,           EP_BELT_ACTIVE          },
2290     { ep_belt_switch,           EP_BELT_SWITCH          },
2291     { ep_tube,                  EP_TUBE                 },
2292     { ep_keygate,               EP_KEYGATE              },
2293     { ep_amoeboid,              EP_AMOEBOID             },
2294     { ep_amoebalive,            EP_AMOEBALIVE           },
2295     { ep_has_content,           EP_HAS_CONTENT          },
2296     { ep_active_bomb,           EP_ACTIVE_BOMB          },
2297     { ep_inactive,              EP_INACTIVE             },
2298
2299     { NULL,                     -1                      }
2300   };
2301
2302   int i, j;
2303
2304   /* always start with reliable default values (element has no properties) */
2305   for (i=0; i < MAX_NUM_ELEMENTS; i++)
2306     for (j=0; j < NUM_ELEMENT_PROPERTIES; j++)
2307       SET_PROPERTY(i, j, FALSE);
2308
2309   /* set all base element properties from above array definitions */
2310   for (i=0; element_properties[i].elements != NULL; i++)
2311     for (j=0; (element_properties[i].elements)[j] != -1; j++)
2312       SET_PROPERTY((element_properties[i].elements)[j],
2313                    element_properties[i].property, TRUE);
2314 }
2315
2316 void InitElementPropertiesEngine(int engine_version)
2317 {
2318 #if 0
2319   static int active_properties[] =
2320   {
2321     EP_AMOEBALIVE,
2322     EP_AMOEBOID,
2323     EP_PFORTE,
2324     EP_ENEMY,
2325     EP_MAUER,
2326     EP_CAN_FALL,
2327     EP_CAN_SMASH,
2328     EP_CAN_PASS_MAGIC_WALL,
2329     EP_CAN_MOVE,
2330     EP_DONT_TOUCH,
2331     EP_DONT_GO_TO,
2332     EP_GEM,
2333     EP_CAN_EXPLODE,
2334     EP_PUSHABLE,
2335     EP_PLAYER,
2336     EP_HAS_CONTENT,
2337     EP_DIGGABLE,
2338     EP_PASSABLE_INSIDE,
2339     EP_OVER_PLAYER,
2340     EP_ACTIVE_BOMB,
2341
2342     EP_BELT,
2343     EP_BELT_ACTIVE,
2344     EP_BELT_SWITCH,
2345     EP_WALKABLE_UNDER,
2346     EP_EM_SLIPPERY_WALL,
2347     EP_CAN_BE_CRUMBLED,
2348   };
2349 #endif
2350
2351   static int no_wall_properties[] =
2352   {
2353     EP_AMOEBALIVE,
2354     EP_AMOEBOID,
2355     EP_CAN_BE_CRUMBLED,
2356     EP_ENEMY,
2357     EP_CAN_FALL,
2358     EP_CAN_SMASH,
2359     EP_CAN_MOVE,
2360     EP_DONT_GO_TO,
2361     EP_FOOD_DARK_YAMYAM,
2362     EP_GEM,
2363     EP_FOOD_PENGUIN,
2364     EP_PUSHABLE,
2365     EP_PLAYER,
2366     EP_ACCESSIBLE,
2367     EP_DIGGABLE,
2368     EP_COLLECTIBLE,
2369     EP_ACTIVE_BOMB,
2370     EP_BELT,
2371     EP_BELT_ACTIVE,
2372     EP_TUBE,
2373     -1
2374   };
2375
2376   int i, j;
2377
2378 #if 0
2379   InitElementPropertiesStatic();
2380 #endif
2381
2382   /* set all special, combined or engine dependant element properties */
2383   for (i=0; i < MAX_NUM_ELEMENTS; i++)
2384   {
2385 #if 0
2386     for (j=EP_ACCESSIBLE_OVER; j < NUM_ELEMENT_PROPERTIES; j++)
2387       SET_PROPERTY(i, j, FALSE);
2388 #endif
2389
2390     /* ---------- INACTIVE ------------------------------------------------- */
2391     if (i >= EL_CHAR_START && i <= EL_CHAR_END)
2392       SET_PROPERTY(i, EP_INACTIVE, TRUE);
2393
2394     /* ---------- WALKABLE, PASSABLE, ACCESSIBLE --------------------------- */
2395     SET_PROPERTY(i, EP_WALKABLE, (IS_WALKABLE_OVER(i) ||
2396                                   IS_WALKABLE_INSIDE(i) ||
2397                                   IS_WALKABLE_UNDER(i)));
2398
2399     SET_PROPERTY(i, EP_PASSABLE, (IS_PASSABLE_OVER(i) ||
2400                                   IS_PASSABLE_INSIDE(i) ||
2401                                   IS_PASSABLE_UNDER(i)));
2402
2403     SET_PROPERTY(i, EP_ACCESSIBLE_OVER, (IS_WALKABLE_OVER(i) ||
2404                                          IS_PASSABLE_OVER(i)));
2405
2406     SET_PROPERTY(i, EP_ACCESSIBLE_INSIDE, (IS_WALKABLE_INSIDE(i) ||
2407                                            IS_PASSABLE_INSIDE(i)));
2408
2409     SET_PROPERTY(i, EP_ACCESSIBLE_UNDER, (IS_WALKABLE_UNDER(i) ||
2410                                           IS_PASSABLE_UNDER(i)));
2411
2412     SET_PROPERTY(i, EP_ACCESSIBLE, (IS_WALKABLE(i) ||
2413                                     IS_PASSABLE(i)));
2414
2415     /* ---------- SNAPPABLE ------------------------------------------------ */
2416     SET_PROPERTY(i, EP_SNAPPABLE, (IS_DIGGABLE(i) ||
2417                                    IS_COLLECTIBLE(i) ||
2418                                    IS_SWITCHABLE(i) ||
2419                                    i == EL_BD_ROCK));
2420
2421     /* ---------- WALL ----------------------------------------------------- */
2422     SET_PROPERTY(i, EP_WALL, TRUE);     /* default: element is wall */
2423
2424     for (j=0; no_wall_properties[j] != -1; j++)
2425       if (HAS_PROPERTY(i, no_wall_properties[j]) ||
2426           i >= EL_FIRST_RUNTIME_UNREAL)
2427         SET_PROPERTY(i, EP_WALL, FALSE);
2428
2429     if (IS_HISTORIC_WALL(i))
2430       SET_PROPERTY(i, EP_WALL, TRUE);
2431
2432     /* ---------- SOLID_FOR_PUSHING ---------------------------------------- */
2433     if (engine_version < VERSION_IDENT(2,2,0))
2434       SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, IS_HISTORIC_SOLID(i));
2435     else
2436       SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, (!IS_WALKABLE(i) &&
2437                                              !IS_DIGGABLE(i) &&
2438                                              !IS_COLLECTIBLE(i)));
2439
2440     /* ---------- DRAGONFIRE_PROOF ----------------------------------------- */
2441
2442     if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
2443       SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE);
2444     else
2445       SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_CUSTOM_ELEMENT(i) &&
2446                                             IS_INDESTRUCTIBLE(i)));
2447
2448     /* ---------- EXPLOSION_PROOF ------------------------------------------ */
2449     if (i == EL_FLAMES)
2450       SET_PROPERTY(i, EP_EXPLOSION_PROOF, TRUE);
2451     else if (engine_version < VERSION_IDENT(2,2,0))
2452       SET_PROPERTY(i, EP_EXPLOSION_PROOF, IS_INDESTRUCTIBLE(i));
2453     else
2454       SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
2455                                            !IS_WALKABLE_OVER(i) &&
2456                                            !IS_WALKABLE_UNDER(i)));
2457
2458     /* ---------- ENEMY ---------------------------------------------------- */
2459     if (DONT_TOUCH(i))
2460       SET_PROPERTY(i, EP_ENEMY, TRUE);
2461
2462     /* ---------- DONT_GO_TO ----------------------------------------------- */
2463     if (IS_ENEMY(i))
2464       SET_PROPERTY(i, EP_DONT_GO_TO, TRUE);
2465   }
2466
2467 #if 0
2468   /* determine inactive elements (used for engine main loop optimization) */
2469   for (i=0; i < MAX_NUM_ELEMENTS; i++)
2470   {
2471     boolean active = FALSE;
2472
2473     for (j=0; i < NUM_ELEMENT_PROPERTIES; j++)
2474     {
2475       if (HAS_PROPERTY(i, j))
2476         active = TRUE;
2477     }
2478
2479 #if 0
2480     if (!active)
2481       SET_PROPERTY(i, EP_INACTIVE, TRUE);
2482 #endif
2483   }
2484 #endif
2485
2486   /* dynamically adjust element properties according to game engine version */
2487   {
2488     static int ep_em_slippery_wall[] =
2489     {
2490       EL_STEELWALL,
2491       EL_WALL,
2492       EL_EXPANDABLE_WALL,
2493       EL_EXPANDABLE_WALL_HORIZONTAL,
2494       EL_EXPANDABLE_WALL_VERTICAL,
2495       EL_EXPANDABLE_WALL_ANY,
2496       -1
2497     };
2498
2499     /* special EM style gems behaviour */
2500     for (i=0; ep_em_slippery_wall[i] != -1; i++)
2501       SET_PROPERTY(ep_em_slippery_wall[i], EP_EM_SLIPPERY_WALL,
2502                    level.em_slippery_gems);
2503
2504     /* "EL_EXPANDABLE_WALL_GROWING" wasn't slippery for EM gems in 2.0.1 */
2505     SET_PROPERTY(EL_EXPANDABLE_WALL_GROWING, EP_EM_SLIPPERY_WALL,
2506                  (level.em_slippery_gems &&
2507                   engine_version > VERSION_IDENT(2,0,1)));
2508   }
2509
2510   /* dynamically adjust element properties according to game engine version */
2511 #if 0
2512   if (engine_version < RELEASE_IDENT(2,2,0,7))
2513 #endif
2514   {
2515     for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
2516     {
2517       int element = EL_CUSTOM_START + i;
2518
2519       element_info[element].push_delay_fixed = 2;
2520       element_info[element].push_delay_random = 8;
2521     }
2522   }
2523 }
2524
2525 static void InitGlobal()
2526 {
2527   global.autoplay_leveldir = NULL;
2528
2529   global.frames_per_second = 0;
2530   global.fps_slowdown = FALSE;
2531   global.fps_slowdown_factor = 1;
2532 }
2533
2534 void Execute_Command(char *command)
2535 {
2536   if (strcmp(command, "print graphicsinfo.conf") == 0)
2537   {
2538     int i;
2539
2540     printf("# You can configure additional/alternative image files here.\n");
2541     printf("# (The images below are default and therefore commented out.)\n");
2542     printf("\n");
2543     printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
2544     printf("\n");
2545     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2546     printf("\n");
2547
2548     for (i=0; image_config[i].token != NULL; i++)
2549       printf("# %s\n",
2550              getFormattedSetupEntry(image_config[i].token,
2551                                     image_config[i].value));
2552
2553     exit(0);
2554   }
2555   else if (strcmp(command, "print soundsinfo.conf") == 0)
2556   {
2557     int i;
2558
2559     printf("# You can configure additional/alternative sound files here.\n");
2560     printf("# (The sounds below are default and therefore commented out.)\n");
2561     printf("\n");
2562     printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
2563     printf("\n");
2564     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2565     printf("\n");
2566
2567     for (i=0; sound_config[i].token != NULL; i++)
2568       printf("# %s\n",
2569              getFormattedSetupEntry(sound_config[i].token,
2570                                     sound_config[i].value));
2571
2572     exit(0);
2573   }
2574   else if (strcmp(command, "print musicinfo.conf") == 0)
2575   {
2576     printf("# (Currently only \"name\" and \"sort_priority\" recognized.)\n");
2577     printf("\n");
2578     printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
2579     printf("\n");
2580     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2581
2582     exit(0);
2583   }
2584   else if (strncmp(command, "dump level ", 11) == 0)
2585   {
2586     char *filename = &command[11];
2587
2588     if (access(filename, F_OK) != 0)
2589       Error(ERR_EXIT, "cannot open file '%s'", filename);
2590
2591     LoadLevelFromFilename(filename);
2592     DumpLevel(&level);
2593
2594     exit(0);
2595   }
2596   else if (strncmp(command, "dump tape ", 10) == 0)
2597   {
2598     char *filename = &command[10];
2599
2600     if (access(filename, F_OK) != 0)
2601       Error(ERR_EXIT, "cannot open file '%s'", filename);
2602
2603     LoadTapeFromFilename(filename);
2604     DumpTape(&tape);
2605
2606     exit(0);
2607   }
2608   else if (strncmp(command, "autoplay ", 9) == 0)
2609   {
2610     char *str_copy = getStringCopy(&command[9]);
2611     char *str_ptr = strchr(str_copy, ' ');
2612
2613     global.autoplay_leveldir = str_copy;
2614     global.autoplay_level_nr = -1;
2615
2616     if (str_ptr != NULL)
2617     {
2618       *str_ptr++ = '\0';                        /* terminate leveldir string */
2619       global.autoplay_level_nr = atoi(str_ptr); /* get level_nr value */
2620     }
2621   }
2622   else
2623   {
2624     Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
2625   }
2626 }
2627
2628 static void InitSetup()
2629 {
2630   LoadSetup();                                  /* global setup info */
2631
2632   /* set some options from setup file */
2633
2634   if (setup.options.verbose)
2635     options.verbose = TRUE;
2636 }
2637
2638 static void InitPlayerInfo()
2639 {
2640   int i;
2641
2642   /* choose default local player */
2643   local_player = &stored_player[0];
2644
2645   for (i=0; i<MAX_PLAYERS; i++)
2646     stored_player[i].connected = FALSE;
2647
2648   local_player->connected = TRUE;
2649 }
2650
2651 static void InitArtworkInfo()
2652 {
2653   LoadArtworkInfo();
2654 }
2655
2656 static char *get_element_class_token(int element)
2657 {
2658   char *element_class_name = element_info[element].class_name;
2659   char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
2660
2661   sprintf(element_class_token, "[%s]", element_class_name);
2662
2663   return element_class_token;
2664 }
2665
2666 static void InitArtworkConfig()
2667 {
2668   static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
2669   static char *sound_id_prefix[MAX_NUM_ELEMENTS + MAX_NUM_ELEMENTS + 1];
2670   static char *action_id_suffix[NUM_ACTIONS + 1];
2671   static char *direction_id_suffix[NUM_DIRECTIONS + 1];
2672   static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
2673   static char *dummy[1] = { NULL };
2674   static char *ignore_generic_tokens[] =
2675   {
2676     "name",
2677     "sort_priority",
2678     NULL
2679   };
2680   static char **ignore_image_tokens, **ignore_sound_tokens;
2681   int num_ignore_generic_tokens;
2682   int num_ignore_image_tokens, num_ignore_sound_tokens;
2683   int i;
2684
2685   /* dynamically determine list of generic tokens to be ignored */
2686   num_ignore_generic_tokens = 0;
2687   for (i=0; ignore_generic_tokens[i] != NULL; i++)
2688     num_ignore_generic_tokens++;
2689
2690   /* dynamically determine list of image tokens to be ignored */
2691   num_ignore_image_tokens = num_ignore_generic_tokens;
2692   for (i=0; image_config_vars[i].token != NULL; i++)
2693     num_ignore_image_tokens++;
2694   ignore_image_tokens =
2695     checked_malloc((num_ignore_image_tokens + 1) * sizeof(char *));
2696   for (i=0; i < num_ignore_generic_tokens; i++)
2697     ignore_image_tokens[i] = ignore_generic_tokens[i];
2698   for (i=0; i < num_ignore_image_tokens - num_ignore_generic_tokens; i++)
2699     ignore_image_tokens[num_ignore_generic_tokens + i] =
2700       image_config_vars[i].token;
2701   ignore_image_tokens[num_ignore_image_tokens] = NULL;
2702
2703   /* dynamically determine list of sound tokens to be ignored */
2704   num_ignore_sound_tokens = num_ignore_generic_tokens;
2705   ignore_sound_tokens =
2706     checked_malloc((num_ignore_sound_tokens + 1) * sizeof(char *));
2707   for (i=0; i < num_ignore_generic_tokens; i++)
2708     ignore_sound_tokens[i] = ignore_generic_tokens[i];
2709   ignore_sound_tokens[num_ignore_sound_tokens] = NULL;
2710
2711   for (i=0; i<MAX_NUM_ELEMENTS; i++)
2712     image_id_prefix[i] = element_info[i].token_name;
2713   for (i=0; i<NUM_FONTS; i++)
2714     image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
2715   image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
2716
2717   for (i=0; i<MAX_NUM_ELEMENTS; i++)
2718     sound_id_prefix[i] = element_info[i].token_name;
2719   for (i=0; i<MAX_NUM_ELEMENTS; i++)
2720     sound_id_prefix[MAX_NUM_ELEMENTS + i] = get_element_class_token(i);
2721   sound_id_prefix[MAX_NUM_ELEMENTS + MAX_NUM_ELEMENTS] = NULL;
2722
2723   for (i=0; i<NUM_ACTIONS; i++)
2724     action_id_suffix[i] = element_action_info[i].suffix;
2725   action_id_suffix[NUM_ACTIONS] = NULL;
2726
2727   for (i=0; i<NUM_DIRECTIONS; i++)
2728     direction_id_suffix[i] = element_direction_info[i].suffix;
2729   direction_id_suffix[NUM_DIRECTIONS] = NULL;
2730
2731   for (i=0; i<NUM_SPECIAL_GFX_ARGS; i++)
2732     special_id_suffix[i] = special_suffix_info[i].suffix;
2733   special_id_suffix[NUM_SPECIAL_GFX_ARGS] = NULL;
2734
2735   InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
2736                 image_id_prefix, action_id_suffix, direction_id_suffix,
2737                 special_id_suffix, ignore_image_tokens);
2738   InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
2739                 sound_id_prefix, action_id_suffix, dummy,
2740                 special_id_suffix, ignore_sound_tokens);
2741 }
2742
2743 static void InitMixer()
2744 {
2745   OpenAudio();
2746   StartMixer();
2747 }
2748
2749 void InitGfx()
2750 {
2751   char *filename_font_initial = NULL;
2752   Bitmap *bitmap_font_initial = NULL;
2753   int i, j;
2754
2755   /* determine settings for initial font (for displaying startup messages) */
2756   for (i=0; image_config[i].token != NULL; i++)
2757   {
2758     for (j=0; j < NUM_INITIAL_FONTS; j++)
2759     {
2760       char font_token[128];
2761       int len_font_token;
2762
2763       sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1);
2764       len_font_token = strlen(font_token);
2765
2766       if (strcmp(image_config[i].token, font_token) == 0)
2767         filename_font_initial = image_config[i].value;
2768       else if (strlen(image_config[i].token) > len_font_token &&
2769                strncmp(image_config[i].token, font_token, len_font_token) == 0)
2770       {
2771         if (strcmp(&image_config[i].token[len_font_token], ".x") == 0)
2772           font_initial[j].src_x = atoi(image_config[i].value);
2773         else if (strcmp(&image_config[i].token[len_font_token], ".y") == 0)
2774           font_initial[j].src_y = atoi(image_config[i].value);
2775         else if (strcmp(&image_config[i].token[len_font_token], ".width") == 0)
2776           font_initial[j].width = atoi(image_config[i].value);
2777         else if (strcmp(&image_config[i].token[len_font_token],".height") == 0)
2778           font_initial[j].height = atoi(image_config[i].value);
2779       }
2780     }
2781   }
2782
2783   for (j=0; j < NUM_INITIAL_FONTS; j++)
2784   {
2785     font_initial[j].num_chars = DEFAULT_NUM_CHARS_PER_FONT;
2786     font_initial[j].num_chars_per_line = DEFAULT_NUM_CHARS_PER_LINE;
2787   }
2788
2789   if (filename_font_initial == NULL)    /* should not happen */
2790     Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
2791
2792   /* create additional image buffers for double-buffering */
2793   bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
2794   bitmap_db_door  = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
2795
2796   /* initialize screen properties */
2797   InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
2798                    REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
2799                    bitmap_db_field);
2800   InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
2801   InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
2802   InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
2803
2804   bitmap_font_initial = LoadCustomImage(filename_font_initial);
2805
2806   for (j=0; j < NUM_INITIAL_FONTS; j++)
2807     font_initial[j].bitmap = bitmap_font_initial;
2808
2809   InitFontGraphicInfo();
2810
2811   DrawInitText(WINDOW_TITLE_STRING, 20, FC_YELLOW);
2812   DrawInitText(WINDOW_SUBTITLE_STRING, 50, FC_RED);
2813
2814   DrawInitText("Loading graphics:", 120, FC_GREEN);
2815
2816   InitTileClipmasks();
2817 }
2818
2819 void InitGfxBackground()
2820 {
2821   int x, y;
2822
2823   drawto = backbuffer;
2824   fieldbuffer = bitmap_db_field;
2825   SetDrawtoField(DRAW_BACKBUFFER);
2826
2827   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
2828              0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2829   ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
2830   ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
2831
2832   for (x=0; x<MAX_BUF_XSIZE; x++)
2833     for (y=0; y<MAX_BUF_YSIZE; y++)
2834       redraw[x][y] = 0;
2835   redraw_tiles = 0;
2836   redraw_mask = REDRAW_ALL;
2837 }
2838
2839 static void InitLevelInfo()
2840 {
2841   LoadLevelInfo();                              /* global level info */
2842   LoadLevelSetup_LastSeries();                  /* last played series info */
2843   LoadLevelSetup_SeriesInfo();                  /* last played level info */
2844 }
2845
2846 void InitLevelArtworkInfo()
2847 {
2848   LoadLevelArtworkInfo();
2849 }
2850
2851 static void InitImages()
2852 {
2853   ReloadCustomImages();
2854
2855   LoadCustomElementDescriptions();
2856   LoadSpecialMenuDesignSettings();
2857
2858   ReinitializeGraphics();
2859 }
2860
2861 static void InitSound()
2862 {
2863   InitReloadCustomSounds(artwork.snd_current->identifier);
2864   ReinitializeSounds();
2865 }
2866
2867 static void InitMusic()
2868 {
2869   InitReloadCustomMusic(artwork.mus_current->identifier);
2870   ReinitializeMusic();
2871 }
2872
2873 void InitNetworkServer()
2874 {
2875 #if defined(PLATFORM_UNIX)
2876   int nr_wanted;
2877 #endif
2878
2879   if (!options.network)
2880     return;
2881
2882 #if defined(PLATFORM_UNIX)
2883   nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
2884
2885   if (!ConnectToServer(options.server_host, options.server_port))
2886     Error(ERR_EXIT, "cannot connect to network game server");
2887
2888   SendToServer_PlayerName(setup.player_name);
2889   SendToServer_ProtocolVersion();
2890
2891   if (nr_wanted)
2892     SendToServer_NrWanted(nr_wanted);
2893 #endif
2894 }
2895
2896 void ReloadCustomArtwork()
2897 {
2898   static char *leveldir_current_identifier = NULL;
2899   static boolean last_override_level_graphics = FALSE;
2900   static boolean last_override_level_sounds = FALSE;
2901   static boolean last_override_level_music = FALSE;
2902   /* identifier for new artwork; default: artwork configured in setup */
2903   char *gfx_new_identifier = artwork.gfx_current->identifier;
2904   char *snd_new_identifier = artwork.snd_current->identifier;
2905   char *mus_new_identifier = artwork.mus_current->identifier;
2906   boolean redraw_screen = FALSE;
2907
2908   if (leveldir_current_identifier == NULL)
2909     leveldir_current_identifier = leveldir_current->identifier;
2910
2911 #if 0
2912   printf("CURRENT GFX: '%s' ['%s']\n", artwork.gfx_current->identifier,
2913          leveldir_current->graphics_set);
2914   printf("CURRENT LEV: '%s' / '%s'\n", leveldir_current_identifier,
2915          leveldir_current->identifier);
2916 #endif
2917
2918 #if 0
2919   printf("graphics --> '%s' ('%s')\n",
2920          artwork.gfx_current_identifier, artwork.gfx_current->filename);
2921   printf("sounds   --> '%s' ('%s')\n",
2922          artwork.snd_current_identifier, artwork.snd_current->filename);
2923   printf("music    --> '%s' ('%s')\n",
2924          artwork.mus_current_identifier, artwork.mus_current->filename);
2925 #endif
2926
2927   /* leveldir_current may be invalid (level group, parent link) */
2928   if (!validLevelSeries(leveldir_current))
2929     return;
2930
2931   /* when a new level series was selected, check if there was a change
2932      in custom artwork stored in level series directory */
2933   if (leveldir_current_identifier != leveldir_current->identifier)
2934   {
2935     char *identifier_old = leveldir_current_identifier;
2936     char *identifier_new = leveldir_current->identifier;
2937
2938     if (getTreeInfoFromIdentifier(artwork.gfx_first, identifier_old) !=
2939         getTreeInfoFromIdentifier(artwork.gfx_first, identifier_new))
2940       gfx_new_identifier = identifier_new;
2941     if (getTreeInfoFromIdentifier(artwork.snd_first, identifier_old) !=
2942         getTreeInfoFromIdentifier(artwork.snd_first, identifier_new))
2943       snd_new_identifier = identifier_new;
2944     if (getTreeInfoFromIdentifier(artwork.mus_first, identifier_new) !=
2945         getTreeInfoFromIdentifier(artwork.mus_first, identifier_new))
2946       mus_new_identifier = identifier_new;
2947
2948     leveldir_current_identifier = leveldir_current->identifier;
2949   }
2950
2951   /* custom level artwork configured in level series configuration file
2952      always overrides custom level artwork stored in level series directory
2953      and (level independant) custom artwork configured in setup menue */
2954   if (leveldir_current->graphics_set != NULL)
2955     gfx_new_identifier = leveldir_current->graphics_set;
2956   if (leveldir_current->sounds_set != NULL)
2957     snd_new_identifier = leveldir_current->sounds_set;
2958   if (leveldir_current->music_set != NULL)
2959     mus_new_identifier = leveldir_current->music_set;
2960
2961   if (strcmp(artwork.gfx_current_identifier, gfx_new_identifier) != 0 ||
2962       last_override_level_graphics != setup.override_level_graphics)
2963   {
2964 #if 0
2965     printf("RELOADING GRAPHICS '%s' -> '%s' ('%s')\n",
2966            artwork.gfx_current_identifier,
2967            artwork.gfx_current->identifier,
2968            gfx_new_identifier);
2969 #endif
2970
2971     setLevelArtworkDir(artwork.gfx_first);
2972
2973     ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
2974
2975     InitImages();
2976
2977     FreeTileClipmasks();
2978     InitTileClipmasks();
2979
2980     artwork.gfx_current_identifier = artwork.gfx_current->identifier;
2981     last_override_level_graphics = setup.override_level_graphics;
2982
2983     redraw_screen = TRUE;
2984   }
2985
2986   if (strcmp(artwork.snd_current_identifier, snd_new_identifier) != 0 ||
2987       last_override_level_sounds != setup.override_level_sounds)
2988   {
2989 #if 0
2990     printf("RELOADING SOUNDS '%s' -> '%s' ('%s')\n",
2991            artwork.snd_current_identifier,
2992            artwork.snd_current->identifier,
2993            snd_new_identifier);
2994 #endif
2995
2996     /* set artwork path to send it to the sound server process */
2997     setLevelArtworkDir(artwork.snd_first);
2998
2999     InitReloadCustomSounds(snd_new_identifier);
3000     ReinitializeSounds();
3001
3002     artwork.snd_current_identifier = artwork.snd_current->identifier;
3003     last_override_level_sounds = setup.override_level_sounds;
3004
3005     redraw_screen = TRUE;
3006   }
3007
3008   if (strcmp(artwork.mus_current_identifier, mus_new_identifier) != 0 ||
3009       last_override_level_music != setup.override_level_music)
3010   {
3011     /* set artwork path to send it to the sound server process */
3012     setLevelArtworkDir(artwork.mus_first);
3013
3014     InitReloadCustomMusic(mus_new_identifier);
3015     ReinitializeMusic();
3016
3017     artwork.mus_current_identifier = artwork.mus_current->identifier;
3018     last_override_level_music = setup.override_level_music;
3019
3020     redraw_screen = TRUE;
3021   }
3022
3023   if (redraw_screen)
3024   {
3025     InitGfxBackground();
3026
3027     /* force redraw of (open or closed) door graphics */
3028     SetDoorState(DOOR_OPEN_ALL);
3029     CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
3030   }
3031 }
3032
3033 void KeyboardAutoRepeatOffUnlessAutoplay()
3034 {
3035   if (global.autoplay_leveldir == NULL)
3036     KeyboardAutoRepeatOff();
3037 }
3038
3039
3040 /* ========================================================================= */
3041 /* OpenAll()                                                                 */
3042 /* ========================================================================= */
3043
3044 void OpenAll()
3045 {
3046   InitGlobal();         /* initialize some global variables */
3047
3048   if (options.execute_command)
3049     Execute_Command(options.execute_command);
3050
3051   if (options.serveronly)
3052   {
3053 #if defined(PLATFORM_UNIX)
3054     NetworkServer(options.server_port, options.serveronly);
3055 #else
3056     Error(ERR_WARN, "networking only supported in Unix version");
3057 #endif
3058     exit(0);    /* never reached */
3059   }
3060
3061   InitSetup();
3062
3063   InitPlayerInfo();
3064   InitArtworkInfo();            /* needed before loading gfx, sound & music */
3065   InitArtworkConfig();          /* needed before forking sound child process */
3066   InitMixer();
3067
3068   InitCounter();
3069
3070   InitRND(NEW_RANDOMIZE);
3071   InitSimpleRND(NEW_RANDOMIZE);
3072
3073   InitJoysticks();
3074
3075   InitVideoDisplay();
3076   InitVideoBuffer(&backbuffer, &window, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH,
3077                   setup.fullscreen);
3078
3079   InitEventFilter(FilterMouseMotionEvents);
3080
3081   InitElementPropertiesStatic();
3082
3083   InitGfx();
3084
3085   InitLevelInfo();
3086   InitLevelArtworkInfo();
3087
3088   InitImages();                 /* needs to know current level directory */
3089   InitSound();                  /* needs to know current level directory */
3090   InitMusic();                  /* needs to know current level directory */
3091
3092   InitGfxBackground();
3093
3094   if (global.autoplay_leveldir)
3095   {
3096     AutoPlayTape();
3097     return;
3098   }
3099
3100   game_status = GAME_MODE_MAIN;
3101
3102   DrawMainMenu();
3103
3104   InitNetworkServer();
3105 }
3106
3107 void CloseAllAndExit(int exit_value)
3108 {
3109   StopSounds();
3110   FreeAllSounds();
3111   FreeAllMusic();
3112   CloseAudio();         /* called after freeing sounds (needed for SDL) */
3113
3114   FreeAllImages();
3115   FreeTileClipmasks();
3116
3117   CloseVideoDisplay();
3118   ClosePlatformDependantStuff();
3119
3120   exit(exit_value);
3121 }