34673f372ffffac791b2c965d24ea1414262beac
[rocksndiamonds.git] / src / init.c
1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back!               *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment                      *
5 *               Holger Schemel                             *
6 *               Detmolder Strasse 189                      *
7 *               33604 Bielefeld                            *
8 *               Germany                                    *
9 *               e-mail: info@artsoft.org                   *
10 *----------------------------------------------------------*
11 * init.c                                                   *
12 ***********************************************************/
13
14 #include "libgame/libgame.h"
15
16 #include "init.h"
17 #include "events.h"
18 #include "screens.h"
19 #include "editor.h"
20 #include "game.h"
21 #include "tape.h"
22 #include "tools.h"
23 #include "files.h"
24 #include "network.h"
25 #include "netserv.h"
26 #include "cartoons.h"
27 #include "config.h"
28
29 #include "conf_e2g.c"   /* include auto-generated data structure definitions */
30
31
32 static char *image_filename[NUM_PICTURES] =
33 {
34 #if 0
35   "RocksScreen.pcx",
36   "RocksDoor.pcx",
37   "RocksToons.pcx",
38   "RocksFontBig.pcx",
39   "RocksFontSmall.pcx",
40   "RocksFontMedium.pcx",
41   "RocksFontEM.pcx"
42 #else
43   "RocksScreen.pcx",
44   "RocksElements.pcx",
45   "RocksDoor.pcx",
46   "RocksHeroes.pcx",
47   "RocksToons.pcx",
48   "RocksSP.pcx",
49   "RocksDC.pcx",
50   "RocksMore.pcx",
51   "RocksFontBig.pcx",
52   "RocksFontSmall.pcx",
53   "RocksFontMedium.pcx",
54   "RocksFontEM.pcx"
55 #endif
56 }; 
57
58 static Bitmap *bitmap_font_initial = NULL;
59
60 static void InitGlobal(void);
61 static void InitSetup(void);
62 static void InitPlayerInfo(void);
63 static void InitLevelInfo(void);
64 static void InitArtworkInfo(void);
65 static void InitLevelArtworkInfo(void);
66 static void InitNetworkServer(void);
67 static void InitArtworkConfig(void);
68 static void InitImages(void);
69 static void InitMixer(void);
70 static void InitSound(void);
71 static void InitMusic(void);
72 static void InitGfx(void);
73 static void InitGfxBackground(void);
74 static void InitGadgets(void);
75 static void InitElementProperties(void);
76 static void InitElementGraphicInfo(void);
77 static void InitElementSoundInfo(void);
78 static void InitGraphicInfo(void);
79 static void InitSoundInfo();
80 static void Execute_Command(char *);
81
82 void OpenAll(void)
83 {
84   InitGlobal();         /* initialize some global variables */
85
86   if (options.execute_command)
87     Execute_Command(options.execute_command);
88
89   if (options.serveronly)
90   {
91 #if defined(PLATFORM_UNIX)
92     NetworkServer(options.server_port, options.serveronly);
93 #else
94     Error(ERR_WARN, "networking only supported in Unix version");
95 #endif
96     exit(0);    /* never reached */
97   }
98
99   InitProgramInfo(UNIX_USERDATA_DIRECTORY,
100                   PROGRAM_TITLE_STRING, getWindowTitleString(),
101                   ICON_TITLE_STRING, X11_ICON_FILENAME, X11_ICONMASK_FILENAME,
102                   MSDOS_POINTER_FILENAME,
103                   COOKIE_PREFIX, FILENAME_PREFIX, GAME_VERSION_ACTUAL);
104
105   InitSetup();
106   InitPlayerInfo();
107   InitArtworkInfo();            /* needed before loading gfx, sound & music */
108   InitArtworkConfig();          /* needed before forking sound child process */
109   InitMixer();
110
111   InitCounter();
112
113   InitJoysticks();
114   InitRND(NEW_RANDOMIZE);
115
116   InitVideoDisplay();
117   InitVideoBuffer(&backbuffer, &window, WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH,
118                   setup.fullscreen);
119
120   InitEventFilter(FilterMouseMotionEvents);
121
122   InitElementProperties();
123
124   InitGfx();
125
126   InitLevelInfo();
127   InitLevelArtworkInfo();
128
129   InitImages();                 /* needs to know current level directory */
130   InitSound();                  /* needs to know current level directory */
131   InitMusic();                  /* needs to know current level directory */
132
133   InitGfxBackground();
134
135   if (global.autoplay_leveldir)
136   {
137     AutoPlayTape();
138     return;
139   }
140
141   DrawMainMenu();
142
143   InitNetworkServer();
144 }
145
146 static void InitGlobal()
147 {
148   global.autoplay_leveldir = NULL;
149
150   global.frames_per_second = 0;
151   global.fps_slowdown = FALSE;
152   global.fps_slowdown_factor = 1;
153 }
154
155 static void InitSetup()
156 {
157   LoadSetup();                                  /* global setup info */
158 }
159
160 static void InitPlayerInfo()
161 {
162   int i;
163
164   /* choose default local player */
165   local_player = &stored_player[0];
166
167   for (i=0; i<MAX_PLAYERS; i++)
168     stored_player[i].connected = FALSE;
169
170   local_player->connected = TRUE;
171 }
172
173 static void InitLevelInfo()
174 {
175   LoadLevelInfo();                              /* global level info */
176   LoadLevelSetup_LastSeries();                  /* last played series info */
177   LoadLevelSetup_SeriesInfo();                  /* last played level info */
178 }
179
180 static void InitArtworkInfo()
181 {
182   LoadArtworkInfo();
183 }
184
185 static void InitArtworkConfig()
186 {
187   static char *element_prefix[MAX_NUM_ELEMENTS + 1];
188   static char *sound_class_prefix[MAX_NUM_ELEMENTS + 1];
189   static char *action_suffix[NUM_ACTIONS + 1];
190   static char *direction_suffix[NUM_DIRECTIONS + 1];
191   static char *dummy[1] = { NULL };
192   int i;
193
194   for (i=0; i<MAX_NUM_ELEMENTS; i++)
195     element_info[i].custom_description = NULL;
196
197   for (i=0; i<MAX_NUM_ELEMENTS + 1; i++)
198     element_prefix[i] = element_info[i].token_name;
199   for (i=0; i<MAX_NUM_ELEMENTS + 1; i++)
200     sound_class_prefix[i] = element_info[i].sound_class_name;
201   for (i=0; i<NUM_ACTIONS + 1; i++)
202     action_suffix[i] = element_action_info[i].suffix;
203   for (i=0; i<NUM_DIRECTIONS + 1; i++)
204     direction_suffix[i] = element_direction_info[i].suffix;
205
206   InitImageList(image_config, NUM_IMAGE_FILES, image_config_suffix,
207                 element_prefix, action_suffix, direction_suffix);
208   InitSoundList(sound_config, NUM_SOUND_FILES, sound_config_suffix,
209                 sound_class_prefix, action_suffix, dummy);
210 }
211
212 void InitLevelArtworkInfo()
213 {
214   LoadLevelArtworkInfo();
215 }
216
217 void InitNetworkServer()
218 {
219 #if defined(PLATFORM_UNIX)
220   int nr_wanted;
221 #endif
222
223   if (!options.network)
224     return;
225
226 #if defined(PLATFORM_UNIX)
227   nr_wanted = Request("Choose player", REQ_PLAYER | REQ_STAY_CLOSED);
228
229   if (!ConnectToServer(options.server_host, options.server_port))
230     Error(ERR_EXIT, "cannot connect to network game server");
231
232   SendToServer_PlayerName(setup.player_name);
233   SendToServer_ProtocolVersion();
234
235   if (nr_wanted)
236     SendToServer_NrWanted(nr_wanted);
237 #endif
238 }
239
240 static void InitMixer()
241 {
242   OpenAudio();
243   StartMixer();
244 }
245
246 static void ReinitializeGraphics()
247 {
248   InitElementGraphicInfo();     /* initialize element/graphic config info */
249   InitGraphicInfo();            /* initialize graphic info from config file */
250
251   InitFontInfo(bitmap_font_initial,
252                graphic_info[IMG_FONT_BIG].bitmap,
253                graphic_info[IMG_FONT_MEDIUM].bitmap,
254                graphic_info[IMG_FONT_SMALL].bitmap,
255                graphic_info[IMG_FONT_EM].bitmap);
256
257   SetMainBackgroundImage(IMG_BACKGROUND_DEFAULT);
258   SetDoorBackgroundImage(IMG_BACKGROUND_DOOR);
259
260   InitGadgets();
261   InitToons();
262
263
264
265   /* !!! TEST ONLY !!! */
266
267 #if 1
268
269   {
270     Bitmap *tst_bitmap = graphic_info[IMG_SAND].bitmap;
271     Bitmap *tmp_bitmap = ZoomBitmap(tst_bitmap,
272                                     tst_bitmap->width / 2,
273                                     tst_bitmap->height / 2);
274
275     BlitBitmap(tmp_bitmap, tst_bitmap, 0, 0, 256, 224, 0, 448);
276
277     FreeBitmap(tmp_bitmap);
278   }
279
280 #else
281 #ifdef TARGET_SDL
282
283   {
284     Bitmap tmp_bitmap;
285     SDL_Surface *dst = SDLZoomSurface(graphic_info[IMG_SAND].bitmap->surface,
286                                       0.5, 0.5);
287     tmp_bitmap.surface = dst;
288
289     BlitBitmap(&tmp_bitmap, graphic_info[IMG_SAND].bitmap,
290                0, 0, 256, 224, 0, 448);
291
292     SDL_FreeSurface(dst);
293   }
294
295 #elif defined(PLATFORM_MSDOS)
296
297   stretch_blit((BITMAP *)(graphic_info[IMG_SAND].bitmap->drawable),
298                (BITMAP *)(graphic_info[IMG_SAND].bitmap->drawable),
299                0, 0, 512, 448,
300                0, 448, 256, 224);
301
302 #endif
303 #endif
304 }
305
306 static void ReinitializeSounds()
307 {
308   InitElementSoundInfo();       /* initialize element/sound config info */
309   InitSoundInfo();              /* initialize sounds info from config file */
310
311   InitPlaySoundLevel();         /* initialize internal game sound values */
312 }
313
314 static void ReinitializeMusic()
315 {
316   /* currently nothing to do */
317 }
318
319 static void InitImages()
320 {
321   ReloadCustomImages();
322   ReinitializeGraphics();
323
324   LoadCustomElementDescriptions();
325 }
326
327 static void InitSound()
328 {
329   InitReloadCustomSounds(artwork.snd_current->identifier);
330   ReinitializeSounds();
331 }
332
333 static void InitMusic()
334 {
335   InitReloadCustomMusic(artwork.mus_current->identifier);
336   ReinitializeMusic();
337 }
338
339 static void InitTileClipmasks()
340 {
341 #if 0
342 #if defined(TARGET_X11)
343   XGCValues clip_gc_values;
344   unsigned long clip_gc_valuemask;
345
346 #if defined(TARGET_X11_NATIVE)
347
348 #if 0
349   GC copy_clipmask_gc;
350
351   static struct
352   {
353     int start;
354     int count;
355   }
356   tile_needs_clipping[] =
357   {
358     { GFX_SPIELER1_UP, 4 },
359     { GFX_SPIELER1_DOWN, 4 },
360     { GFX_SPIELER1_LEFT, 4 },
361     { GFX_SPIELER1_RIGHT, 4 },
362     { GFX_SPIELER1_PUSH_LEFT, 4 },
363     { GFX_SPIELER1_PUSH_RIGHT, 4 },
364     { GFX_SPIELER2_UP, 4 },
365     { GFX_SPIELER2_DOWN, 4 },
366     { GFX_SPIELER2_LEFT, 4 },
367     { GFX_SPIELER2_RIGHT, 4 },
368     { GFX_SPIELER2_PUSH_LEFT, 4 },
369     { GFX_SPIELER2_PUSH_RIGHT, 4 },
370     { GFX_SPIELER3_UP, 4 },
371     { GFX_SPIELER3_DOWN, 4 },
372     { GFX_SPIELER3_LEFT, 4 },
373     { GFX_SPIELER3_RIGHT, 4 },
374     { GFX_SPIELER3_PUSH_LEFT, 4 },
375     { GFX_SPIELER3_PUSH_RIGHT, 4 },
376     { GFX_SPIELER4_UP, 4 },
377     { GFX_SPIELER4_DOWN, 4 },
378     { GFX_SPIELER4_LEFT, 4 },
379     { GFX_SPIELER4_RIGHT, 4 },
380     { GFX_SPIELER4_PUSH_LEFT, 4 },
381     { GFX_SPIELER4_PUSH_RIGHT, 4 },
382     { GFX_SP_MURPHY, 1 },
383     { GFX_MURPHY_GO_LEFT, 3 },
384     { GFX_MURPHY_GO_RIGHT, 3 },
385     { GFX_MURPHY_SNAP_UP, 1 },
386     { GFX_MURPHY_SNAP_DOWN, 1 },
387     { GFX_MURPHY_SNAP_RIGHT, 1 },
388     { GFX_MURPHY_SNAP_LEFT, 1 },
389     { GFX_MURPHY_PUSH_RIGHT, 1 },
390     { GFX_MURPHY_PUSH_LEFT, 1 },
391     { GFX_GEBLUBBER, 4 },
392     { GFX_DYNAMIT, 7 },
393     { GFX_DYNABOMB, 4 },
394     { GFX_EXPLOSION, 8 },
395     { GFX_SOKOBAN_OBJEKT, 1 },
396     { GFX_FUNKELN_BLAU, 3 },
397     { GFX_FUNKELN_WEISS, 3 },
398     { GFX2_SHIELD_PASSIVE, 3 },
399     { GFX2_SHIELD_ACTIVE, 3 },
400     { -1, 0 }
401   };
402 #endif
403
404 #endif /* TARGET_X11_NATIVE */
405 #endif /* TARGET_X11 */
406
407   int i;
408
409   /* initialize pixmap array for special X11 tile clipping to Pixmap 'None' */
410   for (i=0; i<NUM_TILES; i++)
411     tile_clipmask[i] = None;
412
413 #if defined(TARGET_X11)
414   /* This stuff is needed because X11 (XSetClipOrigin(), to be precise) is
415      often very slow when preparing a masked XCopyArea() for big Pixmaps.
416      To prevent this, create small (tile-sized) mask Pixmaps which will then
417      be set much faster with XSetClipOrigin() and speed things up a lot. */
418
419   clip_gc_values.graphics_exposures = False;
420   clip_gc_valuemask = GCGraphicsExposures;
421   tile_clip_gc = XCreateGC(display, window->drawable,
422                            clip_gc_valuemask, &clip_gc_values);
423
424 #if 0
425   for (i=0; i<NUM_BITMAPS; i++)
426   {
427     if (pix[i]->clip_mask)
428     {
429       clip_gc_values.graphics_exposures = False;
430       clip_gc_values.clip_mask = pix[i]->clip_mask;
431       clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
432       pix[i]->stored_clip_gc = XCreateGC(display, window->drawable,
433                                          clip_gc_valuemask, &clip_gc_values);
434     }
435   }
436 #endif
437
438 #if defined(TARGET_X11_NATIVE)
439
440 #if 0
441   /* create graphic context structures needed for clipping */
442   clip_gc_values.graphics_exposures = False;
443   clip_gc_valuemask = GCGraphicsExposures;
444   copy_clipmask_gc = XCreateGC(display, pix[PIX_BACK]->clip_mask,
445                                clip_gc_valuemask, &clip_gc_values);
446
447   /* create only those clipping Pixmaps we really need */
448   for (i=0; tile_needs_clipping[i].start>=0; i++)
449   {
450     int j;
451
452     for (j=0; j<tile_needs_clipping[i].count; j++)
453     {
454       int tile = tile_needs_clipping[i].start + j;
455       int graphic = tile;
456       int src_x, src_y;
457       Bitmap *src_bitmap;
458       Pixmap src_pixmap;
459
460       getGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
461       src_pixmap = src_bitmap->clip_mask;
462
463       tile_clipmask[tile] = XCreatePixmap(display, window->drawable,
464                                           TILEX, TILEY, 1);
465
466       XCopyArea(display, src_pixmap, tile_clipmask[tile], copy_clipmask_gc,
467                 src_x, src_y, TILEX, TILEY, 0, 0);
468     }
469   }
470
471   XFreeGC(display, copy_clipmask_gc);
472 #endif
473
474 #endif /* TARGET_X11_NATIVE */
475 #endif /* TARGET_X11 */
476 #endif
477 }
478
479 void FreeTileClipmasks()
480 {
481 #if 0
482 #if defined(TARGET_X11)
483   int i;
484
485   for (i=0; i<NUM_TILES; i++)
486   {
487     if (tile_clipmask[i] != None)
488     {
489       XFreePixmap(display, tile_clipmask[i]);
490       tile_clipmask[i] = None;
491     }
492   }
493
494   if (tile_clip_gc)
495     XFreeGC(display, tile_clip_gc);
496   tile_clip_gc = None;
497
498 #if 0
499   for (i=0; i<NUM_BITMAPS; i++)
500   {
501     if (pix[i] != NULL && pix[i]->stored_clip_gc)
502     {
503       XFreeGC(display, pix[i]->stored_clip_gc);
504       pix[i]->stored_clip_gc = None;
505     }
506   }
507 #endif
508
509 #endif /* TARGET_X11 */
510 #endif
511 }
512
513 void InitGfx()
514 {
515 #if 0
516   int i;
517 #endif
518
519   /* initialize screen properties */
520   InitGfxFieldInfo(SX, SY, SXSIZE, SYSIZE,
521                    REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
522   InitGfxDoor1Info(DX, DY, DXSIZE, DYSIZE);
523   InitGfxDoor2Info(VX, VY, VXSIZE, VYSIZE);
524   InitGfxScrollbufferInfo(FXSIZE, FYSIZE);
525
526   /* create additional image buffers for double-buffering */
527   bitmap_db_field = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
528   bitmap_db_door  = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
529
530 #if 0
531   pix[PIX_FONT_SMALL] = LoadCustomImage(image_filename[PIX_FONT_SMALL]);
532
533   InitFontInfo(NULL, NULL, pix[PIX_FONT_SMALL], NULL);
534 #else
535   bitmap_font_initial = LoadCustomImage(image_filename[PIX_FONT_SMALL]);
536
537   InitFontInfo(bitmap_font_initial, NULL, NULL, NULL, NULL);
538 #endif
539
540   DrawInitText(WINDOW_TITLE_STRING, 20, FC_YELLOW);
541   DrawInitText(WINDOW_SUBTITLE_STRING, 50, FC_RED);
542
543   DrawInitText("Loading graphics:", 120, FC_GREEN);
544
545 #if 0
546   for (i=0; i<NUM_PICTURES; i++)
547   {
548 #if 0
549     if (i != PIX_FONT_SMALL)
550 #endif
551     {
552       DrawInitText(image_filename[i], 150, FC_YELLOW);
553
554       pix[i] = LoadCustomImage(image_filename[i]);
555     }
556   }
557 #endif
558
559 #if 0
560   InitFontInfo(pix[PIX_FONT_BIG], pix[PIX_FONT_MEDIUM], pix[PIX_FONT_SMALL],
561                pix[PIX_FONT_EM]);
562 #endif
563
564   InitTileClipmasks();
565 }
566
567 void InitGfxBackground()
568 {
569   int x, y;
570
571   drawto = backbuffer;
572   fieldbuffer = bitmap_db_field;
573   SetDrawtoField(DRAW_BACKBUFFER);
574
575   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, backbuffer,
576              0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
577   ClearRectangle(backbuffer, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
578   ClearRectangle(bitmap_db_door, 0, 0, 3 * DXSIZE, DYSIZE + VYSIZE);
579
580   for (x=0; x<MAX_BUF_XSIZE; x++)
581     for (y=0; y<MAX_BUF_YSIZE; y++)
582       redraw[x][y] = 0;
583   redraw_tiles = 0;
584   redraw_mask = REDRAW_ALL;
585 }
586
587 void ReloadCustomArtwork()
588 {
589   static char *leveldir_current_identifier = NULL;
590   static boolean last_override_level_graphics = FALSE;
591   static boolean last_override_level_sounds = FALSE;
592   static boolean last_override_level_music = FALSE;
593   /* identifier for new artwork; default: artwork configured in setup */
594   char *gfx_new_identifier = artwork.gfx_current->identifier;
595   char *snd_new_identifier = artwork.snd_current->identifier;
596   char *mus_new_identifier = artwork.mus_current->identifier;
597   boolean redraw_screen = FALSE;
598
599   if (leveldir_current_identifier == NULL)
600     leveldir_current_identifier = leveldir_current->identifier;
601
602 #if 0
603   printf("CURRENT GFX: '%s' ['%s']\n", artwork.gfx_current->identifier,
604          leveldir_current->graphics_set);
605   printf("CURRENT LEV: '%s' / '%s'\n", leveldir_current_identifier,
606          leveldir_current->identifier);
607 #endif
608
609 #if 0
610   printf("graphics --> '%s' ('%s')\n",
611          artwork.gfx_current_identifier, artwork.gfx_current->filename);
612   printf("sounds   --> '%s' ('%s')\n",
613          artwork.snd_current_identifier, artwork.snd_current->filename);
614   printf("music    --> '%s' ('%s')\n",
615          artwork.mus_current_identifier, artwork.mus_current->filename);
616 #endif
617
618   /* leveldir_current may be invalid (level group, parent link) */
619   if (!validLevelSeries(leveldir_current))
620     return;
621
622   /* when a new level series was selected, check if there was a change
623      in custom artwork stored in level series directory */
624   if (leveldir_current_identifier != leveldir_current->identifier)
625   {
626     char *identifier_old = leveldir_current_identifier;
627     char *identifier_new = leveldir_current->identifier;
628
629     if (getTreeInfoFromIdentifier(artwork.gfx_first, identifier_old) !=
630         getTreeInfoFromIdentifier(artwork.gfx_first, identifier_new))
631       gfx_new_identifier = identifier_new;
632     if (getTreeInfoFromIdentifier(artwork.snd_first, identifier_old) !=
633         getTreeInfoFromIdentifier(artwork.snd_first, identifier_new))
634       snd_new_identifier = identifier_new;
635     if (getTreeInfoFromIdentifier(artwork.mus_first, identifier_new) !=
636         getTreeInfoFromIdentifier(artwork.mus_first, identifier_new))
637       mus_new_identifier = identifier_new;
638
639     leveldir_current_identifier = leveldir_current->identifier;
640   }
641
642   /* custom level artwork configured in level series configuration file
643      always overrides custom level artwork stored in level series directory
644      and (level independant) custom artwork configured in setup menue */
645   if (leveldir_current->graphics_set != NULL)
646     gfx_new_identifier = leveldir_current->graphics_set;
647   if (leveldir_current->sounds_set != NULL)
648     snd_new_identifier = leveldir_current->sounds_set;
649   if (leveldir_current->music_set != NULL)
650     mus_new_identifier = leveldir_current->music_set;
651
652   if (strcmp(artwork.gfx_current_identifier, gfx_new_identifier) != 0 ||
653       last_override_level_graphics != setup.override_level_graphics)
654   {
655 #if 0
656     printf("RELOADING GRAPHICS '%s' -> '%s' ('%s')\n",
657            artwork.gfx_current_identifier,
658            artwork.gfx_current->identifier,
659            gfx_new_identifier);
660 #endif
661
662     setLevelArtworkDir(artwork.gfx_first);
663
664     ClearRectangle(window, 0, 0, WIN_XSIZE, WIN_YSIZE);
665
666     ReloadCustomImages();
667     ReinitializeGraphics();
668
669     LoadCustomElementDescriptions();
670
671     FreeTileClipmasks();
672     InitTileClipmasks();
673
674     artwork.gfx_current_identifier = artwork.gfx_current->identifier;
675     last_override_level_graphics = setup.override_level_graphics;
676
677     redraw_screen = TRUE;
678   }
679
680   if (strcmp(artwork.snd_current_identifier, snd_new_identifier) != 0 ||
681       last_override_level_sounds != setup.override_level_sounds)
682   {
683 #if 0
684     printf("RELOADING SOUNDS '%s' -> '%s' ('%s')\n",
685            artwork.snd_current_identifier,
686            artwork.snd_current->identifier,
687            snd_new_identifier);
688 #endif
689
690     /* set artwork path to send it to the sound server process */
691     setLevelArtworkDir(artwork.snd_first);
692
693     InitReloadCustomSounds(snd_new_identifier);
694     ReinitializeSounds();
695
696     artwork.snd_current_identifier = artwork.snd_current->identifier;
697     last_override_level_sounds = setup.override_level_sounds;
698
699     redraw_screen = TRUE;
700   }
701
702   if (strcmp(artwork.mus_current_identifier, mus_new_identifier) != 0 ||
703       last_override_level_music != setup.override_level_music)
704   {
705     /* set artwork path to send it to the sound server process */
706     setLevelArtworkDir(artwork.mus_first);
707
708     InitReloadCustomMusic(mus_new_identifier);
709     ReinitializeMusic();
710
711     artwork.mus_current_identifier = artwork.mus_current->identifier;
712     last_override_level_music = setup.override_level_music;
713
714     redraw_screen = TRUE;
715   }
716
717   if (redraw_screen)
718   {
719     InitGfxBackground();
720
721     /* force redraw of (open or closed) door graphics */
722     SetDoorState(DOOR_OPEN_ALL);
723     CloseDoor(DOOR_CLOSE_ALL | DOOR_NO_DELAY);
724   }
725 }
726
727 void FreeGadgets()
728 {
729   FreeLevelEditorGadgets();
730   FreeGameButtons();
731   FreeTapeButtons();
732   FreeToolButtons();
733   FreeScreenGadgets();
734 }
735
736 void InitGadgets()
737 {
738   static boolean gadgets_initialized = FALSE;
739
740   if (gadgets_initialized)
741     FreeGadgets();
742
743   CreateLevelEditorGadgets();
744   CreateGameButtons();
745   CreateTapeButtons();
746   CreateToolButtons();
747   CreateScreenGadgets();
748
749   gadgets_initialized = TRUE;
750 }
751
752 void InitElementGraphicInfo()
753 {
754   struct PropertyMapping *property_mapping = getImageListPropertyMapping();
755   int num_property_mappings = getImageListPropertyMappingSize();
756   int i, act, dir;
757
758   /* set values to -1 to identify later as "uninitialized" values */
759   for (i=0; i<MAX_NUM_ELEMENTS; i++)
760   {
761     for (act=0; act<NUM_ACTIONS; act++)
762     {
763       element_info[i].graphic[act] = -1;
764
765       for (dir=0; dir<NUM_DIRECTIONS; dir++)
766         element_info[i].direction_graphic[act][dir] = -1;
767     }
768   }
769
770   for (i=EL_CHAR_START; i<=EL_CHAR_END; i++)
771     element_info[i].graphic[ACTION_DEFAULT] =
772       IMG_CHAR_START + (i - EL_CHAR_START);
773
774   for (i=EL_CUSTOM_START; i<=EL_CUSTOM_END; i++)
775     element_info[i].graphic[ACTION_DEFAULT] =
776       IMG_CUSTOM_START + (i - EL_CUSTOM_START);
777
778   /* initialize element/graphic mapping from static configuration */
779   for (i=0; element_to_graphic[i].element > -1; i++)
780   {
781     int element   = element_to_graphic[i].element;
782     int action    = element_to_graphic[i].action;
783     int direction = element_to_graphic[i].direction;
784     int graphic   = element_to_graphic[i].graphic;
785
786     if (action < 0)
787       action = ACTION_DEFAULT;
788
789     if (direction > -1)
790       element_info[element].direction_graphic[action][direction] = graphic;
791     else
792       element_info[element].graphic[action] = graphic;
793   }
794
795   /* initialize element/graphic mapping from dynamic configuration */
796   for (i=0; i < num_property_mappings; i++)
797   {
798     int element   = property_mapping[i].base_index;
799     int action    = property_mapping[i].ext1_index;
800     int direction = property_mapping[i].ext2_index;
801     int graphic   = property_mapping[i].artwork_index;
802
803     if (action < 0)
804       action = ACTION_DEFAULT;
805
806     if (direction > -1)
807       element_info[element].direction_graphic[action][direction] = graphic;
808     else
809       element_info[element].graphic[action] = graphic;
810   }
811
812   /* now set all '-1' values to element specific default values */
813   for (i=0; i<MAX_NUM_ELEMENTS; i++)
814   {
815     int default_action_graphic = element_info[i].graphic[ACTION_DEFAULT];
816     int default_action_direction_graphic[NUM_DIRECTIONS];
817
818     if (default_action_graphic == -1)
819       default_action_graphic = IMG_CHAR_QUESTION;
820
821     for (dir=0; dir<NUM_DIRECTIONS; dir++)
822     {
823       default_action_direction_graphic[dir] =
824         element_info[i].direction_graphic[ACTION_DEFAULT][dir];
825
826       if (default_action_direction_graphic[dir] == -1)
827         default_action_direction_graphic[dir] = default_action_graphic;
828     }
829
830     for (act=0; act<NUM_ACTIONS; act++)
831     {
832       for (dir=0; dir<NUM_DIRECTIONS; dir++)
833       {
834         int default_direction_graphic = element_info[i].graphic[act];
835
836         /* no graphic for current action -- use default direction graphic */
837         if (default_direction_graphic == -1)
838           default_direction_graphic = default_action_direction_graphic[dir];
839
840         if (element_info[i].direction_graphic[act][dir] == -1)
841           element_info[i].direction_graphic[act][dir] =
842             default_direction_graphic;
843       }
844
845       /* no graphic for this specific action -- use default action graphic */
846       if (element_info[i].graphic[act] == -1)
847         element_info[i].graphic[act] = default_action_graphic;
848     }
849   }
850 }
851
852 static void InitElementSoundInfo()
853 {
854   /* soon to come */
855 }
856
857 static void set_graphic_parameters(int graphic, int *parameter)
858 {
859   Bitmap *src_bitmap = getBitmapFromImageID(graphic);
860   int num_xtiles = (src_bitmap ? src_bitmap->width          : TILEX) / TILEX;
861   int num_ytiles = (src_bitmap ? src_bitmap->height * 2 / 3 : TILEY) / TILEY;
862
863   graphic_info[graphic].bitmap = src_bitmap;
864
865   graphic_info[graphic].src_x = parameter[GFX_ARG_XPOS] * TILEX;
866   graphic_info[graphic].src_y = parameter[GFX_ARG_YPOS] * TILEY;
867   graphic_info[graphic].offset_x = parameter[GFX_ARG_OFFSET];
868   graphic_info[graphic].offset_y = 0;
869
870   /* animation frames are ordered vertically instead of horizontally */
871   if (parameter[GFX_ARG_VERTICAL])
872   {
873     graphic_info[graphic].offset_x = 0;
874     graphic_info[graphic].offset_y = parameter[GFX_ARG_OFFSET];
875   }
876
877   /* optionally, the x and y offset of frames can be specified directly */
878   if (parameter[GFX_ARG_XOFFSET] != ARG_UNDEFINED_VALUE)
879     graphic_info[graphic].offset_x = parameter[GFX_ARG_XOFFSET];
880   if (parameter[GFX_ARG_YOFFSET] != ARG_UNDEFINED_VALUE)
881     graphic_info[graphic].offset_y = parameter[GFX_ARG_YOFFSET];
882
883   /* automatically determine correct number of frames, if not defined */
884   if (parameter[GFX_ARG_FRAMES] != ARG_UNDEFINED_VALUE)
885     graphic_info[graphic].anim_frames = parameter[GFX_ARG_FRAMES];
886   else if (parameter[GFX_ARG_XPOS] == 0 && !parameter[GFX_ARG_VERTICAL])
887     graphic_info[graphic].anim_frames = num_xtiles;
888   else if (parameter[GFX_ARG_YPOS] == 0 && parameter[GFX_ARG_VERTICAL])
889     graphic_info[graphic].anim_frames = num_ytiles;
890   else
891     graphic_info[graphic].anim_frames = 1;
892
893   graphic_info[graphic].anim_delay = parameter[GFX_ARG_DELAY];
894   if (graphic_info[graphic].anim_delay == 0)    /* delay must be at least 1 */
895     graphic_info[graphic].anim_delay = 1;
896
897   /* set mode for animation frame order */
898   if (parameter[GFX_ARG_MODE_LOOP])
899     graphic_info[graphic].anim_mode = ANIM_LOOP;
900   else if (parameter[GFX_ARG_MODE_LINEAR])
901     graphic_info[graphic].anim_mode = ANIM_LINEAR;
902   else if (parameter[GFX_ARG_MODE_PINGPONG])
903     graphic_info[graphic].anim_mode = ANIM_PINGPONG;
904   else if (parameter[GFX_ARG_MODE_PINGPONG2])
905     graphic_info[graphic].anim_mode = ANIM_PINGPONG2;
906   else if (parameter[GFX_ARG_MODE_RANDOM])
907     graphic_info[graphic].anim_mode = ANIM_RANDOM;
908   else if (graphic_info[graphic].anim_frames > 1)
909     graphic_info[graphic].anim_mode = ANIM_LOOP;
910   else
911     graphic_info[graphic].anim_mode = ANIM_NONE;
912
913   /* set additional flag to play animation frames in reverse order */
914   if (parameter[GFX_ARG_MODE_REVERSE])
915     graphic_info[graphic].anim_mode |= ANIM_REVERSE;
916
917   /* automatically determine correct start frame, if not defined */
918   if (parameter[GFX_ARG_START_FRAME] == ARG_UNDEFINED_VALUE)
919     graphic_info[graphic].anim_start_frame = 0;
920   else if (graphic_info[graphic].anim_mode & ANIM_REVERSE)
921     graphic_info[graphic].anim_start_frame =
922       graphic_info[graphic].anim_frames - parameter[GFX_ARG_START_FRAME] - 1;
923   else
924     graphic_info[graphic].anim_start_frame = parameter[GFX_ARG_START_FRAME];
925
926   /* animation synchronized with global frame counter, not move position */
927   graphic_info[graphic].anim_global_sync = parameter[GFX_ARG_GLOBAL_SYNC];
928 }
929
930 static void InitGraphicInfo()
931 {
932   static boolean clipmasks_initialized = FALSE;
933   int num_images = getImageListSize();
934   int i;
935 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
936   Pixmap src_pixmap;
937   XGCValues clip_gc_values;
938   unsigned long clip_gc_valuemask;
939   GC copy_clipmask_gc = None;
940 #endif
941
942   if (graphic_info != NULL)
943     free(graphic_info);
944
945   graphic_info = checked_calloc(num_images * sizeof(struct GraphicInfo));
946
947 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
948   if (clipmasks_initialized)
949   {
950     for (i=0; i<num_images; i++)
951     {
952       if (graphic_info[i].clip_mask)
953         XFreePixmap(display, graphic_info[i].clip_mask);
954       if (graphic_info[i].clip_gc)
955         XFreeGC(display, graphic_info[i].clip_gc);
956
957       graphic_info[i].clip_mask = None;
958       graphic_info[i].clip_gc = None;
959     }
960   }
961 #endif
962
963   for (i=0; i<num_images; i++)
964   {
965     struct FileInfo *image = getImageListEntry(i);
966     Bitmap *src_bitmap;
967     int src_x, src_y;
968     int first_frame, last_frame;
969
970     set_graphic_parameters(i, image->parameter);
971
972     /* now check if no animation frames are outside of the loaded image */
973
974     if (graphic_info[i].bitmap == NULL)
975       continue;         /* skip check for optional images that are undefined */
976
977     first_frame = 0;
978     getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
979     if (src_x < 0 || src_y < 0 ||
980         src_x + TILEX > src_bitmap->width ||
981         src_y + TILEY > src_bitmap->height)
982     {
983       Error(ERR_RETURN_LINE, "-");
984       Error(ERR_RETURN, "warning: error found in config file:");
985       Error(ERR_RETURN, "- config file: '%s'",
986             getImageConfigFilename());
987       Error(ERR_RETURN, "- config token: '%s'",
988             getTokenFromImageID(i));
989       Error(ERR_RETURN, "- image file: '%s'",
990             src_bitmap->source_filename);
991       Error(ERR_RETURN,
992             "error: first animation frame out of bounds (%d, %d)",
993             src_x, src_y);
994       Error(ERR_RETURN, "custom graphic rejected for this element/action");
995       Error(ERR_RETURN_LINE, "-");
996
997       set_graphic_parameters(i, image->default_parameter);
998     }
999
1000     last_frame = graphic_info[i].anim_frames - 1;
1001     getGraphicSource(i, last_frame, &src_bitmap, &src_x, &src_y);
1002     if (src_x < 0 || src_y < 0 ||
1003         src_x + TILEX > src_bitmap->width ||
1004         src_y + TILEY > src_bitmap->height)
1005     {
1006       Error(ERR_RETURN_LINE, "-");
1007       Error(ERR_RETURN, "warning: error found in config file:");
1008       Error(ERR_RETURN, "- config file: '%s'",
1009             getImageConfigFilename());
1010       Error(ERR_RETURN, "- config token: '%s'",
1011             getTokenFromImageID(i));
1012       Error(ERR_RETURN, "- image file: '%s'",
1013             src_bitmap->source_filename);
1014       Error(ERR_RETURN,
1015             "error: last animation frame (%d) out of bounds (%d, %d)",
1016             last_frame, src_x, src_y);
1017       Error(ERR_RETURN, "custom graphic rejected for this element/action");
1018       Error(ERR_RETURN_LINE, "-");
1019
1020       set_graphic_parameters(i, image->default_parameter);
1021     }
1022
1023 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1024     /* currently we need only a tile clip mask from the first frame */
1025     getGraphicSource(i, first_frame, &src_bitmap, &src_x, &src_y);
1026
1027     if (copy_clipmask_gc == None)
1028     {
1029       clip_gc_values.graphics_exposures = False;
1030       clip_gc_valuemask = GCGraphicsExposures;
1031       copy_clipmask_gc = XCreateGC(display, src_bitmap->clip_mask,
1032                                    clip_gc_valuemask, &clip_gc_values);
1033     }
1034
1035     graphic_info[i].clip_mask =
1036       XCreatePixmap(display, window->drawable, TILEX, TILEY, 1);
1037
1038     src_pixmap = src_bitmap->clip_mask;
1039     XCopyArea(display, src_pixmap, graphic_info[i].clip_mask,
1040               copy_clipmask_gc, src_x, src_y, TILEX, TILEY, 0, 0);
1041
1042     clip_gc_values.graphics_exposures = False;
1043     clip_gc_values.clip_mask = graphic_info[i].clip_mask;
1044     clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
1045     graphic_info[i].clip_gc =
1046       XCreateGC(display, window->drawable, clip_gc_valuemask, &clip_gc_values);
1047 #endif
1048   }
1049
1050 #if defined(TARGET_X11_NATIVE_PERFORMANCE_WORKAROUND)
1051   if (copy_clipmask_gc)
1052     XFreeGC(display, copy_clipmask_gc);
1053 #endif
1054
1055   clipmasks_initialized = TRUE;
1056 }
1057
1058 static void set_sound_parameters(int sound, int *parameter)
1059 {
1060   /* explicit loop mode setting in configuration overrides default value */
1061   if (parameter[SND_ARG_MODE_LOOP] != ARG_UNDEFINED_VALUE)
1062     sound_info[sound].loop = parameter[SND_ARG_MODE_LOOP];
1063 }
1064
1065 static void InitSoundInfo()
1066 {
1067   int *sound_effect_properties;
1068   int num_sounds = getSoundListSize();
1069   int i, j;
1070
1071   if (sound_info != NULL)
1072     free(sound_info);
1073
1074   sound_effect_properties = checked_calloc(num_sounds * sizeof(int));
1075   sound_info = checked_calloc(num_sounds * sizeof(struct SoundInfo));
1076
1077   /* initialize sound effect for all elements to "no sound" */
1078   for (i=0; i<MAX_NUM_ELEMENTS; i++)
1079     for (j=0; j<NUM_ACTIONS; j++)
1080       element_info[i].sound[j] = SND_UNDEFINED;
1081
1082   for (i=0; i<num_sounds; i++)
1083   {
1084     struct FileInfo *sound = getSoundListEntry(i);
1085     int len_effect_text = strlen(sound->token);
1086
1087     sound_effect_properties[i] = ACTION_OTHER;
1088     sound_info[i].loop = FALSE;
1089
1090     /* determine all loop sounds and identify certain sound classes */
1091
1092     for (j=0; element_action_info[j].suffix; j++)
1093     {
1094       int len_action_text = strlen(element_action_info[j].suffix);
1095
1096       if (len_action_text < len_effect_text &&
1097           strcmp(&sound->token[len_effect_text - len_action_text],
1098                  element_action_info[j].suffix) == 0)
1099       {
1100         sound_effect_properties[i] = element_action_info[j].value;
1101
1102         if (element_action_info[j].is_loop_sound)
1103           sound_info[i].loop = TRUE;
1104       }
1105     }
1106
1107     /* associate elements and some selected sound actions */
1108
1109     for (j=0; j<MAX_NUM_ELEMENTS; j++)
1110     {
1111       if (element_info[j].sound_class_name)
1112       {
1113         int len_class_text = strlen(element_info[j].sound_class_name);
1114
1115         if (len_class_text + 1 < len_effect_text &&
1116             strncmp(sound->token,
1117                     element_info[j].sound_class_name, len_class_text) == 0 &&
1118             sound->token[len_class_text] == '.')
1119         {
1120           int sound_action_value = sound_effect_properties[i];
1121
1122           element_info[j].sound[sound_action_value] = i;
1123         }
1124       }
1125     }
1126
1127     set_sound_parameters(i, sound->parameter);
1128   }
1129
1130   free(sound_effect_properties);
1131
1132 #if 0
1133   /* TEST ONLY */
1134   {
1135     int element = EL_SAND;
1136     int sound_action = ACTION_DIGGING;
1137     int j = 0;
1138
1139     while (element_action_info[j].suffix)
1140     {
1141       if (element_action_info[j].value == sound_action)
1142         printf("element %d, sound action '%s'  == %d\n",
1143                element, element_action_info[j].suffix,
1144                element_info_[element].sound[sound_action]);
1145       j++;
1146     }
1147   }
1148 #endif
1149 }
1150
1151 void InitElementProperties()
1152 {
1153   int i, j;
1154
1155   static int ep_amoebalive[] =
1156   {
1157     EL_AMOEBA_WET,
1158     EL_AMOEBA_DRY,
1159     EL_AMOEBA_FULL,
1160     EL_BD_AMOEBA
1161   };
1162   static int ep_amoebalive_num = SIZEOF_ARRAY_INT(ep_amoebalive);
1163
1164   static int ep_amoeboid[] =
1165   {
1166     EL_AMOEBA_DEAD,
1167     EL_AMOEBA_WET,
1168     EL_AMOEBA_DRY,
1169     EL_AMOEBA_FULL,
1170     EL_BD_AMOEBA
1171   };
1172   static int ep_amoeboid_num = SIZEOF_ARRAY_INT(ep_amoeboid);
1173
1174   static int ep_schluessel[] =
1175   {
1176     EL_KEY1,
1177     EL_KEY2,
1178     EL_KEY3,
1179     EL_KEY4,
1180     EL_EM_KEY1,
1181     EL_EM_KEY2,
1182     EL_EM_KEY3,
1183     EL_EM_KEY4
1184   };
1185   static int ep_schluessel_num = SIZEOF_ARRAY_INT(ep_schluessel);
1186
1187   static int ep_pforte[] =
1188   {
1189     EL_GATE1,
1190     EL_GATE2,
1191     EL_GATE3,
1192     EL_GATE4,
1193     EL_GATE1_GRAY,
1194     EL_GATE2_GRAY,
1195     EL_GATE3_GRAY,
1196     EL_GATE4_GRAY,
1197     EL_EM_GATE1,
1198     EL_EM_GATE2,
1199     EL_EM_GATE3,
1200     EL_EM_GATE4,
1201     EL_EM_GATE1_GRAY,
1202     EL_EM_GATE2_GRAY,
1203     EL_EM_GATE3_GRAY,
1204     EL_EM_GATE4_GRAY,
1205     EL_SWITCHGATE_OPEN,
1206     EL_SWITCHGATE_OPENING,
1207     EL_SWITCHGATE_CLOSED,
1208     EL_SWITCHGATE_CLOSING,
1209     EL_TIMEGATE_OPEN,
1210     EL_TIMEGATE_OPENING,
1211     EL_TIMEGATE_CLOSED,
1212     EL_TIMEGATE_CLOSING,
1213     EL_TUBE_ALL,
1214     EL_TUBE_VERTICAL,
1215     EL_TUBE_HORIZONTAL,
1216     EL_TUBE_VERTICAL_LEFT,
1217     EL_TUBE_VERTICAL_RIGHT,
1218     EL_TUBE_HORIZONTAL_UP,
1219     EL_TUBE_HORIZONTAL_DOWN,
1220     EL_TUBE_LEFT_UP,
1221     EL_TUBE_LEFT_DOWN,
1222     EL_TUBE_RIGHT_UP,
1223     EL_TUBE_RIGHT_DOWN
1224   };
1225   static int ep_pforte_num = SIZEOF_ARRAY_INT(ep_pforte);
1226
1227   static int ep_solid[] =
1228   {
1229     EL_STEELWALL,
1230     EL_WALL,
1231     EL_WALL_GROWING,
1232     EL_WALL_GROWING_X,
1233     EL_WALL_GROWING_Y,
1234     EL_WALL_GROWING_XY,
1235     EL_BD_WALL,
1236     EL_WALL_CRUMBLED,
1237     EL_EXIT_CLOSED,
1238     EL_EXIT_OPENING,
1239     EL_EXIT_OPEN,
1240     EL_AMOEBA_DEAD,
1241     EL_AMOEBA_WET,
1242     EL_AMOEBA_DRY,
1243     EL_AMOEBA_FULL,
1244     EL_BD_AMOEBA,
1245     EL_QUICKSAND_FULL,
1246     EL_QUICKSAND_EMPTY,
1247     EL_QUICKSAND_FILLING,
1248     EL_QUICKSAND_EMPTYING,
1249     EL_MAGIC_WALL,
1250     EL_MAGIC_WALL_ACTIVE,
1251     EL_MAGIC_WALL_EMPTYING,
1252     EL_MAGIC_WALL_FILLING,
1253     EL_MAGIC_WALL_FULL,
1254     EL_MAGIC_WALL_DEAD,
1255     EL_BD_MAGIC_WALL,
1256     EL_BD_MAGIC_WALL_ACTIVE,
1257     EL_BD_MAGIC_WALL_EMPTYING,
1258     EL_BD_MAGIC_WALL_FULL,
1259     EL_BD_MAGIC_WALL_FILLING,
1260     EL_BD_MAGIC_WALL_DEAD,
1261     EL_GAMEOFLIFE,
1262     EL_BIOMAZE,
1263     EL_ACIDPOOL_TOPLEFT,
1264     EL_ACIDPOOL_TOPRIGHT,
1265     EL_ACIDPOOL_BOTTOMLEFT,
1266     EL_ACIDPOOL_BOTTOM,
1267     EL_ACIDPOOL_BOTTOMRIGHT,
1268     EL_SP_CHIP_SINGLE,
1269     EL_SP_CHIP_LEFT,
1270     EL_SP_CHIP_RIGHT,
1271     EL_SP_CHIP_UPPER,
1272     EL_SP_CHIP_LOWER,
1273     EL_SP_HARD_GRAY,
1274     EL_SP_HARD_GREEN,
1275     EL_SP_HARD_BLUE,
1276     EL_SP_HARD_RED,
1277     EL_SP_HARD_YELLOW,
1278     EL_SP_HARD_BASE1,
1279     EL_SP_HARD_BASE2,
1280     EL_SP_HARD_BASE3,
1281     EL_SP_HARD_BASE4,
1282     EL_SP_HARD_BASE5,
1283     EL_SP_HARD_BASE6,
1284     EL_SP_TERMINAL,
1285     EL_SP_TERMINAL_ACTIVE,
1286     EL_SP_EXIT_CLOSED,
1287     EL_SP_EXIT_OPEN,
1288     EL_INVISIBLE_STEELWALL,
1289     EL_INVISIBLE_STEELWALL_ACTIVE,
1290     EL_INVISIBLE_WALL,
1291     EL_INVISIBLE_WALL_ACTIVE,
1292     EL_CONVEYOR_BELT1_SWITCH_LEFT,
1293     EL_CONVEYOR_BELT1_SWITCH_MIDDLE,
1294     EL_CONVEYOR_BELT1_SWITCH_RIGHT,
1295     EL_CONVEYOR_BELT2_SWITCH_LEFT,
1296     EL_CONVEYOR_BELT2_SWITCH_MIDDLE,
1297     EL_CONVEYOR_BELT2_SWITCH_RIGHT,
1298     EL_CONVEYOR_BELT3_SWITCH_LEFT,
1299     EL_CONVEYOR_BELT3_SWITCH_MIDDLE,
1300     EL_CONVEYOR_BELT3_SWITCH_RIGHT,
1301     EL_CONVEYOR_BELT4_SWITCH_LEFT,
1302     EL_CONVEYOR_BELT4_SWITCH_MIDDLE,
1303     EL_CONVEYOR_BELT4_SWITCH_RIGHT,
1304     EL_SWITCHGATE_SWITCH_UP,
1305     EL_SWITCHGATE_SWITCH_DOWN,
1306     EL_LIGHT_SWITCH,
1307     EL_LIGHT_SWITCH_ACTIVE,
1308     EL_TIMEGATE_SWITCH,
1309     EL_TIMEGATE_SWITCH_ACTIVE,
1310     EL_SIGN_EXCLAMATION,
1311     EL_SIGN_RADIOACTIVITY,
1312     EL_SIGN_STOP,
1313     EL_SIGN_WHEELCHAIR,
1314     EL_SIGN_PARKING,
1315     EL_SIGN_ONEWAY,
1316     EL_SIGN_HEART,
1317     EL_SIGN_TRIANGLE,
1318     EL_SIGN_ROUND,
1319     EL_SIGN_EXIT,
1320     EL_SIGN_YINYANG,
1321     EL_SIGN_OTHER,
1322     EL_STEELWALL_SLANTED,
1323     EL_EMC_STEELWALL1,
1324     EL_EMC_STEELWALL2,
1325     EL_EMC_STEELWALL3,
1326     EL_EMC_STEELWALL4,
1327     EL_EMC_WALL_PILLAR_UPPER,
1328     EL_EMC_WALL_PILLAR_MIDDLE,
1329     EL_EMC_WALL_PILLAR_LOWER,
1330     EL_EMC_WALL4,
1331     EL_EMC_WALL5,
1332     EL_EMC_WALL6,
1333     EL_EMC_WALL7,
1334     EL_EMC_WALL8,
1335     EL_CRYSTAL,
1336     EL_WALL_PEARL,
1337     EL_WALL_CRYSTAL,
1338     EL_GATE1,
1339     EL_GATE2,
1340     EL_GATE3,
1341     EL_GATE4,
1342     EL_GATE1_GRAY,
1343     EL_GATE2_GRAY,
1344     EL_GATE3_GRAY,
1345     EL_GATE4_GRAY,
1346     EL_EM_GATE1,
1347     EL_EM_GATE2,
1348     EL_EM_GATE3,
1349     EL_EM_GATE4,
1350     EL_EM_GATE1_GRAY,
1351     EL_EM_GATE2_GRAY,
1352     EL_EM_GATE3_GRAY,
1353     EL_EM_GATE4_GRAY,
1354     EL_SWITCHGATE_OPEN,
1355     EL_SWITCHGATE_OPENING,
1356     EL_SWITCHGATE_CLOSED,
1357     EL_SWITCHGATE_CLOSING,
1358     EL_TIMEGATE_OPEN,
1359     EL_TIMEGATE_OPENING,
1360     EL_TIMEGATE_CLOSED,
1361     EL_TIMEGATE_CLOSING,
1362     EL_TUBE_ALL,
1363     EL_TUBE_VERTICAL,
1364     EL_TUBE_HORIZONTAL,
1365     EL_TUBE_VERTICAL_LEFT,
1366     EL_TUBE_VERTICAL_RIGHT,
1367     EL_TUBE_HORIZONTAL_UP,
1368     EL_TUBE_HORIZONTAL_DOWN,
1369     EL_TUBE_LEFT_UP,
1370     EL_TUBE_LEFT_DOWN,
1371     EL_TUBE_RIGHT_UP,
1372     EL_TUBE_RIGHT_DOWN
1373   };
1374   static int ep_solid_num = SIZEOF_ARRAY_INT(ep_solid);
1375
1376   static int ep_massive[] =
1377   {
1378     EL_STEELWALL,
1379     EL_ACID,
1380     EL_ACIDPOOL_TOPLEFT,
1381     EL_ACIDPOOL_TOPRIGHT,
1382     EL_ACIDPOOL_BOTTOMLEFT,
1383     EL_ACIDPOOL_BOTTOM,
1384     EL_ACIDPOOL_BOTTOMRIGHT,
1385     EL_SP_HARD_GRAY,
1386     EL_SP_HARD_GREEN,
1387     EL_SP_HARD_BLUE,
1388     EL_SP_HARD_RED,
1389     EL_SP_HARD_YELLOW,
1390     EL_SP_HARD_BASE1,
1391     EL_SP_HARD_BASE2,
1392     EL_SP_HARD_BASE3,
1393     EL_SP_HARD_BASE4,
1394     EL_SP_HARD_BASE5,
1395     EL_SP_HARD_BASE6,
1396     EL_INVISIBLE_STEELWALL,
1397     EL_INVISIBLE_STEELWALL_ACTIVE,
1398     EL_CONVEYOR_BELT1_SWITCH_LEFT,
1399     EL_CONVEYOR_BELT1_SWITCH_MIDDLE,
1400     EL_CONVEYOR_BELT1_SWITCH_RIGHT,
1401     EL_CONVEYOR_BELT2_SWITCH_LEFT,
1402     EL_CONVEYOR_BELT2_SWITCH_MIDDLE,
1403     EL_CONVEYOR_BELT2_SWITCH_RIGHT,
1404     EL_CONVEYOR_BELT3_SWITCH_LEFT,
1405     EL_CONVEYOR_BELT3_SWITCH_MIDDLE,
1406     EL_CONVEYOR_BELT3_SWITCH_RIGHT,
1407     EL_CONVEYOR_BELT4_SWITCH_LEFT,
1408     EL_CONVEYOR_BELT4_SWITCH_MIDDLE,
1409     EL_CONVEYOR_BELT4_SWITCH_RIGHT,
1410     EL_LIGHT_SWITCH,
1411     EL_LIGHT_SWITCH_ACTIVE,
1412     EL_SIGN_EXCLAMATION,
1413     EL_SIGN_RADIOACTIVITY,
1414     EL_SIGN_STOP,
1415     EL_SIGN_WHEELCHAIR,
1416     EL_SIGN_PARKING,
1417     EL_SIGN_ONEWAY,
1418     EL_SIGN_HEART,
1419     EL_SIGN_TRIANGLE,
1420     EL_SIGN_ROUND,
1421     EL_SIGN_EXIT,
1422     EL_SIGN_YINYANG,
1423     EL_SIGN_OTHER,
1424     EL_STEELWALL_SLANTED,
1425     EL_EMC_STEELWALL1,
1426     EL_EMC_STEELWALL2,
1427     EL_EMC_STEELWALL3,
1428     EL_EMC_STEELWALL4,
1429     EL_CRYSTAL,
1430     EL_GATE1,
1431     EL_GATE2,
1432     EL_GATE3,
1433     EL_GATE4,
1434     EL_GATE1_GRAY,
1435     EL_GATE2_GRAY,
1436     EL_GATE3_GRAY,
1437     EL_GATE4_GRAY,
1438     EL_EM_GATE1,
1439     EL_EM_GATE2,
1440     EL_EM_GATE3,
1441     EL_EM_GATE4,
1442     EL_EM_GATE1_GRAY,
1443     EL_EM_GATE2_GRAY,
1444     EL_EM_GATE3_GRAY,
1445     EL_EM_GATE4_GRAY,
1446     EL_SWITCHGATE_OPEN,
1447     EL_SWITCHGATE_OPENING,
1448     EL_SWITCHGATE_CLOSED,
1449     EL_SWITCHGATE_CLOSING,
1450     EL_TIMEGATE_OPEN,
1451     EL_TIMEGATE_OPENING,
1452     EL_TIMEGATE_CLOSED,
1453     EL_TIMEGATE_CLOSING,
1454     EL_TUBE_ALL,
1455     EL_TUBE_VERTICAL,
1456     EL_TUBE_HORIZONTAL,
1457     EL_TUBE_VERTICAL_LEFT,
1458     EL_TUBE_VERTICAL_RIGHT,
1459     EL_TUBE_HORIZONTAL_UP,
1460     EL_TUBE_HORIZONTAL_DOWN,
1461     EL_TUBE_LEFT_UP,
1462     EL_TUBE_LEFT_DOWN,
1463     EL_TUBE_RIGHT_UP,
1464     EL_TUBE_RIGHT_DOWN
1465   };
1466   static int ep_massive_num = SIZEOF_ARRAY_INT(ep_massive);
1467
1468   static int ep_slippery[] =
1469   {
1470     EL_WALL_CRUMBLED,
1471     EL_BD_WALL,
1472     EL_ROCK,
1473     EL_BD_ROCK,
1474     EL_EMERALD,
1475     EL_BD_DIAMOND,
1476     EL_EMERALD_YELLOW,
1477     EL_EMERALD_RED,
1478     EL_EMERALD_PURPLE,
1479     EL_DIAMOND,
1480     EL_BOMB,
1481     EL_NUT,
1482     EL_ROBOT_WHEEL_ACTIVE,
1483     EL_ROBOT_WHEEL,
1484     EL_TIME_ORB_FULL,
1485     EL_TIME_ORB_EMPTY,
1486     EL_LAMP_ACTIVE,
1487     EL_LAMP,
1488     EL_ACIDPOOL_TOPLEFT,
1489     EL_ACIDPOOL_TOPRIGHT,
1490     EL_SATELLITE,
1491     EL_SP_ZONK,
1492     EL_SP_INFOTRON,
1493     EL_SP_CHIP_SINGLE,
1494     EL_SP_CHIP_LEFT,
1495     EL_SP_CHIP_RIGHT,
1496     EL_SP_CHIP_UPPER,
1497     EL_SP_CHIP_LOWER,
1498     EL_SPEED_PILL,
1499     EL_STEELWALL_SLANTED,
1500     EL_PEARL,
1501     EL_CRYSTAL
1502   };
1503   static int ep_slippery_num = SIZEOF_ARRAY_INT(ep_slippery);
1504
1505   static int ep_enemy[] =
1506   {
1507     EL_BUG,
1508     EL_SPACESHIP,
1509     EL_BD_BUTTERFLY,
1510     EL_BD_FIREFLY,
1511     EL_YAMYAM,
1512     EL_DARK_YAMYAM,
1513     EL_ROBOT,
1514     EL_PACMAN,
1515     EL_SP_SNIKSNAK,
1516     EL_SP_ELECTRON
1517   };
1518   static int ep_enemy_num = SIZEOF_ARRAY_INT(ep_enemy);
1519
1520   static int ep_mauer[] =
1521   {
1522     EL_STEELWALL,
1523     EL_GATE1,
1524     EL_GATE2,
1525     EL_GATE3,
1526     EL_GATE4,
1527     EL_GATE1_GRAY,
1528     EL_GATE2_GRAY,
1529     EL_GATE3_GRAY,
1530     EL_GATE4_GRAY,
1531     EL_EM_GATE1,
1532     EL_EM_GATE2,
1533     EL_EM_GATE3,
1534     EL_EM_GATE4,
1535     EL_EM_GATE1_GRAY,
1536     EL_EM_GATE2_GRAY,
1537     EL_EM_GATE3_GRAY,
1538     EL_EM_GATE4_GRAY,
1539     EL_EXIT_CLOSED,
1540     EL_EXIT_OPENING,
1541     EL_EXIT_OPEN,
1542     EL_WALL,
1543     EL_WALL_CRUMBLED,
1544     EL_WALL_GROWING,
1545     EL_WALL_GROWING_X,
1546     EL_WALL_GROWING_Y,
1547     EL_WALL_GROWING_XY,
1548     EL_WALL_GROWING_ACTIVE,
1549     EL_BD_WALL,
1550     EL_SP_CHIP_SINGLE,
1551     EL_SP_CHIP_LEFT,
1552     EL_SP_CHIP_RIGHT,
1553     EL_SP_CHIP_UPPER,
1554     EL_SP_CHIP_LOWER,
1555     EL_SP_HARD_GRAY,
1556     EL_SP_HARD_GREEN,
1557     EL_SP_HARD_BLUE,
1558     EL_SP_HARD_RED,
1559     EL_SP_HARD_YELLOW,
1560     EL_SP_HARD_BASE1,
1561     EL_SP_HARD_BASE2,
1562     EL_SP_HARD_BASE3,
1563     EL_SP_HARD_BASE4,
1564     EL_SP_HARD_BASE5,
1565     EL_SP_HARD_BASE6,
1566     EL_SP_TERMINAL,
1567     EL_SP_TERMINAL_ACTIVE,
1568     EL_SP_EXIT_CLOSED,
1569     EL_SP_EXIT_OPEN,
1570     EL_INVISIBLE_STEELWALL,
1571     EL_INVISIBLE_STEELWALL_ACTIVE,
1572     EL_INVISIBLE_WALL,
1573     EL_INVISIBLE_WALL_ACTIVE,
1574     EL_STEELWALL_SLANTED,
1575     EL_EMC_STEELWALL1,
1576     EL_EMC_STEELWALL2,
1577     EL_EMC_STEELWALL3,
1578     EL_EMC_STEELWALL4,
1579     EL_EMC_WALL_PILLAR_UPPER,
1580     EL_EMC_WALL_PILLAR_MIDDLE,
1581     EL_EMC_WALL_PILLAR_LOWER,
1582     EL_EMC_WALL4,
1583     EL_EMC_WALL5,
1584     EL_EMC_WALL6,
1585     EL_EMC_WALL7,
1586     EL_EMC_WALL8
1587   };
1588   static int ep_mauer_num = SIZEOF_ARRAY_INT(ep_mauer);
1589
1590   static int ep_can_fall[] =
1591   {
1592     EL_ROCK,
1593     EL_BD_ROCK,
1594     EL_EMERALD,
1595     EL_BD_DIAMOND,
1596     EL_EMERALD_YELLOW,
1597     EL_EMERALD_RED,
1598     EL_EMERALD_PURPLE,
1599     EL_DIAMOND,
1600     EL_BOMB,
1601     EL_NUT,
1602     EL_AMOEBA_DROP,
1603     EL_QUICKSAND_FULL,
1604     EL_MAGIC_WALL_FULL,
1605     EL_BD_MAGIC_WALL_FULL,
1606     EL_TIME_ORB_FULL,
1607     EL_TIME_ORB_EMPTY,
1608     EL_SP_ZONK,
1609     EL_SP_INFOTRON,
1610     EL_SP_DISK_ORANGE,
1611     EL_PEARL,
1612     EL_CRYSTAL,
1613     EL_SPRING,
1614     EL_DX_SUPABOMB
1615   };
1616   static int ep_can_fall_num = SIZEOF_ARRAY_INT(ep_can_fall);
1617
1618   static int ep_can_smash[] =
1619   {
1620     EL_ROCK,
1621     EL_BD_ROCK,
1622     EL_EMERALD,
1623     EL_BD_DIAMOND,
1624     EL_EMERALD_YELLOW,
1625     EL_EMERALD_RED,
1626     EL_EMERALD_PURPLE,
1627     EL_DIAMOND,
1628     EL_KEY1,
1629     EL_KEY2,
1630     EL_KEY3,
1631     EL_KEY4,
1632     EL_EM_KEY1,
1633     EL_EM_KEY2,
1634     EL_EM_KEY3,
1635     EL_EM_KEY4,
1636     EL_BOMB,
1637     EL_NUT,
1638     EL_AMOEBA_DROP,
1639     EL_TIME_ORB_FULL,
1640     EL_TIME_ORB_EMPTY,
1641     EL_SP_ZONK,
1642     EL_SP_INFOTRON,
1643     EL_SP_DISK_ORANGE,
1644     EL_PEARL,
1645     EL_CRYSTAL,
1646     EL_SPRING,
1647     EL_DX_SUPABOMB
1648   };
1649   static int ep_can_smash_num = SIZEOF_ARRAY_INT(ep_can_smash);
1650
1651   static int ep_can_change[] =
1652   {
1653     EL_ROCK,
1654     EL_BD_ROCK,
1655     EL_EMERALD,
1656     EL_BD_DIAMOND,
1657     EL_EMERALD_YELLOW,
1658     EL_EMERALD_RED,
1659     EL_EMERALD_PURPLE,
1660     EL_DIAMOND
1661   };
1662   static int ep_can_change_num = SIZEOF_ARRAY_INT(ep_can_change);
1663
1664   static int ep_can_move[] =
1665   {
1666     EL_BUG,
1667     EL_SPACESHIP,
1668     EL_BD_BUTTERFLY,
1669     EL_BD_FIREFLY,
1670     EL_YAMYAM,
1671     EL_DARK_YAMYAM,
1672     EL_ROBOT,
1673     EL_PACMAN,
1674     EL_MOLE,
1675     EL_PENGUIN,
1676     EL_PIG,
1677     EL_DRAGON,
1678     EL_SATELLITE,
1679     EL_SP_SNIKSNAK,
1680     EL_SP_ELECTRON,
1681     EL_BALLOON,
1682     EL_SPRING
1683   };
1684   static int ep_can_move_num = SIZEOF_ARRAY_INT(ep_can_move);
1685
1686   static int ep_could_move[] =
1687   {
1688     EL_BUG_RIGHT,
1689     EL_BUG_UP,
1690     EL_BUG_LEFT,
1691     EL_BUG_DOWN,
1692     EL_SPACESHIP_RIGHT,
1693     EL_SPACESHIP_UP,
1694     EL_SPACESHIP_LEFT,
1695     EL_SPACESHIP_DOWN,
1696     EL_BD_BUTTERFLY_RIGHT,
1697     EL_BD_BUTTERFLY_UP,
1698     EL_BD_BUTTERFLY_LEFT,
1699     EL_BD_BUTTERFLY_DOWN,
1700     EL_BD_FIREFLY_RIGHT,
1701     EL_BD_FIREFLY_UP,
1702     EL_BD_FIREFLY_LEFT,
1703     EL_BD_FIREFLY_DOWN,
1704     EL_PACMAN_RIGHT,
1705     EL_PACMAN_UP,
1706     EL_PACMAN_LEFT,
1707     EL_PACMAN_DOWN
1708   };
1709   static int ep_could_move_num = SIZEOF_ARRAY_INT(ep_could_move);
1710
1711   static int ep_dont_touch[] =
1712   {
1713     EL_BUG,
1714     EL_SPACESHIP,
1715     EL_BD_BUTTERFLY,
1716     EL_BD_FIREFLY
1717   };
1718   static int ep_dont_touch_num = SIZEOF_ARRAY_INT(ep_dont_touch);
1719
1720   static int ep_dont_go_to[] =
1721   {
1722     EL_BUG,
1723     EL_SPACESHIP,
1724     EL_BD_BUTTERFLY,
1725     EL_BD_FIREFLY,
1726     EL_YAMYAM,
1727     EL_DARK_YAMYAM,
1728     EL_ROBOT,
1729     EL_PACMAN,
1730     EL_AMOEBA_DROP,
1731     EL_ACID,
1732     EL_SP_SNIKSNAK,
1733     EL_SP_ELECTRON,
1734     EL_SP_BUGGY_BASE_ACTIVE,
1735     EL_TRAP_ACTIVE,
1736     EL_LANDMINE
1737   };
1738   static int ep_dont_go_to_num = SIZEOF_ARRAY_INT(ep_dont_go_to);
1739
1740   static int ep_mampf2[] =
1741   {
1742     EL_SAND,
1743     EL_BUG,
1744     EL_SPACESHIP,
1745     EL_BD_BUTTERFLY,
1746     EL_BD_FIREFLY,
1747     EL_YAMYAM,
1748     EL_ROBOT,
1749     EL_PACMAN,
1750     EL_AMOEBA_DROP,
1751     EL_AMOEBA_DEAD,
1752     EL_AMOEBA_WET,
1753     EL_AMOEBA_DRY,
1754     EL_AMOEBA_FULL,
1755     EL_BD_AMOEBA,
1756     EL_EMERALD,
1757     EL_BD_DIAMOND,
1758     EL_EMERALD_YELLOW,
1759     EL_EMERALD_RED,
1760     EL_EMERALD_PURPLE,
1761     EL_DIAMOND,
1762     EL_PEARL,
1763     EL_CRYSTAL
1764   };
1765   static int ep_mampf2_num = SIZEOF_ARRAY_INT(ep_mampf2);
1766
1767   static int ep_bd_element[] =
1768   {
1769     EL_EMPTY,
1770     EL_SAND,
1771     EL_WALL_CRUMBLED,
1772     EL_BD_WALL,
1773     EL_ROCK,
1774     EL_BD_ROCK,
1775     EL_BD_DIAMOND,
1776     EL_BD_MAGIC_WALL,
1777     EL_EXIT_CLOSED,
1778     EL_EXIT_OPEN,
1779     EL_STEELWALL,
1780     EL_PLAYER1,
1781     EL_BD_FIREFLY,
1782     EL_BD_FIREFLY_1,
1783     EL_BD_FIREFLY_2,
1784     EL_BD_FIREFLY_3,
1785     EL_BD_FIREFLY_4,
1786     EL_BD_BUTTERFLY,
1787     EL_BD_BUTTERFLY_1,
1788     EL_BD_BUTTERFLY_2,
1789     EL_BD_BUTTERFLY_3,
1790     EL_BD_BUTTERFLY_4,
1791     EL_BD_AMOEBA,
1792     EL_CHAR_QUESTION
1793   };
1794   static int ep_bd_element_num = SIZEOF_ARRAY_INT(ep_bd_element);
1795
1796   static int ep_sb_element[] =
1797   {
1798     EL_EMPTY,
1799     EL_STEELWALL,
1800     EL_SOKOBAN_OBJECT,
1801     EL_SOKOBAN_FIELD_EMPTY,
1802     EL_SOKOBAN_FIELD_FULL,
1803     EL_PLAYER1,
1804     EL_INVISIBLE_STEELWALL
1805   };
1806   static int ep_sb_element_num = SIZEOF_ARRAY_INT(ep_sb_element);
1807
1808   static int ep_gem[] =
1809   {
1810     EL_EMERALD,
1811     EL_BD_DIAMOND,
1812     EL_EMERALD_YELLOW,
1813     EL_EMERALD_RED,
1814     EL_EMERALD_PURPLE,
1815     EL_DIAMOND
1816   };
1817   static int ep_gem_num = SIZEOF_ARRAY_INT(ep_gem);
1818
1819   static int ep_inactive[] =
1820   {
1821     EL_EMPTY,
1822     EL_SAND,
1823     EL_WALL,
1824     EL_BD_WALL,
1825     EL_WALL_CRUMBLED,
1826     EL_STEELWALL,
1827     EL_AMOEBA_DEAD,
1828     EL_QUICKSAND_EMPTY,
1829     EL_STONEBLOCK,
1830     EL_ROBOT_WHEEL,
1831     EL_KEY1,
1832     EL_KEY2,
1833     EL_KEY3,
1834     EL_KEY4,
1835     EL_EM_KEY1,
1836     EL_EM_KEY2,
1837     EL_EM_KEY3,
1838     EL_EM_KEY4,
1839     EL_GATE1,
1840     EL_GATE2,
1841     EL_GATE3,
1842     EL_GATE4,
1843     EL_GATE1_GRAY,
1844     EL_GATE2_GRAY,
1845     EL_GATE3_GRAY,
1846     EL_GATE4_GRAY,
1847     EL_EM_GATE1,
1848     EL_EM_GATE2,
1849     EL_EM_GATE3,
1850     EL_EM_GATE4,
1851     EL_EM_GATE1_GRAY,
1852     EL_EM_GATE2_GRAY,
1853     EL_EM_GATE3_GRAY,
1854     EL_EM_GATE4_GRAY,
1855     EL_DYNAMITE,
1856     EL_INVISIBLE_STEELWALL,
1857     EL_INVISIBLE_WALL,
1858     EL_INVISIBLE_SAND,
1859     EL_LAMP,
1860     EL_LAMP_ACTIVE,
1861     EL_WALL_EMERALD,
1862     EL_WALL_DIAMOND,
1863     EL_WALL_BD_DIAMOND,
1864     EL_WALL_EMERALD_YELLOW,
1865     EL_DYNABOMB_NR,
1866     EL_DYNABOMB_SZ,
1867     EL_DYNABOMB_XL,
1868     EL_SOKOBAN_OBJECT,
1869     EL_SOKOBAN_FIELD_EMPTY,
1870     EL_SOKOBAN_FIELD_FULL,
1871     EL_WALL_EMERALD_RED,
1872     EL_WALL_EMERALD_PURPLE,
1873     EL_ACIDPOOL_TOPLEFT,
1874     EL_ACIDPOOL_TOPRIGHT,
1875     EL_ACIDPOOL_BOTTOMLEFT,
1876     EL_ACIDPOOL_BOTTOM,
1877     EL_ACIDPOOL_BOTTOMRIGHT,
1878     EL_MAGIC_WALL,
1879     EL_MAGIC_WALL_DEAD,
1880     EL_BD_MAGIC_WALL,
1881     EL_BD_MAGIC_WALL_DEAD,
1882     EL_AMOEBA_TO_DIAMOND,
1883     EL_BLOCKED,
1884     EL_SP_EMPTY,
1885     EL_SP_BASE,
1886     EL_SP_PORT1_RIGHT,
1887     EL_SP_PORT1_DOWN,
1888     EL_SP_PORT1_LEFT,
1889     EL_SP_PORT1_UP,
1890     EL_SP_PORT2_RIGHT,
1891     EL_SP_PORT2_DOWN,
1892     EL_SP_PORT2_LEFT,
1893     EL_SP_PORT2_UP,
1894     EL_SP_PORT_X,
1895     EL_SP_PORT_Y,
1896     EL_SP_PORT_XY,
1897     EL_SP_DISK_RED,
1898     EL_SP_DISK_YELLOW,
1899     EL_SP_CHIP_SINGLE,
1900     EL_SP_CHIP_LEFT,
1901     EL_SP_CHIP_RIGHT,
1902     EL_SP_CHIP_UPPER,
1903     EL_SP_CHIP_LOWER,
1904     EL_SP_HARD_GRAY,
1905     EL_SP_HARD_GREEN,
1906     EL_SP_HARD_BLUE,
1907     EL_SP_HARD_RED,
1908     EL_SP_HARD_YELLOW,
1909     EL_SP_HARD_BASE1,
1910     EL_SP_HARD_BASE2,
1911     EL_SP_HARD_BASE3,
1912     EL_SP_HARD_BASE4,
1913     EL_SP_HARD_BASE5,
1914     EL_SP_HARD_BASE6,
1915     EL_CONVEYOR_BELT1_SWITCH_LEFT,
1916     EL_CONVEYOR_BELT1_SWITCH_MIDDLE,
1917     EL_CONVEYOR_BELT1_SWITCH_RIGHT,
1918     EL_CONVEYOR_BELT2_SWITCH_LEFT,
1919     EL_CONVEYOR_BELT2_SWITCH_MIDDLE,
1920     EL_CONVEYOR_BELT2_SWITCH_RIGHT,
1921     EL_CONVEYOR_BELT3_SWITCH_LEFT,
1922     EL_CONVEYOR_BELT3_SWITCH_MIDDLE,
1923     EL_CONVEYOR_BELT3_SWITCH_RIGHT,
1924     EL_CONVEYOR_BELT4_SWITCH_LEFT,
1925     EL_CONVEYOR_BELT4_SWITCH_MIDDLE,
1926     EL_CONVEYOR_BELT4_SWITCH_RIGHT,
1927     EL_SIGN_EXCLAMATION,
1928     EL_SIGN_RADIOACTIVITY,
1929     EL_SIGN_STOP,
1930     EL_SIGN_WHEELCHAIR,
1931     EL_SIGN_PARKING,
1932     EL_SIGN_ONEWAY,
1933     EL_SIGN_HEART,
1934     EL_SIGN_TRIANGLE,
1935     EL_SIGN_ROUND,
1936     EL_SIGN_EXIT,
1937     EL_SIGN_YINYANG,
1938     EL_SIGN_OTHER,
1939     EL_STEELWALL_SLANTED,
1940     EL_EMC_STEELWALL1,
1941     EL_EMC_STEELWALL2,
1942     EL_EMC_STEELWALL3,
1943     EL_EMC_STEELWALL4,
1944     EL_EMC_WALL_PILLAR_UPPER,
1945     EL_EMC_WALL_PILLAR_MIDDLE,
1946     EL_EMC_WALL_PILLAR_LOWER,
1947     EL_EMC_WALL4,
1948     EL_EMC_WALL5,
1949     EL_EMC_WALL6,
1950     EL_EMC_WALL7,
1951     EL_EMC_WALL8
1952   };
1953   static int ep_inactive_num = SIZEOF_ARRAY_INT(ep_inactive);
1954
1955   static int ep_explosive[] =
1956   {
1957     EL_BOMB,
1958     EL_DYNAMITE_ACTIVE,
1959     EL_DYNAMITE,
1960     EL_DYNABOMB_PLAYER1_ACTIVE,
1961     EL_DYNABOMB_PLAYER2_ACTIVE,
1962     EL_DYNABOMB_PLAYER3_ACTIVE,
1963     EL_DYNABOMB_PLAYER4_ACTIVE,
1964     EL_DYNABOMB_NR,
1965     EL_DYNABOMB_SZ,
1966     EL_DYNABOMB_XL,
1967     EL_BUG,
1968     EL_MOLE,
1969     EL_PENGUIN,
1970     EL_PIG,
1971     EL_DRAGON,
1972     EL_SATELLITE,
1973     EL_SP_DISK_RED,
1974     EL_SP_DISK_ORANGE,
1975     EL_SP_DISK_YELLOW,
1976     EL_SP_SNIKSNAK,
1977     EL_SP_ELECTRON,
1978     EL_DX_SUPABOMB
1979   };
1980   static int ep_explosive_num = SIZEOF_ARRAY_INT(ep_explosive);
1981
1982   static int ep_mampf3[] =
1983   {
1984     EL_EMERALD,
1985     EL_BD_DIAMOND,
1986     EL_EMERALD_YELLOW,
1987     EL_EMERALD_RED,
1988     EL_EMERALD_PURPLE,
1989     EL_DIAMOND,
1990     EL_PEARL,
1991     EL_CRYSTAL
1992   };
1993   static int ep_mampf3_num = SIZEOF_ARRAY_INT(ep_mampf3);
1994
1995   static int ep_pushable[] =
1996   {
1997     EL_ROCK,
1998     EL_BD_ROCK,
1999     EL_BOMB,
2000     EL_NUT,
2001     EL_TIME_ORB_EMPTY,
2002     EL_SOKOBAN_FIELD_FULL,
2003     EL_SOKOBAN_OBJECT,
2004     EL_SATELLITE,
2005     EL_SP_ZONK,
2006     EL_SP_DISK_ORANGE,
2007     EL_SP_DISK_YELLOW,
2008     EL_BALLOON,
2009     EL_SPRING,
2010     EL_DX_SUPABOMB
2011   };
2012   static int ep_pushable_num = SIZEOF_ARRAY_INT(ep_pushable);
2013
2014   static int ep_player[] =
2015   {
2016     EL_PLAYER1,
2017     EL_PLAYER2,
2018     EL_PLAYER3,
2019     EL_PLAYER4
2020   };
2021   static int ep_player_num = SIZEOF_ARRAY_INT(ep_player);
2022
2023   static int ep_has_content[] =
2024   {
2025     EL_YAMYAM,
2026     EL_AMOEBA_WET,
2027     EL_AMOEBA_DRY,
2028     EL_AMOEBA_FULL,
2029     EL_BD_AMOEBA
2030   };
2031   static int ep_has_content_num = SIZEOF_ARRAY_INT(ep_has_content);
2032
2033   static int ep_eatable[] =
2034   {
2035     EL_SAND,
2036     EL_SP_BASE,
2037     EL_SP_BUGGY_BASE,
2038     EL_SP_BUGGY_BASE_ACTIVATING,
2039     EL_TRAP,
2040     EL_INVISIBLE_SAND,
2041     EL_INVISIBLE_SAND_ACTIVE
2042   };
2043   static int ep_eatable_num = SIZEOF_ARRAY_INT(ep_eatable);
2044
2045   static int ep_sp_element[] =
2046   {
2047     EL_SP_EMPTY,
2048     EL_SP_ZONK,
2049     EL_SP_BASE,
2050     EL_SP_MURPHY,
2051     EL_SP_INFOTRON,
2052     EL_SP_CHIP_SINGLE,
2053     EL_SP_HARD_GRAY,
2054     EL_SP_EXIT_CLOSED,
2055     EL_SP_EXIT_OPEN,
2056     EL_SP_DISK_ORANGE,
2057     EL_SP_PORT1_RIGHT,
2058     EL_SP_PORT1_DOWN,
2059     EL_SP_PORT1_LEFT,
2060     EL_SP_PORT1_UP,
2061     EL_SP_PORT2_RIGHT,
2062     EL_SP_PORT2_DOWN,
2063     EL_SP_PORT2_LEFT,
2064     EL_SP_PORT2_UP,
2065     EL_SP_SNIKSNAK,
2066     EL_SP_DISK_YELLOW,
2067     EL_SP_TERMINAL,
2068     EL_SP_DISK_RED,
2069     EL_SP_PORT_Y,
2070     EL_SP_PORT_X,
2071     EL_SP_PORT_XY,
2072     EL_SP_ELECTRON,
2073     EL_SP_BUGGY_BASE,
2074     EL_SP_CHIP_LEFT,
2075     EL_SP_CHIP_RIGHT,
2076     EL_SP_HARD_BASE1,
2077     EL_SP_HARD_GREEN,
2078     EL_SP_HARD_BLUE,
2079     EL_SP_HARD_RED,
2080     EL_SP_HARD_YELLOW,
2081     EL_SP_HARD_BASE2,
2082     EL_SP_HARD_BASE3,
2083     EL_SP_HARD_BASE4,
2084     EL_SP_HARD_BASE5,
2085     EL_SP_HARD_BASE6,
2086     EL_SP_CHIP_UPPER,
2087     EL_SP_CHIP_LOWER,
2088     /* additional elements that appeared in newer Supaplex levels */
2089     EL_INVISIBLE_WALL,
2090     /* more than one murphy in a level results in an inactive clone */
2091     EL_SP_MURPHY_CLONE
2092   };
2093   static int ep_sp_element_num = SIZEOF_ARRAY_INT(ep_sp_element);
2094
2095   static int ep_quick_gate[] =
2096   {
2097     EL_EM_GATE1,
2098     EL_EM_GATE2,
2099     EL_EM_GATE3,
2100     EL_EM_GATE4,
2101     EL_EM_GATE1_GRAY,
2102     EL_EM_GATE2_GRAY,
2103     EL_EM_GATE3_GRAY,
2104     EL_EM_GATE4_GRAY,
2105     EL_SP_PORT1_LEFT,
2106     EL_SP_PORT2_LEFT,
2107     EL_SP_PORT1_RIGHT,
2108     EL_SP_PORT2_RIGHT,
2109     EL_SP_PORT1_UP,
2110     EL_SP_PORT2_UP,
2111     EL_SP_PORT1_DOWN,
2112     EL_SP_PORT2_DOWN,
2113     EL_SP_PORT_X,
2114     EL_SP_PORT_Y,
2115     EL_SP_PORT_XY,
2116     EL_SWITCHGATE_OPEN,
2117     EL_TIMEGATE_OPEN
2118   };
2119   static int ep_quick_gate_num = SIZEOF_ARRAY_INT(ep_quick_gate);
2120
2121   static int ep_over_player[] =
2122   {
2123     EL_SP_PORT1_LEFT,
2124     EL_SP_PORT2_LEFT,
2125     EL_SP_PORT1_RIGHT,
2126     EL_SP_PORT2_RIGHT,
2127     EL_SP_PORT1_UP,
2128     EL_SP_PORT2_UP,
2129     EL_SP_PORT1_DOWN,
2130     EL_SP_PORT2_DOWN,
2131     EL_SP_PORT_X,
2132     EL_SP_PORT_Y,
2133     EL_SP_PORT_XY,
2134     EL_TUBE_ALL,
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_over_player_num = SIZEOF_ARRAY_INT(ep_over_player);
2147
2148   static int ep_active_bomb[] =
2149   {
2150     EL_DYNAMITE_ACTIVE,
2151     EL_DYNABOMB_PLAYER1_ACTIVE,
2152     EL_DYNABOMB_PLAYER2_ACTIVE,
2153     EL_DYNABOMB_PLAYER3_ACTIVE,
2154     EL_DYNABOMB_PLAYER4_ACTIVE
2155   };
2156   static int ep_active_bomb_num = SIZEOF_ARRAY_INT(ep_active_bomb);
2157
2158   static int ep_belt[] =
2159   {
2160     EL_CONVEYOR_BELT1_LEFT,
2161     EL_CONVEYOR_BELT1_MIDDLE,
2162     EL_CONVEYOR_BELT1_RIGHT,
2163     EL_CONVEYOR_BELT2_LEFT,
2164     EL_CONVEYOR_BELT2_MIDDLE,
2165     EL_CONVEYOR_BELT2_RIGHT,
2166     EL_CONVEYOR_BELT3_LEFT,
2167     EL_CONVEYOR_BELT3_MIDDLE,
2168     EL_CONVEYOR_BELT3_RIGHT,
2169     EL_CONVEYOR_BELT4_LEFT,
2170     EL_CONVEYOR_BELT4_MIDDLE,
2171     EL_CONVEYOR_BELT4_RIGHT,
2172   };
2173   static int ep_belt_num = SIZEOF_ARRAY_INT(ep_belt);
2174
2175   static int ep_belt_active[] =
2176   {
2177     EL_CONVEYOR_BELT1_LEFT_ACTIVE,
2178     EL_CONVEYOR_BELT1_MIDDLE_ACTIVE,
2179     EL_CONVEYOR_BELT1_RIGHT_ACTIVE,
2180     EL_CONVEYOR_BELT2_LEFT_ACTIVE,
2181     EL_CONVEYOR_BELT2_MIDDLE_ACTIVE,
2182     EL_CONVEYOR_BELT2_RIGHT_ACTIVE,
2183     EL_CONVEYOR_BELT3_LEFT_ACTIVE,
2184     EL_CONVEYOR_BELT3_MIDDLE_ACTIVE,
2185     EL_CONVEYOR_BELT3_RIGHT_ACTIVE,
2186     EL_CONVEYOR_BELT4_LEFT_ACTIVE,
2187     EL_CONVEYOR_BELT4_MIDDLE_ACTIVE,
2188     EL_CONVEYOR_BELT4_RIGHT_ACTIVE,
2189   };
2190   static int ep_belt_active_num = SIZEOF_ARRAY_INT(ep_belt_active);
2191
2192   static int ep_belt_switch[] =
2193   {
2194     EL_CONVEYOR_BELT1_SWITCH_LEFT,
2195     EL_CONVEYOR_BELT1_SWITCH_MIDDLE,
2196     EL_CONVEYOR_BELT1_SWITCH_RIGHT,
2197     EL_CONVEYOR_BELT2_SWITCH_LEFT,
2198     EL_CONVEYOR_BELT2_SWITCH_MIDDLE,
2199     EL_CONVEYOR_BELT2_SWITCH_RIGHT,
2200     EL_CONVEYOR_BELT3_SWITCH_LEFT,
2201     EL_CONVEYOR_BELT3_SWITCH_MIDDLE,
2202     EL_CONVEYOR_BELT3_SWITCH_RIGHT,
2203     EL_CONVEYOR_BELT4_SWITCH_LEFT,
2204     EL_CONVEYOR_BELT4_SWITCH_MIDDLE,
2205     EL_CONVEYOR_BELT4_SWITCH_RIGHT,
2206   };
2207   static int ep_belt_switch_num = SIZEOF_ARRAY_INT(ep_belt_switch);
2208
2209   static int ep_tube[] =
2210   {
2211     EL_TUBE_ALL,
2212     EL_TUBE_VERTICAL,
2213     EL_TUBE_HORIZONTAL,
2214     EL_TUBE_VERTICAL_LEFT,
2215     EL_TUBE_VERTICAL_RIGHT,
2216     EL_TUBE_HORIZONTAL_UP,
2217     EL_TUBE_HORIZONTAL_DOWN,
2218     EL_TUBE_LEFT_UP,
2219     EL_TUBE_LEFT_DOWN,
2220     EL_TUBE_RIGHT_UP,
2221     EL_TUBE_RIGHT_DOWN
2222   };
2223   static int ep_tube_num = SIZEOF_ARRAY_INT(ep_tube);
2224
2225   static long ep1_bit[] =
2226   {
2227     EP_BIT_AMOEBALIVE,
2228     EP_BIT_AMOEBOID,
2229     EP_BIT_SCHLUESSEL,
2230     EP_BIT_PFORTE,
2231     EP_BIT_SOLID,
2232     EP_BIT_MASSIVE,
2233     EP_BIT_SLIPPERY,
2234     EP_BIT_ENEMY,
2235     EP_BIT_MAUER,
2236     EP_BIT_CAN_FALL,
2237     EP_BIT_CAN_SMASH,
2238     EP_BIT_CAN_CHANGE,
2239     EP_BIT_CAN_MOVE,
2240     EP_BIT_COULD_MOVE,
2241     EP_BIT_DONT_TOUCH,
2242     EP_BIT_DONT_GO_TO,
2243     EP_BIT_MAMPF2,
2244     EP_BIT_BD_ELEMENT,
2245     EP_BIT_SB_ELEMENT,
2246     EP_BIT_GEM,
2247     EP_BIT_INACTIVE,
2248     EP_BIT_EXPLOSIVE,
2249     EP_BIT_MAMPF3,
2250     EP_BIT_PUSHABLE,
2251     EP_BIT_PLAYER,
2252     EP_BIT_HAS_CONTENT,
2253     EP_BIT_EATABLE,
2254     EP_BIT_SP_ELEMENT,
2255     EP_BIT_QUICK_GATE,
2256     EP_BIT_OVER_PLAYER,
2257     EP_BIT_ACTIVE_BOMB
2258   };
2259   static long ep2_bit[] =
2260   {
2261     EP_BIT_BELT,
2262     EP_BIT_BELT_ACTIVE,
2263     EP_BIT_BELT_SWITCH,
2264     EP_BIT_TUBE
2265   };
2266   static int *ep1_array[] =
2267   {
2268     ep_amoebalive,
2269     ep_amoeboid,
2270     ep_schluessel,
2271     ep_pforte,
2272     ep_solid,
2273     ep_massive,
2274     ep_slippery,
2275     ep_enemy,
2276     ep_mauer,
2277     ep_can_fall,
2278     ep_can_smash,
2279     ep_can_change,
2280     ep_can_move,
2281     ep_could_move,
2282     ep_dont_touch,
2283     ep_dont_go_to,
2284     ep_mampf2,
2285     ep_bd_element,
2286     ep_sb_element,
2287     ep_gem,
2288     ep_inactive,
2289     ep_explosive,
2290     ep_mampf3,
2291     ep_pushable,
2292     ep_player,
2293     ep_has_content,
2294     ep_eatable,
2295     ep_sp_element,
2296     ep_quick_gate,
2297     ep_over_player,
2298     ep_active_bomb
2299   };
2300   static int *ep2_array[] =
2301   {
2302     ep_belt,
2303     ep_belt_active,
2304     ep_belt_switch,
2305     ep_tube
2306   };
2307   static int *ep1_num[] =
2308   {
2309     &ep_amoebalive_num,
2310     &ep_amoeboid_num,
2311     &ep_schluessel_num,
2312     &ep_pforte_num,
2313     &ep_solid_num,
2314     &ep_massive_num,
2315     &ep_slippery_num,
2316     &ep_enemy_num,
2317     &ep_mauer_num,
2318     &ep_can_fall_num,
2319     &ep_can_smash_num,
2320     &ep_can_change_num,
2321     &ep_can_move_num,
2322     &ep_could_move_num,
2323     &ep_dont_touch_num,
2324     &ep_dont_go_to_num,
2325     &ep_mampf2_num,
2326     &ep_bd_element_num,
2327     &ep_sb_element_num,
2328     &ep_gem_num,
2329     &ep_inactive_num,
2330     &ep_explosive_num,
2331     &ep_mampf3_num,
2332     &ep_pushable_num,
2333     &ep_player_num,
2334     &ep_has_content_num,
2335     &ep_eatable_num,
2336     &ep_sp_element_num,
2337     &ep_quick_gate_num,
2338     &ep_over_player_num,
2339     &ep_active_bomb_num
2340   };
2341   static int *ep2_num[] =
2342   {
2343     &ep_belt_num,
2344     &ep_belt_active_num,
2345     &ep_belt_switch_num,
2346     &ep_tube_num
2347   };
2348   static int num_properties1 = SIZEOF_ARRAY(ep1_num, int *);
2349   static int num_properties2 = SIZEOF_ARRAY(ep2_num, int *);
2350
2351   for (i=0; i<MAX_NUM_ELEMENTS; i++)
2352   {
2353     Properties1[i] = 0;
2354     Properties2[i] = 0;
2355   }
2356
2357   for (i=0; i<num_properties1; i++)
2358     for (j=0; j<*(ep1_num[i]); j++)
2359       Properties1[(ep1_array[i])[j]] |= ep1_bit[i];
2360   for (i=0; i<num_properties2; i++)
2361     for (j=0; j<*(ep2_num[i]); j++)
2362       Properties2[(ep2_array[i])[j]] |= ep2_bit[i];
2363
2364   for (i=EL_CHAR_START; i<=EL_CHAR_END; i++)
2365     Properties1[i] |= (EP_BIT_CHAR | EP_BIT_INACTIVE);
2366 }
2367
2368 void Execute_Command(char *command)
2369 {
2370   if (strcmp(command, "print graphicsinfo.conf") == 0)
2371   {
2372     int i;
2373
2374     printf("# You can configure additional/alternative image files here.\n");
2375     printf("# (The images below are default and therefore commented out.)\n");
2376     printf("\n");
2377     printf("%s\n", getFormattedSetupEntry("name", "Classic Graphics"));
2378     printf("\n");
2379     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2380     printf("\n");
2381
2382     for (i=0; image_config[i].token != NULL; i++)
2383       printf("# %s\n",
2384              getFormattedSetupEntry(image_config[i].token,
2385                                     image_config[i].value));
2386
2387     exit(0);
2388   }
2389   else if (strcmp(command, "print soundsinfo.conf") == 0)
2390   {
2391     int i;
2392
2393     printf("# You can configure additional/alternative sound files here.\n");
2394     printf("# (The sounds below are default and therefore commented out.)\n");
2395     printf("\n");
2396     printf("%s\n", getFormattedSetupEntry("name", "Classic Sounds"));
2397     printf("\n");
2398     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2399     printf("\n");
2400
2401     for (i=0; sound_config[i].token != NULL; i++)
2402       printf("# %s\n",
2403              getFormattedSetupEntry(sound_config[i].token,
2404                                     sound_config[i].value));
2405
2406     exit(0);
2407   }
2408   else if (strcmp(command, "print musicinfo.conf") == 0)
2409   {
2410     printf("# (Currently only \"name\" and \"sort_priority\" recognized.)\n");
2411     printf("\n");
2412     printf("%s\n", getFormattedSetupEntry("name", "Classic Music"));
2413     printf("\n");
2414     printf("%s\n", getFormattedSetupEntry("sort_priority", "100"));
2415
2416     exit(0);
2417   }
2418   else if (strncmp(command, "dump level ", 11) == 0)
2419   {
2420     char *filename = &command[11];
2421
2422     if (access(filename, F_OK) != 0)
2423       Error(ERR_EXIT, "cannot open file '%s'", filename);
2424
2425     LoadLevelFromFilename(filename);
2426     DumpLevel(&level);
2427
2428     exit(0);
2429   }
2430   else if (strncmp(command, "dump tape ", 10) == 0)
2431   {
2432     char *filename = &command[10];
2433
2434     if (access(filename, F_OK) != 0)
2435       Error(ERR_EXIT, "cannot open file '%s'", filename);
2436
2437     LoadTapeFromFilename(filename);
2438     DumpTape(&tape);
2439
2440     exit(0);
2441   }
2442   else if (strncmp(command, "autoplay ", 9) == 0)
2443   {
2444     char *str_copy = getStringCopy(&command[9]);
2445     char *str_ptr = strchr(str_copy, ' ');
2446
2447     global.autoplay_leveldir = str_copy;
2448     global.autoplay_level_nr = -1;
2449
2450     if (str_ptr != NULL)
2451     {
2452       *str_ptr++ = '\0';                        /* terminate leveldir string */
2453       global.autoplay_level_nr = atoi(str_ptr); /* get level_nr value */
2454     }
2455   }
2456   else
2457   {
2458     Error(ERR_EXIT_HELP, "unrecognized command '%s'", command);
2459   }
2460 }
2461
2462 void CloseAllAndExit(int exit_value)
2463 {
2464   StopSounds();
2465   FreeAllSounds();
2466   FreeAllMusic();
2467   CloseAudio();         /* called after freeing sounds (needed for SDL) */
2468
2469   FreeAllImages();
2470   FreeTileClipmasks();
2471
2472   if (bitmap_font_initial)
2473     FreeBitmap(bitmap_font_initial);
2474
2475   CloseVideoDisplay();
2476   ClosePlatformDependantStuff();
2477
2478   exit(exit_value);
2479 }