rnd-20041126-1-src
[rocksndiamonds.git] / src / tools.c
1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back!               *
3 *----------------------------------------------------------*
4 * (c) 1995-2002 Artsoft Entertainment                      *
5 *               Holger Schemel                             *
6 *               Detmolder Strasse 189                      *
7 *               33604 Bielefeld                            *
8 *               Germany                                    *
9 *               e-mail: info@artsoft.org                   *
10 *----------------------------------------------------------*
11 * tools.c                                                  *
12 ***********************************************************/
13
14 #include "libgame/libgame.h"
15
16 #include "tools.h"
17 #include "game.h"
18 #include "events.h"
19 #include "cartoons.h"
20 #include "network.h"
21 #include "tape.h"
22
23 /* tool button identifiers */
24 #define TOOL_CTRL_ID_YES        0
25 #define TOOL_CTRL_ID_NO         1
26 #define TOOL_CTRL_ID_CONFIRM    2
27 #define TOOL_CTRL_ID_PLAYER_1   3
28 #define TOOL_CTRL_ID_PLAYER_2   4
29 #define TOOL_CTRL_ID_PLAYER_3   5
30 #define TOOL_CTRL_ID_PLAYER_4   6
31
32 #define NUM_TOOL_BUTTONS        7
33
34 /* forward declaration for internal use */
35 static void UnmapToolButtons();
36 static void HandleToolButtons(struct GadgetInfo *);
37 static int el_act_dir2crm(int, int, int);
38 static int el_act2crm(int, int);
39
40 static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS];
41 static int request_gadget_id = -1;
42
43 static char *print_if_not_empty(int element)
44 {
45   static char *s = NULL;
46   char *token_name = element_info[element].token_name;
47
48   if (s != NULL)
49     free(s);
50
51   s = checked_malloc(strlen(token_name) + 10 + 1);
52
53   if (element != EL_EMPTY)
54     sprintf(s, "%d\t['%s']", element, token_name);
55   else
56     sprintf(s, "%d", element);
57
58   return s;
59 }
60
61 void DumpTile(int x, int y)
62 {
63   int sx = SCREENX(x);
64   int sy = SCREENY(y);
65
66   printf_line("-", 79);
67   printf("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
68   printf_line("-", 79);
69
70   if (!IN_LEV_FIELD(x, y))
71   {
72     printf("(not in level field)\n");
73     printf("\n");
74
75     return;
76   }
77
78   printf("  Feld:        %d\t['%s']\n", Feld[x][y],
79          element_info[Feld[x][y]].token_name);
80   printf("  Back:        %s\n", print_if_not_empty(Back[x][y]));
81   printf("  Store:       %s\n", print_if_not_empty(Store[x][y]));
82   printf("  Store2:      %s\n", print_if_not_empty(Store2[x][y]));
83   printf("  StorePlayer: %s\n", print_if_not_empty(StorePlayer[x][y]));
84   printf("  MovPos:      %d\n", MovPos[x][y]);
85   printf("  MovDir:      %d\n", MovDir[x][y]);
86   printf("  MovDelay:    %d\n", MovDelay[x][y]);
87   printf("  ChangeDelay: %d\n", ChangeDelay[x][y]);
88   printf("  GfxElement:  %d\n", GfxElement[x][y]);
89   printf("  GfxAction:   %d\n", GfxAction[x][y]);
90   printf("  GfxFrame:    %d\n", GfxFrame[x][y]);
91   printf("\n");
92 }
93
94 void SetDrawtoField(int mode)
95 {
96   if (mode == DRAW_BUFFERED && setup.soft_scrolling)
97   {
98     FX = TILEX;
99     FY = TILEY;
100     BX1 = -1;
101     BY1 = -1;
102     BX2 = SCR_FIELDX;
103     BY2 = SCR_FIELDY;
104     redraw_x1 = 1;
105     redraw_y1 = 1;
106
107     drawto_field = fieldbuffer;
108   }
109   else  /* DRAW_DIRECT, DRAW_BACKBUFFER */
110   {
111     FX = SX;
112     FY = SY;
113     BX1 = 0;
114     BY1 = 0;
115     BX2 = SCR_FIELDX - 1;
116     BY2 = SCR_FIELDY - 1;
117     redraw_x1 = 0;
118     redraw_y1 = 0;
119
120     drawto_field = (mode == DRAW_DIRECT ? window :  backbuffer);
121   }
122 }
123
124 void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height)
125 {
126   if (game_status == GAME_MODE_PLAYING && !game.envelope_active)
127   {
128     if (force_redraw)
129     {
130       x = gfx.sx - TILEX;
131       y = gfx.sy - TILEY;
132       width = gfx.sxsize + 2 * TILEX;
133       height = gfx.sysize + 2 * TILEY;
134     }
135
136     if (force_redraw || setup.direct_draw)
137     {
138       int xx, yy;
139       int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY;
140       int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY;
141
142       if (setup.direct_draw)
143         SetDrawtoField(DRAW_BACKBUFFER);
144
145       for (xx = BX1; xx <= BX2; xx++)
146         for (yy = BY1; yy <= BY2; yy++)
147           if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
148             DrawScreenField(xx, yy);
149       DrawAllPlayers();
150
151       if (setup.direct_draw)
152         SetDrawtoField(DRAW_DIRECT);
153     }
154
155     if (setup.soft_scrolling)
156     {
157       int fx = FX, fy = FY;
158
159       fx += (ScreenMovDir & (MV_LEFT|MV_RIGHT) ? ScreenGfxPos : 0);
160       fy += (ScreenMovDir & (MV_UP|MV_DOWN)    ? ScreenGfxPos : 0);
161
162       BlitBitmap(fieldbuffer, backbuffer, fx,fy, SXSIZE,SYSIZE, SX,SY);
163     }
164   }
165
166   BlitBitmap(drawto, window, x, y, width, height, x, y);
167 }
168
169 void BackToFront()
170 {
171   int x,y;
172   DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field);
173
174   if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
175     redraw_mask &= ~REDRAW_MAIN;
176
177   if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD)
178     redraw_mask |= REDRAW_FIELD;
179
180   if (redraw_mask & REDRAW_FIELD)
181     redraw_mask &= ~REDRAW_TILES;
182
183   if (redraw_mask == REDRAW_NONE)
184     return;
185
186   if (global.fps_slowdown && game_status == GAME_MODE_PLAYING)
187   {
188     static boolean last_frame_skipped = FALSE;
189     boolean skip_even_when_not_scrolling = TRUE;
190     boolean just_scrolling = (ScreenMovDir != 0);
191     boolean verbose = FALSE;
192
193     if (global.fps_slowdown_factor > 1 &&
194         (FrameCounter % global.fps_slowdown_factor) &&
195         (just_scrolling || skip_even_when_not_scrolling))
196     {
197       redraw_mask &= ~REDRAW_MAIN;
198
199       last_frame_skipped = TRUE;
200
201       if (verbose)
202         printf("FRAME SKIPPED\n");
203     }
204     else
205     {
206       if (last_frame_skipped)
207         redraw_mask |= REDRAW_FIELD;
208
209       last_frame_skipped = FALSE;
210
211       if (verbose)
212         printf("frame not skipped\n");
213     }
214   }
215
216   /* synchronize X11 graphics at this point; if we would synchronize the
217      display immediately after the buffer switching (after the XFlush),
218      this could mean that we have to wait for the graphics to complete,
219      although we could go on doing calculations for the next frame */
220
221   SyncDisplay();
222
223   if (redraw_mask & REDRAW_ALL)
224   {
225     BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
226     redraw_mask = 0;
227   }
228
229   if (redraw_mask & REDRAW_FIELD)
230   {
231     if (game_status != GAME_MODE_PLAYING ||
232         redraw_mask & REDRAW_FROM_BACKBUFFER)
233     {
234       BlitBitmap(backbuffer, window,
235                  REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY);
236     }
237     else
238     {
239       int fx = FX, fy = FY;
240
241       if (setup.soft_scrolling)
242       {
243         fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0);
244         fy += (ScreenMovDir & (MV_UP | MV_DOWN)    ? ScreenGfxPos : 0);
245       }
246
247       if (setup.soft_scrolling ||
248           ABS(ScreenMovPos) + ScrollStepSize == TILEX ||
249           ABS(ScreenMovPos) == ScrollStepSize ||
250           redraw_tiles > REDRAWTILES_THRESHOLD)
251       {
252         BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY);
253
254 #ifdef DEBUG
255 #if 0
256         printf("redrawing all (ScreenGfxPos == %d) because %s\n",
257                ScreenGfxPos,
258                (setup.soft_scrolling ?
259                 "setup.soft_scrolling" :
260                 ABS(ScreenGfxPos) + ScrollStepSize == TILEX ?
261                 "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" :
262                 ABS(ScreenGfxPos) == ScrollStepSize ?
263                 "ABS(ScreenGfxPos) == ScrollStepSize" :
264                 "redraw_tiles > REDRAWTILES_THRESHOLD"));
265 #endif
266 #endif
267       }
268     }
269
270     redraw_mask &= ~REDRAW_MAIN;
271   }
272
273   if (redraw_mask & REDRAW_DOORS)
274   {
275     if (redraw_mask & REDRAW_DOOR_1)
276       BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY);
277
278     if (redraw_mask & REDRAW_DOOR_2)
279     {
280 #if 0
281       if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
282 #endif
283         BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY);
284 #if 0
285       else
286       {
287         if (redraw_mask & REDRAW_VIDEO_1)
288           BlitBitmap(backbuffer, window,
289                      VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS,
290                      VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
291                      VX + VIDEO_DISPLAY1_XPOS, VY + VIDEO_DISPLAY1_YPOS);
292         if (redraw_mask & REDRAW_VIDEO_2)
293           BlitBitmap(backbuffer, window,
294                      VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS,
295                      VIDEO_DISPLAY_XSIZE, VIDEO_DISPLAY_YSIZE,
296                      VX + VIDEO_DISPLAY2_XPOS, VY + VIDEO_DISPLAY2_YPOS);
297         if (redraw_mask & REDRAW_VIDEO_3)
298           BlitBitmap(backbuffer, window,
299                      VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS,
300                      VIDEO_CONTROL_XSIZE, VIDEO_CONTROL_YSIZE,
301                      VX + VIDEO_CONTROL_XPOS, VY + VIDEO_CONTROL_YPOS);
302       }
303 #endif
304     }
305
306     if (redraw_mask & REDRAW_DOOR_3)
307       BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY);
308
309     redraw_mask &= ~REDRAW_DOORS;
310   }
311
312   if (redraw_mask & REDRAW_MICROLEVEL)
313   {
314     BlitBitmap(backbuffer, window, SX, SY + 10 * TILEY, SXSIZE, 7 * TILEY,
315                SX, SY + 10 * TILEY);
316
317     redraw_mask &= ~REDRAW_MICROLEVEL;
318   }
319
320   if (redraw_mask & REDRAW_TILES)
321   {
322     for (x = 0; x < SCR_FIELDX; x++)
323       for (y = 0 ; y < SCR_FIELDY; y++)
324         if (redraw[redraw_x1 + x][redraw_y1 + y])
325           BlitBitmap(buffer, window,
326                      FX + x * TILEX, FY + y * TILEY, TILEX, TILEY,
327                      SX + x * TILEX, SY + y * TILEY);
328   }
329
330   if (redraw_mask & REDRAW_FPS)         /* display frames per second */
331   {
332     char text[100];
333     char info1[100];
334
335     sprintf(info1, " (only every %d. frame)", global.fps_slowdown_factor);
336     if (!global.fps_slowdown)
337       info1[0] = '\0';
338
339     sprintf(text, "%.1f fps%s", global.frames_per_second, info1);
340     DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE);
341   }
342
343   FlushDisplay();
344
345   for (x = 0; x < MAX_BUF_XSIZE; x++)
346     for (y = 0; y < MAX_BUF_YSIZE; y++)
347       redraw[x][y] = 0;
348   redraw_tiles = 0;
349   redraw_mask = REDRAW_NONE;
350 }
351
352 void FadeToFront()
353 {
354 #if 0
355   long fading_delay = 300;
356
357   if (setup.fading && (redraw_mask & REDRAW_FIELD))
358   {
359 #endif
360
361 #if 0
362     int x,y;
363
364     ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
365     FlushDisplay();
366
367     for (i = 0; i < 2 * FULL_SYSIZE; i++)
368     {
369       for (y = 0; y < FULL_SYSIZE; y++)
370       {
371         BlitBitmap(backbuffer, window,
372                    REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
373       }
374       FlushDisplay();
375       Delay(10);
376     }
377 #endif
378
379 #if 0
380     for (i = 1; i < FULL_SYSIZE; i+=2)
381       BlitBitmap(backbuffer, window,
382                  REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i);
383     FlushDisplay();
384     Delay(fading_delay);
385 #endif
386
387 #if 0
388     SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0);
389     BlitBitmapMasked(backbuffer, window,
390                      REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
391                      REAL_SX,REAL_SY);
392     FlushDisplay();
393     Delay(fading_delay);
394
395     SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1);
396     BlitBitmapMasked(backbuffer, window,
397                      REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
398                      REAL_SX,REAL_SY);
399     FlushDisplay();
400     Delay(fading_delay);
401
402     SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1);
403     BlitBitmapMasked(backbuffer, window,
404                      REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
405                      REAL_SX,REAL_SY);
406     FlushDisplay();
407     Delay(fading_delay);
408
409     SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0);
410     BlitBitmapMasked(backbuffer, window,
411                      REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
412                      REAL_SX,REAL_SY);
413     FlushDisplay();
414     Delay(fading_delay);
415
416     redraw_mask &= ~REDRAW_MAIN;
417   }
418 #endif
419
420   BackToFront();
421 }
422
423 void SetMainBackgroundImage(int graphic)
424 {
425   SetMainBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
426                           graphic_info[graphic].bitmap ?
427                           graphic_info[graphic].bitmap :
428                           graphic_info[IMG_BACKGROUND].bitmap);
429 }
430
431 void SetDoorBackgroundImage(int graphic)
432 {
433   SetDoorBackgroundBitmap(graphic == IMG_UNDEFINED ? NULL :
434                           graphic_info[graphic].bitmap ?
435                           graphic_info[graphic].bitmap :
436                           graphic_info[IMG_BACKGROUND].bitmap);
437 }
438
439 void DrawBackground(int dst_x, int dst_y, int width, int height)
440 {
441   ClearRectangleOnBackground(backbuffer, dst_x, dst_y, width, height);
442
443   redraw_mask |= REDRAW_FIELD;
444 }
445
446 void ClearWindow()
447 {
448   DrawBackground(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
449
450   if (setup.soft_scrolling && game_status == GAME_MODE_PLAYING)
451   {
452     ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE);
453     SetDrawtoField(DRAW_BUFFERED);
454   }
455   else
456     SetDrawtoField(DRAW_BACKBUFFER);
457
458   if (setup.direct_draw && game_status == GAME_MODE_PLAYING)
459   {
460     ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
461     SetDrawtoField(DRAW_DIRECT);
462   }
463 }
464
465 void MarkTileDirty(int x, int y)
466 {
467   int xx = redraw_x1 + x;
468   int yy = redraw_y1 + y;
469
470   if (!redraw[xx][yy])
471     redraw_tiles++;
472
473   redraw[xx][yy] = TRUE;
474   redraw_mask |= REDRAW_TILES;
475 }
476
477 void SetBorderElement()
478 {
479   int x, y;
480
481   BorderElement = EL_EMPTY;
482
483   for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
484   {
485     for (x = 0; x < lev_fieldx; x++)
486     {
487       if (!IS_INDESTRUCTIBLE(Feld[x][y]))
488         BorderElement = EL_STEELWALL;
489
490       if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
491         x = lev_fieldx - 2;
492     }
493   }
494 }
495
496 void SetRandomAnimationValue(int x, int y)
497 {
498   gfx.anim_random_frame = GfxRandom[x][y];
499 }
500
501 inline int getGraphicAnimationFrame(int graphic, int sync_frame)
502 {
503   /* animation synchronized with global frame counter, not move position */
504   if (graphic_info[graphic].anim_global_sync || sync_frame < 0)
505     sync_frame = FrameCounter;
506
507   return getAnimationFrame(graphic_info[graphic].anim_frames,
508                            graphic_info[graphic].anim_delay,
509                            graphic_info[graphic].anim_mode,
510                            graphic_info[graphic].anim_start_frame,
511                            sync_frame);
512 }
513
514 inline void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
515                                 int *x, int *y, boolean get_backside)
516 {
517   struct GraphicInfo *g = &graphic_info[graphic];
518   int src_x = g->src_x + (get_backside ? g->offset2_x : 0);
519   int src_y = g->src_y + (get_backside ? g->offset2_y : 0);
520
521   *bitmap = g->bitmap;
522
523   if (g->offset_y == 0)         /* frames are ordered horizontally */
524   {
525     int max_width = g->anim_frames_per_line * g->width;
526 #if 1
527     int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x;
528
529     *x = pos % max_width;
530     *y = src_y % g->height + pos / max_width * g->height;
531 #else
532     *x = (src_x + frame * g->offset_x) % max_width;
533     *y = src_y + (src_x + frame * g->offset_x) / max_width * g->height;
534 #endif
535   }
536   else if (g->offset_x == 0)    /* frames are ordered vertically */
537   {
538     int max_height = g->anim_frames_per_line * g->height;
539 #if 1
540     int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y;
541
542     *x = src_x % g->width + pos / max_height * g->width;
543     *y = pos % max_height;
544 #else
545     *x = src_x + (src_y + frame * g->offset_y) / max_height * g->width;
546     *y = (src_y + frame * g->offset_y) % max_height;
547 #endif
548   }
549   else                          /* frames are ordered diagonally */
550   {
551     *x = src_x + frame * g->offset_x;
552     *y = src_y + frame * g->offset_y;
553   }
554 }
555
556 void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y)
557 {
558   getGraphicSourceExt(graphic, frame, bitmap, x, y, FALSE);
559 }
560
561 void DrawGraphic(int x, int y, int graphic, int frame)
562 {
563 #if DEBUG
564   if (!IN_SCR_FIELD(x, y))
565   {
566     printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
567     printf("DrawGraphic(): This should never happen!\n");
568     return;
569   }
570 #endif
571
572   DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame);
573   MarkTileDirty(x, y);
574 }
575
576 void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic,
577                     int frame)
578 {
579   Bitmap *src_bitmap;
580   int src_x, src_y;
581
582   getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
583   BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y);
584 }
585
586 void DrawGraphicThruMask(int x, int y, int graphic, int frame)
587 {
588 #if DEBUG
589   if (!IN_SCR_FIELD(x, y))
590   {
591     printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
592     printf("DrawGraphicThruMask(): This should never happen!\n");
593     return;
594   }
595 #endif
596
597   DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic,
598                          frame);
599   MarkTileDirty(x, y);
600 }
601
602 void DrawGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, int graphic,
603                             int frame)
604 {
605   Bitmap *src_bitmap;
606   int src_x, src_y;
607
608   getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
609
610   SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
611                 dst_x - src_x, dst_y - src_y);
612   BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y);
613 }
614
615 void DrawMiniGraphic(int x, int y, int graphic)
616 {
617   DrawMiniGraphicExt(drawto, SX + x * MINI_TILEX,SY + y * MINI_TILEY, graphic);
618   MarkTileDirty(x / 2, y / 2);
619 }
620
621 void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
622 {
623   struct GraphicInfo *g = &graphic_info[graphic];
624   int mini_startx = 0;
625   int mini_starty = g->bitmap->height * 2 / 3;
626
627   *bitmap = g->bitmap;
628   *x = mini_startx + g->src_x / 2;
629   *y = mini_starty + g->src_y / 2;
630 }
631
632 void DrawMiniGraphicExt(DrawBuffer *d, int x, int y, int graphic)
633 {
634   Bitmap *src_bitmap;
635   int src_x, src_y;
636
637   getMiniGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
638   BlitBitmap(src_bitmap, d, src_x, src_y, MINI_TILEX, MINI_TILEY, x, y);
639 }
640
641 inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy,
642                                             int graphic, int frame,
643                                             int cut_mode, int mask_mode)
644 {
645   Bitmap *src_bitmap;
646   int src_x, src_y;
647   int dst_x, dst_y;
648   int width = TILEX, height = TILEY;
649   int cx = 0, cy = 0;
650
651   if (dx || dy)                 /* shifted graphic */
652   {
653     if (x < BX1)                /* object enters playfield from the left */
654     {
655       x = BX1;
656       width = dx;
657       cx = TILEX - dx;
658       dx = 0;
659     }
660     else if (x > BX2)           /* object enters playfield from the right */
661     {
662       x = BX2;
663       width = -dx;
664       dx = TILEX + dx;
665     }
666     else if (x==BX1 && dx < 0)  /* object leaves playfield to the left */
667     {
668       width += dx;
669       cx = -dx;
670       dx = 0;
671     }
672     else if (x==BX2 && dx > 0)  /* object leaves playfield to the right */
673       width -= dx;
674     else if (dx)                /* general horizontal movement */
675       MarkTileDirty(x + SIGN(dx), y);
676
677     if (y < BY1)                /* object enters playfield from the top */
678     {
679       if (cut_mode==CUT_BELOW)  /* object completely above top border */
680         return;
681
682       y = BY1;
683       height = dy;
684       cy = TILEY - dy;
685       dy = 0;
686     }
687     else if (y > BY2)           /* object enters playfield from the bottom */
688     {
689       y = BY2;
690       height = -dy;
691       dy = TILEY + dy;
692     }
693     else if (y==BY1 && dy < 0)  /* object leaves playfield to the top */
694     {
695       height += dy;
696       cy = -dy;
697       dy = 0;
698     }
699     else if (dy > 0 && cut_mode == CUT_ABOVE)
700     {
701       if (y == BY2)             /* object completely above bottom border */
702         return;
703
704       height = dy;
705       cy = TILEY - dy;
706       dy = TILEY;
707       MarkTileDirty(x, y + 1);
708     }                           /* object leaves playfield to the bottom */
709     else if (dy > 0 && (y == BY2 || cut_mode == CUT_BELOW))
710       height -= dy;
711     else if (dy)                /* general vertical movement */
712       MarkTileDirty(x, y + SIGN(dy));
713   }
714
715 #if DEBUG
716   if (!IN_SCR_FIELD(x, y))
717   {
718     printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
719     printf("DrawGraphicShifted(): This should never happen!\n");
720     return;
721   }
722 #endif
723
724   if (width > 0 && height > 0)
725   {
726     getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
727
728     src_x += cx;
729     src_y += cy;
730
731     dst_x = FX + x * TILEX + dx;
732     dst_y = FY + y * TILEY + dy;
733
734     if (mask_mode == USE_MASKING)
735     {
736       SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
737                     dst_x - src_x, dst_y - src_y);
738       BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
739                        dst_x, dst_y);
740     }
741     else
742       BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
743                  dst_x, dst_y);
744
745     MarkTileDirty(x, y);
746   }
747 }
748
749 inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy,
750                                             int graphic, int frame,
751                                             int cut_mode, int mask_mode)
752 {
753   Bitmap *src_bitmap;
754   int src_x, src_y;
755   int dst_x, dst_y;
756   int width = TILEX, height = TILEY;
757   int x1 = x;
758   int y1 = y;
759   int x2 = x + SIGN(dx);
760   int y2 = y + SIGN(dy);
761   int anim_frames = graphic_info[graphic].anim_frames;
762   int sync_frame = (dx ? ABS(dx) : ABS(dy)) * anim_frames / TILESIZE;
763
764   /* re-calculate animation frame for two-tile movement animation */
765   frame = getGraphicAnimationFrame(graphic, sync_frame);
766
767   if (IN_SCR_FIELD(x1, y1))     /* movement start graphic inside screen area */
768   {
769     getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE);
770
771     dst_x = FX + x1 * TILEX;
772     dst_y = FY + y1 * TILEY;
773
774     if (mask_mode == USE_MASKING)
775     {
776       SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
777                     dst_x - src_x, dst_y - src_y);
778       BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
779                        dst_x, dst_y);
780     }
781     else
782       BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
783                  dst_x, dst_y);
784
785     MarkTileDirty(x1, y1);
786   }
787
788   if (IN_SCR_FIELD(x2, y2))     /* movement end graphic inside screen area */
789   {
790     getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE);
791
792     dst_x = FX + x2 * TILEX;
793     dst_y = FY + y2 * TILEY;
794
795     if (mask_mode == USE_MASKING)
796     {
797       SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
798                     dst_x - src_x, dst_y - src_y);
799       BlitBitmapMasked(src_bitmap, drawto_field, src_x, src_y, width, height,
800                        dst_x, dst_y);
801     }
802     else
803       BlitBitmap(src_bitmap, drawto_field, src_x, src_y, width, height,
804                  dst_x, dst_y);
805
806     MarkTileDirty(x2, y2);
807   }
808
809 #if 0
810   printf("::: DONE DrawGraphicShiftedDouble");
811   BackToFront();
812   Delay(1000);
813 #endif
814 }
815
816 static void DrawGraphicShifted(int x, int y, int dx, int dy,
817                                int graphic, int frame,
818                                int cut_mode, int mask_mode)
819 {
820   if (graphic < 0)
821   {
822     DrawGraphic(x, y, graphic, frame);
823
824     return;
825   }
826
827   if (graphic_info[graphic].double_movement)    /* EM style movement images */
828     DrawGraphicShiftedDouble(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
829   else
830     DrawGraphicShiftedNormal(x, y, dx, dy, graphic, frame, cut_mode,mask_mode);
831 }
832
833 void DrawGraphicShiftedThruMask(int x, int y, int dx, int dy, int graphic,
834                                 int frame, int cut_mode)
835 {
836   DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, USE_MASKING);
837 }
838
839 void DrawScreenElementExt(int x, int y, int dx, int dy, int element,
840                           int cut_mode, int mask_mode)
841 {
842   int lx = LEVELX(x), ly = LEVELY(y);
843   int graphic;
844   int frame;
845
846   if (IN_LEV_FIELD(lx, ly))
847   {
848     SetRandomAnimationValue(lx, ly);
849
850     graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
851     frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
852
853     /* do not use double (EM style) movement graphic when not moving */
854     if (graphic_info[graphic].double_movement && !dx && !dy)
855     {
856       graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
857       frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
858     }
859   }
860   else  /* border element */
861   {
862     graphic = el2img(element);
863     frame = getGraphicAnimationFrame(graphic, -1);
864   }
865
866   if (element == EL_EXPANDABLE_WALL)
867   {
868     boolean left_stopped = FALSE, right_stopped = FALSE;
869
870     if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
871       left_stopped = TRUE;
872     if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
873       right_stopped = TRUE;
874
875     if (left_stopped && right_stopped)
876       graphic = IMG_WALL;
877     else if (left_stopped)
878     {
879       graphic = IMG_EXPANDABLE_WALL_GROWING_RIGHT;
880       frame = graphic_info[graphic].anim_frames - 1;
881     }
882     else if (right_stopped)
883     {
884       graphic = IMG_EXPANDABLE_WALL_GROWING_LEFT;
885       frame = graphic_info[graphic].anim_frames - 1;
886     }
887   }
888
889   if (dx || dy)
890     DrawGraphicShifted(x, y, dx, dy, graphic, frame, cut_mode, mask_mode);
891   else if (mask_mode == USE_MASKING)
892     DrawGraphicThruMask(x, y, graphic, frame);
893   else
894     DrawGraphic(x, y, graphic, frame);
895 }
896
897 void DrawLevelElementExt(int x, int y, int dx, int dy, int element,
898                          int cut_mode, int mask_mode)
899 {
900   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
901     DrawScreenElementExt(SCREENX(x), SCREENY(y), dx, dy, element,
902                          cut_mode, mask_mode);
903 }
904
905 void DrawScreenElementShifted(int x, int y, int dx, int dy, int element,
906                               int cut_mode)
907 {
908   DrawScreenElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
909 }
910
911 void DrawLevelElementShifted(int x, int y, int dx, int dy, int element,
912                              int cut_mode)
913 {
914   DrawLevelElementExt(x, y, dx, dy, element, cut_mode, NO_MASKING);
915 }
916
917 void DrawLevelElementThruMask(int x, int y, int element)
918 {
919   DrawLevelElementExt(x, y, 0, 0, element, NO_CUTTING, USE_MASKING);
920 }
921
922 void DrawLevelFieldThruMask(int x, int y)
923 {
924   DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
925 }
926
927 #define TILE_GFX_ELEMENT(x, y)                                              \
928         (GfxElement[x][y] != EL_UNDEFINED && Feld[x][y] != EL_EXPLOSION ?   \
929          GfxElement[x][y] : Feld[x][y])
930
931 static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame)
932 {
933   Bitmap *src_bitmap;
934   int src_x, src_y;
935   int sx = SCREENX(x), sy = SCREENY(y);
936   int element;
937   int width, height, cx, cy, i;
938 #if 1
939   int crumbled_border_size = graphic_info[graphic].border_size;
940 #else
941   int snip = TILEX / 8; /* number of border pixels from "crumbled graphic" */
942 #endif
943   static int xy[4][2] =
944   {
945     { 0, -1 },
946     { -1, 0 },
947     { +1, 0 },
948     { 0, +1 }
949   };
950
951 #if 0
952   if (x == 0 && y == 7)
953     printf("::: %d, %d [%d]\n", GfxElement[x][y], Feld[x][y],
954            crumbled_border_size);
955 #endif
956
957   if (!IN_LEV_FIELD(x, y))
958     return;
959
960   element = TILE_GFX_ELEMENT(x, y);
961
962   /* crumble field itself */
963   if (GFX_CRUMBLED(element) && !IS_MOVING(x, y))
964   {
965     if (!IN_SCR_FIELD(sx, sy))
966       return;
967
968     getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
969
970     for (i = 0; i < 4; i++)
971     {
972       int xx = x + xy[i][0];
973       int yy = y + xy[i][1];
974
975 #if 1
976       element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) :
977                  BorderElement);
978 #else
979       element = (IN_LEV_FIELD(xx, yy) ? Feld[xx][yy] : BorderElement);
980 #endif
981
982       /* check if neighbour field is of same type */
983       if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy))
984         continue;
985
986 #if 0
987       if (Feld[x][y] == EL_CUSTOM_START + 123)
988         printf("::: crumble [%d] THE CHAOS ENGINE (%d, %d): %d, %d\n",
989                i, Feld[x][y], element,
990                GFX_CRUMBLED(element), IS_MOVING(x, y));
991 #endif
992
993       if (i == 1 || i == 2)
994       {
995         width = crumbled_border_size;
996         height = TILEY;
997         cx = (i == 2 ? TILEX - crumbled_border_size : 0);
998         cy = 0;
999       }
1000       else
1001       {
1002         width = TILEX;
1003         height = crumbled_border_size;
1004         cx = 0;
1005         cy = (i == 3 ? TILEY - crumbled_border_size : 0);
1006       }
1007
1008       BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1009                  width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy);
1010     }
1011
1012     MarkTileDirty(sx, sy);
1013   }
1014   else          /* crumble neighbour fields */
1015   {
1016 #if 0
1017     getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1018 #endif
1019
1020     for (i = 0; i < 4; i++)
1021     {
1022       int xx = x + xy[i][0];
1023       int yy = y + xy[i][1];
1024       int sxx = sx + xy[i][0];
1025       int syy = sy + xy[i][1];
1026
1027 #if 1
1028       if (!IN_LEV_FIELD(xx, yy) ||
1029           !IN_SCR_FIELD(sxx, syy) ||
1030           IS_MOVING(xx, yy))
1031         continue;
1032
1033       element = TILE_GFX_ELEMENT(xx, yy);
1034
1035       if (!GFX_CRUMBLED(element))
1036         continue;
1037 #else
1038       if (!IN_LEV_FIELD(xx, yy) ||
1039           !IN_SCR_FIELD(sxx, syy) ||
1040           !GFX_CRUMBLED(Feld[xx][yy]) ||
1041           IS_MOVING(xx, yy))
1042         continue;
1043 #endif
1044
1045 #if 1
1046       graphic = el_act2crm(Feld[xx][yy], ACTION_DEFAULT);
1047       crumbled_border_size = graphic_info[graphic].border_size;
1048
1049       getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
1050 #endif
1051
1052       if (i == 1 || i == 2)
1053       {
1054         width = crumbled_border_size;
1055         height = TILEY;
1056         cx = (i == 1 ? TILEX - crumbled_border_size : 0);
1057         cy = 0;
1058       }
1059       else
1060       {
1061         width = TILEX;
1062         height = crumbled_border_size;
1063         cx = 0;
1064         cy = (i == 0 ? TILEY - crumbled_border_size : 0);
1065       }
1066
1067       BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
1068                  width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy);
1069
1070       MarkTileDirty(sxx, syy);
1071     }
1072   }
1073 }
1074
1075 void DrawLevelFieldCrumbledSand(int x, int y)
1076 {
1077 #if 1
1078   int graphic;
1079
1080   if (!IN_LEV_FIELD(x, y))
1081     return;
1082
1083   graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT);
1084
1085   DrawLevelFieldCrumbledSandExt(x, y, graphic, 0);
1086 #else
1087   DrawLevelFieldCrumbledSandExt(x, y, IMG_SAND_CRUMBLED, 0);
1088 #endif
1089 }
1090
1091 void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction,
1092                                        int step_frame)
1093 {
1094 #if 1
1095   int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction);
1096   int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction);
1097 #else
1098   int graphic1 = el_act_dir2img(EL_SAND,          ACTION_DIGGING, direction);
1099   int graphic2 = el_act_dir2img(EL_SAND_CRUMBLED, ACTION_DIGGING, direction);
1100 #endif
1101   int frame1 = getGraphicAnimationFrame(graphic1, step_frame);
1102   int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
1103   int sx = SCREENX(x), sy = SCREENY(y);
1104
1105   DrawGraphic(sx, sy, graphic1, frame1);
1106   DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2);
1107 }
1108
1109 void DrawLevelFieldCrumbledSandNeighbours(int x, int y)
1110 {
1111   int sx = SCREENX(x), sy = SCREENY(y);
1112   static int xy[4][2] =
1113   {
1114     { 0, -1 },
1115     { -1, 0 },
1116     { +1, 0 },
1117     { 0, +1 }
1118   };
1119   int i;
1120
1121   for (i = 0; i < 4; i++)
1122   {
1123     int xx = x + xy[i][0];
1124     int yy = y + xy[i][1];
1125     int sxx = sx + xy[i][0];
1126     int syy = sy + xy[i][1];
1127
1128     if (!IN_LEV_FIELD(xx, yy) ||
1129         !IN_SCR_FIELD(sxx, syy) ||
1130         !GFX_CRUMBLED(Feld[xx][yy]) ||
1131         IS_MOVING(xx, yy))
1132       continue;
1133
1134     DrawLevelField(xx, yy);
1135   }
1136 }
1137
1138 static int getBorderElement(int x, int y)
1139 {
1140   int border[7][2] =
1141   {
1142     { EL_STEELWALL_TOPLEFT,             EL_INVISIBLE_STEELWALL_TOPLEFT     },
1143     { EL_STEELWALL_TOPRIGHT,            EL_INVISIBLE_STEELWALL_TOPRIGHT    },
1144     { EL_STEELWALL_BOTTOMLEFT,          EL_INVISIBLE_STEELWALL_BOTTOMLEFT  },
1145     { EL_STEELWALL_BOTTOMRIGHT,         EL_INVISIBLE_STEELWALL_BOTTOMRIGHT },
1146     { EL_STEELWALL_VERTICAL,            EL_INVISIBLE_STEELWALL_VERTICAL    },
1147     { EL_STEELWALL_HORIZONTAL,          EL_INVISIBLE_STEELWALL_HORIZONTAL  },
1148     { EL_STEELWALL,                     EL_INVISIBLE_STEELWALL             }
1149   };
1150   int steel_type = (BorderElement == EL_STEELWALL ? 0 : 1);
1151   int steel_position = (x == -1         && y == -1              ? 0 :
1152                         x == lev_fieldx && y == -1              ? 1 :
1153                         x == -1         && y == lev_fieldy      ? 2 :
1154                         x == lev_fieldx && y == lev_fieldy      ? 3 :
1155                         x == -1         || x == lev_fieldx      ? 4 :
1156                         y == -1         || y == lev_fieldy      ? 5 : 6);
1157
1158   return border[steel_position][steel_type];
1159 }
1160
1161 void DrawScreenElement(int x, int y, int element)
1162 {
1163   DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
1164   DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y));
1165 }
1166
1167 void DrawLevelElement(int x, int y, int element)
1168 {
1169   if (IN_LEV_FIELD(x, y) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1170     DrawScreenElement(SCREENX(x), SCREENY(y), element);
1171 }
1172
1173 void DrawScreenField(int x, int y)
1174 {
1175   int lx = LEVELX(x), ly = LEVELY(y);
1176   int element, content;
1177
1178   if (!IN_LEV_FIELD(lx, ly))
1179   {
1180     if (lx < -1 || lx > lev_fieldx || ly < -1 || ly > lev_fieldy)
1181       element = EL_EMPTY;
1182     else
1183       element = getBorderElement(lx, ly);
1184
1185     DrawScreenElement(x, y, element);
1186     return;
1187   }
1188
1189   element = Feld[lx][ly];
1190   content = Store[lx][ly];
1191
1192   if (IS_MOVING(lx, ly))
1193   {
1194     int horiz_move = (MovDir[lx][ly] == MV_LEFT || MovDir[lx][ly] == MV_RIGHT);
1195     boolean cut_mode = NO_CUTTING;
1196
1197     if (element == EL_QUICKSAND_EMPTYING ||
1198         element == EL_MAGIC_WALL_EMPTYING ||
1199         element == EL_BD_MAGIC_WALL_EMPTYING ||
1200         element == EL_AMOEBA_DROPPING)
1201       cut_mode = CUT_ABOVE;
1202     else if (element == EL_QUICKSAND_FILLING ||
1203              element == EL_MAGIC_WALL_FILLING ||
1204              element == EL_BD_MAGIC_WALL_FILLING)
1205       cut_mode = CUT_BELOW;
1206
1207     if (cut_mode == CUT_ABOVE)
1208       DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING);
1209     else
1210       DrawScreenElement(x, y, EL_EMPTY);
1211
1212     if (horiz_move)
1213       DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
1214     else if (cut_mode == NO_CUTTING)
1215       DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode);
1216     else
1217       DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode);
1218
1219     if (content == EL_ACID)
1220     {
1221       int dir = MovDir[lx][ly];
1222       int newlx = lx + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
1223       int newly = ly + (dir == MV_UP   ? -1 : dir == MV_DOWN  ? +1 : 0);
1224
1225       DrawLevelElementThruMask(newlx, newly, EL_ACID);
1226     }
1227   }
1228   else if (IS_BLOCKED(lx, ly))
1229   {
1230     int oldx, oldy;
1231     int sx, sy;
1232     int horiz_move;
1233     boolean cut_mode = NO_CUTTING;
1234     int element_old, content_old;
1235
1236     Blocked2Moving(lx, ly, &oldx, &oldy);
1237     sx = SCREENX(oldx);
1238     sy = SCREENY(oldy);
1239     horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
1240                   MovDir[oldx][oldy] == MV_RIGHT);
1241
1242     element_old = Feld[oldx][oldy];
1243     content_old = Store[oldx][oldy];
1244
1245     if (element_old == EL_QUICKSAND_EMPTYING ||
1246         element_old == EL_MAGIC_WALL_EMPTYING ||
1247         element_old == EL_BD_MAGIC_WALL_EMPTYING ||
1248         element_old == EL_AMOEBA_DROPPING)
1249       cut_mode = CUT_ABOVE;
1250
1251     DrawScreenElement(x, y, EL_EMPTY);
1252
1253     if (horiz_move)
1254       DrawScreenElementShifted(sx, sy, MovPos[oldx][oldy], 0, element_old,
1255                                NO_CUTTING);
1256     else if (cut_mode == NO_CUTTING)
1257       DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], element_old,
1258                                cut_mode);
1259     else
1260       DrawScreenElementShifted(sx, sy, 0, MovPos[oldx][oldy], content_old,
1261                                cut_mode);
1262   }
1263   else if (IS_DRAWABLE(element))
1264     DrawScreenElement(x, y, element);
1265   else
1266     DrawScreenElement(x, y, EL_EMPTY);
1267 }
1268
1269 void DrawLevelField(int x, int y)
1270 {
1271   if (IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
1272     DrawScreenField(SCREENX(x), SCREENY(y));
1273   else if (IS_MOVING(x, y))
1274   {
1275     int newx,newy;
1276
1277     Moving2Blocked(x, y, &newx, &newy);
1278     if (IN_SCR_FIELD(SCREENX(newx), SCREENY(newy)))
1279       DrawScreenField(SCREENX(newx), SCREENY(newy));
1280   }
1281   else if (IS_BLOCKED(x, y))
1282   {
1283     int oldx, oldy;
1284
1285     Blocked2Moving(x, y, &oldx, &oldy);
1286     if (IN_SCR_FIELD(SCREENX(oldx), SCREENY(oldy)))
1287       DrawScreenField(SCREENX(oldx), SCREENY(oldy));
1288   }
1289 }
1290
1291 void DrawMiniElement(int x, int y, int element)
1292 {
1293   int graphic;
1294
1295   graphic = el2edimg(element);
1296   DrawMiniGraphic(x, y, graphic);
1297 }
1298
1299 void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y)
1300 {
1301   int x = sx + scroll_x, y = sy + scroll_y;
1302
1303   if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
1304     DrawMiniElement(sx, sy, EL_EMPTY);
1305   else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
1306     DrawMiniElement(sx, sy, Feld[x][y]);
1307   else
1308     DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
1309 }
1310
1311 void DrawEnvelopeBackground(int envelope_nr, int startx, int starty,
1312                             int x, int y, int xsize, int ysize, int font_nr)
1313 {
1314   int font_width  = getFontWidth(font_nr);
1315   int font_height = getFontHeight(font_nr);
1316   int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1317   Bitmap *src_bitmap;
1318   int src_x, src_y;
1319   int dst_x = SX + startx + x * font_width;
1320   int dst_y = SY + starty + y * font_height;
1321   int width  = graphic_info[graphic].width;
1322   int height = graphic_info[graphic].height;
1323   int inner_width  = MAX(width  - 2 * font_width,  font_width);
1324   int inner_height = MAX(height - 2 * font_height, font_height);
1325   int inner_sx = (width >= 3 * font_width ? font_width : 0);
1326   int inner_sy = (height >= 3 * font_height ? font_height : 0);
1327   boolean draw_masked = graphic_info[graphic].draw_masked;
1328
1329   getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y);
1330
1331   if (src_bitmap == NULL || width < font_width || height < font_height)
1332   {
1333     ClearRectangle(drawto, dst_x, dst_y, font_width, font_height);
1334     return;
1335   }
1336
1337   src_x += (x == 0 ? 0 : x == xsize - 1 ? width  - font_width  :
1338             inner_sx + (x - 1) * font_width  % inner_width);
1339   src_y += (y == 0 ? 0 : y == ysize - 1 ? height - font_height :
1340             inner_sy + (y - 1) * font_height % inner_height);
1341
1342   if (draw_masked)
1343   {
1344     SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
1345                   dst_x - src_x, dst_y - src_y);
1346     BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1347                      dst_x, dst_y);
1348   }
1349   else
1350     BlitBitmap(src_bitmap, drawto, src_x, src_y, font_width, font_height,
1351                dst_x, dst_y);
1352 }
1353
1354 void AnimateEnvelope(int envelope_nr, int anim_mode, int action)
1355 {
1356   int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1357 #if 1
1358   Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1359   int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1360 #else
1361   boolean draw_masked = graphic_info[graphic].draw_masked;
1362   int mask_mode = (draw_masked ? BLIT_MASKED : BLIT_ON_BACKGROUND);
1363 #endif
1364   boolean ffwd_delay = (tape.playing && tape.fast_forward);
1365   boolean no_delay = (tape.warp_forward);
1366   unsigned long anim_delay = 0;
1367   int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay);
1368   int anim_delay_value = (no_delay ? 0 : frame_delay_value);
1369   int font_nr = FONT_ENVELOPE_1 + envelope_nr;
1370   int font_width = getFontWidth(font_nr);
1371   int font_height = getFontHeight(font_nr);
1372   int max_xsize = level.envelope_xsize[envelope_nr];
1373   int max_ysize = level.envelope_ysize[envelope_nr];
1374   int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0);
1375   int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0);
1376   int xend = max_xsize;
1377   int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0);
1378   int xstep = (xstart < xend ? 1 : 0);
1379   int ystep = (ystart < yend || xstep == 0 ? 1 : 0);
1380   int x, y;
1381
1382   for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep)
1383   {
1384     int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2;
1385     int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2;
1386     int sx = (SXSIZE - xsize * font_width)  / 2;
1387     int sy = (SYSIZE - ysize * font_height) / 2;
1388     int xx, yy;
1389
1390     SetDrawtoField(DRAW_BUFFERED);
1391
1392     BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY);
1393
1394     SetDrawtoField(DRAW_BACKBUFFER);
1395
1396     for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++)
1397       DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr);
1398
1399     DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height,
1400                        level.envelope_text[envelope_nr], font_nr, max_xsize,
1401                        xsize - 2, ysize - 2, mask_mode);
1402
1403     redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER;
1404     BackToFront();
1405
1406     WaitUntilDelayReached(&anim_delay, anim_delay_value / 2);
1407   }
1408 }
1409
1410 void ShowEnvelope(int envelope_nr)
1411 {
1412   int element = EL_ENVELOPE_1 + envelope_nr;
1413   int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr;
1414   int sound_opening = element_info[element].sound[ACTION_OPENING];
1415   int sound_closing = element_info[element].sound[ACTION_CLOSING];
1416   boolean ffwd_delay = (tape.playing && tape.fast_forward);
1417   boolean no_delay = (tape.warp_forward);
1418   int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1);
1419   int wait_delay_value = (no_delay ? 0 : normal_delay_value);
1420   int anim_mode = graphic_info[graphic].anim_mode;
1421   int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
1422                         anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
1423
1424   game.envelope_active = TRUE;  /* needed for RedrawPlayfield() events */
1425
1426   PlaySoundStereo(sound_opening, SOUND_MIDDLE);
1427
1428   if (anim_mode == ANIM_DEFAULT)
1429     AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING);
1430
1431   AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING);
1432
1433   if (tape.playing)
1434     Delay(wait_delay_value);
1435   else
1436     WaitForEventToContinue();
1437
1438   PlaySoundStereo(sound_closing, SOUND_MIDDLE);
1439
1440   if (anim_mode != ANIM_NONE)
1441     AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING);
1442
1443   if (anim_mode == ANIM_DEFAULT)
1444     AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_CLOSING);
1445
1446   game.envelope_active = FALSE;
1447
1448   SetDrawtoField(DRAW_BUFFERED);
1449
1450   redraw_mask |= REDRAW_FIELD;
1451   BackToFront();
1452 }
1453
1454 void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y)
1455 {
1456   Bitmap *src_bitmap = graphic_info[graphic].bitmap;
1457   int mini_startx = src_bitmap->width * 3 / 4;
1458   int mini_starty = src_bitmap->height * 2 / 3;
1459   int src_x = mini_startx + graphic_info[graphic].src_x / 8;
1460   int src_y = mini_starty + graphic_info[graphic].src_y / 8;
1461
1462   *bitmap = src_bitmap;
1463   *x = src_x;
1464   *y = src_y;
1465 }
1466
1467 void DrawMicroElement(int xpos, int ypos, int element)
1468 {
1469   Bitmap *src_bitmap;
1470   int src_x, src_y;
1471   int graphic = el2preimg(element);
1472
1473   getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y);
1474   BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY,
1475              xpos, ypos);
1476 }
1477
1478 void DrawLevel()
1479 {
1480   int x,y;
1481
1482   SetDrawBackgroundMask(REDRAW_NONE);
1483   ClearWindow();
1484
1485   for (x = BX1; x <= BX2; x++)
1486     for (y = BY1; y <= BY2; y++)
1487       DrawScreenField(x, y);
1488
1489   redraw_mask |= REDRAW_FIELD;
1490 }
1491
1492 void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y)
1493 {
1494   int x,y;
1495
1496   for (x = 0; x < size_x; x++)
1497     for (y = 0; y < size_y; y++)
1498       DrawMiniElementOrWall(x, y, scroll_x, scroll_y);
1499
1500   redraw_mask |= REDRAW_FIELD;
1501 }
1502
1503 static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y)
1504 {
1505   int x, y;
1506
1507   DrawBackground(xpos, ypos, MICROLEV_XSIZE, MICROLEV_YSIZE);
1508
1509   if (lev_fieldx < STD_LEV_FIELDX)
1510     xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX;
1511   if (lev_fieldy < STD_LEV_FIELDY)
1512     ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY;
1513
1514   xpos += MICRO_TILEX;
1515   ypos += MICRO_TILEY;
1516
1517   for (x = -1; x <= STD_LEV_FIELDX; x++)
1518   {
1519     for (y = -1; y <= STD_LEV_FIELDY; y++)
1520     {
1521       int lx = from_x + x, ly = from_y + y;
1522
1523       if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy)
1524         DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1525                          level.field[lx][ly]);
1526       else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1
1527                && BorderElement != EL_EMPTY)
1528         DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY,
1529                          getBorderElement(lx, ly));
1530     }
1531   }
1532
1533   redraw_mask |= REDRAW_MICROLEVEL;
1534 }
1535
1536 #define MICROLABEL_EMPTY                0
1537 #define MICROLABEL_LEVEL_NAME           1
1538 #define MICROLABEL_CREATED_BY           2
1539 #define MICROLABEL_LEVEL_AUTHOR         3
1540 #define MICROLABEL_IMPORTED_FROM        4
1541 #define MICROLABEL_LEVEL_IMPORT_INFO    5
1542
1543 static void DrawMicroLevelLabelExt(int mode)
1544 {
1545   char label_text[MAX_OUTPUT_LINESIZE + 1];
1546   int max_len_label_text;
1547   int font_nr = FONT_TEXT_2;
1548
1549   if (mode == MICROLABEL_CREATED_BY || mode == MICROLABEL_IMPORTED_FROM)
1550     font_nr = FONT_TEXT_3;
1551
1552   max_len_label_text = SXSIZE / getFontWidth(font_nr);
1553
1554   DrawBackground(SX, MICROLABEL_YPOS, SXSIZE, getFontHeight(font_nr));
1555
1556   strncpy(label_text, (mode == MICROLABEL_LEVEL_NAME ? level.name :
1557                        mode == MICROLABEL_CREATED_BY ? "created by" :
1558                        mode == MICROLABEL_LEVEL_AUTHOR ? level.author :
1559                        mode == MICROLABEL_IMPORTED_FROM ? "imported from" :
1560                        mode == MICROLABEL_LEVEL_IMPORT_INFO ?
1561                        leveldir_current->imported_from : ""),
1562           max_len_label_text);
1563   label_text[max_len_label_text] = '\0';
1564
1565   if (strlen(label_text) > 0)
1566   {
1567     int lxpos = SX + (SXSIZE - getTextWidth(label_text, font_nr)) / 2;
1568     int lypos = MICROLABEL_YPOS;
1569
1570     DrawText(lxpos, lypos, label_text, font_nr);
1571   }
1572
1573   redraw_mask |= REDRAW_MICROLEVEL;
1574 }
1575
1576 void DrawMicroLevel(int xpos, int ypos, boolean restart)
1577 {
1578   static unsigned long scroll_delay = 0;
1579   static unsigned long label_delay = 0;
1580   static int from_x, from_y, scroll_direction;
1581   static int label_state, label_counter;
1582   int last_game_status = game_status;   /* save current game status */
1583
1584   /* force PREVIEW font on preview level */
1585   game_status = GAME_MODE_PSEUDO_PREVIEW;
1586
1587   if (restart)
1588   {
1589     from_x = from_y = 0;
1590     scroll_direction = MV_RIGHT;
1591     label_state = 1;
1592     label_counter = 0;
1593
1594     DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1595     DrawMicroLevelLabelExt(label_state);
1596
1597     /* initialize delay counters */
1598     DelayReached(&scroll_delay, 0);
1599     DelayReached(&label_delay, 0);
1600
1601     if (leveldir_current->name)
1602     {
1603       int text_width = getTextWidth(leveldir_current->name, FONT_TEXT_1);
1604       int lxpos = SX + (SXSIZE - text_width) / 2;
1605       int lypos = SY + 352;
1606
1607       DrawText(lxpos, lypos, leveldir_current->name, FONT_TEXT_1);
1608     }
1609
1610     game_status = last_game_status;     /* restore current game status */
1611
1612     return;
1613   }
1614
1615   /* scroll micro level, if needed */
1616   if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) &&
1617       DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY))
1618   {
1619     switch (scroll_direction)
1620     {
1621       case MV_LEFT:
1622         if (from_x > 0)
1623           from_x--;
1624         else
1625           scroll_direction = MV_UP;
1626         break;
1627
1628       case MV_RIGHT:
1629         if (from_x < lev_fieldx - STD_LEV_FIELDX)
1630           from_x++;
1631         else
1632           scroll_direction = MV_DOWN;
1633         break;
1634
1635       case MV_UP:
1636         if (from_y > 0)
1637           from_y--;
1638         else
1639           scroll_direction = MV_RIGHT;
1640         break;
1641
1642       case MV_DOWN:
1643         if (from_y < lev_fieldy - STD_LEV_FIELDY)
1644           from_y++;
1645         else
1646           scroll_direction = MV_LEFT;
1647         break;
1648
1649       default:
1650         break;
1651     }
1652
1653     DrawMicroLevelExt(xpos, ypos, from_x, from_y);
1654   }
1655
1656   /* redraw micro level label, if needed */
1657   if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 &&
1658       strcmp(level.author, ANONYMOUS_NAME) != 0 &&
1659       strcmp(level.author, leveldir_current->name) != 0 &&
1660       DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY))
1661   {
1662     int max_label_counter = 23;
1663
1664     if (leveldir_current->imported_from != NULL)
1665       max_label_counter += 14;
1666
1667     label_counter = (label_counter + 1) % max_label_counter;
1668     label_state = (label_counter >= 0 && label_counter <= 7 ?
1669                    MICROLABEL_LEVEL_NAME :
1670                    label_counter >= 9 && label_counter <= 12 ?
1671                    MICROLABEL_CREATED_BY :
1672                    label_counter >= 14 && label_counter <= 21 ?
1673                    MICROLABEL_LEVEL_AUTHOR :
1674                    label_counter >= 23 && label_counter <= 26 ?
1675                    MICROLABEL_IMPORTED_FROM :
1676                    label_counter >= 28 && label_counter <= 35 ?
1677                    MICROLABEL_LEVEL_IMPORT_INFO : MICROLABEL_EMPTY);
1678     DrawMicroLevelLabelExt(label_state);
1679   }
1680
1681   game_status = last_game_status;       /* restore current game status */
1682 }
1683
1684 inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
1685                                     int graphic, int sync_frame, int mask_mode)
1686 {
1687   int frame = getGraphicAnimationFrame(graphic, sync_frame);
1688
1689   if (mask_mode == USE_MASKING)
1690     DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
1691   else
1692     DrawGraphicExt(dst_bitmap, x, y, graphic, frame);
1693 }
1694
1695 inline void DrawGraphicAnimation(int x, int y, int graphic)
1696 {
1697   int lx = LEVELX(x), ly = LEVELY(y);
1698
1699   if (!IN_SCR_FIELD(x, y))
1700     return;
1701
1702   DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
1703                           graphic, GfxFrame[lx][ly], NO_MASKING);
1704   MarkTileDirty(x, y);
1705 }
1706
1707 void DrawLevelGraphicAnimation(int x, int y, int graphic)
1708 {
1709   DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1710 }
1711
1712 void DrawLevelElementAnimation(int x, int y, int element)
1713 {
1714 #if 1
1715   int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1716
1717   DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic);
1718 #else
1719   DrawGraphicAnimation(SCREENX(x), SCREENY(y), el2img(element));
1720 #endif
1721 }
1722
1723 inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic)
1724 {
1725   int sx = SCREENX(x), sy = SCREENY(y);
1726
1727   if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1728     return;
1729
1730   if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1731     return;
1732
1733   DrawGraphicAnimation(sx, sy, graphic);
1734
1735   if (GFX_CRUMBLED(Feld[x][y]))
1736     DrawLevelFieldCrumbledSand(x, y);
1737 }
1738
1739 void DrawLevelElementAnimationIfNeeded(int x, int y, int element)
1740 {
1741   int sx = SCREENX(x), sy = SCREENY(y);
1742   int graphic;
1743
1744   if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
1745     return;
1746
1747   graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]);
1748
1749   if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
1750     return;
1751
1752   DrawGraphicAnimation(sx, sy, graphic);
1753
1754   if (GFX_CRUMBLED(element))
1755     DrawLevelFieldCrumbledSand(x, y);
1756 }
1757
1758 static int getPlayerGraphic(struct PlayerInfo *player, int move_dir)
1759 {
1760   if (player->use_murphy_graphic)
1761   {
1762     /* this works only because currently only one player can be "murphy" ... */
1763     static int last_horizontal_dir = MV_LEFT;
1764     int graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
1765
1766     if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1767       last_horizontal_dir = move_dir;
1768
1769     if (graphic == IMG_SP_MURPHY)       /* undefined => use special graphic */
1770     {
1771       int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
1772
1773       graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
1774     }
1775
1776     return graphic;
1777   }
1778   else
1779     return el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
1780 }
1781
1782 static boolean equalGraphics(int graphic1, int graphic2)
1783 {
1784   struct GraphicInfo *g1 = &graphic_info[graphic1];
1785   struct GraphicInfo *g2 = &graphic_info[graphic2];
1786
1787   return (g1->bitmap      == g2->bitmap &&
1788           g1->src_x       == g2->src_x &&
1789           g1->src_y       == g2->src_y &&
1790           g1->anim_frames == g2->anim_frames &&
1791           g1->anim_delay  == g2->anim_delay &&
1792           g1->anim_mode   == g2->anim_mode);
1793 }
1794
1795 void DrawAllPlayers()
1796 {
1797   int i;
1798
1799   for (i = 0; i < MAX_PLAYERS; i++)
1800     if (stored_player[i].active)
1801       DrawPlayer(&stored_player[i]);
1802 }
1803
1804 void DrawPlayerField(int x, int y)
1805 {
1806   if (!IS_PLAYER(x, y))
1807     return;
1808
1809   DrawPlayer(PLAYERINFO(x, y));
1810 }
1811
1812 void DrawPlayer(struct PlayerInfo *player)
1813 {
1814   int jx = player->jx;
1815   int jy = player->jy;
1816   int move_dir = player->MovDir;
1817 #if 0
1818   int last_jx = player->last_jx;
1819   int last_jy = player->last_jy;
1820   int next_jx = jx + (jx - last_jx);
1821   int next_jy = jy + (jy - last_jy);
1822   boolean player_is_moving = (last_jx != jx || last_jy != jy ? TRUE : FALSE);
1823 #else
1824   int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? +1 : 0);
1825   int dy = (move_dir == MV_UP   ? -1 : move_dir == MV_DOWN  ? +1 : 0);
1826   int last_jx = (player->is_moving ? jx - dx : jx);
1827   int last_jy = (player->is_moving ? jy - dy : jy);
1828   int next_jx = jx + dx;
1829   int next_jy = jy + dy;
1830   boolean player_is_moving = (player->MovPos ? TRUE : FALSE);
1831 #endif
1832   int sx = SCREENX(jx), sy = SCREENY(jy);
1833   int sxx = 0, syy = 0;
1834   int element = Feld[jx][jy], last_element = Feld[last_jx][last_jy];
1835   int graphic;
1836   int action = ACTION_DEFAULT;
1837   int last_player_graphic = getPlayerGraphic(player, move_dir);
1838   int last_player_frame = player->Frame;
1839   int frame = 0;
1840
1841   if (!player->active || !IN_SCR_FIELD(SCREENX(last_jx), SCREENY(last_jy)))
1842     return;
1843
1844 #if DEBUG
1845   if (!IN_LEV_FIELD(jx, jy))
1846   {
1847     printf("DrawPlayerField(): x = %d, y = %d\n",jx,jy);
1848     printf("DrawPlayerField(): sx = %d, sy = %d\n",sx,sy);
1849     printf("DrawPlayerField(): This should never happen!\n");
1850     return;
1851   }
1852 #endif
1853
1854   if (element == EL_EXPLOSION)
1855     return;
1856
1857   action = (player->is_pushing    ? ACTION_PUSHING         :
1858             player->is_digging    ? ACTION_DIGGING         :
1859             player->is_collecting ? ACTION_COLLECTING      :
1860             player->is_moving     ? ACTION_MOVING          :
1861             player->is_snapping   ? ACTION_SNAPPING        :
1862             player->is_dropping   ? ACTION_DROPPING        :
1863             player->is_waiting    ? player->action_waiting : ACTION_DEFAULT);
1864
1865   InitPlayerGfxAnimation(player, action, move_dir);
1866
1867   /* ----------------------------------------------------------------------- */
1868   /* draw things in the field the player is leaving, if needed               */
1869   /* ----------------------------------------------------------------------- */
1870
1871 #if 1
1872   if (player->is_moving)
1873 #else
1874   if (player_is_moving)
1875 #endif
1876   {
1877     if (Back[last_jx][last_jy] && IS_DRAWABLE(last_element))
1878     {
1879       DrawLevelElement(last_jx, last_jy, Back[last_jx][last_jy]);
1880
1881       if (last_element == EL_DYNAMITE_ACTIVE ||
1882           last_element == EL_SP_DISK_RED_ACTIVE)
1883         DrawDynamite(last_jx, last_jy);
1884       else
1885         DrawLevelFieldThruMask(last_jx, last_jy);
1886     }
1887     else if (last_element == EL_DYNAMITE_ACTIVE ||
1888              last_element == EL_SP_DISK_RED_ACTIVE)
1889       DrawDynamite(last_jx, last_jy);
1890     else
1891       DrawLevelField(last_jx, last_jy);
1892
1893     if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy)))
1894       DrawLevelElement(next_jx, next_jy, EL_EMPTY);
1895   }
1896
1897   if (!IN_SCR_FIELD(sx, sy))
1898     return;
1899
1900   if (setup.direct_draw)
1901     SetDrawtoField(DRAW_BUFFERED);
1902
1903   /* ----------------------------------------------------------------------- */
1904   /* draw things behind the player, if needed                                */
1905   /* ----------------------------------------------------------------------- */
1906
1907   if (Back[jx][jy])
1908     DrawLevelElement(jx, jy, Back[jx][jy]);
1909   else if (IS_ACTIVE_BOMB(element))
1910     DrawLevelElement(jx, jy, EL_EMPTY);
1911   else
1912   {
1913     if (player_is_moving && GfxElement[jx][jy] != EL_UNDEFINED)
1914     {
1915       if (GFX_CRUMBLED(GfxElement[jx][jy]))
1916         DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame);
1917       else
1918       {
1919         int old_element = GfxElement[jx][jy];
1920         int old_graphic = el_act_dir2img(old_element, action, move_dir);
1921         int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame);
1922
1923         DrawGraphic(sx, sy, old_graphic, frame);
1924       }
1925     }
1926     else
1927     {
1928       GfxElement[jx][jy] = EL_UNDEFINED;
1929
1930       DrawLevelField(jx, jy);
1931     }
1932   }
1933
1934   /* ----------------------------------------------------------------------- */
1935   /* draw player himself                                                     */
1936   /* ----------------------------------------------------------------------- */
1937
1938 #if 1
1939
1940   graphic = getPlayerGraphic(player, move_dir);
1941
1942   /* in the case of changed player action or direction, prevent the current
1943      animation frame from being restarted for identical animations */
1944   if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
1945     player->Frame = last_player_frame;
1946
1947 #else
1948
1949   if (player->use_murphy_graphic)
1950   {
1951     static int last_horizontal_dir = MV_LEFT;
1952
1953     if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1954       last_horizontal_dir = move_dir;
1955
1956     graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, move_dir);
1957
1958     if (graphic == IMG_SP_MURPHY)       /* undefined => use special graphic */
1959     {
1960       int direction = (player->is_snapping ? move_dir : last_horizontal_dir);
1961
1962       graphic = el_act_dir2img(EL_SP_MURPHY, player->GfxAction, direction);
1963     }
1964   }
1965   else
1966     graphic = el_act_dir2img(player->element_nr, player->GfxAction, move_dir);
1967
1968 #endif
1969
1970   frame = getGraphicAnimationFrame(graphic, player->Frame);
1971
1972   if (player->GfxPos)
1973   {
1974     if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1975       sxx = player->GfxPos;
1976     else
1977       syy = player->GfxPos;
1978   }
1979
1980   if (!setup.soft_scrolling && ScreenMovPos)
1981     sxx = syy = 0;
1982
1983   DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1984
1985   if (SHIELD_ON(player))
1986   {
1987     int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
1988                    IMG_SHIELD_NORMAL_ACTIVE);
1989     int frame = getGraphicAnimationFrame(graphic, -1);
1990
1991     DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1992   }
1993
1994   /* ----------------------------------------------------------------------- */
1995   /* draw things the player is pushing, if needed                            */
1996   /* ----------------------------------------------------------------------- */
1997
1998 #if 0
1999   printf("::: %d, %d [%d, %d] [%d]\n",
2000          player->is_pushing, player_is_moving, player->GfxAction,
2001          player->is_moving, player_is_moving);
2002 #endif
2003
2004 #if 1
2005   if (player->is_pushing && player->is_moving)
2006 #else
2007   if (player->is_pushing && player_is_moving)
2008 #endif
2009   {
2010 #if 1
2011     int px = SCREENX(jx), py = SCREENY(jy);
2012     int pxx = (TILEX - ABS(sxx)) * dx;
2013     int pyy = (TILEY - ABS(syy)) * dy;
2014 #else
2015     int px = SCREENX(next_jx), py = SCREENY(next_jy);
2016     int pxx = sxx;
2017     int pyy = syy;
2018 #endif
2019
2020 #if 1
2021     int graphic;
2022     int frame;
2023
2024     if (!IS_MOVING(jx, jy))             /* push movement already finished */
2025       element = Feld[next_jx][next_jy];
2026
2027     graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
2028     frame = getGraphicAnimationFrame(graphic, player->StepFrame);
2029
2030     if (Back[next_jx][next_jy])
2031       DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
2032
2033     /* masked drawing is needed for EMC style (double) movement graphics */
2034     DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
2035
2036 #else
2037     if (Back[next_jx][next_jy])
2038       DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
2039
2040     if ((pxx || pyy) && element == EL_SOKOBAN_OBJECT)
2041       DrawGraphicShiftedThruMask(px, py, pxx, pyy, IMG_SOKOBAN_OBJECT, 0,
2042                                  NO_CUTTING);
2043     else
2044     {
2045       int element = MovingOrBlocked2Element(next_jx, next_jy);
2046       int graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
2047 #if 1
2048       int frame = getGraphicAnimationFrame(graphic, player->StepFrame);
2049 #else
2050       int frame = getGraphicAnimationFrame(graphic, player->Frame);
2051 #endif
2052
2053 #if 1
2054       /* masked drawing is needed for EMC style (double) movement graphics */
2055       DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame,
2056                                  NO_CUTTING);
2057 #else
2058       DrawGraphicShifted(px, py, pxx, pyy, graphic, frame,
2059                          NO_CUTTING, NO_MASKING);
2060 #endif
2061     }
2062 #endif
2063   }
2064
2065   /* ----------------------------------------------------------------------- */
2066   /* draw things in front of player (active dynamite or dynabombs)           */
2067   /* ----------------------------------------------------------------------- */
2068
2069   if (IS_ACTIVE_BOMB(element))
2070   {
2071     graphic = el2img(element);
2072     frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
2073
2074     if (game.emulation == EMU_SUPAPLEX)
2075       DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
2076     else
2077       DrawGraphicThruMask(sx, sy, graphic, frame);
2078   }
2079
2080   if (player_is_moving && last_element == EL_EXPLOSION)
2081   {
2082     int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
2083     int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
2084     int phase = ExplodePhase[last_jx][last_jy] - 1;
2085     int frame = getGraphicAnimationFrame(graphic, phase - delay);
2086
2087     if (phase >= delay)
2088       DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
2089   }
2090
2091   /* ----------------------------------------------------------------------- */
2092   /* draw elements the player is just walking/passing through/under          */
2093   /* ----------------------------------------------------------------------- */
2094
2095   if (player_is_moving)
2096   {
2097     /* handle the field the player is leaving ... */
2098     if (IS_ACCESSIBLE_INSIDE(last_element))
2099       DrawLevelField(last_jx, last_jy);
2100     else if (IS_ACCESSIBLE_UNDER(last_element))
2101       DrawLevelFieldThruMask(last_jx, last_jy);
2102   }
2103
2104 #if 1
2105   /* do not redraw accessible elements if the player is just pushing them */
2106   if (!player_is_moving || !player->is_pushing)
2107   {
2108     /* ... and the field the player is entering */
2109     if (IS_ACCESSIBLE_INSIDE(element))
2110       DrawLevelField(jx, jy);
2111     else if (IS_ACCESSIBLE_UNDER(element))
2112       DrawLevelFieldThruMask(jx, jy);
2113   }
2114
2115 #else
2116
2117 #if 0
2118   /* !!! I have forgotton what this should be good for !!! */
2119   /* !!! causes player being visible when pushing from within tubes !!! */
2120   if (!player->is_pushing)
2121 #endif
2122   {
2123     /* ... and the field the player is entering */
2124     if (IS_ACCESSIBLE_INSIDE(element))
2125       DrawLevelField(jx, jy);
2126     else if (IS_ACCESSIBLE_UNDER(element))
2127       DrawLevelFieldThruMask(jx, jy);
2128   }
2129 #endif
2130
2131   if (setup.direct_draw)
2132   {
2133     int dst_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
2134     int dst_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
2135     int x_size = TILEX * (1 + ABS(jx - last_jx));
2136     int y_size = TILEY * (1 + ABS(jy - last_jy));
2137
2138     BlitBitmap(drawto_field, window,
2139                dst_x, dst_y, x_size, y_size, dst_x, dst_y);
2140     SetDrawtoField(DRAW_DIRECT);
2141   }
2142
2143   MarkTileDirty(sx, sy);
2144 }
2145
2146 /* ------------------------------------------------------------------------- */
2147
2148 void WaitForEventToContinue()
2149 {
2150   boolean still_wait = TRUE;
2151
2152   /* simulate releasing mouse button over last gadget, if still pressed */
2153   if (button_status)
2154     HandleGadgets(-1, -1, 0);
2155
2156   button_status = MB_RELEASED;
2157
2158   while (still_wait)
2159   {
2160     if (PendingEvent())
2161     {
2162       Event event;
2163
2164       NextEvent(&event);
2165
2166       switch (event.type)
2167       {
2168         case EVENT_BUTTONPRESS:
2169         case EVENT_KEYPRESS:
2170           still_wait = FALSE;
2171           break;
2172
2173         case EVENT_KEYRELEASE:
2174           ClearPlayerAction();
2175           break;
2176
2177         default:
2178           HandleOtherEvents(&event);
2179           break;
2180       }
2181     }
2182     else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2183     {
2184       still_wait = FALSE;
2185     }
2186
2187     DoAnimation();
2188
2189     /* don't eat all CPU time */
2190     Delay(10);
2191   }
2192 }
2193
2194 #define MAX_REQUEST_LINES               13
2195 #define MAX_REQUEST_LINE_FONT1_LEN      7
2196 #define MAX_REQUEST_LINE_FONT2_LEN      10
2197
2198 boolean Request(char *text, unsigned int req_state)
2199 {
2200   int mx, my, ty, result = -1;
2201   unsigned int old_door_state;
2202   int last_game_status = game_status;   /* save current game status */
2203   int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
2204   int font_nr = FONT_TEXT_2;
2205   int max_word_len = 0;
2206   char *text_ptr;
2207
2208   for (text_ptr = text; *text_ptr; text_ptr++)
2209   {
2210     max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2211
2212     if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
2213     {
2214       max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
2215       font_nr = FONT_LEVEL_NUMBER;
2216
2217       break;
2218     }
2219   }
2220
2221 #if 1
2222   /* disable deactivated drawing when quick-loading level tape recording */
2223   if (tape.playing && tape.deactivate_display)
2224     TapeDeactivateDisplayOff(TRUE);
2225 #endif
2226
2227 #if 1
2228   SetMouseCursor(CURSOR_DEFAULT);
2229 #endif
2230
2231 #if defined(NETWORK_AVALIABLE)
2232   /* pause network game while waiting for request to answer */
2233   if (options.network &&
2234       game_status == GAME_MODE_PLAYING &&
2235       req_state & REQUEST_WAIT_FOR_INPUT)
2236     SendToServer_PausePlaying();
2237 #endif
2238
2239   old_door_state = GetDoorState();
2240
2241   /* simulate releasing mouse button over last gadget, if still pressed */
2242   if (button_status)
2243     HandleGadgets(-1, -1, 0);
2244
2245   UnmapAllGadgets();
2246
2247   if (old_door_state & DOOR_OPEN_1)
2248   {
2249     CloseDoor(DOOR_CLOSE_1);
2250
2251     /* save old door content */
2252     BlitBitmap(bitmap_db_door, bitmap_db_door,
2253                DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2254                DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2255   }
2256
2257   SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2258
2259   /* clear door drawing field */
2260   DrawBackground(DX, DY, DXSIZE, DYSIZE);
2261
2262   /* force DOOR font on preview level */
2263   game_status = GAME_MODE_PSEUDO_DOOR;
2264
2265   /* write text for request */
2266   for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2267   {
2268     char text_line[max_request_line_len + 1];
2269     int tx, tl, tc = 0;
2270
2271     if (!*text)
2272       break;
2273
2274     for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
2275     {
2276       tc = *(text + tx);
2277       if (!tc || tc == ' ')
2278         break;
2279     }
2280
2281     if (!tl)
2282     { 
2283       text++; 
2284       ty--; 
2285       continue; 
2286     }
2287
2288     strncpy(text_line, text, tl);
2289     text_line[tl] = 0;
2290
2291     DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
2292              DY + 8 + ty * (getFontHeight(font_nr) + 2),
2293              text_line, font_nr);
2294
2295     text += tl + (tc == ' ' ? 1 : 0);
2296   }
2297
2298   game_status = last_game_status;       /* restore current game status */
2299
2300   if (req_state & REQ_ASK)
2301   {
2302     MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2303     MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2304   }
2305   else if (req_state & REQ_CONFIRM)
2306   {
2307     MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2308   }
2309   else if (req_state & REQ_PLAYER)
2310   {
2311     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2312     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2313     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2314     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2315   }
2316
2317   /* copy request gadgets to door backbuffer */
2318   BlitBitmap(drawto, bitmap_db_door,
2319              DX, DY, DXSIZE, DYSIZE,
2320              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2321
2322   OpenDoor(DOOR_OPEN_1);
2323
2324 #if 0
2325   ClearEventQueue();
2326 #endif
2327
2328   if (!(req_state & REQUEST_WAIT_FOR_INPUT))
2329   {
2330     SetDrawBackgroundMask(REDRAW_FIELD);
2331
2332     return FALSE;
2333   }
2334
2335   if (game_status != GAME_MODE_MAIN)
2336     InitAnimation();
2337
2338   button_status = MB_RELEASED;
2339
2340   request_gadget_id = -1;
2341
2342   SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2343
2344 #if 0
2345   SetMouseCursor(CURSOR_DEFAULT);
2346 #endif
2347
2348   while (result < 0)
2349   {
2350     if (PendingEvent())
2351     {
2352       Event event;
2353
2354       NextEvent(&event);
2355
2356       switch(event.type)
2357       {
2358         case EVENT_BUTTONPRESS:
2359         case EVENT_BUTTONRELEASE:
2360         case EVENT_MOTIONNOTIFY:
2361         {
2362           if (event.type == EVENT_MOTIONNOTIFY)
2363           {
2364             if (!PointerInWindow(window))
2365               continue; /* window and pointer are on different screens */
2366
2367             if (!button_status)
2368               continue;
2369
2370             motion_status = TRUE;
2371             mx = ((MotionEvent *) &event)->x;
2372             my = ((MotionEvent *) &event)->y;
2373           }
2374           else
2375           {
2376             motion_status = FALSE;
2377             mx = ((ButtonEvent *) &event)->x;
2378             my = ((ButtonEvent *) &event)->y;
2379             if (event.type == EVENT_BUTTONPRESS)
2380               button_status = ((ButtonEvent *) &event)->button;
2381             else
2382               button_status = MB_RELEASED;
2383           }
2384
2385           /* this sets 'request_gadget_id' */
2386           HandleGadgets(mx, my, button_status);
2387
2388           switch(request_gadget_id)
2389           {
2390             case TOOL_CTRL_ID_YES:
2391               result = TRUE;
2392               break;
2393             case TOOL_CTRL_ID_NO:
2394               result = FALSE;
2395               break;
2396             case TOOL_CTRL_ID_CONFIRM:
2397               result = TRUE | FALSE;
2398               break;
2399
2400             case TOOL_CTRL_ID_PLAYER_1:
2401               result = 1;
2402               break;
2403             case TOOL_CTRL_ID_PLAYER_2:
2404               result = 2;
2405               break;
2406             case TOOL_CTRL_ID_PLAYER_3:
2407               result = 3;
2408               break;
2409             case TOOL_CTRL_ID_PLAYER_4:
2410               result = 4;
2411               break;
2412
2413             default:
2414               break;
2415           }
2416
2417           break;
2418         }
2419
2420         case EVENT_KEYPRESS:
2421           switch(GetEventKey((KeyEvent *)&event, TRUE))
2422           {
2423             case KSYM_Return:
2424               result = 1;
2425               break;
2426
2427             case KSYM_Escape:
2428               result = 0;
2429               break;
2430
2431             default:
2432               break;
2433           }
2434           if (req_state & REQ_PLAYER)
2435             result = 0;
2436           break;
2437
2438         case EVENT_KEYRELEASE:
2439           ClearPlayerAction();
2440           break;
2441
2442         default:
2443           HandleOtherEvents(&event);
2444           break;
2445       }
2446     }
2447     else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2448     {
2449       int joy = AnyJoystick();
2450
2451       if (joy & JOY_BUTTON_1)
2452         result = 1;
2453       else if (joy & JOY_BUTTON_2)
2454         result = 0;
2455     }
2456
2457     DoAnimation();
2458
2459     /* don't eat all CPU time */
2460     Delay(10);
2461   }
2462
2463   if (game_status != GAME_MODE_MAIN)
2464     StopAnimation();
2465
2466   UnmapToolButtons();
2467
2468   if (!(req_state & REQ_STAY_OPEN))
2469   {
2470     CloseDoor(DOOR_CLOSE_1);
2471
2472     if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
2473         (req_state & REQ_REOPEN))
2474       OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2475   }
2476
2477   RemapAllGadgets();
2478
2479   SetDrawBackgroundMask(REDRAW_FIELD);
2480
2481 #if defined(NETWORK_AVALIABLE)
2482   /* continue network game after request */
2483   if (options.network &&
2484       game_status == GAME_MODE_PLAYING &&
2485       req_state & REQUEST_WAIT_FOR_INPUT)
2486     SendToServer_ContinuePlaying();
2487 #endif
2488
2489 #if 1
2490   /* restore deactivated drawing when quick-loading level tape recording */
2491   if (tape.playing && tape.deactivate_display)
2492     TapeDeactivateDisplayOn();
2493 #endif
2494
2495   return result;
2496 }
2497
2498 unsigned int OpenDoor(unsigned int door_state)
2499 {
2500   if (door_state & DOOR_COPY_BACK)
2501   {
2502     if (door_state & DOOR_OPEN_1)
2503       BlitBitmap(bitmap_db_door, bitmap_db_door,
2504                  DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2505                  DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2506
2507     if (door_state & DOOR_OPEN_2)
2508       BlitBitmap(bitmap_db_door, bitmap_db_door,
2509                  DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
2510                  DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2511
2512     door_state &= ~DOOR_COPY_BACK;
2513   }
2514
2515   return MoveDoor(door_state);
2516 }
2517
2518 unsigned int CloseDoor(unsigned int door_state)
2519 {
2520   unsigned int old_door_state = GetDoorState();
2521
2522   if (!(door_state & DOOR_NO_COPY_BACK))
2523   {
2524     if (old_door_state & DOOR_OPEN_1)
2525       BlitBitmap(backbuffer, bitmap_db_door,
2526                  DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2527
2528     if (old_door_state & DOOR_OPEN_2)
2529       BlitBitmap(backbuffer, bitmap_db_door,
2530                  VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2531
2532     door_state &= ~DOOR_NO_COPY_BACK;
2533   }
2534
2535   return MoveDoor(door_state);
2536 }
2537
2538 unsigned int GetDoorState()
2539 {
2540   return MoveDoor(DOOR_GET_STATE);
2541 }
2542
2543 unsigned int SetDoorState(unsigned int door_state)
2544 {
2545   return MoveDoor(door_state | DOOR_SET_STATE);
2546 }
2547
2548 unsigned int MoveDoor(unsigned int door_state)
2549 {
2550   static int door1 = DOOR_OPEN_1;
2551   static int door2 = DOOR_CLOSE_2;
2552   unsigned long door_delay = 0;
2553   unsigned long door_delay_value;
2554   int stepsize = 1;
2555
2556   if (door_state == DOOR_GET_STATE)
2557     return(door1 | door2);
2558
2559   if (door_state & DOOR_SET_STATE)
2560   {
2561     if (door_state & DOOR_ACTION_1)
2562       door1 = door_state & DOOR_ACTION_1;
2563     if (door_state & DOOR_ACTION_2)
2564       door2 = door_state & DOOR_ACTION_2;
2565
2566     return(door1 | door2);
2567   }
2568
2569   if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2570     door_state &= ~DOOR_OPEN_1;
2571   else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2572     door_state &= ~DOOR_CLOSE_1;
2573   if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2574     door_state &= ~DOOR_OPEN_2;
2575   else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2576     door_state &= ~DOOR_CLOSE_2;
2577
2578   door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2579                       door_2.step_delay);
2580
2581   if (setup.quick_doors)
2582   {
2583     stepsize = 20;              /* must be choosen to always draw last frame */
2584     door_delay_value = 0;
2585
2586 #if 0
2587     StopSound(SND_DOOR_OPENING);
2588     StopSound(SND_DOOR_CLOSING);
2589 #endif
2590   }
2591
2592   if (global.autoplay_leveldir)
2593   {
2594     door_state |= DOOR_NO_DELAY;
2595     door_state &= ~DOOR_CLOSE_ALL;
2596   }
2597
2598   if (door_state & DOOR_ACTION)
2599   {
2600     boolean door_1_done = !(door_state & DOOR_ACTION_1);
2601     boolean door_2_done = !(door_state & DOOR_ACTION_2);
2602     int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2603     int end = (door_state & DOOR_ACTION_1 &&
2604                door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2605     int x;
2606
2607     if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2608     {
2609       /* opening door sound has priority over simultaneously closing door */
2610       if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2611         PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2612       else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2613         PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2614     }
2615
2616     for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2617     {
2618       Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2619       GC gc = bitmap->stored_clip_gc;
2620
2621       if (door_state & DOOR_ACTION_1)
2622       {
2623         int a = MIN(x * door_1.step_offset, end);
2624         int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2625
2626         if (x <= a)
2627         {
2628           BlitBitmap(bitmap_db_door, drawto,
2629                      DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2630                      DXSIZE, DYSIZE - i / 2, DX, DY);
2631
2632           ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2633         }
2634
2635         if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2636         {
2637           int src1_x = DXSIZE,          src1_y = DOOR_GFX_PAGEY1;
2638           int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2639           int src2_x = DXSIZE - i,      src2_y = DOOR_GFX_PAGEY1;
2640           int dst2_x = DX,              dst2_y = DY;
2641           int width = i, height = DYSIZE;
2642
2643           SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2644           BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2645                            dst1_x, dst1_y);
2646
2647           SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2648           BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2649                            dst2_x, dst2_y);
2650         }
2651         else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2652         {
2653           int src1_x = DXSIZE,          src1_y = DOOR_GFX_PAGEY1;
2654           int dst1_x = DX,              dst1_y = DY + DYSIZE - i;
2655           int src2_x = 0,               src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2656           int dst2_x = DX,              dst2_y = DY;
2657           int width = DXSIZE, height = i;
2658
2659           SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2660           BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2661                            dst1_x, dst1_y);
2662
2663           SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2664           BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2665                            dst2_x, dst2_y);
2666         }
2667         else if (x <= DXSIZE)   /* ANIM_DEFAULT */
2668         {
2669           int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2670
2671           SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2672           BlitBitmapMasked(bitmap, drawto,
2673                            DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2674                            DX + DXSIZE - i, DY + j);
2675           BlitBitmapMasked(bitmap, drawto,
2676                            DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2677                            DX + DXSIZE - i, DY + 140 + j);
2678           SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2679                         DY - (DOOR_GFX_PAGEY1 + j));
2680           BlitBitmapMasked(bitmap, drawto,
2681                            DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2682                            DX, DY);
2683           BlitBitmapMasked(bitmap, drawto,
2684                            DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2685                            DX, DY + 140 - j);
2686
2687           BlitBitmapMasked(bitmap, drawto,
2688                            DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2689                            DX, DY + 77 - j);
2690           BlitBitmapMasked(bitmap, drawto,
2691                            DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2692                            DX, DY + 203 - j);
2693           SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2694           BlitBitmapMasked(bitmap, drawto,
2695                            DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2696                            DX + DXSIZE - i, DY + 77 + j);
2697           BlitBitmapMasked(bitmap, drawto,
2698                            DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2699                            DX + DXSIZE - i, DY + 203 + j);
2700         }
2701
2702         redraw_mask |= REDRAW_DOOR_1;
2703         door_1_done = (a == end);
2704       }
2705
2706       if (door_state & DOOR_ACTION_2)
2707       {
2708         int a = MIN(x * door_2.step_offset, VXSIZE);
2709         int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2710
2711         if (x <= VYSIZE)
2712         {
2713           BlitBitmap(bitmap_db_door, drawto,
2714                      DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2715                      VXSIZE, VYSIZE - i / 2, VX, VY);
2716
2717           ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2718         }
2719
2720         if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2721         {
2722           int src1_x = VXSIZE,          src1_y = DOOR_GFX_PAGEY2;
2723           int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2724           int src2_x = VXSIZE - i,      src2_y = DOOR_GFX_PAGEY2;
2725           int dst2_x = VX,              dst2_y = VY;
2726           int width = i, height = VYSIZE;
2727
2728           SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2729           BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2730                            dst1_x, dst1_y);
2731
2732           SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2733           BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2734                            dst2_x, dst2_y);
2735         }
2736         else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2737         {
2738           int src1_x = VXSIZE,          src1_y = DOOR_GFX_PAGEY2;
2739           int dst1_x = VX,              dst1_y = VY + VYSIZE - i;
2740           int src2_x = 0,               src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2741           int dst2_x = VX,              dst2_y = VY;
2742           int width = VXSIZE, height = i;
2743
2744           SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2745           BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2746                            dst1_x, dst1_y);
2747
2748           SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2749           BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2750                            dst2_x, dst2_y);
2751         }
2752         else if (x <= VXSIZE)   /* ANIM_DEFAULT */
2753         {
2754           int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2755
2756           SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2757           BlitBitmapMasked(bitmap, drawto,
2758                            VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2759                            VX + VXSIZE - i, VY + j);
2760           SetClipOrigin(bitmap, gc,
2761                         VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2762           BlitBitmapMasked(bitmap, drawto,
2763                            VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2764                            VX, VY);
2765
2766           BlitBitmapMasked(bitmap, drawto,
2767                            VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2768                            i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2769           SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2770           BlitBitmapMasked(bitmap, drawto,
2771                            VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2772                            i, VYSIZE / 2 - j,
2773                            VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2774         }
2775
2776         redraw_mask |= REDRAW_DOOR_2;
2777         door_2_done = (a == VXSIZE);
2778       }
2779
2780       BackToFront();
2781
2782       if (game_status == GAME_MODE_MAIN)
2783         DoAnimation();
2784
2785       if (!(door_state & DOOR_NO_DELAY))
2786         WaitUntilDelayReached(&door_delay, door_delay_value);
2787     }
2788   }
2789
2790 #if 0
2791   if (setup.quick_doors)
2792   {
2793     StopSound(SND_DOOR_OPENING);
2794     StopSound(SND_DOOR_CLOSING);
2795   }
2796 #endif
2797
2798   if (door_state & DOOR_ACTION_1)
2799     door1 = door_state & DOOR_ACTION_1;
2800   if (door_state & DOOR_ACTION_2)
2801     door2 = door_state & DOOR_ACTION_2;
2802
2803   return (door1 | door2);
2804 }
2805
2806 void DrawSpecialEditorDoor()
2807 {
2808   /* draw bigger toolbox window */
2809   BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2810              DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2811              EX - 4, EY - 12);
2812   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2813              EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2814              EX - 4, EY - 4);
2815
2816   redraw_mask |= REDRAW_ALL;
2817 }
2818
2819 void UndrawSpecialEditorDoor()
2820 {
2821   /* draw normal tape recorder window */
2822   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2823              EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2824              EX - 4, EY - 12);
2825
2826   redraw_mask |= REDRAW_ALL;
2827 }
2828
2829
2830 /* ---------- new tool button stuff ---------------------------------------- */
2831
2832 /* graphic position values for tool buttons */
2833 #define TOOL_BUTTON_YES_XPOS            2
2834 #define TOOL_BUTTON_YES_YPOS            250
2835 #define TOOL_BUTTON_YES_GFX_YPOS        0
2836 #define TOOL_BUTTON_YES_XSIZE           46
2837 #define TOOL_BUTTON_YES_YSIZE           28
2838 #define TOOL_BUTTON_NO_XPOS             52
2839 #define TOOL_BUTTON_NO_YPOS             TOOL_BUTTON_YES_YPOS
2840 #define TOOL_BUTTON_NO_GFX_YPOS         TOOL_BUTTON_YES_GFX_YPOS
2841 #define TOOL_BUTTON_NO_XSIZE            TOOL_BUTTON_YES_XSIZE
2842 #define TOOL_BUTTON_NO_YSIZE            TOOL_BUTTON_YES_YSIZE
2843 #define TOOL_BUTTON_CONFIRM_XPOS        TOOL_BUTTON_YES_XPOS
2844 #define TOOL_BUTTON_CONFIRM_YPOS        TOOL_BUTTON_YES_YPOS
2845 #define TOOL_BUTTON_CONFIRM_GFX_YPOS    30
2846 #define TOOL_BUTTON_CONFIRM_XSIZE       96
2847 #define TOOL_BUTTON_CONFIRM_YSIZE       TOOL_BUTTON_YES_YSIZE
2848 #define TOOL_BUTTON_PLAYER_XSIZE        30
2849 #define TOOL_BUTTON_PLAYER_YSIZE        30
2850 #define TOOL_BUTTON_PLAYER_GFX_XPOS     5
2851 #define TOOL_BUTTON_PLAYER_GFX_YPOS     185
2852 #define TOOL_BUTTON_PLAYER_XPOS         (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2853 #define TOOL_BUTTON_PLAYER_YPOS         (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2854 #define TOOL_BUTTON_PLAYER1_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2855                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2856 #define TOOL_BUTTON_PLAYER2_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2857                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2858 #define TOOL_BUTTON_PLAYER3_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2859                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2860 #define TOOL_BUTTON_PLAYER4_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2861                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2862 #define TOOL_BUTTON_PLAYER1_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2863                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2864 #define TOOL_BUTTON_PLAYER2_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2865                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2866 #define TOOL_BUTTON_PLAYER3_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2867                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2868 #define TOOL_BUTTON_PLAYER4_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2869                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2870
2871 static struct
2872 {
2873   int xpos, ypos;
2874   int x, y;
2875   int width, height;
2876   int gadget_id;
2877   char *infotext;
2878 } toolbutton_info[NUM_TOOL_BUTTONS] =
2879 {
2880   {
2881     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_GFX_YPOS,
2882     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_YPOS,
2883     TOOL_BUTTON_YES_XSIZE,      TOOL_BUTTON_YES_YSIZE,
2884     TOOL_CTRL_ID_YES,
2885     "yes"
2886   },
2887   {
2888     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_GFX_YPOS,
2889     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_YPOS,
2890     TOOL_BUTTON_NO_XSIZE,       TOOL_BUTTON_NO_YSIZE,
2891     TOOL_CTRL_ID_NO,
2892     "no"
2893   },
2894   {
2895     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_GFX_YPOS,
2896     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_YPOS,
2897     TOOL_BUTTON_CONFIRM_XSIZE,  TOOL_BUTTON_CONFIRM_YSIZE,
2898     TOOL_CTRL_ID_CONFIRM,
2899     "confirm"
2900   },
2901   {
2902     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2903     TOOL_BUTTON_PLAYER1_XPOS,   TOOL_BUTTON_PLAYER1_YPOS,
2904     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2905     TOOL_CTRL_ID_PLAYER_1,
2906     "player 1"
2907   },
2908   {
2909     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2910     TOOL_BUTTON_PLAYER2_XPOS,   TOOL_BUTTON_PLAYER2_YPOS,
2911     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2912     TOOL_CTRL_ID_PLAYER_2,
2913     "player 2"
2914   },
2915   {
2916     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2917     TOOL_BUTTON_PLAYER3_XPOS,   TOOL_BUTTON_PLAYER3_YPOS,
2918     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2919     TOOL_CTRL_ID_PLAYER_3,
2920     "player 3"
2921   },
2922   {
2923     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2924     TOOL_BUTTON_PLAYER4_XPOS,   TOOL_BUTTON_PLAYER4_YPOS,
2925     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2926     TOOL_CTRL_ID_PLAYER_4,
2927     "player 4"
2928   }
2929 };
2930
2931 void CreateToolButtons()
2932 {
2933   int i;
2934
2935   for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2936   {
2937     Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2938     Bitmap *deco_bitmap = None;
2939     int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2940     struct GadgetInfo *gi;
2941     unsigned long event_mask;
2942     int gd_xoffset, gd_yoffset;
2943     int gd_x1, gd_x2, gd_y;
2944     int id = i;
2945
2946     event_mask = GD_EVENT_RELEASED;
2947
2948     gd_xoffset = toolbutton_info[i].xpos;
2949     gd_yoffset = toolbutton_info[i].ypos;
2950     gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2951     gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2952     gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2953
2954     if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2955     {
2956       int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2957
2958       getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2959                            &deco_bitmap, &deco_x, &deco_y);
2960       deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2961       deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2962     }
2963
2964     gi = CreateGadget(GDI_CUSTOM_ID, id,
2965                       GDI_INFO_TEXT, toolbutton_info[i].infotext,
2966                       GDI_X, DX + toolbutton_info[i].x,
2967                       GDI_Y, DY + toolbutton_info[i].y,
2968                       GDI_WIDTH, toolbutton_info[i].width,
2969                       GDI_HEIGHT, toolbutton_info[i].height,
2970                       GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2971                       GDI_STATE, GD_BUTTON_UNPRESSED,
2972                       GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2973                       GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2974                       GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2975                       GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2976                       GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2977                       GDI_DECORATION_SHIFTING, 1, 1,
2978                       GDI_EVENT_MASK, event_mask,
2979                       GDI_CALLBACK_ACTION, HandleToolButtons,
2980                       GDI_END);
2981
2982     if (gi == NULL)
2983       Error(ERR_EXIT, "cannot create gadget");
2984
2985     tool_gadget[id] = gi;
2986   }
2987 }
2988
2989 void FreeToolButtons()
2990 {
2991   int i;
2992
2993   for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2994     FreeGadget(tool_gadget[i]);
2995 }
2996
2997 static void UnmapToolButtons()
2998 {
2999   int i;
3000
3001   for (i = 0; i < NUM_TOOL_BUTTONS; i++)
3002     UnmapGadget(tool_gadget[i]);
3003 }
3004
3005 static void HandleToolButtons(struct GadgetInfo *gi)
3006 {
3007   request_gadget_id = gi->custom_id;
3008 }
3009
3010 #if 1
3011
3012 static struct
3013 {
3014   int element_em;
3015   boolean is_rnd_to_em_mapping;         /* unique mapping EM <-> RND */
3016   boolean is_backside;                  /* backside of moving element */
3017
3018   int element_rnd;
3019   int action;
3020   int direction;
3021 }
3022 mapping_EM_to_RND_list[] =
3023 {
3024   {
3025     Xblank,                             TRUE,   FALSE,
3026     EL_EMPTY,                           -1, -1
3027   },
3028   {
3029     Yacid_splash_eB,                    FALSE,  TRUE,
3030     EL_ACID_SPLASH_RIGHT,               -1, -1
3031   },
3032   {
3033     Yacid_splash_wB,                    FALSE,  TRUE,
3034     EL_ACID_SPLASH_LEFT,                -1, -1
3035   },
3036
3037 #ifdef EM_ENGINE_BAD_ROLL
3038   {
3039     Xstone_force_e,                     FALSE,  FALSE,
3040     EL_ROCK,                            -1, MV_BIT_RIGHT
3041   },
3042   {
3043     Xstone_force_w,                     FALSE,  FALSE,
3044     EL_ROCK,                            -1, MV_BIT_LEFT
3045   },
3046   {
3047     Xnut_force_e,                       FALSE,  FALSE,
3048     EL_NUT,                             -1, MV_BIT_RIGHT
3049   },
3050   {
3051     Xnut_force_w,                       FALSE,  FALSE,
3052     EL_NUT,                             -1, MV_BIT_LEFT
3053   },
3054   {
3055     Xspring_force_e,                    FALSE,  FALSE,
3056     EL_SPRING,                          -1, MV_BIT_RIGHT
3057   },
3058   {
3059     Xspring_force_w,                    FALSE,  FALSE,
3060     EL_SPRING,                          -1, MV_BIT_LEFT
3061   },
3062   {
3063     Xemerald_force_e,                   FALSE,  FALSE,
3064     EL_EMERALD,                         -1, MV_BIT_RIGHT
3065   },
3066   {
3067     Xemerald_force_w,                   FALSE,  FALSE,
3068     EL_EMERALD,                         -1, MV_BIT_LEFT
3069   },
3070   {
3071     Xdiamond_force_e,                   FALSE,  FALSE,
3072     EL_DIAMOND,                         -1, MV_BIT_RIGHT
3073   },
3074   {
3075     Xdiamond_force_w,                   FALSE,  FALSE,
3076     EL_DIAMOND,                         -1, MV_BIT_LEFT
3077   },
3078   {
3079     Xbomb_force_e,                      FALSE,  FALSE,
3080     EL_BOMB,                            -1, MV_BIT_RIGHT
3081   },
3082   {
3083     Xbomb_force_w,                      FALSE,  FALSE,
3084     EL_BOMB,                            -1, MV_BIT_LEFT
3085   },
3086 #endif  /* EM_ENGINE_BAD_ROLL */
3087
3088   {
3089     Xstone,                             TRUE,   FALSE,
3090     EL_ROCK,                            -1, -1
3091   },
3092   {
3093     Xstone_pause,                       FALSE,  FALSE,
3094     EL_ROCK,                            -1, -1
3095   },
3096   {
3097     Xstone_fall,                        FALSE,  FALSE,
3098     EL_ROCK,                            -1, -1
3099   },
3100   {
3101     Ystone_s,                           FALSE,  FALSE,
3102     EL_ROCK,                            ACTION_FALLING, -1
3103   },
3104   {
3105     Ystone_sB,                          FALSE,  TRUE,
3106     EL_ROCK,                            ACTION_FALLING, -1
3107   },
3108   {
3109     Ystone_e,                           FALSE,  FALSE,
3110     EL_ROCK,                            ACTION_MOVING, MV_BIT_RIGHT
3111   },
3112   {
3113     Ystone_eB,                          FALSE,  TRUE,
3114     EL_ROCK,                            ACTION_MOVING, MV_BIT_RIGHT
3115   },
3116   {
3117     Ystone_w,                           FALSE,  FALSE,
3118     EL_ROCK,                            ACTION_MOVING, MV_BIT_LEFT
3119   },
3120   {
3121     Ystone_wB,                          FALSE,  TRUE,
3122     EL_ROCK,                            ACTION_MOVING, MV_BIT_LEFT
3123   },
3124   {
3125     Xnut,                               TRUE,   FALSE,
3126     EL_NUT,                             -1, -1
3127   },
3128   {
3129     Xnut_pause,                         FALSE,  FALSE,
3130     EL_NUT,                             -1, -1
3131   },
3132   {
3133     Xnut_fall,                          FALSE,  FALSE,
3134     EL_NUT,                             -1, -1
3135   },
3136   {
3137     Ynut_s,                             FALSE,  FALSE,
3138     EL_NUT,                             ACTION_FALLING, -1
3139   },
3140   {
3141     Ynut_sB,                            FALSE,  TRUE,
3142     EL_NUT,                             ACTION_FALLING, -1
3143   },
3144   {
3145     Ynut_e,                             FALSE,  FALSE,
3146     EL_NUT,                             ACTION_MOVING, MV_BIT_RIGHT
3147   },
3148   {
3149     Ynut_eB,                            FALSE,  TRUE,
3150     EL_NUT,                             ACTION_MOVING, MV_BIT_RIGHT
3151   },
3152   {
3153     Ynut_w,                             FALSE,  FALSE,
3154     EL_NUT,                             ACTION_MOVING, MV_BIT_LEFT
3155   },
3156   {
3157     Ynut_wB,                            FALSE,  TRUE,
3158     EL_NUT,                             ACTION_MOVING, MV_BIT_LEFT
3159   },
3160   {
3161     Xbug_n,                             TRUE,   FALSE,
3162     EL_BUG_UP,                          -1, -1
3163   },
3164   {
3165     Xbug_e,                             TRUE,   FALSE,
3166     EL_BUG_RIGHT,                       -1, -1
3167   },
3168   {
3169     Xbug_s,                             TRUE,   FALSE,
3170     EL_BUG_DOWN,                        -1, -1
3171   },
3172   {
3173     Xbug_w,                             TRUE,   FALSE,
3174     EL_BUG_LEFT,                        -1, -1
3175   },
3176   {
3177     Xbug_gon,                           FALSE,  FALSE,
3178     EL_BUG_UP,                          -1, -1
3179   },
3180   {
3181     Xbug_goe,                           FALSE,  FALSE,
3182     EL_BUG_RIGHT,                       -1, -1
3183   },
3184   {
3185     Xbug_gos,                           FALSE,  FALSE,
3186     EL_BUG_DOWN,                        -1, -1
3187   },
3188   {
3189     Xbug_gow,                           FALSE,  FALSE,
3190     EL_BUG_LEFT,                        -1, -1
3191   },
3192   {
3193     Ybug_n,                             FALSE,  FALSE,
3194     EL_BUG,                             ACTION_MOVING, MV_BIT_UP
3195   },
3196   {
3197     Ybug_nB,                            FALSE,  TRUE,
3198     EL_BUG,                             ACTION_MOVING, MV_BIT_UP
3199   },
3200   {
3201     Ybug_e,                             FALSE,  FALSE,
3202     EL_BUG,                             ACTION_MOVING, MV_BIT_RIGHT
3203   },
3204   {
3205     Ybug_eB,                            FALSE,  TRUE,
3206     EL_BUG,                             ACTION_MOVING, MV_BIT_RIGHT
3207   },
3208   {
3209     Ybug_s,                             FALSE,  FALSE,
3210     EL_BUG,                             ACTION_MOVING, MV_BIT_DOWN
3211   },
3212   {
3213     Ybug_sB,                            FALSE,  TRUE,
3214     EL_BUG,                             ACTION_MOVING, MV_BIT_DOWN
3215   },
3216   {
3217     Ybug_w,                             FALSE,  FALSE,
3218     EL_BUG,                             ACTION_MOVING, MV_BIT_LEFT
3219   },
3220   {
3221     Ybug_wB,                            FALSE,  TRUE,
3222     EL_BUG,                             ACTION_MOVING, MV_BIT_LEFT
3223   },
3224   {
3225     Ybug_w_n,                           FALSE,  FALSE,
3226     EL_BUG,                             ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3227   },
3228   {
3229     Ybug_n_e,                           FALSE,  FALSE,
3230     EL_BUG,                             ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3231   },
3232   {
3233     Ybug_e_s,                           FALSE,  FALSE,
3234     EL_BUG,                             ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3235   },
3236   {
3237     Ybug_s_w,                           FALSE,  FALSE,
3238     EL_BUG,                             ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3239   },
3240   {
3241     Ybug_e_n,                           FALSE,  FALSE,
3242     EL_BUG,                             ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3243   },
3244   {
3245     Ybug_s_e,                           FALSE,  FALSE,
3246     EL_BUG,                             ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3247   },
3248   {
3249     Ybug_w_s,                           FALSE,  FALSE,
3250     EL_BUG,                             ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3251   },
3252   {
3253     Ybug_n_w,                           FALSE,  FALSE,
3254     EL_BUG,                             ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3255   },
3256   {
3257     Ybug_stone,                         FALSE,  FALSE,
3258     EL_BUG,                             ACTION_SMASHED_BY_ROCK, -1
3259   },
3260   {
3261     Ybug_spring,                        FALSE,  FALSE,
3262     EL_BUG,                             ACTION_SMASHED_BY_SPRING, -1
3263   },
3264   {
3265     Xtank_n,                            TRUE,   FALSE,
3266     EL_SPACESHIP_UP,                    -1, -1
3267   },
3268   {
3269     Xtank_e,                            TRUE,   FALSE,
3270     EL_SPACESHIP_RIGHT,                 -1, -1
3271   },
3272   {
3273     Xtank_s,                            TRUE,   FALSE,
3274     EL_SPACESHIP_DOWN,                  -1, -1
3275   },
3276   {
3277     Xtank_w,                            TRUE,   FALSE,
3278     EL_SPACESHIP_LEFT,                  -1, -1
3279   },
3280   {
3281     Xtank_gon,                          FALSE,  FALSE,
3282     EL_SPACESHIP_UP,                    -1, -1
3283   },
3284   {
3285     Xtank_goe,                          FALSE,  FALSE,
3286     EL_SPACESHIP_RIGHT,                 -1, -1
3287   },
3288   {
3289     Xtank_gos,                          FALSE,  FALSE,
3290     EL_SPACESHIP_DOWN,                  -1, -1
3291   },
3292   {
3293     Xtank_gow,                          FALSE,  FALSE,
3294     EL_SPACESHIP_LEFT,                  -1, -1
3295   },
3296   {
3297     Ytank_n,                            FALSE,  FALSE,
3298     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_UP
3299   },
3300   {
3301     Ytank_nB,                           FALSE,  TRUE,
3302     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_UP
3303   },
3304   {
3305     Ytank_e,                            FALSE,  FALSE,
3306     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_RIGHT
3307   },
3308   {
3309     Ytank_eB,                           FALSE,  TRUE,
3310     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_RIGHT
3311   },
3312   {
3313     Ytank_s,                            FALSE,  FALSE,
3314     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_DOWN
3315   },
3316   {
3317     Ytank_sB,                           FALSE,  TRUE,
3318     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_DOWN
3319   },
3320   {
3321     Ytank_w,                            FALSE,  FALSE,
3322     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_LEFT
3323   },
3324   {
3325     Ytank_wB,                           FALSE,  TRUE,
3326     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_LEFT
3327   },
3328   {
3329     Ytank_w_n,                          FALSE,  FALSE,
3330     EL_SPACESHIP,                       ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3331   },
3332   {
3333     Ytank_n_e,                          FALSE,  FALSE,
3334     EL_SPACESHIP,                       ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3335   },
3336   {
3337     Ytank_e_s,                          FALSE,  FALSE,
3338     EL_SPACESHIP,                       ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3339   },
3340   {
3341     Ytank_s_w,                          FALSE,  FALSE,
3342     EL_SPACESHIP,                       ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3343   },
3344   {
3345     Ytank_e_n,                          FALSE,  FALSE,
3346     EL_SPACESHIP,                       ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3347   },
3348   {
3349     Ytank_s_e,                          FALSE,  FALSE,
3350     EL_SPACESHIP,                       ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3351   },
3352   {
3353     Ytank_w_s,                          FALSE,  FALSE,
3354     EL_SPACESHIP,                       ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3355   },
3356   {
3357     Ytank_n_w,                          FALSE,  FALSE,
3358     EL_SPACESHIP,                       ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3359   },
3360   {
3361     Ytank_stone,                        FALSE,  FALSE,
3362     EL_SPACESHIP,                       ACTION_SMASHED_BY_ROCK, -1
3363   },
3364   {
3365     Ytank_spring,                       FALSE,  FALSE,
3366     EL_SPACESHIP,                       ACTION_SMASHED_BY_SPRING, -1
3367   },
3368   {
3369     Xandroid,                           TRUE,   FALSE,
3370     EL_EMC_ANDROID,                     ACTION_ACTIVE, -1
3371   },
3372   {
3373     Xandroid_1_n,                       FALSE,  FALSE,
3374     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_UP
3375   },
3376   {
3377     Xandroid_2_n,                       FALSE,  FALSE,
3378     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_UP
3379   },
3380   {
3381     Xandroid_1_e,                       FALSE,  FALSE,
3382     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_RIGHT
3383   },
3384   {
3385     Xandroid_2_e,                       FALSE,  FALSE,
3386     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_RIGHT
3387   },
3388   {
3389     Xandroid_1_w,                       FALSE,  FALSE,
3390     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_LEFT
3391   },
3392   {
3393     Xandroid_2_w,                       FALSE,  FALSE,
3394     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_LEFT
3395   },
3396   {
3397     Xandroid_1_s,                       FALSE,  FALSE,
3398     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_DOWN
3399   },
3400   {
3401     Xandroid_2_s,                       FALSE,  FALSE,
3402     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_DOWN
3403   },
3404   {
3405     Yandroid_n,                         FALSE,  FALSE,
3406     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_UP
3407   },
3408   {
3409     Yandroid_nB,                        FALSE,  TRUE,
3410     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_UP
3411   },
3412   {
3413     Yandroid_ne,                        FALSE,  FALSE,
3414     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3415   },
3416   {
3417     Yandroid_neB,                       FALSE,  TRUE,
3418     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3419   },
3420   {
3421     Yandroid_e,                         FALSE,  FALSE,
3422     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_RIGHT
3423   },
3424   {
3425     Yandroid_eB,                        FALSE,  TRUE,
3426     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_RIGHT
3427   },
3428   {
3429     Yandroid_se,                        FALSE,  FALSE,
3430     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3431   },
3432   {
3433     Yandroid_seB,                       FALSE,  TRUE,
3434     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3435   },
3436   {
3437     Yandroid_s,                         FALSE,  FALSE,
3438     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_DOWN
3439   },
3440   {
3441     Yandroid_sB,                        FALSE,  TRUE,
3442     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_DOWN
3443   },
3444   {
3445     Yandroid_sw,                        FALSE,  FALSE,
3446     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3447   },
3448   {
3449     Yandroid_swB,                       FALSE,  TRUE,
3450     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3451   },
3452   {
3453     Yandroid_w,                         FALSE,  FALSE,
3454     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_LEFT
3455   },
3456   {
3457     Yandroid_wB,                        FALSE,  TRUE,
3458     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_LEFT
3459   },
3460   {
3461     Yandroid_nw,                        FALSE,  FALSE,
3462     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3463   },
3464   {
3465     Yandroid_nwB,                       FALSE,  TRUE,
3466     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3467   },
3468   {
3469     Xspring,                            TRUE,   FALSE,
3470     EL_SPRING,                          -1, -1
3471   },
3472   {
3473     Xspring_pause,                      FALSE,  FALSE,
3474     EL_SPRING,                          -1, -1
3475   },
3476   {
3477     Xspring_e,                          FALSE,  FALSE,
3478     EL_SPRING,                          -1, -1
3479   },
3480   {
3481     Xspring_w,                          FALSE,  FALSE,
3482     EL_SPRING,                          -1, -1
3483   },
3484   {
3485     Xspring_fall,                       FALSE,  FALSE,
3486     EL_SPRING,                          -1, -1
3487   },
3488   {
3489     Yspring_s,                          FALSE,  FALSE,
3490     EL_SPRING,                          ACTION_FALLING, -1
3491   },
3492   {
3493     Yspring_sB,                         FALSE,  TRUE,
3494     EL_SPRING,                          ACTION_FALLING, -1
3495   },
3496   {
3497     Yspring_e,                          FALSE,  FALSE,
3498     EL_SPRING,                          ACTION_MOVING, MV_BIT_RIGHT
3499   },
3500   {
3501     Yspring_eB,                         FALSE,  TRUE,
3502     EL_SPRING,                          ACTION_MOVING, MV_BIT_RIGHT
3503   },
3504   {
3505     Yspring_w,                          FALSE,  FALSE,
3506     EL_SPRING,                          ACTION_MOVING, MV_BIT_LEFT
3507   },
3508   {
3509     Yspring_wB,                         FALSE,  TRUE,
3510     EL_SPRING,                          ACTION_MOVING, MV_BIT_LEFT
3511   },
3512   {
3513     Yspring_kill_e,                     FALSE,  FALSE,
3514     EL_ROBOT,                           ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3515   },
3516   {
3517     Yspring_kill_eB,                    FALSE,  TRUE,
3518     EL_ROBOT,                           ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3519   },
3520   {
3521     Yspring_kill_w,                     FALSE,  FALSE,
3522     EL_ROBOT,                           ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3523   },
3524   {
3525     Yspring_kill_wB,                    FALSE,  TRUE,
3526     EL_ROBOT,                           ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3527   },
3528   {
3529     Xeater_n,                           TRUE,   FALSE,
3530     EL_YAMYAM,                          -1, -1
3531   },
3532   {
3533     Xeater_e,                           FALSE,  FALSE,
3534     EL_YAMYAM,                          -1, -1
3535   },
3536   {
3537     Xeater_w,                           FALSE,  FALSE,
3538     EL_YAMYAM,                          -1, -1
3539   },
3540   {
3541     Xeater_s,                           FALSE,  FALSE,
3542     EL_YAMYAM,                          -1, -1
3543   },
3544   {
3545     Yeater_n,                           FALSE,  FALSE,
3546     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_UP
3547   },
3548   {
3549     Yeater_nB,                          FALSE,  TRUE,
3550     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_UP
3551   },
3552   {
3553     Yeater_e,                           FALSE,  FALSE,
3554     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_RIGHT
3555   },
3556   {
3557     Yeater_eB,                          FALSE,  TRUE,
3558     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_RIGHT
3559   },
3560   {
3561     Yeater_s,                           FALSE,  FALSE,
3562     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_DOWN
3563   },
3564   {
3565     Yeater_sB,                          FALSE,  TRUE,
3566     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_DOWN
3567   },
3568   {
3569     Yeater_w,                           FALSE,  FALSE,
3570     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_LEFT
3571   },
3572   {
3573     Yeater_wB,                          FALSE,  TRUE,
3574     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_LEFT
3575   },
3576   {
3577     Yeater_stone,                       FALSE,  FALSE,
3578     EL_YAMYAM,                          ACTION_SMASHED_BY_ROCK, -1
3579   },
3580   {
3581     Yeater_spring,                      FALSE,  FALSE,
3582     EL_YAMYAM,                          ACTION_SMASHED_BY_SPRING, -1
3583   },
3584   {
3585     Xalien,                             TRUE,   FALSE,
3586     EL_ROBOT,                           -1, -1
3587   },
3588   {
3589     Xalien_pause,                       FALSE,  FALSE,
3590     EL_ROBOT,                           -1, -1
3591   },
3592   {
3593     Yalien_n,                           FALSE,  FALSE,
3594     EL_ROBOT,                           ACTION_MOVING, MV_BIT_UP
3595   },
3596   {
3597     Yalien_nB,                          FALSE,  TRUE,
3598     EL_ROBOT,                           ACTION_MOVING, MV_BIT_UP
3599   },
3600   {
3601     Yalien_e,                           FALSE,  FALSE,
3602     EL_ROBOT,                           ACTION_MOVING, MV_BIT_RIGHT
3603   },
3604   {
3605     Yalien_eB,                          FALSE,  TRUE,
3606     EL_ROBOT,                           ACTION_MOVING, MV_BIT_RIGHT
3607   },
3608   {
3609     Yalien_s,                           FALSE,  FALSE,
3610     EL_ROBOT,                           ACTION_MOVING, MV_BIT_DOWN
3611   },
3612   {
3613     Yalien_sB,                          FALSE,  TRUE,
3614     EL_ROBOT,                           ACTION_MOVING, MV_BIT_DOWN
3615   },
3616   {
3617     Yalien_w,                           FALSE,  FALSE,
3618     EL_ROBOT,                           ACTION_MOVING, MV_BIT_LEFT
3619   },
3620   {
3621     Yalien_wB,                          FALSE,  TRUE,
3622     EL_ROBOT,                           ACTION_MOVING, MV_BIT_LEFT
3623   },
3624   {
3625     Yalien_stone,                       FALSE,  FALSE,
3626     EL_ROBOT,                           ACTION_SMASHED_BY_ROCK, -1
3627   },
3628   {
3629     Yalien_spring,                      FALSE,  FALSE,
3630     EL_ROBOT,                           ACTION_SMASHED_BY_SPRING, -1
3631   },
3632   {
3633     Xemerald,                           TRUE,   FALSE,
3634     EL_EMERALD,                         -1, -1
3635   },
3636   {
3637     Xemerald_pause,                     FALSE,  FALSE,
3638     EL_EMERALD,                         -1, -1
3639   },
3640   {
3641     Xemerald_fall,                      FALSE,  FALSE,
3642     EL_EMERALD,                         -1, -1
3643   },
3644   {
3645     Xemerald_shine,                     FALSE,  FALSE,
3646     EL_EMERALD,                         ACTION_TWINKLING, -1
3647   },
3648   {
3649     Yemerald_s,                         FALSE,  FALSE,
3650     EL_EMERALD,                         ACTION_FALLING, -1
3651   },
3652   {
3653     Yemerald_sB,                        FALSE,  TRUE,
3654     EL_EMERALD,                         ACTION_FALLING, -1
3655   },
3656   {
3657     Yemerald_e,                         FALSE,  FALSE,
3658     EL_EMERALD,                         ACTION_MOVING, MV_BIT_RIGHT
3659   },
3660   {
3661     Yemerald_eB,                        FALSE,  TRUE,
3662     EL_EMERALD,                         ACTION_MOVING, MV_BIT_RIGHT
3663   },
3664   {
3665     Yemerald_w,                         FALSE,  FALSE,
3666     EL_EMERALD,                         ACTION_MOVING, MV_BIT_LEFT
3667   },
3668   {
3669     Yemerald_wB,                        FALSE,  TRUE,
3670     EL_EMERALD,                         ACTION_MOVING, MV_BIT_LEFT
3671   },
3672   {
3673     Yemerald_eat,                       FALSE,  FALSE,
3674     EL_EMERALD,                         ACTION_COLLECTING, -1
3675   },
3676   {
3677     Yemerald_stone,                     FALSE,  FALSE,
3678     EL_NUT,                             ACTION_BREAKING, -1
3679   },
3680   {
3681     Xdiamond,                           TRUE,   FALSE,
3682     EL_DIAMOND,                         -1, -1
3683   },
3684   {
3685     Xdiamond_pause,                     FALSE,  FALSE,
3686     EL_DIAMOND,                         -1, -1
3687   },
3688   {
3689     Xdiamond_fall,                      FALSE,  FALSE,
3690     EL_DIAMOND,                         -1, -1
3691   },
3692   {
3693     Xdiamond_shine,                     FALSE,  FALSE,
3694     EL_DIAMOND,                         ACTION_TWINKLING, -1
3695   },
3696   {
3697     Ydiamond_s,                         FALSE,  FALSE,
3698     EL_DIAMOND,                         ACTION_FALLING, -1
3699   },
3700   {
3701     Ydiamond_sB,                        FALSE,  TRUE,
3702     EL_DIAMOND,                         ACTION_FALLING, -1
3703   },
3704   {
3705     Ydiamond_e,                         FALSE,  FALSE,
3706     EL_DIAMOND,                         ACTION_MOVING, MV_BIT_RIGHT
3707   },
3708   {
3709     Ydiamond_eB,                        FALSE,  TRUE,
3710     EL_DIAMOND,                         ACTION_MOVING, MV_BIT_RIGHT
3711   },
3712   {
3713     Ydiamond_w,                         FALSE,  FALSE,
3714     EL_DIAMOND,                         ACTION_MOVING, MV_BIT_LEFT
3715   },
3716   {
3717     Ydiamond_wB,                        FALSE,  TRUE,
3718     EL_DIAMOND,                         ACTION_MOVING, MV_BIT_LEFT
3719   },
3720   {
3721     Ydiamond_eat,                       FALSE,  FALSE,
3722     EL_DIAMOND,                         ACTION_COLLECTING, -1
3723   },
3724   {
3725     Ydiamond_stone,                     FALSE,  FALSE,
3726     EL_DIAMOND,                         ACTION_SMASHED_BY_ROCK, -1
3727   },
3728   {
3729     Xdrip_fall,                         TRUE,   FALSE,
3730     EL_AMOEBA_DROP,                     -1, -1
3731   },
3732   {
3733     Xdrip_stretch,                      FALSE,  FALSE,
3734     EL_AMOEBA_DROP,                     ACTION_FALLING, -1
3735   },
3736   {
3737     Xdrip_stretchB,                     FALSE,  TRUE,
3738     EL_AMOEBA_DROP,                     ACTION_FALLING, -1
3739   },
3740   {
3741     Xdrip_eat,                          FALSE,  FALSE,
3742     EL_AMOEBA_DROP,                     ACTION_GROWING, -1
3743   },
3744   {
3745     Ydrip_s1,                           FALSE,  FALSE,
3746     EL_AMOEBA_DROP,                     ACTION_FALLING, -1
3747   },
3748   {
3749     Ydrip_s1B,                          FALSE,  TRUE,
3750     EL_AMOEBA_DROP,                     ACTION_FALLING, -1
3751   },
3752   {
3753     Ydrip_s2,                           FALSE,  FALSE,
3754     EL_AMOEBA_DROP,                     ACTION_FALLING, -1
3755   },
3756   {
3757     Ydrip_s2B,                          FALSE,  TRUE,
3758     EL_AMOEBA_DROP,                     ACTION_FALLING, -1
3759   },
3760   {
3761     Xbomb,                              TRUE,   FALSE,
3762     EL_BOMB,                            -1, -1
3763   },
3764   {
3765     Xbomb_pause,                        FALSE,  FALSE,
3766     EL_BOMB,                            -1, -1
3767   },
3768   {
3769     Xbomb_fall,                         FALSE,  FALSE,
3770     EL_BOMB,                            -1, -1
3771   },
3772   {
3773     Ybomb_s,                            FALSE,  FALSE,
3774     EL_BOMB,                            ACTION_FALLING, -1
3775   },
3776   {
3777     Ybomb_sB,                           FALSE,  TRUE,
3778     EL_BOMB,                            ACTION_FALLING, -1
3779   },
3780   {
3781     Ybomb_e,                            FALSE,  FALSE,
3782     EL_BOMB,                            ACTION_MOVING, MV_BIT_RIGHT
3783   },
3784   {
3785     Ybomb_eB,                           FALSE,  TRUE,
3786     EL_BOMB,                            ACTION_MOVING, MV_BIT_RIGHT
3787   },
3788   {
3789     Ybomb_w,                            FALSE,  FALSE,
3790     EL_BOMB,                            ACTION_MOVING, MV_BIT_LEFT
3791   },
3792   {
3793     Ybomb_wB,                           FALSE,  TRUE,
3794     EL_BOMB,                            ACTION_MOVING, MV_BIT_LEFT
3795   },
3796   {
3797     Ybomb_eat,                          FALSE,  FALSE,
3798     EL_BOMB,                            ACTION_SMASHED_BY_ROCK, -1
3799   },
3800   {
3801     Xballoon,                           TRUE,   FALSE,
3802     EL_BALLOON,                         -1, -1
3803   },
3804   {
3805     Yballoon_n,                         FALSE,  FALSE,
3806     EL_BALLOON,                         ACTION_MOVING, MV_BIT_UP
3807   },
3808   {
3809     Yballoon_nB,                        FALSE,  TRUE,
3810     EL_BALLOON,                         ACTION_MOVING, MV_BIT_UP
3811   },
3812   {
3813     Yballoon_e,                         FALSE,  FALSE,
3814     EL_BALLOON,                         ACTION_MOVING, MV_BIT_RIGHT
3815   },
3816   {
3817     Yballoon_eB,                        FALSE,  TRUE,
3818     EL_BALLOON,                         ACTION_MOVING, MV_BIT_RIGHT
3819   },
3820   {
3821     Yballoon_s,                         FALSE,  FALSE,
3822     EL_BALLOON,                         ACTION_MOVING, MV_BIT_DOWN
3823   },
3824   {
3825     Yballoon_sB,                        FALSE,  TRUE,
3826     EL_BALLOON,                         ACTION_MOVING, MV_BIT_DOWN
3827   },
3828   {
3829     Yballoon_w,                         FALSE,  FALSE,
3830     EL_BALLOON,                         ACTION_MOVING, MV_BIT_LEFT
3831   },
3832   {
3833     Yballoon_wB,                        FALSE,  TRUE,
3834     EL_BALLOON,                         ACTION_MOVING, MV_BIT_LEFT
3835   },
3836   {
3837     Xgrass,                             TRUE,   FALSE,
3838     EL_EMC_GRASS,                       -1, -1
3839   },
3840   {
3841     Ygrass_nB,                          FALSE,  TRUE,
3842     EL_EMC_GRASS,                       ACTION_DIGGING, MV_BIT_UP
3843   },
3844   {
3845     Ygrass_eB,                          FALSE,  TRUE,
3846     EL_EMC_GRASS,                       ACTION_DIGGING, MV_BIT_RIGHT
3847   },
3848   {
3849     Ygrass_sB,                          FALSE,  TRUE,
3850     EL_EMC_GRASS,                       ACTION_DIGGING, MV_BIT_DOWN
3851   },
3852   {
3853     Ygrass_wB,                          FALSE,  TRUE,
3854     EL_EMC_GRASS,                       ACTION_DIGGING, MV_BIT_LEFT
3855   },
3856   {
3857     Xdirt,                              TRUE,   FALSE,
3858     EL_SAND,                            -1, -1
3859   },
3860   {
3861     Ydirt_nB,                           FALSE,  TRUE,
3862     EL_SAND,                            ACTION_DIGGING, MV_BIT_UP
3863   },
3864   {
3865     Ydirt_eB,                           FALSE,  TRUE,
3866     EL_SAND,                            ACTION_DIGGING, MV_BIT_RIGHT
3867   },
3868   {
3869     Ydirt_sB,                           FALSE,  TRUE,
3870     EL_SAND,                            ACTION_DIGGING, MV_BIT_DOWN
3871   },
3872   {
3873     Ydirt_wB,                           FALSE,  TRUE,
3874     EL_SAND,                            ACTION_DIGGING, MV_BIT_LEFT
3875   },
3876   {
3877     Xacid_ne,                           TRUE,   FALSE,
3878     EL_ACID_POOL_TOPRIGHT,              -1, -1
3879   },
3880   {
3881     Xacid_se,                           TRUE,   FALSE,
3882     EL_ACID_POOL_BOTTOMRIGHT,           -1, -1
3883   },
3884   {
3885     Xacid_s,                            TRUE,   FALSE,
3886     EL_ACID_POOL_BOTTOM,                -1, -1
3887   },
3888   {
3889     Xacid_sw,                           TRUE,   FALSE,
3890     EL_ACID_POOL_BOTTOMLEFT,            -1, -1
3891   },
3892   {
3893     Xacid_nw,                           TRUE,   FALSE,
3894     EL_ACID_POOL_TOPLEFT,               -1, -1
3895   },
3896   {
3897     Xacid_1,                            TRUE,   FALSE,
3898     EL_ACID,                            -1, -1
3899   },
3900   {
3901     Xacid_2,                            FALSE,  FALSE,
3902     EL_ACID,                            -1, -1
3903   },
3904   {
3905     Xacid_3,                            FALSE,  FALSE,
3906     EL_ACID,                            -1, -1
3907   },
3908   {
3909     Xacid_4,                            FALSE,  FALSE,
3910     EL_ACID,                            -1, -1
3911   },
3912   {
3913     Xacid_5,                            FALSE,  FALSE,
3914     EL_ACID,                            -1, -1
3915   },
3916   {
3917     Xacid_6,                            FALSE,  FALSE,
3918     EL_ACID,                            -1, -1
3919   },
3920   {
3921     Xacid_7,                            FALSE,  FALSE,
3922     EL_ACID,                            -1, -1
3923   },
3924   {
3925     Xacid_8,                            FALSE,  FALSE,
3926     EL_ACID,                            -1, -1
3927   },
3928   {
3929     Xball_1,                            TRUE,   FALSE,
3930     EL_EMC_MAGIC_BALL,                  -1, -1
3931   },
3932   {
3933     Xball_1B,                           FALSE,  TRUE,
3934     EL_EMC_MAGIC_BALL,                  ACTION_ACTIVE, -1
3935   },
3936   {
3937     Xball_2,                            FALSE,  FALSE,
3938     EL_EMC_MAGIC_BALL,                  ACTION_ACTIVE, -1
3939   },
3940   {
3941     Xball_2B,                           FALSE,  TRUE,
3942     EL_EMC_MAGIC_BALL,                  ACTION_ACTIVE, -1
3943   },
3944   {
3945     Yball_eat,                          FALSE,  FALSE,
3946     EL_EMC_MAGIC_BALL,                  ACTION_DROPPING, -1
3947   },
3948   {
3949     Xgrow_ns,                           TRUE,   FALSE,
3950     EL_EXPANDABLE_WALL_VERTICAL,        -1, -1
3951   },
3952   {
3953     Ygrow_ns_eat,                       FALSE,  FALSE,
3954     EL_EXPANDABLE_WALL_VERTICAL,        ACTION_GROWING, -1
3955   },
3956   {
3957     Xgrow_ew,                           TRUE,   FALSE,
3958     EL_EXPANDABLE_WALL_HORIZONTAL,      -1, -1
3959   },
3960   {
3961     Ygrow_ew_eat,                       FALSE,  FALSE,
3962     EL_EXPANDABLE_WALL_HORIZONTAL,      ACTION_GROWING, -1
3963   },
3964   {
3965     Xwonderwall,                        TRUE,   FALSE,
3966     EL_MAGIC_WALL,                      -1, -1
3967   },
3968   {
3969     XwonderwallB,                       FALSE,  FALSE,
3970     EL_MAGIC_WALL,                      ACTION_ACTIVE, -1
3971   },
3972   {
3973     Xamoeba_1,                          TRUE,   FALSE,
3974     EL_AMOEBA_DRY,                      ACTION_OTHER, -1
3975   },
3976   {
3977     Xamoeba_2,                          FALSE,  FALSE,
3978     EL_AMOEBA_DRY,                      ACTION_OTHER, -1
3979   },
3980   {
3981     Xamoeba_3,                          FALSE,  FALSE,
3982     EL_AMOEBA_DRY,                      ACTION_OTHER, -1
3983   },
3984   {
3985     Xamoeba_4,                          FALSE,  FALSE,
3986     EL_AMOEBA_DRY,                      ACTION_OTHER, -1
3987   },
3988   {
3989     Xamoeba_5,                          FALSE,  FALSE,
3990     EL_AMOEBA_WET,                      ACTION_OTHER, -1
3991   },
3992   {
3993     Xamoeba_6,                          FALSE,  FALSE,
3994     EL_AMOEBA_WET,                      ACTION_OTHER, -1
3995   },
3996   {
3997     Xamoeba_7,                          FALSE,  FALSE,
3998     EL_AMOEBA_WET,                      ACTION_OTHER, -1
3999   },
4000   {
4001     Xamoeba_8,                          FALSE,  FALSE,
4002     EL_AMOEBA_WET,                      ACTION_OTHER, -1
4003   },
4004   {
4005     Xdoor_1,                            TRUE,   FALSE,
4006     EL_EM_GATE_1,                       -1, -1
4007   },
4008   {
4009     Xdoor_2,                            TRUE,   FALSE,
4010     EL_EM_GATE_2,                       -1, -1
4011   },
4012   {
4013     Xdoor_3,                            TRUE,   FALSE,
4014     EL_EM_GATE_3,                       -1, -1
4015   },
4016   {
4017     Xdoor_4,                            TRUE,   FALSE,
4018     EL_EM_GATE_4,                       -1, -1
4019   },
4020   {
4021     Xdoor_5,                            TRUE,   FALSE,
4022     EL_EM_GATE_5,                       -1, -1
4023   },
4024   {
4025     Xdoor_6,                            TRUE,   FALSE,
4026     EL_EM_GATE_6,                       -1, -1
4027   },
4028   {
4029     Xdoor_7,                            TRUE,   FALSE,
4030     EL_EM_GATE_7,                       -1, -1
4031   },
4032   {
4033     Xdoor_8,                            TRUE,   FALSE,
4034     EL_EM_GATE_8,                       -1, -1
4035   },
4036   {
4037     Xkey_1,                             TRUE,   FALSE,
4038     EL_EM_KEY_1,                        -1, -1
4039   },
4040   {
4041     Xkey_2,                             TRUE,   FALSE,
4042     EL_EM_KEY_2,                        -1, -1
4043   },
4044   {
4045     Xkey_3,                             TRUE,   FALSE,
4046     EL_EM_KEY_3,                        -1, -1
4047   },
4048   {
4049     Xkey_4,                             TRUE,   FALSE,
4050     EL_EM_KEY_4,                        -1, -1
4051   },
4052   {
4053     Xkey_5,                             TRUE,   FALSE,
4054     EL_EM_KEY_5,                        -1, -1
4055   },
4056   {
4057     Xkey_6,                             TRUE,   FALSE,
4058     EL_EM_KEY_6,                        -1, -1
4059   },
4060   {
4061     Xkey_7,                             TRUE,   FALSE,
4062     EL_EM_KEY_7,                        -1, -1
4063   },
4064   {
4065     Xkey_8,                             TRUE,   FALSE,
4066     EL_EM_KEY_8,                        -1, -1
4067   },
4068   {
4069     Xwind_n,                            TRUE,   FALSE,
4070     EL_BALLOON_SWITCH_UP,               -1, -1
4071   },
4072   {
4073     Xwind_e,                            TRUE,   FALSE,
4074     EL_BALLOON_SWITCH_RIGHT,            -1, -1
4075   },
4076   {
4077     Xwind_s,                            TRUE,   FALSE,
4078     EL_BALLOON_SWITCH_DOWN,             -1, -1
4079   },
4080   {
4081     Xwind_w,                            TRUE,   FALSE,
4082     EL_BALLOON_SWITCH_LEFT,             -1, -1
4083   },
4084   {
4085     Xwind_nesw,                         TRUE,   FALSE,
4086     EL_BALLOON_SWITCH_ANY,              -1, -1
4087   },
4088   {
4089     Xwind_stop,                         TRUE,   FALSE,
4090     EL_BALLOON_SWITCH_NONE,             -1, -1
4091   },
4092   {
4093     Xexit,                              TRUE,   FALSE,
4094     EL_EXIT_CLOSED,                     -1, -1
4095   },
4096   {
4097     Xexit_1,                            TRUE,   FALSE,
4098     EL_EXIT_OPEN,                       -1, -1
4099   },
4100   {
4101     Xexit_2,                            FALSE,  FALSE,
4102     EL_EXIT_OPEN,                       -1, -1
4103   },
4104   {
4105     Xexit_3,                            FALSE,  FALSE,
4106     EL_EXIT_OPEN,                       -1, -1
4107   },
4108   {
4109     Xdynamite,                          TRUE,   FALSE,
4110     EL_DYNAMITE,                        -1, -1
4111   },
4112   {
4113     Ydynamite_eat,                      FALSE,  FALSE,
4114     EL_DYNAMITE,                        ACTION_COLLECTING, -1
4115   },
4116   {
4117     Xdynamite_1,                        TRUE,   FALSE,
4118     EL_DYNAMITE_ACTIVE,                 -1, -1
4119   },
4120   {
4121     Xdynamite_2,                        FALSE,  FALSE,
4122     EL_DYNAMITE_ACTIVE,                 -1, -1
4123   },
4124   {
4125     Xdynamite_3,                        FALSE,  FALSE,
4126     EL_DYNAMITE_ACTIVE,                 -1, -1
4127   },
4128   {
4129     Xdynamite_4,                        FALSE,  FALSE,
4130     EL_DYNAMITE_ACTIVE,                 -1, -1
4131   },
4132   {
4133     Xbumper,                            TRUE,   FALSE,
4134     EL_EMC_SPRING_BUMPER,               -1, -1
4135   },
4136   {
4137     XbumperB,                           FALSE,  FALSE,
4138     EL_EMC_SPRING_BUMPER,               ACTION_ACTIVE, -1
4139   },
4140   {
4141     Xwheel,                             TRUE,   FALSE,
4142     EL_ROBOT_WHEEL,                     -1, -1
4143   },
4144   {
4145     XwheelB,                            FALSE,  FALSE,
4146     EL_ROBOT_WHEEL,                     ACTION_ACTIVE, -1
4147   },
4148   {
4149     Xswitch,                            TRUE,   FALSE,
4150     EL_EMC_MAGIC_BALL_SWITCH,           -1, -1
4151   },
4152   {
4153     XswitchB,                           FALSE,  FALSE,
4154     EL_EMC_MAGIC_BALL_SWITCH,           ACTION_ACTIVE, -1
4155   },
4156   {
4157     Xsand,                              TRUE,   FALSE,
4158     EL_QUICKSAND_EMPTY,                 -1, -1
4159   },
4160   {
4161     Xsand_stone,                        TRUE,   FALSE,
4162     EL_QUICKSAND_FULL,                  -1, -1
4163   },
4164   {
4165     Xsand_stonein_1,                    FALSE,  FALSE,
4166     EL_ROCK,                            ACTION_FILLING, -1
4167   },
4168   {
4169     Xsand_stonein_2,                    FALSE,  FALSE,
4170     EL_ROCK,                            ACTION_FILLING, -1
4171   },
4172   {
4173     Xsand_stonein_3,                    FALSE,  FALSE,
4174     EL_ROCK,                            ACTION_FILLING, -1
4175   },
4176   {
4177     Xsand_stonein_4,                    FALSE,  FALSE,
4178     EL_ROCK,                            ACTION_FILLING, -1
4179   },
4180   {
4181     Xsand_stonesand_1,                  FALSE,  FALSE,
4182     EL_QUICKSAND_FULL,                  -1, -1
4183   },
4184   {
4185     Xsand_stonesand_2,                  FALSE,  FALSE,
4186     EL_QUICKSAND_FULL,                  -1, -1
4187   },
4188   {
4189     Xsand_stonesand_3,                  FALSE,  FALSE,
4190     EL_QUICKSAND_FULL,                  -1, -1
4191   },
4192   {
4193     Xsand_stonesand_4,                  FALSE,  FALSE,
4194     EL_QUICKSAND_FULL,                  -1, -1
4195   },
4196   {
4197     Xsand_stoneout_1,                   FALSE,  FALSE,
4198     EL_ROCK,                            ACTION_EMPTYING, -1
4199   },
4200   {
4201     Xsand_stoneout_2,                   FALSE,  FALSE,
4202     EL_ROCK,                            ACTION_EMPTYING, -1
4203   },
4204   {
4205     Xsand_sandstone_1,                  FALSE,  FALSE,
4206     EL_QUICKSAND_FULL,                  -1, -1
4207   },
4208   {
4209     Xsand_sandstone_2,                  FALSE,  FALSE,
4210     EL_QUICKSAND_FULL,                  -1, -1
4211   },
4212   {
4213     Xsand_sandstone_3,                  FALSE,  FALSE,
4214     EL_QUICKSAND_FULL,                  -1, -1
4215   },
4216   {
4217     Xsand_sandstone_4,                  FALSE,  FALSE,
4218     EL_QUICKSAND_FULL,                  -1, -1
4219   },
4220   {
4221     Xplant,                             TRUE,   FALSE,
4222     EL_EMC_PLANT,                       -1, -1
4223   },
4224   {
4225     Yplant,                             FALSE,  FALSE,
4226     EL_EMC_PLANT,                       -1, -1
4227   },
4228   {
4229     Xlenses,                            TRUE,   FALSE,
4230     EL_EMC_LENSES,                      -1, -1
4231   },
4232   {
4233     Xmagnify,                           TRUE,   FALSE,
4234     EL_EMC_MAGNIFIER,                   -1, -1
4235   },
4236   {
4237     Xdripper,                           TRUE,   FALSE,
4238     EL_EMC_DRIPPER,                     -1, -1
4239   },
4240   {
4241     XdripperB,                          FALSE,  FALSE,
4242     EL_EMC_DRIPPER,                     ACTION_ACTIVE, -1
4243   },
4244   {
4245     Xfake_blank,                        TRUE,   FALSE,
4246     EL_INVISIBLE_WALL,                  -1, -1
4247   },
4248   {
4249     Xfake_blankB,                       FALSE,  FALSE,
4250     EL_INVISIBLE_WALL,                  ACTION_ACTIVE, -1
4251   },
4252   {
4253     Xfake_grass,                        TRUE,   FALSE,
4254     EL_EMC_FAKE_GRASS,                  -1, -1
4255   },
4256   {
4257     Xfake_grassB,                       FALSE,  FALSE,
4258     EL_EMC_FAKE_GRASS,                  ACTION_ACTIVE, -1
4259   },
4260   {
4261     Xfake_door_1,                       TRUE,   FALSE,
4262     EL_EM_GATE_1_GRAY,                  -1, -1
4263   },
4264   {
4265     Xfake_door_2,                       TRUE,   FALSE,
4266     EL_EM_GATE_2_GRAY,                  -1, -1
4267   },
4268   {
4269     Xfake_door_3,                       TRUE,   FALSE,
4270     EL_EM_GATE_3_GRAY,                  -1, -1
4271   },
4272   {
4273     Xfake_door_4,                       TRUE,   FALSE,
4274     EL_EM_GATE_4_GRAY,                  -1, -1
4275   },
4276   {
4277     Xfake_door_5,                       TRUE,   FALSE,
4278     EL_EM_GATE_5_GRAY,                  -1, -1
4279   },
4280   {
4281     Xfake_door_6,                       TRUE,   FALSE,
4282     EL_EM_GATE_6_GRAY,                  -1, -1
4283   },
4284   {
4285     Xfake_door_7,                       TRUE,   FALSE,
4286     EL_EM_GATE_7_GRAY,                  -1, -1
4287   },
4288   {
4289     Xfake_door_8,                       TRUE,   FALSE,
4290     EL_EM_GATE_8_GRAY,                  -1, -1
4291   },
4292   {
4293     Xsteel_1,                           TRUE,   FALSE,
4294     EL_STEELWALL,                       -1, -1
4295   },
4296   {
4297     Xsteel_2,                           TRUE,   FALSE,
4298     EL_EMC_STEELWALL_2,                 -1, -1
4299   },
4300   {
4301     Xsteel_3,                           TRUE,   FALSE,
4302     EL_EMC_STEELWALL_3,                 -1, -1
4303   },
4304   {
4305     Xsteel_4,                           TRUE,   FALSE,
4306     EL_EMC_STEELWALL_4,                 -1, -1
4307   },
4308   {
4309     Xwall_1,                            TRUE,   FALSE,
4310     EL_WALL,                            -1, -1
4311   },
4312   {
4313     Xwall_2,                            TRUE,   FALSE,
4314     EL_EMC_WALL_14,                     -1, -1
4315   },
4316   {
4317     Xwall_3,                            TRUE,   FALSE,
4318     EL_EMC_WALL_15,                     -1, -1
4319   },
4320   {
4321     Xwall_4,                            TRUE,   FALSE,
4322     EL_EMC_WALL_16,                     -1, -1
4323   },
4324   {
4325     Xround_wall_1,                      TRUE,   FALSE,
4326     EL_WALL_SLIPPERY,                   -1, -1
4327   },
4328   {
4329     Xround_wall_2,                      TRUE,   FALSE,
4330     EL_EMC_WALL_SLIPPERY_2,             -1, -1
4331   },
4332   {
4333     Xround_wall_3,                      TRUE,   FALSE,
4334     EL_EMC_WALL_SLIPPERY_3,             -1, -1
4335   },
4336   {
4337     Xround_wall_4,                      TRUE,   FALSE,
4338     EL_EMC_WALL_SLIPPERY_4,             -1, -1
4339   },
4340   {
4341     Xdecor_1,                           TRUE,   FALSE,
4342     EL_EMC_WALL_8,                      -1, -1
4343   },
4344   {
4345     Xdecor_2,                           TRUE,   FALSE,
4346     EL_EMC_WALL_6,                      -1, -1
4347   },
4348   {
4349     Xdecor_3,                           TRUE,   FALSE,
4350     EL_EMC_WALL_4,                      -1, -1
4351   },
4352   {
4353     Xdecor_4,                           TRUE,   FALSE,
4354     EL_EMC_WALL_7,                      -1, -1
4355   },
4356   {
4357     Xdecor_5,                           TRUE,   FALSE,
4358     EL_EMC_WALL_5,                      -1, -1
4359   },
4360   {
4361     Xdecor_6,                           TRUE,   FALSE,
4362     EL_EMC_WALL_9,                      -1, -1
4363   },
4364   {
4365     Xdecor_7,                           TRUE,   FALSE,
4366     EL_EMC_WALL_10,                     -1, -1
4367   },
4368   {
4369     Xdecor_8,                           TRUE,   FALSE,
4370     EL_EMC_WALL_1,                      -1, -1
4371   },
4372   {
4373     Xdecor_9,                           TRUE,   FALSE,
4374     EL_EMC_WALL_2,                      -1, -1
4375   },
4376   {
4377     Xdecor_10,                          TRUE,   FALSE,
4378     EL_EMC_WALL_3,                      -1, -1
4379   },
4380   {
4381     Xdecor_11,                          TRUE,   FALSE,
4382     EL_EMC_WALL_11,                     -1, -1
4383   },
4384   {
4385     Xdecor_12,                          TRUE,   FALSE,
4386     EL_EMC_WALL_12,                     -1, -1
4387   },
4388   {
4389     Xalpha_0,                           TRUE,   FALSE,
4390     EL_CHAR('0'),                       -1, -1
4391   },
4392   {
4393     Xalpha_1,                           TRUE,   FALSE,
4394     EL_CHAR('1'),                       -1, -1
4395   },
4396   {
4397     Xalpha_2,                           TRUE,   FALSE,
4398     EL_CHAR('2'),                       -1, -1
4399   },
4400   {
4401     Xalpha_3,                           TRUE,   FALSE,
4402     EL_CHAR('3'),                       -1, -1
4403   },
4404   {
4405     Xalpha_4,                           TRUE,   FALSE,
4406     EL_CHAR('4'),                       -1, -1
4407   },
4408   {
4409     Xalpha_5,                           TRUE,   FALSE,
4410     EL_CHAR('5'),                       -1, -1
4411   },
4412   {
4413     Xalpha_6,                           TRUE,   FALSE,
4414     EL_CHAR('6'),                       -1, -1
4415   },
4416   {
4417     Xalpha_7,                           TRUE,   FALSE,
4418     EL_CHAR('7'),                       -1, -1
4419   },
4420   {
4421     Xalpha_8,                           TRUE,   FALSE,
4422     EL_CHAR('8'),                       -1, -1
4423   },
4424   {
4425     Xalpha_9,                           TRUE,   FALSE,
4426     EL_CHAR('9'),                       -1, -1
4427   },
4428   {
4429     Xalpha_excla,                       TRUE,   FALSE,
4430     EL_CHAR('!'),                       -1, -1
4431   },
4432   {
4433     Xalpha_quote,                       TRUE,   FALSE,
4434     EL_CHAR('"'),                       -1, -1
4435   },
4436   {
4437     Xalpha_comma,                       TRUE,   FALSE,
4438     EL_CHAR(','),                       -1, -1
4439   },
4440   {
4441     Xalpha_minus,                       TRUE,   FALSE,
4442     EL_CHAR('-'),                       -1, -1
4443   },
4444   {
4445     Xalpha_perio,                       TRUE,   FALSE,
4446     EL_CHAR('.'),                       -1, -1
4447   },
4448   {
4449     Xalpha_colon,                       TRUE,   FALSE,
4450     EL_CHAR(':'),                       -1, -1
4451   },
4452   {
4453     Xalpha_quest,                       TRUE,   FALSE,
4454     EL_CHAR('?'),                       -1, -1
4455   },
4456   {
4457     Xalpha_a,                           TRUE,   FALSE,
4458     EL_CHAR('A'),                       -1, -1
4459   },
4460   {
4461     Xalpha_b,                           TRUE,   FALSE,
4462     EL_CHAR('B'),                       -1, -1
4463   },
4464   {
4465     Xalpha_c,                           TRUE,   FALSE,
4466     EL_CHAR('C'),                       -1, -1
4467   },
4468   {
4469     Xalpha_d,                           TRUE,   FALSE,
4470     EL_CHAR('D'),                       -1, -1
4471   },
4472   {
4473     Xalpha_e,                           TRUE,   FALSE,
4474     EL_CHAR('E'),                       -1, -1
4475   },
4476   {
4477     Xalpha_f,                           TRUE,   FALSE,
4478     EL_CHAR('F'),                       -1, -1
4479   },
4480   {
4481     Xalpha_g,                           TRUE,   FALSE,
4482     EL_CHAR('G'),                       -1, -1
4483   },
4484   {
4485     Xalpha_h,                           TRUE,   FALSE,
4486     EL_CHAR('H'),                       -1, -1
4487   },
4488   {
4489     Xalpha_i,                           TRUE,   FALSE,
4490     EL_CHAR('I'),                       -1, -1
4491   },
4492   {
4493     Xalpha_j,                           TRUE,   FALSE,
4494     EL_CHAR('J'),                       -1, -1
4495   },
4496   {
4497     Xalpha_k,                           TRUE,   FALSE,
4498     EL_CHAR('K'),                       -1, -1
4499   },
4500   {
4501     Xalpha_l,                           TRUE,   FALSE,
4502     EL_CHAR('L'),                       -1, -1
4503   },
4504   {
4505     Xalpha_m,                           TRUE,   FALSE,
4506     EL_CHAR('M'),                       -1, -1
4507   },
4508   {
4509     Xalpha_n,                           TRUE,   FALSE,
4510     EL_CHAR('N'),                       -1, -1
4511   },
4512   {
4513     Xalpha_o,                           TRUE,   FALSE,
4514     EL_CHAR('O'),                       -1, -1
4515   },
4516   {
4517     Xalpha_p,                           TRUE,   FALSE,
4518     EL_CHAR('P'),                       -1, -1
4519   },
4520   {
4521     Xalpha_q,                           TRUE,   FALSE,
4522     EL_CHAR('Q'),                       -1, -1
4523   },
4524   {
4525     Xalpha_r,                           TRUE,   FALSE,
4526     EL_CHAR('R'),                       -1, -1
4527   },
4528   {
4529     Xalpha_s,                           TRUE,   FALSE,
4530     EL_CHAR('S'),                       -1, -1
4531   },
4532   {
4533     Xalpha_t,                           TRUE,   FALSE,
4534     EL_CHAR('T'),                       -1, -1
4535   },
4536   {
4537     Xalpha_u,                           TRUE,   FALSE,
4538     EL_CHAR('U'),                       -1, -1
4539   },
4540   {
4541     Xalpha_v,                           TRUE,   FALSE,
4542     EL_CHAR('V'),                       -1, -1
4543   },
4544   {
4545     Xalpha_w,                           TRUE,   FALSE,
4546     EL_CHAR('W'),                       -1, -1
4547   },
4548   {
4549     Xalpha_x,                           TRUE,   FALSE,
4550     EL_CHAR('X'),                       -1, -1
4551   },
4552   {
4553     Xalpha_y,                           TRUE,   FALSE,
4554     EL_CHAR('Y'),                       -1, -1
4555   },
4556   {
4557     Xalpha_z,                           TRUE,   FALSE,
4558     EL_CHAR('Z'),                       -1, -1
4559   },
4560   {
4561     Xalpha_arrow_e,                     TRUE,   FALSE,
4562     EL_CHAR('>'),                       -1, -1
4563   },
4564   {
4565     Xalpha_arrow_w,                     TRUE,   FALSE,
4566     EL_CHAR('<'),                       -1, -1
4567   },
4568   {
4569     Xalpha_copyr,                       TRUE,   FALSE,
4570     EL_CHAR('©'),                       -1, -1
4571   },
4572   {
4573     Xalpha_copyr,                       TRUE,   FALSE,
4574     EL_CHAR('©'),                       -1, -1
4575   },
4576
4577   {
4578     Xboom_bug,                          FALSE,  FALSE,
4579     EL_BUG,                             ACTION_EXPLODING, -1
4580   },
4581   {
4582     Xboom_bomb,                         FALSE,  FALSE,
4583     EL_BOMB,                            ACTION_EXPLODING, -1
4584   },
4585   {
4586     Xboom_android,                      FALSE,  FALSE,
4587     EL_EMC_ANDROID,                     ACTION_OTHER, -1
4588   },
4589   {
4590     Xboom_1,                            FALSE,  FALSE,
4591     EL_DEFAULT,                         ACTION_EXPLODING, -1
4592   },
4593   {
4594     Xboom_2,                            FALSE,  FALSE,
4595     EL_DEFAULT,                         ACTION_EXPLODING, -1
4596   },
4597   {
4598     Znormal,                            FALSE,  FALSE,
4599     EL_EMPTY,                           -1, -1
4600   },
4601   {
4602     Zdynamite,                          FALSE,  FALSE,
4603     EL_EMPTY,                           -1, -1
4604   },
4605   {
4606     Zplayer,                            FALSE,  FALSE,
4607     EL_EMPTY,                           -1, -1
4608   },
4609   {
4610     ZBORDER,                            FALSE,  FALSE,
4611     EL_EMPTY,                           -1, -1
4612   },
4613
4614   {
4615     -1,                                 FALSE,  FALSE,
4616     -1,                                 -1, -1
4617   }
4618 };
4619
4620 int map_element_RND_to_EM(int element_rnd)
4621 {
4622   static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4623   static boolean mapping_initialized = FALSE;
4624
4625   if (!mapping_initialized)
4626   {
4627     int i;
4628
4629     /* return "Xalpha_quest" for all undefined elements in mapping array */
4630     for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4631       mapping_RND_to_EM[i] = Xalpha_quest;
4632
4633     for (i = 0; mapping_EM_to_RND_list[i].element_em != -1; i++)
4634       if (mapping_EM_to_RND_list[i].is_rnd_to_em_mapping)
4635         mapping_RND_to_EM[mapping_EM_to_RND_list[i].element_rnd] =
4636           mapping_EM_to_RND_list[i].element_em;
4637
4638     mapping_initialized = TRUE;
4639   }
4640
4641   if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4642     return mapping_RND_to_EM[element_rnd];
4643
4644   Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4645
4646   return EL_UNKNOWN;
4647 }
4648
4649 int map_element_EM_to_RND(int element_em)
4650 {
4651   static unsigned short mapping_EM_to_RND[TILE_MAX];
4652   static boolean mapping_initialized = FALSE;
4653
4654   if (!mapping_initialized)
4655   {
4656     int i;
4657
4658     /* return "EL_UNKNOWN" for all undefined elements in mapping array */
4659     for (i = 0; i < TILE_MAX; i++)
4660       mapping_EM_to_RND[i] = EL_UNKNOWN;
4661
4662     for (i = 0; mapping_EM_to_RND_list[i].element_em != -1; i++)
4663       mapping_EM_to_RND[mapping_EM_to_RND_list[i].element_em] =
4664         mapping_EM_to_RND_list[i].element_rnd;
4665
4666     mapping_initialized = TRUE;
4667   }
4668
4669   if (element_em >= 0 && element_em < TILE_MAX)
4670     return mapping_EM_to_RND[element_em];
4671
4672   Error(ERR_WARN, "invalid EM level element %d", element_em);
4673
4674   return EL_UNKNOWN;
4675 }
4676
4677 #else
4678
4679 int map_element_RND_to_EM(int element_rnd)
4680 {
4681   static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4682   static boolean mapping_initialized = FALSE;
4683
4684   struct
4685   {
4686     int element_em;
4687     int element_rnd;
4688   }
4689   mapping_RND_to_EM_list[] =
4690   {
4691     { Xblank,                   EL_EMPTY                        },
4692     { Xstone,                   EL_ROCK                         },
4693     { Xnut,                     EL_NUT                          },
4694     { Xbug_n,                   EL_BUG_UP                       },
4695     { Xbug_e,                   EL_BUG_RIGHT                    },
4696     { Xbug_s,                   EL_BUG_DOWN                     },
4697     { Xbug_w,                   EL_BUG_LEFT                     },
4698     { Xtank_n,                  EL_SPACESHIP_UP                 },
4699     { Xtank_e,                  EL_SPACESHIP_RIGHT              },
4700     { Xtank_s,                  EL_SPACESHIP_DOWN               },
4701     { Xtank_w,                  EL_SPACESHIP_LEFT               },
4702     { Xandroid,                 EL_EMC_ANDROID                  },
4703     { Xandroid_1_n,             EL_EMC_ANDROID_UP               },
4704     { Xandroid_1_e,             EL_EMC_ANDROID_RIGHT            },
4705     { Xandroid_1_w,             EL_EMC_ANDROID_LEFT             },
4706     { Xandroid_1_s,             EL_EMC_ANDROID_DOWN             },
4707     { Xspring,                  EL_SPRING                       },
4708     { Xeater_n,                 EL_YAMYAM                       },
4709     { Xalien,                   EL_ROBOT                        },
4710     { Xemerald,                 EL_EMERALD                      },
4711     { Xdiamond,                 EL_DIAMOND                      },
4712     { Xdrip_fall,               EL_AMOEBA_DROP                  },
4713     { Xbomb,                    EL_BOMB                         },
4714     { Xballoon,                 EL_BALLOON                      },
4715     { Xgrass,                   EL_EMC_GRASS                    },
4716     { Xdirt,                    EL_SAND                         },
4717     { Xacid_ne,                 EL_ACID_POOL_TOPRIGHT           },
4718     { Xacid_se,                 EL_ACID_POOL_BOTTOMRIGHT        },
4719     { Xacid_s,                  EL_ACID_POOL_BOTTOM             },
4720     { Xacid_sw,                 EL_ACID_POOL_BOTTOMLEFT         },
4721     { Xacid_nw,                 EL_ACID_POOL_TOPLEFT            },
4722     { Xacid_1,                  EL_ACID                         },
4723     { Xball_1,                  EL_EMC_MAGIC_BALL               },
4724     { Xgrow_ns,                 EL_EMC_GROW                     },
4725     { Xwonderwall,              EL_MAGIC_WALL                   },
4726     { Xamoeba_1,                EL_AMOEBA_WET                   },
4727     { Xdoor_1,                  EL_EM_GATE_1                    },
4728     { Xdoor_2,                  EL_EM_GATE_2                    },
4729     { Xdoor_3,                  EL_EM_GATE_3                    },
4730     { Xdoor_4,                  EL_EM_GATE_4                    },
4731     { Xdoor_5,                  EL_EMC_GATE_5                   },
4732     { Xdoor_6,                  EL_EMC_GATE_6                   },
4733     { Xdoor_7,                  EL_EMC_GATE_7                   },
4734     { Xdoor_8,                  EL_EMC_GATE_8                   },
4735     { Xkey_1,                   EL_EM_KEY_1                     },
4736     { Xkey_2,                   EL_EM_KEY_2                     },
4737     { Xkey_3,                   EL_EM_KEY_3                     },
4738     { Xkey_4,                   EL_EM_KEY_4                     },
4739     { Xkey_5,                   EL_EMC_KEY_5                    },
4740     { Xkey_6,                   EL_EMC_KEY_6                    },
4741     { Xkey_7,                   EL_EMC_KEY_7                    },
4742     { Xkey_8,                   EL_EMC_KEY_8                    },
4743     { Xwind_n,                  EL_BALLOON_SWITCH_UP            },
4744     { Xwind_e,                  EL_BALLOON_SWITCH_RIGHT         },
4745     { Xwind_s,                  EL_BALLOON_SWITCH_DOWN          },
4746     { Xwind_w,                  EL_BALLOON_SWITCH_LEFT          },
4747     { Xwind_nesw,               EL_BALLOON_SWITCH_ANY           },
4748     { Xwind_stop,               EL_BALLOON_SWITCH_NONE          },
4749     { Xexit,                    EL_EXIT_CLOSED                  },
4750     { Xexit_1,                  EL_EXIT_OPEN                    },
4751     { Xdynamite,                EL_DYNAMITE                     },
4752     { Xdynamite_1,              EL_DYNAMITE_ACTIVE              },
4753     { Xbumper,                  EL_EMC_BUMPER                   },
4754     { Xwheel,                   EL_ROBOT_WHEEL                  },
4755     { Xswitch,                  EL_UNKNOWN                      },
4756     { Xsand,                    EL_QUICKSAND_EMPTY              },
4757     { Xsand_stone,              EL_QUICKSAND_FULL               },
4758     { Xplant,                   EL_EMC_PLANT                    },
4759     { Xlenses,                  EL_EMC_LENSES                   },
4760     { Xmagnify,                 EL_EMC_MAGNIFIER                },
4761     { Xdripper,                 EL_UNKNOWN                      },
4762     { Xfake_blank,              EL_INVISIBLE_WALL               },
4763     { Xfake_grass,              EL_INVISIBLE_SAND               },
4764     { Xfake_door_1,             EL_EM_GATE_1_GRAY               },
4765     { Xfake_door_2,             EL_EM_GATE_2_GRAY               },
4766     { Xfake_door_3,             EL_EM_GATE_3_GRAY               },
4767     { Xfake_door_4,             EL_EM_GATE_4_GRAY               },
4768     { Xfake_door_5,             EL_EMC_GATE_5_GRAY              },
4769     { Xfake_door_6,             EL_EMC_GATE_6_GRAY              },
4770     { Xfake_door_7,             EL_EMC_GATE_7_GRAY              },
4771     { Xfake_door_8,             EL_EMC_GATE_8_GRAY              },
4772     { Xsteel_1,                 EL_STEELWALL                    },
4773     { Xsteel_2,                 EL_UNKNOWN                      },
4774     { Xsteel_3,                 EL_EMC_STEELWALL_1              },
4775     { Xsteel_4,                 EL_UNKNOWN                      },
4776     { Xwall_1,                  EL_WALL                         },
4777     { Xwall_2,                  EL_UNKNOWN                      },
4778     { Xwall_3,                  EL_UNKNOWN                      },
4779     { Xwall_4,                  EL_UNKNOWN                      },
4780     { Xround_wall_1,            EL_WALL_SLIPPERY                },
4781     { Xround_wall_2,            EL_UNKNOWN                      },
4782     { Xround_wall_3,            EL_UNKNOWN                      },
4783     { Xround_wall_4,            EL_UNKNOWN                      },
4784     { Xdecor_1,                 EL_UNKNOWN                      },
4785     { Xdecor_2,                 EL_EMC_WALL_6                   },
4786     { Xdecor_3,                 EL_EMC_WALL_4                   },
4787     { Xdecor_4,                 EL_EMC_WALL_5                   },
4788     { Xdecor_5,                 EL_EMC_WALL_7                   },
4789     { Xdecor_6,                 EL_EMC_WALL_8                   },
4790     { Xdecor_7,                 EL_UNKNOWN                      },
4791     { Xdecor_8,                 EL_EMC_WALL_1                   },
4792     { Xdecor_9,                 EL_EMC_WALL_2                   },
4793     { Xdecor_10,                EL_EMC_WALL_3                   },
4794     { Xdecor_11,                EL_UNKNOWN                      },
4795     { Xdecor_12,                EL_UNKNOWN                      },
4796     { Xalpha_0,                 EL_CHAR('0')                    },
4797     { Xalpha_1,                 EL_CHAR('1')                    },
4798     { Xalpha_2,                 EL_CHAR('2')                    },
4799     { Xalpha_3,                 EL_CHAR('3')                    },
4800     { Xalpha_4,                 EL_CHAR('4')                    },
4801     { Xalpha_5,                 EL_CHAR('5')                    },
4802     { Xalpha_6,                 EL_CHAR('6')                    },
4803     { Xalpha_7,                 EL_CHAR('7')                    },
4804     { Xalpha_8,                 EL_CHAR('8')                    },
4805     { Xalpha_9,                 EL_CHAR('9')                    },
4806     { Xalpha_excla,             EL_CHAR('!')                    },
4807     { Xalpha_quote,             EL_CHAR('"')                    },
4808     { Xalpha_comma,             EL_CHAR(',')                    },
4809     { Xalpha_minus,             EL_CHAR('-')                    },
4810     { Xalpha_perio,             EL_CHAR('.')                    },
4811     { Xalpha_colon,             EL_CHAR(':')                    },
4812     { Xalpha_quest,             EL_CHAR('?')                    },
4813     { Xalpha_a,                 EL_CHAR('A')                    },
4814     { Xalpha_b,                 EL_CHAR('B')                    },
4815     { Xalpha_c,                 EL_CHAR('C')                    },
4816     { Xalpha_d,                 EL_CHAR('D')                    },
4817     { Xalpha_e,                 EL_CHAR('E')                    },
4818     { Xalpha_f,                 EL_CHAR('F')                    },
4819     { Xalpha_g,                 EL_CHAR('G')                    },
4820     { Xalpha_h,                 EL_CHAR('H')                    },
4821     { Xalpha_i,                 EL_CHAR('I')                    },
4822     { Xalpha_j,                 EL_CHAR('J')                    },
4823     { Xalpha_k,                 EL_CHAR('K')                    },
4824     { Xalpha_l,                 EL_CHAR('L')                    },
4825     { Xalpha_m,                 EL_CHAR('M')                    },
4826     { Xalpha_n,                 EL_CHAR('N')                    },
4827     { Xalpha_o,                 EL_CHAR('O')                    },
4828     { Xalpha_p,                 EL_CHAR('P')                    },
4829     { Xalpha_q,                 EL_CHAR('Q')                    },
4830     { Xalpha_r,                 EL_CHAR('R')                    },
4831     { Xalpha_s,                 EL_CHAR('S')                    },
4832     { Xalpha_t,                 EL_CHAR('T')                    },
4833     { Xalpha_u,                 EL_CHAR('U')                    },
4834     { Xalpha_v,                 EL_CHAR('V')                    },
4835     { Xalpha_w,                 EL_CHAR('W')                    },
4836     { Xalpha_x,                 EL_CHAR('X')                    },
4837     { Xalpha_y,                 EL_CHAR('Y')                    },
4838     { Xalpha_z,                 EL_CHAR('Z')                    },
4839     { Xalpha_arrow_e,           EL_CHAR('>')                    },
4840     { Xalpha_arrow_w,           EL_CHAR('<')                    },
4841     { Xalpha_copyr,             EL_CHAR('©')                    },
4842
4843     { Zplayer,                  EL_PLAYER_1                     },
4844     { Zplayer,                  EL_PLAYER_2                     },
4845     { Zplayer,                  EL_PLAYER_3                     },
4846     { Zplayer,                  EL_PLAYER_4                     },
4847
4848     { ZBORDER,                  EL_EMC_LEVEL_BORDER             },
4849
4850     { -1,                       -1                              }
4851   };
4852
4853   if (!mapping_initialized)
4854   {
4855     int i;
4856
4857     /* return "Xalpha_quest" for all undefined elements in mapping array */
4858     for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4859       mapping_RND_to_EM[i] = Xalpha_quest;
4860
4861     for (i = 0; mapping_RND_to_EM_list[i].element_rnd != -1; i++)
4862       mapping_RND_to_EM[mapping_RND_to_EM_list[i].element_rnd] =
4863         mapping_RND_to_EM_list[i].element_em;
4864
4865     mapping_initialized = TRUE;
4866   }
4867
4868   if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4869     return mapping_RND_to_EM[element_rnd];
4870
4871   Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4872
4873   return EL_UNKNOWN;
4874 }
4875
4876 int map_element_EM_to_RND(int element_em)
4877 {
4878   static unsigned short mapping_EM_to_RND[TILE_MAX];
4879   static boolean mapping_initialized = FALSE;
4880
4881   struct
4882   {
4883     int element_em;
4884     int element_rnd;
4885   }
4886   mapping_EM_to_RND_list[] =
4887   {
4888     { Xblank,                   EL_EMPTY                        },
4889     { Yacid_splash_eB,          EL_EMPTY                        },
4890     { Yacid_splash_wB,          EL_EMPTY                        },
4891
4892 #ifdef EM_ENGINE_BAD_ROLL
4893     { Xstone_force_e,           EL_ROCK                         },
4894     { Xstone_force_w,           EL_ROCK                         },
4895     { Xnut_force_e,             EL_NUT                          },
4896     { Xnut_force_w,             EL_NUT                          },
4897     { Xspring_force_e,          EL_SPRING                       },
4898     { Xspring_force_w,          EL_SPRING                       },
4899     { Xemerald_force_e,         EL_EMERALD                      },
4900     { Xemerald_force_w,         EL_EMERALD                      },
4901     { Xdiamond_force_e,         EL_DIAMOND                      },
4902     { Xdiamond_force_w,         EL_DIAMOND                      },
4903     { Xbomb_force_e,            EL_BOMB                         },
4904     { Xbomb_force_w,            EL_BOMB                         },
4905 #endif
4906
4907     { Xstone,                   EL_ROCK                         },
4908     { Xstone_pause,             EL_ROCK                         },
4909     { Xstone_fall,              EL_ROCK                         },
4910     { Ystone_s,                 EL_ROCK                         },
4911     { Ystone_sB,                EL_ROCK                         },
4912     { Ystone_e,                 EL_ROCK                         },
4913     { Ystone_eB,                EL_ROCK                         },
4914     { Ystone_w,                 EL_ROCK                         },
4915     { Ystone_wB,                EL_ROCK                         },
4916     { Xnut,                     EL_NUT                          },
4917     { Xnut_pause,               EL_NUT                          },
4918     { Xnut_fall,                EL_NUT                          },
4919     { Ynut_s,                   EL_NUT                          },
4920     { Ynut_sB,                  EL_NUT                          },
4921     { Ynut_e,                   EL_NUT                          },
4922     { Ynut_eB,                  EL_NUT                          },
4923     { Ynut_w,                   EL_NUT                          },
4924     { Ynut_wB,                  EL_NUT                          },
4925     { Xbug_n,                   EL_BUG_UP                       },
4926     { Xbug_e,                   EL_BUG_RIGHT                    },
4927     { Xbug_s,                   EL_BUG_DOWN                     },
4928     { Xbug_w,                   EL_BUG_LEFT                     },
4929     { Xbug_gon,                 EL_BUG_UP                       },
4930     { Xbug_goe,                 EL_BUG_RIGHT                    },
4931     { Xbug_gos,                 EL_BUG_DOWN                     },
4932     { Xbug_gow,                 EL_BUG_LEFT                     },
4933     { Ybug_n,                   EL_BUG_UP                       },
4934     { Ybug_nB,                  EL_BUG_UP                       },
4935     { Ybug_e,                   EL_BUG_RIGHT                    },
4936     { Ybug_eB,                  EL_BUG_RIGHT                    },
4937     { Ybug_s,                   EL_BUG_DOWN                     },
4938     { Ybug_sB,                  EL_BUG_DOWN                     },
4939     { Ybug_w,                   EL_BUG_LEFT                     },
4940     { Ybug_wB,                  EL_BUG_LEFT                     },
4941     { Ybug_w_n,                 EL_BUG_UP                       },
4942     { Ybug_n_e,                 EL_BUG_RIGHT                    },
4943     { Ybug_e_s,                 EL_BUG_DOWN                     },
4944     { Ybug_s_w,                 EL_BUG_LEFT                     },
4945     { Ybug_e_n,                 EL_BUG_UP                       },
4946     { Ybug_s_e,                 EL_BUG_RIGHT                    },
4947     { Ybug_w_s,                 EL_BUG_DOWN                     },
4948     { Ybug_n_w,                 EL_BUG_LEFT                     },
4949     { Ybug_stone,               EL_ROCK                         },
4950     { Ybug_spring,              EL_SPRING                       },
4951     { Xtank_n,                  EL_SPACESHIP_UP                 },
4952     { Xtank_e,                  EL_SPACESHIP_RIGHT              },
4953     { Xtank_s,                  EL_SPACESHIP_DOWN               },
4954     { Xtank_w,                  EL_SPACESHIP_LEFT               },
4955     { Xtank_gon,                EL_SPACESHIP_UP                 },
4956     { Xtank_goe,                EL_SPACESHIP_RIGHT              },
4957     { Xtank_gos,                EL_SPACESHIP_DOWN               },
4958     { Xtank_gow,                EL_SPACESHIP_LEFT               },
4959     { Ytank_n,                  EL_SPACESHIP_UP                 },
4960     { Ytank_nB,                 EL_SPACESHIP_UP                 },
4961     { Ytank_e,                  EL_SPACESHIP_RIGHT              },
4962     { Ytank_eB,                 EL_SPACESHIP_RIGHT              },
4963     { Ytank_s,                  EL_SPACESHIP_DOWN               },
4964     { Ytank_sB,                 EL_SPACESHIP_DOWN               },
4965     { Ytank_w,                  EL_SPACESHIP_LEFT               },
4966     { Ytank_wB,                 EL_SPACESHIP_LEFT               },
4967     { Ytank_w_n,                EL_SPACESHIP_UP                 },
4968     { Ytank_n_e,                EL_SPACESHIP_RIGHT              },
4969     { Ytank_e_s,                EL_SPACESHIP_DOWN               },
4970     { Ytank_s_w,                EL_SPACESHIP_LEFT               },
4971     { Ytank_e_n,                EL_SPACESHIP_UP                 },
4972     { Ytank_s_e,                EL_SPACESHIP_RIGHT              },
4973     { Ytank_w_s,                EL_SPACESHIP_DOWN               },
4974     { Ytank_n_w,                EL_SPACESHIP_LEFT               },
4975     { Ytank_stone,              EL_ROCK                         },
4976     { Ytank_spring,             EL_SPRING                       },
4977     { Xandroid,                 EL_EMC_ANDROID                  },
4978     { Xandroid_1_n,             EL_EMC_ANDROID_UP               },
4979     { Xandroid_2_n,             EL_EMC_ANDROID_UP               },
4980     { Xandroid_1_e,             EL_EMC_ANDROID_RIGHT            },
4981     { Xandroid_2_e,             EL_EMC_ANDROID_RIGHT            },
4982     { Xandroid_1_w,             EL_EMC_ANDROID_LEFT             },
4983     { Xandroid_2_w,             EL_EMC_ANDROID_LEFT             },
4984     { Xandroid_1_s,             EL_EMC_ANDROID_DOWN             },
4985     { Xandroid_2_s,             EL_EMC_ANDROID_DOWN             },
4986     { Yandroid_n,               EL_EMC_ANDROID_UP               },
4987     { Yandroid_nB,              EL_EMC_ANDROID_UP               },
4988     { Yandroid_ne,              EL_EMC_ANDROID_RIGHT_UP         },
4989     { Yandroid_neB,             EL_EMC_ANDROID_RIGHT_UP         },
4990     { Yandroid_e,               EL_EMC_ANDROID_RIGHT            },
4991     { Yandroid_eB,              EL_EMC_ANDROID_RIGHT            },
4992     { Yandroid_se,              EL_EMC_ANDROID_RIGHT_DOWN       },
4993     { Yandroid_seB,             EL_EMC_ANDROID_RIGHT_DOWN       },
4994     { Yandroid_s,               EL_EMC_ANDROID_DOWN             },
4995     { Yandroid_sB,              EL_EMC_ANDROID_DOWN             },
4996     { Yandroid_sw,              EL_EMC_ANDROID_LEFT_DOWN        },
4997     { Yandroid_swB,             EL_EMC_ANDROID_LEFT_DOWN        },
4998     { Yandroid_w,               EL_EMC_ANDROID_LEFT             },
4999     { Yandroid_wB,              EL_EMC_ANDROID_LEFT             },
5000     { Yandroid_nw,              EL_EMC_ANDROID_LEFT_UP          },
5001     { Yandroid_nwB,             EL_EMC_ANDROID_LEFT_UP          },
5002     { Xspring,                  EL_SPRING                       },
5003     { Xspring_pause,            EL_SPRING                       },
5004     { Xspring_e,                EL_SPRING                       },
5005     { Xspring_w,                EL_SPRING                       },
5006     { Xspring_fall,             EL_SPRING                       },
5007     { Yspring_s,                EL_SPRING                       },
5008     { Yspring_sB,               EL_SPRING                       },
5009     { Yspring_e,                EL_SPRING                       },
5010     { Yspring_eB,               EL_SPRING                       },
5011     { Yspring_w,                EL_SPRING                       },
5012     { Yspring_wB,               EL_SPRING                       },
5013     { Yspring_kill_e,           EL_SPRING                       },
5014     { Yspring_kill_eB,          EL_SPRING                       },
5015     { Yspring_kill_w,           EL_SPRING                       },
5016     { Yspring_kill_wB,          EL_SPRING                       },
5017     { Xeater_n,                 EL_YAMYAM                       },
5018     { Xeater_e,                 EL_YAMYAM                       },
5019     { Xeater_w,                 EL_YAMYAM                       },
5020     { Xeater_s,                 EL_YAMYAM                       },
5021     { Yeater_n,                 EL_YAMYAM                       },
5022     { Yeater_nB,                EL_YAMYAM                       },
5023     { Yeater_e,                 EL_YAMYAM                       },
5024     { Yeater_eB,                EL_YAMYAM                       },
5025     { Yeater_s,                 EL_YAMYAM                       },
5026     { Yeater_sB,                EL_YAMYAM                       },
5027     { Yeater_w,                 EL_YAMYAM                       },
5028     { Yeater_wB,                EL_YAMYAM                       },
5029     { Yeater_stone,             EL_ROCK                         },
5030     { Yeater_spring,            EL_SPRING                       },
5031     { Xalien,                   EL_ROBOT                        },
5032     { Xalien_pause,             EL_ROBOT                        },
5033     { Yalien_n,                 EL_ROBOT                        },
5034     { Yalien_nB,                EL_ROBOT                        },
5035     { Yalien_e,                 EL_ROBOT                        },
5036     { Yalien_eB,                EL_ROBOT                        },
5037     { Yalien_s,                 EL_ROBOT                        },
5038     { Yalien_sB,                EL_ROBOT                        },
5039     { Yalien_w,                 EL_ROBOT                        },
5040     { Yalien_wB,                EL_ROBOT                        },
5041     { Yalien_stone,             EL_ROCK                         },
5042     { Yalien_spring,            EL_SPRING                       },
5043     { Xemerald,                 EL_EMERALD                      },
5044     { Xemerald_pause,           EL_EMERALD                      },
5045     { Xemerald_fall,            EL_EMERALD                      },
5046     { Xemerald_shine,           EL_EMERALD                      },
5047     { Yemerald_s,               EL_EMERALD                      },
5048     { Yemerald_sB,              EL_EMERALD                      },
5049     { Yemerald_e,               EL_EMERALD                      },
5050     { Yemerald_eB,              EL_EMERALD                      },
5051     { Yemerald_w,               EL_EMERALD                      },
5052     { Yemerald_wB,              EL_EMERALD                      },
5053     { Yemerald_eat,             EL_EMERALD                      },
5054     { Yemerald_stone,           EL_ROCK                         },
5055     { Xdiamond,                 EL_DIAMOND                      },
5056     { Xdiamond_pause,           EL_DIAMOND                      },
5057     { Xdiamond_fall,            EL_DIAMOND                      },
5058     { Xdiamond_shine,           EL_DIAMOND                      },
5059     { Ydiamond_s,               EL_DIAMOND                      },
5060     { Ydiamond_sB,              EL_DIAMOND                      },
5061     { Ydiamond_e,               EL_DIAMOND                      },
5062     { Ydiamond_eB,              EL_DIAMOND                      },
5063     { Ydiamond_w,               EL_DIAMOND                      },
5064     { Ydiamond_wB,              EL_DIAMOND                      },
5065     { Ydiamond_eat,             EL_DIAMOND                      },
5066     { Ydiamond_stone,           EL_ROCK                         },
5067     { Xdrip_fall,               EL_AMOEBA_DROP                  },
5068     { Xdrip_stretch,            EL_AMOEBA_DROP                  },
5069     { Xdrip_stretchB,           EL_AMOEBA_DROP                  },
5070     { Xdrip_eat,                EL_AMOEBA_DROP                  },
5071     { Ydrip_s1,                 EL_AMOEBA_DROP                  },
5072     { Ydrip_s1B,                EL_AMOEBA_DROP                  },
5073     { Ydrip_s2,                 EL_AMOEBA_DROP                  },
5074     { Ydrip_s2B,                EL_AMOEBA_DROP                  },
5075     { Xbomb,                    EL_BOMB                         },
5076     { Xbomb_pause,              EL_BOMB                         },
5077     { Xbomb_fall,               EL_BOMB                         },
5078     { Ybomb_s,                  EL_BOMB                         },
5079     { Ybomb_sB,                 EL_BOMB                         },
5080     { Ybomb_e,                  EL_BOMB                         },
5081     { Ybomb_eB,                 EL_BOMB                         },
5082     { Ybomb_w,                  EL_BOMB                         },
5083     { Ybomb_wB,                 EL_BOMB                         },
5084     { Ybomb_eat,                EL_BOMB                         },
5085     { Xballoon,                 EL_BALLOON                      },
5086     { Yballoon_n,               EL_BALLOON                      },
5087     { Yballoon_nB,              EL_BALLOON                      },
5088     { Yballoon_e,               EL_BALLOON                      },
5089     { Yballoon_eB,              EL_BALLOON                      },
5090     { Yballoon_s,               EL_BALLOON                      },
5091     { Yballoon_sB,              EL_BALLOON                      },
5092     { Yballoon_w,               EL_BALLOON                      },
5093     { Yballoon_wB,              EL_BALLOON                      },
5094     { Xgrass,                   EL_SAND                         },
5095     { Ygrass_nB,                EL_SAND                         },
5096     { Ygrass_eB,                EL_SAND                         },
5097     { Ygrass_sB,                EL_SAND                         },
5098     { Ygrass_wB,                EL_SAND                         },
5099     { Xdirt,                    EL_SAND                         },
5100     { Ydirt_nB,                 EL_SAND                         },
5101     { Ydirt_eB,                 EL_SAND                         },
5102     { Ydirt_sB,                 EL_SAND                         },
5103     { Ydirt_wB,                 EL_SAND                         },
5104     { Xacid_ne,                 EL_ACID_POOL_TOPRIGHT           },
5105     { Xacid_se,                 EL_ACID_POOL_BOTTOMRIGHT        },
5106     { Xacid_s,                  EL_ACID_POOL_BOTTOM             },
5107     { Xacid_sw,                 EL_ACID_POOL_BOTTOMLEFT         },
5108     { Xacid_nw,                 EL_ACID_POOL_TOPLEFT            },
5109     { Xacid_1,                  EL_ACID                         },
5110     { Xacid_2,                  EL_ACID                         },
5111     { Xacid_3,                  EL_ACID                         },
5112     { Xacid_4,                  EL_ACID                         },
5113     { Xacid_5,                  EL_ACID                         },
5114     { Xacid_6,                  EL_ACID                         },
5115     { Xacid_7,                  EL_ACID                         },
5116     { Xacid_8,                  EL_ACID                         },
5117     { Xball_1,                  EL_EMC_MAGIC_BALL               },
5118     { Xball_1B,                 EL_EMC_MAGIC_BALL               },
5119     { Xball_2,                  EL_EMC_MAGIC_BALL               },
5120     { Xball_2B,                 EL_EMC_MAGIC_BALL               },
5121     { Yball_eat,                EL_EMC_MAGIC_BALL               },
5122     { Xgrow_ns,                 EL_EMC_GROW                     },
5123     { Ygrow_ns_eat,             EL_EMC_GROW                     },
5124     { Xgrow_ew,                 EL_EMC_GROW                     },
5125     { Ygrow_ew_eat,             EL_EMC_GROW                     },
5126     { Xwonderwall,              EL_MAGIC_WALL                   },
5127     { XwonderwallB,             EL_MAGIC_WALL                   },
5128     { Xamoeba_1,                EL_AMOEBA_WET                   },
5129     { Xamoeba_2,                EL_AMOEBA_WET                   },
5130     { Xamoeba_3,                EL_AMOEBA_WET                   },
5131     { Xamoeba_4,                EL_AMOEBA_WET                   },
5132     { Xamoeba_5,                EL_AMOEBA_WET                   },
5133     { Xamoeba_6,                EL_AMOEBA_WET                   },
5134     { Xamoeba_7,                EL_AMOEBA_WET                   },
5135     { Xamoeba_8,                EL_AMOEBA_WET                   },
5136     { Xdoor_1,                  EL_EM_GATE_1                    },
5137     { Xdoor_2,                  EL_EM_GATE_2                    },
5138     { Xdoor_3,                  EL_EM_GATE_3                    },
5139     { Xdoor_4,                  EL_EM_GATE_4                    },
5140     { Xdoor_5,                  EL_EMC_GATE_5                   },
5141     { Xdoor_6,                  EL_EMC_GATE_6                   },
5142     { Xdoor_7,                  EL_EMC_GATE_7                   },
5143     { Xdoor_8,                  EL_EMC_GATE_8                   },
5144     { Xkey_1,                   EL_EM_KEY_1                     },
5145     { Xkey_2,                   EL_EM_KEY_2                     },
5146     { Xkey_3,                   EL_EM_KEY_3                     },
5147     { Xkey_4,                   EL_EM_KEY_4                     },
5148     { Xkey_5,                   EL_EMC_KEY_5                    },
5149     { Xkey_6,                   EL_EMC_KEY_6                    },
5150     { Xkey_7,                   EL_EMC_KEY_7                    },
5151     { Xkey_8,                   EL_EMC_KEY_8                    },
5152     { Xwind_n,                  EL_BALLOON_SWITCH_UP            },
5153     { Xwind_e,                  EL_BALLOON_SWITCH_RIGHT         },
5154     { Xwind_s,                  EL_BALLOON_SWITCH_DOWN          },
5155     { Xwind_w,                  EL_BALLOON_SWITCH_LEFT          },
5156     { Xwind_nesw,               EL_BALLOON_SWITCH_ANY           },
5157     { Xwind_stop,               EL_BALLOON_SWITCH_NONE          },
5158     { Xexit,                    EL_EXIT_CLOSED                  },
5159     { Xexit_1,                  EL_EXIT_OPEN                    },
5160     { Xexit_2,                  EL_EXIT_OPEN                    },
5161     { Xexit_3,                  EL_EXIT_OPEN                    },
5162     { Xdynamite,                EL_DYNAMITE                     },
5163     { Ydynamite_eat,            EL_DYNAMITE                     },
5164     { Xdynamite_1,              EL_DYNAMITE_ACTIVE              },
5165     { Xdynamite_2,              EL_DYNAMITE_ACTIVE              },
5166     { Xdynamite_3,              EL_DYNAMITE_ACTIVE              },
5167     { Xdynamite_4,              EL_DYNAMITE_ACTIVE              },
5168     { Xbumper,                  EL_EMC_BUMPER                   },
5169     { XbumperB,                 EL_EMC_BUMPER                   },
5170     { Xwheel,                   EL_ROBOT_WHEEL                  },
5171     { XwheelB,                  EL_ROBOT_WHEEL                  },
5172     { Xswitch,                  EL_UNKNOWN                      },
5173     { XswitchB,                 EL_UNKNOWN                      },
5174     { Xsand,                    EL_QUICKSAND_EMPTY              },
5175     { Xsand_stone,              EL_QUICKSAND_FULL               },
5176     { Xsand_stonein_1,          EL_QUICKSAND_FULL               },
5177     { Xsand_stonein_2,          EL_QUICKSAND_FULL               },
5178     { Xsand_stonein_3,          EL_QUICKSAND_FULL               },
5179     { Xsand_stonein_4,          EL_QUICKSAND_FULL               },
5180     { Xsand_stonesand_1,        EL_QUICKSAND_FULL               },
5181     { Xsand_stonesand_2,        EL_QUICKSAND_FULL               },
5182     { Xsand_stonesand_3,        EL_QUICKSAND_FULL               },
5183     { Xsand_stonesand_4,        EL_QUICKSAND_FULL               },
5184     { Xsand_stoneout_1,         EL_QUICKSAND_FULL               },
5185     { Xsand_stoneout_2,         EL_QUICKSAND_FULL               },
5186     { Xsand_sandstone_1,        EL_QUICKSAND_FULL               },
5187     { Xsand_sandstone_2,        EL_QUICKSAND_FULL               },
5188     { Xsand_sandstone_3,        EL_QUICKSAND_FULL               },
5189     { Xsand_sandstone_4,        EL_QUICKSAND_FULL               },
5190     { Xplant,                   EL_EMC_PLANT                    },
5191     { Yplant,                   EL_EMC_PLANT                    },
5192     { Xlenses,                  EL_EMC_LENSES                   },
5193     { Xmagnify,                 EL_EMC_MAGNIFIER                },
5194     { Xdripper,                 EL_UNKNOWN                      },
5195     { XdripperB,                EL_UNKNOWN                      },
5196     { Xfake_blank,              EL_INVISIBLE_WALL               },
5197     { Xfake_blankB,             EL_INVISIBLE_WALL               },
5198     { Xfake_grass,              EL_INVISIBLE_SAND               },
5199     { Xfake_grassB,             EL_INVISIBLE_SAND               },
5200     { Xfake_door_1,             EL_EM_GATE_1_GRAY               },
5201     { Xfake_door_2,             EL_EM_GATE_2_GRAY               },
5202     { Xfake_door_3,             EL_EM_GATE_3_GRAY               },
5203     { Xfake_door_4,             EL_EM_GATE_4_GRAY               },
5204     { Xfake_door_5,             EL_EMC_GATE_5_GRAY              },
5205     { Xfake_door_6,             EL_EMC_GATE_6_GRAY              },
5206     { Xfake_door_7,             EL_EMC_GATE_7_GRAY              },
5207     { Xfake_door_8,             EL_EMC_GATE_8_GRAY              },
5208     { Xsteel_1,                 EL_STEELWALL                    },
5209     { Xsteel_2,                 EL_UNKNOWN                      },
5210     { Xsteel_3,                 EL_EMC_STEELWALL_1              },
5211     { Xsteel_4,                 EL_UNKNOWN                      },
5212     { Xwall_1,                  EL_WALL                         },
5213     { Xwall_2,                  EL_UNKNOWN                      },
5214     { Xwall_3,                  EL_UNKNOWN                      },
5215     { Xwall_4,                  EL_UNKNOWN                      },
5216     { Xround_wall_1,            EL_WALL_SLIPPERY                },
5217     { Xround_wall_2,            EL_UNKNOWN                      },
5218     { Xround_wall_3,            EL_UNKNOWN                      },
5219     { Xround_wall_4,            EL_UNKNOWN                      },
5220     { Xdecor_1,                 EL_UNKNOWN                      },
5221     { Xdecor_2,                 EL_EMC_WALL_6                   },
5222     { Xdecor_3,                 EL_EMC_WALL_4                   },
5223     { Xdecor_4,                 EL_EMC_WALL_5                   },
5224     { Xdecor_5,                 EL_EMC_WALL_7                   },
5225     { Xdecor_6,                 EL_EMC_WALL_8                   },
5226     { Xdecor_7,                 EL_UNKNOWN                      },
5227     { Xdecor_8,                 EL_EMC_WALL_1                   },
5228     { Xdecor_9,                 EL_EMC_WALL_2                   },
5229     { Xdecor_10,                EL_EMC_WALL_3                   },
5230     { Xdecor_11,                EL_UNKNOWN                      },
5231     { Xdecor_12,                EL_UNKNOWN                      },
5232     { Xalpha_0,                 EL_CHAR('0')                    },
5233     { Xalpha_1,                 EL_CHAR('1')                    },
5234     { Xalpha_2,                 EL_CHAR('2')                    },
5235     { Xalpha_3,                 EL_CHAR('3')                    },
5236     { Xalpha_4,                 EL_CHAR('4')                    },
5237     { Xalpha_5,                 EL_CHAR('5')                    },
5238     { Xalpha_6,                 EL_CHAR('6')                    },
5239     { Xalpha_7,                 EL_CHAR('7')                    },
5240     { Xalpha_8,                 EL_CHAR('8')                    },
5241     { Xalpha_9,                 EL_CHAR('9')                    },
5242     { Xalpha_excla,             EL_CHAR('!')                    },
5243     { Xalpha_quote,             EL_CHAR('"')                    },
5244     { Xalpha_comma,             EL_CHAR(',')                    },
5245     { Xalpha_minus,             EL_CHAR('-')                    },
5246     { Xalpha_perio,             EL_CHAR('.')                    },
5247     { Xalpha_colon,             EL_CHAR(':')                    },
5248     { Xalpha_quest,             EL_CHAR('?')                    },
5249     { Xalpha_a,                 EL_CHAR('A')                    },
5250     { Xalpha_b,                 EL_CHAR('B')                    },
5251     { Xalpha_c,                 EL_CHAR('C')                    },
5252     { Xalpha_d,                 EL_CHAR('D')                    },
5253     { Xalpha_e,                 EL_CHAR('E')                    },
5254     { Xalpha_f,                 EL_CHAR('F')                    },
5255     { Xalpha_g,                 EL_CHAR('G')                    },
5256     { Xalpha_h,                 EL_CHAR('H')                    },
5257     { Xalpha_i,                 EL_CHAR('I')                    },
5258     { Xalpha_j,                 EL_CHAR('J')                    },
5259     { Xalpha_k,                 EL_CHAR('K')                    },
5260     { Xalpha_l,                 EL_CHAR('L')                    },
5261     { Xalpha_m,                 EL_CHAR('M')                    },
5262     { Xalpha_n,                 EL_CHAR('N')                    },
5263     { Xalpha_o,                 EL_CHAR('O')                    },
5264     { Xalpha_p,                 EL_CHAR('P')                    },
5265     { Xalpha_q,                 EL_CHAR('Q')                    },
5266     { Xalpha_r,                 EL_CHAR('R')                    },
5267     { Xalpha_s,                 EL_CHAR('S')                    },
5268     { Xalpha_t,                 EL_CHAR('T')                    },
5269     { Xalpha_u,                 EL_CHAR('U')                    },
5270     { Xalpha_v,                 EL_CHAR('V')                    },
5271     { Xalpha_w,                 EL_CHAR('W')                    },
5272     { Xalpha_x,                 EL_CHAR('X')                    },
5273     { Xalpha_y,                 EL_CHAR('Y')                    },
5274     { Xalpha_z,                 EL_CHAR('Z')                    },
5275     { Xalpha_arrow_e,           EL_CHAR('>')                    },
5276     { Xalpha_arrow_w,           EL_CHAR('<')                    },
5277     { Xalpha_copyr,             EL_CHAR('©')                    },
5278
5279     { Zplayer,                  EL_PLAYER_1                     },
5280
5281     { ZBORDER,                  EL_EMC_LEVEL_BORDER             },
5282
5283     { -1,                       -1                              }
5284   };
5285
5286   if (!mapping_initialized)
5287   {
5288     int i;
5289
5290     /* return "EL_UNKNOWN" for all undefined elements in mapping array */
5291     for (i = 0; i < TILE_MAX; i++)
5292       mapping_EM_to_RND[i] = EL_UNKNOWN;
5293
5294     for (i = 0; mapping_EM_to_RND_list[i].element_em != -1; i++)
5295       mapping_EM_to_RND[mapping_EM_to_RND_list[i].element_em] =
5296         mapping_EM_to_RND_list[i].element_rnd;
5297
5298     mapping_initialized = TRUE;
5299   }
5300
5301   if (element_em >= 0 && element_em < TILE_MAX)
5302     return mapping_EM_to_RND[element_em];
5303
5304   Error(ERR_WARN, "invalid EM level element %d", element_em);
5305
5306   return EL_UNKNOWN;
5307 }
5308
5309 #endif
5310
5311 int get_next_element(int element)
5312 {
5313   switch(element)
5314   {
5315     case EL_QUICKSAND_FILLING:          return EL_QUICKSAND_FULL;
5316     case EL_QUICKSAND_EMPTYING:         return EL_QUICKSAND_EMPTY;
5317     case EL_MAGIC_WALL_FILLING:         return EL_MAGIC_WALL_FULL;
5318     case EL_MAGIC_WALL_EMPTYING:        return EL_MAGIC_WALL_ACTIVE;
5319     case EL_BD_MAGIC_WALL_FILLING:      return EL_BD_MAGIC_WALL_FULL;
5320     case EL_BD_MAGIC_WALL_EMPTYING:     return EL_BD_MAGIC_WALL_ACTIVE;
5321     case EL_AMOEBA_DROPPING:            return EL_AMOEBA_WET;
5322
5323     default:                            return element;
5324   }
5325 }
5326
5327 int el_act_dir2img(int element, int action, int direction)
5328 {
5329   element = GFX_ELEMENT(element);
5330   direction = MV_DIR_BIT(direction);    /* default: MV_NO_MOVING => MV_DOWN */
5331
5332   return element_info[element].direction_graphic[action][direction];
5333 }
5334
5335 static int el_act_dir2crm(int element, int action, int direction)
5336 {
5337   element = GFX_ELEMENT(element);
5338   direction = MV_DIR_BIT(direction);    /* default: MV_NO_MOVING => MV_DOWN */
5339
5340   return element_info[element].direction_crumbled[action][direction];
5341 }
5342
5343 int el_act2img(int element, int action)
5344 {
5345   element = GFX_ELEMENT(element);
5346
5347   return element_info[element].graphic[action];
5348 }
5349
5350 int el_act2crm(int element, int action)
5351 {
5352   element = GFX_ELEMENT(element);
5353
5354   return element_info[element].crumbled[action];
5355 }
5356
5357 int el_dir2img(int element, int direction)
5358 {
5359   element = GFX_ELEMENT(element);
5360
5361   return el_act_dir2img(element, ACTION_DEFAULT, direction);
5362 }
5363
5364 int el2baseimg(int element)
5365 {
5366   return element_info[element].graphic[ACTION_DEFAULT];
5367 }
5368
5369 int el2img(int element)
5370 {
5371   element = GFX_ELEMENT(element);
5372
5373   return element_info[element].graphic[ACTION_DEFAULT];
5374 }
5375
5376 int el2edimg(int element)
5377 {
5378   element = GFX_ELEMENT(element);
5379
5380   return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
5381 }
5382
5383 int el2preimg(int element)
5384 {
5385   element = GFX_ELEMENT(element);
5386
5387   return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
5388 }
5389
5390 int getGameFrameDelay_EM(int native_em_game_frame_delay)
5391 {
5392   return (GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
5393           GameFrameDelay);
5394 }
5395
5396 unsigned int InitRND(long seed)
5397 {
5398   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
5399     return InitEngineRND_EM(seed);
5400   else
5401     return InitEngineRND(seed);
5402 }
5403
5404 void InitGraphicInfo_EM(void)
5405 {
5406   int mapping_EM_to_RND_element[TILE_MAX];
5407   int mapping_EM_to_RND_action[TILE_MAX];
5408   int mapping_EM_to_RND_direction[TILE_MAX];
5409   boolean mapping_EM_to_RND_backside[TILE_MAX];
5410   int i, j;
5411
5412   /* return "EL_UNKNOWN" for all undefined elements in mapping array */
5413   for (i = 0; i < TILE_MAX; i++)
5414   {
5415     mapping_EM_to_RND_element[i] = EL_UNKNOWN;
5416     mapping_EM_to_RND_backside[i] = FALSE;
5417     mapping_EM_to_RND_action[i] = ACTION_DEFAULT;
5418     mapping_EM_to_RND_direction[i] = MV_NO_MOVING;
5419   }
5420
5421   for (i = 0; mapping_EM_to_RND_list[i].element_em != -1; i++)
5422   {
5423     int e = mapping_EM_to_RND_list[i].element_em;
5424
5425     mapping_EM_to_RND_element[e] = mapping_EM_to_RND_list[i].element_rnd;
5426     mapping_EM_to_RND_backside[e] = mapping_EM_to_RND_list[i].is_backside;
5427
5428     if (mapping_EM_to_RND_list[i].action != -1)
5429       mapping_EM_to_RND_action[e] = mapping_EM_to_RND_list[i].action;
5430
5431     if (mapping_EM_to_RND_list[i].direction != -1)
5432       mapping_EM_to_RND_direction[e] = 1<< mapping_EM_to_RND_list[i].direction;
5433   }
5434
5435   for (i = 0; i < TILE_MAX; i++)
5436   {
5437     int element = mapping_EM_to_RND_element[i];
5438     int action = mapping_EM_to_RND_action[i];
5439     int direction = mapping_EM_to_RND_direction[i];
5440     int backside = mapping_EM_to_RND_backside[i];
5441     boolean action_removing = (action == ACTION_DIGGING ||
5442                                action == ACTION_SNAPPING ||
5443                                action == ACTION_COLLECTING);
5444     boolean action_exploding = ((action == ACTION_EXPLODING ||
5445                                  action == ACTION_SMASHED_BY_ROCK ||
5446                                  action == ACTION_SMASHED_BY_SPRING) &&
5447                                 element != EL_DIAMOND);
5448     boolean action_active = (action == ACTION_ACTIVE);
5449     boolean action_other = (action == ACTION_OTHER);
5450
5451     for (j = 0; j < 8; j++)
5452     {
5453       int effective_element = (j < 7 ? element :
5454                                i == Ynut_sB ? element :
5455                                i == Xdrip_stretch ? element :
5456                                i == Xdrip_stretchB ? element :
5457                                i == Ydrip_s1 ? element :
5458                                i == Ydrip_s1B ? element :
5459                                i == Xball_1B ? element :
5460                                i == Xball_2 ? element :
5461                                i == Xball_2B ? element :
5462                                i == Yball_eat ? element :
5463                                i == Yspring_kill_e ? EL_SPRING :
5464                                i == Yspring_kill_w ? EL_SPRING :
5465                                i == Yemerald_stone ? EL_EMERALD :
5466                                i == Ydiamond_stone ? EL_ROCK :
5467                                backside ? EL_EMPTY :
5468                                action_removing ? EL_EMPTY :
5469                                element);
5470       int effective_action = (j < 7 ? action :
5471                               i == Ynut_sB ? action :
5472                               i == Xdrip_stretch ? action :
5473                               i == Xdrip_stretchB ? action :
5474                               i == Ydrip_s1 ? action :
5475                               i == Ydrip_s1B ? action :
5476                               i == Xball_1B ? action :
5477                               i == Xball_2 ? action :
5478                               i == Xball_2B ? action :
5479                               i == Yball_eat ? action :
5480                               i == Xsand_stonein_1 ? action :
5481                               i == Xsand_stonein_2 ? action :
5482                               i == Xsand_stonein_3 ? action :
5483                               i == Xsand_stonein_4 ? action :
5484                               i == Xsand_stoneout_1 ? action :
5485                               i == Xsand_stoneout_2 ? action :
5486                               i == Xboom_android ? ACTION_EXPLODING :
5487                               action_exploding ? ACTION_EXPLODING :
5488                               action_active ? action :
5489                               action_other ? action :
5490                               ACTION_DEFAULT);
5491       int graphic = (direction == MV_NO_MOVING ?
5492                      el_act2img(effective_element, effective_action) :
5493                      el_act_dir2img(effective_element, effective_action,
5494                                     direction));
5495       struct GraphicInfo *g = &graphic_info[graphic];
5496       struct GraphicInfo_EM *g_em = &graphic_info_em[i][7 - j];
5497       Bitmap *src_bitmap;
5498       int src_x, src_y;
5499       int sync_frame = (i == Xdrip_stretch ? 7 :
5500                         i == Xdrip_stretchB ? 7 :
5501                         i == Ydrip_s2 ? j + 8 :
5502                         i == Ydrip_s2B ? j + 8 :
5503                         i == Xacid_1 ? 0 :
5504                         i == Xacid_2 ? 1 :
5505                         i == Xacid_3 ? 2 :
5506                         i == Xacid_4 ? 3 :
5507                         i == Xacid_5 ? 4 :
5508                         i == Xacid_6 ? 5 :
5509                         i == Xacid_7 ? 6 :
5510                         i == Xacid_8 ? 7 :
5511                         i == Xball_2 ? 7 :
5512                         i == Xball_2B ? j + 8 :
5513                         i == Yball_eat ? j + 1 :
5514                         i == Xamoeba_1 ? 0 :
5515                         i == Xamoeba_2 ? 1 :
5516                         i == Xamoeba_3 ? 2 :
5517                         i == Xamoeba_4 ? 3 :
5518                         i == Xamoeba_5 ? 0 :
5519                         i == Xamoeba_6 ? 1 :
5520                         i == Xamoeba_7 ? 2 :
5521                         i == Xamoeba_8 ? 3 :
5522                         i == Xexit_2 ? j + 8 :
5523                         i == Xexit_3 ? j + 16 :
5524                         i == Xdynamite_1 ? 0 :
5525                         i == Xdynamite_2 ? 2 :
5526                         i == Xdynamite_3 ? 4 :
5527                         i == Xdynamite_4 ? 6 :
5528                         i == Xsand_stonein_1 ? j + 1 :
5529                         i == Xsand_stonein_2 ? j + 9 :
5530                         i == Xsand_stonein_3 ? j + 17 :
5531                         i == Xsand_stonein_4 ? j + 25 :
5532                         i == Xsand_stoneout_1 && j == 0 ? 1 :
5533                         i == Xsand_stoneout_1 && j == 1 ? 1 :
5534                         i == Xsand_stoneout_1 && j == 2 ? 2 :
5535                         i == Xsand_stoneout_1 && j == 3 ? 4 :
5536                         i == Xsand_stoneout_1 && j == 4 ? 4 :
5537                         i == Xsand_stoneout_1 && j == 5 ? 6 :
5538                         i == Xsand_stoneout_1 && j == 6 ? 8 :
5539                         i == Xsand_stoneout_1 && j == 7 ? 8 :
5540                         i == Xsand_stoneout_2 && j == 0 ? 10 :
5541                         i == Xsand_stoneout_2 && j == 1 ? 12 :
5542                         i == Xsand_stoneout_2 && j == 2 ? 14 :
5543                         i == Xsand_stoneout_2 && j == 3 ? 16 :
5544                         i == Xsand_stoneout_2 && j == 4 ? 18 :
5545                         i == Xsand_stoneout_2 && j == 5 ? 22 :
5546                         i == Xsand_stoneout_2 && j == 6 ? 26 :
5547                         i == Xsand_stoneout_2 && j == 7 ? 30 :
5548                         i == Xboom_bug && j == 2 ? 1 :
5549                         i == Xboom_bug && j == 3 ? 2 :
5550                         i == Xboom_bug && j == 4 ? 2 :
5551                         i == Xboom_bug && j == 5 ? 1 :
5552                         i == Xboom_bug && j == 6 ? 1 :
5553                         i == Xboom_bug && j == 7 ? 0 :
5554                         i == Xboom_bomb && j == 2 ? 1 :
5555                         i == Xboom_bomb && j == 3 ? 2 :
5556                         i == Xboom_bomb && j == 4 ? 2 :
5557                         i == Xboom_bomb && j == 5 ? 1 :
5558                         i == Xboom_bomb && j == 6 ? 1 :
5559                         i == Xboom_bomb && j == 7 ? 0 :
5560                         i == Xboom_android && j == 7 ? 3 :
5561                         i == Xboom_1 && j == 2 ? 1 :
5562                         i == Xboom_1 && j == 3 ? 2 :
5563                         i == Xboom_1 && j == 4 ? 2 :
5564                         i == Xboom_1 && j == 5 ? 3 :
5565                         i == Xboom_1 && j == 6 ? 3 :
5566                         i == Xboom_1 && j == 7 ? 4 :
5567                         i == Xboom_2 && j == 0 ? 4 :
5568                         i == Xboom_2 && j == 1 ? 4 :
5569                         i == Xboom_2 && j == 2 ? 5 :
5570                         i == Xboom_2 && j == 3 ? 5 :
5571                         i == Xboom_2 && j == 4 ? 5 :
5572                         i == Xboom_2 && j == 5 ? 6 :
5573                         effective_action != action ? 0 :
5574                         j);
5575 #if 0
5576       Bitmap *debug_bitmap = g_em->bitmap;
5577       int debug_src_x = g_em->src_x;
5578       int debug_src_y = g_em->src_y;
5579 #endif
5580
5581       int frame = getAnimationFrame(g->anim_frames,
5582                                     g->anim_delay,
5583                                     g->anim_mode,
5584                                     g->anim_start_frame,
5585                                     sync_frame);
5586
5587       getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
5588                           g->double_movement && backside);
5589
5590 #if 1
5591       g_em->bitmap = src_bitmap;
5592       g_em->src_x = src_x;
5593       g_em->src_y = src_y;
5594       g_em->src_offset_x = 0;
5595       g_em->src_offset_y = 0;
5596       g_em->dst_offset_x = 0;
5597       g_em->dst_offset_y = 0;
5598       g_em->width  = TILEX;
5599       g_em->height = TILEY;
5600 #endif
5601
5602 #if 1
5603       if (!g->double_movement && (effective_action == ACTION_FALLING ||
5604                                   effective_action == ACTION_MOVING ||
5605                                   effective_action == ACTION_PUSHING))
5606       {
5607         int move_dir =
5608           (effective_action == ACTION_FALLING ? MV_DOWN : direction);
5609         int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
5610         int dy = (move_dir == MV_UP   ? -1 : move_dir == MV_DOWN  ? 1 : 0);
5611         int cx = ABS(dx) * TILEX / 8;
5612         int cy = ABS(dy) * TILEY / 8;
5613
5614         if (backside)           /* tile where movement starts */
5615         {
5616           if (dx < 0 || dy < 0)
5617           {
5618             g_em->src_offset_x = cx * (j + 1);
5619             g_em->src_offset_y = cy * (j + 1);
5620           }
5621           else
5622           {
5623             g_em->dst_offset_x = cx * (j + 1);
5624             g_em->dst_offset_y = cy * (j + 1);
5625           }
5626
5627           g_em->width  = TILEX - cx * (j + 1);
5628           g_em->height = TILEY - cy * (j + 1);
5629         }
5630         else                    /* tile where movement ends */
5631         {
5632           if (dx < 0 || dy < 0)
5633           {
5634             g_em->dst_offset_x = cx * (7 - j);
5635             g_em->dst_offset_y = cy * (7 - j);
5636           }
5637           else
5638           {
5639             g_em->src_offset_x = cx * (7 - j);
5640             g_em->src_offset_y = cy * (7 - j);
5641           }
5642
5643           g_em->width  = TILEX - cx * (7 - j);
5644           g_em->height = TILEY - cy * (7 - j);
5645         }
5646       }
5647 #endif
5648
5649 #if 0
5650       if (g_em->bitmap != debug_bitmap ||
5651           g_em->src_x != debug_src_x ||
5652           g_em->src_y != debug_src_y ||
5653           g_em->src_offset_x != 0 ||
5654           g_em->src_offset_y != 0 ||
5655           g_em->dst_offset_x != 0 ||
5656           g_em->dst_offset_y != 0 ||
5657           g_em->width != TILEX ||
5658           g_em->height != TILEY)
5659       {
5660         static int last_i = -1;
5661
5662         if (i != last_i)
5663         {
5664           printf("\n");
5665
5666           last_i = i;
5667         }
5668
5669         printf("::: EMC GFX ERROR for element %d -> %d ('%s')",
5670                i, element, element_info[element].token_name);
5671
5672         if (element != effective_element)
5673           printf(" [%d ('%s')]",
5674                  effective_element,element_info[effective_element].token_name);
5675
5676         printf("\n");
5677
5678         if (g_em->bitmap != debug_bitmap)
5679           printf("    %d(%d): different bitmap!\n",
5680                  j, backside);
5681
5682         if (g_em->src_x != debug_src_x ||
5683             g_em->src_y != debug_src_y)
5684           printf("    frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
5685                  j, (backside ? 'B' : 'F'),
5686                  g_em->src_x, g_em->src_y,
5687                  g_em->src_x / 32, g_em->src_y / 32,
5688                  debug_src_x, debug_src_y,
5689                  debug_src_x / 32, debug_src_y / 32);
5690
5691         if (g_em->src_offset_x != 0 ||
5692             g_em->src_offset_y != 0 ||
5693             g_em->dst_offset_x != 0 ||
5694             g_em->dst_offset_y != 0)
5695           printf("    %d(%d): offsets %d,%d and %d,%d should be all 0\n",
5696                  j, backside,
5697                  g_em->src_offset_x, g_em->src_offset_y,
5698                  g_em->dst_offset_x, g_em->dst_offset_y);
5699
5700         if (g_em->width != TILEX ||
5701             g_em->height != TILEY)
5702           printf("    %d(%d): size %d,%d should be %d,%d\n",
5703                  j, backside,
5704                  g_em->width, g_em->height, TILEX, TILEY);
5705       }
5706 #endif
5707
5708     }
5709   }
5710
5711 #if 0
5712   exit(0);
5713 #endif
5714 }