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