rnd-19980930-1
[rocksndiamonds.git] / src / init.c
1 /***********************************************************
2 *  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
3 *----------------------------------------------------------*
4 *  (c) 1995-98 Artsoft Entertainment                       *
5 *              Holger Schemel                              *
6 *              Oststrasse 11a                              *
7 *              33604 Bielefeld                             *
8 *              phone: ++49 +521 290471                     *
9 *              email: aeglos@valinor.owl.de                *
10 *----------------------------------------------------------*
11 *  init.c                                                  *
12 ***********************************************************/
13
14 #include <signal.h>
15 #include <sys/socket.h>
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
18 #include <netdb.h>
19
20 #include "init.h"
21 #include "misc.h"
22 #include "sound.h"
23 #include "screens.h"
24 #include "tools.h"
25 #include "files.h"
26 #include "joystick.h"
27 #include "gfxload.h"
28 #include "gifload.h"
29
30 #ifdef DEBUG
31 /*
32 #define DEBUG_TIMING
33 */
34 #endif
35
36 struct PictureFileInfo
37 {
38   char *picture_filename;
39   BOOL picture_with_mask;
40 };
41
42 struct IconFileInfo
43 {
44   char *picture_filename;
45   char *picturemask_filename;
46 };
47
48 static int sound_process_id = 0;
49
50 static void InitServer(void);
51 static void InitLevelAndPlayerInfo(void);
52 static void InitDisplay(int, char **);
53 static void InitSound(void);
54 static void InitSoundProcess(void);
55 static void InitWindow(int, char **);
56 static void InitGfx(void);
57 static void LoadGfx(int, struct PictureFileInfo *);
58 static void InitElementProperties(void);
59
60 void OpenAll(int argc, char *argv[])
61 {
62
63
64   /* TEST TEST TEST */
65   InitServer();
66   /* TEST TEST TEST */
67
68
69   InitLevelAndPlayerInfo();
70
71   InitCounter();
72   InitSound();
73   InitSoundProcess();
74   InitJoystick();
75   InitRND(NEW_RANDOMIZE);
76
77   signal(SIGINT, CloseAll);
78   signal(SIGTERM, CloseAll);
79
80   InitDisplay(argc, argv);
81   InitWindow(argc, argv);
82
83   XMapWindow(display, window);
84   XFlush(display);
85
86   InitGfx();
87   InitElementProperties();
88
89   DrawMainMenu();
90 }
91
92
93
94 /* TEST STUFF -------------------------------------------------------------- */
95
96 int norestart = 0;
97 int nospeedup = 0;
98
99 /* server stuff */
100
101 #define DEFAULTPORT     19503
102 #define BUFLEN          4096
103
104 int sfd;
105 unsigned char realbuf[512], readbuf[BUFLEN], writbuf[BUFLEN];
106 unsigned char *buf = realbuf + 4;
107 int nread = 0, nwrite = 0;
108
109 void fatal(char *s)
110 {
111   fprintf(stderr, "%s.\n", s);
112   exit(1);
113 }
114
115 void u_sleep(int i)
116 {
117   struct timeval tm;
118   tm.tv_sec = i / 1000000;
119   tm.tv_usec = i % 1000000;
120   select(0, NULL, NULL, NULL, &tm);
121 }
122
123 void startserver()
124 {
125   char *options[2];
126   int n = 0;
127
128   options[0] = options[1] = NULL;
129   if (norestart)
130     options[n++] = "-norestart";
131   if (nospeedup)
132     options[n++] = "-nospeedup";
133
134   switch (fork())
135   {
136     case 0:
137       execlp(
138 #ifdef XTRISPATH
139       XTRISPATH "/rnd_server",
140 #else
141       "rnd_server",
142 #endif
143       "rnd_server", "-once", "-v", options[0], options[1], NULL);
144
145       fprintf(stderr, "Can't start server '%s'.\n",
146 #ifdef XTRISPATH
147         XTRISPATH "/xtserv");
148 #else
149         "xtserv");
150 #endif
151
152       _exit(1);
153     
154     case -1:
155       fatal("fork() failed");
156     
157     default:
158       return;
159   }
160 }
161
162 void connect2server(char *host, int port)
163 {
164   struct hostent *hp;
165   struct sockaddr_in s;
166   struct protoent *tcpproto;
167   int on = 1, i;
168
169   if (host)
170   {
171     if ((s.sin_addr.s_addr = inet_addr(host)) == -1)
172     {
173       hp = gethostbyname(host);
174       if (!hp)
175         fatal("Host not found");
176       s.sin_addr = *(struct in_addr *)(hp->h_addr_list[0]);
177     }
178   }
179   else
180     s.sin_addr.s_addr = inet_addr("127.0.0.1");
181
182   s.sin_port = htons(port);
183   s.sin_family = AF_INET;
184   sfd = socket(PF_INET, SOCK_STREAM, 0);
185   if (sfd < 0)
186     fatal("Out of file descriptors");
187   if ((tcpproto = getprotobyname("tcp")) != NULL)
188     setsockopt(sfd, tcpproto->p_proto, TCP_NODELAY, (char *)&on, sizeof(int));
189
190   if (connect(sfd, (struct sockaddr *)&s, sizeof(s)) < 0)
191   {
192     if (!host)
193     {
194       printf("No xtris server on localhost - starting up one ...\n");
195       startserver();
196       for (i=0; i<6; i++)
197       {
198         u_sleep(500000);
199         close(sfd);
200         sfd = socket(PF_INET, SOCK_STREAM, 0);
201         if (sfd < 0)
202           fatal("Out of file descriptors");
203         setsockopt(sfd, tcpproto->p_proto, TCP_NODELAY, (char *)&on, sizeof(int));
204         if (connect(sfd, (struct sockaddr *)&s, sizeof(s)) >= 0)
205           break;
206       }
207       if (i==6)
208         fatal("Can't connect to server");
209     }
210     else
211       fatal("Can't connect to server");
212   }
213 }
214
215 void InitServer()
216 {
217   if (server_port == 0)
218     server_port = DEFAULTPORT;
219
220   connect2server(server_host, server_port);
221 }
222
223 /* TEST STUFF -------------------------------------------------------------- */
224
225
226
227 void InitLevelAndPlayerInfo()
228 {
229   local_player = &stored_player[0];
230
231   if (!LoadLevelInfo())                 /* global level info */
232     CloseAll();
233
234   LoadPlayerInfo(PLAYER_SETUP);         /* global setup info */
235   LoadPlayerInfo(PLAYER_LEVEL);         /* level specific info */
236 }
237
238 void InitSound()
239 {
240   int i;
241
242   if (sound_status==SOUND_OFF)
243     return;
244
245 #ifndef MSDOS
246   if (access(sound_device_name,W_OK)<0)
247   {
248     fprintf(stderr,"%s: cannot access sound device - no sounds\n",progname);
249     sound_status=SOUND_OFF;
250     return;
251   }
252
253   if ((sound_device=open(sound_device_name,O_WRONLY))<0)
254   {
255     fprintf(stderr,"%s: cannot open sound device - no sounds\n",progname);
256     sound_status=SOUND_OFF;
257     return;
258   }
259
260   close(sound_device);
261   sound_status=SOUND_AVAILABLE;
262
263 #ifdef VOXWARE
264   sound_loops_allowed = TRUE;
265   sound_loops_on = TRUE;
266 #endif
267 #else
268   sound_loops_allowed = TRUE;
269   sound_loops_on = TRUE;
270 #endif
271
272   for(i=0;i<NUM_SOUNDS;i++)
273   {
274 #ifdef MSDOS
275   sprintf(sound_name[i], "%d", i+1);
276 #endif
277     Sound[i].name = sound_name[i];
278     if (!LoadSound(&Sound[i]))
279     {
280       sound_status=SOUND_OFF;
281       return;
282     }
283   }
284 }
285
286 void InitSoundProcess()
287 {
288   if (sound_status==SOUND_OFF)
289     return;
290
291 #ifndef MSDOS
292   if (pipe(sound_pipe)<0)
293   {
294     fprintf(stderr,"%s: cannot create pipe - no sounds\n",progname);
295     sound_status=SOUND_OFF;
296     return;
297   }
298
299   if ((sound_process_id=fork())<0)
300   {       
301     fprintf(stderr,"%s: cannot create child process - no sounds\n",progname);
302     sound_status=SOUND_OFF;
303     return;
304   }
305
306   if (!sound_process_id)        /* we are child */
307     SoundServer();
308   else                          /* we are parent */
309     close(sound_pipe[0]);       /* no reading from pipe needed */
310 #else
311   SoundServer();
312 #endif
313 }
314
315 void InitJoystick()
316 {
317   if (global_joystick_status==JOYSTICK_OFF)
318     return;
319
320 #ifndef MSDOS
321   if (access(joystick_device_name[joystick_nr],R_OK)<0)
322   {
323     fprintf(stderr,"%s: cannot access joystick device '%s'\n",
324             progname,joystick_device_name[joystick_nr]);
325     joystick_status = JOYSTICK_OFF;
326     return;
327   }
328
329   if ((joystick_device=open(joystick_device_name[joystick_nr],O_RDONLY))<0)
330   {
331     fprintf(stderr,"%s: cannot open joystick device '%s'\n",
332             progname,joystick_device_name[joystick_nr]);
333     joystick_status = JOYSTICK_OFF;
334     return;
335   }
336
337   joystick_status = JOYSTICK_AVAILABLE;
338   LoadJoystickData();
339 #else
340   joystick_status = JOYSTICK_AVAILABLE;
341 #endif
342 }
343
344 void InitDisplay(int argc, char *argv[])
345 {
346   char *display_name = NULL;
347   XVisualInfo vinfo_template, *vinfo;
348   int num_visuals;
349   unsigned int depth;
350   int i;
351
352   /* get X server to connect to, if given as an argument */
353   for (i=1;i<argc-1;i++)
354   {
355     char *dispstr="-display";
356     int len=MAX(strlen(dispstr),strlen(argv[i]));
357
358     if (len<4)
359       continue;
360     else if (!strncmp(argv[i],dispstr,len))
361     {
362       display_name=argv[i+1];
363       break;
364     }
365   }
366
367   /* connect to X server */
368   if (!(display=XOpenDisplay(display_name)))
369   {
370     fprintf(stderr,"%s: cannot connect to X server %s\n", 
371             progname, XDisplayName(display_name));
372     exit(-1);
373   }
374   
375   screen = DefaultScreen(display);
376   visual = DefaultVisual(display, screen);
377   depth  = DefaultDepth(display, screen);
378   cmap   = DefaultColormap(display, screen);
379
380   /* look for good enough visual */
381   vinfo_template.screen = screen;
382   vinfo_template.class = (depth == 8 ? PseudoColor : TrueColor);
383   vinfo_template.depth = depth;
384   if ((vinfo = XGetVisualInfo(display, VisualScreenMask | VisualClassMask |
385                               VisualDepthMask, &vinfo_template, &num_visuals)))
386   {
387     visual = vinfo->visual;
388     XFree((void *)vinfo);
389   }
390
391   /* got appropriate visual? */
392   if (depth < 8)
393   {
394     printf("Sorry, displays with less than 8 bits per pixel not supported.\n");
395     exit(-1);
396   }
397   else if ((depth ==8 && visual->class != PseudoColor) ||
398            (depth > 8 && visual->class != TrueColor &&
399             visual->class != DirectColor))
400   {
401     printf("Sorry, cannot get appropriate visual.\n");
402     exit(-1);
403   }
404 }
405
406 void InitWindow(int argc, char *argv[])
407 {
408   unsigned int border_width = 4;
409   Pixmap icon_pixmap, iconmask_pixmap;
410   unsigned int icon_width,icon_height;
411   int icon_hot_x,icon_hot_y;
412   char icon_filename[256];
413   XSizeHints size_hints;
414   XWMHints wm_hints;
415   XClassHint class_hints;
416   XTextProperty windowName, iconName;
417   XGCValues gc_values;
418   unsigned long gc_valuemask;
419   char *window_name = WINDOWTITLE_STRING;
420   char *icon_name = WINDOWTITLE_STRING;
421   long window_event_mask;
422   Atom proto_atom = None, delete_atom = None;
423   int screen_width, screen_height;
424   int win_xpos = WIN_XPOS, win_ypos = WIN_YPOS;
425   unsigned long pen_fg = WhitePixel(display,screen);
426   unsigned long pen_bg = BlackPixel(display,screen);
427
428 #ifndef MSDOS
429   static struct IconFileInfo icon_pic =
430   {
431     "rocks_icon.xbm",
432     "rocks_iconmask.xbm"
433   };
434 #endif
435
436   screen_width = XDisplayWidth(display, screen);
437   screen_height = XDisplayHeight(display, screen);
438
439   width = WIN_XSIZE;
440   height = WIN_YSIZE;
441
442   win_xpos = (screen_width - width) / 2;
443   win_ypos = (screen_height - height) / 2;
444
445   window = XCreateSimpleWindow(display, RootWindow(display, screen),
446                                win_xpos, win_ypos, width, height, border_width,
447                                pen_fg, pen_bg);
448
449 #ifndef MSDOS
450   proto_atom = XInternAtom(display, "WM_PROTOCOLS", FALSE);
451   delete_atom = XInternAtom(display, "WM_DELETE_WINDOW", FALSE);
452   if ((proto_atom != None) && (delete_atom != None))
453     XChangeProperty(display, window, proto_atom, XA_ATOM, 32,
454                     PropModePrepend, (unsigned char *) &delete_atom, 1);
455
456   sprintf(icon_filename,"%s/%s",GFX_PATH,icon_pic.picture_filename);
457   XReadBitmapFile(display,window,icon_filename,
458                   &icon_width,&icon_height,
459                   &icon_pixmap,&icon_hot_x,&icon_hot_y);
460   if (!icon_pixmap)
461   {
462     fprintf(stderr, "%s: cannot read icon bitmap file '%s'.\n",
463             progname,icon_filename);
464     exit(-1);
465   }
466
467   sprintf(icon_filename,"%s/%s",GFX_PATH,icon_pic.picturemask_filename);
468   XReadBitmapFile(display,window,icon_filename,
469                   &icon_width,&icon_height,
470                   &iconmask_pixmap,&icon_hot_x,&icon_hot_y);
471   if (!iconmask_pixmap)
472   {
473     fprintf(stderr, "%s: cannot read icon bitmap file '%s'.\n",
474             progname,icon_filename);
475     exit(-1);
476   }
477
478   size_hints.width  = size_hints.min_width  = size_hints.max_width  = width;
479   size_hints.height = size_hints.min_height = size_hints.max_height = height;
480   size_hints.flags = PSize | PMinSize | PMaxSize;
481
482   if (win_xpos || win_ypos)
483   {
484     size_hints.x = win_xpos;
485     size_hints.y = win_ypos;
486     size_hints.flags |= PPosition;
487   }
488
489   if (!XStringListToTextProperty(&window_name, 1, &windowName))
490   {
491     fprintf(stderr, "%s: structure allocation for windowName failed.\n",
492             progname);
493     exit(-1);
494   }
495
496   if (!XStringListToTextProperty(&icon_name, 1, &iconName))
497   {
498     fprintf(stderr, "%s: structure allocation for iconName failed.\n",
499             progname);
500     exit(-1);
501   }
502
503   wm_hints.initial_state = NormalState;
504   wm_hints.input = True;
505   wm_hints.icon_pixmap = icon_pixmap;
506   wm_hints.icon_mask = iconmask_pixmap;
507   wm_hints.flags = StateHint | IconPixmapHint | IconMaskHint | InputHint;
508
509   class_hints.res_name = progname;
510   class_hints.res_class = "Rocks'n'Diamonds";
511
512   XSetWMProperties(display, window, &windowName, &iconName, 
513                    argv, argc, &size_hints, &wm_hints, 
514                    &class_hints);
515
516   XFree(windowName.value);
517   XFree(iconName.value);
518
519   /* Select event types wanted */
520   window_event_mask = ExposureMask | StructureNotifyMask | FocusChangeMask |
521                       ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
522                       KeyPressMask | KeyReleaseMask;
523   XSelectInput(display, window, window_event_mask);
524 #endif
525
526   /* create GC for drawing with window depth */
527   gc_values.graphics_exposures = False;
528   gc_values.foreground = pen_bg;
529   gc_values.background = pen_bg;
530   gc_valuemask = GCGraphicsExposures | GCForeground | GCBackground;
531   gc = XCreateGC(display, window, gc_valuemask, &gc_values);
532 }
533
534 void DrawInitText(char *text, int ypos, int color)
535 {
536   if (display && window && pix[PIX_SMALLFONT])
537   {
538     XFillRectangle(display,window,gc,0,ypos, WIN_XSIZE,FONT2_YSIZE);
539     DrawTextExt(window,gc,(WIN_XSIZE-strlen(text)*FONT2_XSIZE)/2,
540                 ypos,text,FS_SMALL,color);
541     XFlush(display);
542   }
543 }
544
545 void InitGfx()
546 {
547   int i,j;
548   GC copy_clipmask_gc;
549   XGCValues clip_gc_values;
550   unsigned long clip_gc_valuemask;
551
552 #ifdef MSDOS
553   static struct PictureFileInfo pic[NUM_PICTURES] =
554   {
555     { "Screen", TRUE },
556     { "Door",   TRUE },
557     { "Heroes", TRUE },
558     { "Toons",  TRUE },
559     { "Font",   FALSE },
560     { "Font2",  FALSE }
561   }; 
562 #else
563   static struct PictureFileInfo pic[NUM_PICTURES] =
564   {
565     { "RocksScreen",    TRUE },
566     { "RocksDoor",      TRUE },
567     { "RocksHeroes",    TRUE },
568     { "RocksToons",     TRUE },
569     { "RocksFont",      FALSE },
570     { "RocksFont2",     FALSE }
571   }; 
572 #endif
573
574   static struct
575   {
576     int start;
577     int count;
578   }
579   tile_needs_clipping[] =
580   {
581     { GFX_SPIELER1_UP, 4 },
582     { GFX_SPIELER1_DOWN, 4 },
583     { GFX_SPIELER1_LEFT, 4 },
584     { GFX_SPIELER1_RIGHT, 4 },
585     { GFX_SPIELER1_PUSH_LEFT, 4 },
586     { GFX_SPIELER1_PUSH_RIGHT, 4 },
587     { GFX_SPIELER2_UP, 4 },
588     { GFX_SPIELER2_DOWN, 4 },
589     { GFX_SPIELER2_LEFT, 4 },
590     { GFX_SPIELER2_RIGHT, 4 },
591     { GFX_SPIELER2_PUSH_LEFT, 4 },
592     { GFX_SPIELER2_PUSH_RIGHT, 4 },
593     { GFX_SPIELER3_UP, 4 },
594     { GFX_SPIELER3_DOWN, 4 },
595     { GFX_SPIELER3_LEFT, 4 },
596     { GFX_SPIELER3_RIGHT, 4 },
597     { GFX_SPIELER3_PUSH_LEFT, 4 },
598     { GFX_SPIELER3_PUSH_RIGHT, 4 },
599     { GFX_SPIELER4_UP, 4 },
600     { GFX_SPIELER4_DOWN, 4 },
601     { GFX_SPIELER4_LEFT, 4 },
602     { GFX_SPIELER4_RIGHT, 4 },
603     { GFX_SPIELER4_PUSH_LEFT, 4 },
604     { GFX_SPIELER4_PUSH_RIGHT, 4 },
605     { GFX_GEBLUBBER, 4 },
606     { GFX_DYNAMIT, 7 },
607     { GFX_DYNABOMB, 4 },
608     { GFX_SOKOBAN_OBJEKT, 1 },
609     { GFX_FUNKELN_BLAU, 3 },
610     { GFX_FUNKELN_WEISS, 3 },
611     { -1, 0 }
612   };
613
614 #ifdef DEBUG_TIMING
615   long count1, count2;
616   count1 = Counter();
617 #endif
618
619   LoadGfx(PIX_SMALLFONT,&pic[PIX_SMALLFONT]);
620   DrawInitText(WINDOWTITLE_STRING,20,FC_YELLOW);
621   DrawInitText(COPYRIGHT_STRING,50,FC_RED);
622 #ifdef MSDOS
623   DrawInitText("MSDOS version done by Guido Schulz",210,FC_BLUE);
624   rest(200);
625 #endif MSDOS
626   DrawInitText("Loading graphics:",120,FC_GREEN);
627
628   for(i=0; i<NUM_PICTURES; i++)
629     if (i != PIX_SMALLFONT)
630       LoadGfx(i,&pic[i]);
631
632 #ifdef DEBUG_TIMING
633   count2 = Counter();
634   printf("SUMMARY: %.2f SECONDS LOADING TIME\n",(float)(count2-count1)/1000.0);
635 #endif
636
637
638   pix[PIX_DB_BACK] = XCreatePixmap(display, window,
639                                    WIN_XSIZE,WIN_YSIZE,
640                                    XDefaultDepth(display,screen));
641   pix[PIX_DB_DOOR] = XCreatePixmap(display, window,
642                                    3*DXSIZE,DYSIZE+VYSIZE,
643                                    XDefaultDepth(display,screen));
644   pix[PIX_DB_FIELD] = XCreatePixmap(display, window,
645                                     FXSIZE,FYSIZE,
646                                     XDefaultDepth(display,screen));
647
648   clip_gc_values.graphics_exposures = False;
649   clip_gc_valuemask = GCGraphicsExposures;
650   copy_clipmask_gc =
651     XCreateGC(display,clipmask[PIX_BACK],clip_gc_valuemask,&clip_gc_values);
652
653   clip_gc_values.graphics_exposures = False;
654   clip_gc_valuemask = GCGraphicsExposures;
655   tile_clip_gc =
656     XCreateGC(display,window,clip_gc_valuemask,&clip_gc_values);
657
658   /* initialize pixmap array to Pixmap 'None' */
659   for(i=0; i<NUM_TILES; i++)
660     tile_clipmask[i] = None;
661
662   /* create only those clipping Pixmaps we really need */
663   for(i=0; tile_needs_clipping[i].start>=0; i++)
664   {
665     for(j=0; j<tile_needs_clipping[i].count; j++)
666     {
667       int tile = tile_needs_clipping[i].start + j;
668       int graphic = tile;
669       int src_x, src_y;
670       Pixmap src_pixmap;
671
672       if (graphic >= GFX_START_ROCKSSCREEN &&
673           graphic <= GFX_END_ROCKSSCREEN)
674       {
675         src_pixmap = clipmask[PIX_BACK];
676         graphic -= GFX_START_ROCKSSCREEN;
677         src_x = SX + (graphic % GFX_PER_LINE) * TILEX;
678         src_y = SY + (graphic / GFX_PER_LINE) * TILEY;
679       }
680       else if (graphic >= GFX_START_ROCKSHEROES &&
681                graphic <= GFX_END_ROCKSHEROES)
682       {
683         src_pixmap = clipmask[PIX_HEROES];
684         graphic -= GFX_START_ROCKSHEROES;
685         src_x = (graphic % HEROES_PER_LINE) * TILEX;
686         src_y = (graphic / HEROES_PER_LINE) * TILEY;
687       }
688       else if (graphic >= GFX_START_ROCKSFONT &&
689                graphic <= GFX_END_ROCKSFONT)
690       {
691         src_pixmap = clipmask[PIX_BIGFONT];
692         graphic -= GFX_START_ROCKSFONT;
693         src_x = (graphic % FONT_CHARS_PER_LINE) * TILEX;
694         src_y = (graphic / FONT_CHARS_PER_LINE) * TILEY +
695           FC_SPECIAL1 * FONT_LINES_PER_FONT * TILEY;
696       }
697       else
698         break;
699
700       tile_clipmask[tile] = XCreatePixmap(display, window, TILEX,TILEY, 1);
701
702       XCopyArea(display,src_pixmap,tile_clipmask[tile],copy_clipmask_gc,
703                 src_x,src_y, TILEX,TILEY, 0,0);
704     }
705   }
706
707   if (!pix[PIX_DB_BACK] || !pix[PIX_DB_DOOR])
708   {
709     fprintf(stderr, "%s: cannot create additional Pixmaps!\n",progname);
710     CloseAll();
711     exit(-1);
712   }
713
714   for(i=0;i<NUM_PIXMAPS;i++)
715   {
716     if (clipmask[i])
717     {
718       clip_gc_values.graphics_exposures = False;
719       clip_gc_values.clip_mask = clipmask[i];
720       clip_gc_valuemask = GCGraphicsExposures | GCClipMask;
721       clip_gc[i] = XCreateGC(display,window,clip_gc_valuemask,&clip_gc_values);
722     }
723   }
724
725   drawto = backbuffer = pix[PIX_DB_BACK];
726   fieldbuffer = pix[PIX_DB_FIELD];
727   SetDrawtoField(DRAW_BACKBUFFER);
728
729   XCopyArea(display,pix[PIX_BACK],backbuffer,gc,
730             0,0, WIN_XSIZE,WIN_YSIZE, 0,0);
731   XFillRectangle(display,pix[PIX_DB_BACK],gc,
732                  REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE);
733   XFillRectangle(display,pix[PIX_DB_DOOR],gc,
734                  0,0, 3*DXSIZE,DYSIZE+VYSIZE);
735
736   for(i=0; i<MAX_BUF_XSIZE; i++)
737     for(j=0; j<MAX_BUF_YSIZE; j++)
738       redraw[i][j] = 0;
739   redraw_tiles = 0;
740   redraw_mask = REDRAW_ALL;
741 }
742
743 void LoadGfx(int pos, struct PictureFileInfo *pic)
744 {
745   char basefilename[256];
746   char filename[256];
747
748 #ifdef XPM_INCLUDE_FILE
749   int xpm_err, xbm_err;
750   unsigned int width,height;
751   int hot_x,hot_y;
752   Pixmap shapemask;
753   char *picture_ext = ".xpm";
754   char *picturemask_ext = "Mask.xbm";
755 #else
756   int gif_err;
757   char *picture_ext = ".gif";
758 #endif
759
760 #ifdef DEBUG_TIMING
761   long count1, count2;
762 #endif
763
764   /* Grafik laden */
765   if (pic->picture_filename)
766   {
767     sprintf(basefilename,"%s%s",pic->picture_filename,picture_ext);
768     DrawInitText(basefilename,150,FC_YELLOW);
769     sprintf(filename,"%s/%s",GFX_PATH,basefilename);
770
771 #ifdef MSDOS
772     rest(100);
773 #endif MSDOS
774
775 #ifdef DEBUG_TIMING
776     count1 = Counter();
777 #endif
778
779 #ifdef XPM_INCLUDE_FILE
780
781     xpm_att[pos].valuemask = XpmCloseness;
782     xpm_att[pos].closeness = 20000;
783     xpm_err = XpmReadFileToPixmap(display,window,filename,
784                                   &pix[pos],&shapemask,&xpm_att[pos]);
785
786     switch(xpm_err)
787     {
788       case XpmOpenFailed:
789         fprintf(stderr,"Cannot open Xpm file '%s' !\n",filename);
790         CloseAll();
791         exit(-1);
792       case XpmFileInvalid:
793         fprintf(stderr,"Invalid Xpm file '%s'!\n",filename);
794         CloseAll();
795         exit(-1);
796       case XpmNoMemory:
797         fprintf(stderr,"Not enough memory for Xpm file '%s'!\n",filename);
798         CloseAll();
799         exit(1);
800       case XpmColorFailed:
801         fprintf(stderr,"Can't get colors for Xpm file '%s'!\n",filename);
802         CloseAll();
803         exit(-1);
804       default:
805         break;
806     }
807
808 #ifdef DEBUG_TIMING
809     count2 = Counter();
810     printf("XPM LOADING %s IN %.2f SECONDS\n",
811            filename,(float)(count2-count1)/1000.0);
812 #endif
813
814 #else 
815
816     gif_err = Read_GIF_to_Pixmaps(display, window, filename,
817                                   &pix[pos], &clipmask[pos]);
818
819     switch(gif_err)
820     {
821       case GIF_Success:
822         break;
823       case GIF_OpenFailed:
824         fprintf(stderr,"Cannot open GIF file '%s' !\n",filename);
825         CloseAll();
826         exit(-1);
827       case GIF_ReadFailed:
828         fprintf(stderr,"Cannot read GIF file '%s' !\n",filename);
829         CloseAll();
830         exit(-1);
831       case GIF_FileInvalid:
832         fprintf(stderr,"Invalid GIF file '%s'!\n",filename);
833         CloseAll();
834         exit(-1);
835       case GIF_NoMemory:
836         fprintf(stderr,"Not enough memory for GIF file '%s'!\n",filename);
837         CloseAll();
838         exit(1);
839       case GIF_ColorFailed:
840         fprintf(stderr,"Can't get colors for GIF file '%s'!\n",filename);
841         CloseAll();
842         exit(-1);
843       default:
844         break;
845     }
846
847 #ifdef DEBUG_TIMING
848     count2 = Counter();
849     printf("GIF LOADING %s IN %.2f SECONDS\n",
850            filename,(float)(count2-count1)/1000.0);
851 #endif
852
853 #endif
854
855     if (!pix[pos])
856     {
857       fprintf(stderr, "%s: cannot get graphics for '%s'.\n",
858               progname, pic->picture_filename);
859       CloseAll();
860       exit(-1);
861     }
862   }
863
864   /* zugehörige Maske laden (wenn vorhanden) */
865   if (pic->picture_with_mask)
866   {
867
868 #ifdef XPM_INCLUDE_FILE
869
870     sprintf(basefilename,"%s%s",pic->picture_filename,picturemask_ext);
871     DrawInitText(basefilename,150,FC_YELLOW);
872     sprintf(filename,"%s/%s",GFX_PATH,basefilename);
873
874 #ifdef DEBUG_TIMING
875     count1 = Counter();
876 #endif
877
878     xbm_err = XReadBitmapFile(display,window,filename,
879                               &width,&height,&clipmask[pos],&hot_x,&hot_y);
880
881     switch(xbm_err)
882     {
883       case BitmapSuccess:
884         break;
885       case BitmapOpenFailed:
886         fprintf(stderr,"Bitmap file open failed on '%s' !\n",filename);
887         CloseAll();
888         exit(-1);
889         break;
890       case BitmapFileInvalid:
891         fprintf(stderr,"Bitmap file invalid: '%s' !\n",filename);
892         CloseAll();
893         exit(-1);
894         break;
895       case BitmapNoMemory:
896         fprintf(stderr,"No memory for file '%s' !\n",filename);
897         CloseAll();
898         exit(-1);
899         break;
900       default:
901         break;
902     }
903
904 #ifdef DEBUG_TIMING
905     count2 = Counter();
906     printf("XBM LOADING %s IN %.2f SECONDS\n",
907            filename,(float)(count2-count1)/1000.0);
908 #endif
909
910 #endif
911
912     if (!clipmask[pos])
913     {
914       fprintf(stderr, "%s: cannot get clipmask for '%s'.\n",
915               progname, pic->picture_filename);
916       CloseAll();
917       exit(-1);
918     }
919   }
920 }
921
922 void InitElementProperties()
923 {
924   int i,j;
925
926   static int ep_amoebalive[] =
927   {
928     EL_AMOEBE_NASS,
929     EL_AMOEBE_NORM,
930     EL_AMOEBE_VOLL,
931     EL_AMOEBE_BD
932   };
933   static int ep_amoebalive_num = sizeof(ep_amoebalive)/sizeof(int);
934
935   static int ep_amoeboid[] =
936   {
937     EL_AMOEBE_TOT,
938     EL_AMOEBE_NASS,
939     EL_AMOEBE_NORM,
940     EL_AMOEBE_VOLL,
941     EL_AMOEBE_BD
942   };
943   static int ep_amoeboid_num = sizeof(ep_amoeboid)/sizeof(int);
944
945   static int ep_schluessel[] =
946   {
947     EL_SCHLUESSEL1,
948     EL_SCHLUESSEL2,
949     EL_SCHLUESSEL3,
950     EL_SCHLUESSEL4
951   };
952   static int ep_schluessel_num = sizeof(ep_schluessel)/sizeof(int);
953
954   static int ep_pforte[] =
955   {
956     EL_PFORTE1,
957     EL_PFORTE2,
958     EL_PFORTE3,
959     EL_PFORTE4,
960     EL_PFORTE1X,
961     EL_PFORTE2X,
962     EL_PFORTE3X,
963     EL_PFORTE4X
964   };
965   static int ep_pforte_num = sizeof(ep_pforte)/sizeof(int);
966
967   static int ep_solid[] =
968   {
969     EL_BETON,
970     EL_MAUERWERK,
971     EL_MAUER_LEBT,
972     EL_FELSBODEN,
973     EL_AUSGANG_ZU,
974     EL_AUSGANG_ACT,
975     EL_AUSGANG_AUF,
976     EL_AMOEBE_TOT,
977     EL_AMOEBE_NASS,
978     EL_AMOEBE_NORM,
979     EL_AMOEBE_VOLL,
980     EL_AMOEBE_BD,
981     EL_MORAST_VOLL,
982     EL_MORAST_LEER,
983     EL_SIEB_VOLL,
984     EL_SIEB_LEER,
985     EL_SIEB_TOT,
986     EL_SIEB2_VOLL,
987     EL_SIEB2_LEER,
988     EL_SIEB2_TOT,
989     EL_LIFE,
990     EL_LIFE_ASYNC,
991     EL_BADEWANNE1,
992     EL_BADEWANNE2,
993     EL_BADEWANNE3,
994     EL_BADEWANNE4,
995     EL_BADEWANNE5
996   };
997   static int ep_solid_num = sizeof(ep_solid)/sizeof(int);
998
999   static int ep_massiv[] =
1000   {
1001     EL_BETON,
1002     EL_SALZSAEURE,
1003     EL_BADEWANNE1,
1004     EL_BADEWANNE2,
1005     EL_BADEWANNE3,
1006     EL_BADEWANNE4,
1007     EL_BADEWANNE5,
1008     EL_PFORTE1,
1009     EL_PFORTE2,
1010     EL_PFORTE3,
1011     EL_PFORTE4,
1012     EL_PFORTE1X,
1013     EL_PFORTE2X,
1014     EL_PFORTE3X,
1015     EL_PFORTE4X
1016   };
1017   static int ep_massiv_num = sizeof(ep_massiv)/sizeof(int);
1018
1019   static int ep_slippery[] =
1020   {
1021     EL_FELSBODEN,
1022     EL_FELSBROCKEN,
1023     EL_EDELSTEIN,
1024     EL_EDELSTEIN_BD,
1025     EL_EDELSTEIN_GELB,
1026     EL_EDELSTEIN_ROT,
1027     EL_EDELSTEIN_LILA,
1028     EL_DIAMANT,
1029     EL_BOMBE,
1030     EL_KOKOSNUSS,
1031     EL_ABLENK_EIN,
1032     EL_ABLENK_AUS,
1033     EL_ZEIT_VOLL,
1034     EL_ZEIT_LEER,
1035     EL_BIRNE_EIN,
1036     EL_BIRNE_AUS,
1037     EL_BADEWANNE1,
1038     EL_BADEWANNE2,
1039     EL_SONDE
1040   };
1041   static int ep_slippery_num = sizeof(ep_slippery)/sizeof(int);
1042
1043   static int ep_enemy[] =
1044   {
1045     EL_KAEFER,
1046     EL_FLIEGER,
1047     EL_BUTTERFLY,
1048     EL_FIREFLY,
1049     EL_MAMPFER,
1050     EL_MAMPFER2,
1051     EL_ROBOT,
1052     EL_PACMAN
1053   };
1054   static int ep_enemy_num = sizeof(ep_enemy)/sizeof(int);
1055
1056   static int ep_mauer[] =
1057   {
1058     EL_BETON,
1059     EL_PFORTE1,
1060     EL_PFORTE2,
1061     EL_PFORTE3,
1062     EL_PFORTE4,
1063     EL_PFORTE1X,
1064     EL_PFORTE2X,
1065     EL_PFORTE3X,
1066     EL_PFORTE4X,
1067     EL_AUSGANG_ZU,
1068     EL_AUSGANG_ACT,
1069     EL_AUSGANG_AUF,
1070     EL_MAUERWERK,
1071     EL_FELSBODEN,
1072     EL_MAUER_LEBT,
1073     EL_MAUERND
1074   };
1075   static int ep_mauer_num = sizeof(ep_mauer)/sizeof(int);
1076
1077   static int ep_can_fall[] =
1078   {
1079     EL_FELSBROCKEN,
1080     EL_EDELSTEIN,
1081     EL_EDELSTEIN_BD,
1082     EL_EDELSTEIN_GELB,
1083     EL_EDELSTEIN_ROT,
1084     EL_EDELSTEIN_LILA,
1085     EL_DIAMANT,
1086     EL_BOMBE,
1087     EL_KOKOSNUSS,
1088     EL_TROPFEN,
1089     EL_MORAST_VOLL,
1090     EL_SIEB_VOLL,
1091     EL_SIEB2_VOLL,
1092     EL_ZEIT_VOLL,
1093     EL_ZEIT_LEER
1094   };
1095   static int ep_can_fall_num = sizeof(ep_can_fall)/sizeof(int);
1096
1097   static int ep_can_smash[] =
1098   {
1099     EL_FELSBROCKEN,
1100     EL_EDELSTEIN,
1101     EL_EDELSTEIN_BD,
1102     EL_EDELSTEIN_GELB,
1103     EL_EDELSTEIN_ROT,
1104     EL_EDELSTEIN_LILA,
1105     EL_DIAMANT,
1106     EL_SCHLUESSEL1,
1107     EL_SCHLUESSEL2,
1108     EL_SCHLUESSEL3,
1109     EL_SCHLUESSEL4,
1110     EL_BOMBE,
1111     EL_KOKOSNUSS,
1112     EL_TROPFEN,
1113     EL_ZEIT_VOLL,
1114     EL_ZEIT_LEER
1115   };
1116   static int ep_can_smash_num = sizeof(ep_can_smash)/sizeof(int);
1117
1118   static int ep_can_change[] =
1119   {
1120     EL_FELSBROCKEN,
1121     EL_EDELSTEIN,
1122     EL_EDELSTEIN_BD,
1123     EL_EDELSTEIN_GELB,
1124     EL_EDELSTEIN_ROT,
1125     EL_EDELSTEIN_LILA,
1126     EL_DIAMANT
1127   };
1128   static int ep_can_change_num = sizeof(ep_can_change)/sizeof(int);
1129
1130   static int ep_can_move[] =
1131   {
1132     EL_KAEFER,
1133     EL_FLIEGER,
1134     EL_BUTTERFLY,
1135     EL_FIREFLY,
1136     EL_MAMPFER,
1137     EL_MAMPFER2,
1138     EL_ROBOT,
1139     EL_PACMAN,
1140     EL_MAULWURF,
1141     EL_PINGUIN,
1142     EL_SCHWEIN,
1143     EL_DRACHE,
1144     EL_SONDE
1145   };
1146   static int ep_can_move_num = sizeof(ep_can_move)/sizeof(int);
1147
1148   static int ep_could_move[] =
1149   {
1150     EL_KAEFER_R,
1151     EL_KAEFER_O,
1152     EL_KAEFER_L,
1153     EL_KAEFER_U,
1154     EL_FLIEGER_R,
1155     EL_FLIEGER_O,
1156     EL_FLIEGER_L,
1157     EL_FLIEGER_U,
1158     EL_BUTTERFLY_R,
1159     EL_BUTTERFLY_O,
1160     EL_BUTTERFLY_L,
1161     EL_BUTTERFLY_U,
1162     EL_FIREFLY_R,
1163     EL_FIREFLY_O,
1164     EL_FIREFLY_L,
1165     EL_FIREFLY_U,
1166     EL_PACMAN_R,
1167     EL_PACMAN_O,
1168     EL_PACMAN_L,
1169     EL_PACMAN_U
1170   };
1171   static int ep_could_move_num = sizeof(ep_could_move)/sizeof(int);
1172
1173   static int ep_dont_touch[] =
1174   {
1175     EL_KAEFER,
1176     EL_FLIEGER,
1177     EL_BUTTERFLY,
1178     EL_FIREFLY
1179   };
1180   static int ep_dont_touch_num = sizeof(ep_dont_touch)/sizeof(int);
1181
1182   static int ep_dont_go_to[] =
1183   {
1184     EL_KAEFER,
1185     EL_FLIEGER,
1186     EL_BUTTERFLY,
1187     EL_FIREFLY,
1188     EL_MAMPFER,
1189     EL_MAMPFER2,
1190     EL_ROBOT,
1191     EL_PACMAN,
1192     EL_TROPFEN,
1193     EL_SALZSAEURE
1194   };
1195   static int ep_dont_go_to_num = sizeof(ep_dont_go_to)/sizeof(int);
1196
1197   static int ep_mampf2[] =
1198   {
1199     EL_ERDREICH,
1200     EL_KAEFER,
1201     EL_FLIEGER,
1202     EL_BUTTERFLY,
1203     EL_FIREFLY,
1204     EL_MAMPFER,
1205     EL_ROBOT,
1206     EL_PACMAN,
1207     EL_TROPFEN,
1208     EL_AMOEBE_TOT,
1209     EL_AMOEBE_NASS,
1210     EL_AMOEBE_NORM,
1211     EL_AMOEBE_VOLL,
1212     EL_AMOEBE_BD,
1213     EL_EDELSTEIN,
1214     EL_EDELSTEIN_BD,
1215     EL_EDELSTEIN_GELB,
1216     EL_EDELSTEIN_ROT,
1217     EL_EDELSTEIN_LILA,
1218     EL_DIAMANT
1219   };
1220   static int ep_mampf2_num = sizeof(ep_mampf2)/sizeof(int);
1221
1222   static int ep_bd_element[] =
1223   {
1224     EL_LEERRAUM,
1225     EL_ERDREICH,
1226     EL_FELSBODEN,
1227     EL_FELSBROCKEN,
1228     EL_EDELSTEIN_BD,
1229     EL_SIEB2_LEER,
1230     EL_AUSGANG_ZU,
1231     EL_AUSGANG_AUF,
1232     EL_BETON,
1233     EL_SPIELFIGUR,
1234     EL_FIREFLY,
1235     EL_FIREFLY_1,
1236     EL_FIREFLY_2,
1237     EL_FIREFLY_3,
1238     EL_FIREFLY_4,
1239     EL_BUTTERFLY,
1240     EL_BUTTERFLY_1,
1241     EL_BUTTERFLY_2,
1242     EL_BUTTERFLY_3,
1243     EL_BUTTERFLY_4,
1244     EL_AMOEBE_BD,
1245     EL_CHAR_FRAGE
1246   };
1247   static int ep_bd_element_num = sizeof(ep_bd_element)/sizeof(int);
1248
1249   static int ep_sb_element[] =
1250   {
1251     EL_LEERRAUM,
1252     EL_BETON,
1253     EL_SOKOBAN_OBJEKT,
1254     EL_SOKOBAN_FELD_LEER,
1255     EL_SOKOBAN_FELD_VOLL,
1256     EL_SPIELFIGUR
1257   };
1258   static int ep_sb_element_num = sizeof(ep_sb_element)/sizeof(int);
1259
1260   static int ep_gem[] =
1261   {
1262     EL_EDELSTEIN,
1263     EL_EDELSTEIN_BD,
1264     EL_EDELSTEIN_GELB,
1265     EL_EDELSTEIN_ROT,
1266     EL_EDELSTEIN_LILA,
1267     EL_DIAMANT
1268   };
1269   static int ep_gem_num = sizeof(ep_gem)/sizeof(int);
1270
1271   static int ep_inactive[] =
1272   {
1273     EL_LEERRAUM,
1274     EL_ERDREICH,
1275     EL_MAUERWERK,
1276     EL_FELSBODEN,
1277     EL_SCHLUESSEL,
1278     EL_BETON,
1279     EL_AMOEBE_TOT,
1280     EL_MORAST_LEER,
1281     EL_BADEWANNE,
1282     EL_ABLENK_AUS,
1283     EL_SCHLUESSEL1,
1284     EL_SCHLUESSEL2,
1285     EL_SCHLUESSEL3,
1286     EL_SCHLUESSEL4,
1287     EL_PFORTE1,
1288     EL_PFORTE2,
1289     EL_PFORTE3,
1290     EL_PFORTE4,
1291     EL_PFORTE1X,
1292     EL_PFORTE2X,
1293     EL_PFORTE3X,
1294     EL_PFORTE4X,
1295     EL_DYNAMIT_AUS,
1296     EL_UNSICHTBAR,
1297     EL_BIRNE_AUS,
1298     EL_BIRNE_EIN,
1299     EL_ERZ_EDEL,
1300     EL_ERZ_DIAM,
1301     EL_ERZ_EDEL_BD,
1302     EL_ERZ_EDEL_GELB,
1303     EL_DYNABOMB_NR,
1304     EL_DYNABOMB_SZ,
1305     EL_DYNABOMB_XL,
1306     EL_SOKOBAN_OBJEKT,
1307     EL_SOKOBAN_FELD_LEER,
1308     EL_SOKOBAN_FELD_VOLL,
1309     EL_ERZ_EDEL_ROT,
1310     EL_ERZ_EDEL_LILA,
1311     EL_BADEWANNE1,
1312     EL_BADEWANNE2,
1313     EL_BADEWANNE3,
1314     EL_BADEWANNE4,
1315     EL_BADEWANNE5,
1316     EL_SIEB_TOT,
1317     EL_SIEB2_TOT,
1318     EL_AMOEBA2DIAM,
1319     EL_BLOCKED
1320   };
1321   static int ep_inactive_num = sizeof(ep_inactive)/sizeof(int);
1322
1323   static int ep_explosive[] =
1324   {
1325     EL_BOMBE,
1326     EL_DYNAMIT,
1327     EL_DYNAMIT_AUS,
1328     EL_DYNABOMB,
1329     EL_DYNABOMB_NR,
1330     EL_DYNABOMB_SZ,
1331     EL_DYNABOMB_XL,
1332     EL_KAEFER,
1333     EL_MAULWURF,
1334     EL_PINGUIN,
1335     EL_SCHWEIN,
1336     EL_DRACHE,
1337     EL_SONDE
1338   };
1339   static int ep_explosive_num = sizeof(ep_explosive)/sizeof(int);
1340
1341   static int ep_mampf3[] =
1342   {
1343     EL_EDELSTEIN,
1344     EL_EDELSTEIN_BD,
1345     EL_EDELSTEIN_GELB,
1346     EL_EDELSTEIN_ROT,
1347     EL_EDELSTEIN_LILA,
1348     EL_DIAMANT
1349   };
1350   static int ep_mampf3_num = sizeof(ep_mampf3)/sizeof(int);
1351
1352   static int ep_pushable[] =
1353   {
1354     EL_FELSBROCKEN,
1355     EL_BOMBE,
1356     EL_KOKOSNUSS,
1357     EL_ZEIT_LEER,
1358     EL_SOKOBAN_FELD_VOLL,
1359     EL_SOKOBAN_OBJEKT,
1360     EL_SONDE
1361   };
1362   static int ep_pushable_num = sizeof(ep_pushable)/sizeof(int);
1363
1364   static int ep_player[] =
1365   {
1366     EL_SPIELFIGUR,
1367     EL_SPIELER1,
1368     EL_SPIELER2,
1369     EL_SPIELER3,
1370     EL_SPIELER4
1371   };
1372   static int ep_player_num = sizeof(ep_player)/sizeof(int);
1373
1374   static long ep_bit[] =
1375   {
1376     EP_BIT_AMOEBALIVE,
1377     EP_BIT_AMOEBOID,
1378     EP_BIT_SCHLUESSEL,
1379     EP_BIT_PFORTE,
1380     EP_BIT_SOLID,
1381     EP_BIT_MASSIV,
1382     EP_BIT_SLIPPERY,
1383     EP_BIT_ENEMY,
1384     EP_BIT_MAUER,
1385     EP_BIT_CAN_FALL,
1386     EP_BIT_CAN_SMASH,
1387     EP_BIT_CAN_CHANGE,
1388     EP_BIT_CAN_MOVE,
1389     EP_BIT_COULD_MOVE,
1390     EP_BIT_DONT_TOUCH,
1391     EP_BIT_DONT_GO_TO,
1392     EP_BIT_MAMPF2,
1393     EP_BIT_BD_ELEMENT,
1394     EP_BIT_SB_ELEMENT,
1395     EP_BIT_GEM,
1396     EP_BIT_INACTIVE,
1397     EP_BIT_EXPLOSIVE,
1398     EP_BIT_MAMPF3,
1399     EP_BIT_PUSHABLE,
1400     EP_BIT_PLAYER
1401   };
1402   static int *ep_array[] =
1403   {
1404     ep_amoebalive,
1405     ep_amoeboid,
1406     ep_schluessel,
1407     ep_pforte,
1408     ep_solid,
1409     ep_massiv,
1410     ep_slippery,
1411     ep_enemy,
1412     ep_mauer,
1413     ep_can_fall,
1414     ep_can_smash,
1415     ep_can_change,
1416     ep_can_move,
1417     ep_could_move,
1418     ep_dont_touch,
1419     ep_dont_go_to,
1420     ep_mampf2,
1421     ep_bd_element,
1422     ep_sb_element,
1423     ep_gem,
1424     ep_inactive,
1425     ep_explosive,
1426     ep_mampf3,
1427     ep_pushable,
1428     ep_player
1429   };
1430   static int *ep_num[] =
1431   {
1432     &ep_amoebalive_num,
1433     &ep_amoeboid_num,
1434     &ep_schluessel_num,
1435     &ep_pforte_num,
1436     &ep_solid_num,
1437     &ep_massiv_num,
1438     &ep_slippery_num,
1439     &ep_enemy_num,
1440     &ep_mauer_num,
1441     &ep_can_fall_num,
1442     &ep_can_smash_num,
1443     &ep_can_change_num,
1444     &ep_can_move_num,
1445     &ep_could_move_num,
1446     &ep_dont_touch_num,
1447     &ep_dont_go_to_num,
1448     &ep_mampf2_num,
1449     &ep_bd_element_num,
1450     &ep_sb_element_num,
1451     &ep_gem_num,
1452     &ep_inactive_num,
1453     &ep_explosive_num,
1454     &ep_mampf3_num,
1455     &ep_pushable_num,
1456     &ep_player_num
1457   };
1458   static int num_properties = sizeof(ep_num)/sizeof(int *);
1459
1460   for(i=0;i<MAX_ELEMENTS;i++)
1461     Elementeigenschaften[i] = 0;
1462
1463   for(i=0;i<num_properties;i++)
1464     for(j=0;j<*(ep_num[i]);j++)
1465       Elementeigenschaften[(ep_array[i])[j]] |= ep_bit[i];
1466   for(i=EL_CHAR_START;i<EL_CHAR_END;i++)
1467     Elementeigenschaften[i] |= (EP_BIT_CHAR | EP_BIT_INACTIVE);
1468 }
1469
1470 void CloseAll()
1471 {
1472   int i;
1473
1474   if (sound_process_id)
1475   {
1476     StopSounds();
1477     kill(sound_process_id, SIGTERM);
1478     FreeSounds(NUM_SOUNDS);
1479   }
1480
1481   for(i=0;i<NUM_PIXMAPS;i++)
1482   {
1483     if (pix[i])
1484     {
1485 #ifdef XPM_INCLUDE_FILE
1486       if (i<NUM_PICTURES)       /* XPM pictures */
1487       {
1488         XFreeColors(display,DefaultColormap(display,screen),
1489                     xpm_att[i].pixels,xpm_att[i].npixels,0);
1490         XpmFreeAttributes(&xpm_att[i]);
1491       }
1492 #endif
1493       XFreePixmap(display,pix[i]);
1494     }
1495     if (clipmask[i])
1496       XFreePixmap(display,clipmask[i]);
1497     if (clip_gc[i])
1498       XFreeGC(display, clip_gc[i]);
1499   }
1500
1501   if (gc)
1502     XFreeGC(display, gc);
1503
1504   if (display)
1505   {
1506     XAutoRepeatOn(display);
1507     XCloseDisplay(display);
1508   }
1509
1510   exit(0);
1511 }