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