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