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