rnd-20040326-1-src
[rocksndiamonds.git] / src / init.c
1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back!               *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment                      *
5 *               Holger Schemel                             *
6 *               Detmolder Strasse 189                      *
7 *               33604 Bielefeld                            *
8 *               Germany                                    *
9 *               e-mail: info@artsoft.org                   *
10 *----------------------------------------------------------*
11 * init.c                                                   *
12 ***********************************************************/
13
14 #include "libgame/libgame.h"
15
16 #include "init.h"
17 #include "events.h"
18 #include "screens.h"
19 #include "editor.h"
20 #include "game.h"
21 #include "tape.h"
22 #include "tools.h"
23 #include "files.h"
24 #include "network.h"
25 #include "netserv.h"
26 #include "cartoons.h"
27 #include "config.h"
28
29 #include "conf_e2g.c"   /* include auto-generated data structure definitions */
30 #include "conf_esg.c"   /* include auto-generated data structure definitions */
31 #include "conf_e2s.c"   /* include auto-generated data structure definitions */
32 #include "conf_fnt.c"   /* include auto-generated data structure definitions */
33 #include "conf_g2s.c"   /* include auto-generated data structure definitions */
34 #include "conf_g2m.c"   /* include auto-generated data structure definitions */
35
36
37 #define CONFIG_TOKEN_FONT_INITIAL               "font.initial"
38
39
40 struct FontBitmapInfo font_initial[NUM_INITIAL_FONTS];
41
42
43 static void InitTileClipmasks()
44 {
45 #if 0
46 #if defined(TARGET_X11)
47   XGCValues clip_gc_values;
48   unsigned long clip_gc_valuemask;
49
50 #if defined(TARGET_X11_NATIVE)
51
52 #if 0
53   GC copy_clipmask_gc;
54
55   static struct
56   {
57     int start;
58     int count;
59   }
60   tile_needs_clipping[] =
61   {
62     { GFX_SPIELER1_UP, 4 },
63     { GFX_SPIELER1_DOWN, 4 },
64     { GFX_SPIELER1_LEFT, 4 },
65     { GFX_SPIELER1_RIGHT, 4 },
66     { GFX_SPIELER1_PUSH_LEFT, 4 },
67     { GFX_SPIELER1_PUSH_RIGHT, 4 },
68     { GFX_SPIELER2_UP, 4 },
69     { GFX_SPIELER2_DOWN, 4 },
70     { GFX_SPIELER2_LEFT, 4 },
71     { GFX_SPIELER2_RIGHT, 4 },
72     { GFX_SPIELER2_PUSH_LEFT, 4 },
73     { GFX_SPIELER2_PUSH_RIGHT, 4 },
74     { GFX_SPIELER3_UP, 4 },
75     { GFX_SPIELER3_DOWN, 4 },
76     { GFX_SPIELER3_LEFT, 4 },
77     { GFX_SPIELER3_RIGHT, 4 },
78     { GFX_SPIELER3_PUSH_LEFT, 4 },
79     { GFX_SPIELER3_PUSH_RIGHT, 4 },
80     { GFX_SPIELER4_UP, 4 },
81     { GFX_SPIELER4_DOWN, 4 },
82     { GFX_SPIELER4_LEFT, 4 },
83     { GFX_SPIELER4_RIGHT, 4 },
84     { GFX_SPIELER4_PUSH_LEFT, 4 },
85     { GFX_SPIELER4_PUSH_RIGHT, 4 },
86     { GFX_SP_MURPHY, 1 },
87     { GFX_MURPHY_GO_LEFT, 3 },
88     { GFX_MURPHY_GO_RIGHT, 3 },
89     { GFX_MURPHY_SNAP_UP, 1 },
90     { GFX_MURPHY_SNAP_DOWN, 1 },
91     { GFX_MURPHY_SNAP_RIGHT, 1 },
92     { GFX_MURPHY_SNAP_LEFT, 1 },
93     { GFX_MURPHY_PUSH_RIGHT, 1 },
94     { GFX_MURPHY_PUSH_LEFT, 1 },
95     { GFX_GEBLUBBER, 4 },
96     { GFX_DYNAMIT, 7 },
97     { GFX_DYNABOMB, 4 },
98     { GFX_EXPLOSION, 8 },
99     { GFX_SOKOBAN_OBJEKT, 1 },
100     { GFX_FUNKELN_BLAU, 3 },
101     { GFX_FUNKELN_WEISS, 3 },
102     { GFX2_SHIELD_PASSIVE, 3 },
103     { GFX2_SHIELD_ACTIVE, 3 },
104     { -1, 0 }
105   };
106 #endif
107
108 #endif /* TARGET_X11_NATIVE */
109 #endif /* TARGET_X11 */
110
111   int i;
112
113   /* initialize pixmap array for special X11 tile clipping to Pixmap 'None' */
114   for (i = 0; i < NUM_TILES; i++)
115     tile_clipmask[i] = None;
116
117 #if defined(TARGET_X11)
118   /* This stuff is needed because X11 (XSetClipOrigin(), to be precise) is
119      often very slow when preparing a masked XCopyArea() for big Pixmaps.
120      To prevent this, create small (tile-sized) mask Pixmaps which will then
121      be set much faster with XSetClipOrigin() and speed things up a lot. */
122
123   clip_gc_values.graphics_exposures = False;
124   clip_gc_valuemask = GCGraphicsExposures;
125   tile_clip_gc = XCreateGC(display, window->drawable,
126                            clip_gc_valuemask, &clip_gc_values);
127
128 #if 0
129   for (i = 0; i < NUM_BITMAPS; i++)
130   {
131     if (pix[i]->clip_mask)
132     {
133       clip_gc_values.graphics_exposures = False;
134       clip_gc_values.clip_mask = pix[i]->clip_mask;
135       clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
136       pix[i]->stored_clip_gc = XCreateGC(display, window->drawable,
137                                          clip_gc_valuemask, &clip_gc_values);
138     }
139   }
140 #endif
141
142 #if defined(TARGET_X11_NATIVE)
143
144 #if 0
145   /* create graphic context structures needed for clipping */
146   clip_gc_values.graphics_exposures = False;
147   clip_gc_valuemask = GCGraphicsExposures;
148   copy_clipmask_gc = XCreateGC(display, pix[PIX_BACK]->clip_mask,
149                                clip_gc_valuemask, &clip_gc_values);
150
151   /* create only those clipping Pixmaps we really need */
152   for (i = 0; tile_needs_clipping[i].start >= 0; i++)
153   {
154     int j;
155
156     for (j = 0; j < tile_needs_clipping[i].count; j++)
157     {
158       int tile = tile_needs_clipping[i].start + j;
159       int graphic = tile;
160       int src_x, src_y;
161       Bitmap *src_bitmap;
162       Pixmap src_pixmap;
163
164       getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
165       src_pixmap = src_bitmap->clip_mask;
166
167       tile_clipmask[tile] = XCreatePixmap(display, window->drawable,
168                                           TILEX, TILEY, 1);
169
170       XCopyArea(display, src_pixmap, tile_clipmask[tile], copy_clipmask_gc,
171                 src_x, src_y, TILEX, TILEY, 0, 0);
172     }
173   }
174
175   XFreeGC(display, copy_clipmask_gc);
176 #endif
177
178 #endif /* TARGET_X11_NATIVE */
179 #endif /* TARGET_X11 */
180 #endif
181 }
182
183 void FreeTileClipmasks()
184 {
185 #if 0
186 #if defined(TARGET_X11)
187   int i;
188
189   for (i = 0; i < NUM_TILES; i++)
190   {
191     if (tile_clipmask[i] != None)
192     {
193       XFreePixmap(display, tile_clipmask[i]);
194       tile_clipmask[i] = None;
195     }
196   }
197
198   if (tile_clip_gc)
199     XFreeGC(display, tile_clip_gc);
200   tile_clip_gc = None;
201
202 #if 0
203   for (i = 0; i < NUM_BITMAPS; i++)
204   {
205     if (pix[i] != NULL && pix[i]->stored_clip_gc)
206     {
207       XFreeGC(display, pix[i]->stored_clip_gc);
208       pix[i]->stored_clip_gc = None;
209     }
210   }
211 #endif
212
213 #endif /* TARGET_X11 */
214 #endif
215 }
216
217 void FreeGadgets()
218 {
219   FreeLevelEditorGadgets();
220   FreeGameButtons();
221   FreeTapeButtons();
222   FreeToolButtons();
223   FreeScreenGadgets();
224 }
225
226 void InitGadgets()
227 {
228   static boolean gadgets_initialized = FALSE;
229
230   if (gadgets_initialized)
231     FreeGadgets();
232
233   CreateLevelEditorGadgets();
234   CreateGameButtons();
235   CreateTapeButtons();
236   CreateToolButtons();
237   CreateScreenGadgets();
238
239   gadgets_initialized = TRUE;
240 }
241
242 void InitElementSmallImages()
243 {
244   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
245   int num_property_mappings = getImageListPropertyMappingSize();
246   int i;
247
248   /* initialize normal images from static configuration */
249   for (i = 0; element_to_graphic[i].element > -1; i++)
250     CreateImageWithSmallImages(element_to_graphic[i].graphic);
251
252   /* initialize special images from static configuration */
253   for (i = 0; element_to_special_graphic[i].element > -1; i++)
254     CreateImageWithSmallImages(element_to_special_graphic[i].graphic);
255
256   /* initialize images from dynamic configuration */
257   for (i = 0; i < num_property_mappings; i++)
258     if (property_mapping[i].artwork_index < MAX_NUM_ELEMENTS)
259       CreateImageWithSmallImages(property_mapping[i].artwork_index);
260 }
261
262 static int getFontBitmapID(int font_nr)
263 {
264   int special = -1;
265
266   if (game_status >= GAME_MODE_MAIN && game_status <= GAME_MODE_PSEUDO_PREVIEW)
267     special = game_status;
268   else if (game_status == GAME_MODE_PSEUDO_TYPENAME)
269     special = GFX_SPECIAL_ARG_MAIN;
270   else if (game_status == GAME_MODE_PLAYING)
271     special = GFX_SPECIAL_ARG_DOOR;
272
273   if (special != -1)
274     return font_info[font_nr].special_bitmap_id[special];
275   else
276     return font_nr;
277 }
278
279 void InitFontGraphicInfo()
280 {
281   static struct FontBitmapInfo *font_bitmap_info = NULL;
282   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
283   int num_property_mappings = getImageListPropertyMappingSize();
284   int num_font_bitmaps = NUM_FONTS;
285   int i, j;
286
287   if (graphic_info == NULL)             /* still at startup phase */
288   {
289     InitFontInfo(font_initial, NUM_INITIAL_FONTS, getFontBitmapID);
290
291     return;
292   }
293
294   /* ---------- initialize font graphic definitions ---------- */
295
296   /* always start with reliable default values (normal font graphics) */
297 #if 1
298   for (i = 0; i < NUM_FONTS; i++)
299     font_info[i].graphic = IMG_FONT_INITIAL_1;
300 #else
301   for (i = 0; i < NUM_FONTS; i++)
302     font_info[i].graphic = FONT_INITIAL_1;
303 #endif
304
305   /* initialize normal font/graphic mapping from static configuration */
306   for (i = 0; font_to_graphic[i].font_nr > -1; i++)
307   {
308     int font_nr = font_to_graphic[i].font_nr;
309     int special = font_to_graphic[i].special;
310     int graphic = font_to_graphic[i].graphic;
311
312     if (special != -1)
313       continue;
314
315     font_info[font_nr].graphic = graphic;
316   }
317
318   /* always start with reliable default values (special font graphics) */
319   for (i = 0; i < NUM_FONTS; i++)
320   {
321     for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
322     {
323       font_info[i].special_graphic[j] = font_info[i].graphic;
324       font_info[i].special_bitmap_id[j] = i;
325     }
326   }
327
328   /* initialize special font/graphic mapping from static configuration */
329   for (i = 0; font_to_graphic[i].font_nr > -1; i++)
330   {
331     int font_nr = font_to_graphic[i].font_nr;
332     int special = font_to_graphic[i].special;
333     int graphic = font_to_graphic[i].graphic;
334
335     if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
336     {
337       font_info[font_nr].special_graphic[special] = graphic;
338       font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
339       num_font_bitmaps++;
340     }
341   }
342
343   /* initialize special element/graphic mapping from dynamic configuration */
344   for (i = 0; i < num_property_mappings; i++)
345   {
346     int font_nr = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
347     int special = property_mapping[i].ext3_index;
348     int graphic = property_mapping[i].artwork_index;
349
350     if (font_nr < 0)
351       continue;
352
353     if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
354     {
355       font_info[font_nr].special_graphic[special] = graphic;
356       font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
357       num_font_bitmaps++;
358     }
359   }
360
361   /* ---------- initialize font bitmap array ---------- */
362
363   if (font_bitmap_info != NULL)
364     FreeFontInfo(font_bitmap_info);
365
366   font_bitmap_info =
367     checked_calloc(num_font_bitmaps * sizeof(struct FontBitmapInfo));
368
369   /* ---------- initialize font bitmap definitions ---------- */
370
371   for (i = 0; i < NUM_FONTS; i++)
372   {
373     if (i < NUM_INITIAL_FONTS)
374     {
375       font_bitmap_info[i] = font_initial[i];
376       continue;
377     }
378
379     for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
380     {
381       int font_bitmap_id = font_info[i].special_bitmap_id[j];
382       int graphic = font_info[i].special_graphic[j];
383
384       /* set 'graphic_info' for font entries, if uninitialized (guessed) */
385       if (graphic_info[graphic].anim_frames < MIN_NUM_CHARS_PER_FONT)
386       {
387         graphic_info[graphic].anim_frames = DEFAULT_NUM_CHARS_PER_FONT;
388         graphic_info[graphic].anim_frames_per_line= DEFAULT_NUM_CHARS_PER_LINE;
389       }
390
391       /* copy font relevant information from graphics information */
392       font_bitmap_info[font_bitmap_id].bitmap = graphic_info[graphic].bitmap;
393       font_bitmap_info[font_bitmap_id].src_x  = graphic_info[graphic].src_x;
394       font_bitmap_info[font_bitmap_id].src_y  = graphic_info[graphic].src_y;
395       font_bitmap_info[font_bitmap_id].width  = graphic_info[graphic].width;
396       font_bitmap_info[font_bitmap_id].height = graphic_info[graphic].height;
397       font_bitmap_info[font_bitmap_id].draw_x = graphic_info[graphic].draw_x;
398       font_bitmap_info[font_bitmap_id].draw_y = graphic_info[graphic].draw_y;
399
400       font_bitmap_info[font_bitmap_id].num_chars =
401         graphic_info[graphic].anim_frames;
402       font_bitmap_info[font_bitmap_id].num_chars_per_line =
403         graphic_info[graphic].anim_frames_per_line;
404     }
405   }
406
407   InitFontInfo(font_bitmap_info, num_font_bitmaps, getFontBitmapID);
408 }
409
410 void InitElementGraphicInfo()
411 {
412   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
413   int num_property_mappings = getImageListPropertyMappingSize();
414   int i, act, dir;
415
416   if (graphic_info == NULL)             /* still at startup phase */
417     return;
418
419   /* set values to -1 to identify later as "uninitialized" values */
420   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
421   {
422     for (act = 0; act < NUM_ACTIONS; act++)
423     {
424       element_info[i].graphic[act] = -1;
425       element_info[i].crumbled[act] = -1;
426
427       for (dir = 0; dir < NUM_DIRECTIONS; dir++)
428       {
429         element_info[i].direction_graphic[act][dir] = -1;
430         element_info[i].direction_crumbled[act][dir] = -1;
431       }
432     }
433   }
434
435   /* initialize normal element/graphic mapping from static configuration */
436   for (i = 0; element_to_graphic[i].element > -1; i++)
437   {
438     int element      = element_to_graphic[i].element;
439     int action       = element_to_graphic[i].action;
440     int direction    = element_to_graphic[i].direction;
441     boolean crumbled = element_to_graphic[i].crumbled;
442     int graphic      = element_to_graphic[i].graphic;
443
444     if (graphic_info[graphic].bitmap == NULL)
445       continue;
446
447     if ((action > -1 || direction > -1 || crumbled == TRUE) &&
448         el2img(element) != -1)
449     {
450       boolean base_redefined = getImageListEntry(el2img(element))->redefined;
451       boolean act_dir_redefined = getImageListEntry(graphic)->redefined;
452
453       /* if the base graphic ("emerald", for example) has been redefined,
454          but not the action graphic ("emerald.falling", for example), do not
455          use an existing (in this case considered obsolete) action graphic
456          anymore, but use the automatically determined default graphic */
457       if (base_redefined && !act_dir_redefined)
458         continue;
459     }
460
461     if (action < 0)
462       action = ACTION_DEFAULT;
463
464     if (crumbled)
465     {
466       if (direction > -1)
467         element_info[element].direction_crumbled[action][direction] = graphic;
468       else
469         element_info[element].crumbled[action] = graphic;
470     }
471     else
472     {
473       if (direction > -1)
474         element_info[element].direction_graphic[action][direction] = graphic;
475       else
476         element_info[element].graphic[action] = graphic;
477     }
478   }
479
480   /* initialize normal element/graphic mapping from dynamic configuration */
481   for (i = 0; i < num_property_mappings; i++)
482   {
483     int element   = property_mapping[i].base_index;
484     int action    = property_mapping[i].ext1_index;
485     int direction = property_mapping[i].ext2_index;
486     int special   = property_mapping[i].ext3_index;
487     int graphic   = property_mapping[i].artwork_index;
488     boolean crumbled = FALSE;
489
490     if (special == GFX_SPECIAL_ARG_CRUMBLED)
491     {
492       special = -1;
493       crumbled = TRUE;
494     }
495
496     if (graphic_info[graphic].bitmap == NULL)
497       continue;
498
499     if (element >= MAX_NUM_ELEMENTS || special != -1)
500       continue;
501
502     if (action < 0)
503       action = ACTION_DEFAULT;
504
505     if (crumbled)
506     {
507       if (direction < 0)
508         for (dir = 0; dir < NUM_DIRECTIONS; dir++)
509           element_info[element].direction_crumbled[action][dir] = -1;
510
511       if (direction > -1)
512         element_info[element].direction_crumbled[action][direction] = graphic;
513       else
514         element_info[element].crumbled[action] = graphic;
515     }
516     else
517     {
518       if (direction < 0)
519         for (dir = 0; dir < NUM_DIRECTIONS; dir++)
520           element_info[element].direction_graphic[action][dir] = -1;
521
522       if (direction > -1)
523         element_info[element].direction_graphic[action][direction] = graphic;
524       else
525         element_info[element].graphic[action] = graphic;
526     }
527   }
528
529   /* now copy all graphics that are defined to be cloned from other graphics */
530   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
531   {
532     int graphic = element_info[i].graphic[ACTION_DEFAULT];
533     int crumbled_like, diggable_like;
534
535     if (graphic == -1)
536       continue;
537
538     crumbled_like = graphic_info[graphic].crumbled_like;
539     diggable_like = graphic_info[graphic].diggable_like;
540
541     if (crumbled_like != -1 && element_info[i].crumbled[ACTION_DEFAULT] == -1)
542     {
543       for (act = 0; act < NUM_ACTIONS; act++)
544         element_info[i].crumbled[act] =
545           element_info[crumbled_like].crumbled[act];
546       for (act = 0; act < NUM_ACTIONS; act++)
547         for (dir = 0; dir < NUM_DIRECTIONS; dir++)
548           element_info[i].direction_crumbled[act][dir] =
549             element_info[crumbled_like].direction_crumbled[act][dir];
550     }
551
552     if (diggable_like != -1 && element_info[i].graphic[ACTION_DIGGING] == -1)
553     {
554       element_info[i].graphic[ACTION_DIGGING] =
555         element_info[diggable_like].graphic[ACTION_DIGGING];
556       for (dir = 0; dir < NUM_DIRECTIONS; dir++)
557         element_info[i].direction_graphic[ACTION_DIGGING][dir] =
558           element_info[diggable_like].direction_graphic[ACTION_DIGGING][dir];
559     }
560   }
561
562 #if 1
563   /* now set all undefined/invalid graphics to -1 to set to default after it */
564   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
565   {
566     for (act = 0; act < NUM_ACTIONS; act++)
567     {
568       int graphic;
569
570       graphic = element_info[i].graphic[act];
571       if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
572         element_info[i].graphic[act] = -1;
573
574       graphic = element_info[i].crumbled[act];
575       if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
576         element_info[i].crumbled[act] = -1;
577
578       for (dir = 0; dir < NUM_DIRECTIONS; dir++)
579       {
580         graphic = element_info[i].direction_graphic[act][dir];
581         if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
582           element_info[i].direction_graphic[act][dir] = -1;
583
584         graphic = element_info[i].direction_crumbled[act][dir];
585         if (graphic > 0 && graphic_info[graphic].bitmap == NULL)
586           element_info[i].direction_crumbled[act][dir] = -1;
587       }
588     }
589   }
590 #endif
591
592   /* now set all '-1' values to element specific default values */
593   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
594   {
595     int default_graphic = element_info[i].graphic[ACTION_DEFAULT];
596     int default_crumbled = element_info[i].crumbled[ACTION_DEFAULT];
597     int default_direction_graphic[NUM_DIRECTIONS];
598     int default_direction_crumbled[NUM_DIRECTIONS];
599
600     if (default_graphic == -1)
601       default_graphic = IMG_UNKNOWN;
602     if (default_crumbled == -1)
603       default_crumbled = IMG_EMPTY;
604
605     for (dir = 0; dir < NUM_DIRECTIONS; dir++)
606     {
607       default_direction_graphic[dir] =
608         element_info[i].direction_graphic[ACTION_DEFAULT][dir];
609       default_direction_crumbled[dir] =
610         element_info[i].direction_crumbled[ACTION_DEFAULT][dir];
611
612       if (default_direction_graphic[dir] == -1)
613         default_direction_graphic[dir] = default_graphic;
614       if (default_direction_crumbled[dir] == -1)
615         default_direction_crumbled[dir] = default_crumbled;
616     }
617
618     for (act = 0; act < NUM_ACTIONS; act++)
619     {
620       boolean act_remove = ((IS_DIGGABLE(i)    && act == ACTION_DIGGING)  ||
621                             (IS_SNAPPABLE(i)   && act == ACTION_SNAPPING) ||
622                             (IS_COLLECTIBLE(i) && act == ACTION_COLLECTING));
623       boolean act_turning = (act == ACTION_TURNING_FROM_LEFT ||
624                              act == ACTION_TURNING_FROM_RIGHT ||
625                              act == ACTION_TURNING_FROM_UP ||
626                              act == ACTION_TURNING_FROM_DOWN);
627
628       /* generic default action graphic (defined by "[default]" directive) */
629       int default_action_graphic = element_info[EL_DEFAULT].graphic[act];
630       int default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
631
632       /* look for special default action graphic (classic game specific) */
633       if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].graphic[act] != -1)
634         default_action_graphic = element_info[EL_BD_DEFAULT].graphic[act];
635       if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].graphic[act] != -1)
636         default_action_graphic = element_info[EL_SP_DEFAULT].graphic[act];
637       if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].graphic[act] != -1)
638         default_action_graphic = element_info[EL_SB_DEFAULT].graphic[act];
639
640       if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].crumbled[act] != -1)
641         default_action_crumbled = element_info[EL_BD_DEFAULT].crumbled[act];
642       if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].crumbled[act] != -1)
643         default_action_crumbled = element_info[EL_SP_DEFAULT].crumbled[act];
644       if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].crumbled[act] != -1)
645         default_action_crumbled = element_info[EL_SB_DEFAULT].crumbled[act];
646
647 #if 1
648       /* !!! make this better !!! */
649       if (i == EL_EMPTY_SPACE)
650       {
651         default_action_graphic = element_info[EL_DEFAULT].graphic[act];
652         default_action_crumbled = element_info[EL_DEFAULT].crumbled[act];
653       }
654 #endif
655
656       if (default_action_graphic == -1)
657         default_action_graphic = default_graphic;
658       if (default_action_crumbled == -1)
659         default_action_crumbled = default_crumbled;
660
661       for (dir = 0; dir < NUM_DIRECTIONS; dir++)
662       {
663         int default_action_direction_graphic = element_info[i].graphic[act];
664         int default_action_direction_crumbled = element_info[i].crumbled[act];
665
666         /* no graphic for current action -- use default direction graphic */
667         if (default_action_direction_graphic == -1)
668           default_action_direction_graphic =
669             (act_remove ? IMG_EMPTY :
670              act_turning ?
671              element_info[i].direction_graphic[ACTION_TURNING][dir] :
672              default_direction_graphic[dir]);
673         if (default_action_direction_crumbled == -1)
674           default_action_direction_crumbled =
675             (act_remove ? IMG_EMPTY :
676              act_turning ?
677              element_info[i].direction_crumbled[ACTION_TURNING][dir] :
678              default_direction_crumbled[dir]);
679
680         if (element_info[i].direction_graphic[act][dir] == -1)
681           element_info[i].direction_graphic[act][dir] =
682             default_action_direction_graphic;
683         if (element_info[i].direction_crumbled[act][dir] == -1)
684           element_info[i].direction_crumbled[act][dir] =
685             default_action_direction_crumbled;
686       }
687
688       /* no graphic for this specific action -- use default action graphic */
689       if (element_info[i].graphic[act] == -1)
690         element_info[i].graphic[act] =
691           (act_remove ? IMG_EMPTY :
692            act_turning ? element_info[i].graphic[ACTION_TURNING] :
693            default_action_graphic);
694       if (element_info[i].crumbled[act] == -1)
695         element_info[i].crumbled[act] =
696           (act_remove ? IMG_EMPTY :
697            act_turning ? element_info[i].crumbled[ACTION_TURNING] :
698            default_action_crumbled);
699     }
700   }
701
702 #if 1
703   /* set animation mode to "none" for each graphic with only 1 frame */
704   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
705   {
706     for (act = 0; act < NUM_ACTIONS; act++)
707     {
708       int graphic = element_info[i].graphic[act];
709       int crumbled = element_info[i].crumbled[act];
710
711       if (graphic_info[graphic].anim_frames == 1)
712         graphic_info[graphic].anim_mode = ANIM_NONE;
713       if (graphic_info[crumbled].anim_frames == 1)
714         graphic_info[crumbled].anim_mode = ANIM_NONE;
715
716       for (dir = 0; dir < NUM_DIRECTIONS; dir++)
717       {
718         graphic = element_info[i].direction_graphic[act][dir];
719         crumbled = element_info[i].direction_crumbled[act][dir];
720
721         if (graphic_info[graphic].anim_frames == 1)
722           graphic_info[graphic].anim_mode = ANIM_NONE;
723         if (graphic_info[crumbled].anim_frames == 1)
724           graphic_info[crumbled].anim_mode = ANIM_NONE;
725       }
726     }
727   }
728 #endif
729
730 #if 0
731 #if DEBUG
732   if (options.verbose)
733   {
734     for (i = 0; i < MAX_NUM_ELEMENTS; i++)
735       if (element_info[i].graphic[ACTION_DEFAULT] == IMG_UNKNOWN &&
736           i != EL_UNKNOWN)
737         Error(ERR_RETURN, "warning: no graphic for element '%s' (%d)",
738               element_info[i].token_name, i);
739   }
740 #endif
741 #endif
742 }
743
744 void InitElementSpecialGraphicInfo()
745 {
746   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
747   int num_property_mappings = getImageListPropertyMappingSize();
748   int i, j;
749
750   /* always start with reliable default values */
751   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
752     for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
753       element_info[i].special_graphic[j] =
754         element_info[i].graphic[ACTION_DEFAULT];
755
756   /* initialize special element/graphic mapping from static configuration */
757   for (i = 0; element_to_special_graphic[i].element > -1; i++)
758   {
759     int element = element_to_special_graphic[i].element;
760     int special = element_to_special_graphic[i].special;
761     int graphic = element_to_special_graphic[i].graphic;
762     boolean base_redefined = getImageListEntry(el2img(element))->redefined;
763     boolean special_redefined = getImageListEntry(graphic)->redefined;
764
765     /* if the base graphic ("emerald", for example) has been redefined,
766        but not the special graphic ("emerald.EDITOR", for example), do not
767        use an existing (in this case considered obsolete) special graphic
768        anymore, but use the automatically created (down-scaled) graphic */
769     if (base_redefined && !special_redefined)
770       continue;
771
772     element_info[element].special_graphic[special] = graphic;
773   }
774
775   /* initialize special element/graphic mapping from dynamic configuration */
776   for (i = 0; i < num_property_mappings; i++)
777   {
778     int element = property_mapping[i].base_index;
779     int special = property_mapping[i].ext3_index;
780     int graphic = property_mapping[i].artwork_index;
781
782     if (element >= MAX_NUM_ELEMENTS)
783       continue;
784
785     if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
786       element_info[element].special_graphic[special] = graphic;
787   }
788
789 #if 1
790   /* now set all undefined/invalid graphics to default */
791   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
792     for (j = 0; j < NUM_SPECIAL_GFX_ARGS; j++)
793       if (graphic_info[element_info[i].special_graphic[j]].bitmap == NULL)
794         element_info[i].special_graphic[j] =
795           element_info[i].graphic[ACTION_DEFAULT];
796 #endif
797 }
798
799 static int get_element_from_token(char *token)
800 {
801   int i;
802
803   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
804     if (strcmp(element_info[i].token_name, token) == 0)
805       return i;
806
807   return -1;
808 }
809
810 static void set_graphic_parameters(int graphic, char **parameter_raw)
811 {
812   Bitmap *src_bitmap = getBitmapFromImageID(graphic);
813   int parameter[NUM_GFX_ARGS];
814   int anim_frames_per_row = 1, anim_frames_per_col = 1;
815   int anim_frames_per_line = 1;
816   int i;
817
818   /* get integer values from string parameters */
819   for (i = 0; i < NUM_GFX_ARGS; i++)
820   {
821     parameter[i] =
822       get_parameter_value(image_config_suffix[i].token, parameter_raw[i],
823                           image_config_suffix[i].type);
824
825     if (image_config_suffix[i].type == TYPE_TOKEN)
826       parameter[i] = get_element_from_token(parameter_raw[i]);
827   }
828
829   graphic_info[graphic].bitmap = src_bitmap;
830
831   /* start with reliable default values */
832   graphic_info[graphic].src_x = 0;
833   graphic_info[graphic].src_y = 0;
834   graphic_info[graphic].width = TILEX;
835   graphic_info[graphic].height = TILEY;
836   graphic_info[graphic].offset_x = 0;   /* one or both of these values ... */
837   graphic_info[graphic].offset_y = 0;   /* ... will be corrected later */
838   graphic_info[graphic].crumbled_like = -1;     /* do not use clone element */
839   graphic_info[graphic].diggable_like = -1;     /* do not use clone element */
840   graphic_info[graphic].border_size = TILEX / 8;  /* "CRUMBLED" border size */
841   graphic_info[graphic].anim_delay_fixed = 0;
842   graphic_info[graphic].anim_delay_random = 0;
843   graphic_info[graphic].post_delay_fixed = 0;
844   graphic_info[graphic].post_delay_random = 0;
845
846   /* optional x and y tile position of animation frame sequence */
847   if (parameter[GFX_ARG_XPOS] != ARG_UNDEFINED_VALUE)
848     graphic_info[graphic].src_x = parameter[GFX_ARG_XPOS] * TILEX;
849   if (parameter[GFX_ARG_YPOS] != ARG_UNDEFINED_VALUE)
850     graphic_info[graphic].src_y = parameter[GFX_ARG_YPOS] * TILEY;
851
852   /* optional x and y pixel position of animation frame sequence */
853   if (parameter[GFX_ARG_X] != ARG_UNDEFINED_VALUE)
854     graphic_info[graphic].src_x = parameter[GFX_ARG_X];
855   if (parameter[GFX_ARG_Y] != ARG_UNDEFINED_VALUE)
856     graphic_info[graphic].src_y = parameter[GFX_ARG_Y];
857
858   /* optional width and height of each animation frame */
859   if (parameter[GFX_ARG_WIDTH] != ARG_UNDEFINED_VALUE)
860     graphic_info[graphic].width = parameter[GFX_ARG_WIDTH];
861   if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE)
862     graphic_info[graphic].height = parameter[GFX_ARG_HEIGHT];
863
864   if (src_bitmap)
865   {
866     anim_frames_per_row = src_bitmap->width  / graphic_info[graphic].width;
867     anim_frames_per_col = src_bitmap->height / graphic_info[graphic].height;
868   }
869
870   /* correct x or y offset dependent of vertical or horizontal frame order */
871   if (parameter[GFX_ARG_VERTICAL])      /* frames are ordered vertically */
872   {
873     graphic_info[graphic].offset_y =
874       (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
875        parameter[GFX_ARG_OFFSET] : graphic_info[graphic].height);
876     anim_frames_per_line = anim_frames_per_col;
877   }
878   else                                  /* frames are ordered horizontally */
879   {
880     graphic_info[graphic].offset_x =
881       (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
882        parameter[GFX_ARG_OFFSET] : graphic_info[graphic].width);
883     anim_frames_per_line = anim_frames_per_row;
884   }
885
886   /* optionally, the x and y offset of frames can be specified directly */
887   if (parameter[GFX_ARG_XOFFSET] != ARG_UNDEFINED_VALUE)
888     graphic_info[graphic].offset_x = parameter[GFX_ARG_XOFFSET];
889   if (parameter[GFX_ARG_YOFFSET] != ARG_UNDEFINED_VALUE)
890     graphic_info[graphic].offset_y = parameter[GFX_ARG_YOFFSET];
891
892   /* automatically determine correct number of frames, if not defined */
893   if (parameter[GFX_ARG_FRAMES] != ARG_UNDEFINED_VALUE)
894     graphic_info[graphic].anim_frames = parameter[GFX_ARG_FRAMES];
895   else if (parameter[GFX_ARG_XPOS] == 0 && !parameter[GFX_ARG_VERTICAL])
896     graphic_info[graphic].anim_frames = anim_frames_per_row;
897   else if (parameter[GFX_ARG_YPOS] == 0 && parameter[GFX_ARG_VERTICAL])
898     graphic_info[graphic].anim_frames = anim_frames_per_col;
899   else
900     graphic_info[graphic].anim_frames = 1;
901
902   graphic_info[graphic].anim_frames_per_line =
903     (parameter[GFX_ARG_FRAMES_PER_LINE] != ARG_UNDEFINED_VALUE ?
904      parameter[GFX_ARG_FRAMES_PER_LINE] : anim_frames_per_line);
905
906   graphic_info[graphic].anim_delay = parameter[GFX_ARG_DELAY];
907   if (graphic_info[graphic].anim_delay == 0)    /* delay must be at least 1 */
908     graphic_info[graphic].anim_delay = 1;
909
910   graphic_info[graphic].anim_mode = parameter[GFX_ARG_ANIM_MODE];
911 #if 0
912   if (graphic_info[graphic].anim_frames == 1)
913     graphic_info[graphic].anim_mode = ANIM_NONE;
914 #endif
915
916   /* automatically determine correct start frame, if not defined */
917   if (parameter[GFX_ARG_START_FRAME] == ARG_UNDEFINED_VALUE)
918     graphic_info[graphic].anim_start_frame = 0;
919   else if (graphic_info[graphic].anim_mode & ANIM_REVERSE)
920     graphic_info[graphic].anim_start_frame =
921       graphic_info[graphic].anim_frames - parameter[GFX_ARG_START_FRAME] - 1;
922   else
923     graphic_info[graphic].anim_start_frame = parameter[GFX_ARG_START_FRAME];
924
925   /* animation synchronized with global frame counter, not move position */
926   graphic_info[graphic].anim_global_sync = parameter[GFX_ARG_GLOBAL_SYNC];
927
928   /* optional element for cloning crumble graphics */
929   if (parameter[GFX_ARG_CRUMBLED_LIKE] != ARG_UNDEFINED_VALUE)
930     graphic_info[graphic].crumbled_like = parameter[GFX_ARG_CRUMBLED_LIKE];
931
932   /* optional element for cloning digging graphics */
933   if (parameter[GFX_ARG_DIGGABLE_LIKE] != ARG_UNDEFINED_VALUE)
934     graphic_info[graphic].diggable_like = parameter[GFX_ARG_DIGGABLE_LIKE];
935
936   /* optional border size for "crumbling" diggable graphics */
937   if (parameter[GFX_ARG_BORDER_SIZE] != ARG_UNDEFINED_VALUE)
938     graphic_info[graphic].border_size = parameter[GFX_ARG_BORDER_SIZE];
939
940   /* this is only used for player "boring" and "sleeping" actions */
941   if (parameter[GFX_ARG_ANIM_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
942     graphic_info[graphic].anim_delay_fixed =
943       parameter[GFX_ARG_ANIM_DELAY_FIXED];
944   if (parameter[GFX_ARG_ANIM_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
945     graphic_info[graphic].anim_delay_random =
946       parameter[GFX_ARG_ANIM_DELAY_RANDOM];
947   if (parameter[GFX_ARG_POST_DELAY_FIXED] != ARG_UNDEFINED_VALUE)
948     graphic_info[graphic].post_delay_fixed =
949       parameter[GFX_ARG_POST_DELAY_FIXED];
950   if (parameter[GFX_ARG_POST_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
951     graphic_info[graphic].post_delay_random =
952       parameter[GFX_ARG_POST_DELAY_RANDOM];
953
954   /* this is only used for toon animations */
955   graphic_info[graphic].step_offset = parameter[GFX_ARG_STEP_OFFSET];
956   graphic_info[graphic].step_delay  = parameter[GFX_ARG_STEP_DELAY];
957
958   /* this is only used for drawing font characters */
959   graphic_info[graphic].draw_x = parameter[GFX_ARG_DRAW_XOFFSET];
960   graphic_info[graphic].draw_y = parameter[GFX_ARG_DRAW_YOFFSET];
961
962   /* this is only used for drawing envelope graphics */
963   graphic_info[graphic].draw_masked = parameter[GFX_ARG_DRAW_MASKED];
964 }
965
966 static void InitGraphicInfo()
967 {
968   int fallback_graphic = IMG_CHAR_EXCLAM;
969   struct FileInfo *fallback_image = getImageListEntry(fallback_graphic);
970   Bitmap *fallback_bitmap = getBitmapFromImageID(fallback_graphic);
971   int num_images = getImageListSize();
972   int i;
973
974 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
975   static boolean clipmasks_initialized = FALSE;
976   Pixmap src_pixmap;
977   XGCValues clip_gc_values;
978   unsigned long clip_gc_valuemask;
979   GC copy_clipmask_gc = None;
980 #endif
981
982   checked_free(graphic_info);
983
984   graphic_info = checked_calloc(num_images * sizeof(struct GraphicInfo));
985
986 #if 0
987   printf("::: graphic_info: %d entries\n", num_images);
988 #endif
989
990 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
991   if (clipmasks_initialized)
992   {
993     for (i = 0; i < num_images; i++)
994     {
995       if (graphic_info[i].clip_mask)
996         XFreePixmap(display, graphic_info[i].clip_mask);
997       if (graphic_info[i].clip_gc)
998         XFreeGC(display, graphic_info[i].clip_gc);
999
1000       graphic_info[i].clip_mask = None;
1001       graphic_info[i].clip_gc = None;
1002     }
1003   }
1004 #endif
1005
1006   for (i = 0; i < num_images; i++)
1007   {
1008     struct FileInfo *image = getImageListEntry(i);
1009     Bitmap *src_bitmap;
1010     int src_x, src_y;
1011     int first_frame, last_frame;
1012
1013 #if 0
1014     printf("::: image: '%s' [%d]\n", image->token, i);
1015 #endif
1016
1017 #if 0
1018     printf("::: image # %d: '%s' ['%s']\n",
1019            i, image->token,
1020            getTokenFromImageID(i));
1021 #endif
1022
1023     set_graphic_parameters(i, image->parameter);
1024
1025     /* now check if no animation frames are outside of the loaded image */
1026
1027     if (graphic_info[i].bitmap == NULL)
1028       continue;         /* skip check for optional images that are undefined */
1029
1030     first_frame = 0;
1031     getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
1032     if (src_x < 0 || src_y < 0 ||
1033         src_x + TILEX > src_bitmap->width ||
1034         src_y + TILEY > src_bitmap->height)
1035     {
1036       Error(ERR_RETURN_LINE, "-");
1037       Error(ERR_RETURN, "warning: error found in config file:");
1038       Error(ERR_RETURN, "- config file: '%s'",
1039             getImageConfigFilename());
1040       Error(ERR_RETURN, "- config token: '%s'",
1041             getTokenFromImageID(i));
1042       Error(ERR_RETURN, "- image file: '%s'",
1043             src_bitmap->source_filename);
1044       Error(ERR_RETURN,
1045             "error: first animation frame out of bounds (%d, %d)",
1046             src_x, src_y);
1047       Error(ERR_RETURN, "custom graphic rejected for this element/action");
1048
1049       if (i == fallback_graphic)
1050         Error(ERR_EXIT, "fatal error: no fallback graphic available");
1051
1052       Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
1053       Error(ERR_RETURN_LINE, "-");
1054
1055       set_graphic_parameters(i, fallback_image->default_parameter);
1056       graphic_info[i].bitmap = fallback_bitmap;
1057     }
1058
1059     last_frame = graphic_info[i].anim_frames - 1;
1060     getGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y);
1061     if (src_x < 0 || src_y < 0 ||
1062         src_x + TILEX > src_bitmap->width ||
1063         src_y + TILEY > src_bitmap->height)
1064     {
1065       Error(ERR_RETURN_LINE, "-");
1066       Error(ERR_RETURN, "warning: error found in config file:");
1067       Error(ERR_RETURN, "- config file: '%s'",
1068             getImageConfigFilename());
1069       Error(ERR_RETURN, "- config token: '%s'",
1070             getTokenFromImageID(i));
1071       Error(ERR_RETURN, "- image file: '%s'",
1072             src_bitmap->source_filename);
1073       Error(ERR_RETURN,
1074             "error: last animation frame (%d) out of bounds (%d, %d)",
1075             last_frame, src_x, src_y);
1076       Error(ERR_RETURN, "custom graphic rejected for this element/action");
1077
1078       if (i == fallback_graphic)
1079         Error(ERR_EXIT, "fatal error: no fallback graphic available");
1080
1081       Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
1082       Error(ERR_RETURN_LINE, "-");
1083
1084       set_graphic_parameters(i, fallback_image->default_parameter);
1085       graphic_info[i].bitmap = fallback_bitmap;
1086     }
1087
1088 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1089     /* currently we need only a tile clip mask from the first frame */
1090     getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
1091
1092     if (copy_clipmask_gc == None)
1093     {
1094       clip_gc_values.graphics_exposures = False;
1095       clip_gc_valuemask = GCGraphicsExposures;
1096       copy_clipmask_gc = XCreateGC(display, src_bitmap->clip_mask,
1097                                    clip_gc_valuemask, &clip_gc_values);
1098     }
1099
1100     graphic_info[i].clip_mask =
1101       XCreatePixmap(display, window->drawable, TILEX, TILEY, 1);
1102
1103     src_pixmap = src_bitmap->clip_mask;
1104     XCopyArea(display, src_pixmap, graphic_info[i].clip_mask,
1105               copy_clipmask_gc, src_x, src_y, TILEX, TILEY, 0, 0);
1106
1107     clip_gc_values.graphics_exposures = False;
1108     clip_gc_values.clip_mask = graphic_info[i].clip_mask;
1109     clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
1110
1111     graphic_info[i].clip_gc =
1112       XCreateGC(display, window->drawable, clip_gc_valuemask, &clip_gc_values);
1113 #endif
1114   }
1115
1116 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1117   if (copy_clipmask_gc)
1118     XFreeGC(display, copy_clipmask_gc);
1119
1120   clipmasks_initialized = TRUE;
1121 #endif
1122 }
1123
1124 static void InitElementSoundInfo()
1125 {
1126   struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1127   int num_property_mappings = getSoundListPropertyMappingSize();
1128   int i, j, act;
1129
1130   /* set values to -1 to identify later as "uninitialized" values */
1131   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1132     for (act = 0; act < NUM_ACTIONS; act++)
1133       element_info[i].sound[act] = -1;
1134
1135   /* initialize element/sound mapping from static configuration */
1136   for (i = 0; element_to_sound[i].element > -1; i++)
1137   {
1138     int element      = element_to_sound[i].element;
1139     int action       = element_to_sound[i].action;
1140     int sound        = element_to_sound[i].sound;
1141     boolean is_class = element_to_sound[i].is_class;
1142
1143     if (action < 0)
1144       action = ACTION_DEFAULT;
1145
1146     if (!is_class)
1147       element_info[element].sound[action] = sound;
1148     else
1149       for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1150         if (strcmp(element_info[j].class_name,
1151                    element_info[element].class_name) == 0)
1152           element_info[j].sound[action] = sound;
1153   }
1154
1155   /* initialize element class/sound mapping from dynamic configuration */
1156   for (i = 0; i < num_property_mappings; i++)
1157   {
1158     int element_class = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
1159     int action        = property_mapping[i].ext1_index;
1160     int sound         = property_mapping[i].artwork_index;
1161
1162     if (element_class < 0 || element_class >= MAX_NUM_ELEMENTS)
1163       continue;
1164
1165     if (action < 0)
1166       action = ACTION_DEFAULT;
1167
1168     for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1169       if (strcmp(element_info[j].class_name,
1170                  element_info[element_class].class_name) == 0)
1171         element_info[j].sound[action] = sound;
1172   }
1173
1174   /* initialize element/sound mapping from dynamic configuration */
1175   for (i = 0; i < num_property_mappings; i++)
1176   {
1177     int element = property_mapping[i].base_index;
1178     int action  = property_mapping[i].ext1_index;
1179     int sound   = property_mapping[i].artwork_index;
1180
1181     if (element >= MAX_NUM_ELEMENTS)
1182       continue;
1183
1184     if (action < 0)
1185       action = ACTION_DEFAULT;
1186
1187     element_info[element].sound[action] = sound;
1188   }
1189
1190   /* now set all '-1' values to element specific default values */
1191   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1192   {
1193     for (act = 0; act < NUM_ACTIONS; act++)
1194     {
1195       /* generic default action sound (defined by "[default]" directive) */
1196       int default_action_sound = element_info[EL_DEFAULT].sound[act];
1197
1198       /* look for special default action sound (classic game specific) */
1199       if (IS_BD_ELEMENT(i) && element_info[EL_BD_DEFAULT].sound[act] != -1)
1200         default_action_sound = element_info[EL_BD_DEFAULT].sound[act];
1201       if (IS_SP_ELEMENT(i) && element_info[EL_SP_DEFAULT].sound[act] != -1)
1202         default_action_sound = element_info[EL_SP_DEFAULT].sound[act];
1203       if (IS_SB_ELEMENT(i) && element_info[EL_SB_DEFAULT].sound[act] != -1)
1204         default_action_sound = element_info[EL_SB_DEFAULT].sound[act];
1205
1206       /* !!! there's no such thing as a "default action sound" !!! */
1207 #if 0
1208       /* look for element specific default sound (independent from action) */
1209       if (element_info[i].sound[ACTION_DEFAULT] != -1)
1210         default_action_sound = element_info[i].sound[ACTION_DEFAULT];
1211 #endif
1212
1213       /* no sound for this specific action -- use default action sound */
1214       if (element_info[i].sound[act] == -1)
1215         element_info[i].sound[act] = default_action_sound;
1216     }
1217   }
1218 }
1219
1220 static void InitGameModeSoundInfo()
1221 {
1222   int i;
1223
1224   /* set values to -1 to identify later as "uninitialized" values */
1225   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1226     menu.sound[i] = -1;
1227
1228   /* initialize gamemode/sound mapping from static configuration */
1229   for (i = 0; gamemode_to_sound[i].sound > -1; i++)
1230   {
1231     int gamemode = gamemode_to_sound[i].gamemode;
1232     int sound    = gamemode_to_sound[i].sound;
1233
1234     if (gamemode < 0)
1235       gamemode = GAME_MODE_DEFAULT;
1236
1237     menu.sound[gamemode] = sound;
1238   }
1239
1240   /* now set all '-1' values to levelset specific default values */
1241   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1242     if (menu.sound[i] == -1)
1243       menu.sound[i] = menu.sound[GAME_MODE_DEFAULT];
1244
1245 #if 0
1246   /* TEST ONLY */
1247   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1248     if (menu.sound[i] != -1)
1249       printf("::: menu.sound[%d] == %d\n", i, menu.sound[i]);
1250 #endif
1251 }
1252
1253 static void set_sound_parameters(int sound, char **parameter_raw)
1254 {
1255   int parameter[NUM_SND_ARGS];
1256   int i;
1257
1258   /* get integer values from string parameters */
1259   for (i = 0; i < NUM_SND_ARGS; i++)
1260     parameter[i] =
1261       get_parameter_value(sound_config_suffix[i].token, parameter_raw[i],
1262                           sound_config_suffix[i].type);
1263
1264   /* explicit loop mode setting in configuration overrides default value */
1265   if (parameter[SND_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
1266     sound_info[sound].loop = parameter[SND_ARG_MODE_LOOP];
1267 }
1268
1269 static void InitSoundInfo()
1270 {
1271 #if 0
1272   struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
1273   int num_property_mappings = getSoundListPropertyMappingSize();
1274 #endif
1275   int *sound_effect_properties;
1276   int num_sounds = getSoundListSize();
1277   int i, j;
1278
1279   checked_free(sound_info);
1280
1281   sound_effect_properties = checked_calloc(num_sounds * sizeof(int));
1282   sound_info = checked_calloc(num_sounds * sizeof(struct SoundInfo));
1283
1284   /* initialize sound effect for all elements to "no sound" */
1285   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
1286     for (j = 0; j < NUM_ACTIONS; j++)
1287       element_info[i].sound[j] = SND_UNDEFINED;
1288
1289   for (i = 0; i < num_sounds; i++)
1290   {
1291     struct FileInfo *sound = getSoundListEntry(i);
1292     int len_effect_text = strlen(sound->token);
1293
1294     sound_effect_properties[i] = ACTION_OTHER;
1295     sound_info[i].loop = FALSE;         /* default: play sound only once */
1296
1297 #if 0
1298     printf("::: sound %d: '%s'\n", i, sound->token);
1299 #endif
1300
1301     /* determine all loop sounds and identify certain sound classes */
1302
1303     for (j = 0; element_action_info[j].suffix; j++)
1304     {
1305       int len_action_text = strlen(element_action_info[j].suffix);
1306
1307       if (len_action_text < len_effect_text &&
1308           strcmp(&sound->token[len_effect_text - len_action_text],
1309                  element_action_info[j].suffix) == 0)
1310       {
1311         sound_effect_properties[i] = element_action_info[j].value;
1312         sound_info[i].loop = element_action_info[j].is_loop_sound;
1313
1314         break;
1315       }
1316     }
1317
1318 #if 0
1319     if (strcmp(sound->token, "custom_42") == 0)
1320       printf("::: '%s' -> %d\n", sound->token, sound_info[i].loop);
1321 #endif
1322
1323     /* associate elements and some selected sound actions */
1324
1325     for (j = 0; j < MAX_NUM_ELEMENTS; j++)
1326     {
1327       if (element_info[j].class_name)
1328       {
1329         int len_class_text = strlen(element_info[j].class_name);
1330
1331         if (len_class_text + 1 < len_effect_text &&
1332             strncmp(sound->token,
1333                     element_info[j].class_name, len_class_text) == 0 &&
1334             sound->token[len_class_text] == '.')
1335         {
1336           int sound_action_value = sound_effect_properties[i];
1337
1338           element_info[j].sound[sound_action_value] = i;
1339         }
1340       }
1341     }
1342
1343     set_sound_parameters(i, sound->parameter);
1344   }
1345
1346   free(sound_effect_properties);
1347
1348 #if 0
1349   /* !!! now handled in InitElementSoundInfo() !!! */
1350   /* initialize element/sound mapping from dynamic configuration */
1351   for (i = 0; i < num_property_mappings; i++)
1352   {
1353     int element   = property_mapping[i].base_index;
1354     int action    = property_mapping[i].ext1_index;
1355     int sound     = property_mapping[i].artwork_index;
1356
1357     if (action < 0)
1358       action = ACTION_DEFAULT;
1359
1360     printf("::: %d: %d, %d, %d ['%s']\n",
1361            i, element, action, sound, element_info[element].token_name);
1362
1363     element_info[element].sound[action] = sound;
1364   }
1365 #endif
1366
1367 #if 0
1368   /* TEST ONLY */
1369   {
1370     int element = EL_CUSTOM_11;
1371     int j = 0;
1372
1373     while (element_action_info[j].suffix)
1374     {
1375       printf("element %d, sound action '%s'  == %d\n",
1376              element, element_action_info[j].suffix,
1377              element_info[element].sound[j]);
1378       j++;
1379     }
1380   }
1381
1382   PlaySoundLevelElementAction(0,0, EL_CUSTOM_11, ACTION_PUSHING);
1383 #endif
1384
1385 #if 0
1386   /* TEST ONLY */
1387   {
1388     int element = EL_SAND;
1389     int sound_action = ACTION_DIGGING;
1390     int j = 0;
1391
1392     while (element_action_info[j].suffix)
1393     {
1394       if (element_action_info[j].value == sound_action)
1395         printf("element %d, sound action '%s'  == %d\n",
1396                element, element_action_info[j].suffix,
1397                element_info[element].sound[sound_action]);
1398       j++;
1399     }
1400   }
1401 #endif
1402 }
1403
1404 static void InitGameModeMusicInfo()
1405 {
1406   struct PropertyMapping *property_mapping = getMusicListPropertyMapping();
1407   int num_property_mappings = getMusicListPropertyMappingSize();
1408   int default_levelset_music = -1;
1409   int i;
1410
1411   /* set values to -1 to identify later as "uninitialized" values */
1412   for (i = 0; i < MAX_LEVELS; i++)
1413     levelset.music[i] = -1;
1414   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1415     menu.music[i] = -1;
1416
1417   /* initialize gamemode/music mapping from static configuration */
1418   for (i = 0; gamemode_to_music[i].music > -1; i++)
1419   {
1420     int gamemode = gamemode_to_music[i].gamemode;
1421     int music    = gamemode_to_music[i].music;
1422
1423 #if 0
1424     printf("::: gamemode == %d, music == %d\n", gamemode, music);
1425 #endif
1426
1427     if (gamemode < 0)
1428       gamemode = GAME_MODE_DEFAULT;
1429
1430     menu.music[gamemode] = music;
1431   }
1432
1433   /* initialize gamemode/music mapping from dynamic configuration */
1434   for (i = 0; i < num_property_mappings; i++)
1435   {
1436     int prefix   = property_mapping[i].base_index;
1437     int gamemode = property_mapping[i].ext1_index;
1438     int level    = property_mapping[i].ext2_index;
1439     int music    = property_mapping[i].artwork_index;
1440
1441 #if 0
1442     printf("::: prefix == %d, gamemode == %d, level == %d, music == %d\n",
1443            prefix, gamemode, level, music);
1444 #endif
1445
1446     if (prefix < 0 || prefix >= NUM_MUSIC_PREFIXES)
1447       continue;
1448
1449     if (gamemode < 0)
1450       gamemode = GAME_MODE_DEFAULT;
1451
1452     /* level specific music only allowed for in-game music */
1453     if (level != -1 && gamemode == GAME_MODE_DEFAULT)
1454       gamemode = GAME_MODE_PLAYING;
1455
1456     if (level == -1)
1457     {
1458       level = 0;
1459       default_levelset_music = music;
1460     }
1461
1462     if (gamemode == GAME_MODE_PLAYING || gamemode == GAME_MODE_DEFAULT)
1463       levelset.music[level] = music;
1464     if (gamemode != GAME_MODE_PLAYING)
1465       menu.music[gamemode] = music;
1466   }
1467
1468   /* now set all '-1' values to menu specific default values */
1469   /* (undefined values of "levelset.music[]" might stay at "-1" to
1470      allow dynamic selection of music files from music directory!) */
1471   for (i = 0; i < MAX_LEVELS; i++)
1472     if (levelset.music[i] == -1)
1473       levelset.music[i] = default_levelset_music;
1474   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1475     if (menu.music[i] == -1)
1476       menu.music[i] = menu.music[GAME_MODE_DEFAULT];
1477
1478 #if 0
1479   /* TEST ONLY */
1480   for (i = 0; i < MAX_LEVELS; i++)
1481     if (levelset.music[i] != -1)
1482       printf("::: levelset.music[%d] == %d\n", i, levelset.music[i]);
1483   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
1484     if (menu.music[i] != -1)
1485       printf("::: menu.music[%d] == %d\n", i, menu.music[i]);
1486 #endif
1487 }
1488
1489 static void set_music_parameters(int music, char **parameter_raw)
1490 {
1491   int parameter[NUM_MUS_ARGS];
1492   int i;
1493
1494   /* get integer values from string parameters */
1495   for (i = 0; i < NUM_MUS_ARGS; i++)
1496     parameter[i] =
1497       get_parameter_value(music_config_suffix[i].token, parameter_raw[i],
1498                           music_config_suffix[i].type);
1499
1500   /* explicit loop mode setting in configuration overrides default value */
1501   if (parameter[MUS_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
1502     music_info[music].loop = parameter[MUS_ARG_MODE_LOOP];
1503 }
1504
1505 static void InitMusicInfo()
1506 {
1507   int num_music = getMusicListSize();
1508   int i, j;
1509
1510   checked_free(music_info);
1511
1512   music_info = checked_calloc(num_music * sizeof(struct MusicInfo));
1513
1514   for (i = 0; i < num_music; i++)
1515   {
1516     struct FileInfo *music = getMusicListEntry(i);
1517     int len_music_text = strlen(music->token);
1518
1519     music_info[i].loop = TRUE;          /* default: play music in loop mode */
1520
1521     /* determine all loop music */
1522
1523     for (j = 0; music_prefix_info[j].prefix; j++)
1524     {
1525       int len_prefix_text = strlen(music_prefix_info[j].prefix);
1526
1527       if (len_prefix_text < len_music_text &&
1528           strncmp(music->token,
1529                   music_prefix_info[j].prefix, len_prefix_text) == 0)
1530       {
1531         music_info[i].loop = music_prefix_info[j].is_loop_music;
1532
1533         break;
1534       }
1535     }
1536
1537     set_music_parameters(i, music->parameter);
1538   }
1539 }
1540
1541 static void ReinitializeGraphics()
1542 {
1543   InitGraphicInfo();                    /* graphic properties mapping */
1544   InitElementGraphicInfo();             /* element game graphic mapping */
1545   InitElementSpecialGraphicInfo();      /* element special graphic mapping */
1546
1547   InitElementSmallImages();             /* create editor and preview images */
1548   InitFontGraphicInfo();                /* initialize text drawing functions */
1549
1550   SetMainBackgroundImage(IMG_BACKGROUND);
1551   SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
1552
1553   InitGadgets();
1554   InitToons();
1555 }
1556
1557 static void ReinitializeSounds()
1558 {
1559   InitSoundInfo();              /* sound properties mapping */
1560   InitElementSoundInfo();       /* element game sound mapping */
1561   InitGameModeSoundInfo();      /* game mode sound mapping */
1562
1563   InitPlayLevelSound();         /* internal game sound settings */
1564 }
1565
1566 static void ReinitializeMusic()
1567 {
1568   InitMusicInfo();              /* music properties mapping */
1569   InitGameModeMusicInfo();      /* game mode music mapping */
1570 }
1571
1572 static int get_special_property_bit(int element, int property_bit_nr)
1573 {
1574   struct PropertyBitInfo
1575   {
1576     int element;
1577     int bit_nr;
1578   };
1579
1580   static struct PropertyBitInfo pb_can_move_into_acid[] =
1581   {
1582     /* the player may be able fall into acid when gravity is activated */
1583     { EL_PLAYER_1,              0       },
1584     { EL_PLAYER_2,              0       },
1585     { EL_PLAYER_3,              0       },
1586     { EL_PLAYER_4,              0       },
1587     { EL_SP_MURPHY,             0       },
1588     { EL_SOKOBAN_FIELD_PLAYER,  0       },
1589
1590     /* all element that can move may be able to also move into acid */
1591     { EL_BUG,                   1       },
1592     { EL_BUG_LEFT,              1       },
1593     { EL_BUG_RIGHT,             1       },
1594     { EL_BUG_UP,                1       },
1595     { EL_BUG_DOWN,              1       },
1596     { EL_SPACESHIP,             2       },
1597     { EL_SPACESHIP_LEFT,        2       },
1598     { EL_SPACESHIP_RIGHT,       2       },
1599     { EL_SPACESHIP_UP,          2       },
1600     { EL_SPACESHIP_DOWN,        2       },
1601     { EL_BD_BUTTERFLY,          3       },
1602     { EL_BD_BUTTERFLY_LEFT,     3       },
1603     { EL_BD_BUTTERFLY_RIGHT,    3       },
1604     { EL_BD_BUTTERFLY_UP,       3       },
1605     { EL_BD_BUTTERFLY_DOWN,     3       },
1606     { EL_BD_FIREFLY,            4       },
1607     { EL_BD_FIREFLY_LEFT,       4       },
1608     { EL_BD_FIREFLY_RIGHT,      4       },
1609     { EL_BD_FIREFLY_UP,         4       },
1610     { EL_BD_FIREFLY_DOWN,       4       },
1611     { EL_YAMYAM,                5       },
1612     { EL_DARK_YAMYAM,           6       },
1613     { EL_ROBOT,                 7       },
1614     { EL_PACMAN,                8       },
1615     { EL_PACMAN_LEFT,           8       },
1616     { EL_PACMAN_RIGHT,          8       },
1617     { EL_PACMAN_UP,             8       },
1618     { EL_PACMAN_DOWN,           8       },
1619     { EL_MOLE,                  9       },
1620     { EL_MOLE_LEFT,             9       },
1621     { EL_MOLE_RIGHT,            9       },
1622     { EL_MOLE_UP,               9       },
1623     { EL_MOLE_DOWN,             9       },
1624     { EL_PENGUIN,               10      },
1625     { EL_PIG,                   11      },
1626     { EL_DRAGON,                12      },
1627     { EL_SATELLITE,             13      },
1628     { EL_SP_SNIKSNAK,           14      },
1629     { EL_SP_ELECTRON,           15      },
1630     { EL_BALLOON,               16      },
1631     { EL_SPRING,                17      },
1632
1633     { -1,                       -1      },
1634   };
1635
1636   static struct PropertyBitInfo pb_dont_collide_with[] =
1637   {
1638     { EL_SP_SNIKSNAK,           0       },
1639     { EL_SP_ELECTRON,           1       },
1640
1641     { -1,                       -1      },
1642   };
1643
1644   static struct
1645   {
1646     int bit_nr;
1647     struct PropertyBitInfo *pb_info;
1648   } pb_definition[] =
1649   {
1650     { EP_CAN_MOVE_INTO_ACID,    pb_can_move_into_acid   },
1651     { EP_DONT_COLLIDE_WITH,     pb_dont_collide_with    },
1652
1653     { -1,                       NULL                    },
1654   };
1655
1656   struct PropertyBitInfo *pb_info = NULL;
1657   int i;
1658
1659   for (i = 0; pb_definition[i].bit_nr != -1; i++)
1660     if (pb_definition[i].bit_nr == property_bit_nr)
1661       pb_info = pb_definition[i].pb_info;
1662
1663   if (pb_info == NULL)
1664     return -1;
1665
1666   for (i = 0; pb_info[i].element != -1; i++)
1667     if (pb_info[i].element == element)
1668       return pb_info[i].bit_nr;
1669
1670   return -1;
1671 }
1672
1673 #if 1
1674 void setBitfieldProperty(int *bitfield, int property_bit_nr, int element,
1675                          boolean property_value)
1676 {
1677   int bit_nr = get_special_property_bit(element, property_bit_nr);
1678
1679   if (bit_nr > -1)
1680   {
1681     if (property_value)
1682       *bitfield |=  (1 << bit_nr);
1683     else
1684       *bitfield &= ~(1 << bit_nr);
1685   }
1686 }
1687
1688 boolean getBitfieldProperty(int *bitfield, int property_bit_nr, int element)
1689 {
1690   int bit_nr = get_special_property_bit(element, property_bit_nr);
1691
1692   if (bit_nr > -1)
1693     return ((*bitfield & (1 << bit_nr)) != 0);
1694
1695   return FALSE;
1696 }
1697
1698 #else
1699
1700 void setMoveIntoAcidProperty(struct LevelInfo *level, int element, boolean set)
1701 {
1702   int bit_nr = get_special_property_bit(element, EP_CAN_MOVE_INTO_ACID);
1703
1704   if (bit_nr > -1)
1705   {
1706     level->can_move_into_acid_bits &= ~(1 << bit_nr);
1707
1708     if (set)
1709       level->can_move_into_acid_bits |= (1 << bit_nr);
1710   }
1711 }
1712
1713 boolean getMoveIntoAcidProperty(struct LevelInfo *level, int element)
1714 {
1715   int bit_nr = get_special_property_bit(element, EP_CAN_MOVE_INTO_ACID);
1716
1717   if (bit_nr > -1)
1718     return ((level->can_move_into_acid_bits & (1 << bit_nr)) != 0);
1719
1720   return FALSE;
1721 }
1722 #endif
1723
1724 void InitElementPropertiesStatic()
1725 {
1726   static int ep_diggable[] =
1727   {
1728     EL_SAND,
1729     EL_SP_BASE,
1730     EL_SP_BUGGY_BASE,
1731     EL_SP_BUGGY_BASE_ACTIVATING,
1732     EL_TRAP,
1733     EL_INVISIBLE_SAND,
1734     EL_INVISIBLE_SAND_ACTIVE,
1735
1736     /* !!! currently not diggable, but handled by 'ep_dont_run_into' !!! */
1737     /* (if amoeba can grow into anything diggable, maybe keep these out) */
1738 #if 0
1739     EL_LANDMINE,
1740     EL_TRAP_ACTIVE,
1741     EL_SP_BUGGY_BASE_ACTIVE,
1742 #endif
1743     -1
1744   };
1745
1746   static int ep_collectible_only[] =
1747   {
1748     EL_BD_DIAMOND,
1749     EL_EMERALD,
1750     EL_DIAMOND,
1751     EL_EMERALD_YELLOW,
1752     EL_EMERALD_RED,
1753     EL_EMERALD_PURPLE,
1754     EL_KEY_1,
1755     EL_KEY_2,
1756     EL_KEY_3,
1757     EL_KEY_4,
1758     EL_EM_KEY_1,
1759     EL_EM_KEY_2,
1760     EL_EM_KEY_3,
1761     EL_EM_KEY_4,
1762     EL_DYNAMITE,
1763     EL_DYNABOMB_INCREASE_NUMBER,
1764     EL_DYNABOMB_INCREASE_SIZE,
1765     EL_DYNABOMB_INCREASE_POWER,
1766     EL_SP_INFOTRON,
1767     EL_SP_DISK_RED,
1768     EL_PEARL,
1769     EL_CRYSTAL,
1770     EL_KEY_WHITE,
1771     EL_SHIELD_NORMAL,
1772     EL_SHIELD_DEADLY,
1773     EL_EXTRA_TIME,
1774     EL_ENVELOPE_1,
1775     EL_ENVELOPE_2,
1776     EL_ENVELOPE_3,
1777     EL_ENVELOPE_4,
1778     EL_SPEED_PILL,
1779     -1
1780   };
1781
1782   static int ep_dont_run_into[] =
1783   {
1784     /* same elements as in 'ep_dont_touch' */
1785     EL_BUG,
1786     EL_SPACESHIP,
1787     EL_BD_BUTTERFLY,
1788     EL_BD_FIREFLY,
1789
1790     /* same elements as in 'ep_dont_collide_with' */
1791     EL_YAMYAM,
1792     EL_DARK_YAMYAM,
1793     EL_ROBOT,
1794     EL_PACMAN,
1795     EL_SP_SNIKSNAK,
1796     EL_SP_ELECTRON,
1797
1798     /* new elements */
1799     EL_AMOEBA_DROP,
1800     EL_ACID,
1801
1802     /* !!! maybe this should better be handled by 'ep_diggable' !!! */
1803 #if 1
1804     EL_LANDMINE,
1805     EL_TRAP_ACTIVE,
1806     EL_SP_BUGGY_BASE_ACTIVE,
1807 #endif
1808     -1
1809   };
1810
1811   static int ep_dont_collide_with[] =
1812   {
1813     /* same elements as in 'ep_dont_touch' */
1814     EL_BUG,
1815     EL_SPACESHIP,
1816     EL_BD_BUTTERFLY,
1817     EL_BD_FIREFLY,
1818
1819     /* new elements */
1820     EL_YAMYAM,
1821     EL_DARK_YAMYAM,
1822     EL_ROBOT,
1823     EL_PACMAN,
1824     EL_SP_SNIKSNAK,
1825     EL_SP_ELECTRON,
1826     -1
1827   };
1828
1829   static int ep_dont_touch[] =
1830   {
1831     EL_BUG,
1832     EL_SPACESHIP,
1833     EL_BD_BUTTERFLY,
1834     EL_BD_FIREFLY,
1835     -1
1836   };
1837
1838   static int ep_indestructible[] =
1839   {
1840     EL_STEELWALL,
1841     EL_ACID,
1842     EL_ACID_POOL_TOPLEFT,
1843     EL_ACID_POOL_TOPRIGHT,
1844     EL_ACID_POOL_BOTTOMLEFT,
1845     EL_ACID_POOL_BOTTOM,
1846     EL_ACID_POOL_BOTTOMRIGHT,
1847     EL_SP_HARDWARE_GRAY,
1848     EL_SP_HARDWARE_GREEN,
1849     EL_SP_HARDWARE_BLUE,
1850     EL_SP_HARDWARE_RED,
1851     EL_SP_HARDWARE_YELLOW,
1852     EL_SP_HARDWARE_BASE_1,
1853     EL_SP_HARDWARE_BASE_2,
1854     EL_SP_HARDWARE_BASE_3,
1855     EL_SP_HARDWARE_BASE_4,
1856     EL_SP_HARDWARE_BASE_5,
1857     EL_SP_HARDWARE_BASE_6,
1858     EL_INVISIBLE_STEELWALL,
1859     EL_INVISIBLE_STEELWALL_ACTIVE,
1860     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
1861     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
1862     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
1863     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
1864     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
1865     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
1866     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
1867     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
1868     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
1869     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
1870     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
1871     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
1872     EL_LIGHT_SWITCH,
1873     EL_LIGHT_SWITCH_ACTIVE,
1874     EL_SIGN_EXCLAMATION,
1875     EL_SIGN_RADIOACTIVITY,
1876     EL_SIGN_STOP,
1877     EL_SIGN_WHEELCHAIR,
1878     EL_SIGN_PARKING,
1879     EL_SIGN_ONEWAY,
1880     EL_SIGN_HEART,
1881     EL_SIGN_TRIANGLE,
1882     EL_SIGN_ROUND,
1883     EL_SIGN_EXIT,
1884     EL_SIGN_YINYANG,
1885     EL_SIGN_OTHER,
1886     EL_STEELWALL_SLIPPERY,
1887     EL_EMC_STEELWALL_1,
1888     EL_EMC_STEELWALL_2,
1889     EL_EMC_STEELWALL_3,
1890     EL_EMC_STEELWALL_4,
1891     EL_CRYSTAL,
1892     EL_GATE_1,
1893     EL_GATE_2,
1894     EL_GATE_3,
1895     EL_GATE_4,
1896     EL_GATE_1_GRAY,
1897     EL_GATE_2_GRAY,
1898     EL_GATE_3_GRAY,
1899     EL_GATE_4_GRAY,
1900     EL_EM_GATE_1,
1901     EL_EM_GATE_2,
1902     EL_EM_GATE_3,
1903     EL_EM_GATE_4,
1904     EL_EM_GATE_1_GRAY,
1905     EL_EM_GATE_2_GRAY,
1906     EL_EM_GATE_3_GRAY,
1907     EL_EM_GATE_4_GRAY,
1908     EL_SWITCHGATE_OPEN,
1909     EL_SWITCHGATE_OPENING,
1910     EL_SWITCHGATE_CLOSED,
1911     EL_SWITCHGATE_CLOSING,
1912 #if 0
1913     EL_SWITCHGATE_SWITCH_UP,
1914     EL_SWITCHGATE_SWITCH_DOWN,
1915 #endif
1916     EL_TIMEGATE_OPEN,
1917     EL_TIMEGATE_OPENING,
1918     EL_TIMEGATE_CLOSED,
1919     EL_TIMEGATE_CLOSING,
1920 #if 0
1921     EL_TIMEGATE_SWITCH,
1922     EL_TIMEGATE_SWITCH_ACTIVE,
1923 #endif
1924     EL_TUBE_ANY,
1925     EL_TUBE_VERTICAL,
1926     EL_TUBE_HORIZONTAL,
1927     EL_TUBE_VERTICAL_LEFT,
1928     EL_TUBE_VERTICAL_RIGHT,
1929     EL_TUBE_HORIZONTAL_UP,
1930     EL_TUBE_HORIZONTAL_DOWN,
1931     EL_TUBE_LEFT_UP,
1932     EL_TUBE_LEFT_DOWN,
1933     EL_TUBE_RIGHT_UP,
1934     EL_TUBE_RIGHT_DOWN,
1935     -1
1936   };
1937
1938   static int ep_slippery[] =
1939   {
1940     EL_WALL_SLIPPERY,
1941     EL_BD_WALL,
1942     EL_ROCK,
1943     EL_BD_ROCK,
1944     EL_EMERALD,
1945     EL_BD_DIAMOND,
1946     EL_EMERALD_YELLOW,
1947     EL_EMERALD_RED,
1948     EL_EMERALD_PURPLE,
1949     EL_DIAMOND,
1950     EL_BOMB,
1951     EL_NUT,
1952     EL_ROBOT_WHEEL_ACTIVE,
1953     EL_ROBOT_WHEEL,
1954     EL_TIME_ORB_FULL,
1955     EL_TIME_ORB_EMPTY,
1956     EL_LAMP_ACTIVE,
1957     EL_LAMP,
1958     EL_ACID_POOL_TOPLEFT,
1959     EL_ACID_POOL_TOPRIGHT,
1960     EL_SATELLITE,
1961     EL_SP_ZONK,
1962     EL_SP_INFOTRON,
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_SPEED_PILL,
1969     EL_STEELWALL_SLIPPERY,
1970     EL_PEARL,
1971     EL_CRYSTAL,
1972     -1
1973   };
1974
1975   static int ep_can_change[] =
1976   {
1977     -1
1978   };
1979
1980   static int ep_can_move[] =
1981   {
1982     /* same elements as in 'pb_can_move_into_acid' */
1983     EL_BUG,
1984     EL_SPACESHIP,
1985     EL_BD_BUTTERFLY,
1986     EL_BD_FIREFLY,
1987     EL_YAMYAM,
1988     EL_DARK_YAMYAM,
1989     EL_ROBOT,
1990     EL_PACMAN,
1991     EL_MOLE,
1992     EL_PENGUIN,
1993     EL_PIG,
1994     EL_DRAGON,
1995     EL_SATELLITE,
1996     EL_SP_SNIKSNAK,
1997     EL_SP_ELECTRON,
1998     EL_BALLOON,
1999     EL_SPRING,
2000     -1
2001   };
2002
2003   static int ep_can_fall[] =
2004   {
2005     EL_ROCK,
2006     EL_BD_ROCK,
2007     EL_EMERALD,
2008     EL_BD_DIAMOND,
2009     EL_EMERALD_YELLOW,
2010     EL_EMERALD_RED,
2011     EL_EMERALD_PURPLE,
2012     EL_DIAMOND,
2013     EL_BOMB,
2014     EL_NUT,
2015     EL_AMOEBA_DROP,
2016     EL_QUICKSAND_FULL,
2017     EL_MAGIC_WALL_FULL,
2018     EL_BD_MAGIC_WALL_FULL,
2019     EL_TIME_ORB_FULL,
2020     EL_TIME_ORB_EMPTY,
2021     EL_SP_ZONK,
2022     EL_SP_INFOTRON,
2023     EL_SP_DISK_ORANGE,
2024     EL_PEARL,
2025     EL_CRYSTAL,
2026     EL_SPRING,
2027     EL_DX_SUPABOMB,
2028     -1
2029   };
2030
2031   static int ep_can_smash_player[] =
2032   {
2033     EL_ROCK,
2034     EL_BD_ROCK,
2035     EL_EMERALD,
2036     EL_BD_DIAMOND,
2037     EL_EMERALD_YELLOW,
2038     EL_EMERALD_RED,
2039     EL_EMERALD_PURPLE,
2040     EL_DIAMOND,
2041     EL_BOMB,
2042     EL_NUT,
2043     EL_AMOEBA_DROP,
2044     EL_TIME_ORB_FULL,
2045     EL_TIME_ORB_EMPTY,
2046     EL_SP_ZONK,
2047     EL_SP_INFOTRON,
2048     EL_SP_DISK_ORANGE,
2049     EL_PEARL,
2050     EL_CRYSTAL,
2051     EL_SPRING,
2052     EL_DX_SUPABOMB,
2053     -1
2054   };
2055
2056   static int ep_can_smash_enemies[] =
2057   {
2058     EL_ROCK,
2059     EL_BD_ROCK,
2060     EL_SP_ZONK,
2061     -1
2062   };
2063
2064   static int ep_can_smash_everything[] =
2065   {
2066     EL_ROCK,
2067     EL_BD_ROCK,
2068     EL_SP_ZONK,
2069     -1
2070   };
2071
2072   static int ep_can_explode_by_fire[] =
2073   {
2074     /* same elements as in 'ep_can_explode_impact' */
2075     EL_BOMB,
2076     EL_SP_DISK_ORANGE,
2077     EL_DX_SUPABOMB,
2078
2079     /* same elements as in 'ep_can_explode_smashed' */
2080     EL_SATELLITE,
2081     EL_PIG,
2082     EL_DRAGON,
2083     EL_MOLE,
2084
2085     /* new elements */
2086     EL_DYNAMITE_ACTIVE,
2087     EL_DYNAMITE,
2088     EL_DYNABOMB_PLAYER_1_ACTIVE,
2089     EL_DYNABOMB_PLAYER_2_ACTIVE,
2090     EL_DYNABOMB_PLAYER_3_ACTIVE,
2091     EL_DYNABOMB_PLAYER_4_ACTIVE,
2092     EL_DYNABOMB_INCREASE_NUMBER,
2093     EL_DYNABOMB_INCREASE_SIZE,
2094     EL_DYNABOMB_INCREASE_POWER,
2095     EL_SP_DISK_RED_ACTIVE,
2096     EL_BUG,
2097     EL_PENGUIN,
2098     EL_SP_DISK_RED,
2099     EL_SP_DISK_YELLOW,
2100     EL_SP_SNIKSNAK,
2101     EL_SP_ELECTRON,
2102 #if 0
2103     EL_BLACK_ORB,
2104 #endif
2105     -1
2106   };
2107
2108   static int ep_can_explode_smashed[] =
2109   {
2110     /* same elements as in 'ep_can_explode_impact' */
2111     EL_BOMB,
2112     EL_SP_DISK_ORANGE,
2113     EL_DX_SUPABOMB,
2114
2115     /* new elements */
2116     EL_SATELLITE,
2117     EL_PIG,
2118     EL_DRAGON,
2119     EL_MOLE,
2120     -1
2121   };
2122
2123   static int ep_can_explode_impact[] =
2124   {
2125     EL_BOMB,
2126     EL_SP_DISK_ORANGE,
2127     EL_DX_SUPABOMB,
2128     -1
2129   };
2130
2131   static int ep_walkable_over[] =
2132   {
2133     EL_EMPTY_SPACE,
2134     EL_SP_EMPTY_SPACE,
2135     EL_SOKOBAN_FIELD_EMPTY,
2136     EL_EXIT_OPEN,
2137     EL_SP_EXIT_OPEN,
2138     EL_SP_EXIT_OPENING,
2139     EL_GATE_1,
2140     EL_GATE_2,
2141     EL_GATE_3,
2142     EL_GATE_4,
2143     EL_GATE_1_GRAY,
2144     EL_GATE_2_GRAY,
2145     EL_GATE_3_GRAY,
2146     EL_GATE_4_GRAY,
2147     EL_PENGUIN,
2148     EL_PIG,
2149     EL_DRAGON,
2150     -1
2151   };
2152
2153   static int ep_walkable_inside[] =
2154   {
2155     EL_TUBE_ANY,
2156     EL_TUBE_VERTICAL,
2157     EL_TUBE_HORIZONTAL,
2158     EL_TUBE_VERTICAL_LEFT,
2159     EL_TUBE_VERTICAL_RIGHT,
2160     EL_TUBE_HORIZONTAL_UP,
2161     EL_TUBE_HORIZONTAL_DOWN,
2162     EL_TUBE_LEFT_UP,
2163     EL_TUBE_LEFT_DOWN,
2164     EL_TUBE_RIGHT_UP,
2165     EL_TUBE_RIGHT_DOWN,
2166     -1
2167   };
2168
2169   static int ep_walkable_under[] =
2170   {
2171     -1
2172   };
2173
2174   static int ep_passable_over[] =
2175   {
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     EL_SWITCHGATE_OPEN,
2185     EL_TIMEGATE_OPEN,
2186     -1
2187   };
2188
2189   static int ep_passable_inside[] =
2190   {
2191     EL_SP_PORT_LEFT,
2192     EL_SP_PORT_RIGHT,
2193     EL_SP_PORT_UP,
2194     EL_SP_PORT_DOWN,
2195     EL_SP_PORT_HORIZONTAL,
2196     EL_SP_PORT_VERTICAL,
2197     EL_SP_PORT_ANY,
2198     EL_SP_GRAVITY_PORT_LEFT,
2199     EL_SP_GRAVITY_PORT_RIGHT,
2200     EL_SP_GRAVITY_PORT_UP,
2201     EL_SP_GRAVITY_PORT_DOWN,
2202     -1
2203   };
2204
2205   static int ep_passable_under[] =
2206   {
2207     -1
2208   };
2209
2210   static int ep_droppable[] =
2211   {
2212     -1
2213   };
2214
2215   static int ep_can_explode_1x1[] =
2216   {
2217     -1
2218   };
2219
2220   static int ep_pushable[] =
2221   {
2222     EL_ROCK,
2223     EL_BOMB,
2224     EL_DX_SUPABOMB,
2225     EL_NUT,
2226     EL_TIME_ORB_EMPTY,
2227     EL_SP_ZONK,
2228     EL_SP_DISK_ORANGE,
2229     EL_SPRING,
2230     EL_BD_ROCK,
2231     EL_SOKOBAN_OBJECT,
2232     EL_SOKOBAN_FIELD_FULL,
2233     EL_SATELLITE,
2234     EL_SP_DISK_YELLOW,
2235     EL_BALLOON,
2236     -1
2237   };
2238
2239   static int ep_can_explode_cross[] =
2240   {
2241     -1
2242   };
2243
2244   static int ep_protected[] =
2245   {
2246     EL_EM_GATE_1,
2247     EL_EM_GATE_2,
2248     EL_EM_GATE_3,
2249     EL_EM_GATE_4,
2250     EL_EM_GATE_1_GRAY,
2251     EL_EM_GATE_2_GRAY,
2252     EL_EM_GATE_3_GRAY,
2253     EL_EM_GATE_4_GRAY,
2254     EL_SWITCHGATE_OPEN,
2255     EL_TIMEGATE_OPEN,
2256     -1
2257   };
2258
2259   static int ep_player[] =
2260   {
2261     EL_PLAYER_1,
2262     EL_PLAYER_2,
2263     EL_PLAYER_3,
2264     EL_PLAYER_4,
2265     EL_SP_MURPHY,
2266     EL_SOKOBAN_FIELD_PLAYER,
2267     -1
2268   };
2269
2270   static int ep_can_pass_magic_wall[] =
2271   {
2272     EL_ROCK,
2273     EL_BD_ROCK,
2274     EL_EMERALD,
2275     EL_BD_DIAMOND,
2276     EL_EMERALD_YELLOW,
2277     EL_EMERALD_RED,
2278     EL_EMERALD_PURPLE,
2279     EL_DIAMOND,
2280     -1
2281   };
2282
2283   static int ep_switchable[] =
2284   {
2285     EL_ROBOT_WHEEL,
2286     EL_SP_TERMINAL,
2287     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2288     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2289     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2290     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2291     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2292     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2293     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2294     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2295     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2296     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2297     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2298     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2299     EL_SWITCHGATE_SWITCH_UP,
2300     EL_SWITCHGATE_SWITCH_DOWN,
2301     EL_LIGHT_SWITCH,
2302     EL_LIGHT_SWITCH_ACTIVE,
2303     EL_TIMEGATE_SWITCH,
2304     EL_BALLOON_SWITCH_LEFT,
2305     EL_BALLOON_SWITCH_RIGHT,
2306     EL_BALLOON_SWITCH_UP,
2307     EL_BALLOON_SWITCH_DOWN,
2308     EL_BALLOON_SWITCH_ANY,
2309     EL_LAMP,
2310     EL_TIME_ORB_FULL,
2311     -1
2312   };
2313
2314   static int ep_bd_element[] =
2315   {
2316     EL_EMPTY,
2317     EL_SAND,
2318     EL_WALL_SLIPPERY,
2319     EL_BD_WALL,
2320     EL_ROCK,
2321     EL_BD_ROCK,
2322     EL_BD_DIAMOND,
2323     EL_BD_MAGIC_WALL,
2324     EL_EXIT_CLOSED,
2325     EL_EXIT_OPEN,
2326     EL_STEELWALL,
2327     EL_PLAYER_1,
2328     EL_PLAYER_2,
2329     EL_PLAYER_3,
2330     EL_PLAYER_4,
2331     EL_BD_FIREFLY,
2332     EL_BD_FIREFLY_1,
2333     EL_BD_FIREFLY_2,
2334     EL_BD_FIREFLY_3,
2335     EL_BD_FIREFLY_4,
2336     EL_BD_BUTTERFLY,
2337     EL_BD_BUTTERFLY_1,
2338     EL_BD_BUTTERFLY_2,
2339     EL_BD_BUTTERFLY_3,
2340     EL_BD_BUTTERFLY_4,
2341     EL_BD_AMOEBA,
2342     EL_CHAR_QUESTION,
2343     EL_UNKNOWN,
2344     -1
2345   };
2346
2347   static int ep_sp_element[] =
2348   {
2349     /* should always be valid */
2350     EL_EMPTY,
2351
2352     EL_SP_EMPTY,
2353     EL_SP_ZONK,
2354     EL_SP_BASE,
2355     EL_SP_MURPHY,
2356     EL_SP_INFOTRON,
2357     EL_SP_CHIP_SINGLE,
2358     EL_SP_HARDWARE_GRAY,
2359     EL_SP_EXIT_CLOSED,
2360     EL_SP_EXIT_OPEN,
2361     EL_SP_DISK_ORANGE,
2362     EL_SP_PORT_RIGHT,
2363     EL_SP_PORT_DOWN,
2364     EL_SP_PORT_LEFT,
2365     EL_SP_PORT_UP,
2366     EL_SP_GRAVITY_PORT_RIGHT,
2367     EL_SP_GRAVITY_PORT_DOWN,
2368     EL_SP_GRAVITY_PORT_LEFT,
2369     EL_SP_GRAVITY_PORT_UP,
2370     EL_SP_SNIKSNAK,
2371     EL_SP_DISK_YELLOW,
2372     EL_SP_TERMINAL,
2373     EL_SP_DISK_RED,
2374     EL_SP_PORT_VERTICAL,
2375     EL_SP_PORT_HORIZONTAL,
2376     EL_SP_PORT_ANY,
2377     EL_SP_ELECTRON,
2378     EL_SP_BUGGY_BASE,
2379     EL_SP_CHIP_LEFT,
2380     EL_SP_CHIP_RIGHT,
2381     EL_SP_HARDWARE_BASE_1,
2382     EL_SP_HARDWARE_GREEN,
2383     EL_SP_HARDWARE_BLUE,
2384     EL_SP_HARDWARE_RED,
2385     EL_SP_HARDWARE_YELLOW,
2386     EL_SP_HARDWARE_BASE_2,
2387     EL_SP_HARDWARE_BASE_3,
2388     EL_SP_HARDWARE_BASE_4,
2389     EL_SP_HARDWARE_BASE_5,
2390     EL_SP_HARDWARE_BASE_6,
2391     EL_SP_CHIP_TOP,
2392     EL_SP_CHIP_BOTTOM,
2393     /* additional elements that appeared in newer Supaplex levels */
2394     EL_INVISIBLE_WALL,
2395     /* more than one murphy in a level results in an inactive clone */
2396     EL_SP_MURPHY_CLONE,
2397     /* runtime elements*/
2398     EL_SP_DISK_RED_ACTIVE,
2399     EL_SP_TERMINAL_ACTIVE,
2400     EL_SP_BUGGY_BASE_ACTIVATING,
2401     EL_SP_BUGGY_BASE_ACTIVE,
2402     EL_SP_EXIT_OPENING,
2403     EL_SP_EXIT_CLOSING,
2404     -1
2405   };
2406
2407   static int ep_sb_element[] =
2408   {
2409     EL_EMPTY,
2410     EL_STEELWALL,
2411     EL_SOKOBAN_OBJECT,
2412     EL_SOKOBAN_FIELD_EMPTY,
2413     EL_SOKOBAN_FIELD_FULL,
2414     EL_SOKOBAN_FIELD_PLAYER,
2415     EL_PLAYER_1,
2416     EL_PLAYER_2,
2417     EL_PLAYER_3,
2418     EL_PLAYER_4,
2419     EL_INVISIBLE_STEELWALL,
2420     -1
2421   };
2422
2423   static int ep_gem[] =
2424   {
2425     EL_BD_DIAMOND,
2426     EL_EMERALD,
2427     EL_EMERALD_YELLOW,
2428     EL_EMERALD_RED,
2429     EL_EMERALD_PURPLE,
2430     EL_DIAMOND,
2431     -1
2432   };
2433
2434   static int ep_food_dark_yamyam[] =
2435   {
2436     EL_SAND,
2437     EL_BUG,
2438     EL_SPACESHIP,
2439     EL_BD_BUTTERFLY,
2440     EL_BD_FIREFLY,
2441     EL_YAMYAM,
2442     EL_ROBOT,
2443     EL_PACMAN,
2444     EL_AMOEBA_DROP,
2445     EL_AMOEBA_DEAD,
2446     EL_AMOEBA_WET,
2447     EL_AMOEBA_DRY,
2448     EL_AMOEBA_FULL,
2449     EL_BD_AMOEBA,
2450     EL_EMERALD,
2451     EL_BD_DIAMOND,
2452     EL_EMERALD_YELLOW,
2453     EL_EMERALD_RED,
2454     EL_EMERALD_PURPLE,
2455     EL_DIAMOND,
2456     EL_PEARL,
2457     EL_CRYSTAL,
2458     -1
2459   };
2460
2461   static int ep_food_penguin[] =
2462   {
2463     EL_EMERALD,
2464     EL_BD_DIAMOND,
2465     EL_EMERALD_YELLOW,
2466     EL_EMERALD_RED,
2467     EL_EMERALD_PURPLE,
2468     EL_DIAMOND,
2469     EL_PEARL,
2470     EL_CRYSTAL,
2471     -1
2472   };
2473
2474   static int ep_food_pig[] =
2475   {
2476     EL_EMERALD,
2477     EL_BD_DIAMOND,
2478     EL_EMERALD_YELLOW,
2479     EL_EMERALD_RED,
2480     EL_EMERALD_PURPLE,
2481     EL_DIAMOND,
2482     -1
2483   };
2484
2485   static int ep_historic_wall[] =
2486   {
2487     EL_STEELWALL,
2488     EL_GATE_1,
2489     EL_GATE_2,
2490     EL_GATE_3,
2491     EL_GATE_4,
2492     EL_GATE_1_GRAY,
2493     EL_GATE_2_GRAY,
2494     EL_GATE_3_GRAY,
2495     EL_GATE_4_GRAY,
2496     EL_EM_GATE_1,
2497     EL_EM_GATE_2,
2498     EL_EM_GATE_3,
2499     EL_EM_GATE_4,
2500     EL_EM_GATE_1_GRAY,
2501     EL_EM_GATE_2_GRAY,
2502     EL_EM_GATE_3_GRAY,
2503     EL_EM_GATE_4_GRAY,
2504     EL_EXIT_CLOSED,
2505     EL_EXIT_OPENING,
2506     EL_EXIT_OPEN,
2507     EL_WALL,
2508     EL_WALL_SLIPPERY,
2509     EL_EXPANDABLE_WALL,
2510     EL_EXPANDABLE_WALL_HORIZONTAL,
2511     EL_EXPANDABLE_WALL_VERTICAL,
2512     EL_EXPANDABLE_WALL_ANY,
2513     EL_EXPANDABLE_WALL_GROWING,
2514     EL_BD_WALL,
2515     EL_SP_CHIP_SINGLE,
2516     EL_SP_CHIP_LEFT,
2517     EL_SP_CHIP_RIGHT,
2518     EL_SP_CHIP_TOP,
2519     EL_SP_CHIP_BOTTOM,
2520     EL_SP_HARDWARE_GRAY,
2521     EL_SP_HARDWARE_GREEN,
2522     EL_SP_HARDWARE_BLUE,
2523     EL_SP_HARDWARE_RED,
2524     EL_SP_HARDWARE_YELLOW,
2525     EL_SP_HARDWARE_BASE_1,
2526     EL_SP_HARDWARE_BASE_2,
2527     EL_SP_HARDWARE_BASE_3,
2528     EL_SP_HARDWARE_BASE_4,
2529     EL_SP_HARDWARE_BASE_5,
2530     EL_SP_HARDWARE_BASE_6,
2531     EL_SP_TERMINAL,
2532     EL_SP_TERMINAL_ACTIVE,
2533     EL_SP_EXIT_CLOSED,
2534     EL_SP_EXIT_OPEN,
2535     EL_INVISIBLE_STEELWALL,
2536     EL_INVISIBLE_STEELWALL_ACTIVE,
2537     EL_INVISIBLE_WALL,
2538     EL_INVISIBLE_WALL_ACTIVE,
2539     EL_STEELWALL_SLIPPERY,
2540     EL_EMC_STEELWALL_1,
2541     EL_EMC_STEELWALL_2,
2542     EL_EMC_STEELWALL_3,
2543     EL_EMC_STEELWALL_4,
2544     EL_EMC_WALL_1,
2545     EL_EMC_WALL_2,
2546     EL_EMC_WALL_3,
2547     EL_EMC_WALL_4,
2548     EL_EMC_WALL_5,
2549     EL_EMC_WALL_6,
2550     EL_EMC_WALL_7,
2551     EL_EMC_WALL_8,
2552     -1
2553   };
2554
2555   static int ep_historic_solid[] =
2556   {
2557     EL_WALL,
2558     EL_EXPANDABLE_WALL,
2559     EL_EXPANDABLE_WALL_HORIZONTAL,
2560     EL_EXPANDABLE_WALL_VERTICAL,
2561     EL_EXPANDABLE_WALL_ANY,
2562     EL_BD_WALL,
2563     EL_WALL_SLIPPERY,
2564     EL_EXIT_CLOSED,
2565     EL_EXIT_OPENING,
2566     EL_EXIT_OPEN,
2567     EL_AMOEBA_DEAD,
2568     EL_AMOEBA_WET,
2569     EL_AMOEBA_DRY,
2570     EL_AMOEBA_FULL,
2571     EL_BD_AMOEBA,
2572     EL_QUICKSAND_EMPTY,
2573     EL_QUICKSAND_FULL,
2574     EL_QUICKSAND_FILLING,
2575     EL_QUICKSAND_EMPTYING,
2576     EL_MAGIC_WALL,
2577     EL_MAGIC_WALL_ACTIVE,
2578     EL_MAGIC_WALL_EMPTYING,
2579     EL_MAGIC_WALL_FILLING,
2580     EL_MAGIC_WALL_FULL,
2581     EL_MAGIC_WALL_DEAD,
2582     EL_BD_MAGIC_WALL,
2583     EL_BD_MAGIC_WALL_ACTIVE,
2584     EL_BD_MAGIC_WALL_EMPTYING,
2585     EL_BD_MAGIC_WALL_FULL,
2586     EL_BD_MAGIC_WALL_FILLING,
2587     EL_BD_MAGIC_WALL_DEAD,
2588     EL_GAME_OF_LIFE,
2589     EL_BIOMAZE,
2590     EL_SP_CHIP_SINGLE,
2591     EL_SP_CHIP_LEFT,
2592     EL_SP_CHIP_RIGHT,
2593     EL_SP_CHIP_TOP,
2594     EL_SP_CHIP_BOTTOM,
2595     EL_SP_TERMINAL,
2596     EL_SP_TERMINAL_ACTIVE,
2597     EL_SP_EXIT_CLOSED,
2598     EL_SP_EXIT_OPEN,
2599     EL_INVISIBLE_WALL,
2600     EL_INVISIBLE_WALL_ACTIVE,
2601     EL_SWITCHGATE_SWITCH_UP,
2602     EL_SWITCHGATE_SWITCH_DOWN,
2603     EL_TIMEGATE_SWITCH,
2604     EL_TIMEGATE_SWITCH_ACTIVE,
2605     EL_EMC_WALL_1,
2606     EL_EMC_WALL_2,
2607     EL_EMC_WALL_3,
2608     EL_EMC_WALL_4,
2609     EL_EMC_WALL_5,
2610     EL_EMC_WALL_6,
2611     EL_EMC_WALL_7,
2612     EL_EMC_WALL_8,
2613     EL_WALL_PEARL,
2614     EL_WALL_CRYSTAL,
2615
2616     /* the following elements are a direct copy of "indestructible" elements,
2617        except "EL_ACID", which is "indestructible", but not "solid"! */
2618 #if 0
2619     EL_ACID,
2620 #endif
2621     EL_STEELWALL,
2622     EL_ACID_POOL_TOPLEFT,
2623     EL_ACID_POOL_TOPRIGHT,
2624     EL_ACID_POOL_BOTTOMLEFT,
2625     EL_ACID_POOL_BOTTOM,
2626     EL_ACID_POOL_BOTTOMRIGHT,
2627     EL_SP_HARDWARE_GRAY,
2628     EL_SP_HARDWARE_GREEN,
2629     EL_SP_HARDWARE_BLUE,
2630     EL_SP_HARDWARE_RED,
2631     EL_SP_HARDWARE_YELLOW,
2632     EL_SP_HARDWARE_BASE_1,
2633     EL_SP_HARDWARE_BASE_2,
2634     EL_SP_HARDWARE_BASE_3,
2635     EL_SP_HARDWARE_BASE_4,
2636     EL_SP_HARDWARE_BASE_5,
2637     EL_SP_HARDWARE_BASE_6,
2638     EL_INVISIBLE_STEELWALL,
2639     EL_INVISIBLE_STEELWALL_ACTIVE,
2640     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2641     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2642     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2643     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2644     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2645     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2646     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2647     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2648     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2649     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2650     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2651     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2652     EL_LIGHT_SWITCH,
2653     EL_LIGHT_SWITCH_ACTIVE,
2654     EL_SIGN_EXCLAMATION,
2655     EL_SIGN_RADIOACTIVITY,
2656     EL_SIGN_STOP,
2657     EL_SIGN_WHEELCHAIR,
2658     EL_SIGN_PARKING,
2659     EL_SIGN_ONEWAY,
2660     EL_SIGN_HEART,
2661     EL_SIGN_TRIANGLE,
2662     EL_SIGN_ROUND,
2663     EL_SIGN_EXIT,
2664     EL_SIGN_YINYANG,
2665     EL_SIGN_OTHER,
2666     EL_STEELWALL_SLIPPERY,
2667     EL_EMC_STEELWALL_1,
2668     EL_EMC_STEELWALL_2,
2669     EL_EMC_STEELWALL_3,
2670     EL_EMC_STEELWALL_4,
2671     EL_CRYSTAL,
2672     EL_GATE_1,
2673     EL_GATE_2,
2674     EL_GATE_3,
2675     EL_GATE_4,
2676     EL_GATE_1_GRAY,
2677     EL_GATE_2_GRAY,
2678     EL_GATE_3_GRAY,
2679     EL_GATE_4_GRAY,
2680     EL_EM_GATE_1,
2681     EL_EM_GATE_2,
2682     EL_EM_GATE_3,
2683     EL_EM_GATE_4,
2684     EL_EM_GATE_1_GRAY,
2685     EL_EM_GATE_2_GRAY,
2686     EL_EM_GATE_3_GRAY,
2687     EL_EM_GATE_4_GRAY,
2688     EL_SWITCHGATE_OPEN,
2689     EL_SWITCHGATE_OPENING,
2690     EL_SWITCHGATE_CLOSED,
2691     EL_SWITCHGATE_CLOSING,
2692     EL_TIMEGATE_OPEN,
2693     EL_TIMEGATE_OPENING,
2694     EL_TIMEGATE_CLOSED,
2695     EL_TIMEGATE_CLOSING,
2696     EL_TUBE_ANY,
2697     EL_TUBE_VERTICAL,
2698     EL_TUBE_HORIZONTAL,
2699     EL_TUBE_VERTICAL_LEFT,
2700     EL_TUBE_VERTICAL_RIGHT,
2701     EL_TUBE_HORIZONTAL_UP,
2702     EL_TUBE_HORIZONTAL_DOWN,
2703     EL_TUBE_LEFT_UP,
2704     EL_TUBE_LEFT_DOWN,
2705     EL_TUBE_RIGHT_UP,
2706     EL_TUBE_RIGHT_DOWN,
2707     -1
2708   };
2709
2710   static int ep_classic_enemy[] =
2711   {
2712     EL_BUG,
2713     EL_SPACESHIP,
2714     EL_BD_BUTTERFLY,
2715     EL_BD_FIREFLY,
2716
2717     EL_YAMYAM,
2718     EL_DARK_YAMYAM,
2719     EL_ROBOT,
2720     EL_PACMAN,
2721     EL_SP_SNIKSNAK,
2722     EL_SP_ELECTRON,
2723     -1
2724   };
2725
2726   static int ep_belt[] =
2727   {
2728     EL_CONVEYOR_BELT_1_LEFT,
2729     EL_CONVEYOR_BELT_1_MIDDLE,
2730     EL_CONVEYOR_BELT_1_RIGHT,
2731     EL_CONVEYOR_BELT_2_LEFT,
2732     EL_CONVEYOR_BELT_2_MIDDLE,
2733     EL_CONVEYOR_BELT_2_RIGHT,
2734     EL_CONVEYOR_BELT_3_LEFT,
2735     EL_CONVEYOR_BELT_3_MIDDLE,
2736     EL_CONVEYOR_BELT_3_RIGHT,
2737     EL_CONVEYOR_BELT_4_LEFT,
2738     EL_CONVEYOR_BELT_4_MIDDLE,
2739     EL_CONVEYOR_BELT_4_RIGHT,
2740     -1
2741   };
2742
2743   static int ep_belt_active[] =
2744   {
2745     EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
2746     EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE,
2747     EL_CONVEYOR_BELT_1_RIGHT_ACTIVE,
2748     EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
2749     EL_CONVEYOR_BELT_2_MIDDLE_ACTIVE,
2750     EL_CONVEYOR_BELT_2_RIGHT_ACTIVE,
2751     EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
2752     EL_CONVEYOR_BELT_3_MIDDLE_ACTIVE,
2753     EL_CONVEYOR_BELT_3_RIGHT_ACTIVE,
2754     EL_CONVEYOR_BELT_4_LEFT_ACTIVE,
2755     EL_CONVEYOR_BELT_4_MIDDLE_ACTIVE,
2756     EL_CONVEYOR_BELT_4_RIGHT_ACTIVE,
2757     -1
2758   };
2759
2760   static int ep_belt_switch[] =
2761   {
2762     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2763     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2764     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2765     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2766     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2767     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2768     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2769     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2770     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2771     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2772     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2773     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2774     -1
2775   };
2776
2777   static int ep_tube[] =
2778   {
2779     EL_TUBE_LEFT_UP,
2780     EL_TUBE_LEFT_DOWN,
2781     EL_TUBE_RIGHT_UP,
2782     EL_TUBE_RIGHT_DOWN,
2783     EL_TUBE_HORIZONTAL,
2784     EL_TUBE_HORIZONTAL_UP,
2785     EL_TUBE_HORIZONTAL_DOWN,
2786     EL_TUBE_VERTICAL,
2787     EL_TUBE_VERTICAL_LEFT,
2788     EL_TUBE_VERTICAL_RIGHT,
2789     EL_TUBE_ANY,
2790     -1
2791   };
2792
2793   static int ep_keygate[] =
2794   {
2795     EL_GATE_1,
2796     EL_GATE_2,
2797     EL_GATE_3,
2798     EL_GATE_4,
2799     EL_GATE_1_GRAY,
2800     EL_GATE_2_GRAY,
2801     EL_GATE_3_GRAY,
2802     EL_GATE_4_GRAY,
2803     EL_EM_GATE_1,
2804     EL_EM_GATE_2,
2805     EL_EM_GATE_3,
2806     EL_EM_GATE_4,
2807     EL_EM_GATE_1_GRAY,
2808     EL_EM_GATE_2_GRAY,
2809     EL_EM_GATE_3_GRAY,
2810     EL_EM_GATE_4_GRAY,
2811     -1
2812   };
2813
2814   static int ep_amoeboid[] =
2815   {
2816     EL_AMOEBA_DEAD,
2817     EL_AMOEBA_WET,
2818     EL_AMOEBA_DRY,
2819     EL_AMOEBA_FULL,
2820     EL_BD_AMOEBA,
2821     -1
2822   };
2823
2824   static int ep_amoebalive[] =
2825   {
2826     EL_AMOEBA_WET,
2827     EL_AMOEBA_DRY,
2828     EL_AMOEBA_FULL,
2829     EL_BD_AMOEBA,
2830     -1
2831   };
2832
2833   static int ep_has_content[] =
2834   {
2835     EL_YAMYAM,
2836     EL_AMOEBA_WET,
2837     EL_AMOEBA_DRY,
2838     EL_AMOEBA_FULL,
2839     EL_BD_AMOEBA,
2840     -1
2841   };
2842
2843   static int ep_can_turn_each_move[] =
2844   {
2845     /* !!! do something with this one !!! */
2846     -1
2847   };
2848
2849   static int ep_can_grow[] =
2850   {
2851     EL_BD_AMOEBA,
2852     EL_AMOEBA_DROP,
2853     EL_AMOEBA_WET,
2854     EL_AMOEBA_DRY,
2855     EL_AMOEBA_FULL,
2856     EL_GAME_OF_LIFE,
2857     EL_BIOMAZE,
2858     -1
2859   };
2860
2861   static int ep_active_bomb[] =
2862   {
2863     EL_DYNAMITE_ACTIVE,
2864     EL_DYNABOMB_PLAYER_1_ACTIVE,
2865     EL_DYNABOMB_PLAYER_2_ACTIVE,
2866     EL_DYNABOMB_PLAYER_3_ACTIVE,
2867     EL_DYNABOMB_PLAYER_4_ACTIVE,
2868     EL_SP_DISK_RED_ACTIVE,
2869     -1
2870   };
2871
2872   static int ep_inactive[] =
2873   {
2874     EL_EMPTY,
2875     EL_SAND,
2876     EL_WALL,
2877     EL_BD_WALL,
2878     EL_WALL_SLIPPERY,
2879     EL_STEELWALL,
2880     EL_AMOEBA_DEAD,
2881     EL_QUICKSAND_EMPTY,
2882     EL_STONEBLOCK,
2883     EL_ROBOT_WHEEL,
2884     EL_KEY_1,
2885     EL_KEY_2,
2886     EL_KEY_3,
2887     EL_KEY_4,
2888     EL_EM_KEY_1,
2889     EL_EM_KEY_2,
2890     EL_EM_KEY_3,
2891     EL_EM_KEY_4,
2892     EL_GATE_1,
2893     EL_GATE_2,
2894     EL_GATE_3,
2895     EL_GATE_4,
2896     EL_GATE_1_GRAY,
2897     EL_GATE_2_GRAY,
2898     EL_GATE_3_GRAY,
2899     EL_GATE_4_GRAY,
2900     EL_EM_GATE_1,
2901     EL_EM_GATE_2,
2902     EL_EM_GATE_3,
2903     EL_EM_GATE_4,
2904     EL_EM_GATE_1_GRAY,
2905     EL_EM_GATE_2_GRAY,
2906     EL_EM_GATE_3_GRAY,
2907     EL_EM_GATE_4_GRAY,
2908     EL_DYNAMITE,
2909     EL_INVISIBLE_STEELWALL,
2910     EL_INVISIBLE_WALL,
2911     EL_INVISIBLE_SAND,
2912     EL_LAMP,
2913     EL_LAMP_ACTIVE,
2914     EL_WALL_EMERALD,
2915     EL_WALL_DIAMOND,
2916     EL_WALL_BD_DIAMOND,
2917     EL_WALL_EMERALD_YELLOW,
2918     EL_DYNABOMB_INCREASE_NUMBER,
2919     EL_DYNABOMB_INCREASE_SIZE,
2920     EL_DYNABOMB_INCREASE_POWER,
2921 #if 0
2922     EL_SOKOBAN_OBJECT,
2923 #endif
2924     EL_SOKOBAN_FIELD_EMPTY,
2925     EL_SOKOBAN_FIELD_FULL,
2926     EL_WALL_EMERALD_RED,
2927     EL_WALL_EMERALD_PURPLE,
2928     EL_ACID_POOL_TOPLEFT,
2929     EL_ACID_POOL_TOPRIGHT,
2930     EL_ACID_POOL_BOTTOMLEFT,
2931     EL_ACID_POOL_BOTTOM,
2932     EL_ACID_POOL_BOTTOMRIGHT,
2933     EL_MAGIC_WALL,
2934     EL_MAGIC_WALL_DEAD,
2935     EL_BD_MAGIC_WALL,
2936     EL_BD_MAGIC_WALL_DEAD,
2937     EL_AMOEBA_TO_DIAMOND,
2938     EL_BLOCKED,
2939     EL_SP_EMPTY,
2940     EL_SP_BASE,
2941     EL_SP_PORT_RIGHT,
2942     EL_SP_PORT_DOWN,
2943     EL_SP_PORT_LEFT,
2944     EL_SP_PORT_UP,
2945     EL_SP_GRAVITY_PORT_RIGHT,
2946     EL_SP_GRAVITY_PORT_DOWN,
2947     EL_SP_GRAVITY_PORT_LEFT,
2948     EL_SP_GRAVITY_PORT_UP,
2949     EL_SP_PORT_HORIZONTAL,
2950     EL_SP_PORT_VERTICAL,
2951     EL_SP_PORT_ANY,
2952     EL_SP_DISK_RED,
2953 #if 0
2954     EL_SP_DISK_YELLOW,
2955 #endif
2956     EL_SP_CHIP_SINGLE,
2957     EL_SP_CHIP_LEFT,
2958     EL_SP_CHIP_RIGHT,
2959     EL_SP_CHIP_TOP,
2960     EL_SP_CHIP_BOTTOM,
2961     EL_SP_HARDWARE_GRAY,
2962     EL_SP_HARDWARE_GREEN,
2963     EL_SP_HARDWARE_BLUE,
2964     EL_SP_HARDWARE_RED,
2965     EL_SP_HARDWARE_YELLOW,
2966     EL_SP_HARDWARE_BASE_1,
2967     EL_SP_HARDWARE_BASE_2,
2968     EL_SP_HARDWARE_BASE_3,
2969     EL_SP_HARDWARE_BASE_4,
2970     EL_SP_HARDWARE_BASE_5,
2971     EL_SP_HARDWARE_BASE_6,
2972     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2973     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2974     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2975     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2976     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2977     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2978     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2979     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2980     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2981     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2982     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2983     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2984     EL_SIGN_EXCLAMATION,
2985     EL_SIGN_RADIOACTIVITY,
2986     EL_SIGN_STOP,
2987     EL_SIGN_WHEELCHAIR,
2988     EL_SIGN_PARKING,
2989     EL_SIGN_ONEWAY,
2990     EL_SIGN_HEART,
2991     EL_SIGN_TRIANGLE,
2992     EL_SIGN_ROUND,
2993     EL_SIGN_EXIT,
2994     EL_SIGN_YINYANG,
2995     EL_SIGN_OTHER,
2996     EL_STEELWALL_SLIPPERY,
2997     EL_EMC_STEELWALL_1,
2998     EL_EMC_STEELWALL_2,
2999     EL_EMC_STEELWALL_3,
3000     EL_EMC_STEELWALL_4,
3001     EL_EMC_WALL_1,
3002     EL_EMC_WALL_2,
3003     EL_EMC_WALL_3,
3004     EL_EMC_WALL_4,
3005     EL_EMC_WALL_5,
3006     EL_EMC_WALL_6,
3007     EL_EMC_WALL_7,
3008     EL_EMC_WALL_8,
3009     -1
3010   };
3011
3012   static int ep_em_slippery_wall[] =
3013   {
3014     -1
3015   };
3016
3017   static int ep_gfx_crumbled[] =
3018   {
3019     EL_SAND,
3020     EL_LANDMINE,
3021     EL_TRAP,
3022     EL_TRAP_ACTIVE,
3023     -1
3024   };
3025
3026   static struct
3027   {
3028     int *elements;
3029     int property;
3030   } element_properties[] =
3031   {
3032     { ep_diggable,              EP_DIGGABLE             },
3033     { ep_collectible_only,      EP_COLLECTIBLE_ONLY     },
3034     { ep_dont_run_into,         EP_DONT_RUN_INTO        },
3035     { ep_dont_collide_with,     EP_DONT_COLLIDE_WITH    },
3036     { ep_dont_touch,            EP_DONT_TOUCH           },
3037     { ep_indestructible,        EP_INDESTRUCTIBLE       },
3038     { ep_slippery,              EP_SLIPPERY             },
3039     { ep_can_change,            EP_CAN_CHANGE           },
3040     { ep_can_move,              EP_CAN_MOVE             },
3041     { ep_can_fall,              EP_CAN_FALL             },
3042     { ep_can_smash_player,      EP_CAN_SMASH_PLAYER     },
3043     { ep_can_smash_enemies,     EP_CAN_SMASH_ENEMIES    },
3044     { ep_can_smash_everything,  EP_CAN_SMASH_EVERYTHING },
3045     { ep_can_explode_by_fire,   EP_CAN_EXPLODE_BY_FIRE  },
3046     { ep_can_explode_smashed,   EP_CAN_EXPLODE_SMASHED  },
3047     { ep_can_explode_impact,    EP_CAN_EXPLODE_IMPACT   },
3048     { ep_walkable_over,         EP_WALKABLE_OVER        },
3049     { ep_walkable_inside,       EP_WALKABLE_INSIDE      },
3050     { ep_walkable_under,        EP_WALKABLE_UNDER       },
3051     { ep_passable_over,         EP_PASSABLE_OVER        },
3052     { ep_passable_inside,       EP_PASSABLE_INSIDE      },
3053     { ep_passable_under,        EP_PASSABLE_UNDER       },
3054     { ep_droppable,             EP_DROPPABLE            },
3055     { ep_can_explode_1x1,       EP_CAN_EXPLODE_1X1      },
3056     { ep_pushable,              EP_PUSHABLE             },
3057     { ep_can_explode_cross,     EP_CAN_EXPLODE_CROSS    },
3058     { ep_protected,             EP_PROTECTED            },
3059
3060     { ep_player,                EP_PLAYER               },
3061     { ep_can_pass_magic_wall,   EP_CAN_PASS_MAGIC_WALL  },
3062     { ep_switchable,            EP_SWITCHABLE           },
3063     { ep_bd_element,            EP_BD_ELEMENT           },
3064     { ep_sp_element,            EP_SP_ELEMENT           },
3065     { ep_sb_element,            EP_SB_ELEMENT           },
3066     { ep_gem,                   EP_GEM                  },
3067     { ep_food_dark_yamyam,      EP_FOOD_DARK_YAMYAM     },
3068     { ep_food_penguin,          EP_FOOD_PENGUIN         },
3069     { ep_food_pig,              EP_FOOD_PIG             },
3070     { ep_historic_wall,         EP_HISTORIC_WALL        },
3071     { ep_historic_solid,        EP_HISTORIC_SOLID       },
3072     { ep_classic_enemy,         EP_CLASSIC_ENEMY        },
3073     { ep_belt,                  EP_BELT                 },
3074     { ep_belt_active,           EP_BELT_ACTIVE          },
3075     { ep_belt_switch,           EP_BELT_SWITCH          },
3076     { ep_tube,                  EP_TUBE                 },
3077     { ep_keygate,               EP_KEYGATE              },
3078     { ep_amoeboid,              EP_AMOEBOID             },
3079     { ep_amoebalive,            EP_AMOEBALIVE           },
3080     { ep_has_content,           EP_HAS_CONTENT          },
3081     { ep_can_turn_each_move,    EP_CAN_TURN_EACH_MOVE   },
3082     { ep_can_grow,              EP_CAN_GROW             },
3083     { ep_active_bomb,           EP_ACTIVE_BOMB          },
3084     { ep_inactive,              EP_INACTIVE             },
3085
3086     { ep_em_slippery_wall,      EP_EM_SLIPPERY_WALL     },
3087
3088     { ep_gfx_crumbled,          EP_GFX_CRUMBLED         },
3089
3090     { NULL,                     -1                      }
3091   };
3092
3093   static int copy_properties[][5] =
3094   {
3095     {
3096       EL_BUG,
3097       EL_BUG_LEFT,              EL_BUG_RIGHT,
3098       EL_BUG_UP,                EL_BUG_DOWN
3099     },
3100     {
3101       EL_SPACESHIP,
3102       EL_SPACESHIP_LEFT,        EL_SPACESHIP_RIGHT,
3103       EL_SPACESHIP_UP,          EL_SPACESHIP_DOWN
3104     },
3105     {
3106       EL_BD_BUTTERFLY,
3107       EL_BD_BUTTERFLY_LEFT,     EL_BD_BUTTERFLY_RIGHT,
3108       EL_BD_BUTTERFLY_UP,       EL_BD_BUTTERFLY_DOWN
3109     },
3110     {
3111       EL_BD_FIREFLY,
3112       EL_BD_FIREFLY_LEFT,       EL_BD_FIREFLY_RIGHT,
3113       EL_BD_FIREFLY_UP,         EL_BD_FIREFLY_DOWN
3114     },
3115     {
3116       EL_PACMAN,
3117       EL_PACMAN_LEFT,           EL_PACMAN_RIGHT,
3118       EL_PACMAN_UP,             EL_PACMAN_DOWN
3119     },
3120     {
3121       EL_MOLE,
3122       EL_MOLE_LEFT,             EL_MOLE_RIGHT,
3123       EL_MOLE_UP,               EL_MOLE_DOWN
3124     },
3125     {
3126       -1,
3127       -1, -1, -1, -1
3128     }
3129   };
3130
3131   int i, j, k;
3132
3133   /* always start with reliable default values (element has no properties) */
3134   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3135     for (j = 0; j < NUM_ELEMENT_PROPERTIES; j++)
3136       SET_PROPERTY(i, j, FALSE);
3137
3138   /* set all base element properties from above array definitions */
3139   for (i = 0; element_properties[i].elements != NULL; i++)
3140     for (j = 0; (element_properties[i].elements)[j] != -1; j++)
3141       SET_PROPERTY((element_properties[i].elements)[j],
3142                    element_properties[i].property, TRUE);
3143
3144   /* copy properties to some elements that are only stored in level file */
3145   for (i = 0; i < NUM_ELEMENT_PROPERTIES; i++)
3146     for (j = 0; copy_properties[j][0] != -1; j++)
3147       if (HAS_PROPERTY(copy_properties[j][0], i))
3148         for (k = 1; k <= 4; k++)
3149           SET_PROPERTY(copy_properties[j][k], i, TRUE);
3150 }
3151
3152 void InitElementPropertiesEngine(int engine_version)
3153 {
3154 #if 0
3155   static int active_properties[] =
3156   {
3157     EP_AMOEBALIVE,
3158     EP_AMOEBOID,
3159     EP_PFORTE,
3160     EP_DONT_COLLIDE_WITH,
3161     EP_MAUER,
3162     EP_CAN_FALL,
3163     EP_CAN_SMASH,
3164     EP_CAN_PASS_MAGIC_WALL,
3165     EP_CAN_MOVE,
3166     EP_DONT_TOUCH,
3167     EP_DONT_RUN_INTO,
3168     EP_GEM,
3169     EP_CAN_EXPLODE_BY_FIRE,
3170     EP_PUSHABLE,
3171     EP_PLAYER,
3172     EP_HAS_CONTENT,
3173     EP_DIGGABLE,
3174     EP_PASSABLE_INSIDE,
3175     EP_OVER_PLAYER,
3176     EP_ACTIVE_BOMB,
3177
3178     EP_BELT,
3179     EP_BELT_ACTIVE,
3180     EP_BELT_SWITCH,
3181     EP_WALKABLE_UNDER,
3182     EP_EM_SLIPPERY_WALL,
3183   };
3184 #endif
3185
3186   static int no_wall_properties[] =
3187   {
3188     EP_DIGGABLE,
3189     EP_COLLECTIBLE_ONLY,
3190     EP_DONT_RUN_INTO,
3191     EP_DONT_COLLIDE_WITH,
3192     EP_CAN_MOVE,
3193     EP_CAN_FALL,
3194     EP_CAN_SMASH_PLAYER,
3195     EP_CAN_SMASH_ENEMIES,
3196     EP_CAN_SMASH_EVERYTHING,
3197     EP_PUSHABLE,
3198
3199     EP_PLAYER,
3200     EP_GEM,
3201     EP_FOOD_DARK_YAMYAM,
3202     EP_FOOD_PENGUIN,
3203     EP_BELT,
3204     EP_BELT_ACTIVE,
3205     EP_TUBE,
3206     EP_AMOEBOID,
3207     EP_AMOEBALIVE,
3208     EP_ACTIVE_BOMB,
3209
3210     EP_ACCESSIBLE,
3211
3212     -1
3213   };
3214
3215   int i, j;
3216
3217 #if 0
3218   InitElementPropertiesStatic();
3219 #endif
3220
3221   /* important: after initialization in InitElementPropertiesStatic(), the
3222      elements are not again initialized to a default value; therefore all
3223      changes have to make sure that they leave the element with a defined
3224      property (which means that conditional property changes must be set to
3225      a reliable default value before) */
3226
3227   /* set all special, combined or engine dependent element properties */
3228   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3229   {
3230 #if 0
3231     for (j = EP_ACCESSIBLE_OVER; j < NUM_ELEMENT_PROPERTIES; j++)
3232       SET_PROPERTY(i, j, FALSE);
3233 #endif
3234
3235     /* ---------- INACTIVE ------------------------------------------------- */
3236     SET_PROPERTY(i, EP_INACTIVE, (i >= EL_CHAR_START && i <= EL_CHAR_END));
3237
3238     /* ---------- WALKABLE, PASSABLE, ACCESSIBLE --------------------------- */
3239     SET_PROPERTY(i, EP_WALKABLE, (IS_WALKABLE_OVER(i) ||
3240                                   IS_WALKABLE_INSIDE(i) ||
3241                                   IS_WALKABLE_UNDER(i)));
3242
3243     SET_PROPERTY(i, EP_PASSABLE, (IS_PASSABLE_OVER(i) ||
3244                                   IS_PASSABLE_INSIDE(i) ||
3245                                   IS_PASSABLE_UNDER(i)));
3246
3247     SET_PROPERTY(i, EP_ACCESSIBLE_OVER, (IS_WALKABLE_OVER(i) ||
3248                                          IS_PASSABLE_OVER(i)));
3249
3250     SET_PROPERTY(i, EP_ACCESSIBLE_INSIDE, (IS_WALKABLE_INSIDE(i) ||
3251                                            IS_PASSABLE_INSIDE(i)));
3252
3253     SET_PROPERTY(i, EP_ACCESSIBLE_UNDER, (IS_WALKABLE_UNDER(i) ||
3254                                           IS_PASSABLE_UNDER(i)));
3255
3256     SET_PROPERTY(i, EP_ACCESSIBLE, (IS_WALKABLE(i) ||
3257                                     IS_PASSABLE(i)));
3258
3259     /* ---------- COLLECTIBLE ---------------------------------------------- */
3260     SET_PROPERTY(i, EP_COLLECTIBLE, (IS_COLLECTIBLE_ONLY(i) ||
3261                                      IS_DROPPABLE(i)));
3262
3263     /* ---------- SNAPPABLE ------------------------------------------------ */
3264     SET_PROPERTY(i, EP_SNAPPABLE, (IS_DIGGABLE(i) ||
3265                                    IS_COLLECTIBLE(i) ||
3266                                    IS_SWITCHABLE(i) ||
3267                                    i == EL_BD_ROCK));
3268
3269     /* ---------- WALL ----------------------------------------------------- */
3270     SET_PROPERTY(i, EP_WALL, TRUE);     /* default: element is wall */
3271
3272     for (j = 0; no_wall_properties[j] != -1; j++)
3273       if (HAS_PROPERTY(i, no_wall_properties[j]) ||
3274           i >= EL_FIRST_RUNTIME_UNREAL)
3275         SET_PROPERTY(i, EP_WALL, FALSE);
3276
3277     if (IS_HISTORIC_WALL(i))
3278       SET_PROPERTY(i, EP_WALL, TRUE);
3279
3280     /* ---------- SOLID_FOR_PUSHING ---------------------------------------- */
3281     if (engine_version < VERSION_IDENT(2,2,0,0))
3282       SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, IS_HISTORIC_SOLID(i));
3283     else
3284       SET_PROPERTY(i, EP_SOLID_FOR_PUSHING, (!IS_WALKABLE(i) &&
3285                                              !IS_DIGGABLE(i) &&
3286                                              !IS_COLLECTIBLE(i)));
3287
3288 #if 1
3289     /* ---------- PROTECTED ------------------------------------------------ */
3290     if (IS_ACCESSIBLE_INSIDE(i))
3291       SET_PROPERTY(i, EP_PROTECTED, TRUE);
3292 #endif
3293
3294     /* ---------- DRAGONFIRE_PROOF ----------------------------------------- */
3295
3296     if (IS_HISTORIC_SOLID(i) || i == EL_EXPLOSION)
3297       SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, TRUE);
3298     else
3299       SET_PROPERTY(i, EP_DRAGONFIRE_PROOF, (IS_CUSTOM_ELEMENT(i) &&
3300                                             IS_INDESTRUCTIBLE(i)));
3301
3302     /* ---------- EXPLOSION_PROOF ------------------------------------------ */
3303     if (i == EL_FLAMES)
3304       SET_PROPERTY(i, EP_EXPLOSION_PROOF, TRUE);
3305     else if (engine_version < VERSION_IDENT(2,2,0,0))
3306       SET_PROPERTY(i, EP_EXPLOSION_PROOF, IS_INDESTRUCTIBLE(i));
3307     else
3308 #if 1
3309       SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
3310                                            (!IS_WALKABLE(i) ||
3311                                             IS_PROTECTED(i))));
3312 #else
3313 #if 1
3314       SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
3315                                            !IS_WALKABLE_OVER(i) &&
3316                                            !IS_WALKABLE_UNDER(i)));
3317 #else
3318       SET_PROPERTY(i, EP_EXPLOSION_PROOF, (IS_INDESTRUCTIBLE(i) &&
3319                                            IS_PROTECTED(i)));
3320 #endif
3321 #endif
3322
3323     if (IS_CUSTOM_ELEMENT(i))
3324     {
3325       /* these are additional properties which are initially false when set */
3326
3327       /* ---------- DONT_COLLIDE_WITH / DONT_RUN_INTO ---------------------- */
3328       if (DONT_TOUCH(i))
3329         SET_PROPERTY(i, EP_DONT_COLLIDE_WITH, TRUE);
3330       if (DONT_COLLIDE_WITH(i))
3331         SET_PROPERTY(i, EP_DONT_RUN_INTO, TRUE);
3332
3333       /* ---------- CAN_SMASH_ENEMIES / CAN_SMASH_PLAYER ------------------- */
3334       if (CAN_SMASH_EVERYTHING(i))
3335         SET_PROPERTY(i, EP_CAN_SMASH_ENEMIES, TRUE);
3336       if (CAN_SMASH_ENEMIES(i))
3337         SET_PROPERTY(i, EP_CAN_SMASH_PLAYER, TRUE);
3338     }
3339
3340     /* ---------- CAN_SMASH ------------------------------------------------ */
3341     SET_PROPERTY(i, EP_CAN_SMASH, (CAN_SMASH_PLAYER(i) ||
3342                                    CAN_SMASH_ENEMIES(i) ||
3343                                    CAN_SMASH_EVERYTHING(i)));
3344
3345     /* ---------- CAN_EXPLODE ---------------------------------------------- */
3346     SET_PROPERTY(i, EP_CAN_EXPLODE, (CAN_EXPLODE_BY_FIRE(i) ||
3347                                      CAN_EXPLODE_SMASHED(i) ||
3348                                      CAN_EXPLODE_IMPACT(i)));
3349
3350     /* ---------- CAN_EXPLODE_3X3 ------------------------------------------ */
3351     SET_PROPERTY(i, EP_CAN_EXPLODE_3X3, (CAN_EXPLODE(i) &&
3352                                          !CAN_EXPLODE_1X1(i) &&
3353                                          !CAN_EXPLODE_CROSS(i)));
3354
3355     /* ---------- CAN_EXPLODE_BY_DRAGONFIRE -------------------------------- */
3356     SET_PROPERTY(i, EP_CAN_EXPLODE_BY_DRAGONFIRE, CAN_EXPLODE_BY_FIRE(i));
3357
3358     /* ---------- CAN_EXPLODE_BY_EXPLOSION --------------------------------- */
3359     SET_PROPERTY(i, EP_CAN_EXPLODE_BY_EXPLOSION, (CAN_EXPLODE_BY_FIRE(i) ||
3360                                                   i == EL_BLACK_ORB));
3361
3362     /* ---------- COULD_MOVE_INTO_ACID ------------------------------------- */
3363     SET_PROPERTY(i, EP_COULD_MOVE_INTO_ACID, (ELEM_IS_PLAYER(i) ||
3364                                               CAN_MOVE(i) ||
3365                                               IS_CUSTOM_ELEMENT(i)));
3366
3367     /* ---------- MAYBE_DONT_COLLIDE_WITH ---------------------------------- */
3368     SET_PROPERTY(i, EP_MAYBE_DONT_COLLIDE_WITH, (i == EL_SP_SNIKSNAK ||
3369                                                  i == EL_SP_ELECTRON));
3370
3371     /* ---------- CAN_MOVE_INTO_ACID --------------------------------------- */
3372     if (COULD_MOVE_INTO_ACID(i) && !IS_CUSTOM_ELEMENT(i))
3373       SET_PROPERTY(i, EP_CAN_MOVE_INTO_ACID,
3374                    getMoveIntoAcidProperty(&level, i));
3375
3376     /* ---------- DONT_COLLIDE_WITH ---------------------------------------- */
3377     if (MAYBE_DONT_COLLIDE_WITH(i))
3378       SET_PROPERTY(i, EP_DONT_COLLIDE_WITH,
3379                    getDontCollideWithProperty(&level, i));
3380
3381     /* ---------- SP_PORT -------------------------------------------------- */
3382     SET_PROPERTY(i, EP_SP_PORT, (IS_SP_ELEMENT(i) &&
3383                                  IS_PASSABLE_INSIDE(i)));
3384
3385 #if 0
3386     if (i == EL_CUSTOM_START + 253)
3387       printf("::: %d, %d, %d -> %d\n",
3388              CAN_EXPLODE_1X1(i),
3389              CAN_EXPLODE_3X3(i),
3390              CAN_EXPLODE_CROSS(i),
3391              CAN_EXPLODE(i));
3392 #endif
3393
3394     /* ---------- CAN_CHANGE ----------------------------------------------- */
3395     SET_PROPERTY(i, EP_CAN_CHANGE, FALSE);      /* default: cannot change */
3396     for (j = 0; j < element_info[i].num_change_pages; j++)
3397       if (element_info[i].change_page[j].can_change)
3398         SET_PROPERTY(i, EP_CAN_CHANGE, TRUE);
3399
3400     /* ---------- GFX_CRUMBLED --------------------------------------------- */
3401     SET_PROPERTY(i, EP_GFX_CRUMBLED,
3402                  element_info[i].crumbled[ACTION_DEFAULT] != IMG_EMPTY);
3403   }
3404
3405 #if 0
3406   /* determine inactive elements (used for engine main loop optimization) */
3407   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3408   {
3409     boolean active = FALSE;
3410
3411     for (j = 0; i < NUM_ELEMENT_PROPERTIES; j++)
3412     {
3413       if (HAS_PROPERTY(i, j))
3414         active = TRUE;
3415     }
3416
3417 #if 0
3418     if (!active)
3419       SET_PROPERTY(i, EP_INACTIVE, TRUE);
3420 #endif
3421   }
3422 #endif
3423
3424   /* dynamically adjust element properties according to game engine version */
3425   {
3426     static int ep_em_slippery_wall[] =
3427     {
3428       EL_STEELWALL,
3429       EL_WALL,
3430       EL_EXPANDABLE_WALL,
3431       EL_EXPANDABLE_WALL_HORIZONTAL,
3432       EL_EXPANDABLE_WALL_VERTICAL,
3433       EL_EXPANDABLE_WALL_ANY,
3434       -1
3435     };
3436
3437     /* special EM style gems behaviour */
3438     for (i = 0; ep_em_slippery_wall[i] != -1; i++)
3439       SET_PROPERTY(ep_em_slippery_wall[i], EP_EM_SLIPPERY_WALL,
3440                    level.em_slippery_gems);
3441
3442     /* "EL_EXPANDABLE_WALL_GROWING" wasn't slippery for EM gems in 2.0.1 */
3443     SET_PROPERTY(EL_EXPANDABLE_WALL_GROWING, EP_EM_SLIPPERY_WALL,
3444                  (level.em_slippery_gems &&
3445                   engine_version > VERSION_IDENT(2,0,1,0)));
3446   }
3447
3448 #if 1
3449   /* set default push delay values (corrected since version 3.0.7-1) */
3450   if (engine_version < VERSION_IDENT(3,0,7,1))
3451   {
3452     game.default_push_delay_fixed = 2;
3453     game.default_push_delay_random = 8;
3454   }
3455   else
3456   {
3457     game.default_push_delay_fixed = 8;
3458     game.default_push_delay_random = 8;
3459   }
3460
3461   /* set uninitialized push delay values of custom elements in older levels */
3462   for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
3463   {
3464     int element = EL_CUSTOM_START + i;
3465
3466     if (element_info[element].push_delay_fixed == -1)
3467       element_info[element].push_delay_fixed = game.default_push_delay_fixed;
3468     if (element_info[element].push_delay_random == -1)
3469       element_info[element].push_delay_random = game.default_push_delay_random;
3470   }
3471
3472   /* set some other uninitialized values of custom elements in older levels */
3473   if (engine_version < VERSION_IDENT(3,1,0,0))
3474   {
3475     for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
3476     {
3477       int element = EL_CUSTOM_START + i;
3478
3479       element_info[element].access_direction = MV_ALL_DIRECTIONS;
3480
3481       element_info[element].explosion_delay = 17;
3482       element_info[element].ignition_delay = 8;
3483     }
3484   }
3485
3486 #if 0
3487   /* set element properties that were handled incorrectly in older levels */
3488   if (engine_version < VERSION_IDENT(3,1,0,0))
3489   {
3490     SET_PROPERTY(EL_SP_SNIKSNAK, EP_DONT_COLLIDE_WITH, FALSE);
3491     SET_PROPERTY(EL_SP_ELECTRON, EP_DONT_COLLIDE_WITH, FALSE);
3492   }
3493 #endif
3494
3495 #endif
3496
3497   /* this is needed because some graphics depend on element properties */
3498   if (game_status == GAME_MODE_PLAYING)
3499     InitElementGraphicInfo();
3500 }
3501
3502 static void InitGlobal()
3503 {
3504   global.autoplay_leveldir = NULL;
3505
3506   global.frames_per_second = 0;
3507   global.fps_slowdown = FALSE;
3508   global.fps_slowdown_factor = 1;
3509 }
3510
3511 void Execute_Command(char *command)
3512 {
3513   int i;
3514
3515   if (strcmp(command, "print graphicsinfo.conf") == 0)
3516   {
3517     printf("# You can configure additional/alternative image files here.\n");
3518     printf("# (The entries below are default and therefore commented out.)\n");
3519     printf("\n");
3520     printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
3521     printf("\n");
3522     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
3523     printf("\n");
3524
3525     for (i = 0; image_config[i].token != NULL; i++)
3526       printf("# %s\n", getFormattedSetupEntry(image_config[i].token,
3527                                               image_config[i].value));
3528
3529     exit(0);
3530   }
3531   else if (strcmp(command, "print soundsinfo.conf") == 0)
3532   {
3533     printf("# You can configure additional/alternative sound files here.\n");
3534     printf("# (The entries below are default and therefore commented out.)\n");
3535     printf("\n");
3536     printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
3537     printf("\n");
3538     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
3539     printf("\n");
3540
3541     for (i = 0; sound_config[i].token != NULL; i++)
3542       printf("# %s\n", getFormattedSetupEntry(sound_config[i].token,
3543                                               sound_config[i].value));
3544
3545     exit(0);
3546   }
3547   else if (strcmp(command, "print musicinfo.conf") == 0)
3548   {
3549     printf("# You can configure additional/alternative music files here.\n");
3550     printf("# (The entries below are default and therefore commented out.)\n");
3551     printf("\n");
3552     printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
3553     printf("\n");
3554     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
3555     printf("\n");
3556
3557     for (i = 0; music_config[i].token != NULL; i++)
3558       printf("# %s\n", getFormattedSetupEntry(music_config[i].token,
3559                                               music_config[i].value));
3560
3561     exit(0);
3562   }
3563   else if (strcmp(command, "print editorsetup.conf") == 0)
3564   {
3565     printf("# You can configure your personal editor element list here.\n");
3566     printf("# (The entries below are default and therefore commented out.)\n");
3567     printf("\n");
3568
3569     PrintEditorElementList();
3570
3571     exit(0);
3572   }
3573   else if (strcmp(command, "print helpanim.conf") == 0)
3574   {
3575     printf("# You can configure different element help animations here.\n");
3576     printf("# (The entries below are default and therefore commented out.)\n");
3577     printf("\n");
3578
3579     for (i = 0; helpanim_config[i].token != NULL; i++)
3580     {
3581       printf("# %s\n", getFormattedSetupEntry(helpanim_config[i].token,
3582                                               helpanim_config[i].value));
3583
3584       if (strcmp(helpanim_config[i].token, "end") == 0)
3585         printf("#\n");
3586     }
3587
3588     exit(0);
3589   }
3590   else if (strcmp(command, "print helptext.conf") == 0)
3591   {
3592     printf("# You can configure different element help text here.\n");
3593     printf("# (The entries below are default and therefore commented out.)\n");
3594     printf("\n");
3595
3596     for (i = 0; helptext_config[i].token != NULL; i++)
3597       printf("# %s\n", getFormattedSetupEntry(helptext_config[i].token,
3598                                               helptext_config[i].value));
3599
3600     exit(0);
3601   }
3602   else if (strncmp(command, "dump level ", 11) == 0)
3603   {
3604     char *filename = &command[11];
3605
3606     if (access(filename, F_OK) != 0)
3607       Error(ERR_EXIT, "cannot open file '%s'", filename);
3608
3609     LoadLevelFromFilename(&level, filename);
3610     DumpLevel(&level);
3611
3612     exit(0);
3613   }
3614   else if (strncmp(command, "dump tape ", 10) == 0)
3615   {
3616     char *filename = &command[10];
3617
3618     if (access(filename, F_OK) != 0)
3619       Error(ERR_EXIT, "cannot open file '%s'", filename);
3620
3621     LoadTapeFromFilename(filename);
3622     DumpTape(&tape);
3623
3624     exit(0);
3625   }
3626   else if (strncmp(command, "autoplay ", 9) == 0)
3627   {
3628     char *str_copy = getStringCopy(&command[9]);
3629     char *str_ptr = strchr(str_copy, ' ');
3630
3631     global.autoplay_leveldir = str_copy;
3632     global.autoplay_level_nr = -1;
3633
3634     if (str_ptr != NULL)
3635     {
3636       *str_ptr++ = '\0';                        /* terminate leveldir string */
3637       global.autoplay_level_nr = atoi(str_ptr); /* get level_nr value */
3638     }
3639   }
3640   else
3641   {
3642     Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
3643   }
3644 }
3645
3646 static void InitSetup()
3647 {
3648   LoadSetup();                                  /* global setup info */
3649
3650   /* set some options from setup file */
3651
3652   if (setup.options.verbose)
3653     options.verbose = TRUE;
3654 }
3655
3656 static void InitPlayerInfo()
3657 {
3658   int i;
3659
3660   /* choose default local player */
3661   local_player = &stored_player[0];
3662
3663   for (i = 0; i < MAX_PLAYERS; i++)
3664     stored_player[i].connected = FALSE;
3665
3666   local_player->connected = TRUE;
3667 }
3668
3669 static void InitArtworkInfo()
3670 {
3671   LoadArtworkInfo();
3672 }
3673
3674 static char *get_string_in_brackets(char *string)
3675 {
3676   char *string_in_brackets = checked_malloc(strlen(string) + 3);
3677
3678   sprintf(string_in_brackets, "[%s]", string);
3679
3680   return string_in_brackets;
3681 }
3682
3683 static char *get_level_id_suffix(int id_nr)
3684 {
3685   char *id_suffix = checked_malloc(1 + 3 + 1);
3686
3687   if (id_nr < 0 || id_nr > 999)
3688     id_nr = 0;
3689
3690   sprintf(id_suffix, ".%03d", id_nr);
3691
3692   return id_suffix;
3693 }
3694
3695 #if 0
3696 static char *get_element_class_token(int element)
3697 {
3698   char *element_class_name = element_info[element].class_name;
3699   char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
3700
3701   sprintf(element_class_token, "[%s]", element_class_name);
3702
3703   return element_class_token;
3704 }
3705
3706 static char *get_action_class_token(int action)
3707 {
3708   char *action_class_name = &element_action_info[action].suffix[1];
3709   char *action_class_token = checked_malloc(strlen(action_class_name) + 3);
3710
3711   sprintf(action_class_token, "[%s]", action_class_name);
3712
3713   return action_class_token;
3714 }
3715 #endif
3716
3717 static void InitArtworkConfig()
3718 {
3719   static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
3720   static char *sound_id_prefix[2 * MAX_NUM_ELEMENTS + 1];
3721   static char *music_id_prefix[NUM_MUSIC_PREFIXES + 1];
3722   static char *action_id_suffix[NUM_ACTIONS + 1];
3723   static char *direction_id_suffix[NUM_DIRECTIONS + 1];
3724   static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
3725   static char *level_id_suffix[MAX_LEVELS + 1];
3726   static char *dummy[1] = { NULL };
3727   static char *ignore_generic_tokens[] =
3728   {
3729     "name",
3730     "sort_priority",
3731     NULL
3732   };
3733   static char **ignore_image_tokens;
3734   static char **ignore_sound_tokens;
3735   static char **ignore_music_tokens;
3736   int num_ignore_generic_tokens;
3737   int num_ignore_image_tokens;
3738   int num_ignore_sound_tokens;
3739   int num_ignore_music_tokens;
3740   int i;
3741
3742   /* dynamically determine list of generic tokens to be ignored */
3743   num_ignore_generic_tokens = 0;
3744   for (i = 0; ignore_generic_tokens[i] != NULL; i++)
3745     num_ignore_generic_tokens++;
3746
3747   /* dynamically determine list of image tokens to be ignored */
3748   num_ignore_image_tokens = num_ignore_generic_tokens;
3749   for (i = 0; image_config_vars[i].token != NULL; i++)
3750     num_ignore_image_tokens++;
3751   ignore_image_tokens =
3752     checked_malloc((num_ignore_image_tokens + 1) * sizeof(char *));
3753   for (i = 0; i < num_ignore_generic_tokens; i++)
3754     ignore_image_tokens[i] = ignore_generic_tokens[i];
3755   for (i = 0; i < num_ignore_image_tokens - num_ignore_generic_tokens; i++)
3756     ignore_image_tokens[num_ignore_generic_tokens + i] =
3757       image_config_vars[i].token;
3758   ignore_image_tokens[num_ignore_image_tokens] = NULL;
3759
3760   /* dynamically determine list of sound tokens to be ignored */
3761   num_ignore_sound_tokens = num_ignore_generic_tokens;
3762   ignore_sound_tokens =
3763     checked_malloc((num_ignore_sound_tokens + 1) * sizeof(char *));
3764   for (i = 0; i < num_ignore_generic_tokens; i++)
3765     ignore_sound_tokens[i] = ignore_generic_tokens[i];
3766   ignore_sound_tokens[num_ignore_sound_tokens] = NULL;
3767
3768   /* dynamically determine list of music tokens to be ignored */
3769   num_ignore_music_tokens = num_ignore_generic_tokens;
3770   ignore_music_tokens =
3771     checked_malloc((num_ignore_music_tokens + 1) * sizeof(char *));
3772   for (i = 0; i < num_ignore_generic_tokens; i++)
3773     ignore_music_tokens[i] = ignore_generic_tokens[i];
3774   ignore_music_tokens[num_ignore_music_tokens] = NULL;
3775
3776   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3777     image_id_prefix[i] = element_info[i].token_name;
3778   for (i = 0; i < NUM_FONTS; i++)
3779     image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
3780   image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
3781
3782   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3783     sound_id_prefix[i] = element_info[i].token_name;
3784   for (i = 0; i < MAX_NUM_ELEMENTS; i++)
3785     sound_id_prefix[MAX_NUM_ELEMENTS + i] =
3786       get_string_in_brackets(element_info[i].class_name);
3787   sound_id_prefix[2 * MAX_NUM_ELEMENTS] = NULL;
3788
3789   for (i = 0; i < NUM_MUSIC_PREFIXES; i++)
3790     music_id_prefix[i] = music_prefix_info[i].prefix;
3791   music_id_prefix[MAX_LEVELS] = NULL;
3792
3793   for (i = 0; i < NUM_ACTIONS; i++)
3794     action_id_suffix[i] = element_action_info[i].suffix;
3795   action_id_suffix[NUM_ACTIONS] = NULL;
3796
3797   for (i = 0; i < NUM_DIRECTIONS; i++)
3798     direction_id_suffix[i] = element_direction_info[i].suffix;
3799   direction_id_suffix[NUM_DIRECTIONS] = NULL;
3800
3801   for (i = 0; i < NUM_SPECIAL_GFX_ARGS; i++)
3802     special_id_suffix[i] = special_suffix_info[i].suffix;
3803   special_id_suffix[NUM_SPECIAL_GFX_ARGS] = NULL;
3804
3805   for (i = 0; i < MAX_LEVELS; i++)
3806     level_id_suffix[i] = get_level_id_suffix(i);
3807   level_id_suffix[MAX_LEVELS] = NULL;
3808
3809   InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
3810                 image_id_prefix, action_id_suffix, direction_id_suffix,
3811                 special_id_suffix, ignore_image_tokens);
3812   InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
3813                 sound_id_prefix, action_id_suffix, dummy,
3814                 special_id_suffix, ignore_sound_tokens);
3815   InitMusicList(music_config, NUM_MUSIC_FILES, music_config_suffix,
3816                 music_id_prefix, special_id_suffix, level_id_suffix,
3817                 dummy, ignore_music_tokens);
3818 }
3819
3820 static void InitMixer()
3821 {
3822   OpenAudio();
3823   StartMixer();
3824 }
3825
3826 void InitGfx()
3827 {
3828   char *filename_font_initial = NULL;
3829   Bitmap *bitmap_font_initial = NULL;
3830   int i, j;
3831
3832   /* determine settings for initial font (for displaying startup messages) */
3833   for (i = 0; image_config[i].token != NULL; i++)
3834   {
3835     for (j = 0; j < NUM_INITIAL_FONTS; j++)
3836     {
3837       char font_token[128];
3838       int len_font_token;
3839
3840       sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1);
3841       len_font_token = strlen(font_token);
3842
3843       if (strcmp(image_config[i].token, font_token) == 0)
3844         filename_font_initial = image_config[i].value;
3845       else if (strlen(image_config[i].token) > len_font_token &&
3846                strncmp(image_config[i].token, font_token, len_font_token) == 0)
3847       {
3848         if (strcmp(&image_config[i].token[len_font_token], ".x") == 0)
3849           font_initial[j].src_x = atoi(image_config[i].value);
3850         else if (strcmp(&image_config[i].token[len_font_token], ".y") == 0)
3851           font_initial[j].src_y = atoi(image_config[i].value);
3852         else if (strcmp(&image_config[i].token[len_font_token], ".width") == 0)
3853           font_initial[j].width = atoi(image_config[i].value);
3854         else if (strcmp(&image_config[i].token[len_font_token],".height") == 0)
3855           font_initial[j].height = atoi(image_config[i].value);
3856       }
3857     }
3858   }
3859
3860   for (j = 0; j < NUM_INITIAL_FONTS; j++)
3861   {
3862     font_initial[j].num_chars = DEFAULT_NUM_CHARS_PER_FONT;
3863     font_initial[j].num_chars_per_line = DEFAULT_NUM_CHARS_PER_LINE;
3864   }
3865
3866   if (filename_font_initial == NULL)    /* should not happen */
3867     Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
3868
3869   /* create additional image buffers for double-buffering */
3870   bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
3871   bitmap_db_door  = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
3872
3873   /* initialize screen properties */
3874   InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
3875                    REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
3876                    bitmap_db_field);
3877   InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
3878   InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
3879   InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
3880
3881   bitmap_font_initial = LoadCustomImage(filename_font_initial);
3882
3883   for (j = 0; j < NUM_INITIAL_FONTS; j++)
3884     font_initial[j].bitmap = bitmap_font_initial;
3885
3886   InitFontGraphicInfo();
3887
3888   DrawInitText(getProgramInitString(), 20, FC_YELLOW);
3889   DrawInitText(PROGRAM_COPYRIGHT_STRING, 50, FC_RED);
3890
3891   DrawInitText("Loading graphics:", 120, FC_GREEN);
3892
3893   InitTileClipmasks();
3894 }
3895
3896 void InitGfxBackground()
3897 {
3898   int x, y;
3899
3900   drawto = backbuffer;
3901   fieldbuffer = bitmap_db_field;
3902   SetDrawtoField(DRAW_BACKBUFFER);
3903
3904   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
3905              0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
3906   ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
3907   ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
3908
3909   for (x = 0; x < MAX_BUF_XSIZE; x++)
3910     for (y = 0; y < MAX_BUF_YSIZE; y++)
3911       redraw[x][y] = 0;
3912   redraw_tiles = 0;
3913   redraw_mask = REDRAW_ALL;
3914 }
3915
3916 static void InitLevelInfo()
3917 {
3918   LoadLevelInfo();                              /* global level info */
3919   LoadLevelSetup_LastSeries();                  /* last played series info */
3920   LoadLevelSetup_SeriesInfo();                  /* last played level info */
3921 }
3922
3923 void InitLevelArtworkInfo()
3924 {
3925   LoadLevelArtworkInfo();
3926 }
3927
3928 static void InitImages()
3929 {
3930 #if 1
3931   setLevelArtworkDir(artwork.gfx_first);
3932 #endif
3933
3934 #if 0
3935   printf("::: InitImages for '%s' ['%s', '%s'] ['%s', '%s']\n",
3936          leveldir_current->identifier,
3937          artwork.gfx_current_identifier,
3938          artwork.gfx_current->identifier,
3939          leveldir_current->graphics_set,
3940          leveldir_current->graphics_path);
3941 #endif
3942
3943   ReloadCustomImages();
3944
3945   LoadCustomElementDescriptions();
3946   LoadSpecialMenuDesignSettings();
3947
3948   ReinitializeGraphics();
3949 }
3950
3951 static void InitSound(char *identifier)
3952 {
3953   if (identifier == NULL)
3954     identifier = artwork.snd_current->identifier;
3955
3956 #if 1
3957   /* set artwork path to send it to the sound server process */
3958   setLevelArtworkDir(artwork.snd_first);
3959 #endif
3960
3961   InitReloadCustomSounds(identifier);
3962   ReinitializeSounds();
3963 }
3964
3965 static void InitMusic(char *identifier)
3966 {
3967   if (identifier == NULL)
3968     identifier = artwork.mus_current->identifier;
3969
3970 #if 1
3971   /* set artwork path to send it to the sound server process */
3972   setLevelArtworkDir(artwork.mus_first);
3973 #endif
3974
3975   InitReloadCustomMusic(identifier);
3976   ReinitializeMusic();
3977 }
3978
3979 void InitNetworkServer()
3980 {
3981 #if defined(PLATFORM_UNIX)
3982   int nr_wanted;
3983 #endif
3984
3985   if (!options.network)
3986     return;
3987
3988 #if defined(PLATFORM_UNIX)
3989   nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
3990
3991   if (!ConnectToServer(options.server_host, options.server_port))
3992     Error(ERR_EXIT, "cannot connect to network game server");
3993
3994   SendToServer_PlayerName(setup.player_name);
3995   SendToServer_ProtocolVersion();
3996
3997   if (nr_wanted)
3998     SendToServer_NrWanted(nr_wanted);
3999 #endif
4000 }
4001
4002 static char *getNewArtworkIdentifier(int type)
4003 {
4004   static char *leveldir_current_identifier[3] = { NULL, NULL, NULL };
4005   static boolean last_override_level_artwork[3] = { FALSE, FALSE, FALSE };
4006   static boolean last_has_level_artwork_set[3] = { FALSE, FALSE, FALSE };
4007   static boolean initialized[3] = { FALSE, FALSE, FALSE };
4008   TreeInfo *artwork_first_node = ARTWORK_FIRST_NODE(artwork, type);
4009   boolean setup_override_artwork = SETUP_OVERRIDE_ARTWORK(setup, type);
4010   char *setup_artwork_set = SETUP_ARTWORK_SET(setup, type);
4011   char *leveldir_identifier = leveldir_current->identifier;
4012 #if 1
4013   /* !!! setLevelArtworkDir() should be moved to an earlier stage !!! */
4014   char *leveldir_artwork_set = setLevelArtworkDir(artwork_first_node);
4015 #else
4016   char *leveldir_artwork_set = LEVELDIR_ARTWORK_SET(leveldir_current, type);
4017 #endif
4018   boolean has_level_artwork_set = (leveldir_artwork_set != NULL);
4019   char *artwork_current_identifier;
4020   char *artwork_new_identifier = NULL;  /* default: nothing has changed */
4021
4022   /* leveldir_current may be invalid (level group, parent link) */
4023   if (!validLevelSeries(leveldir_current))
4024     return NULL;
4025
4026   /* 1st step: determine artwork set to be activated in descending order:
4027      --------------------------------------------------------------------
4028      1. setup artwork (when configured to override everything else)
4029      2. artwork set configured in "levelinfo.conf" of current level set
4030         (artwork in level directory will have priority when loading later)
4031      3. artwork in level directory (stored in artwork sub-directory)
4032      4. setup artwork (currently configured in setup menu) */
4033
4034   if (setup_override_artwork)
4035     artwork_current_identifier = setup_artwork_set;
4036   else if (leveldir_artwork_set != NULL)
4037     artwork_current_identifier = leveldir_artwork_set;
4038   else if (getTreeInfoFromIdentifier(artwork_first_node, leveldir_identifier))
4039     artwork_current_identifier = leveldir_identifier;
4040   else
4041     artwork_current_identifier = setup_artwork_set;
4042
4043
4044   /* 2nd step: check if it is really needed to reload artwork set
4045      ------------------------------------------------------------ */
4046
4047 #if 0
4048   if (type == ARTWORK_TYPE_GRAPHICS)
4049     printf("::: 0: '%s' ['%s', '%s'] ['%s' ('%s')]\n",
4050            artwork_new_identifier,
4051            ARTWORK_CURRENT_IDENTIFIER(artwork, type),
4052            artwork_current_identifier,
4053            leveldir_current->graphics_set,
4054            leveldir_current->identifier);
4055 #endif
4056
4057   /* ---------- reload if level set and also artwork set has changed ------- */
4058   if (leveldir_current_identifier[type] != leveldir_identifier &&
4059       (last_has_level_artwork_set[type] || has_level_artwork_set))
4060     artwork_new_identifier = artwork_current_identifier;
4061
4062   leveldir_current_identifier[type] = leveldir_identifier;
4063   last_has_level_artwork_set[type] = has_level_artwork_set;
4064
4065 #if 0
4066   if (type == ARTWORK_TYPE_GRAPHICS)
4067     printf("::: 1: '%s'\n", artwork_new_identifier);
4068 #endif
4069
4070   /* ---------- reload if "override artwork" setting has changed ----------- */
4071   if (last_override_level_artwork[type] != setup_override_artwork)
4072     artwork_new_identifier = artwork_current_identifier;
4073
4074   last_override_level_artwork[type] = setup_override_artwork;
4075
4076 #if 0
4077   if (type == ARTWORK_TYPE_GRAPHICS)
4078     printf("::: 2: '%s'\n", artwork_new_identifier);
4079 #endif
4080
4081   /* ---------- reload if current artwork identifier has changed ----------- */
4082   if (strcmp(ARTWORK_CURRENT_IDENTIFIER(artwork, type),
4083              artwork_current_identifier) != 0)
4084     artwork_new_identifier = artwork_current_identifier;
4085
4086   *(&(ARTWORK_CURRENT_IDENTIFIER(artwork, type))) = artwork_current_identifier;
4087
4088 #if 0
4089   if (type == ARTWORK_TYPE_GRAPHICS)
4090     printf("::: 3: '%s'\n", artwork_new_identifier);
4091 #endif
4092
4093   /* ---------- do not reload directly after starting ---------------------- */
4094   if (!initialized[type])
4095     artwork_new_identifier = NULL;
4096
4097   initialized[type] = TRUE;
4098
4099 #if 0
4100   if (type == ARTWORK_TYPE_GRAPHICS)
4101     printf("::: 4: '%s'\n", artwork_new_identifier);
4102 #endif
4103
4104 #if 0
4105   if (type == ARTWORK_TYPE_GRAPHICS)
4106     printf("CHECKING OLD/NEW GFX:\n- OLD: %s\n- NEW: %s ['%s', '%s'] ['%s']\n",
4107            artwork.gfx_current_identifier, artwork_current_identifier,
4108            artwork.gfx_current->identifier, leveldir_current->graphics_set,
4109            artwork_new_identifier);
4110 #endif
4111
4112   return artwork_new_identifier;
4113 }
4114
4115 void ReloadCustomArtwork(int force_reload)
4116 {
4117   char *gfx_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_GRAPHICS);
4118   char *snd_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_SOUNDS);
4119   char *mus_new_identifier = getNewArtworkIdentifier(ARTWORK_TYPE_MUSIC);
4120   boolean force_reload_gfx = (force_reload & (1 << ARTWORK_TYPE_GRAPHICS));
4121   boolean force_reload_snd = (force_reload & (1 << ARTWORK_TYPE_SOUNDS));
4122   boolean force_reload_mus = (force_reload & (1 << ARTWORK_TYPE_MUSIC));
4123   boolean redraw_screen = FALSE;
4124
4125   if (gfx_new_identifier != NULL || force_reload_gfx)
4126   {
4127 #if 0
4128     printf("RELOADING GRAPHICS '%s' -> '%s' ['%s', '%s']\n",
4129            artwork.gfx_current_identifier,
4130            gfx_new_identifier,
4131            artwork.gfx_current->identifier,
4132            leveldir_current->graphics_set);
4133 #endif
4134
4135     ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
4136
4137     InitImages();
4138
4139 #if 0
4140     printf("... '%s'\n",
4141            leveldir_current->graphics_set);
4142 #endif
4143
4144     FreeTileClipmasks();
4145     InitTileClipmasks();
4146
4147     redraw_screen = TRUE;
4148   }
4149
4150   if (snd_new_identifier != NULL || force_reload_snd)
4151   {
4152     ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
4153
4154     InitSound(snd_new_identifier);
4155
4156     redraw_screen = TRUE;
4157   }
4158
4159   if (mus_new_identifier != NULL || force_reload_mus)
4160   {
4161     ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
4162
4163     InitMusic(mus_new_identifier);
4164
4165     redraw_screen = TRUE;
4166   }
4167
4168   if (redraw_screen)
4169   {
4170     InitGfxBackground();
4171
4172     /* force redraw of (open or closed) door graphics */
4173     SetDoorState(DOOR_OPEN_ALL);
4174     CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
4175   }
4176 }
4177
4178 void KeyboardAutoRepeatOffUnlessAutoplay()
4179 {
4180   if (global.autoplay_leveldir == NULL)
4181     KeyboardAutoRepeatOff();
4182 }
4183
4184
4185 /* ========================================================================= */
4186 /* OpenAll()                                                                 */
4187 /* ========================================================================= */
4188
4189 void OpenAll()
4190 {
4191   InitGlobal();         /* initialize some global variables */
4192
4193   if (options.execute_command)
4194     Execute_Command(options.execute_command);
4195
4196   if (options.serveronly)
4197   {
4198 #if defined(PLATFORM_UNIX)
4199     NetworkServer(options.server_port, options.serveronly);
4200 #else
4201     Error(ERR_WARN, "networking only supported in Unix version");
4202 #endif
4203     exit(0);    /* never reached */
4204   }
4205
4206   InitSetup();
4207
4208   InitPlayerInfo();
4209   InitArtworkInfo();            /* needed before loading gfx, sound & music */
4210   InitArtworkConfig();          /* needed before forking sound child process */
4211   InitMixer();
4212
4213   InitCounter();
4214
4215   InitRND(NEW_RANDOMIZE);
4216   InitSimpleRND(NEW_RANDOMIZE);
4217
4218   InitJoysticks();
4219
4220   InitVideoDisplay();
4221   InitVideoBuffer(&backbuffer, &window, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH,
4222                   setup.fullscreen);
4223
4224   InitEventFilter(FilterMouseMotionEvents);
4225
4226   InitElementPropertiesStatic();
4227   InitElementPropertiesEngine(GAME_VERSION_ACTUAL);
4228
4229   InitGfx();
4230
4231   InitLevelInfo();
4232   InitLevelArtworkInfo();
4233
4234   InitImages();                 /* needs to know current level directory */
4235   InitSound(NULL);              /* needs to know current level directory */
4236   InitMusic(NULL);              /* needs to know current level directory */
4237
4238   InitGfxBackground();
4239
4240   if (global.autoplay_leveldir)
4241   {
4242     AutoPlayTape();
4243     return;
4244   }
4245
4246   game_status = GAME_MODE_MAIN;
4247
4248   DrawMainMenu();
4249
4250   InitNetworkServer();
4251 }
4252
4253 void CloseAllAndExit(int exit_value)
4254 {
4255   StopSounds();
4256   FreeAllSounds();
4257   FreeAllMusic();
4258   CloseAudio();         /* called after freeing sounds (needed for SDL) */
4259
4260   FreeAllImages();
4261   FreeTileClipmasks();
4262
4263   CloseVideoDisplay();
4264   ClosePlatformDependentStuff();
4265
4266   exit(exit_value);
4267 }