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