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