rnd-20030406-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 == MAINMENU || game_status == TYPENAME)
264     special = GFX_SPECIAL_ARG_MAIN;
265   else if (game_status == CHOOSELEVEL)
266     special = GFX_SPECIAL_ARG_LEVELS;
267   else if (game_status == HALLOFFAME)
268     special = GFX_SPECIAL_ARG_SCORES;
269   else if (game_status == LEVELED)
270     special = GFX_SPECIAL_ARG_EDITOR;
271   else if (game_status == HELPSCREEN)
272     special = GFX_SPECIAL_ARG_INFO;
273   else if (game_status == SETUP)
274     special = GFX_SPECIAL_ARG_SETUP;
275   else if (game_status == PSEUDO_PREVIEW)
276     special = GFX_SPECIAL_ARG_PREVIEW;
277   else if (game_status == PLAYING || game_status == PSEUDO_DOOR)
278     special = GFX_SPECIAL_ARG_DOOR;
279
280   if (special != -1)
281     return font_info[font_nr].special_bitmap_id[special];
282   else
283     return font_nr;
284 }
285
286 void InitFontGraphicInfo()
287 {
288   static struct FontBitmapInfo *font_bitmap_info = NULL;
289   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
290   int num_property_mappings = getImageListPropertyMappingSize();
291   int num_font_bitmaps = NUM_FONTS;
292   int i, j;
293
294   if (graphic_info == NULL)             /* still at startup phase */
295   {
296     InitFontInfo(font_initial, NUM_INITIAL_FONTS, getFontBitmapID);
297
298     return;
299   }
300
301   /* ---------- initialize font graphic definitions ---------- */
302
303   /* always start with reliable default values (normal font graphics) */
304   for (i=0; i < NUM_FONTS; i++)
305     font_info[i].graphic = FONT_INITIAL_1;
306
307   /* initialize normal font/graphic mapping from static configuration */
308   for (i=0; font_to_graphic[i].font_nr > -1; i++)
309   {
310     int font_nr = font_to_graphic[i].font_nr;
311     int special = font_to_graphic[i].special;
312     int graphic = font_to_graphic[i].graphic;
313
314     if (special != -1)
315       continue;
316
317     font_info[font_nr].graphic = graphic;
318   }
319
320   /* always start with reliable default values (special font graphics) */
321   for (i=0; i < NUM_FONTS; i++)
322   {
323     for (j=0; j < NUM_SPECIAL_GFX_ARGS; j++)
324     {
325       font_info[i].special_graphic[j] = font_info[i].graphic;
326       font_info[i].special_bitmap_id[j] = i;
327     }
328   }
329
330   /* initialize special font/graphic mapping from static configuration */
331   for (i=0; font_to_graphic[i].font_nr > -1; i++)
332   {
333     int font_nr = font_to_graphic[i].font_nr;
334     int special = font_to_graphic[i].special;
335     int graphic = font_to_graphic[i].graphic;
336
337     if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
338     {
339       font_info[font_nr].special_graphic[special] = graphic;
340       font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
341       num_font_bitmaps++;
342     }
343   }
344
345   /* initialize special element/graphic mapping from dynamic configuration */
346   for (i=0; i < num_property_mappings; i++)
347   {
348     int font_nr = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
349     int special = property_mapping[i].ext3_index;
350     int graphic = property_mapping[i].artwork_index;
351
352     if (font_nr < 0)
353       continue;
354
355     if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
356     {
357       font_info[font_nr].special_graphic[special] = graphic;
358       font_info[font_nr].special_bitmap_id[special] = num_font_bitmaps;
359       num_font_bitmaps++;
360     }
361   }
362
363   /* ---------- initialize font bitmap array ---------- */
364
365   if (font_bitmap_info != NULL)
366     free(font_bitmap_info);
367
368   font_bitmap_info =
369     checked_calloc(num_font_bitmaps * sizeof(struct FontBitmapInfo));
370
371   /* ---------- initialize font bitmap definitions ---------- */
372
373   for (i=0; i < NUM_FONTS; i++)
374   {
375     if (i < NUM_INITIAL_FONTS)
376     {
377       font_bitmap_info[i] = font_initial[i];
378       continue;
379     }
380
381     for (j=0; j < NUM_SPECIAL_GFX_ARGS; j++)
382     {
383       int font_bitmap_id = font_info[i].special_bitmap_id[j];
384       int graphic = font_info[i].special_graphic[j];
385
386       /* set 'graphic_info' for font entries, if uninitialized */
387       if (graphic_info[graphic].anim_frames < MIN_NUM_CHARS_PER_FONT)
388       {
389         graphic_info[graphic].anim_frames = DEFAULT_NUM_CHARS_PER_FONT;
390         graphic_info[graphic].anim_frames_per_line= DEFAULT_NUM_CHARS_PER_LINE;
391       }
392
393       /* copy font relevant information from graphics information */
394       font_bitmap_info[font_bitmap_id].bitmap = graphic_info[graphic].bitmap;
395       font_bitmap_info[font_bitmap_id].src_x  = graphic_info[graphic].src_x;
396       font_bitmap_info[font_bitmap_id].src_y  = graphic_info[graphic].src_y;
397       font_bitmap_info[font_bitmap_id].width  = graphic_info[graphic].width;
398       font_bitmap_info[font_bitmap_id].height = graphic_info[graphic].height;
399       font_bitmap_info[font_bitmap_id].draw_x = graphic_info[graphic].draw_x;
400       font_bitmap_info[font_bitmap_id].draw_y = graphic_info[graphic].draw_y;
401
402       font_bitmap_info[font_bitmap_id].num_chars =
403         graphic_info[graphic].anim_frames;
404       font_bitmap_info[font_bitmap_id].num_chars_per_line =
405         graphic_info[graphic].anim_frames_per_line;
406     }
407   }
408
409   InitFontInfo(font_bitmap_info, num_font_bitmaps, getFontBitmapID);
410 }
411
412 void InitElementGraphicInfo()
413 {
414   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
415   int num_property_mappings = getImageListPropertyMappingSize();
416   int i, act, dir;
417
418   /* set values to -1 to identify later as "uninitialized" values */
419   for (i=0; i<MAX_NUM_ELEMENTS; i++)
420   {
421     for (act=0; act<NUM_ACTIONS; act++)
422     {
423       element_info[i].graphic[act] = -1;
424
425       for (dir=0; dir<NUM_DIRECTIONS; dir++)
426         element_info[i].direction_graphic[act][dir] = -1;
427     }
428   }
429
430   /* initialize normal element/graphic mapping from static configuration */
431   for (i=0; element_to_graphic[i].element > -1; i++)
432   {
433     int element   = element_to_graphic[i].element;
434     int action    = element_to_graphic[i].action;
435     int direction = element_to_graphic[i].direction;
436     int graphic   = element_to_graphic[i].graphic;
437
438     if (graphic_info[graphic].bitmap == NULL)
439       continue;
440
441     if (action < 0)
442       action = ACTION_DEFAULT;
443
444     if (direction > -1)
445       element_info[element].direction_graphic[action][direction] = graphic;
446     else
447       element_info[element].graphic[action] = graphic;
448   }
449
450   /* initialize normal element/graphic mapping from dynamic configuration */
451   for (i=0; i < num_property_mappings; i++)
452   {
453     int element   = property_mapping[i].base_index;
454     int action    = property_mapping[i].ext1_index;
455     int direction = property_mapping[i].ext2_index;
456     int special   = property_mapping[i].ext3_index;
457     int graphic   = property_mapping[i].artwork_index;
458
459     if (graphic_info[graphic].bitmap == NULL)
460       continue;
461
462     if (element >= MAX_NUM_ELEMENTS || special != -1)
463       continue;
464
465     if (action < 0)
466       action = ACTION_DEFAULT;
467
468     if (direction > -1)
469       element_info[element].direction_graphic[action][direction] = graphic;
470     else
471       element_info[element].graphic[action] = graphic;
472   }
473
474   /* now set all '-1' values to element specific default values */
475   for (i=0; i<MAX_NUM_ELEMENTS; i++)
476   {
477     int default_action_graphic = element_info[i].graphic[ACTION_DEFAULT];
478     int default_action_direction_graphic[NUM_DIRECTIONS];
479
480     if (default_action_graphic == -1)
481       default_action_graphic = IMG_CHAR_QUESTION;
482
483     for (dir=0; dir<NUM_DIRECTIONS; dir++)
484     {
485       default_action_direction_graphic[dir] =
486         element_info[i].direction_graphic[ACTION_DEFAULT][dir];
487
488       if (default_action_direction_graphic[dir] == -1)
489         default_action_direction_graphic[dir] = default_action_graphic;
490     }
491
492     for (act=0; act<NUM_ACTIONS; act++)
493     {
494       boolean act_empty = (act == ACTION_DIGGING ||
495                            act == ACTION_SNAPPING ||
496                            act == ACTION_COLLECTING);
497
498       for (dir=0; dir<NUM_DIRECTIONS; dir++)
499       {
500         int default_direction_graphic = element_info[i].graphic[act];
501
502         /* no graphic for current action -- use default direction graphic */
503         if (default_direction_graphic == -1)
504           default_direction_graphic =
505             (act_empty ? IMG_EMPTY : default_action_direction_graphic[dir]);
506
507         if (element_info[i].direction_graphic[act][dir] == -1)
508           element_info[i].direction_graphic[act][dir] =
509             default_direction_graphic;
510       }
511
512       /* no graphic for this specific action -- use default action graphic */
513       if (element_info[i].graphic[act] == -1)
514         element_info[i].graphic[act] =
515           (act_empty ? IMG_EMPTY : default_action_graphic);
516     }
517   }
518
519 #if 0
520 #if DEBUG
521   if (options.verbose)
522   {
523     for (i=0; i<MAX_NUM_ELEMENTS; i++)
524       if (element_info[i].graphic[ACTION_DEFAULT] == IMG_CHAR_QUESTION &&
525           i != EL_CHAR_QUESTION)
526         Error(ERR_RETURN, "warning: no graphic for element '%s' (%d)",
527               element_info[i].token_name, i);
528   }
529 #endif
530 #endif
531 }
532
533 void InitElementSpecialGraphicInfo()
534 {
535   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
536   int num_property_mappings = getImageListPropertyMappingSize();
537   int i, j;
538
539   /* always start with reliable default values */
540   for (i=0; i < MAX_NUM_ELEMENTS; i++)
541     for (j=0; j < NUM_SPECIAL_GFX_ARGS; j++)
542       element_info[i].special_graphic[j] =
543         element_info[i].graphic[ACTION_DEFAULT];
544
545   /* initialize special element/graphic mapping from static configuration */
546   for (i=0; element_to_special_graphic[i].element > -1; i++)
547   {
548     int element = element_to_special_graphic[i].element;
549     int special = element_to_special_graphic[i].special;
550     int graphic = element_to_special_graphic[i].graphic;
551     boolean base_redefined = getImageListEntry(el2img(element))->redefined;
552     boolean special_redefined = getImageListEntry(graphic)->redefined;
553
554     if (base_redefined && !special_redefined)
555       continue;
556
557     element_info[element].special_graphic[special] = graphic;
558   }
559
560   /* initialize special element/graphic mapping from dynamic configuration */
561   for (i=0; i < num_property_mappings; i++)
562   {
563     int element = property_mapping[i].base_index;
564     int special = property_mapping[i].ext3_index;
565     int graphic = property_mapping[i].artwork_index;
566
567     if (element >= MAX_NUM_ELEMENTS)
568       continue;
569
570     if (special >= 0 && special < NUM_SPECIAL_GFX_ARGS)
571       element_info[element].special_graphic[special] = graphic;
572   }
573 }
574
575 static void set_graphic_parameters(int graphic, char **parameter_raw)
576 {
577   Bitmap *src_bitmap = getBitmapFromImageID(graphic);
578   int parameter[NUM_GFX_ARGS];
579   int num_xtiles = 1, num_ytiles = 1;
580   int i;
581
582   /* get integer values from string parameters */
583   for (i=0; i < NUM_GFX_ARGS; i++)
584     parameter[i] =
585       get_parameter_value(image_config_suffix[i].token, parameter_raw[i],
586                           image_config_suffix[i].type);
587
588   graphic_info[graphic].bitmap = src_bitmap;
589
590   /* start with reliable default values */
591   graphic_info[graphic].src_x = 0;
592   graphic_info[graphic].src_y = 0;
593   graphic_info[graphic].width = TILEX;
594   graphic_info[graphic].height = TILEY;
595   graphic_info[graphic].offset_x = 0;   /* one or both of these values ... */
596   graphic_info[graphic].offset_y = 0;   /* ... will be corrected later */
597
598   /* optional x and y tile position of animation frame sequence */
599   if (parameter[GFX_ARG_XPOS] != ARG_UNDEFINED_VALUE)
600     graphic_info[graphic].src_x = parameter[GFX_ARG_XPOS] * TILEX;
601   if (parameter[GFX_ARG_YPOS] != ARG_UNDEFINED_VALUE)
602     graphic_info[graphic].src_y = parameter[GFX_ARG_YPOS] * TILEY;
603
604   /* optional x and y pixel position of animation frame sequence */
605   if (parameter[GFX_ARG_X] != ARG_UNDEFINED_VALUE)
606     graphic_info[graphic].src_x = parameter[GFX_ARG_X];
607   if (parameter[GFX_ARG_Y] != ARG_UNDEFINED_VALUE)
608     graphic_info[graphic].src_y = parameter[GFX_ARG_Y];
609
610   /* optional width and height of each animation frame */
611   if (parameter[GFX_ARG_WIDTH] != ARG_UNDEFINED_VALUE)
612     graphic_info[graphic].width = parameter[GFX_ARG_WIDTH];
613   if (parameter[GFX_ARG_HEIGHT] != ARG_UNDEFINED_VALUE)
614     graphic_info[graphic].height = parameter[GFX_ARG_HEIGHT];
615
616   if (src_bitmap)
617   {
618     num_xtiles = src_bitmap->width  / graphic_info[graphic].width;
619     num_ytiles = src_bitmap->height / graphic_info[graphic].height;
620   }
621
622   /* correct x or y offset dependant of vertical or horizontal frame order */
623   if (parameter[GFX_ARG_VERTICAL])      /* frames are ordered vertically */
624     graphic_info[graphic].offset_y =
625       (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
626        parameter[GFX_ARG_OFFSET] : graphic_info[graphic].height);
627   else                                  /* frames are ordered horizontally */
628     graphic_info[graphic].offset_x =
629       (parameter[GFX_ARG_OFFSET] != ARG_UNDEFINED_VALUE ?
630        parameter[GFX_ARG_OFFSET] : graphic_info[graphic].width);
631
632   /* optionally, the x and y offset of frames can be specified directly */
633   if (parameter[GFX_ARG_XOFFSET] != ARG_UNDEFINED_VALUE)
634     graphic_info[graphic].offset_x = parameter[GFX_ARG_XOFFSET];
635   if (parameter[GFX_ARG_YOFFSET] != ARG_UNDEFINED_VALUE)
636     graphic_info[graphic].offset_y = parameter[GFX_ARG_YOFFSET];
637
638   /* automatically determine correct number of frames, if not defined */
639   if (parameter[GFX_ARG_FRAMES] != ARG_UNDEFINED_VALUE)
640     graphic_info[graphic].anim_frames = parameter[GFX_ARG_FRAMES];
641   else if (parameter[GFX_ARG_XPOS] == 0 && !parameter[GFX_ARG_VERTICAL])
642     graphic_info[graphic].anim_frames = num_xtiles;
643   else if (parameter[GFX_ARG_YPOS] == 0 && parameter[GFX_ARG_VERTICAL])
644     graphic_info[graphic].anim_frames = num_ytiles;
645   else
646     graphic_info[graphic].anim_frames = 1;
647
648   graphic_info[graphic].anim_frames_per_line =
649     (parameter[GFX_ARG_FRAMES_PER_LINE] != ARG_UNDEFINED_VALUE ?
650      parameter[GFX_ARG_FRAMES_PER_LINE] : graphic_info[graphic].anim_frames);
651
652   graphic_info[graphic].anim_delay = parameter[GFX_ARG_DELAY];
653   if (graphic_info[graphic].anim_delay == 0)    /* delay must be at least 1 */
654     graphic_info[graphic].anim_delay = 1;
655
656   graphic_info[graphic].anim_mode = parameter[GFX_ARG_ANIM_MODE];
657   if (graphic_info[graphic].anim_frames == 1)
658     graphic_info[graphic].anim_mode = ANIM_NONE;
659
660   /* automatically determine correct start frame, if not defined */
661   if (parameter[GFX_ARG_START_FRAME] == ARG_UNDEFINED_VALUE)
662     graphic_info[graphic].anim_start_frame = 0;
663   else if (graphic_info[graphic].anim_mode & ANIM_REVERSE)
664     graphic_info[graphic].anim_start_frame =
665       graphic_info[graphic].anim_frames - parameter[GFX_ARG_START_FRAME] - 1;
666   else
667     graphic_info[graphic].anim_start_frame = parameter[GFX_ARG_START_FRAME];
668
669   /* animation synchronized with global frame counter, not move position */
670   graphic_info[graphic].anim_global_sync = parameter[GFX_ARG_GLOBAL_SYNC];
671
672   /* this is only used for toon animations */
673   graphic_info[graphic].step_offset = parameter[GFX_ARG_STEP_OFFSET];
674   graphic_info[graphic].step_delay  = parameter[GFX_ARG_STEP_DELAY];
675
676   /* this is only used for drawing font characters */
677   graphic_info[graphic].draw_x = parameter[GFX_ARG_DRAW_XOFFSET];
678   graphic_info[graphic].draw_y = parameter[GFX_ARG_DRAW_YOFFSET];
679 }
680
681 static void InitGraphicInfo()
682 {
683   int fallback_graphic = IMG_CHAR_EXCLAM;
684   struct FileInfo *fallback_image = getImageListEntry(fallback_graphic);
685   Bitmap *fallback_bitmap = getBitmapFromImageID(fallback_graphic);
686   int num_images = getImageListSize();
687   int i;
688
689 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
690   static boolean clipmasks_initialized = FALSE;
691   Pixmap src_pixmap;
692   XGCValues clip_gc_values;
693   unsigned long clip_gc_valuemask;
694   GC copy_clipmask_gc = None;
695 #endif
696
697   if (graphic_info != NULL)
698     free(graphic_info);
699
700   graphic_info = checked_calloc(num_images * sizeof(struct GraphicInfo));
701
702 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
703   if (clipmasks_initialized)
704   {
705     for (i=0; i<num_images; i++)
706     {
707       if (graphic_info[i].clip_mask)
708         XFreePixmap(display, graphic_info[i].clip_mask);
709       if (graphic_info[i].clip_gc)
710         XFreeGC(display, graphic_info[i].clip_gc);
711
712       graphic_info[i].clip_mask = None;
713       graphic_info[i].clip_gc = None;
714     }
715   }
716 #endif
717
718   for (i=0; i<num_images; i++)
719   {
720     struct FileInfo *image = getImageListEntry(i);
721     Bitmap *src_bitmap;
722     int src_x, src_y;
723     int first_frame, last_frame;
724
725     set_graphic_parameters(i, image->parameter);
726
727     /* now check if no animation frames are outside of the loaded image */
728
729     if (graphic_info[i].bitmap == NULL)
730       continue;         /* skip check for optional images that are undefined */
731
732     first_frame = 0;
733     getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
734     if (src_x < 0 || src_y < 0 ||
735         src_x + TILEX > src_bitmap->width ||
736         src_y + TILEY > src_bitmap->height)
737     {
738       Error(ERR_RETURN_LINE, "-");
739       Error(ERR_RETURN, "warning: error found in config file:");
740       Error(ERR_RETURN, "- config file: '%s'",
741             getImageConfigFilename());
742       Error(ERR_RETURN, "- config token: '%s'",
743             getTokenFromImageID(i));
744       Error(ERR_RETURN, "- image file: '%s'",
745             src_bitmap->source_filename);
746       Error(ERR_RETURN,
747             "error: first animation frame out of bounds (%d, %d)",
748             src_x, src_y);
749       Error(ERR_RETURN, "custom graphic rejected for this element/action");
750
751       if (i == fallback_graphic)
752         Error(ERR_EXIT, "fatal error: no fallback graphic available");
753
754       Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
755       Error(ERR_RETURN_LINE, "-");
756
757       set_graphic_parameters(i, fallback_image->default_parameter);
758       graphic_info[i].bitmap = fallback_bitmap;
759     }
760
761     last_frame = graphic_info[i].anim_frames - 1;
762     getGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y);
763     if (src_x < 0 || src_y < 0 ||
764         src_x + TILEX > src_bitmap->width ||
765         src_y + TILEY > src_bitmap->height)
766     {
767       Error(ERR_RETURN_LINE, "-");
768       Error(ERR_RETURN, "warning: error found in config file:");
769       Error(ERR_RETURN, "- config file: '%s'",
770             getImageConfigFilename());
771       Error(ERR_RETURN, "- config token: '%s'",
772             getTokenFromImageID(i));
773       Error(ERR_RETURN, "- image file: '%s'",
774             src_bitmap->source_filename);
775       Error(ERR_RETURN,
776             "error: last animation frame (%d) out of bounds (%d, %d)",
777             last_frame, src_x, src_y);
778       Error(ERR_RETURN, "custom graphic rejected for this element/action");
779
780       if (i == fallback_graphic)
781         Error(ERR_EXIT, "fatal error: no fallback graphic available");
782
783       Error(ERR_RETURN, "fallback done to 'char_exclam' for this graphic");
784       Error(ERR_RETURN_LINE, "-");
785
786       set_graphic_parameters(i, fallback_image->default_parameter);
787       graphic_info[i].bitmap = fallback_bitmap;
788     }
789
790 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
791     /* currently we need only a tile clip mask from the first frame */
792     getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
793
794     if (copy_clipmask_gc == None)
795     {
796       clip_gc_values.graphics_exposures = False;
797       clip_gc_valuemask = GCGraphicsExposures;
798       copy_clipmask_gc = XCreateGC(display, src_bitmap->clip_mask,
799                                    clip_gc_valuemask, &clip_gc_values);
800     }
801
802     graphic_info[i].clip_mask =
803       XCreatePixmap(display, window->drawable, TILEX, TILEY, 1);
804
805     src_pixmap = src_bitmap->clip_mask;
806     XCopyArea(display, src_pixmap, graphic_info[i].clip_mask,
807               copy_clipmask_gc, src_x, src_y, TILEX, TILEY, 0, 0);
808
809     clip_gc_values.graphics_exposures = False;
810     clip_gc_values.clip_mask = graphic_info[i].clip_mask;
811     clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
812
813     graphic_info[i].clip_gc =
814       XCreateGC(display, window->drawable, clip_gc_valuemask, &clip_gc_values);
815 #endif
816   }
817
818 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
819   if (copy_clipmask_gc)
820     XFreeGC(display, copy_clipmask_gc);
821
822   clipmasks_initialized = TRUE;
823 #endif
824 }
825
826 static void InitElementSoundInfo()
827 {
828   struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
829   int num_property_mappings = getSoundListPropertyMappingSize();
830   int i, j, act;
831
832   /* set values to -1 to identify later as "uninitialized" values */
833   for (i=0; i < MAX_NUM_ELEMENTS; i++)
834     for (act=0; act < NUM_ACTIONS; act++)
835       element_info[i].sound[act] = -1;
836
837   /* initialize element/sound mapping from static configuration */
838   for (i=0; element_to_sound[i].element > -1; i++)
839   {
840     int element      = element_to_sound[i].element;
841     int action       = element_to_sound[i].action;
842     int sound        = element_to_sound[i].sound;
843     boolean is_class = element_to_sound[i].is_class;
844
845     if (action < 0)
846       action = ACTION_DEFAULT;
847
848     if (!is_class)
849       element_info[element].sound[action] = sound;
850     else
851       for (j=0; j < MAX_NUM_ELEMENTS; j++)
852         if (strcmp(element_info[j].class_name,
853                    element_info[element].class_name) == 0)
854           element_info[j].sound[action] = sound;
855   }
856
857   /* initialize element/sound mapping from dynamic configuration */
858   for (i=0; i < num_property_mappings; i++)
859   {
860     int element = property_mapping[i].base_index;
861     int action  = property_mapping[i].ext1_index;
862     int sound   = property_mapping[i].artwork_index;
863
864     if (element >= MAX_NUM_ELEMENTS)
865       continue;
866
867     if (action < 0)
868       action = ACTION_DEFAULT;
869
870     element_info[element].sound[action] = sound;
871   }
872
873   /* initialize element class/sound mapping from dynamic configuration */
874   for (i=0; i < num_property_mappings; i++)
875   {
876     int element_class = property_mapping[i].base_index - MAX_NUM_ELEMENTS;
877     int action        = property_mapping[i].ext1_index;
878     int sound         = property_mapping[i].artwork_index;
879
880     if (element_class < 0 || element_class >= MAX_NUM_ELEMENTS)
881       continue;
882
883     if (action < 0)
884       action = ACTION_DEFAULT;
885
886     for (j=0; j < MAX_NUM_ELEMENTS; j++)
887       if (strcmp(element_info[j].class_name,
888                  element_info[element_class].class_name) == 0)
889         element_info[j].sound[action] = sound;
890   }
891
892   /* now set all '-1' values to element specific default values */
893   for (i=0; i<MAX_NUM_ELEMENTS; i++)
894   {
895     int default_action_sound = element_info[i].sound[ACTION_DEFAULT];
896
897     for (act=0; act < NUM_ACTIONS; act++)
898     {
899       /* no sound for this specific action -- use default action sound */
900       if (element_info[i].sound[act] == -1)
901         element_info[i].sound[act] = default_action_sound;
902     }
903   }
904 }
905
906 static void set_sound_parameters(int sound, char **parameter_raw)
907 {
908   int parameter[NUM_SND_ARGS];
909   int i;
910
911   /* get integer values from string parameters */
912   for (i=0; i < NUM_SND_ARGS; i++)
913     parameter[i] =
914       get_parameter_value(sound_config_suffix[i].token, parameter_raw[i],
915                           sound_config_suffix[i].type);
916
917   /* explicit loop mode setting in configuration overrides default value */
918   if (parameter[SND_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
919     sound_info[sound].loop = parameter[SND_ARG_MODE_LOOP];
920 }
921
922 static void InitSoundInfo()
923 {
924   struct PropertyMapping *property_mapping = getSoundListPropertyMapping();
925   int num_property_mappings = getSoundListPropertyMappingSize();
926   int *sound_effect_properties;
927   int num_sounds = getSoundListSize();
928   int i, j;
929
930   if (sound_info != NULL)
931     free(sound_info);
932
933   sound_effect_properties = checked_calloc(num_sounds * sizeof(int));
934   sound_info = checked_calloc(num_sounds * sizeof(struct SoundInfo));
935
936   /* initialize sound effect for all elements to "no sound" */
937   for (i=0; i<MAX_NUM_ELEMENTS; i++)
938     for (j=0; j<NUM_ACTIONS; j++)
939       element_info[i].sound[j] = SND_UNDEFINED;
940
941   for (i=0; i<num_sounds; i++)
942   {
943     struct FileInfo *sound = getSoundListEntry(i);
944     int len_effect_text = strlen(sound->token);
945
946     sound_effect_properties[i] = ACTION_OTHER;
947     sound_info[i].loop = FALSE;
948
949     /* determine all loop sounds and identify certain sound classes */
950
951     for (j=0; element_action_info[j].suffix; j++)
952     {
953       int len_action_text = strlen(element_action_info[j].suffix);
954
955       if (len_action_text < len_effect_text &&
956           strcmp(&sound->token[len_effect_text - len_action_text],
957                  element_action_info[j].suffix) == 0)
958       {
959         sound_effect_properties[i] = element_action_info[j].value;
960
961         if (element_action_info[j].is_loop_sound)
962           sound_info[i].loop = TRUE;
963       }
964     }
965
966     /* associate elements and some selected sound actions */
967
968     for (j=0; j<MAX_NUM_ELEMENTS; j++)
969     {
970       if (element_info[j].class_name)
971       {
972         int len_class_text = strlen(element_info[j].class_name);
973
974         if (len_class_text + 1 < len_effect_text &&
975             strncmp(sound->token,
976                     element_info[j].class_name, len_class_text) == 0 &&
977             sound->token[len_class_text] == '.')
978         {
979           int sound_action_value = sound_effect_properties[i];
980
981           element_info[j].sound[sound_action_value] = i;
982         }
983       }
984     }
985
986     set_sound_parameters(i, sound->parameter);
987   }
988
989   free(sound_effect_properties);
990
991   /* initialize element/sound mapping from dynamic configuration */
992   for (i=0; i < num_property_mappings; i++)
993   {
994     int element   = property_mapping[i].base_index;
995     int action    = property_mapping[i].ext1_index;
996     int sound     = property_mapping[i].artwork_index;
997
998     if (action < 0)
999       action = ACTION_DEFAULT;
1000
1001     element_info[element].sound[action] = sound;
1002   }
1003
1004 #if 0
1005   /* TEST ONLY */
1006   {
1007     int element = EL_CUSTOM_11;
1008     int j = 0;
1009
1010     while (element_action_info[j].suffix)
1011     {
1012       printf("element %d, sound action '%s'  == %d\n",
1013              element, element_action_info[j].suffix,
1014              element_info[element].sound[j]);
1015       j++;
1016     }
1017   }
1018
1019   PlaySoundLevelElementAction(0,0, EL_CUSTOM_11, ACTION_PUSHING);
1020 #endif
1021
1022 #if 0
1023   /* TEST ONLY */
1024   {
1025     int element = EL_SAND;
1026     int sound_action = ACTION_DIGGING;
1027     int j = 0;
1028
1029     while (element_action_info[j].suffix)
1030     {
1031       if (element_action_info[j].value == sound_action)
1032         printf("element %d, sound action '%s'  == %d\n",
1033                element, element_action_info[j].suffix,
1034                element_info[element].sound[sound_action]);
1035       j++;
1036     }
1037   }
1038 #endif
1039 }
1040
1041 static void ReinitializeGraphics()
1042 {
1043   InitGraphicInfo();                    /* graphic properties mapping */
1044   InitElementGraphicInfo();             /* element game graphic mapping */
1045   InitElementSpecialGraphicInfo();      /* element special graphic mapping */
1046
1047   InitElementSmallImages();             /* create editor and preview images */
1048   InitFontGraphicInfo();                /* initialize text drawing functions */
1049
1050   SetMainBackgroundImage(IMG_BACKGROUND);
1051   SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
1052
1053   InitGadgets();
1054   InitToons();
1055 }
1056
1057 static void ReinitializeSounds()
1058 {
1059   InitSoundInfo();              /* sound properties mapping */
1060   InitElementSoundInfo();       /* element game sound mapping */
1061
1062 #if 1
1063   InitElementSoundInfo();       /* element game sound mapping */
1064 #endif
1065
1066   InitPlaySoundLevel();         /* internal game sound settings */
1067 }
1068
1069 static void ReinitializeMusic()
1070 {
1071   /* currently nothing to do */
1072 }
1073
1074 void InitElementProperties()
1075 {
1076   int i, j;
1077
1078   static int ep_amoebalive[] =
1079   {
1080     EL_AMOEBA_WET,
1081     EL_AMOEBA_DRY,
1082     EL_AMOEBA_FULL,
1083     EL_BD_AMOEBA
1084   };
1085   static int ep_amoebalive_num = SIZEOF_ARRAY_INT(ep_amoebalive);
1086
1087   static int ep_amoeboid[] =
1088   {
1089     EL_AMOEBA_DEAD,
1090     EL_AMOEBA_WET,
1091     EL_AMOEBA_DRY,
1092     EL_AMOEBA_FULL,
1093     EL_BD_AMOEBA
1094   };
1095   static int ep_amoeboid_num = SIZEOF_ARRAY_INT(ep_amoeboid);
1096
1097   static int ep_schluessel[] =
1098   {
1099     EL_KEY_1,
1100     EL_KEY_2,
1101     EL_KEY_3,
1102     EL_KEY_4,
1103     EL_EM_KEY_1,
1104     EL_EM_KEY_2,
1105     EL_EM_KEY_3,
1106     EL_EM_KEY_4
1107   };
1108   static int ep_schluessel_num = SIZEOF_ARRAY_INT(ep_schluessel);
1109
1110   static int ep_pforte[] =
1111   {
1112     EL_GATE_1,
1113     EL_GATE_2,
1114     EL_GATE_3,
1115     EL_GATE_4,
1116     EL_GATE_1_GRAY,
1117     EL_GATE_2_GRAY,
1118     EL_GATE_3_GRAY,
1119     EL_GATE_4_GRAY,
1120     EL_EM_GATE_1,
1121     EL_EM_GATE_2,
1122     EL_EM_GATE_3,
1123     EL_EM_GATE_4,
1124     EL_EM_GATE_1_GRAY,
1125     EL_EM_GATE_2_GRAY,
1126     EL_EM_GATE_3_GRAY,
1127     EL_EM_GATE_4_GRAY,
1128     EL_SWITCHGATE_OPEN,
1129     EL_SWITCHGATE_OPENING,
1130     EL_SWITCHGATE_CLOSED,
1131     EL_SWITCHGATE_CLOSING,
1132     EL_TIMEGATE_OPEN,
1133     EL_TIMEGATE_OPENING,
1134     EL_TIMEGATE_CLOSED,
1135     EL_TIMEGATE_CLOSING,
1136     EL_TUBE_ANY,
1137     EL_TUBE_VERTICAL,
1138     EL_TUBE_HORIZONTAL,
1139     EL_TUBE_VERTICAL_LEFT,
1140     EL_TUBE_VERTICAL_RIGHT,
1141     EL_TUBE_HORIZONTAL_UP,
1142     EL_TUBE_HORIZONTAL_DOWN,
1143     EL_TUBE_LEFT_UP,
1144     EL_TUBE_LEFT_DOWN,
1145     EL_TUBE_RIGHT_UP,
1146     EL_TUBE_RIGHT_DOWN
1147   };
1148   static int ep_pforte_num = SIZEOF_ARRAY_INT(ep_pforte);
1149
1150   static int ep_solid[] =
1151   {
1152     EL_WALL,
1153     EL_EXPANDABLE_WALL,
1154     EL_EXPANDABLE_WALL_HORIZONTAL,
1155     EL_EXPANDABLE_WALL_VERTICAL,
1156     EL_EXPANDABLE_WALL_ANY,
1157     EL_BD_WALL,
1158     EL_WALL_CRUMBLED,
1159     EL_EXIT_CLOSED,
1160     EL_EXIT_OPENING,
1161     EL_EXIT_OPEN,
1162     EL_AMOEBA_DEAD,
1163     EL_AMOEBA_WET,
1164     EL_AMOEBA_DRY,
1165     EL_AMOEBA_FULL,
1166     EL_BD_AMOEBA,
1167     EL_QUICKSAND_EMPTY,
1168     EL_QUICKSAND_FULL,
1169     EL_QUICKSAND_FILLING,
1170     EL_QUICKSAND_EMPTYING,
1171     EL_MAGIC_WALL,
1172     EL_MAGIC_WALL_ACTIVE,
1173     EL_MAGIC_WALL_EMPTYING,
1174     EL_MAGIC_WALL_FILLING,
1175     EL_MAGIC_WALL_FULL,
1176     EL_MAGIC_WALL_DEAD,
1177     EL_BD_MAGIC_WALL,
1178     EL_BD_MAGIC_WALL_ACTIVE,
1179     EL_BD_MAGIC_WALL_EMPTYING,
1180     EL_BD_MAGIC_WALL_FULL,
1181     EL_BD_MAGIC_WALL_FILLING,
1182     EL_BD_MAGIC_WALL_DEAD,
1183     EL_GAME_OF_LIFE,
1184     EL_BIOMAZE,
1185     EL_SP_CHIP_SINGLE,
1186     EL_SP_CHIP_LEFT,
1187     EL_SP_CHIP_RIGHT,
1188     EL_SP_CHIP_TOP,
1189     EL_SP_CHIP_BOTTOM,
1190     EL_SP_TERMINAL,
1191     EL_SP_TERMINAL_ACTIVE,
1192     EL_SP_EXIT_CLOSED,
1193     EL_SP_EXIT_OPEN,
1194     EL_INVISIBLE_WALL,
1195     EL_INVISIBLE_WALL_ACTIVE,
1196     EL_SWITCHGATE_SWITCH_UP,
1197     EL_SWITCHGATE_SWITCH_DOWN,
1198     EL_TIMEGATE_SWITCH,
1199     EL_TIMEGATE_SWITCH_ACTIVE,
1200     EL_EMC_WALL_1,
1201     EL_EMC_WALL_2,
1202     EL_EMC_WALL_3,
1203     EL_EMC_WALL_4,
1204     EL_EMC_WALL_5,
1205     EL_EMC_WALL_6,
1206     EL_EMC_WALL_7,
1207     EL_EMC_WALL_8,
1208     EL_WALL_PEARL,
1209     EL_WALL_CRYSTAL,
1210
1211     /* the following elements are a direct copy of "indestructible" elements,
1212        except "EL_ACID", which is "indestructible", but not "solid"! */
1213 #if 0
1214     EL_ACID,
1215 #endif
1216     EL_STEELWALL,
1217     EL_ACID_POOL_TOPLEFT,
1218     EL_ACID_POOL_TOPRIGHT,
1219     EL_ACID_POOL_BOTTOMLEFT,
1220     EL_ACID_POOL_BOTTOM,
1221     EL_ACID_POOL_BOTTOMRIGHT,
1222     EL_SP_HARDWARE_GRAY,
1223     EL_SP_HARDWARE_GREEN,
1224     EL_SP_HARDWARE_BLUE,
1225     EL_SP_HARDWARE_RED,
1226     EL_SP_HARDWARE_YELLOW,
1227     EL_SP_HARDWARE_BASE_1,
1228     EL_SP_HARDWARE_BASE_2,
1229     EL_SP_HARDWARE_BASE_3,
1230     EL_SP_HARDWARE_BASE_4,
1231     EL_SP_HARDWARE_BASE_5,
1232     EL_SP_HARDWARE_BASE_6,
1233     EL_INVISIBLE_STEELWALL,
1234     EL_INVISIBLE_STEELWALL_ACTIVE,
1235     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
1236     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
1237     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
1238     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
1239     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
1240     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
1241     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
1242     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
1243     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
1244     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
1245     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
1246     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
1247     EL_LIGHT_SWITCH,
1248     EL_LIGHT_SWITCH_ACTIVE,
1249     EL_SIGN_EXCLAMATION,
1250     EL_SIGN_RADIOACTIVITY,
1251     EL_SIGN_STOP,
1252     EL_SIGN_WHEELCHAIR,
1253     EL_SIGN_PARKING,
1254     EL_SIGN_ONEWAY,
1255     EL_SIGN_HEART,
1256     EL_SIGN_TRIANGLE,
1257     EL_SIGN_ROUND,
1258     EL_SIGN_EXIT,
1259     EL_SIGN_YINYANG,
1260     EL_SIGN_OTHER,
1261     EL_STEELWALL_SLANTED,
1262     EL_EMC_STEELWALL_1,
1263     EL_EMC_STEELWALL_2,
1264     EL_EMC_STEELWALL_3,
1265     EL_EMC_STEELWALL_4,
1266     EL_CRYSTAL,
1267     EL_GATE_1,
1268     EL_GATE_2,
1269     EL_GATE_3,
1270     EL_GATE_4,
1271     EL_GATE_1_GRAY,
1272     EL_GATE_2_GRAY,
1273     EL_GATE_3_GRAY,
1274     EL_GATE_4_GRAY,
1275     EL_EM_GATE_1,
1276     EL_EM_GATE_2,
1277     EL_EM_GATE_3,
1278     EL_EM_GATE_4,
1279     EL_EM_GATE_1_GRAY,
1280     EL_EM_GATE_2_GRAY,
1281     EL_EM_GATE_3_GRAY,
1282     EL_EM_GATE_4_GRAY,
1283     EL_SWITCHGATE_OPEN,
1284     EL_SWITCHGATE_OPENING,
1285     EL_SWITCHGATE_CLOSED,
1286     EL_SWITCHGATE_CLOSING,
1287     EL_TIMEGATE_OPEN,
1288     EL_TIMEGATE_OPENING,
1289     EL_TIMEGATE_CLOSED,
1290     EL_TIMEGATE_CLOSING,
1291     EL_TUBE_ANY,
1292     EL_TUBE_VERTICAL,
1293     EL_TUBE_HORIZONTAL,
1294     EL_TUBE_VERTICAL_LEFT,
1295     EL_TUBE_VERTICAL_RIGHT,
1296     EL_TUBE_HORIZONTAL_UP,
1297     EL_TUBE_HORIZONTAL_DOWN,
1298     EL_TUBE_LEFT_UP,
1299     EL_TUBE_LEFT_DOWN,
1300     EL_TUBE_RIGHT_UP,
1301     EL_TUBE_RIGHT_DOWN
1302   };
1303   static int ep_solid_num = SIZEOF_ARRAY_INT(ep_solid);
1304
1305   static int ep_indestructible[] =
1306   {
1307     EL_STEELWALL,
1308     EL_ACID,
1309     EL_ACID_POOL_TOPLEFT,
1310     EL_ACID_POOL_TOPRIGHT,
1311     EL_ACID_POOL_BOTTOMLEFT,
1312     EL_ACID_POOL_BOTTOM,
1313     EL_ACID_POOL_BOTTOMRIGHT,
1314     EL_SP_HARDWARE_GRAY,
1315     EL_SP_HARDWARE_GREEN,
1316     EL_SP_HARDWARE_BLUE,
1317     EL_SP_HARDWARE_RED,
1318     EL_SP_HARDWARE_YELLOW,
1319     EL_SP_HARDWARE_BASE_1,
1320     EL_SP_HARDWARE_BASE_2,
1321     EL_SP_HARDWARE_BASE_3,
1322     EL_SP_HARDWARE_BASE_4,
1323     EL_SP_HARDWARE_BASE_5,
1324     EL_SP_HARDWARE_BASE_6,
1325     EL_INVISIBLE_STEELWALL,
1326     EL_INVISIBLE_STEELWALL_ACTIVE,
1327     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
1328     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
1329     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
1330     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
1331     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
1332     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
1333     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
1334     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
1335     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
1336     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
1337     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
1338     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
1339     EL_LIGHT_SWITCH,
1340     EL_LIGHT_SWITCH_ACTIVE,
1341     EL_SIGN_EXCLAMATION,
1342     EL_SIGN_RADIOACTIVITY,
1343     EL_SIGN_STOP,
1344     EL_SIGN_WHEELCHAIR,
1345     EL_SIGN_PARKING,
1346     EL_SIGN_ONEWAY,
1347     EL_SIGN_HEART,
1348     EL_SIGN_TRIANGLE,
1349     EL_SIGN_ROUND,
1350     EL_SIGN_EXIT,
1351     EL_SIGN_YINYANG,
1352     EL_SIGN_OTHER,
1353     EL_STEELWALL_SLANTED,
1354     EL_EMC_STEELWALL_1,
1355     EL_EMC_STEELWALL_2,
1356     EL_EMC_STEELWALL_3,
1357     EL_EMC_STEELWALL_4,
1358     EL_CRYSTAL,
1359     EL_GATE_1,
1360     EL_GATE_2,
1361     EL_GATE_3,
1362     EL_GATE_4,
1363     EL_GATE_1_GRAY,
1364     EL_GATE_2_GRAY,
1365     EL_GATE_3_GRAY,
1366     EL_GATE_4_GRAY,
1367     EL_EM_GATE_1,
1368     EL_EM_GATE_2,
1369     EL_EM_GATE_3,
1370     EL_EM_GATE_4,
1371     EL_EM_GATE_1_GRAY,
1372     EL_EM_GATE_2_GRAY,
1373     EL_EM_GATE_3_GRAY,
1374     EL_EM_GATE_4_GRAY,
1375     EL_SWITCHGATE_OPEN,
1376     EL_SWITCHGATE_OPENING,
1377     EL_SWITCHGATE_CLOSED,
1378     EL_SWITCHGATE_CLOSING,
1379     EL_TIMEGATE_OPEN,
1380     EL_TIMEGATE_OPENING,
1381     EL_TIMEGATE_CLOSED,
1382     EL_TIMEGATE_CLOSING,
1383     EL_TUBE_ANY,
1384     EL_TUBE_VERTICAL,
1385     EL_TUBE_HORIZONTAL,
1386     EL_TUBE_VERTICAL_LEFT,
1387     EL_TUBE_VERTICAL_RIGHT,
1388     EL_TUBE_HORIZONTAL_UP,
1389     EL_TUBE_HORIZONTAL_DOWN,
1390     EL_TUBE_LEFT_UP,
1391     EL_TUBE_LEFT_DOWN,
1392     EL_TUBE_RIGHT_UP,
1393     EL_TUBE_RIGHT_DOWN
1394   };
1395   static int ep_indestructible_num = SIZEOF_ARRAY_INT(ep_indestructible);
1396
1397   static int ep_slippery[] =
1398   {
1399     EL_WALL_CRUMBLED,
1400     EL_BD_WALL,
1401     EL_ROCK,
1402     EL_BD_ROCK,
1403     EL_EMERALD,
1404     EL_BD_DIAMOND,
1405     EL_EMERALD_YELLOW,
1406     EL_EMERALD_RED,
1407     EL_EMERALD_PURPLE,
1408     EL_DIAMOND,
1409     EL_BOMB,
1410     EL_NUT,
1411     EL_ROBOT_WHEEL_ACTIVE,
1412     EL_ROBOT_WHEEL,
1413     EL_TIME_ORB_FULL,
1414     EL_TIME_ORB_EMPTY,
1415     EL_LAMP_ACTIVE,
1416     EL_LAMP,
1417     EL_ACID_POOL_TOPLEFT,
1418     EL_ACID_POOL_TOPRIGHT,
1419     EL_SATELLITE,
1420     EL_SP_ZONK,
1421     EL_SP_INFOTRON,
1422     EL_SP_CHIP_SINGLE,
1423     EL_SP_CHIP_LEFT,
1424     EL_SP_CHIP_RIGHT,
1425     EL_SP_CHIP_TOP,
1426     EL_SP_CHIP_BOTTOM,
1427     EL_SPEED_PILL,
1428     EL_STEELWALL_SLANTED,
1429     EL_PEARL,
1430     EL_CRYSTAL
1431   };
1432   static int ep_slippery_num = SIZEOF_ARRAY_INT(ep_slippery);
1433
1434   static int ep_enemy[] =
1435   {
1436     EL_BUG,
1437     EL_SPACESHIP,
1438     EL_BD_BUTTERFLY,
1439     EL_BD_FIREFLY,
1440     EL_YAMYAM,
1441     EL_DARK_YAMYAM,
1442     EL_ROBOT,
1443     EL_PACMAN,
1444     EL_SP_SNIKSNAK,
1445     EL_SP_ELECTRON
1446   };
1447   static int ep_enemy_num = SIZEOF_ARRAY_INT(ep_enemy);
1448
1449   static int ep_mauer[] =
1450   {
1451     EL_STEELWALL,
1452     EL_GATE_1,
1453     EL_GATE_2,
1454     EL_GATE_3,
1455     EL_GATE_4,
1456     EL_GATE_1_GRAY,
1457     EL_GATE_2_GRAY,
1458     EL_GATE_3_GRAY,
1459     EL_GATE_4_GRAY,
1460     EL_EM_GATE_1,
1461     EL_EM_GATE_2,
1462     EL_EM_GATE_3,
1463     EL_EM_GATE_4,
1464     EL_EM_GATE_1_GRAY,
1465     EL_EM_GATE_2_GRAY,
1466     EL_EM_GATE_3_GRAY,
1467     EL_EM_GATE_4_GRAY,
1468     EL_EXIT_CLOSED,
1469     EL_EXIT_OPENING,
1470     EL_EXIT_OPEN,
1471     EL_WALL,
1472     EL_WALL_CRUMBLED,
1473     EL_EXPANDABLE_WALL,
1474     EL_EXPANDABLE_WALL_HORIZONTAL,
1475     EL_EXPANDABLE_WALL_VERTICAL,
1476     EL_EXPANDABLE_WALL_ANY,
1477     EL_EXPANDABLE_WALL_GROWING,
1478     EL_BD_WALL,
1479     EL_SP_CHIP_SINGLE,
1480     EL_SP_CHIP_LEFT,
1481     EL_SP_CHIP_RIGHT,
1482     EL_SP_CHIP_TOP,
1483     EL_SP_CHIP_BOTTOM,
1484     EL_SP_HARDWARE_GRAY,
1485     EL_SP_HARDWARE_GREEN,
1486     EL_SP_HARDWARE_BLUE,
1487     EL_SP_HARDWARE_RED,
1488     EL_SP_HARDWARE_YELLOW,
1489     EL_SP_HARDWARE_BASE_1,
1490     EL_SP_HARDWARE_BASE_2,
1491     EL_SP_HARDWARE_BASE_3,
1492     EL_SP_HARDWARE_BASE_4,
1493     EL_SP_HARDWARE_BASE_5,
1494     EL_SP_HARDWARE_BASE_6,
1495     EL_SP_TERMINAL,
1496     EL_SP_TERMINAL_ACTIVE,
1497     EL_SP_EXIT_CLOSED,
1498     EL_SP_EXIT_OPEN,
1499     EL_INVISIBLE_STEELWALL,
1500     EL_INVISIBLE_STEELWALL_ACTIVE,
1501     EL_INVISIBLE_WALL,
1502     EL_INVISIBLE_WALL_ACTIVE,
1503     EL_STEELWALL_SLANTED,
1504     EL_EMC_STEELWALL_1,
1505     EL_EMC_STEELWALL_2,
1506     EL_EMC_STEELWALL_3,
1507     EL_EMC_STEELWALL_4,
1508     EL_EMC_WALL_1,
1509     EL_EMC_WALL_2,
1510     EL_EMC_WALL_3,
1511     EL_EMC_WALL_4,
1512     EL_EMC_WALL_5,
1513     EL_EMC_WALL_6,
1514     EL_EMC_WALL_7,
1515     EL_EMC_WALL_8
1516   };
1517   static int ep_mauer_num = SIZEOF_ARRAY_INT(ep_mauer);
1518
1519   static int ep_can_fall[] =
1520   {
1521     EL_ROCK,
1522     EL_BD_ROCK,
1523     EL_EMERALD,
1524     EL_BD_DIAMOND,
1525     EL_EMERALD_YELLOW,
1526     EL_EMERALD_RED,
1527     EL_EMERALD_PURPLE,
1528     EL_DIAMOND,
1529     EL_BOMB,
1530     EL_NUT,
1531     EL_AMOEBA_DROP,
1532     EL_QUICKSAND_FULL,
1533     EL_MAGIC_WALL_FULL,
1534     EL_BD_MAGIC_WALL_FULL,
1535     EL_TIME_ORB_FULL,
1536     EL_TIME_ORB_EMPTY,
1537     EL_SP_ZONK,
1538     EL_SP_INFOTRON,
1539     EL_SP_DISK_ORANGE,
1540     EL_PEARL,
1541     EL_CRYSTAL,
1542     EL_SPRING,
1543     EL_DX_SUPABOMB
1544   };
1545   static int ep_can_fall_num = SIZEOF_ARRAY_INT(ep_can_fall);
1546
1547   static int ep_can_smash[] =
1548   {
1549     EL_ROCK,
1550     EL_BD_ROCK,
1551     EL_EMERALD,
1552     EL_BD_DIAMOND,
1553     EL_EMERALD_YELLOW,
1554     EL_EMERALD_RED,
1555     EL_EMERALD_PURPLE,
1556     EL_DIAMOND,
1557     EL_BOMB,
1558     EL_NUT,
1559     EL_AMOEBA_DROP,
1560     EL_TIME_ORB_FULL,
1561     EL_TIME_ORB_EMPTY,
1562     EL_SP_ZONK,
1563     EL_SP_INFOTRON,
1564     EL_SP_DISK_ORANGE,
1565     EL_PEARL,
1566     EL_CRYSTAL,
1567     EL_SPRING,
1568     EL_DX_SUPABOMB
1569   };
1570   static int ep_can_smash_num = SIZEOF_ARRAY_INT(ep_can_smash);
1571
1572   static int ep_can_change[] =
1573   {
1574     EL_ROCK,
1575     EL_BD_ROCK,
1576     EL_EMERALD,
1577     EL_BD_DIAMOND,
1578     EL_EMERALD_YELLOW,
1579     EL_EMERALD_RED,
1580     EL_EMERALD_PURPLE,
1581     EL_DIAMOND
1582   };
1583   static int ep_can_change_num = SIZEOF_ARRAY_INT(ep_can_change);
1584
1585   static int ep_can_move[] =
1586   {
1587     EL_BUG,
1588     EL_SPACESHIP,
1589     EL_BD_BUTTERFLY,
1590     EL_BD_FIREFLY,
1591     EL_YAMYAM,
1592     EL_DARK_YAMYAM,
1593     EL_ROBOT,
1594     EL_PACMAN,
1595     EL_MOLE,
1596     EL_PENGUIN,
1597     EL_PIG,
1598     EL_DRAGON,
1599     EL_SATELLITE,
1600     EL_SP_SNIKSNAK,
1601     EL_SP_ELECTRON,
1602     EL_BALLOON,
1603     EL_SPRING
1604   };
1605   static int ep_can_move_num = SIZEOF_ARRAY_INT(ep_can_move);
1606
1607   static int ep_could_move[] =
1608   {
1609     EL_BUG_RIGHT,
1610     EL_BUG_UP,
1611     EL_BUG_LEFT,
1612     EL_BUG_DOWN,
1613     EL_SPACESHIP_RIGHT,
1614     EL_SPACESHIP_UP,
1615     EL_SPACESHIP_LEFT,
1616     EL_SPACESHIP_DOWN,
1617     EL_BD_BUTTERFLY_RIGHT,
1618     EL_BD_BUTTERFLY_UP,
1619     EL_BD_BUTTERFLY_LEFT,
1620     EL_BD_BUTTERFLY_DOWN,
1621     EL_BD_FIREFLY_RIGHT,
1622     EL_BD_FIREFLY_UP,
1623     EL_BD_FIREFLY_LEFT,
1624     EL_BD_FIREFLY_DOWN,
1625     EL_PACMAN_RIGHT,
1626     EL_PACMAN_UP,
1627     EL_PACMAN_LEFT,
1628     EL_PACMAN_DOWN
1629   };
1630   static int ep_could_move_num = SIZEOF_ARRAY_INT(ep_could_move);
1631
1632   static int ep_dont_touch[] =
1633   {
1634     EL_BUG,
1635     EL_SPACESHIP,
1636     EL_BD_BUTTERFLY,
1637     EL_BD_FIREFLY
1638   };
1639   static int ep_dont_touch_num = SIZEOF_ARRAY_INT(ep_dont_touch);
1640
1641   static int ep_dont_go_to[] =
1642   {
1643     EL_BUG,
1644     EL_SPACESHIP,
1645     EL_BD_BUTTERFLY,
1646     EL_BD_FIREFLY,
1647     EL_YAMYAM,
1648     EL_DARK_YAMYAM,
1649     EL_ROBOT,
1650     EL_PACMAN,
1651     EL_AMOEBA_DROP,
1652     EL_ACID,
1653     EL_SP_SNIKSNAK,
1654     EL_SP_ELECTRON,
1655     EL_SP_BUGGY_BASE_ACTIVE,
1656     EL_TRAP_ACTIVE,
1657     EL_LANDMINE
1658   };
1659   static int ep_dont_go_to_num = SIZEOF_ARRAY_INT(ep_dont_go_to);
1660
1661   static int ep_mampf2[] =
1662   {
1663     EL_SAND,
1664     EL_BUG,
1665     EL_SPACESHIP,
1666     EL_BD_BUTTERFLY,
1667     EL_BD_FIREFLY,
1668     EL_YAMYAM,
1669     EL_ROBOT,
1670     EL_PACMAN,
1671     EL_AMOEBA_DROP,
1672     EL_AMOEBA_DEAD,
1673     EL_AMOEBA_WET,
1674     EL_AMOEBA_DRY,
1675     EL_AMOEBA_FULL,
1676     EL_BD_AMOEBA,
1677     EL_EMERALD,
1678     EL_BD_DIAMOND,
1679     EL_EMERALD_YELLOW,
1680     EL_EMERALD_RED,
1681     EL_EMERALD_PURPLE,
1682     EL_DIAMOND,
1683     EL_PEARL,
1684     EL_CRYSTAL
1685   };
1686   static int ep_mampf2_num = SIZEOF_ARRAY_INT(ep_mampf2);
1687
1688   static int ep_bd_element[] =
1689   {
1690     EL_EMPTY,
1691     EL_SAND,
1692     EL_WALL_CRUMBLED,
1693     EL_BD_WALL,
1694     EL_ROCK,
1695     EL_BD_ROCK,
1696     EL_BD_DIAMOND,
1697     EL_BD_MAGIC_WALL,
1698     EL_EXIT_CLOSED,
1699     EL_EXIT_OPEN,
1700     EL_STEELWALL,
1701     EL_PLAYER_1,
1702     EL_BD_FIREFLY,
1703     EL_BD_FIREFLY_1,
1704     EL_BD_FIREFLY_2,
1705     EL_BD_FIREFLY_3,
1706     EL_BD_FIREFLY_4,
1707     EL_BD_BUTTERFLY,
1708     EL_BD_BUTTERFLY_1,
1709     EL_BD_BUTTERFLY_2,
1710     EL_BD_BUTTERFLY_3,
1711     EL_BD_BUTTERFLY_4,
1712     EL_BD_AMOEBA,
1713     EL_CHAR_QUESTION
1714   };
1715   static int ep_bd_element_num = SIZEOF_ARRAY_INT(ep_bd_element);
1716
1717   static int ep_sb_element[] =
1718   {
1719     EL_EMPTY,
1720     EL_STEELWALL,
1721     EL_SOKOBAN_OBJECT,
1722     EL_SOKOBAN_FIELD_EMPTY,
1723     EL_SOKOBAN_FIELD_FULL,
1724     EL_PLAYER_1,
1725     EL_INVISIBLE_STEELWALL
1726   };
1727   static int ep_sb_element_num = SIZEOF_ARRAY_INT(ep_sb_element);
1728
1729   static int ep_gem[] =
1730   {
1731     EL_EMERALD,
1732     EL_BD_DIAMOND,
1733     EL_EMERALD_YELLOW,
1734     EL_EMERALD_RED,
1735     EL_EMERALD_PURPLE,
1736     EL_DIAMOND
1737   };
1738   static int ep_gem_num = SIZEOF_ARRAY_INT(ep_gem);
1739
1740   static int ep_inactive[] =
1741   {
1742     EL_EMPTY,
1743     EL_SAND,
1744     EL_WALL,
1745     EL_BD_WALL,
1746     EL_WALL_CRUMBLED,
1747     EL_STEELWALL,
1748     EL_AMOEBA_DEAD,
1749     EL_QUICKSAND_EMPTY,
1750     EL_STONEBLOCK,
1751     EL_ROBOT_WHEEL,
1752     EL_KEY_1,
1753     EL_KEY_2,
1754     EL_KEY_3,
1755     EL_KEY_4,
1756     EL_EM_KEY_1,
1757     EL_EM_KEY_2,
1758     EL_EM_KEY_3,
1759     EL_EM_KEY_4,
1760     EL_GATE_1,
1761     EL_GATE_2,
1762     EL_GATE_3,
1763     EL_GATE_4,
1764     EL_GATE_1_GRAY,
1765     EL_GATE_2_GRAY,
1766     EL_GATE_3_GRAY,
1767     EL_GATE_4_GRAY,
1768     EL_EM_GATE_1,
1769     EL_EM_GATE_2,
1770     EL_EM_GATE_3,
1771     EL_EM_GATE_4,
1772     EL_EM_GATE_1_GRAY,
1773     EL_EM_GATE_2_GRAY,
1774     EL_EM_GATE_3_GRAY,
1775     EL_EM_GATE_4_GRAY,
1776     EL_DYNAMITE,
1777     EL_INVISIBLE_STEELWALL,
1778     EL_INVISIBLE_WALL,
1779     EL_INVISIBLE_SAND,
1780     EL_LAMP,
1781     EL_LAMP_ACTIVE,
1782     EL_WALL_EMERALD,
1783     EL_WALL_DIAMOND,
1784     EL_WALL_BD_DIAMOND,
1785     EL_WALL_EMERALD_YELLOW,
1786     EL_DYNABOMB_INCREASE_NUMBER,
1787     EL_DYNABOMB_INCREASE_SIZE,
1788     EL_DYNABOMB_INCREASE_POWER,
1789     EL_SOKOBAN_OBJECT,
1790     EL_SOKOBAN_FIELD_EMPTY,
1791     EL_SOKOBAN_FIELD_FULL,
1792     EL_WALL_EMERALD_RED,
1793     EL_WALL_EMERALD_PURPLE,
1794     EL_ACID_POOL_TOPLEFT,
1795     EL_ACID_POOL_TOPRIGHT,
1796     EL_ACID_POOL_BOTTOMLEFT,
1797     EL_ACID_POOL_BOTTOM,
1798     EL_ACID_POOL_BOTTOMRIGHT,
1799     EL_MAGIC_WALL,
1800     EL_MAGIC_WALL_DEAD,
1801     EL_BD_MAGIC_WALL,
1802     EL_BD_MAGIC_WALL_DEAD,
1803     EL_AMOEBA_TO_DIAMOND,
1804     EL_BLOCKED,
1805     EL_SP_EMPTY,
1806     EL_SP_BASE,
1807     EL_SP_PORT_RIGHT,
1808     EL_SP_PORT_DOWN,
1809     EL_SP_PORT_LEFT,
1810     EL_SP_PORT_UP,
1811     EL_SP_GRAVITY_PORT_RIGHT,
1812     EL_SP_GRAVITY_PORT_DOWN,
1813     EL_SP_GRAVITY_PORT_LEFT,
1814     EL_SP_GRAVITY_PORT_UP,
1815     EL_SP_PORT_HORIZONTAL,
1816     EL_SP_PORT_VERTICAL,
1817     EL_SP_PORT_ANY,
1818     EL_SP_DISK_RED,
1819     EL_SP_DISK_YELLOW,
1820     EL_SP_CHIP_SINGLE,
1821     EL_SP_CHIP_LEFT,
1822     EL_SP_CHIP_RIGHT,
1823     EL_SP_CHIP_TOP,
1824     EL_SP_CHIP_BOTTOM,
1825     EL_SP_HARDWARE_GRAY,
1826     EL_SP_HARDWARE_GREEN,
1827     EL_SP_HARDWARE_BLUE,
1828     EL_SP_HARDWARE_RED,
1829     EL_SP_HARDWARE_YELLOW,
1830     EL_SP_HARDWARE_BASE_1,
1831     EL_SP_HARDWARE_BASE_2,
1832     EL_SP_HARDWARE_BASE_3,
1833     EL_SP_HARDWARE_BASE_4,
1834     EL_SP_HARDWARE_BASE_5,
1835     EL_SP_HARDWARE_BASE_6,
1836     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
1837     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
1838     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
1839     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
1840     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
1841     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
1842     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
1843     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
1844     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
1845     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
1846     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
1847     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
1848     EL_SIGN_EXCLAMATION,
1849     EL_SIGN_RADIOACTIVITY,
1850     EL_SIGN_STOP,
1851     EL_SIGN_WHEELCHAIR,
1852     EL_SIGN_PARKING,
1853     EL_SIGN_ONEWAY,
1854     EL_SIGN_HEART,
1855     EL_SIGN_TRIANGLE,
1856     EL_SIGN_ROUND,
1857     EL_SIGN_EXIT,
1858     EL_SIGN_YINYANG,
1859     EL_SIGN_OTHER,
1860     EL_STEELWALL_SLANTED,
1861     EL_EMC_STEELWALL_1,
1862     EL_EMC_STEELWALL_2,
1863     EL_EMC_STEELWALL_3,
1864     EL_EMC_STEELWALL_4,
1865     EL_EMC_WALL_1,
1866     EL_EMC_WALL_2,
1867     EL_EMC_WALL_3,
1868     EL_EMC_WALL_4,
1869     EL_EMC_WALL_5,
1870     EL_EMC_WALL_6,
1871     EL_EMC_WALL_7,
1872     EL_EMC_WALL_8
1873   };
1874   static int ep_inactive_num = SIZEOF_ARRAY_INT(ep_inactive);
1875
1876   static int ep_explosive[] =
1877   {
1878     EL_BOMB,
1879     EL_DYNAMITE_ACTIVE,
1880     EL_DYNAMITE,
1881     EL_DYNABOMB_PLAYER_1_ACTIVE,
1882     EL_DYNABOMB_PLAYER_2_ACTIVE,
1883     EL_DYNABOMB_PLAYER_3_ACTIVE,
1884     EL_DYNABOMB_PLAYER_4_ACTIVE,
1885     EL_DYNABOMB_INCREASE_NUMBER,
1886     EL_DYNABOMB_INCREASE_SIZE,
1887     EL_DYNABOMB_INCREASE_POWER,
1888     EL_SP_DISK_RED_ACTIVE,
1889     EL_BUG,
1890     EL_MOLE,
1891     EL_PENGUIN,
1892     EL_PIG,
1893     EL_DRAGON,
1894     EL_SATELLITE,
1895     EL_SP_DISK_RED,
1896     EL_SP_DISK_ORANGE,
1897     EL_SP_DISK_YELLOW,
1898     EL_SP_SNIKSNAK,
1899     EL_SP_ELECTRON,
1900     EL_DX_SUPABOMB
1901   };
1902   static int ep_explosive_num = SIZEOF_ARRAY_INT(ep_explosive);
1903
1904   static int ep_mampf3[] =
1905   {
1906     EL_EMERALD,
1907     EL_BD_DIAMOND,
1908     EL_EMERALD_YELLOW,
1909     EL_EMERALD_RED,
1910     EL_EMERALD_PURPLE,
1911     EL_DIAMOND,
1912     EL_PEARL,
1913     EL_CRYSTAL
1914   };
1915   static int ep_mampf3_num = SIZEOF_ARRAY_INT(ep_mampf3);
1916
1917   static int ep_pushable[] =
1918   {
1919     EL_ROCK,
1920     EL_BD_ROCK,
1921     EL_BOMB,
1922     EL_NUT,
1923     EL_TIME_ORB_EMPTY,
1924     EL_SOKOBAN_FIELD_FULL,
1925     EL_SOKOBAN_OBJECT,
1926     EL_SATELLITE,
1927     EL_SP_ZONK,
1928     EL_SP_DISK_ORANGE,
1929     EL_SP_DISK_YELLOW,
1930     EL_BALLOON,
1931     EL_SPRING,
1932     EL_DX_SUPABOMB
1933   };
1934   static int ep_pushable_num = SIZEOF_ARRAY_INT(ep_pushable);
1935
1936   static int ep_player[] =
1937   {
1938     EL_PLAYER_1,
1939     EL_PLAYER_2,
1940     EL_PLAYER_3,
1941     EL_PLAYER_4
1942   };
1943   static int ep_player_num = SIZEOF_ARRAY_INT(ep_player);
1944
1945   static int ep_has_content[] =
1946   {
1947     EL_YAMYAM,
1948     EL_AMOEBA_WET,
1949     EL_AMOEBA_DRY,
1950     EL_AMOEBA_FULL,
1951     EL_BD_AMOEBA
1952   };
1953   static int ep_has_content_num = SIZEOF_ARRAY_INT(ep_has_content);
1954
1955   static int ep_eatable[] =
1956   {
1957     EL_SAND,
1958     EL_SP_BASE,
1959     EL_SP_BUGGY_BASE,
1960     EL_SP_BUGGY_BASE_ACTIVATING,
1961     EL_TRAP,
1962     EL_INVISIBLE_SAND,
1963     EL_INVISIBLE_SAND_ACTIVE
1964   };
1965   static int ep_eatable_num = SIZEOF_ARRAY_INT(ep_eatable);
1966
1967   static int ep_sp_element[] =
1968   {
1969     EL_SP_EMPTY,
1970     EL_SP_ZONK,
1971     EL_SP_BASE,
1972     EL_SP_MURPHY,
1973     EL_SP_INFOTRON,
1974     EL_SP_CHIP_SINGLE,
1975     EL_SP_HARDWARE_GRAY,
1976     EL_SP_EXIT_CLOSED,
1977     EL_SP_EXIT_OPEN,
1978     EL_SP_DISK_ORANGE,
1979     EL_SP_PORT_RIGHT,
1980     EL_SP_PORT_DOWN,
1981     EL_SP_PORT_LEFT,
1982     EL_SP_PORT_UP,
1983     EL_SP_GRAVITY_PORT_RIGHT,
1984     EL_SP_GRAVITY_PORT_DOWN,
1985     EL_SP_GRAVITY_PORT_LEFT,
1986     EL_SP_GRAVITY_PORT_UP,
1987     EL_SP_SNIKSNAK,
1988     EL_SP_DISK_YELLOW,
1989     EL_SP_TERMINAL,
1990     EL_SP_DISK_RED,
1991     EL_SP_PORT_VERTICAL,
1992     EL_SP_PORT_HORIZONTAL,
1993     EL_SP_PORT_ANY,
1994     EL_SP_ELECTRON,
1995     EL_SP_BUGGY_BASE,
1996     EL_SP_CHIP_LEFT,
1997     EL_SP_CHIP_RIGHT,
1998     EL_SP_HARDWARE_BASE_1,
1999     EL_SP_HARDWARE_GREEN,
2000     EL_SP_HARDWARE_BLUE,
2001     EL_SP_HARDWARE_RED,
2002     EL_SP_HARDWARE_YELLOW,
2003     EL_SP_HARDWARE_BASE_2,
2004     EL_SP_HARDWARE_BASE_3,
2005     EL_SP_HARDWARE_BASE_4,
2006     EL_SP_HARDWARE_BASE_5,
2007     EL_SP_HARDWARE_BASE_6,
2008     EL_SP_CHIP_TOP,
2009     EL_SP_CHIP_BOTTOM,
2010     /* additional elements that appeared in newer Supaplex levels */
2011     EL_INVISIBLE_WALL,
2012     /* more than one murphy in a level results in an inactive clone */
2013     EL_SP_MURPHY_CLONE
2014   };
2015   static int ep_sp_element_num = SIZEOF_ARRAY_INT(ep_sp_element);
2016
2017   static int ep_quick_gate[] =
2018   {
2019     EL_EM_GATE_1,
2020     EL_EM_GATE_2,
2021     EL_EM_GATE_3,
2022     EL_EM_GATE_4,
2023     EL_EM_GATE_1_GRAY,
2024     EL_EM_GATE_2_GRAY,
2025     EL_EM_GATE_3_GRAY,
2026     EL_EM_GATE_4_GRAY,
2027     EL_SP_PORT_LEFT,
2028     EL_SP_PORT_RIGHT,
2029     EL_SP_PORT_UP,
2030     EL_SP_PORT_DOWN,
2031     EL_SP_GRAVITY_PORT_LEFT,
2032     EL_SP_GRAVITY_PORT_RIGHT,
2033     EL_SP_GRAVITY_PORT_UP,
2034     EL_SP_GRAVITY_PORT_DOWN,
2035     EL_SP_PORT_HORIZONTAL,
2036     EL_SP_PORT_VERTICAL,
2037     EL_SP_PORT_ANY,
2038     EL_SWITCHGATE_OPEN,
2039     EL_TIMEGATE_OPEN
2040   };
2041   static int ep_quick_gate_num = SIZEOF_ARRAY_INT(ep_quick_gate);
2042
2043   static int ep_over_player[] =
2044   {
2045     EL_SP_PORT_LEFT,
2046     EL_SP_PORT_RIGHT,
2047     EL_SP_PORT_UP,
2048     EL_SP_PORT_DOWN,
2049     EL_SP_GRAVITY_PORT_LEFT,
2050     EL_SP_GRAVITY_PORT_RIGHT,
2051     EL_SP_GRAVITY_PORT_UP,
2052     EL_SP_GRAVITY_PORT_DOWN,
2053     EL_SP_PORT_HORIZONTAL,
2054     EL_SP_PORT_VERTICAL,
2055     EL_SP_PORT_ANY,
2056     EL_TUBE_ANY,
2057     EL_TUBE_VERTICAL,
2058     EL_TUBE_HORIZONTAL,
2059     EL_TUBE_VERTICAL_LEFT,
2060     EL_TUBE_VERTICAL_RIGHT,
2061     EL_TUBE_HORIZONTAL_UP,
2062     EL_TUBE_HORIZONTAL_DOWN,
2063     EL_TUBE_LEFT_UP,
2064     EL_TUBE_LEFT_DOWN,
2065     EL_TUBE_RIGHT_UP,
2066     EL_TUBE_RIGHT_DOWN
2067   };
2068   static int ep_over_player_num = SIZEOF_ARRAY_INT(ep_over_player);
2069
2070   static int ep_active_bomb[] =
2071   {
2072     EL_DYNAMITE_ACTIVE,
2073     EL_DYNABOMB_PLAYER_1_ACTIVE,
2074     EL_DYNABOMB_PLAYER_2_ACTIVE,
2075     EL_DYNABOMB_PLAYER_3_ACTIVE,
2076     EL_DYNABOMB_PLAYER_4_ACTIVE,
2077     EL_SP_DISK_RED_ACTIVE
2078   };
2079   static int ep_active_bomb_num = SIZEOF_ARRAY_INT(ep_active_bomb);
2080
2081   static int ep_belt[] =
2082   {
2083     EL_CONVEYOR_BELT_1_LEFT,
2084     EL_CONVEYOR_BELT_1_MIDDLE,
2085     EL_CONVEYOR_BELT_1_RIGHT,
2086     EL_CONVEYOR_BELT_2_LEFT,
2087     EL_CONVEYOR_BELT_2_MIDDLE,
2088     EL_CONVEYOR_BELT_2_RIGHT,
2089     EL_CONVEYOR_BELT_3_LEFT,
2090     EL_CONVEYOR_BELT_3_MIDDLE,
2091     EL_CONVEYOR_BELT_3_RIGHT,
2092     EL_CONVEYOR_BELT_4_LEFT,
2093     EL_CONVEYOR_BELT_4_MIDDLE,
2094     EL_CONVEYOR_BELT_4_RIGHT,
2095   };
2096   static int ep_belt_num = SIZEOF_ARRAY_INT(ep_belt);
2097
2098   static int ep_belt_active[] =
2099   {
2100     EL_CONVEYOR_BELT_1_LEFT_ACTIVE,
2101     EL_CONVEYOR_BELT_1_MIDDLE_ACTIVE,
2102     EL_CONVEYOR_BELT_1_RIGHT_ACTIVE,
2103     EL_CONVEYOR_BELT_2_LEFT_ACTIVE,
2104     EL_CONVEYOR_BELT_2_MIDDLE_ACTIVE,
2105     EL_CONVEYOR_BELT_2_RIGHT_ACTIVE,
2106     EL_CONVEYOR_BELT_3_LEFT_ACTIVE,
2107     EL_CONVEYOR_BELT_3_MIDDLE_ACTIVE,
2108     EL_CONVEYOR_BELT_3_RIGHT_ACTIVE,
2109     EL_CONVEYOR_BELT_4_LEFT_ACTIVE,
2110     EL_CONVEYOR_BELT_4_MIDDLE_ACTIVE,
2111     EL_CONVEYOR_BELT_4_RIGHT_ACTIVE,
2112   };
2113   static int ep_belt_active_num = SIZEOF_ARRAY_INT(ep_belt_active);
2114
2115   static int ep_belt_switch[] =
2116   {
2117     EL_CONVEYOR_BELT_1_SWITCH_LEFT,
2118     EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
2119     EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
2120     EL_CONVEYOR_BELT_2_SWITCH_LEFT,
2121     EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
2122     EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
2123     EL_CONVEYOR_BELT_3_SWITCH_LEFT,
2124     EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
2125     EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
2126     EL_CONVEYOR_BELT_4_SWITCH_LEFT,
2127     EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
2128     EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
2129   };
2130   static int ep_belt_switch_num = SIZEOF_ARRAY_INT(ep_belt_switch);
2131
2132   static int ep_tube[] =
2133   {
2134     EL_TUBE_ANY,
2135     EL_TUBE_VERTICAL,
2136     EL_TUBE_HORIZONTAL,
2137     EL_TUBE_VERTICAL_LEFT,
2138     EL_TUBE_VERTICAL_RIGHT,
2139     EL_TUBE_HORIZONTAL_UP,
2140     EL_TUBE_HORIZONTAL_DOWN,
2141     EL_TUBE_LEFT_UP,
2142     EL_TUBE_LEFT_DOWN,
2143     EL_TUBE_RIGHT_UP,
2144     EL_TUBE_RIGHT_DOWN
2145   };
2146   static int ep_tube_num = SIZEOF_ARRAY_INT(ep_tube);
2147
2148   static int ep_em_slippery_wall[] =
2149   {
2150   };
2151   static int ep_em_slippery_wall_num = SIZEOF_ARRAY_INT(ep_em_slippery_wall);
2152
2153   static int ep_can_be_crumbled[] =
2154   {
2155     EL_SAND,
2156     EL_LANDMINE,
2157     EL_TRAP,
2158     EL_TRAP_ACTIVE
2159   };
2160   static int ep_can_be_crumbled_num = SIZEOF_ARRAY_INT(ep_can_be_crumbled);
2161
2162   static long ep1_bit[] =
2163   {
2164     EP_BIT_AMOEBALIVE,
2165     EP_BIT_AMOEBOID,
2166     EP_BIT_SCHLUESSEL,
2167     EP_BIT_PFORTE,
2168     EP_BIT_SOLID,
2169     EP_BIT_INDESTRUCTIBLE,
2170     EP_BIT_SLIPPERY,
2171     EP_BIT_ENEMY,
2172     EP_BIT_MAUER,
2173     EP_BIT_CAN_FALL,
2174     EP_BIT_CAN_SMASH,
2175     EP_BIT_CAN_CHANGE,
2176     EP_BIT_CAN_MOVE,
2177     EP_BIT_COULD_MOVE,
2178     EP_BIT_DONT_TOUCH,
2179     EP_BIT_DONT_GO_TO,
2180     EP_BIT_MAMPF2,
2181     EP_BIT_BD_ELEMENT,
2182     EP_BIT_SB_ELEMENT,
2183     EP_BIT_GEM,
2184     EP_BIT_INACTIVE,
2185     EP_BIT_EXPLOSIVE,
2186     EP_BIT_MAMPF3,
2187     EP_BIT_PUSHABLE,
2188     EP_BIT_PLAYER,
2189     EP_BIT_HAS_CONTENT,
2190     EP_BIT_EATABLE,
2191     EP_BIT_SP_ELEMENT,
2192     EP_BIT_QUICK_GATE,
2193     EP_BIT_OVER_PLAYER,
2194     EP_BIT_ACTIVE_BOMB
2195   };
2196   static long ep2_bit[] =
2197   {
2198     EP_BIT_BELT,
2199     EP_BIT_BELT_ACTIVE,
2200     EP_BIT_BELT_SWITCH,
2201     EP_BIT_TUBE,
2202     EP_BIT_EM_SLIPPERY_WALL,
2203     EP_BIT_CAN_BE_CRUMBLED
2204   };
2205   static int *ep1_array[] =
2206   {
2207     ep_amoebalive,
2208     ep_amoeboid,
2209     ep_schluessel,
2210     ep_pforte,
2211     ep_solid,
2212     ep_indestructible,
2213     ep_slippery,
2214     ep_enemy,
2215     ep_mauer,
2216     ep_can_fall,
2217     ep_can_smash,
2218     ep_can_change,
2219     ep_can_move,
2220     ep_could_move,
2221     ep_dont_touch,
2222     ep_dont_go_to,
2223     ep_mampf2,
2224     ep_bd_element,
2225     ep_sb_element,
2226     ep_gem,
2227     ep_inactive,
2228     ep_explosive,
2229     ep_mampf3,
2230     ep_pushable,
2231     ep_player,
2232     ep_has_content,
2233     ep_eatable,
2234     ep_sp_element,
2235     ep_quick_gate,
2236     ep_over_player,
2237     ep_active_bomb
2238   };
2239   static int *ep2_array[] =
2240   {
2241     ep_belt,
2242     ep_belt_active,
2243     ep_belt_switch,
2244     ep_tube,
2245     ep_em_slippery_wall,
2246     ep_can_be_crumbled
2247   };
2248   static int *ep1_num[] =
2249   {
2250     &ep_amoebalive_num,
2251     &ep_amoeboid_num,
2252     &ep_schluessel_num,
2253     &ep_pforte_num,
2254     &ep_solid_num,
2255     &ep_indestructible_num,
2256     &ep_slippery_num,
2257     &ep_enemy_num,
2258     &ep_mauer_num,
2259     &ep_can_fall_num,
2260     &ep_can_smash_num,
2261     &ep_can_change_num,
2262     &ep_can_move_num,
2263     &ep_could_move_num,
2264     &ep_dont_touch_num,
2265     &ep_dont_go_to_num,
2266     &ep_mampf2_num,
2267     &ep_bd_element_num,
2268     &ep_sb_element_num,
2269     &ep_gem_num,
2270     &ep_inactive_num,
2271     &ep_explosive_num,
2272     &ep_mampf3_num,
2273     &ep_pushable_num,
2274     &ep_player_num,
2275     &ep_has_content_num,
2276     &ep_eatable_num,
2277     &ep_sp_element_num,
2278     &ep_quick_gate_num,
2279     &ep_over_player_num,
2280     &ep_active_bomb_num
2281   };
2282   static int *ep2_num[] =
2283   {
2284     &ep_belt_num,
2285     &ep_belt_active_num,
2286     &ep_belt_switch_num,
2287     &ep_tube_num,
2288     &ep_em_slippery_wall_num,
2289     &ep_can_be_crumbled_num
2290   };
2291   static int num_properties1 = SIZEOF_ARRAY(ep1_num, int *);
2292   static int num_properties2 = SIZEOF_ARRAY(ep2_num, int *);
2293
2294   for (i=0; i<MAX_NUM_ELEMENTS; i++)
2295   {
2296     Properties1[i] = 0;
2297     Properties2[i] = 0;
2298   }
2299
2300   for (i=0; i<num_properties1; i++)
2301     for (j=0; j<*(ep1_num[i]); j++)
2302       Properties1[(ep1_array[i])[j]] |= ep1_bit[i];
2303   for (i=0; i<num_properties2; i++)
2304     for (j=0; j<*(ep2_num[i]); j++)
2305       Properties2[(ep2_array[i])[j]] |= ep2_bit[i];
2306
2307   for (i=EL_CHAR_START; i<=EL_CHAR_END; i++)
2308     Properties1[i] |= (EP_BIT_CHAR | EP_BIT_INACTIVE);
2309 }
2310
2311 static void InitGlobal()
2312 {
2313   global.autoplay_leveldir = NULL;
2314
2315   global.frames_per_second = 0;
2316   global.fps_slowdown = FALSE;
2317   global.fps_slowdown_factor = 1;
2318 }
2319
2320 void Execute_Command(char *command)
2321 {
2322   if (strcmp(command, "print graphicsinfo.conf") == 0)
2323   {
2324     int i;
2325
2326     printf("# You can configure additional/alternative image files here.\n");
2327     printf("# (The images below are default and therefore commented out.)\n");
2328     printf("\n");
2329     printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
2330     printf("\n");
2331     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2332     printf("\n");
2333
2334     for (i=0; image_config[i].token != NULL; i++)
2335       printf("# %s\n",
2336              getFormattedSetupEntry(image_config[i].token,
2337                                     image_config[i].value));
2338
2339     exit(0);
2340   }
2341   else if (strcmp(command, "print soundsinfo.conf") == 0)
2342   {
2343     int i;
2344
2345     printf("# You can configure additional/alternative sound files here.\n");
2346     printf("# (The sounds below are default and therefore commented out.)\n");
2347     printf("\n");
2348     printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
2349     printf("\n");
2350     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2351     printf("\n");
2352
2353     for (i=0; sound_config[i].token != NULL; i++)
2354       printf("# %s\n",
2355              getFormattedSetupEntry(sound_config[i].token,
2356                                     sound_config[i].value));
2357
2358     exit(0);
2359   }
2360   else if (strcmp(command, "print musicinfo.conf") == 0)
2361   {
2362     printf("# (Currently only \"name\" and \"sort_priority\" recognized.)\n");
2363     printf("\n");
2364     printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
2365     printf("\n");
2366     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2367
2368     exit(0);
2369   }
2370   else if (strncmp(command, "dump level ", 11) == 0)
2371   {
2372     char *filename = &command[11];
2373
2374     if (access(filename, F_OK) != 0)
2375       Error(ERR_EXIT, "cannot open file '%s'", filename);
2376
2377     LoadLevelFromFilename(filename);
2378     DumpLevel(&level);
2379
2380     exit(0);
2381   }
2382   else if (strncmp(command, "dump tape ", 10) == 0)
2383   {
2384     char *filename = &command[10];
2385
2386     if (access(filename, F_OK) != 0)
2387       Error(ERR_EXIT, "cannot open file '%s'", filename);
2388
2389     LoadTapeFromFilename(filename);
2390     DumpTape(&tape);
2391
2392     exit(0);
2393   }
2394   else if (strncmp(command, "autoplay ", 9) == 0)
2395   {
2396     char *str_copy = getStringCopy(&command[9]);
2397     char *str_ptr = strchr(str_copy, ' ');
2398
2399     global.autoplay_leveldir = str_copy;
2400     global.autoplay_level_nr = -1;
2401
2402     if (str_ptr != NULL)
2403     {
2404       *str_ptr++ = '\0';                        /* terminate leveldir string */
2405       global.autoplay_level_nr = atoi(str_ptr); /* get level_nr value */
2406     }
2407   }
2408   else
2409   {
2410     Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
2411   }
2412 }
2413
2414 static void InitSetup()
2415 {
2416   LoadSetup();                                  /* global setup info */
2417
2418   /* set some options from setup file */
2419
2420   if (setup.options.verbose)
2421     options.verbose = TRUE;
2422 }
2423
2424 static void InitPlayerInfo()
2425 {
2426   int i;
2427
2428   /* choose default local player */
2429   local_player = &stored_player[0];
2430
2431   for (i=0; i<MAX_PLAYERS; i++)
2432     stored_player[i].connected = FALSE;
2433
2434   local_player->connected = TRUE;
2435 }
2436
2437 static void InitArtworkInfo()
2438 {
2439   LoadArtworkInfo();
2440 }
2441
2442 static char *get_element_class_token(int element)
2443 {
2444   char *element_class_name = element_info[element].class_name;
2445   char *element_class_token = checked_malloc(strlen(element_class_name) + 3);
2446
2447   sprintf(element_class_token, "[%s]", element_class_name);
2448
2449   return element_class_token;
2450 }
2451
2452 static void InitArtworkConfig()
2453 {
2454   static char *image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS + 1];
2455   static char *sound_id_prefix[MAX_NUM_ELEMENTS + MAX_NUM_ELEMENTS + 1];
2456   static char *action_id_suffix[NUM_ACTIONS + 1];
2457   static char *direction_id_suffix[NUM_DIRECTIONS + 1];
2458   static char *special_id_suffix[NUM_SPECIAL_GFX_ARGS + 1];
2459   static char *dummy[1] = { NULL };
2460   static char *ignore_image_tokens[] =
2461   {
2462     "name",
2463     "sort_priority",
2464     "global.num_toons",
2465     "menu.draw_xoffset",
2466     "menu.draw_yoffset",
2467     "menu.draw_xoffset.MAIN",
2468     "menu.draw_yoffset.MAIN",
2469     "door.step_offset",
2470     "door.step_delay",
2471     NULL
2472   };
2473   static char *ignore_sound_tokens[] =
2474   {
2475     "name",
2476     "sort_priority",
2477     NULL
2478   };
2479   int i;
2480
2481   for (i=0; i<MAX_NUM_ELEMENTS; i++)
2482     image_id_prefix[i] = element_info[i].token_name;
2483   for (i=0; i<NUM_FONTS; i++)
2484     image_id_prefix[MAX_NUM_ELEMENTS + i] = font_info[i].token_name;
2485   image_id_prefix[MAX_NUM_ELEMENTS + NUM_FONTS] = NULL;
2486
2487   for (i=0; i<MAX_NUM_ELEMENTS; i++)
2488     sound_id_prefix[i] = element_info[i].token_name;
2489   for (i=0; i<MAX_NUM_ELEMENTS; i++)
2490     sound_id_prefix[MAX_NUM_ELEMENTS + i] = get_element_class_token(i);
2491   sound_id_prefix[MAX_NUM_ELEMENTS + MAX_NUM_ELEMENTS] = NULL;
2492
2493   for (i=0; i<NUM_ACTIONS; i++)
2494     action_id_suffix[i] = element_action_info[i].suffix;
2495   action_id_suffix[NUM_ACTIONS] = NULL;
2496
2497   for (i=0; i<NUM_DIRECTIONS; i++)
2498     direction_id_suffix[i] = element_direction_info[i].suffix;
2499   direction_id_suffix[NUM_DIRECTIONS] = NULL;
2500
2501   for (i=0; i<NUM_SPECIAL_GFX_ARGS; i++)
2502     special_id_suffix[i] = special_suffix_info[i].suffix;
2503   special_id_suffix[NUM_SPECIAL_GFX_ARGS] = NULL;
2504
2505   InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
2506                 image_id_prefix, action_id_suffix, direction_id_suffix,
2507                 special_id_suffix, ignore_image_tokens);
2508   InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
2509                 sound_id_prefix, action_id_suffix, dummy,
2510                 special_id_suffix, ignore_sound_tokens);
2511 }
2512
2513 static void InitMixer()
2514 {
2515   OpenAudio();
2516   StartMixer();
2517 }
2518
2519 void InitGfx()
2520 {
2521   char *filename_font_initial = NULL;
2522   Bitmap *bitmap_font_initial = NULL;
2523   int i, j;
2524
2525   /* determine settings for initial font (for displaying startup messages) */
2526   for (i=0; image_config[i].token != NULL; i++)
2527   {
2528     for (j=0; j < NUM_INITIAL_FONTS; j++)
2529     {
2530       char font_token[128];
2531       int len_font_token;
2532
2533       sprintf(font_token, "%s_%d", CONFIG_TOKEN_FONT_INITIAL, j + 1);
2534       len_font_token = strlen(font_token);
2535
2536       if (strcmp(image_config[i].token, font_token) == 0)
2537         filename_font_initial = image_config[i].value;
2538       else if (strlen(image_config[i].token) > len_font_token &&
2539                strncmp(image_config[i].token, font_token, len_font_token) == 0)
2540       {
2541         if (strcmp(&image_config[i].token[len_font_token], ".x") == 0)
2542           font_initial[j].src_x = atoi(image_config[i].value);
2543         else if (strcmp(&image_config[i].token[len_font_token], ".y") == 0)
2544           font_initial[j].src_y = atoi(image_config[i].value);
2545         else if (strcmp(&image_config[i].token[len_font_token], ".width") == 0)
2546           font_initial[j].width = atoi(image_config[i].value);
2547         else if (strcmp(&image_config[i].token[len_font_token],".height") == 0)
2548           font_initial[j].height = atoi(image_config[i].value);
2549       }
2550     }
2551   }
2552
2553   for (j=0; j < NUM_INITIAL_FONTS; j++)
2554   {
2555     font_initial[j].num_chars = DEFAULT_NUM_CHARS_PER_FONT;
2556     font_initial[j].num_chars_per_line = DEFAULT_NUM_CHARS_PER_LINE;
2557   }
2558
2559   if (filename_font_initial == NULL)    /* should not happen */
2560     Error(ERR_EXIT, "cannot get filename for '%s'", CONFIG_TOKEN_FONT_INITIAL);
2561
2562   /* create additional image buffers for double-buffering */
2563   bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
2564   bitmap_db_door  = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
2565
2566   /* initialize screen properties */
2567   InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
2568                    REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE,
2569                    bitmap_db_field);
2570   InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
2571   InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
2572   InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
2573
2574   bitmap_font_initial = LoadCustomImage(filename_font_initial);
2575
2576   for (j=0; j < NUM_INITIAL_FONTS; j++)
2577     font_initial[j].bitmap = bitmap_font_initial;
2578
2579   InitFontGraphicInfo();
2580
2581   DrawInitText(WINDOW_TITLE_STRING, 20, FC_YELLOW);
2582   DrawInitText(WINDOW_SUBTITLE_STRING, 50, FC_RED);
2583
2584   DrawInitText("Loading graphics:", 120, FC_GREEN);
2585
2586   InitTileClipmasks();
2587 }
2588
2589 void InitGfxBackground()
2590 {
2591   int x, y;
2592
2593   drawto = backbuffer;
2594   fieldbuffer = bitmap_db_field;
2595   SetDrawtoField(DRAW_BACKBUFFER);
2596
2597   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
2598              0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
2599   ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
2600   ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
2601
2602   for (x=0; x<MAX_BUF_XSIZE; x++)
2603     for (y=0; y<MAX_BUF_YSIZE; y++)
2604       redraw[x][y] = 0;
2605   redraw_tiles = 0;
2606   redraw_mask = REDRAW_ALL;
2607 }
2608
2609 static void InitLevelInfo()
2610 {
2611   LoadLevelInfo();                              /* global level info */
2612   LoadLevelSetup_LastSeries();                  /* last played series info */
2613   LoadLevelSetup_SeriesInfo();                  /* last played level info */
2614 }
2615
2616 void InitLevelArtworkInfo()
2617 {
2618   LoadLevelArtworkInfo();
2619 }
2620
2621 static void InitImages()
2622 {
2623   ReloadCustomImages();
2624
2625   LoadCustomElementDescriptions();
2626   LoadSpecialMenuDesignSettings();
2627
2628   ReinitializeGraphics();
2629 }
2630
2631 static void InitSound()
2632 {
2633   InitReloadCustomSounds(artwork.snd_current->identifier);
2634   ReinitializeSounds();
2635 }
2636
2637 static void InitMusic()
2638 {
2639   InitReloadCustomMusic(artwork.mus_current->identifier);
2640   ReinitializeMusic();
2641 }
2642
2643 void InitNetworkServer()
2644 {
2645 #if defined(PLATFORM_UNIX)
2646   int nr_wanted;
2647 #endif
2648
2649   if (!options.network)
2650     return;
2651
2652 #if defined(PLATFORM_UNIX)
2653   nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
2654
2655   if (!ConnectToServer(options.server_host, options.server_port))
2656     Error(ERR_EXIT, "cannot connect to network game server");
2657
2658   SendToServer_PlayerName(setup.player_name);
2659   SendToServer_ProtocolVersion();
2660
2661   if (nr_wanted)
2662     SendToServer_NrWanted(nr_wanted);
2663 #endif
2664 }
2665
2666 void ReloadCustomArtwork()
2667 {
2668   static char *leveldir_current_identifier = NULL;
2669   static boolean last_override_level_graphics = FALSE;
2670   static boolean last_override_level_sounds = FALSE;
2671   static boolean last_override_level_music = FALSE;
2672   /* identifier for new artwork; default: artwork configured in setup */
2673   char *gfx_new_identifier = artwork.gfx_current->identifier;
2674   char *snd_new_identifier = artwork.snd_current->identifier;
2675   char *mus_new_identifier = artwork.mus_current->identifier;
2676   boolean redraw_screen = FALSE;
2677
2678   if (leveldir_current_identifier == NULL)
2679     leveldir_current_identifier = leveldir_current->identifier;
2680
2681 #if 0
2682   printf("CURRENT GFX: '%s' ['%s']\n", artwork.gfx_current->identifier,
2683          leveldir_current->graphics_set);
2684   printf("CURRENT LEV: '%s' / '%s'\n", leveldir_current_identifier,
2685          leveldir_current->identifier);
2686 #endif
2687
2688 #if 0
2689   printf("graphics --> '%s' ('%s')\n",
2690          artwork.gfx_current_identifier, artwork.gfx_current->filename);
2691   printf("sounds   --> '%s' ('%s')\n",
2692          artwork.snd_current_identifier, artwork.snd_current->filename);
2693   printf("music    --> '%s' ('%s')\n",
2694          artwork.mus_current_identifier, artwork.mus_current->filename);
2695 #endif
2696
2697   /* leveldir_current may be invalid (level group, parent link) */
2698   if (!validLevelSeries(leveldir_current))
2699     return;
2700
2701   /* when a new level series was selected, check if there was a change
2702      in custom artwork stored in level series directory */
2703   if (leveldir_current_identifier != leveldir_current->identifier)
2704   {
2705     char *identifier_old = leveldir_current_identifier;
2706     char *identifier_new = leveldir_current->identifier;
2707
2708     if (getTreeInfoFromIdentifier(artwork.gfx_first, identifier_old) !=
2709         getTreeInfoFromIdentifier(artwork.gfx_first, identifier_new))
2710       gfx_new_identifier = identifier_new;
2711     if (getTreeInfoFromIdentifier(artwork.snd_first, identifier_old) !=
2712         getTreeInfoFromIdentifier(artwork.snd_first, identifier_new))
2713       snd_new_identifier = identifier_new;
2714     if (getTreeInfoFromIdentifier(artwork.mus_first, identifier_new) !=
2715         getTreeInfoFromIdentifier(artwork.mus_first, identifier_new))
2716       mus_new_identifier = identifier_new;
2717
2718     leveldir_current_identifier = leveldir_current->identifier;
2719   }
2720
2721   /* custom level artwork configured in level series configuration file
2722      always overrides custom level artwork stored in level series directory
2723      and (level independant) custom artwork configured in setup menue */
2724   if (leveldir_current->graphics_set != NULL)
2725     gfx_new_identifier = leveldir_current->graphics_set;
2726   if (leveldir_current->sounds_set != NULL)
2727     snd_new_identifier = leveldir_current->sounds_set;
2728   if (leveldir_current->music_set != NULL)
2729     mus_new_identifier = leveldir_current->music_set;
2730
2731   if (strcmp(artwork.gfx_current_identifier, gfx_new_identifier) != 0 ||
2732       last_override_level_graphics != setup.override_level_graphics)
2733   {
2734 #if 0
2735     printf("RELOADING GRAPHICS '%s' -> '%s' ('%s')\n",
2736            artwork.gfx_current_identifier,
2737            artwork.gfx_current->identifier,
2738            gfx_new_identifier);
2739 #endif
2740
2741     setLevelArtworkDir(artwork.gfx_first);
2742
2743     ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
2744
2745     InitImages();
2746
2747     FreeTileClipmasks();
2748     InitTileClipmasks();
2749
2750     artwork.gfx_current_identifier = artwork.gfx_current->identifier;
2751     last_override_level_graphics = setup.override_level_graphics;
2752
2753     redraw_screen = TRUE;
2754   }
2755
2756   if (strcmp(artwork.snd_current_identifier, snd_new_identifier) != 0 ||
2757       last_override_level_sounds != setup.override_level_sounds)
2758   {
2759 #if 0
2760     printf("RELOADING SOUNDS '%s' -> '%s' ('%s')\n",
2761            artwork.snd_current_identifier,
2762            artwork.snd_current->identifier,
2763            snd_new_identifier);
2764 #endif
2765
2766     /* set artwork path to send it to the sound server process */
2767     setLevelArtworkDir(artwork.snd_first);
2768
2769     InitReloadCustomSounds(snd_new_identifier);
2770     ReinitializeSounds();
2771
2772     artwork.snd_current_identifier = artwork.snd_current->identifier;
2773     last_override_level_sounds = setup.override_level_sounds;
2774
2775     redraw_screen = TRUE;
2776   }
2777
2778   if (strcmp(artwork.mus_current_identifier, mus_new_identifier) != 0 ||
2779       last_override_level_music != setup.override_level_music)
2780   {
2781     /* set artwork path to send it to the sound server process */
2782     setLevelArtworkDir(artwork.mus_first);
2783
2784     InitReloadCustomMusic(mus_new_identifier);
2785     ReinitializeMusic();
2786
2787     artwork.mus_current_identifier = artwork.mus_current->identifier;
2788     last_override_level_music = setup.override_level_music;
2789
2790     redraw_screen = TRUE;
2791   }
2792
2793   if (redraw_screen)
2794   {
2795     InitGfxBackground();
2796
2797     /* force redraw of (open or closed) door graphics */
2798     SetDoorState(DOOR_OPEN_ALL);
2799     CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
2800   }
2801 }
2802
2803
2804 /* ========================================================================= */
2805 /* OpenAll()                                                                 */
2806 /* ========================================================================= */
2807
2808 void OpenAll()
2809 {
2810   InitGlobal();         /* initialize some global variables */
2811
2812   if (options.execute_command)
2813     Execute_Command(options.execute_command);
2814
2815   if (options.serveronly)
2816   {
2817 #if defined(PLATFORM_UNIX)
2818     NetworkServer(options.server_port, options.serveronly);
2819 #else
2820     Error(ERR_WARN, "networking only supported in Unix version");
2821 #endif
2822     exit(0);    /* never reached */
2823   }
2824
2825   InitSetup();
2826
2827   InitPlayerInfo();
2828   InitArtworkInfo();            /* needed before loading gfx, sound & music */
2829   InitArtworkConfig();          /* needed before forking sound child process */
2830   InitMixer();
2831
2832   InitCounter();
2833
2834   InitRND(NEW_RANDOMIZE);
2835   InitSimpleRND(NEW_RANDOMIZE);
2836
2837   InitJoysticks();
2838
2839   InitVideoDisplay();
2840   InitVideoBuffer(&backbuffer, &window, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH,
2841                   setup.fullscreen);
2842
2843   InitEventFilter(FilterMouseMotionEvents);
2844
2845   InitElementProperties();
2846
2847   InitGfx();
2848
2849   InitLevelInfo();
2850   InitLevelArtworkInfo();
2851
2852   InitImages();                 /* needs to know current level directory */
2853   InitSound();                  /* needs to know current level directory */
2854   InitMusic();                  /* needs to know current level directory */
2855
2856   InitGfxBackground();
2857
2858   if (global.autoplay_leveldir)
2859   {
2860     AutoPlayTape();
2861     return;
2862   }
2863
2864   game_status = MAINMENU;
2865
2866   DrawMainMenu();
2867
2868   InitNetworkServer();
2869 }
2870
2871 void CloseAllAndExit(int exit_value)
2872 {
2873   StopSounds();
2874   FreeAllSounds();
2875   FreeAllMusic();
2876   CloseAudio();         /* called after freeing sounds (needed for SDL) */
2877
2878   FreeAllImages();
2879   FreeTileClipmasks();
2880
2881   CloseVideoDisplay();
2882   ClosePlatformDependantStuff();
2883
2884   exit(exit_value);
2885 }