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