rocks_n_diamonds-0.9b2
[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 || element==EL_EDELSTEIN2 ||
456             element==EL_EDELSTEIN3 || element==EL_DIAMANT)
457            && horiz_move && phase)
458   {
459     if (element==EL_FELSBROCKEN)
460       graphic += 2;
461     else
462       graphic += 1;
463   }
464   else if ((element==EL_SIEB_LEER || element==EL_SIEB2_LEER ||
465             element==EL_SIEB_VOLL || element==EL_SIEB2_VOLL) && SiebAktiv)
466   {
467     graphic += 3-(SiebAktiv%8)/2;
468   }
469   else if (IS_AMOEBOID(element))
470   {
471     graphic = (element==EL_AMOEBE_TOT ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
472     graphic += (x+2*y) % 4;
473   }
474   else if (element==EL_MAUER_LEBT)
475   {
476     BOOL links_massiv = FALSE, rechts_massiv = FALSE;
477
478     if (!IN_LEV_FIELD(ux-1,uy) || IS_MAUER(Feld[ux-1][uy]))
479       links_massiv = TRUE;
480     if (!IN_LEV_FIELD(ux+1,uy) || IS_MAUER(Feld[ux+1][uy]))
481       rechts_massiv = TRUE;
482
483     if (links_massiv && rechts_massiv)
484       graphic = GFX_MAUERWERK;
485     else if (links_massiv)
486       graphic = GFX_MAUER_R;
487     else if (rechts_massiv)
488       graphic = GFX_MAUER_L;
489   }
490
491   if (dx || dy)
492     DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode);
493   else
494     DrawGraphic(x,y, graphic);
495 }
496
497 void ErdreichAnbroeckeln(int x, int y)
498 {
499   int i, width, height, cx,cy;
500   int ux = UNSCROLLX(x), uy = UNSCROLLY(y);
501   int element, graphic;
502   int snip = 4;
503   static int xy[4][2] =
504   {
505     0,-1,
506     -1,0,
507     +1,0,
508     0,+1
509   };
510
511   if (!IN_LEV_FIELD(ux,uy))
512     return;
513
514   element = Feld[ux][uy];
515
516   if (element==EL_ERDREICH)
517   {
518     if (!IN_SCR_FIELD(x,y))
519       return;
520
521     graphic = GFX_ERDENRAND;
522
523     for(i=0;i<4;i++)
524     {
525       int uxx,uyy;
526
527       uxx = ux+xy[i][0];
528       uyy = uy+xy[i][1];
529       if (!IN_LEV_FIELD(uxx,uyy))
530         element = EL_BETON;
531       else
532         element = Feld[uxx][uyy];
533
534 /*
535       if (element==EL_ERDREICH || IS_SOLID(element))
536         continue;
537 */
538       if (element==EL_ERDREICH)
539         continue;
540
541       if (i==1 || i==2)
542       {
543         width = snip;
544         height = TILEY;
545         cx = (i==2 ? TILEX-snip : 0);
546         cy = 0;
547       }
548       else
549       {
550         width = TILEX;
551         height = snip;
552         cx = 0;
553         cy = (i==3 ? TILEY-snip : 0);
554       }
555
556       XCopyArea(display,pix[PIX_BACK],drawto_field,gc,
557                 SX+(graphic % GFX_PER_LINE)*TILEX+cx,
558                 SY+(graphic / GFX_PER_LINE)*TILEY+cy,
559                 width,height, SX+x*TILEX+cx,SY+y*TILEY+cy);
560     }
561
562     redraw_tiles++;
563     redraw[x][y]=TRUE;
564   }
565   else
566   {
567     graphic = GFX_ERDENRAND;
568
569     for(i=0;i<4;i++)
570     {
571       int xx,yy,uxx,uyy;
572
573       xx = x+xy[i][0];
574       yy = y+xy[i][1];
575       uxx = ux+xy[i][0];
576       uyy = uy+xy[i][1];
577 /*
578       if (!IN_LEV_FIELD(uxx,uyy) || Feld[uxx][uyy]!=EL_ERDREICH ||
579           !IN_SCR_FIELD(xx,yy) || IS_SOLID(element))
580         continue;
581 */
582
583       if (!IN_LEV_FIELD(uxx,uyy) || Feld[uxx][uyy]!=EL_ERDREICH ||
584           !IN_SCR_FIELD(xx,yy))
585         continue;
586
587       if (i==1 || i==2)
588       {
589         width = snip;
590         height = TILEY;
591         cx = (i==1 ? TILEX-snip : 0);
592         cy = 0;
593       }
594       else
595       {
596         width = TILEX;
597         height = snip;
598         cx = 0;
599         cy = (i==0 ? TILEY-snip : 0);
600       }
601
602       XCopyArea(display,pix[PIX_BACK],drawto_field,gc,
603                 SX+(graphic % GFX_PER_LINE)*TILEX+cx,
604                 SY+(graphic / GFX_PER_LINE)*TILEY+cy,
605                 width,height, SX+xx*TILEX+cx,SY+yy*TILEY+cy);
606
607       redraw_tiles++;
608       redraw[xx][yy]=TRUE;
609     }
610   }
611 }
612
613 void DrawScreenElement(int x, int y, int element)
614 {
615   DrawElementShifted(x,y,0,0,element,CUT_NO_CUTTING);
616   ErdreichAnbroeckeln(x,y);
617 }
618
619 void DrawLevelElement(int x, int y, int element)
620 {
621   if (IN_LEV_FIELD(x,y) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
622     DrawScreenElement(SCROLLX(x),SCROLLY(y),element);
623 }
624
625 void DrawScreenField(int x, int y)
626 {
627   int ux = UNSCROLLX(x), uy = UNSCROLLY(y);
628   int element;
629
630   if (!IN_LEV_FIELD(ux,uy))
631   {
632     DrawScreenElement(x,y,EL_BETON);
633     return;
634   }
635
636   element = Feld[ux][uy];
637
638   if (IS_MOVING(ux,uy))
639   {
640     int horiz_move = (MovDir[ux][uy]==MV_LEFT || MovDir[ux][uy]==MV_RIGHT);
641     BOOL cut_mode = CUT_NO_CUTTING;
642
643     if (Store[ux][uy]==EL_MORAST_LEER ||
644         Store[ux][uy]==EL_SIEB_LEER ||
645         Store[ux][uy]==EL_SIEB2_LEER ||
646         Store[ux][uy]==EL_AMOEBE_NASS)
647       cut_mode = CUT_ABOVE;
648     else if (Store[ux][uy]==EL_MORAST_VOLL ||
649         Store[ux][uy]==EL_SIEB_VOLL ||
650         Store[ux][uy]==EL_SIEB2_VOLL ||
651         Store[ux][uy]==EL_SALZSAEURE)
652       cut_mode = CUT_BELOW;
653
654     if (cut_mode==CUT_ABOVE)
655       DrawElementShifted(x,y,0,0,Store[ux][uy],CUT_NO_CUTTING);
656     else
657       DrawScreenElement(x,y,EL_LEERRAUM);
658
659     if (horiz_move)
660       DrawElementShifted(x,y,MovPos[ux][uy],0,element,CUT_NO_CUTTING);
661     else
662       DrawElementShifted(x,y,0,MovPos[ux][uy],element,cut_mode);
663   }
664   else if (IS_BLOCKED(ux,uy))
665   {
666     int oldx,oldy;
667     int sx, sy;
668     int horiz_move;
669     BOOL cut_mode = CUT_NO_CUTTING;
670
671     Blocked2Moving(ux,uy,&oldx,&oldy);
672     sx = SCROLLX(oldx);
673     sy = SCROLLY(oldy);
674     horiz_move = (MovDir[oldx][oldy]==MV_LEFT || MovDir[oldx][oldy]==MV_RIGHT);
675
676     if (Store[oldx][oldy]==EL_MORAST_LEER ||
677         Store[oldx][oldy]==EL_SIEB_LEER ||
678         Store[oldx][oldy]==EL_SIEB2_LEER ||
679         Store[oldx][oldy]==EL_AMOEBE_NASS)
680       cut_mode = CUT_ABOVE;
681
682     DrawScreenElement(x,y,EL_LEERRAUM);
683     element = Feld[oldx][oldy];
684
685     if (horiz_move)
686       DrawElementShifted(sx,sy,MovPos[oldx][oldy],0,element,CUT_NO_CUTTING);
687     else
688       DrawElementShifted(sx,sy,0,MovPos[oldx][oldy],element,cut_mode);
689   }
690   else if (IS_DRAWABLE(element))
691     DrawScreenElement(x,y,element);
692   else
693     DrawScreenElement(x,y,EL_LEERRAUM);
694 }
695
696 void DrawLevelField(int x, int y)
697 {
698   if (IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
699     DrawScreenField(SCROLLX(x),SCROLLY(y));
700   else if (IS_MOVING(x,y))
701   {
702     int newx,newy;
703
704     Moving2Blocked(x,y,&newx,&newy);
705     if (IN_SCR_FIELD(SCROLLX(newx),SCROLLY(newy)))
706       DrawScreenField(SCROLLX(newx),SCROLLY(newy));
707   }
708   else if (IS_BLOCKED(x,y))
709   {
710     int oldx,oldy;
711
712     Blocked2Moving(x,y,&oldx,&oldy);
713     if (IN_SCR_FIELD(SCROLLX(oldx),SCROLLY(oldy)))
714       DrawScreenField(SCROLLX(oldx),SCROLLY(oldy));
715   }
716 }
717
718 void DrawMiniElement(int x, int y, int element)
719 {
720   int graphic;
721
722   if (!element)
723   {
724     DrawMiniGraphic(x,y,-1);
725     return;
726   }
727
728   graphic = el2gfx(element);
729   DrawMiniGraphic(x,y,graphic);
730
731   redraw_tiles++;
732   redraw[x/2][y/2]=TRUE;
733   redraw_mask|=REDRAW_TILES;
734 }
735
736 void DrawMiniElementOrWall(int x, int y, int scroll_x, int scroll_y)
737 {
738   if (x+scroll_x<-1 || x+scroll_x>lev_fieldx ||
739       y+scroll_y<-1 || y+scroll_y>lev_fieldy)
740     DrawMiniElement(x,y,EL_LEERRAUM);
741   else if (x+scroll_x==-1 || x+scroll_x==lev_fieldx ||
742            y+scroll_y==-1 || y+scroll_y==lev_fieldy)
743     DrawMiniElement(x,y,EL_BETON);
744   else
745     DrawMiniElement(x,y,Feld[x+scroll_x][y+scroll_y]);
746 }
747
748 void DrawMicroElement(int xpos, int ypos, int element)
749 {
750   int graphic;
751
752   if (element==EL_LEERRAUM)
753     return;
754
755   graphic = el2gfx(element);
756
757   XCopyArea(display,pix[PIX_BACK],drawto,gc,
758             MICRO_GFX_STARTX+(graphic % MICRO_GFX_PER_LINE)*MICRO_TILEX,
759             MICRO_GFX_STARTY+(graphic / MICRO_GFX_PER_LINE)*MICRO_TILEY,
760             MICRO_TILEX,MICRO_TILEY, xpos,ypos);
761 }
762
763 void DrawLevel()
764 {
765   int x,y;
766
767   ClearWindow();
768
769   for(x=0;x<SCR_FIELDX;x++)
770     for(y=0;y<SCR_FIELDY;y++)
771       DrawScreenField(x,y);
772
773   redraw_mask |= REDRAW_FIELD;
774 }
775
776 void DrawMiniLevel(int scroll_x, int scroll_y)
777 {
778   int x,y;
779
780   ClearWindow();
781
782   for(x=0;x<2*SCR_FIELDX;x++)
783     for(y=0;y<2*SCR_FIELDY;y++)
784       DrawMiniElementOrWall(x,y,scroll_x,scroll_y);
785
786   redraw_mask |= REDRAW_FIELD;
787 }
788
789 void DrawMicroLevel(int xpos, int ypos)
790 {
791   int x,y;
792
793   XFillRectangle(display,drawto,gc,
794                  xpos-MICRO_TILEX,ypos-MICRO_TILEY,
795                  MICRO_TILEX*(STD_LEV_FIELDX+2),
796                  MICRO_TILEY*(STD_LEV_FIELDY+2));
797
798   for(x=-1;x<=STD_LEV_FIELDX;x++)
799     for(y=-1;y<=STD_LEV_FIELDY;y++)
800       if (x>=0 && x<lev_fieldx && y>=0 && y<lev_fieldy)
801         DrawMicroElement(xpos+MICRO_TILEX*x,ypos+MICRO_TILEY*y,
802                          Feld[x][y]=Ur[x][y]);
803       else if (x>=-1 && x<lev_fieldx+1 && y>=-1 && y<lev_fieldy+1)
804         DrawMicroElement(xpos+MICRO_TILEX*x,ypos+MICRO_TILEY*y,
805                          EL_BETON);
806
807   XFillRectangle(display,drawto,gc, SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE);
808
809   if (level.name)
810   {
811     int len = strlen(level.name);
812     int lxpos = SX+(SXSIZE-len*FONT4_XSIZE)/2;
813     int lypos = MICROLABEL_YPOS;
814
815     DrawText(lxpos,lypos,level.name,FS_SMALL,FC_SPECIAL2);
816   }
817
818   redraw_mask |= REDRAW_MICROLEV;
819 }
820
821 int AYS_in_range(int x, int y)
822 {
823   if (y>DY+249 && y<DY+278)
824   {
825     if (x>DX+1 && x<DX+48)
826       return(1);
827     else if (x>DX+51 && x<DX+98) 
828       return(2);
829   }
830   return(0);
831 }
832
833 BOOL AreYouSure(char *text, unsigned int ays_state)
834 {
835   int mx,my, ty, result = -1;
836
837   CloseDoor(DOOR_CLOSE_1);
838
839   /* Alten Türinhalt sichern */
840   XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
841             DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
842             DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1);
843
844   /* Fragetext schreiben */
845   XFillRectangle(display,pix[PIX_DB_DOOR],gc,
846                  DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1,DXSIZE,DYSIZE);
847
848   for(ty=0;ty<13;ty++)
849   {
850     int tx,tl,tc;
851     char txt[256];
852
853     if (!(*text))
854       break;
855     for(tl=0,tx=0;tx<7;tl++,tx++)
856     {
857       tc=*(text+tx);
858       if (!tc || tc==32)
859         break;
860     }
861     if (!tl)
862     { 
863       text++; 
864       ty--; 
865       continue; 
866     }
867     sprintf(txt,text); 
868     txt[tl]=0;
869     DrawTextExt(pix[PIX_DB_DOOR],gc,
870                 DOOR_GFX_PAGEX1+51-(tl*14)/2,SY+ty*16,txt,FS_SMALL,FC_YELLOW);
871     text+=(tl+(tc==32));
872   }
873
874   if (ays_state & AYS_ASK)
875     XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
876               DOOR_GFX_PAGEX4,OK_BUTTON_GFX_YPOS,
877               DXSIZE,OK_BUTTON_YSIZE,
878               DOOR_GFX_PAGEX1,OK_BUTTON_YPOS);
879   else if (ays_state & AYS_CONFIRM)
880     XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
881               DOOR_GFX_PAGEX4,CONFIRM_BUTTON_GFX_YPOS,
882               DXSIZE,CONFIRM_BUTTON_YSIZE,
883               DOOR_GFX_PAGEX1,CONFIRM_BUTTON_YPOS);
884
885   OpenDoor(DOOR_OPEN_1);
886
887   if (!(ays_state & AYS_ASK) && !(ays_state & AYS_CONFIRM))
888     return(FALSE);
889
890   if (game_status!=MAINMENU)
891     InitAnimation();
892
893   button_status = MB_RELEASED;
894
895   while(result<0)
896   {
897     DoAnimation();
898     Delay(10000);
899
900     if (XPending(display))
901     {
902       XEvent event;
903
904       XNextEvent(display, &event);
905       switch(event.type)
906       {
907         case Expose:
908           HandleExposeEvent((XExposeEvent *) &event);
909           break;
910         case UnmapNotify:
911           SleepWhileUnmapped();
912           break;
913         case ButtonPress:
914         case ButtonRelease:
915         case MotionNotify:
916         {
917           int choice;
918
919           if (event.type==MotionNotify)
920           {
921             motion_status = TRUE;
922             mx = ((XMotionEvent *) &event)->x;
923             my = ((XMotionEvent *) &event)->y;
924           }
925           else
926           {
927             motion_status = FALSE;
928             mx = ((XButtonEvent *) &event)->x;
929             my = ((XButtonEvent *) &event)->y;
930             if (event.type==ButtonPress)
931               button_status = ((XButtonEvent *) &event)->button;
932             else
933               button_status = MB_RELEASED;
934           }
935
936           if (ays_state & AYS_ASK)
937             choice = CheckChooseButtons(mx,my,button_status);
938           else
939             choice = CheckConfirmButton(mx,my,button_status);
940
941           switch(choice)
942           {
943             case BUTTON_OK:
944               result = TRUE;
945               break;
946             case BUTTON_NO:
947               result = FALSE;
948               break;
949             case BUTTON_CONFIRM:
950               result = TRUE|FALSE;
951               break;
952             default:
953               break;
954           }
955           break;
956         }
957         case KeyPress:
958           key_status = KEY_PRESSED;
959           switch(XLookupKeysym((XKeyEvent *)&event,
960                                ((XKeyEvent *)&event)->state))
961           {
962             case XK_Return:
963               result = 1;
964               break;
965             case XK_Escape:
966               result = 0;
967               break;
968           }
969           break;
970         case FocusIn:
971           HandleFocusEvent(FOCUS_IN);
972           break;
973         case FocusOut:
974           HandleFocusEvent(FOCUS_OUT);
975           break;
976         default:
977           break;
978       }
979     }
980     else if (JoystickButton()==JOY_BUTTON_NEW_PRESSED)
981     {
982       int joy=Joystick();
983
984       if (joy & JOY_BUTTON_1)
985         result = 1;
986       else if (joy & JOY_BUTTON_2)
987         result = 0;
988     }
989   }
990
991   if (game_status!=MAINMENU)
992     StopAnimation();
993
994   if (!(ays_state & AYS_STAY_OPEN))
995   {
996     CloseDoor(DOOR_CLOSE_1);
997
998     if (!(ays_state & AYS_STAY_CLOSED) &&
999         (game_status==PLAYING || game_status==LEVELED))
1000     {
1001       XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1002                 DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
1003                 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1004       OpenDoor(DOOR_OPEN_1);
1005     }
1006   }
1007
1008   return(result);
1009 }
1010
1011 void OpenDoor(unsigned int door_state)
1012 {
1013   if (door_state & DOOR_COPY_BACK)
1014   {
1015     XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1016               DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE+VYSIZE,
1017               DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1018     door_state &= ~DOOR_COPY_BACK;
1019   }
1020
1021   MoveDoor(door_state);
1022   ClearEventQueue();
1023 }
1024
1025 void CloseDoor(unsigned int door_state)
1026 {
1027   XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,
1028             DX,DY, DXSIZE,DYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1029   XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,
1030             VX,VY, VXSIZE,VYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1031
1032   MoveDoor(door_state);
1033   ClearEventQueue();
1034 }
1035
1036 void MoveDoor(unsigned int door_state)
1037 {
1038   static int door1 = DOOR_OPEN_1;
1039   static int door2 = DOOR_CLOSE_2;
1040   int x, start, stepsize = 4, door_anim_delay = stepsize*5000;
1041
1042   if (door1==DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
1043     door_state &= ~DOOR_OPEN_1;
1044   else if (door1==DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
1045     door_state &= ~DOOR_CLOSE_1;
1046   if (door2==DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
1047     door_state &= ~DOOR_OPEN_2;
1048   else if (door2==DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
1049     door_state &= ~DOOR_CLOSE_2;
1050
1051   if (quick_doors)
1052   {
1053     stepsize = 20;
1054     door_anim_delay = 0;
1055     StopSound(SND_OEFFNEN);
1056   }
1057
1058   if (door_state & DOOR_ACTION)
1059   {
1060     if (!(door_state & DOOR_NO_DELAY))
1061       PlaySoundStereo(SND_OEFFNEN,PSND_MAX_RIGHT);
1062
1063     start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
1064
1065     for(x=start;x<=DXSIZE;x+=stepsize)
1066     {
1067       if (door_state & DOOR_ACTION_1)
1068       {
1069         int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
1070         int j = (DXSIZE - i)/3;
1071
1072         XCopyArea(display,pix[PIX_DB_DOOR],drawto,gc,
1073                   DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1+i/2,
1074                   DXSIZE,DYSIZE-i/2, DX,DY);
1075
1076         XFillRectangle(display,drawto,gc,DX,DY+DYSIZE-i/2,DXSIZE,i/2);
1077
1078         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1079                        DX-i,(DY+j)-DOOR_GFX_PAGEY1);
1080         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1081                   DXSIZE,DOOR_GFX_PAGEY1, i,77, DX+DXSIZE-i,DY+j);
1082         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1083                   DXSIZE,DOOR_GFX_PAGEY1+140, i,63, DX+DXSIZE-i,DY+140+j);
1084         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1085                        DX-DXSIZE+i,DY-(DOOR_GFX_PAGEY1+j));
1086         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1087                   DXSIZE-i,DOOR_GFX_PAGEY1+j, i,77-j, DX,DY);
1088         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1089                   DXSIZE-i,DOOR_GFX_PAGEY1+140, i,63, DX,DY+140-j);
1090
1091         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1092                   DXSIZE-i,DOOR_GFX_PAGEY1+77, i,63,
1093                   DX,DY+77-j);
1094         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1095                   DXSIZE-i,DOOR_GFX_PAGEY1+203, i,77,
1096                   DX,DY+203-j);
1097         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1098                        DX-i,(DY+j)-DOOR_GFX_PAGEY1);
1099         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1100                   DXSIZE,DOOR_GFX_PAGEY1+77, i,63,
1101                   DX+DXSIZE-i,DY+77+j);
1102         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1103                   DXSIZE,DOOR_GFX_PAGEY1+203, i,77-j,
1104                   DX+DXSIZE-i,DY+203+j);
1105
1106         redraw_mask |= REDRAW_DOOR_1;
1107       }
1108
1109       if (door_state & DOOR_ACTION_2)
1110       {
1111         int i = (door_state & DOOR_OPEN_2 ? VXSIZE-x : x);
1112         int j = (VXSIZE - i)/3;
1113
1114         XCopyArea(display,pix[PIX_DB_DOOR],drawto,gc,
1115                   DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2+i/2,
1116                   VXSIZE,VYSIZE-i/2, VX,VY);
1117
1118         XFillRectangle(display,drawto,gc,VX,VY+VYSIZE-i/2,VXSIZE,i/2);
1119
1120         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1121                        VX-i,(VY+j)-DOOR_GFX_PAGEY2);
1122         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1123                   VXSIZE,DOOR_GFX_PAGEY2, i,VYSIZE/2, VX+VXSIZE-i,VY+j);
1124         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1125                        VX-VXSIZE+i,VY-(DOOR_GFX_PAGEY2+j));
1126         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1127                   VXSIZE-i,DOOR_GFX_PAGEY2+j, i,VYSIZE/2-j, VX,VY);
1128
1129         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1130                   VXSIZE-i,DOOR_GFX_PAGEY2+VYSIZE/2, i,VYSIZE/2,
1131                   VX,VY+VYSIZE/2-j);
1132         XSetClipOrigin(display,clip_gc[PIX_DOOR],
1133                        VX-i,(VY+j)-DOOR_GFX_PAGEY2);
1134         XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
1135                   VXSIZE,DOOR_GFX_PAGEY2+VYSIZE/2, i,VYSIZE/2-j,
1136                   VX+VXSIZE-i,VY+VYSIZE/2+j);
1137
1138         redraw_mask |= REDRAW_DOOR_2;
1139       }
1140
1141       BackToFront();
1142       Delay(door_anim_delay);
1143
1144       if (game_status==MAINMENU)
1145         DoAnimation();
1146     }
1147   }
1148
1149   if (door_state & DOOR_ACTION_1)
1150     door1 = door_state & DOOR_ACTION_1;
1151   if (door_state & DOOR_ACTION_2)
1152     door2 = door_state & DOOR_ACTION_2;
1153 }
1154
1155 int ReadPixel(Drawable d, int x, int y)
1156 {
1157   static XImage *pixelimage;
1158
1159   pixelimage = XGetImage(display, d, x,y, 1,1, AllPlanes, ZPixmap);
1160   return(XGetPixel(pixelimage,0,0));
1161 }
1162
1163 void CheckJoystickData()
1164 {
1165   int i;
1166   int distance = 100;
1167
1168   for(i=0;i<2;i++)
1169   {
1170     if (joystick[i].xmiddle <= distance)
1171       joystick[i].xmiddle = distance;
1172     if (joystick[i].ymiddle <= distance)
1173       joystick[i].ymiddle = distance;
1174
1175     if (joystick[i].xleft >= joystick[i].xmiddle)
1176       joystick[i].xleft = joystick[i].xmiddle-distance;
1177     if (joystick[i].xright <= joystick[i].xmiddle)
1178       joystick[i].xright = joystick[i].xmiddle+distance;
1179
1180     if (joystick[i].yupper >= joystick[i].ymiddle)
1181       joystick[i].yupper = joystick[i].ymiddle-distance;
1182     if (joystick[i].ylower <= joystick[i].ymiddle)
1183       joystick[i].ylower = joystick[i].ymiddle+distance;
1184   }
1185 }
1186
1187 int JoystickPosition(int middle, int margin, int actual)
1188 {
1189   long range, pos;
1190   int percentage;
1191
1192   if (margin<middle && actual>middle)
1193     return(0);
1194   if (margin>middle && actual<middle)
1195     return(0);
1196
1197   range = ABS(margin-middle);
1198   pos = ABS(actual-middle);
1199   percentage = (int)(pos*100/range);
1200   if (percentage>100)
1201     percentage = 100;
1202
1203   return(percentage);
1204 }
1205
1206 int Joystick()
1207 {
1208 #ifdef __FreeBSD__
1209   struct joystick joy_ctrl;
1210 #else
1211   struct joystick_control
1212   {
1213     int buttons;
1214     int x;
1215     int y;
1216   } joy_ctrl;
1217 #endif
1218
1219   int js_x,js_y, js_b1,js_b2;
1220   int left, right, up, down;
1221   int result=0;
1222
1223   if (joystick_status==JOYSTICK_OFF)
1224     return(0);
1225
1226   if (read(joystick_device, &joy_ctrl, sizeof(joy_ctrl)) != sizeof(joy_ctrl))
1227   {
1228     fprintf(stderr,"%s: cannot read joystick settings - no joystick support\n",
1229             progname);
1230     joystick_status = JOYSTICK_OFF;
1231     return(0);
1232   }
1233
1234   js_x  = joy_ctrl.x;
1235   js_y  = joy_ctrl.y;
1236 #ifdef __FreeBSD__
1237   js_b1 = joy_ctrl.b1;
1238   js_b2 = joy_ctrl.b2;
1239 #else
1240   js_b1 = joy_ctrl.buttons & 1;
1241   js_b2 = joy_ctrl.buttons & 2;
1242 #endif
1243
1244   left = JoystickPosition(joystick[joystick_nr].xmiddle,
1245                           joystick[joystick_nr].xleft,  js_x);
1246   right = JoystickPosition(joystick[joystick_nr].xmiddle,
1247                            joystick[joystick_nr].xright, js_x);
1248   up =    JoystickPosition(joystick[joystick_nr].ymiddle,
1249                            joystick[joystick_nr].yupper, js_y);
1250   down =  JoystickPosition(joystick[joystick_nr].ymiddle,
1251                            joystick[joystick_nr].ylower, js_y);
1252
1253   if (left>JOYSTICK_PERCENT)
1254     result |= JOY_LEFT;
1255   else if (right>JOYSTICK_PERCENT)
1256     result |= JOY_RIGHT;
1257   if (up>JOYSTICK_PERCENT)
1258     result |= JOY_UP;
1259   else if (down>JOYSTICK_PERCENT)
1260     result |= JOY_DOWN;
1261   if (js_b1)
1262     result |= JOY_BUTTON_1;
1263   if (js_b2)
1264     result |= JOY_BUTTON_2;
1265
1266   return(result);
1267 }
1268
1269 int JoystickButton()
1270 {
1271   static int last_joy_button = 0;
1272   int joy_button = (Joystick() & JOY_BUTTON);
1273   int result;
1274
1275   if (joy_button)
1276   {
1277     if (last_joy_button)
1278       result = JOY_BUTTON_PRESSED;
1279     else
1280       result = JOY_BUTTON_NEW_PRESSED;
1281   }
1282   else
1283   {
1284     if (last_joy_button)
1285       result = JOY_BUTTON_NEW_RELEASED;
1286     else
1287       result = JOY_BUTTON_NOT_PRESSED;
1288   }
1289
1290   last_joy_button = joy_button;
1291   return(result);
1292 }
1293
1294 int el2gfx(int element)
1295 {
1296   switch(element)
1297   {
1298     case EL_LEERRAUM:           return(-1);
1299     case EL_ERDREICH:           return(GFX_ERDREICH);
1300     case EL_MAUERWERK:          return(GFX_MAUERWERK);
1301     case EL_FELSBODEN:          return(GFX_FELSBODEN);
1302     case EL_FELSBROCKEN:        return(GFX_FELSBROCKEN);
1303     case EL_SCHLUESSEL:         return(GFX_SCHLUESSEL);
1304     case EL_EDELSTEIN:          return(GFX_EDELSTEIN);
1305     case EL_AUSGANG_ZU:         return(GFX_AUSGANG_ZU);
1306     case EL_AUSGANG_ACT:        return(GFX_AUSGANG_ACT);
1307     case EL_AUSGANG_AUF:        return(GFX_AUSGANG_AUF);
1308     case EL_SPIELFIGUR:         return(GFX_SPIELFIGUR);
1309     case EL_SPIELER1:           return(GFX_SPIELER1);
1310     case EL_SPIELER2:           return(GFX_SPIELER2);
1311     case EL_SPIELER3:           return(GFX_SPIELER3);
1312     case EL_SPIELER4:           return(GFX_SPIELER4);
1313     case EL_KAEFER:             return(GFX_KAEFER);
1314     case EL_KAEFER_R:           return(GFX_KAEFER_R);
1315     case EL_KAEFER_O:           return(GFX_KAEFER_O);
1316     case EL_KAEFER_L:           return(GFX_KAEFER_L);
1317     case EL_KAEFER_U:           return(GFX_KAEFER_U);
1318     case EL_FLIEGER:            return(GFX_FLIEGER);
1319     case EL_FLIEGER_R:          return(GFX_FLIEGER_R);
1320     case EL_FLIEGER_O:          return(GFX_FLIEGER_O);
1321     case EL_FLIEGER_L:          return(GFX_FLIEGER_L);
1322     case EL_FLIEGER_U:          return(GFX_FLIEGER_U);
1323     case EL_MAMPFER:            return(GFX_MAMPFER);
1324     case EL_ZOMBIE:             return(GFX_ZOMBIE);
1325     case EL_BETON:              return(GFX_BETON);
1326     case EL_DIAMANT:            return(GFX_DIAMANT);
1327     case EL_MORAST_LEER:        return(GFX_MORAST_LEER);
1328     case EL_MORAST_VOLL:        return(GFX_MORAST_VOLL);
1329     case EL_TROPFEN:            return(GFX_TROPFEN);
1330     case EL_BOMBE:              return(GFX_BOMBE);
1331     case EL_SIEB_LEER:          return(GFX_SIEB_LEER);
1332     case EL_SIEB_VOLL:          return(GFX_SIEB_VOLL);
1333     case EL_SIEB_TOT:           return(GFX_SIEB_TOT);
1334     case EL_SALZSAEURE:         return(GFX_SALZSAEURE);
1335     case EL_AMOEBE_TOT:         return(GFX_AMOEBE_TOT);
1336     case EL_AMOEBE_NASS:        return(GFX_AMOEBE_NASS);
1337     case EL_AMOEBE_NORM:        return(GFX_AMOEBE_NORM);
1338     case EL_AMOEBE_VOLL:        return(GFX_AMOEBE_VOLL);
1339     case EL_AMOEBA2DIAM:        return(GFX_AMOEBA2DIAM);
1340     case EL_KOKOSNUSS:          return(GFX_KOKOSNUSS);
1341     case EL_LIFE:               return(GFX_LIFE);
1342     case EL_LIFE_ASYNC:         return(GFX_LIFE_ASYNC);
1343     case EL_DYNAMIT:            return(GFX_DYNAMIT);
1344     case EL_BADEWANNE:          return(GFX_BADEWANNE);
1345     case EL_BADEWANNE1:         return(GFX_BADEWANNE1);
1346     case EL_BADEWANNE2:         return(GFX_BADEWANNE2);
1347     case EL_BADEWANNE3:         return(GFX_BADEWANNE3);
1348     case EL_BADEWANNE4:         return(GFX_BADEWANNE4);
1349     case EL_BADEWANNE5:         return(GFX_BADEWANNE5);
1350     case EL_ABLENK_AUS:         return(GFX_ABLENK_AUS);
1351     case EL_ABLENK_EIN:         return(GFX_ABLENK_EIN);
1352     case EL_SCHLUESSEL1:        return(GFX_SCHLUESSEL1);
1353     case EL_SCHLUESSEL2:        return(GFX_SCHLUESSEL2);
1354     case EL_SCHLUESSEL3:        return(GFX_SCHLUESSEL3);
1355     case EL_SCHLUESSEL4:        return(GFX_SCHLUESSEL4);
1356     case EL_PFORTE1:            return(GFX_PFORTE1);
1357     case EL_PFORTE2:            return(GFX_PFORTE2);
1358     case EL_PFORTE3:            return(GFX_PFORTE3);
1359     case EL_PFORTE4:            return(GFX_PFORTE4);
1360     case EL_PFORTE1X:           return(GFX_PFORTE1X);
1361     case EL_PFORTE2X:           return(GFX_PFORTE2X);
1362     case EL_PFORTE3X:           return(GFX_PFORTE3X);
1363     case EL_PFORTE4X:           return(GFX_PFORTE4X);
1364     case EL_DYNAMIT_AUS:        return(GFX_DYNAMIT_AUS);
1365     case EL_PACMAN:             return(GFX_PACMAN);
1366     case EL_PACMAN_R:           return(GFX_PACMAN_R);
1367     case EL_PACMAN_O:           return(GFX_PACMAN_O);
1368     case EL_PACMAN_L:           return(GFX_PACMAN_L);
1369     case EL_PACMAN_U:           return(GFX_PACMAN_U);
1370     case EL_UNSICHTBAR:         return(GFX_UNSICHTBAR);
1371     case EL_ERZ_EDEL:           return(GFX_ERZ_EDEL);
1372     case EL_ERZ_DIAM:           return(GFX_ERZ_DIAM);
1373     case EL_BIRNE_AUS:          return(GFX_BIRNE_AUS);
1374     case EL_BIRNE_EIN:          return(GFX_BIRNE_EIN);
1375     case EL_ZEIT_VOLL:          return(GFX_ZEIT_VOLL);
1376     case EL_ZEIT_LEER:          return(GFX_ZEIT_LEER);
1377     case EL_MAUER_LEBT:         return(GFX_MAUER_LEBT);
1378     case EL_EDELSTEIN2:         return(GFX_EDELSTEIN2);
1379     case EL_EDELSTEIN3:         return(GFX_EDELSTEIN3);
1380     case EL_ERZ_EDEL2:          return(GFX_ERZ_EDEL2);
1381     case EL_ERZ_EDEL3:          return(GFX_ERZ_EDEL3);
1382     case EL_MAMPFER2:           return(GFX_MAMPFER2);
1383     case EL_SIEB2_LEER:         return(GFX_SIEB2_LEER);
1384     case EL_SIEB2_VOLL:         return(GFX_SIEB2_VOLL);
1385     case EL_SIEB2_TOT:          return(GFX_SIEB2_TOT);
1386     case EL_DYNABOMB:           return(GFX_DYNABOMB);
1387     case EL_DYNABOMB_NR:        return(GFX_DYNABOMB_NR);
1388     case EL_DYNABOMB_SZ:        return(GFX_DYNABOMB_SZ);
1389     default:
1390     {
1391       if (IS_CHAR(element))
1392         return(GFX_CHAR_START + (element-EL_CHAR_START));
1393       else
1394         return(-1);
1395     }
1396   }
1397 }