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