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