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