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