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