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