rnd-19980904
[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 #ifdef MSDOS
508   char *picture_ext = ".gif";
509 #else
510   char *picture_ext = ".xpm";
511 #endif
512   char *picturemask_ext = "Mask.xbm";
513 #else
514   int gif_err, ilbm_err;
515   char *picture_ext = ".gif";
516   char *picturemask_ext = "Mask.ilbm";
517 #endif
518
519 #ifdef DEBUG_TIMING
520   long count1, count2;
521 #endif
522
523   /* Grafik laden */
524   if (pic->picture_filename)
525   {
526
527
528
529
530
531     sprintf(basefilename,"%s%s",pic->picture_filename,".gif");
532     DrawInitText(basefilename,150,FC_YELLOW);
533     sprintf(filename,"%s/%s",GFX_PATH,basefilename);
534
535 #ifdef DEBUG_TIMING
536     count1 = Counter();
537 #endif
538
539     Read_GIF_to_Pixmaps(display, window, filename);
540
541 #ifdef DEBUG_TIMING
542     count2 = Counter();
543     printf("GIF LOADING %s IN %.2f SECONDS\n",
544            filename,(float)(count2-count1)/100.0);
545 #endif
546
547
548
549
550
551
552     sprintf(basefilename,"%s%s",pic->picture_filename,picture_ext);
553     DrawInitText(basefilename,150,FC_YELLOW);
554 #ifdef MSDOS
555     rest(100);
556 #endif MSDOS
557     sprintf(filename,"%s/%s",GFX_PATH,basefilename);
558
559 #ifdef DEBUG_TIMING
560     count1 = Counter();
561 #endif
562
563 #ifdef XPM_INCLUDE_FILE
564
565     xpm_att[pos].valuemask = XpmCloseness;
566     xpm_att[pos].closeness = 65535;
567
568     /*
569     xpm_att[pos].closeness = 20000;
570     */
571
572 #if 0
573     xpm_err = XpmReadFileToPixmap(display,window,filename,
574                                   &pix[pos],&shapemask,&xpm_att[pos]);
575 #else
576     xpm_err = XpmSuccess;
577 #endif
578
579     switch(xpm_err)
580     {
581       case XpmOpenFailed:
582         fprintf(stderr,"Cannot open Xpm file '%s' !\n",filename);
583         CloseAll();
584         exit(-1);
585       case XpmFileInvalid:
586         fprintf(stderr,"Invalid Xpm file '%s'!\n",filename);
587         CloseAll();
588         exit(-1);
589       case XpmNoMemory:
590         fprintf(stderr,"Not enough memory for Xpm file '%s'!\n",filename);
591         CloseAll();
592         exit(1);
593       case XpmColorFailed:
594         fprintf(stderr,"Can't get colors for Xpm file '%s'!\n",filename);
595         CloseAll();
596         exit(-1);
597       default:
598         break;
599     }
600
601 #else 
602
603     gif_err = Read_GIF_to_Pixmap(display,filename,&pix[pos]);
604
605     switch(gif_err)
606     {
607       case GIF_Success:
608         break;
609       case GIF_OpenFailed:
610         fprintf(stderr,"Cannot open GIF file '%s' !\n",filename);
611         CloseAll();
612         exit(-1);
613       case GIF_ReadFailed:
614         fprintf(stderr,"Cannot read GIF file '%s' !\n",filename);
615         CloseAll();
616         exit(-1);
617       case GIF_FileInvalid:
618         fprintf(stderr,"Invalid GIF file '%s'!\n",filename);
619         CloseAll();
620         exit(-1);
621       case GIF_NoMemory:
622         fprintf(stderr,"Not enough memory for GIF file '%s'!\n",filename);
623         CloseAll();
624         exit(1);
625       case GIF_ColorFailed:
626         fprintf(stderr,"Can't get colors for GIF file '%s'!\n",filename);
627         CloseAll();
628         exit(-1);
629       default:
630         break;
631     }
632
633 #endif
634
635 #ifdef DEBUG_TIMING
636     count2 = Counter();
637     /*
638     printf("XPM LOADING %s IN %.2f SECONDS\n",
639            filename,(float)(count2-count1)/100.0);
640            */
641 #endif
642
643 #if 0
644     if (!pix[pos])
645     {
646       fprintf(stderr, "%s: cannot read graphics file '%s'.\n",
647               progname,filename);
648       CloseAll();
649       exit(-1);
650     }
651 #endif
652
653   }
654
655   /* zugehörige Maske laden (wenn vorhanden) */
656   if (pic->picture_with_mask)
657   {
658 #ifdef MSDOS
659     xbm_err = BitmapSuccess;
660     clipmask[pos] = DUMMY_MASK;
661     goto msdos_jmp;
662 #else
663     sprintf(basefilename,"%s%s",pic->picture_filename,picturemask_ext);
664     DrawInitText(basefilename,150,FC_YELLOW);
665     sprintf(filename,"%s/%s",GFX_PATH,basefilename);
666 #endif
667
668 #ifdef DEBUG_TIMING
669     count1 = Counter();
670 #endif
671
672 #ifdef XPM_INCLUDE_FILE
673
674 #if 0
675     xbm_err = XReadBitmapFile(display,window,filename,
676                               &width,&height,&clipmask[pos],&hot_x,&hot_y);
677 #else
678     xbm_err = BitmapSuccess;
679 #endif
680
681 #ifdef MSDOS
682 msdos_jmp:
683 #endif
684     switch(xbm_err)
685     {
686       case BitmapSuccess:
687         break;
688       case BitmapOpenFailed:
689         fprintf(stderr,"Bitmap file open failed on '%s' !\n",filename);
690         CloseAll();
691         exit(-1);
692         break;
693       case BitmapFileInvalid:
694         fprintf(stderr,"Bitmap file invalid: '%s' !\n",filename);
695         CloseAll();
696         exit(-1);
697         break;
698       case BitmapNoMemory:
699         fprintf(stderr,"No memory for file '%s' !\n",filename);
700         CloseAll();
701         exit(-1);
702         break;
703       default:
704         break;
705     }
706
707 #else
708
709     ilbm_err = Read_ILBM_to_Bitmap(display,filename,&clipmask[pos]);
710
711     switch(ilbm_err)
712     {
713       case ILBM_Success:
714         break;
715       case ILBM_OpenFailed:
716         fprintf(stderr,"Cannot open ILBM file '%s' !\n",filename);
717         CloseAll();
718         exit(-1);
719       case ILBM_ReadFailed:
720         fprintf(stderr,"Cannot read ILBM file '%s' !\n",filename);
721         CloseAll();
722         exit(-1);
723       case ILBM_FileInvalid:
724         fprintf(stderr,"Invalid ILBM file '%s'!\n",filename);
725         CloseAll();
726         exit(-1);
727       case ILBM_NoMemory:
728         fprintf(stderr,"Not enough memory for ILBM file '%s'!\n",filename);
729         CloseAll();
730         exit(1);
731       default:
732         break;
733     }
734
735 #endif
736
737 #ifdef DEBUG_TIMING
738     count2 = Counter();
739     /*
740     printf("LOADING %s IN %.2f SECONDS\n",
741            filename,(float)(count2-count1)/100.0);
742            */
743 #endif
744
745 #if 0
746     if (!clipmask[pos])
747     {
748       fprintf(stderr, "%s: cannot read graphics file '%s'.\n",
749               progname,filename);
750       CloseAll();
751       exit(-1);
752     }
753 #endif
754
755   }
756
757   pix[pos] = test_pix[test_picture_count-1];
758   clipmask[pos] = test_clipmask[test_picture_count-1];
759 }
760
761 void InitElementProperties()
762 {
763   int i,j;
764
765   static int ep_amoebalive[] =
766   {
767     EL_AMOEBE_NASS,
768     EL_AMOEBE_NORM,
769     EL_AMOEBE_VOLL,
770     EL_AMOEBE_BD
771   };
772   static int ep_amoebalive_num = sizeof(ep_amoebalive)/sizeof(int);
773
774   static int ep_amoeboid[] =
775   {
776     EL_AMOEBE_TOT,
777     EL_AMOEBE_NASS,
778     EL_AMOEBE_NORM,
779     EL_AMOEBE_VOLL,
780     EL_AMOEBE_BD
781   };
782   static int ep_amoeboid_num = sizeof(ep_amoeboid)/sizeof(int);
783
784   static int ep_schluessel[] =
785   {
786     EL_SCHLUESSEL1,
787     EL_SCHLUESSEL2,
788     EL_SCHLUESSEL3,
789     EL_SCHLUESSEL4
790   };
791   static int ep_schluessel_num = sizeof(ep_schluessel)/sizeof(int);
792
793   static int ep_pforte[] =
794   {
795     EL_PFORTE1,
796     EL_PFORTE2,
797     EL_PFORTE3,
798     EL_PFORTE4,
799     EL_PFORTE1X,
800     EL_PFORTE2X,
801     EL_PFORTE3X,
802     EL_PFORTE4X
803   };
804   static int ep_pforte_num = sizeof(ep_pforte)/sizeof(int);
805
806   static int ep_solid[] =
807   {
808     EL_BETON,
809     EL_MAUERWERK,
810     EL_MAUER_LEBT,
811     EL_FELSBODEN,
812     EL_AUSGANG_ZU,
813     EL_AUSGANG_ACT,
814     EL_AUSGANG_AUF,
815     EL_AMOEBE_TOT,
816     EL_AMOEBE_NASS,
817     EL_AMOEBE_NORM,
818     EL_AMOEBE_VOLL,
819     EL_AMOEBE_BD,
820     EL_MORAST_VOLL,
821     EL_MORAST_LEER,
822     EL_SIEB_VOLL,
823     EL_SIEB_LEER,
824     EL_SIEB_TOT,
825     EL_SIEB2_VOLL,
826     EL_SIEB2_LEER,
827     EL_SIEB2_TOT,
828     EL_LIFE,
829     EL_LIFE_ASYNC,
830     EL_BADEWANNE1,
831     EL_BADEWANNE2,
832     EL_BADEWANNE3,
833     EL_BADEWANNE4,
834     EL_BADEWANNE5
835   };
836   static int ep_solid_num = sizeof(ep_solid)/sizeof(int);
837
838   static int ep_massiv[] =
839   {
840     EL_BETON,
841     EL_SALZSAEURE,
842     EL_BADEWANNE1,
843     EL_BADEWANNE2,
844     EL_BADEWANNE3,
845     EL_BADEWANNE4,
846     EL_BADEWANNE5,
847     EL_PFORTE1,
848     EL_PFORTE2,
849     EL_PFORTE3,
850     EL_PFORTE4,
851     EL_PFORTE1X,
852     EL_PFORTE2X,
853     EL_PFORTE3X,
854     EL_PFORTE4X
855   };
856   static int ep_massiv_num = sizeof(ep_massiv)/sizeof(int);
857
858   static int ep_slippery[] =
859   {
860     EL_FELSBODEN,
861     EL_FELSBROCKEN,
862     EL_EDELSTEIN,
863     EL_EDELSTEIN_BD,
864     EL_EDELSTEIN_GELB,
865     EL_EDELSTEIN_ROT,
866     EL_EDELSTEIN_LILA,
867     EL_DIAMANT,
868     EL_BOMBE,
869     EL_KOKOSNUSS,
870     EL_ABLENK_EIN,
871     EL_ABLENK_AUS,
872     EL_ZEIT_VOLL,
873     EL_ZEIT_LEER,
874     EL_BIRNE_EIN,
875     EL_BIRNE_AUS,
876     EL_BADEWANNE1,
877     EL_BADEWANNE2,
878     EL_SONDE
879   };
880   static int ep_slippery_num = sizeof(ep_slippery)/sizeof(int);
881
882   static int ep_enemy[] =
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   };
893   static int ep_enemy_num = sizeof(ep_enemy)/sizeof(int);
894
895   static int ep_mauer[] =
896   {
897     EL_BETON,
898     EL_PFORTE1,
899     EL_PFORTE2,
900     EL_PFORTE3,
901     EL_PFORTE4,
902     EL_PFORTE1X,
903     EL_PFORTE2X,
904     EL_PFORTE3X,
905     EL_PFORTE4X,
906     EL_AUSGANG_ZU,
907     EL_AUSGANG_ACT,
908     EL_AUSGANG_AUF,
909     EL_MAUERWERK,
910     EL_FELSBODEN,
911     EL_MAUER_LEBT,
912     EL_MAUERND
913   };
914   static int ep_mauer_num = sizeof(ep_mauer)/sizeof(int);
915
916   static int ep_can_fall[] =
917   {
918     EL_FELSBROCKEN,
919     EL_EDELSTEIN,
920     EL_EDELSTEIN_BD,
921     EL_EDELSTEIN_GELB,
922     EL_EDELSTEIN_ROT,
923     EL_EDELSTEIN_LILA,
924     EL_DIAMANT,
925     EL_BOMBE,
926     EL_KOKOSNUSS,
927     EL_TROPFEN,
928     EL_MORAST_VOLL,
929     EL_SIEB_VOLL,
930     EL_SIEB2_VOLL,
931     EL_ZEIT_VOLL,
932     EL_ZEIT_LEER
933   };
934   static int ep_can_fall_num = sizeof(ep_can_fall)/sizeof(int);
935
936   static int ep_can_smash[] =
937   {
938     EL_FELSBROCKEN,
939     EL_EDELSTEIN,
940     EL_EDELSTEIN_BD,
941     EL_EDELSTEIN_GELB,
942     EL_EDELSTEIN_ROT,
943     EL_EDELSTEIN_LILA,
944     EL_DIAMANT,
945     EL_SCHLUESSEL1,
946     EL_SCHLUESSEL2,
947     EL_SCHLUESSEL3,
948     EL_SCHLUESSEL4,
949     EL_BOMBE,
950     EL_KOKOSNUSS,
951     EL_TROPFEN,
952     EL_ZEIT_VOLL,
953     EL_ZEIT_LEER
954   };
955   static int ep_can_smash_num = sizeof(ep_can_smash)/sizeof(int);
956
957   static int ep_can_change[] =
958   {
959     EL_FELSBROCKEN,
960     EL_EDELSTEIN,
961     EL_EDELSTEIN_BD,
962     EL_EDELSTEIN_GELB,
963     EL_EDELSTEIN_ROT,
964     EL_EDELSTEIN_LILA,
965     EL_DIAMANT
966   };
967   static int ep_can_change_num = sizeof(ep_can_change)/sizeof(int);
968
969   static int ep_can_move[] =
970   {
971     EL_KAEFER,
972     EL_FLIEGER,
973     EL_BUTTERFLY,
974     EL_FIREFLY,
975     EL_MAMPFER,
976     EL_MAMPFER2,
977     EL_ROBOT,
978     EL_PACMAN,
979     EL_MAULWURF,
980     EL_PINGUIN,
981     EL_SCHWEIN,
982     EL_DRACHE,
983     EL_SONDE
984   };
985   static int ep_can_move_num = sizeof(ep_can_move)/sizeof(int);
986
987   static int ep_could_move[] =
988   {
989     EL_KAEFER_R,
990     EL_KAEFER_O,
991     EL_KAEFER_L,
992     EL_KAEFER_U,
993     EL_FLIEGER_R,
994     EL_FLIEGER_O,
995     EL_FLIEGER_L,
996     EL_FLIEGER_U,
997     EL_BUTTERFLY_R,
998     EL_BUTTERFLY_O,
999     EL_BUTTERFLY_L,
1000     EL_BUTTERFLY_U,
1001     EL_FIREFLY_R,
1002     EL_FIREFLY_O,
1003     EL_FIREFLY_L,
1004     EL_FIREFLY_U,
1005     EL_PACMAN_R,
1006     EL_PACMAN_O,
1007     EL_PACMAN_L,
1008     EL_PACMAN_U
1009   };
1010   static int ep_could_move_num = sizeof(ep_could_move)/sizeof(int);
1011
1012   static int ep_dont_touch[] =
1013   {
1014     EL_KAEFER,
1015     EL_FLIEGER,
1016     EL_BUTTERFLY,
1017     EL_FIREFLY
1018   };
1019   static int ep_dont_touch_num = sizeof(ep_dont_touch)/sizeof(int);
1020
1021   static int ep_dont_go_to[] =
1022   {
1023     EL_KAEFER,
1024     EL_FLIEGER,
1025     EL_BUTTERFLY,
1026     EL_FIREFLY,
1027     EL_MAMPFER,
1028     EL_MAMPFER2,
1029     EL_ROBOT,
1030     EL_PACMAN,
1031     EL_TROPFEN,
1032     EL_SALZSAEURE
1033   };
1034   static int ep_dont_go_to_num = sizeof(ep_dont_go_to)/sizeof(int);
1035
1036   static int ep_mampf2[] =
1037   {
1038     EL_ERDREICH,
1039     EL_KAEFER,
1040     EL_FLIEGER,
1041     EL_BUTTERFLY,
1042     EL_FIREFLY,
1043     EL_MAMPFER,
1044     EL_ROBOT,
1045     EL_PACMAN,
1046     EL_TROPFEN,
1047     EL_AMOEBE_TOT,
1048     EL_AMOEBE_NASS,
1049     EL_AMOEBE_NORM,
1050     EL_AMOEBE_VOLL,
1051     EL_AMOEBE_BD,
1052     EL_EDELSTEIN,
1053     EL_EDELSTEIN_BD,
1054     EL_EDELSTEIN_GELB,
1055     EL_EDELSTEIN_ROT,
1056     EL_EDELSTEIN_LILA,
1057     EL_DIAMANT
1058   };
1059   static int ep_mampf2_num = sizeof(ep_mampf2)/sizeof(int);
1060
1061   static int ep_bd_element[] =
1062   {
1063     EL_LEERRAUM,
1064     EL_ERDREICH,
1065     EL_FELSBODEN,
1066     EL_FELSBROCKEN,
1067     EL_EDELSTEIN_BD,
1068     EL_SIEB2_LEER,
1069     EL_AUSGANG_ZU,
1070     EL_AUSGANG_AUF,
1071     EL_BETON,
1072     EL_SPIELFIGUR,
1073     EL_FIREFLY,
1074     EL_FIREFLY_1,
1075     EL_FIREFLY_2,
1076     EL_FIREFLY_3,
1077     EL_FIREFLY_4,
1078     EL_BUTTERFLY,
1079     EL_BUTTERFLY_1,
1080     EL_BUTTERFLY_2,
1081     EL_BUTTERFLY_3,
1082     EL_BUTTERFLY_4,
1083     EL_AMOEBE_BD,
1084     EL_CHAR_FRAGE
1085   };
1086   static int ep_bd_element_num = sizeof(ep_bd_element)/sizeof(int);
1087
1088   static int ep_sb_element[] =
1089   {
1090     EL_LEERRAUM,
1091     EL_BETON,
1092     EL_SOKOBAN_OBJEKT,
1093     EL_SOKOBAN_FELD_LEER,
1094     EL_SOKOBAN_FELD_VOLL,
1095     EL_SPIELFIGUR
1096   };
1097   static int ep_sb_element_num = sizeof(ep_sb_element)/sizeof(int);
1098
1099   static int ep_gem[] =
1100   {
1101     EL_EDELSTEIN,
1102     EL_EDELSTEIN_BD,
1103     EL_EDELSTEIN_GELB,
1104     EL_EDELSTEIN_ROT,
1105     EL_EDELSTEIN_LILA,
1106     EL_DIAMANT
1107   };
1108   static int ep_gem_num = sizeof(ep_gem)/sizeof(int);
1109
1110   static int ep_inactive[] =
1111   {
1112     EL_LEERRAUM,
1113     EL_ERDREICH,
1114     EL_MAUERWERK,
1115     EL_FELSBODEN,
1116     EL_SCHLUESSEL,
1117     EL_BETON,
1118     EL_AMOEBE_TOT,
1119     EL_MORAST_LEER,
1120     EL_BADEWANNE,
1121     EL_ABLENK_AUS,
1122     EL_SCHLUESSEL1,
1123     EL_SCHLUESSEL2,
1124     EL_SCHLUESSEL3,
1125     EL_SCHLUESSEL4,
1126     EL_PFORTE1,
1127     EL_PFORTE2,
1128     EL_PFORTE3,
1129     EL_PFORTE4,
1130     EL_PFORTE1X,
1131     EL_PFORTE2X,
1132     EL_PFORTE3X,
1133     EL_PFORTE4X,
1134     EL_DYNAMIT_AUS,
1135     EL_UNSICHTBAR,
1136     EL_BIRNE_AUS,
1137     EL_BIRNE_EIN,
1138     EL_ERZ_EDEL,
1139     EL_ERZ_DIAM,
1140     EL_ERZ_EDEL_BD,
1141     EL_ERZ_EDEL_GELB,
1142     EL_DYNABOMB_NR,
1143     EL_DYNABOMB_SZ,
1144     EL_DYNABOMB_XL,
1145     EL_SOKOBAN_OBJEKT,
1146     EL_SOKOBAN_FELD_LEER,
1147     EL_SOKOBAN_FELD_VOLL,
1148     EL_ERZ_EDEL_ROT,
1149     EL_ERZ_EDEL_LILA,
1150     EL_BADEWANNE1,
1151     EL_BADEWANNE2,
1152     EL_BADEWANNE3,
1153     EL_BADEWANNE4,
1154     EL_BADEWANNE5,
1155     EL_SIEB_TOT,
1156     EL_SIEB2_TOT,
1157     EL_AMOEBA2DIAM,
1158     EL_BLOCKED
1159   };
1160   static int ep_inactive_num = sizeof(ep_inactive)/sizeof(int);
1161
1162   static int ep_explosive[] =
1163   {
1164     EL_BOMBE,
1165     EL_DYNAMIT,
1166     EL_DYNAMIT_AUS,
1167     EL_DYNABOMB,
1168     EL_DYNABOMB_NR,
1169     EL_DYNABOMB_SZ,
1170     EL_DYNABOMB_XL,
1171     EL_KAEFER,
1172     EL_MAULWURF,
1173     EL_PINGUIN,
1174     EL_SCHWEIN,
1175     EL_DRACHE,
1176     EL_SONDE
1177   };
1178   static int ep_explosive_num = sizeof(ep_explosive)/sizeof(int);
1179
1180   static int ep_mampf3[] =
1181   {
1182     EL_EDELSTEIN,
1183     EL_EDELSTEIN_BD,
1184     EL_EDELSTEIN_GELB,
1185     EL_EDELSTEIN_ROT,
1186     EL_EDELSTEIN_LILA,
1187     EL_DIAMANT
1188   };
1189   static int ep_mampf3_num = sizeof(ep_mampf3)/sizeof(int);
1190
1191   static int ep_pushable[] =
1192   {
1193     EL_FELSBROCKEN,
1194     EL_BOMBE,
1195     EL_KOKOSNUSS,
1196     EL_ZEIT_LEER,
1197     EL_SOKOBAN_FELD_VOLL,
1198     EL_SOKOBAN_OBJEKT,
1199     EL_SONDE
1200   };
1201   static int ep_pushable_num = sizeof(ep_pushable)/sizeof(int);
1202
1203   static long ep_bit[] =
1204   {
1205     EP_BIT_AMOEBALIVE,
1206     EP_BIT_AMOEBOID,
1207     EP_BIT_SCHLUESSEL,
1208     EP_BIT_PFORTE,
1209     EP_BIT_SOLID,
1210     EP_BIT_MASSIV,
1211     EP_BIT_SLIPPERY,
1212     EP_BIT_ENEMY,
1213     EP_BIT_MAUER,
1214     EP_BIT_CAN_FALL,
1215     EP_BIT_CAN_SMASH,
1216     EP_BIT_CAN_CHANGE,
1217     EP_BIT_CAN_MOVE,
1218     EP_BIT_COULD_MOVE,
1219     EP_BIT_DONT_TOUCH,
1220     EP_BIT_DONT_GO_TO,
1221     EP_BIT_MAMPF2,
1222     EP_BIT_BD_ELEMENT,
1223     EP_BIT_SB_ELEMENT,
1224     EP_BIT_GEM,
1225     EP_BIT_INACTIVE,
1226     EP_BIT_EXPLOSIVE,
1227     EP_BIT_MAMPF3,
1228     EP_BIT_PUSHABLE
1229   };
1230   static int *ep_array[] =
1231   {
1232     ep_amoebalive,
1233     ep_amoeboid,
1234     ep_schluessel,
1235     ep_pforte,
1236     ep_solid,
1237     ep_massiv,
1238     ep_slippery,
1239     ep_enemy,
1240     ep_mauer,
1241     ep_can_fall,
1242     ep_can_smash,
1243     ep_can_change,
1244     ep_can_move,
1245     ep_could_move,
1246     ep_dont_touch,
1247     ep_dont_go_to,
1248     ep_mampf2,
1249     ep_bd_element,
1250     ep_sb_element,
1251     ep_gem,
1252     ep_inactive,
1253     ep_explosive,
1254     ep_mampf3,
1255     ep_pushable
1256   };
1257   static int *ep_num[] =
1258   {
1259     &ep_amoebalive_num,
1260     &ep_amoeboid_num,
1261     &ep_schluessel_num,
1262     &ep_pforte_num,
1263     &ep_solid_num,
1264     &ep_massiv_num,
1265     &ep_slippery_num,
1266     &ep_enemy_num,
1267     &ep_mauer_num,
1268     &ep_can_fall_num,
1269     &ep_can_smash_num,
1270     &ep_can_change_num,
1271     &ep_can_move_num,
1272     &ep_could_move_num,
1273     &ep_dont_touch_num,
1274     &ep_dont_go_to_num,
1275     &ep_mampf2_num,
1276     &ep_bd_element_num,
1277     &ep_sb_element_num,
1278     &ep_gem_num,
1279     &ep_inactive_num,
1280     &ep_explosive_num,
1281     &ep_mampf3_num,
1282     &ep_pushable_num
1283   };
1284   static int num_properties = sizeof(ep_num)/sizeof(int *);
1285
1286   for(i=0;i<MAX_ELEMENTS;i++)
1287     Elementeigenschaften[i] = 0;
1288
1289   for(i=0;i<num_properties;i++)
1290     for(j=0;j<*(ep_num[i]);j++)
1291       Elementeigenschaften[(ep_array[i])[j]] |= ep_bit[i];
1292   for(i=EL_CHAR_START;i<EL_CHAR_END;i++)
1293     Elementeigenschaften[i] |= (EP_BIT_CHAR | EP_BIT_INACTIVE);
1294 }
1295
1296 void CloseAll()
1297 {
1298   int i;
1299
1300   if (sound_process_id)
1301   {
1302     StopSounds();
1303     kill(sound_process_id, SIGTERM);
1304     FreeSounds(NUM_SOUNDS);
1305   }
1306
1307   for(i=0;i<NUM_PIXMAPS;i++)
1308   {
1309     if (pix[i])
1310     {
1311 #ifdef XPM_INCLUDE_FILE
1312       if (i<NUM_PICTURES)       /* XPM pictures */
1313       {
1314         XFreeColors(display,DefaultColormap(display,screen),
1315                     xpm_att[i].pixels,xpm_att[i].npixels,0);
1316         XpmFreeAttributes(&xpm_att[i]);
1317       }
1318 #endif
1319       XFreePixmap(display,pix[i]);
1320     }
1321     if (clipmask[i])
1322       XFreePixmap(display,clipmask[i]);
1323     if (clip_gc[i])
1324       XFreeGC(display, clip_gc[i]);
1325   }
1326
1327   if (gc)
1328     XFreeGC(display, gc);
1329   if (display)
1330     XCloseDisplay(display);
1331
1332   exit(0);
1333 }