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