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