rocks_n_diamonds-0.9b
[rocksndiamonds.git] / src / tools.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 *  tools.c                                                 *
13 ***********************************************************/
14
15 #ifdef __FreeBSD__
16 #include <machine/joystick.h>
17 #endif
18
19 #include "tools.h"
20 #include "game.h"
21 #include "events.h"
22 #include "sound.h"
23 #include "misc.h"
24 #include "buttons.h"
25 #include <math.h>
26
27 void BackToFront()
28 {
29   int x,y;
30
31   if (direct_draw_on && game_status==PLAYING)
32     redraw_mask &= ~REDRAW_MAIN;
33
34   if (!redraw_mask)
35     return;
36
37   if (redraw_mask & REDRAW_ALL ||
38       (redraw_mask & REDRAW_FIELD && redraw_mask & REDRAW_DOORS))
39   {
40     XCopyArea(display,backbuffer,window,gc,
41               0,0, WIN_XSIZE,WIN_YSIZE,
42               0,0);
43     redraw_mask = 0;
44   }
45   else if (redraw_mask & REDRAW_FIELD)
46   {
47     XCopyArea(display,backbuffer,window,gc,
48               REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
49               REAL_SX,REAL_SY);
50     redraw_mask &= ~REDRAW_MAIN;
51   }
52   else if (redraw_mask & REDRAW_DOORS)
53   {
54     if (redraw_mask & REDRAW_DOOR_1)
55       XCopyArea(display,backbuffer,window,gc,
56                 DX,DY, DXSIZE,DYSIZE, DX,DY);
57     if (redraw_mask & REDRAW_DOOR_2)
58     {
59       if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
60         XCopyArea(display,backbuffer,window,gc,
61                   VX,VY, VXSIZE,VYSIZE, VX,VY);
62       else
63       {
64         if (redraw_mask & REDRAW_VIDEO_1)
65           XCopyArea(display,backbuffer,window,gc,
66                     VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
67                     VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
68                     VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
69         if (redraw_mask & REDRAW_VIDEO_2)
70           XCopyArea(display,backbuffer,window,gc,
71                     VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
72                     VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
73                     VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
74         if (redraw_mask & REDRAW_VIDEO_3)
75           XCopyArea(display,backbuffer,window,gc,
76                     VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
77                     VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
78                     VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
79       }
80     }
81     redraw_mask &= ~REDRAW_DOORS;
82   }
83
84   if (redraw_mask & REDRAW_MICROLEV)
85   {
86     XCopyArea(display,backbuffer,window,gc,
87               MICROLEV_XPOS,MICROLEV_YPOS, MICROLEV_XSIZE,MICROLEV_YSIZE,
88               MICROLEV_XPOS,MICROLEV_YPOS);
89     XCopyArea(display,backbuffer,window,gc,
90               SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE,
91               SX,MICROLABEL_YPOS);
92     redraw_mask &= ~REDRAW_MICROLEV;
93   }
94
95   if (redraw_mask & REDRAW_TILES)
96   {
97     if (redraw_tiles>REDRAWTILES_TH)
98       XCopyArea(display,backbuffer,window,gc,SX,SY,SXSIZE,SYSIZE,SX,SY);
99     else
100       for(x=0;x<SCR_FIELDX;x++)
101         for(y=0;y<SCR_FIELDY;y++)
102           if (redraw[x][y])
103             XCopyArea(display,backbuffer,window,gc,
104                       SX+x*TILEX,SY+y*TILEY,TILEX,TILEY,SX+x*TILEX,SY+y*TILEY);
105   }
106
107   XFlush(display);
108
109   for(x=0;x<SCR_FIELDX;x++)
110     for(y=0;y<SCR_FIELDY;y++)
111       redraw[x][y]=0;
112   redraw_tiles=0;
113   redraw_mask=0;
114 }
115
116 void FadeToFront()
117 {
118   long fading_delay = 300000;
119
120   if (fading_on && (redraw_mask & REDRAW_FIELD))
121   {
122
123 /*
124     int x,y;
125
126     XFillRectangle(display,window,gc,
127                    REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
128     XFlush(display);
129
130     for(i=0;i<2*FULL_SYSIZE;i++)
131     {
132       for(y=0;y<FULL_SYSIZE;y++)
133       {
134         XCopyArea(display,backbuffer,window,gc,
135                   REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
136       }
137       XFlush(display);
138       Delay(10000);
139     }
140 */
141
142 /*
143     for(i=1;i<FULL_SYSIZE;i+=2)
144       XCopyArea(display,backbuffer,window,gc,
145                 REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
146     XFlush(display);
147     Delay(fading_delay);
148 */
149
150
151     XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
152     XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
153               REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
154     XFlush(display);
155     Delay(fading_delay);
156
157     XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
158     XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
159               REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
160     XFlush(display);
161     Delay(fading_delay);
162
163     XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
164     XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
165               REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
166     XFlush(display);
167     Delay(fading_delay);
168
169     XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
170     XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
171               REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
172     XFlush(display);
173     Delay(fading_delay);
174
175     redraw_mask &= ~REDRAW_MAIN;
176   }
177
178   BackToFront();
179 }
180
181 void ClearWindow()
182 {
183   drawto_field = backbuffer;
184   XFillRectangle(display,drawto_field,gc,
185                  REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
186   redraw_mask|=REDRAW_FIELD;
187
188   if (game_status==PLAYING && direct_draw_on)
189   {
190     drawto_field = window;
191     XFillRectangle(display,drawto_field,gc,
192                    REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
193   }
194 }
195
196 void DrawText(int x, int y, char *text, int font, int col)
197 {
198   DrawTextExt(drawto, gc, x, y, text, font, col);
199   if (x<DX)
200     redraw_mask|=REDRAW_FIELD;
201   else if (y<VY)
202     redraw_mask|=REDRAW_DOOR_1;
203 }
204
205 void DrawTextExt(Drawable d, GC gc, int x, int y,
206                  char *text, int font, int font_color)
207 {
208   int font_width, font_height, font_start;
209   int font_pixmap;
210
211   if (font!=FS_SMALL && font!=FS_BIG)
212     font = FS_SMALL;
213   if (font_color<FC_RED || font_color>FC_SPECIAL2)
214     font_color = FC_RED;
215
216   font_width =
217     (font==FS_BIG ? FONT1_XSIZE :
218      font_color<FC_SPECIAL1 ? FONT2_XSIZE :
219      font_color<FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
220   font_height =
221     (font==FS_BIG ? FONT1_XSIZE :
222      font_color<FC_SPECIAL2 ? FONT2_XSIZE: FONT4_XSIZE);
223   font_pixmap = (font==FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
224   font_start =
225     font_color*(font==FS_BIG ? FONT1_YSIZE : FONT2_YSIZE)*FONT_LINES_PER_FONT;
226
227   while(*text)
228   {
229     char c = *text++;
230
231     if (c>='a' && c<='z')
232       c = 'A' + (c - 'a');
233     else if (c=='ä' || c=='Ä')
234       c = 91;
235     else if (c=='ö' || c=='Ö')
236       c = 92;
237     else if (c=='ü' || c=='Ü')
238       c = 93;
239
240     if (c>=32 && c<=95)
241       XCopyArea(display,pix[font_pixmap],d,gc,
242                 ((c-32) % FONT_CHARS_PER_LINE)*font_width,
243                 ((c-32) / FONT_CHARS_PER_LINE)*font_height + font_start,
244                 font_width,font_height, x,y);
245
246     x += font_width;
247   }
248 }
249
250 void DrawGraphic(int x, int y, int graphic)
251 {
252   DrawGraphicExt(drawto_field, gc, x, y, graphic);
253   redraw_tiles++;
254   redraw[x][y] = TRUE;
255   redraw_mask |= REDRAW_TILES;
256 }
257
258 void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
259 {
260   DrawGraphicExtHiRes(d, gc, SX+x*TILEX, SY+y*TILEY, graphic);
261 }
262
263 void DrawGraphicExtHiRes(Drawable d, GC gc, int x, int y, int graphic)
264 {
265   if (graphic<0)
266     XFillRectangle(display,d,gc, x,y, TILEX,TILEY);
267   else if (graphic<256)
268     XCopyArea(display,pix[PIX_BACK],d,gc,
269               SX+(graphic % GFX_PER_LINE)*TILEX,
270               SY+(graphic / GFX_PER_LINE)*TILEY,
271               TILEX,TILEY, x,y);
272   else
273   {
274     graphic -= 256;
275     XCopyArea(display,pix[PIX_BIGFONT],d,gc,
276               (graphic % FONT_CHARS_PER_LINE)*TILEX,
277               (graphic / FONT_CHARS_PER_LINE)*TILEY +
278               FC_SPECIAL1*TILEY*FONT_LINES_PER_FONT,
279               TILEX,TILEY, x,y);
280   }
281 }
282
283 void DrawGraphicThruMask(int x, int y, int graphic)
284 {
285   int src_x,src_y, dest_x,dest_y;
286
287   if (graphic<0 || graphic>255)
288   {
289     DrawGraphic(x,y,graphic);
290     return;
291   }
292
293   src_x  = SX+(graphic % GFX_PER_LINE)*TILEX;
294   src_y  = SY+(graphic / GFX_PER_LINE)*TILEY;
295   dest_x = SX+x*TILEX;
296   dest_y = SY+y*TILEY;
297
298   XSetClipOrigin(display,clip_gc[PIX_BACK],dest_x-src_x,dest_y-src_y);
299   XCopyArea(display,pix[PIX_BACK],drawto_field,clip_gc[PIX_BACK], src_x,src_y,
300             TILEX,TILEY, dest_x,dest_y);
301
302   redraw_tiles++;
303   redraw[x][y]=TRUE;
304   redraw_mask|=REDRAW_TILES;
305 }
306
307 void DrawElementThruMask(int x, int y, int element)
308 {
309   DrawGraphicThruMask(x,y,el2gfx(element));
310 }
311
312 void DrawMiniGraphic(int x, int y, int graphic)
313 {
314   DrawMiniGraphicExt(drawto, gc, x, y, graphic);
315   redraw_tiles++;
316   redraw[x/2][y/2]=TRUE;
317   redraw_mask|=REDRAW_TILES;
318 }
319
320 void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
321 {
322   DrawMiniGraphicExtHiRes(d,gc, SX+x*MINI_TILEX,SY+y*MINI_TILEY, graphic);
323 }
324
325 void DrawMiniGraphicExtHiRes(Drawable d, GC gc, int x, int y, int graphic)
326 {
327   if (graphic<0)
328     XFillRectangle(display,d,gc, x,y, MINI_TILEX,MINI_TILEY);
329   else if (graphic<256)
330     XCopyArea(display,pix[PIX_BACK],d,gc,
331               MINI_GFX_STARTX+(graphic % MINI_GFX_PER_LINE)*MINI_TILEX,
332               MINI_GFX_STARTY+(graphic / MINI_GFX_PER_LINE)*MINI_TILEY,
333               MINI_TILEX,MINI_TILEY, x,y);
334   else
335   {
336     graphic -= 256;
337     XCopyArea(display,pix[PIX_SMALLFONT],d,gc,
338               (graphic % FONT_CHARS_PER_LINE)*FONT4_XSIZE,
339               (graphic / FONT_CHARS_PER_LINE)*FONT4_YSIZE +
340               FC_SPECIAL2*FONT2_YSIZE*FONT_LINES_PER_FONT,
341               MINI_TILEX,MINI_TILEY, x,y);
342   }
343 }
344
345 void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int cut_mode)
346 {
347   int width = TILEX, height = TILEY;
348   int cx = 0, cy = 0;
349
350   if (graphic<0)
351   {
352     DrawGraphic(x,y,graphic);
353     return;
354   }
355
356   if (dx || dy)                 /* Verschiebung der Grafik? */
357   {
358     if (x<0)                    /* Element kommt von links ins Bild */
359     {
360       x=0;
361       width=dx;
362       cx=TILEX-dx;
363       dx=0;
364     }
365     else if (x==SCR_FIELDX)     /* Element kommt von rechts ins Bild */
366     {
367       x=SCR_FIELDX-1;
368       width=-dx;
369       dx=TILEX+dx;
370     }
371     else if (x==0 && dx<0)      /* Element verläßt links das Bild */
372     {
373       width+=dx;
374       cx=-dx;
375       dx=0;
376     }
377     else if (x==SCR_FIELDX-1 && dx>0)   /* El. verläßt rechts das Bild */
378       width-=dx;
379     else if (dx)                /* allg. Bewegung in x-Richtung */
380       redraw[x+SIGN(dx)][y]=TRUE;
381
382     if (y<0)                    /* Element kommt von oben ins Bild */
383     {
384       if (cut_mode==CUT_BELOW)  /* Element oberhalb des Bildes */
385         return;
386
387       y=0;
388       height=dy;
389       cy=TILEY-dy;
390       dy=0;
391     }
392     else if (y==SCR_FIELDY)     /* Element kommt von unten ins Bild */
393     {
394       y=SCR_FIELDY-1;
395       height=-dy;
396       dy=TILEY+dy;
397     }
398     else if (y==0 && dy<0)      /* Element verläßt oben das Bild */
399     {
400       height+=dy;
401       cy=-dy;
402       dy=0;
403     }
404     else if (dy>0 && cut_mode==CUT_ABOVE)
405     {
406       if (y==SCR_FIELDY-1)      /* Element unterhalb des Bildes */
407         return;
408
409       height=dy;
410       cy=TILEY-dy;
411       dy=TILEY;
412       redraw[x][y+1]=TRUE;
413     }                           /* Element verläßt unten das Bild */
414     else if (dy>0 && (y==SCR_FIELDY-1 || cut_mode==CUT_BELOW))
415       height-=dy;
416     else if (dy)                /* allg. Bewegung in y-Richtung */
417       redraw[x][y+SIGN(dy)]=TRUE;
418   }
419
420   XCopyArea(display,pix[PIX_BACK],drawto_field,gc,
421             SX+(graphic % GFX_PER_LINE)*TILEX+cx,
422             SY+(graphic / GFX_PER_LINE)*TILEY+cy,
423             width,height, SX+x*TILEX+dx,SY+y*TILEY+dy);
424
425   redraw_tiles++;
426   redraw[x][y]=TRUE;
427   redraw_mask|=REDRAW_TILES;
428 }
429
430 void DrawElementShifted(int x, int y, int dx, int dy, int element,int cut_mode)
431 {
432   int ux = UNSCROLLX(x), uy = UNSCROLLY(y);
433   int graphic = el2gfx(element);
434   int phase = ABS(MovPos[ux][uy])/(TILEX/2);
435   int dir = MovDir[ux][uy];
436   int horiz_move = (dir==MV_LEFT || dir==MV_RIGHT);
437
438   if (element==EL_PACMAN ||
439       element==EL_KAEFER ||
440       element==EL_FLIEGER)
441   {
442     if (element==EL_PACMAN)
443       graphic = GFX_PACMAN + 4*!phase;
444     else
445       graphic += 4*!phase;
446
447     if (dir==MV_UP)
448       graphic += 1;
449     else if (dir==MV_LEFT)
450       graphic += 2;
451     else if (dir==MV_DOWN)
452       graphic += 3;
453   }
454   else if ((element==EL_FELSBROCKEN ||
455             element==EL_EDELSTEIN ||
456             element==EL_DIAMANT) && horiz_move && phase)
457   {
458     if (element==EL_FELSBROCKEN)
459       graphic += 2;
460     else
461       graphic += 1;
462   }
463   else if ((element==EL_SIEB_LEER ||
464             element==EL_SIEB_VOLL) && SiebAktiv)
465   {
466     graphic += 3-(SiebAktiv%8)/2;
467   }
468   else if (IS_AMOEBOID(element))
469   {
470     graphic = (element==EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
471     graphic += (x+2*y) % 4;
472   }
473
474   if (dx || dy)
475     DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode);
476   else
477     DrawGraphic(x,y, graphic);
478 }
479
480 void ErdreichAnbroeckeln(int x, int y)
481 {
482   int i, width, height, cx,cy;
483   int ux = UNSCROLLX(x), uy = UNSCROLLY(y);
484   int element, graphic;
485   int snip = 4;
486   static int xy[4][2] =
487   {
488     0,-1,
489     -1,0,
490     +1,0,
491     0,+1
492   };
493
494   if (!IN_LEV_FIELD(ux,uy))
495     return;
496
497   element = Feld[ux][uy];
498
499   if (element==EL_ERDREICH)
500   {
501     if (!IN_SCR_FIELD(x,y))
502       return;
503
504     graphic = GFX_ERDENRAND;
505
506     for(i=0;i<4;i++)
507     {
508       int uxx,uyy;
509
510       uxx = ux+xy[i][0];
511       uyy = uy+xy[i][1];
512       if (!IN_LEV_FIELD(uxx,uyy))
513         element = EL_BETON;
514       else
515         element = Feld[uxx][uyy];
516
517 /*
518       if (element==EL_ERDREICH || IS_SOLID(element))
519         continue;
520 */
521       if (element==EL_ERDREICH)
522         continue;
523
524       if (i==1 || i==2)
525       {
526         width = snip;
527         height = TILEY;
528         cx = (i==2 ? TILEX-snip : 0);
529         cy = 0;
530       }
531       else
532       {
533         width = TILEX;
534         height = snip;
535         cx = 0;
536         cy = (i==3 ? TILEY-snip : 0);
537       }
538
539       XCopyArea(display,pix[PIX_BACK],drawto_field,gc,
540                 SX+(graphic % GFX_PER_LINE)*TILEX+cx,
541                 SY+(graphic / GFX_PER_LINE)*TILEY+cy,
542                 width,height, SX+x*TILEX+cx,SY+y*TILEY+cy);
543     }
544
545     redraw_tiles++;
546     redraw[x][y]=TRUE;
547   }
548   else
549   {
550     graphic = GFX_ERDENRAND;
551
552     for(i=0;i<4;i++)
553     {
554       int xx,yy,uxx,uyy;
555
556       xx = x+xy[i][0];
557       yy = y+xy[i][1];
558       uxx = ux+xy[i][0];
559       uyy = uy+xy[i][1];
560 /*
561       if (!IN_LEV_FIELD(uxx,uyy) || Feld[uxx][uyy]!=EL_ERDREICH ||
562           !IN_SCR_FIELD(xx,yy) || IS_SOLID(element))
563         continue;
564 */
565
566       if (!IN_LEV_FIELD(uxx,uyy) || Feld[uxx][uyy]!=EL_ERDREICH ||
567           !IN_SCR_FIELD(xx,yy))
568         continue;
569
570       if (i==1 || i==2)
571       {
572         width = snip;
573         height = TILEY;
574         cx = (i==1 ? TILEX-snip : 0);
575         cy = 0;
576       }
577       else
578       {
579         width = TILEX;
580         height = snip;
581         cx = 0;
582         cy = (i==0 ? TILEY-snip : 0);
583       }
584
585       XCopyArea(display,pix[PIX_BACK],drawto_field,gc,
586                 SX+(graphic % GFX_PER_LINE)*TILEX+cx,
587                 SY+(graphic / GFX_PER_LINE)*TILEY+cy,
588                 width,height, SX+xx*TILEX+cx,SY+yy*TILEY+cy);
589
590       redraw_tiles++;
591       redraw[xx][yy]=TRUE;
592     }
593   }
594 }
595
596 void DrawScreenElement(int x, int y, int element)
597 {
598   DrawElementShifted(x,y,0,0,element,CUT_NO_CUTTING);
599   ErdreichAnbroeckeln(x,y);
600 }
601
602 void DrawLevelElement(int x, int y, int element)
603 {
604   if (IN_LEV_FIELD(x,y) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
605     DrawScreenElement(SCROLLX(x),SCROLLY(y),element);
606 }
607
608 void DrawScreenField(int x, int y)
609 {
610   int ux = UNSCROLLX(x), uy = UNSCROLLY(y);
611   int element;
612
613   if (!IN_LEV_FIELD(ux,uy))
614   {
615     DrawScreenElement(x,y,EL_BETON);
616     return;
617   }
618
619   element = Feld[ux][uy];
620
621   if (IS_MOVING(ux,uy))
622   {
623     int horiz_move = (MovDir[ux][uy]==MV_LEFT || MovDir[ux][uy]==MV_RIGHT);
624     BOOL cut_mode = CUT_NO_CUTTING;
625
626     if (Store[ux][uy]==EL_MORAST_LEER ||
627         Store[ux][uy]==EL_SIEB_LEER ||
628         Store[ux][uy]==EL_AMOEBE_NASS)
629       cut_mode = CUT_ABOVE;
630     else if (Store[ux][uy]==EL_MORAST_VOLL ||
631         Store[ux][uy]==EL_SIEB_VOLL ||
632         Store[ux][uy]==EL_SALZSAEURE)
633       cut_mode = CUT_BELOW;
634
635     if (cut_mode==CUT_ABOVE)
636       DrawElementShifted(x,y,0,0,Store[ux][uy],CUT_NO_CUTTING);
637     else
638       DrawScreenElement(x,y,EL_LEERRAUM);
639
640     if (horiz_move)
641       DrawElementShifted(x,y,MovPos[ux][uy],0,element,CUT_NO_CUTTING);
642     else
643       DrawElementShifted(x,y,0,MovPos[ux][uy],element,cut_mode);
644   }
645   else if (IS_BLOCKED(ux,uy))
646   {
647     int oldx,oldy;
648     int sx, sy;
649     int horiz_move;
650     BOOL cut_mode = CUT_NO_CUTTING;
651
652     Blocked2Moving(ux,uy,&oldx,&oldy);
653     sx = SCROLLX(oldx);
654     sy = SCROLLY(oldy);
655     horiz_move = (MovDir[oldx][oldy]==MV_LEFT || MovDir[oldx][oldy]==MV_RIGHT);
656
657     if (Store[oldx][oldy]==EL_MORAST_LEER ||
658         Store[oldx][oldy]==EL_SIEB_LEER ||
659         Store[oldx][oldy]==EL_AMOEBE_NASS)
660       cut_mode = CUT_ABOVE;
661
662     DrawScreenElement(x,y,EL_LEERRAUM);
663     element = Feld[oldx][oldy];
664
665     if (horiz_move)
666       DrawElementShifted(sx,sy,MovPos[oldx][oldy],0,element,CUT_NO_CUTTING);
667     else
668       DrawElementShifted(sx,sy,0,MovPos[oldx][oldy],element,cut_mode);
669   }
670   else if (IS_DRAWABLE(element))
671     DrawScreenElement(x,y,element);
672   else
673     DrawScreenElement(x,y,EL_LEERRAUM);
674 }
675
676 void DrawLevelField(int x, int y)
677 {
678   if (IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
679     DrawScreenField(SCROLLX(x),SCROLLY(y));
680   else if (IS_MOVING(x,y))
681   {
682     int newx,newy;
683
684     Moving2Blocked(x,y,&newx,&newy);
685     if (IN_SCR_FIELD(SCROLLX(newx),SCROLLY(newy)))
686       DrawScreenField(SCROLLX(newx),SCROLLY(newy));
687   }
688   else if (IS_BLOCKED(x,y))
689   {
690     int oldx,oldy;
691
692     Blocked2Moving(x,y,&oldx,&oldy);
693     if (IN_SCR_FIELD(SCROLLX(oldx),SCROLLY(oldy)))
694       DrawScreenField(SCROLLX(oldx),SCROLLY(oldy));
695   }
696 }
697
698 void DrawMiniElement(int x, int y, int element)
699 {
700   int graphic;
701
702   if (!element)
703   {
704     DrawMiniGraphic(x,y,-1);
705     return;
706   }
707
708   graphic = el2gfx(element);
709   DrawMiniGraphic(x,y,graphic);
710
711   redraw_tiles++;
712   redraw[x/2][y/2]=TRUE;
713   redraw_mask|=REDRAW_TILES;
714 }
715
716 void DrawMiniElementOrWall(int x, int y, int scroll_x, int scroll_y)
717 {
718   if (x+scroll_x<-1 || x+scroll_x>lev_fieldx ||
719       y+scroll_y<-1 || y+scroll_y>lev_fieldy)
720     DrawMiniElement(x,y,EL_LEERRAUM);
721   else if (x+scroll_x==-1 || x+scroll_x==lev_fieldx ||
722            y+scroll_y==-1 || y+scroll_y==lev_fieldy)
723     DrawMiniElement(x,y,EL_BETON);
724   else
725     DrawMiniElement(x,y,Feld[x+scroll_x][y+scroll_y]);
726 }
727
728 void DrawMicroElement(int xpos, int ypos, int element)
729 {
730   int graphic;
731
732   if (element==EL_LEERRAUM)
733     return;
734
735   graphic = el2gfx(element);
736
737   XCopyArea(display,pix[PIX_BACK],drawto,gc,
738             MICRO_GFX_STARTX+(graphic % MICRO_GFX_PER_LINE)*MICRO_TILEX,
739             MICRO_GFX_STARTY+(graphic / MICRO_GFX_PER_LINE)*MICRO_TILEY,
740             MICRO_TILEX,MICRO_TILEY, xpos,ypos);
741 }
742
743 void DrawLevel()
744 {
745   int x,y;
746
747   ClearWindow();
748
749   for(x=0;x<SCR_FIELDX;x++)
750     for(y=0;y<SCR_FIELDY;y++)
751       DrawScreenField(x,y);
752
753   redraw_mask |= REDRAW_FIELD;
754 }
755
756 void DrawMiniLevel(int scroll_x, int scroll_y)
757 {
758   int x,y;
759
760   ClearWindow();
761
762   for(x=0;x<2*SCR_FIELDX;x++)
763     for(y=0;y<2*SCR_FIELDY;y++)
764       DrawMiniElementOrWall(x,y,scroll_x,scroll_y);
765
766   redraw_mask |= REDRAW_FIELD;
767 }
768
769 void DrawMicroLevel(int xpos, int ypos)
770 {
771   int x,y;
772
773   XFillRectangle(display,drawto,gc,
774                  xpos-MICRO_TILEX,ypos-MICRO_TILEY,
775                  MICRO_TILEX*(STD_LEV_FIELDX+2),
776                  MICRO_TILEY*(STD_LEV_FIELDY+2));
777
778   for(x=-1;x<=STD_LEV_FIELDX;x++)
779     for(y=-1;y<=STD_LEV_FIELDY;y++)
780       if (x>=0 && x<lev_fieldx && y>=0 && y<lev_fieldy)
781         DrawMicroElement(xpos+MICRO_TILEX*x,ypos+MICRO_TILEY*y,
782                          Feld[x][y]=Ur[x][y]);
783       else if (x>=-1 && x<lev_fieldx+1 && y>=-1 && y<lev_fieldy+1)
784         DrawMicroElement(xpos+MICRO_TILEX*x,ypos+MICRO_TILEY*y,
785                          EL_BETON);
786
787   XFillRectangle(display,drawto,gc, SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE);
788
789   if (level.name)
790   {
791     int len = strlen(level.name);
792     int lxpos = SX+(SXSIZE-len*FONT4_XSIZE)/2;
793     int lypos = MICROLABEL_YPOS;
794
795     DrawText(lxpos,lypos,level.name,FS_SMALL,FC_SPECIAL2);
796   }
797
798   redraw_mask |= REDRAW_MICROLEV;
799 }
800
801 int AYS_in_range(int x, int y)
802 {
803   if (y>DY+249 && y<DY+278)
804   {
805     if (x>DX+1 && x<DX+48)
806       return(1);
807     else if (x>DX+51 && x<DX+98) 
808       return(2);
809   }
810   return(0);
811 }
812
813 BOOL AreYouSure(char *text, unsigned int ays_state)
814 {
815   int mx,my, ty, result = -1;
816
817   CloseDoor(DOOR_CLOSE_1);
818
819   /* Alten Türinhalt sichern */
820   XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
821             DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
822             DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1);
823
824   /* Fragetext schreiben */
825   XFillRectangle(display,pix[PIX_DB_DOOR],gc,
826                  DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1,DXSIZE,DYSIZE);
827
828   for(ty=0;ty<13;ty++)
829   {
830     int tx,tl,tc;
831     char txt[256];
832
833     if (!(*text))
834       break;
835     for(tl=0,tx=0;tx<7;tl++,tx++)
836     {
837       tc=*(text+tx);
838       if (!tc || tc==32)
839         break;
840     }
841     if (!tl)
842     { 
843       text++; 
844       ty--; 
845       continue; 
846     }
847     sprintf(txt,text); 
848     txt[tl]=0;
849     DrawTextExt(pix[PIX_DB_DOOR],gc,
850                 DOOR_GFX_PAGEX1+51-(tl*14)/2,SY+ty*16,txt,FS_SMALL,FC_YELLOW);
851     text+=(tl+(tc==32));
852   }
853
854   if (ays_state & AYS_ASK)
855     XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
856               DOOR_GFX_PAGEX4,OK_BUTTON_GFX_YPOS,
857               DXSIZE,OK_BUTTON_YSIZE,
858               DOOR_GFX_PAGEX1,OK_BUTTON_YPOS);
859   else if (ays_state & AYS_CONFIRM)
860     XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
861               DOOR_GFX_PAGEX4,CONFIRM_BUTTON_GFX_YPOS,
862               DXSIZE,CONFIRM_BUTTON_YSIZE,
863               DOOR_GFX_PAGEX1,CONFIRM_BUTTON_YPOS);
864
865   OpenDoor(DOOR_OPEN_1);
866
867   if (!(ays_state & AYS_ASK) && !(ays_state & AYS_CONFIRM))
868     return(FALSE);
869
870   if (game_status!=MAINMENU)
871     InitAnimation();
872
873   button_status = MB_RELEASED;
874
875   while(result<0)
876   {
877     DoAnimation();
878     Delay(10000);
879
880     if (XPending(display))
881     {
882       XEvent event;
883
884       XNextEvent(display, &event);
885       switch(event.type)
886       {
887         case Expose:
888           HandleExposeEvent((XExposeEvent *) &event);
889           break;
890         case UnmapNotify:
891           SleepWhileUnmapped();
892           break;
893         case ButtonPress:
894         case ButtonRelease:
895         case MotionNotify:
896         {
897           int choice;
898
899           if (event.type==MotionNotify)
900           {
901             motion_status = TRUE;
902             mx = ((XMotionEvent *) &event)->x;
903             my = ((XMotionEvent *) &event)->y;
904           }
905           else
906           {
907             motion_status = FALSE;
908             mx = ((XButtonEvent *) &event)->x;
909             my = ((XButtonEvent *) &event)->y;
910             if (event.type==ButtonPress)
911               button_status = ((XButtonEvent *) &event)->button;
912             else
913               button_status = MB_RELEASED;
914           }
915
916           if (ays_state & AYS_ASK)
917             choice = CheckChooseButtons(mx,my,button_status);
918           else
919             choice = CheckConfirmButton(mx,my,button_status);
920
921           switch(choice)
922           {
923             case BUTTON_OK:
924               result = TRUE;
925               break;
926             case BUTTON_NO:
927               result = FALSE;
928               break;
929             case BUTTON_CONFIRM:
930               result = TRUE|FALSE;
931               break;
932             default:
933               break;
934           }
935           break;
936         }
937         case KeyPress:
938           key_status = KEY_PRESSED;
939           switch(XLookupKeysym((XKeyEvent *)&event,
940                                ((XKeyEvent *)&event)->state))
941           {
942             case XK_Return:
943               result = 1;
944               break;
945             case XK_Escape:
946               result = 0;
947               break;
948           }
949           break;
950         case FocusIn:
951           HandleFocusEvent(FOCUS_IN);
952           break;
953         case FocusOut:
954           HandleFocusEvent(FOCUS_OUT);
955           break;
956         default:
957           break;
958       }
959     }
960     else if (JoystickButton()==JOY_BUTTON_NEW_PRESSED)
961     {
962       int joy=Joystick();
963
964       if (joy & JOY_BUTTON_1)
965         result = 1;
966       else if (joy & JOY_BUTTON_2)
967         result = 0;
968     }
969   }
970
971   if (game_status!=MAINMENU)
972     StopAnimation();
973
974   if (!(ays_state & AYS_STAY_OPEN))
975   {
976     CloseDoor(DOOR_CLOSE_1);
977
978     if (!(ays_state & AYS_STAY_CLOSED) &&
979         (game_status==PLAYING || game_status==LEVELED))
980     {
981       XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
982                 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
983                 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
984       OpenDoor(DOOR_OPEN_1);
985     }
986   }
987
988   return(result);
989 }
990
991 void OpenDoor(unsigned int door_state)
992 {
993   if (door_state & DOOR_COPY_BACK)
994   {
995     XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
996               DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE+VYSIZE,
997               DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
998     door_state &= ~DOOR_COPY_BACK;
999   }
1000
1001   MoveDoor(door_state);
1002   ClearEventQueue();
1003 }
1004
1005 void CloseDoor(unsigned int door_state)
1006 {
1007   XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,
1008             DX,DY, DXSIZE,DYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1009   XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,
1010             VX,VY, VXSIZE,VYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1011
1012   MoveDoor(door_state);
1013   ClearEventQueue();
1014 }
1015
1016 void MoveDoor(unsigned int door_state)
1017 {
1018   static int door1 = DOOR_OPEN_1;
1019   static int door2 = DOOR_CLOSE_2;
1020   int x, start, stepsize = 4, door_anim_delay = stepsize*5000;
1021
1022   if (door1==DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1023     door_state &= ~DOOR_OPEN_1;
1024   else if (door1==DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1025     door_state &= ~DOOR_CLOSE_1;
1026   if (door2==DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1027     door_state &= ~DOOR_OPEN_2;
1028   else if (door2==DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1029     door_state &= ~DOOR_CLOSE_2;
1030
1031   if (quick_doors)
1032   {
1033     stepsize = 20;
1034     door_anim_delay = 0;
1035     StopSound(SND_OEFFNEN);
1036   }
1037
1038   if (door_state & DOOR_ACTION)
1039   {
1040     if (!(door_state & DOOR_NO_DELAY))
1041       PlaySoundStereo(SND_OEFFNEN,PSND_MAX_RIGHT);
1042
1043     start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1044
1045     for(x=start;x<=DXSIZE;x+=stepsize)
1046     {
1047       if (door_state & DOOR_ACTION_1)
1048       {
1049         int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1050         int j = (DXSIZE - i)/3;
1051
1052         XCopyArea(display,pix[PIX_DB_DOOR],drawto,gc,
1053                   DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1+i/2,
1054                   DXSIZE,DYSIZE-i/2, DX,DY);
1055
1056         XFillRectangle(display,drawto,gc,DX,DY+DYSIZE-i/2,DXSIZE,i/2);
1057
1058         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1059                        DX-i,(DY+j)-DOOR_GFX_PAGEY1);
1060         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1061                   DXSIZE,DOOR_GFX_PAGEY1, i,77, DX+DXSIZE-i,DY+j);
1062         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1063                   DXSIZE,DOOR_GFX_PAGEY1+140, i,63, DX+DXSIZE-i,DY+140+j);
1064         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1065                        DX-DXSIZE+i,DY-(DOOR_GFX_PAGEY1+j));
1066         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1067                   DXSIZE-i,DOOR_GFX_PAGEY1+j, i,77-j, DX,DY);
1068         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1069                   DXSIZE-i,DOOR_GFX_PAGEY1+140, i,63, DX,DY+140-j);
1070
1071         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1072                   DXSIZE-i,DOOR_GFX_PAGEY1+77, i,63,
1073                   DX,DY+77-j);
1074         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1075                   DXSIZE-i,DOOR_GFX_PAGEY1+203, i,77,
1076                   DX,DY+203-j);
1077         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1078                        DX-i,(DY+j)-DOOR_GFX_PAGEY1);
1079         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1080                   DXSIZE,DOOR_GFX_PAGEY1+77, i,63,
1081                   DX+DXSIZE-i,DY+77+j);
1082         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1083                   DXSIZE,DOOR_GFX_PAGEY1+203, i,77-j,
1084                   DX+DXSIZE-i,DY+203+j);
1085
1086         redraw_mask |= REDRAW_DOOR_1;
1087       }
1088
1089       if (door_state & DOOR_ACTION_2)
1090       {
1091         int i = (door_state & DOOR_OPEN_2 ? VXSIZE-x : x);
1092         int j = (VXSIZE - i)/3;
1093
1094         XCopyArea(display,pix[PIX_DB_DOOR],drawto,gc,
1095                   DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2+i/2,
1096                   VXSIZE,VYSIZE-i/2, VX,VY);
1097
1098         XFillRectangle(display,drawto,gc,VX,VY+VYSIZE-i/2,VXSIZE,i/2);
1099
1100         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1101                        VX-i,(VY+j)-DOOR_GFX_PAGEY2);
1102         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1103                   VXSIZE,DOOR_GFX_PAGEY2, i,VYSIZE/2, VX+VXSIZE-i,VY+j);
1104         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1105                        VX-VXSIZE+i,VY-(DOOR_GFX_PAGEY2+j));
1106         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1107                   VXSIZE-i,DOOR_GFX_PAGEY2+j, i,VYSIZE/2-j, VX,VY);
1108
1109         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1110                   VXSIZE-i,DOOR_GFX_PAGEY2+VYSIZE/2, i,VYSIZE/2,
1111                   VX,VY+VYSIZE/2-j);
1112         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1113                        VX-i,(VY+j)-DOOR_GFX_PAGEY2);
1114         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1115                   VXSIZE,DOOR_GFX_PAGEY2+VYSIZE/2, i,VYSIZE/2-j,
1116                   VX+VXSIZE-i,VY+VYSIZE/2+j);
1117
1118         redraw_mask |= REDRAW_DOOR_2;
1119       }
1120
1121       BackToFront();
1122       Delay(door_anim_delay);
1123
1124       if (game_status==MAINMENU)
1125         DoAnimation();
1126     }
1127   }
1128
1129   if (door_state & DOOR_ACTION_1)
1130     door1 = door_state & DOOR_ACTION_1;
1131   if (door_state & DOOR_ACTION_2)
1132     door2 = door_state & DOOR_ACTION_2;
1133 }
1134
1135 int ReadPixel(Drawable d, int x, int y)
1136 {
1137   static XImage *pixelimage;
1138
1139   pixelimage = XGetImage(display, d, x,y, 1,1, AllPlanes, ZPixmap);
1140   return(XGetPixel(pixelimage,0,0));
1141 }
1142
1143 void CheckJoystickData()
1144 {
1145   int i;
1146   int distance = 100;
1147
1148   for(i=0;i<2;i++)
1149   {
1150     if (joystick[i].xmiddle <= distance)
1151       joystick[i].xmiddle = distance;
1152     if (joystick[i].ymiddle <= distance)
1153       joystick[i].ymiddle = distance;
1154
1155     if (joystick[i].xleft >= joystick[i].xmiddle)
1156       joystick[i].xleft = joystick[i].xmiddle-distance;
1157     if (joystick[i].xright <= joystick[i].xmiddle)
1158       joystick[i].xright = joystick[i].xmiddle+distance;
1159
1160     if (joystick[i].yupper >= joystick[i].ymiddle)
1161       joystick[i].yupper = joystick[i].ymiddle-distance;
1162     if (joystick[i].ylower <= joystick[i].ymiddle)
1163       joystick[i].ylower = joystick[i].ymiddle+distance;
1164   }
1165 }
1166
1167 int JoystickPosition(int middle, int margin, int actual)
1168 {
1169   long range, pos;
1170   int percentage;
1171
1172   if (margin<middle && actual>middle)
1173     return(0);
1174   if (margin>middle && actual<middle)
1175     return(0);
1176
1177   range = ABS(margin-middle);
1178   pos = ABS(actual-middle);
1179   percentage = (int)(pos*100/range);
1180   if (percentage>100)
1181     percentage = 100;
1182
1183   return(percentage);
1184 }
1185
1186 int Joystick()
1187 {
1188 #ifdef __FreeBSD__
1189   struct joystick joy_ctrl;
1190 #else
1191   struct joystick_control
1192   {
1193     int buttons;
1194     int x;
1195     int y;
1196   } joy_ctrl;
1197 #endif
1198
1199   int js_x,js_y, js_b1,js_b2;
1200   int left, right, up, down;
1201   int result=0;
1202
1203   if (joystick_status==JOYSTICK_OFF)
1204     return(0);
1205
1206   if (read(joystick_device, &joy_ctrl, sizeof(joy_ctrl)) != sizeof(joy_ctrl))
1207   {
1208     fprintf(stderr,"%s: cannot read joystick settings - no joystick support\n",
1209             progname);
1210     joystick_status = JOYSTICK_OFF;
1211     return(0);
1212   }
1213
1214   js_x  = joy_ctrl.x;
1215   js_y  = joy_ctrl.y;
1216 #ifdef __FreeBSD__
1217   js_b1 = joy_ctrl.b1;
1218   js_b2 = joy_ctrl.b2;
1219 #else
1220   js_b1 = joy_ctrl.buttons & 1;
1221   js_b2 = joy_ctrl.buttons & 2;
1222 #endif
1223
1224   left = JoystickPosition(joystick[joystick_nr].xmiddle,
1225                           joystick[joystick_nr].xleft,  js_x);
1226   right = JoystickPosition(joystick[joystick_nr].xmiddle,
1227                            joystick[joystick_nr].xright, js_x);
1228   up =    JoystickPosition(joystick[joystick_nr].ymiddle,
1229                            joystick[joystick_nr].yupper, js_y);
1230   down =  JoystickPosition(joystick[joystick_nr].ymiddle,
1231                            joystick[joystick_nr].ylower, js_y);
1232
1233   if (left>JOYSTICK_PERCENT)
1234     result |= JOY_LEFT;
1235   else if (right>JOYSTICK_PERCENT)
1236     result |= JOY_RIGHT;
1237   if (up>JOYSTICK_PERCENT)
1238     result |= JOY_UP;
1239   else if (down>JOYSTICK_PERCENT)
1240     result |= JOY_DOWN;
1241   if (js_b1)
1242     result |= JOY_BUTTON_1;
1243   if (js_b2)
1244     result |= JOY_BUTTON_2;
1245
1246   return(result);
1247 }
1248
1249 int JoystickButton()
1250 {
1251   static int last_joy_button = 0;
1252   int joy_button = (Joystick() & JOY_BUTTON);
1253   int result;
1254
1255   if (joy_button)
1256   {
1257     if (last_joy_button)
1258       result = JOY_BUTTON_PRESSED;
1259     else
1260       result = JOY_BUTTON_NEW_PRESSED;
1261   }
1262   else
1263   {
1264     if (last_joy_button)
1265       result = JOY_BUTTON_NEW_RELEASED;
1266     else
1267       result = JOY_BUTTON_NOT_PRESSED;
1268   }
1269
1270   last_joy_button = joy_button;
1271   return(result);
1272 }
1273
1274 int el2gfx(int element)
1275 {
1276   switch(element)
1277   {
1278     case EL_LEERRAUM:           return(-1);
1279     case EL_ERDREICH:           return(GFX_ERDREICH);
1280     case EL_MAUERWERK:          return(GFX_MAUERWERK);
1281     case EL_FELSBODEN:          return(GFX_FELSBODEN);
1282     case EL_FELSBROCKEN:        return(GFX_FELSBROCKEN);
1283     case EL_SCHLUESSEL:         return(GFX_SCHLUESSEL);
1284     case EL_EDELSTEIN:          return(GFX_EDELSTEIN);
1285     case EL_AUSGANG_ZU:         return(GFX_AUSGANG_ZU);
1286     case EL_AUSGANG_ACT:        return(GFX_AUSGANG_ACT);
1287     case EL_AUSGANG_AUF:        return(GFX_AUSGANG_AUF);
1288     case EL_SPIELFIGUR:         return(GFX_SPIELFIGUR);
1289     case EL_SPIELER1:           return(GFX_SPIELER1);
1290     case EL_SPIELER2:           return(GFX_SPIELER2);
1291     case EL_SPIELER3:           return(GFX_SPIELER3);
1292     case EL_SPIELER4:           return(GFX_SPIELER4);
1293     case EL_KAEFER:             return(GFX_KAEFER);
1294     case EL_KAEFER_R:           return(GFX_KAEFER_R);
1295     case EL_KAEFER_O:           return(GFX_KAEFER_O);
1296     case EL_KAEFER_L:           return(GFX_KAEFER_L);
1297     case EL_KAEFER_U:           return(GFX_KAEFER_U);
1298     case EL_FLIEGER:            return(GFX_FLIEGER);
1299     case EL_FLIEGER_R:          return(GFX_FLIEGER_R);
1300     case EL_FLIEGER_O:          return(GFX_FLIEGER_O);
1301     case EL_FLIEGER_L:          return(GFX_FLIEGER_L);
1302     case EL_FLIEGER_U:          return(GFX_FLIEGER_U);
1303     case EL_MAMPFER:            return(GFX_MAMPFER);
1304     case EL_ZOMBIE:             return(GFX_ZOMBIE);
1305     case EL_BETON:              return(GFX_BETON);
1306     case EL_DIAMANT:            return(GFX_DIAMANT);
1307     case EL_MORAST_LEER:        return(GFX_MORAST_LEER);
1308     case EL_MORAST_VOLL:        return(GFX_MORAST_VOLL);
1309     case EL_TROPFEN:            return(GFX_TROPFEN);
1310     case EL_BOMBE:              return(GFX_BOMBE);
1311     case EL_SIEB_LEER:          return(GFX_SIEB_LEER);
1312     case EL_SIEB_VOLL:          return(GFX_SIEB_VOLL);
1313     case EL_SIEB_TOT:           return(GFX_SIEB_TOT);
1314     case EL_SALZSAEURE:         return(GFX_SALZSAEURE);
1315     case EL_AMOEBE_TOT:         return(GFX_AMOEBE_TOT);
1316     case EL_AMOEBE_NASS:        return(GFX_AMOEBE_NASS);
1317     case EL_AMOEBE_NORM:        return(GFX_AMOEBE_NORM);
1318     case EL_AMOEBE_VOLL:        return(GFX_AMOEBE_VOLL);
1319     case EL_AMOEBA2DIAM:        return(GFX_AMOEBA2DIAM);
1320     case EL_KOKOSNUSS:          return(GFX_KOKOSNUSS);
1321     case EL_LIFE:               return(GFX_LIFE);
1322     case EL_LIFE_ASYNC:         return(GFX_LIFE_ASYNC);
1323     case EL_DYNAMIT:            return(GFX_DYNAMIT);
1324     case EL_BADEWANNE:          return(GFX_BADEWANNE);
1325     case EL_BADEWANNE1:         return(GFX_BADEWANNE1);
1326     case EL_BADEWANNE2:         return(GFX_BADEWANNE2);
1327     case EL_BADEWANNE3:         return(GFX_BADEWANNE3);
1328     case EL_BADEWANNE4:         return(GFX_BADEWANNE4);
1329     case EL_BADEWANNE5:         return(GFX_BADEWANNE5);
1330     case EL_ABLENK_AUS:         return(GFX_ABLENK_AUS);
1331     case EL_ABLENK_EIN:         return(GFX_ABLENK_EIN);
1332     case EL_SCHLUESSEL1:        return(GFX_SCHLUESSEL1);
1333     case EL_SCHLUESSEL2:        return(GFX_SCHLUESSEL2);
1334     case EL_SCHLUESSEL3:        return(GFX_SCHLUESSEL3);
1335     case EL_SCHLUESSEL4:        return(GFX_SCHLUESSEL4);
1336     case EL_PFORTE1:            return(GFX_PFORTE1);
1337     case EL_PFORTE2:            return(GFX_PFORTE2);
1338     case EL_PFORTE3:            return(GFX_PFORTE3);
1339     case EL_PFORTE4:            return(GFX_PFORTE4);
1340     case EL_PFORTE1X:           return(GFX_PFORTE1X);
1341     case EL_PFORTE2X:           return(GFX_PFORTE2X);
1342     case EL_PFORTE3X:           return(GFX_PFORTE3X);
1343     case EL_PFORTE4X:           return(GFX_PFORTE4X);
1344     case EL_DYNAMIT_AUS:        return(GFX_DYNAMIT_AUS);
1345     case EL_PACMAN:             return(GFX_PACMAN);
1346     case EL_PACMAN_R:           return(GFX_PACMAN_R);
1347     case EL_PACMAN_O:           return(GFX_PACMAN_O);
1348     case EL_PACMAN_L:           return(GFX_PACMAN_L);
1349     case EL_PACMAN_U:           return(GFX_PACMAN_U);
1350     case EL_UNSICHTBAR:         return(GFX_UNSICHTBAR);
1351     case EL_ERZ_EDEL:           return(GFX_ERZ_EDEL);
1352     case EL_ERZ_DIAM:           return(GFX_ERZ_DIAM);
1353     case EL_BIRNE_AUS:          return(GFX_BIRNE_AUS);
1354     case EL_BIRNE_EIN:          return(GFX_BIRNE_EIN);
1355     case EL_ZEIT_VOLL:          return(GFX_ZEIT_VOLL);
1356     case EL_ZEIT_LEER:          return(GFX_ZEIT_LEER);
1357     default:
1358     {
1359       if (IS_CHAR(element))
1360         return(GFX_CHAR_START + (element-EL_CHAR_START));
1361       else
1362         return(-1);
1363     }
1364   }
1365 }