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