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