rnd-20051127-3-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       DrawLevelField(jx, jy);
1885     }
1886   }
1887
1888   /* ----------------------------------------------------------------------- */
1889   /* draw player himself                                                     */
1890   /* ----------------------------------------------------------------------- */
1891
1892   graphic = getPlayerGraphic(player, move_dir);
1893
1894   /* in the case of changed player action or direction, prevent the current
1895      animation frame from being restarted for identical animations */
1896   if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic))
1897     player->Frame = last_player_frame;
1898
1899   frame = getGraphicAnimationFrame(graphic, player->Frame);
1900
1901   if (player->GfxPos)
1902   {
1903     if (move_dir == MV_LEFT || move_dir == MV_RIGHT)
1904       sxx = player->GfxPos;
1905     else
1906       syy = player->GfxPos;
1907   }
1908
1909   if (!setup.soft_scrolling && ScreenMovPos)
1910     sxx = syy = 0;
1911
1912   DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1913
1914   if (SHIELD_ON(player))
1915   {
1916     int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE :
1917                    IMG_SHIELD_NORMAL_ACTIVE);
1918     int frame = getGraphicAnimationFrame(graphic, -1);
1919
1920     DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING);
1921   }
1922
1923   /* ----------------------------------------------------------------------- */
1924   /* draw things the player is pushing, if needed                            */
1925   /* ----------------------------------------------------------------------- */
1926
1927 #if 0
1928   printf("::: %d, %d [%d, %d] [%d]\n",
1929          player->is_pushing, player_is_moving, player->GfxAction,
1930          player->is_moving, player_is_moving);
1931 #endif
1932
1933   if (player->is_pushing && player->is_moving)
1934   {
1935     int px = SCREENX(jx), py = SCREENY(jy);
1936     int pxx = (TILEX - ABS(sxx)) * dx;
1937     int pyy = (TILEY - ABS(syy)) * dy;
1938
1939     int graphic;
1940     int frame;
1941
1942     if (!IS_MOVING(jx, jy))             /* push movement already finished */
1943       element = Feld[next_jx][next_jy];
1944
1945     graphic = el_act_dir2img(element, ACTION_PUSHING, move_dir);
1946     frame = getGraphicAnimationFrame(graphic, player->StepFrame);
1947
1948     /* draw background element under pushed element (like the Sokoban field) */
1949     if (Back[next_jx][next_jy])
1950       DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]);
1951
1952     /* masked drawing is needed for EMC style (double) movement graphics */
1953     DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
1954   }
1955
1956   /* ----------------------------------------------------------------------- */
1957   /* draw things in front of player (active dynamite or dynabombs)           */
1958   /* ----------------------------------------------------------------------- */
1959
1960   if (IS_ACTIVE_BOMB(element))
1961   {
1962     graphic = el2img(element);
1963     frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
1964
1965     if (game.emulation == EMU_SUPAPLEX)
1966       DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
1967     else
1968       DrawGraphicThruMask(sx, sy, graphic, frame);
1969   }
1970
1971   if (player_is_moving && last_element == EL_EXPLOSION)
1972   {
1973     int graphic = el_act2img(GfxElement[last_jx][last_jy], ACTION_EXPLODING);
1974     int delay = (game.emulation == EMU_SUPAPLEX ? 3 : 2);
1975     int phase = ExplodePhase[last_jx][last_jy] - 1;
1976     int frame = getGraphicAnimationFrame(graphic, phase - delay);
1977
1978     if (phase >= delay)
1979       DrawGraphicThruMask(SCREENX(last_jx), SCREENY(last_jy), graphic, frame);
1980   }
1981
1982   /* ----------------------------------------------------------------------- */
1983   /* draw elements the player is just walking/passing through/under          */
1984   /* ----------------------------------------------------------------------- */
1985
1986   if (player_is_moving)
1987   {
1988     /* handle the field the player is leaving ... */
1989     if (IS_ACCESSIBLE_INSIDE(last_element))
1990       DrawLevelField(last_jx, last_jy);
1991     else if (IS_ACCESSIBLE_UNDER(last_element))
1992       DrawLevelFieldThruMask(last_jx, last_jy);
1993   }
1994
1995   /* do not redraw accessible elements if the player is just pushing them */
1996   if (!player_is_moving || !player->is_pushing)
1997   {
1998     /* ... and the field the player is entering */
1999     if (IS_ACCESSIBLE_INSIDE(element))
2000       DrawLevelField(jx, jy);
2001     else if (IS_ACCESSIBLE_UNDER(element))
2002       DrawLevelFieldThruMask(jx, jy);
2003   }
2004
2005   if (setup.direct_draw)
2006   {
2007     int dst_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX;
2008     int dst_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY;
2009     int x_size = TILEX * (1 + ABS(jx - last_jx));
2010     int y_size = TILEY * (1 + ABS(jy - last_jy));
2011
2012     BlitBitmap(drawto_field, window,
2013                dst_x, dst_y, x_size, y_size, dst_x, dst_y);
2014     SetDrawtoField(DRAW_DIRECT);
2015   }
2016
2017   MarkTileDirty(sx, sy);
2018 }
2019
2020 /* ------------------------------------------------------------------------- */
2021
2022 void WaitForEventToContinue()
2023 {
2024   boolean still_wait = TRUE;
2025
2026   /* simulate releasing mouse button over last gadget, if still pressed */
2027   if (button_status)
2028     HandleGadgets(-1, -1, 0);
2029
2030   button_status = MB_RELEASED;
2031
2032   while (still_wait)
2033   {
2034     if (PendingEvent())
2035     {
2036       Event event;
2037
2038       NextEvent(&event);
2039
2040       switch (event.type)
2041       {
2042         case EVENT_BUTTONPRESS:
2043         case EVENT_KEYPRESS:
2044           still_wait = FALSE;
2045           break;
2046
2047         case EVENT_KEYRELEASE:
2048           ClearPlayerAction();
2049           break;
2050
2051         default:
2052           HandleOtherEvents(&event);
2053           break;
2054       }
2055     }
2056     else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2057     {
2058       still_wait = FALSE;
2059     }
2060
2061     DoAnimation();
2062
2063     /* don't eat all CPU time */
2064     Delay(10);
2065   }
2066 }
2067
2068 #define MAX_REQUEST_LINES               13
2069 #define MAX_REQUEST_LINE_FONT1_LEN      7
2070 #define MAX_REQUEST_LINE_FONT2_LEN      10
2071
2072 boolean Request(char *text, unsigned int req_state)
2073 {
2074   int mx, my, ty, result = -1;
2075   unsigned int old_door_state;
2076   int last_game_status = game_status;   /* save current game status */
2077   int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
2078   int font_nr = FONT_TEXT_2;
2079   int max_word_len = 0;
2080   char *text_ptr;
2081
2082   for (text_ptr = text; *text_ptr; text_ptr++)
2083   {
2084     max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0);
2085
2086     if (max_word_len > MAX_REQUEST_LINE_FONT1_LEN)
2087     {
2088       max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN;
2089       font_nr = FONT_LEVEL_NUMBER;
2090
2091       break;
2092     }
2093   }
2094
2095   if (game_status == GAME_MODE_PLAYING &&
2096       level.game_engine_type == GAME_ENGINE_TYPE_EM)
2097     BlitScreenToBitmap_EM(backbuffer);
2098
2099   /* disable deactivated drawing when quick-loading level tape recording */
2100   if (tape.playing && tape.deactivate_display)
2101     TapeDeactivateDisplayOff(TRUE);
2102
2103   SetMouseCursor(CURSOR_DEFAULT);
2104
2105 #if defined(NETWORK_AVALIABLE)
2106   /* pause network game while waiting for request to answer */
2107   if (options.network &&
2108       game_status == GAME_MODE_PLAYING &&
2109       req_state & REQUEST_WAIT_FOR_INPUT)
2110     SendToServer_PausePlaying();
2111 #endif
2112
2113   old_door_state = GetDoorState();
2114
2115   /* simulate releasing mouse button over last gadget, if still pressed */
2116   if (button_status)
2117     HandleGadgets(-1, -1, 0);
2118
2119   UnmapAllGadgets();
2120
2121   if (old_door_state & DOOR_OPEN_1)
2122   {
2123     CloseDoor(DOOR_CLOSE_1);
2124
2125     /* save old door content */
2126     BlitBitmap(bitmap_db_door, bitmap_db_door,
2127                DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2128                DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1);
2129   }
2130
2131   SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2132
2133   /* clear door drawing field */
2134   DrawBackground(DX, DY, DXSIZE, DYSIZE);
2135
2136   /* force DOOR font on preview level */
2137   game_status = GAME_MODE_PSEUDO_DOOR;
2138
2139   /* write text for request */
2140   for (ty = 0; ty < MAX_REQUEST_LINES; ty++)
2141   {
2142     char text_line[max_request_line_len + 1];
2143     int tx, tl, tc = 0;
2144
2145     if (!*text)
2146       break;
2147
2148     for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++)
2149     {
2150       tc = *(text + tx);
2151       if (!tc || tc == ' ')
2152         break;
2153     }
2154
2155     if (!tl)
2156     { 
2157       text++; 
2158       ty--; 
2159       continue; 
2160     }
2161
2162     strncpy(text_line, text, tl);
2163     text_line[tl] = 0;
2164
2165     DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2,
2166              DY + 8 + ty * (getFontHeight(font_nr) + 2),
2167              text_line, font_nr);
2168
2169     text += tl + (tc == ' ' ? 1 : 0);
2170   }
2171
2172   game_status = last_game_status;       /* restore current game status */
2173
2174   if (req_state & REQ_ASK)
2175   {
2176     MapGadget(tool_gadget[TOOL_CTRL_ID_YES]);
2177     MapGadget(tool_gadget[TOOL_CTRL_ID_NO]);
2178   }
2179   else if (req_state & REQ_CONFIRM)
2180   {
2181     MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]);
2182   }
2183   else if (req_state & REQ_PLAYER)
2184   {
2185     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_1]);
2186     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_2]);
2187     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_3]);
2188     MapGadget(tool_gadget[TOOL_CTRL_ID_PLAYER_4]);
2189   }
2190
2191   /* copy request gadgets to door backbuffer */
2192   BlitBitmap(drawto, bitmap_db_door,
2193              DX, DY, DXSIZE, DYSIZE,
2194              DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2195
2196   OpenDoor(DOOR_OPEN_1);
2197
2198   if (!(req_state & REQUEST_WAIT_FOR_INPUT))
2199   {
2200     SetDrawBackgroundMask(REDRAW_FIELD);
2201
2202     return FALSE;
2203   }
2204
2205   if (game_status != GAME_MODE_MAIN)
2206     InitAnimation();
2207
2208   button_status = MB_RELEASED;
2209
2210   request_gadget_id = -1;
2211
2212   SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
2213
2214   while (result < 0)
2215   {
2216     if (PendingEvent())
2217     {
2218       Event event;
2219
2220       NextEvent(&event);
2221
2222       switch(event.type)
2223       {
2224         case EVENT_BUTTONPRESS:
2225         case EVENT_BUTTONRELEASE:
2226         case EVENT_MOTIONNOTIFY:
2227         {
2228           if (event.type == EVENT_MOTIONNOTIFY)
2229           {
2230             if (!PointerInWindow(window))
2231               continue; /* window and pointer are on different screens */
2232
2233             if (!button_status)
2234               continue;
2235
2236             motion_status = TRUE;
2237             mx = ((MotionEvent *) &event)->x;
2238             my = ((MotionEvent *) &event)->y;
2239           }
2240           else
2241           {
2242             motion_status = FALSE;
2243             mx = ((ButtonEvent *) &event)->x;
2244             my = ((ButtonEvent *) &event)->y;
2245             if (event.type == EVENT_BUTTONPRESS)
2246               button_status = ((ButtonEvent *) &event)->button;
2247             else
2248               button_status = MB_RELEASED;
2249           }
2250
2251           /* this sets 'request_gadget_id' */
2252           HandleGadgets(mx, my, button_status);
2253
2254           switch(request_gadget_id)
2255           {
2256             case TOOL_CTRL_ID_YES:
2257               result = TRUE;
2258               break;
2259             case TOOL_CTRL_ID_NO:
2260               result = FALSE;
2261               break;
2262             case TOOL_CTRL_ID_CONFIRM:
2263               result = TRUE | FALSE;
2264               break;
2265
2266             case TOOL_CTRL_ID_PLAYER_1:
2267               result = 1;
2268               break;
2269             case TOOL_CTRL_ID_PLAYER_2:
2270               result = 2;
2271               break;
2272             case TOOL_CTRL_ID_PLAYER_3:
2273               result = 3;
2274               break;
2275             case TOOL_CTRL_ID_PLAYER_4:
2276               result = 4;
2277               break;
2278
2279             default:
2280               break;
2281           }
2282
2283           break;
2284         }
2285
2286         case EVENT_KEYPRESS:
2287           switch(GetEventKey((KeyEvent *)&event, TRUE))
2288           {
2289             case KSYM_Return:
2290               result = 1;
2291               break;
2292
2293             case KSYM_Escape:
2294               result = 0;
2295               break;
2296
2297             default:
2298               break;
2299           }
2300           if (req_state & REQ_PLAYER)
2301             result = 0;
2302           break;
2303
2304         case EVENT_KEYRELEASE:
2305           ClearPlayerAction();
2306           break;
2307
2308         default:
2309           HandleOtherEvents(&event);
2310           break;
2311       }
2312     }
2313     else if (AnyJoystickButton() == JOY_BUTTON_NEW_PRESSED)
2314     {
2315       int joy = AnyJoystick();
2316
2317       if (joy & JOY_BUTTON_1)
2318         result = 1;
2319       else if (joy & JOY_BUTTON_2)
2320         result = 0;
2321     }
2322
2323     DoAnimation();
2324
2325     /* don't eat all CPU time */
2326     Delay(10);
2327   }
2328
2329   if (game_status != GAME_MODE_MAIN)
2330     StopAnimation();
2331
2332   UnmapToolButtons();
2333
2334   if (!(req_state & REQ_STAY_OPEN))
2335   {
2336     CloseDoor(DOOR_CLOSE_1);
2337
2338     if (((old_door_state & DOOR_OPEN_1) && !(req_state & REQ_STAY_CLOSED)) ||
2339         (req_state & REQ_REOPEN))
2340       OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
2341   }
2342
2343   RemapAllGadgets();
2344
2345   SetDrawBackgroundMask(REDRAW_FIELD);
2346
2347 #if defined(NETWORK_AVALIABLE)
2348   /* continue network game after request */
2349   if (options.network &&
2350       game_status == GAME_MODE_PLAYING &&
2351       req_state & REQUEST_WAIT_FOR_INPUT)
2352     SendToServer_ContinuePlaying();
2353 #endif
2354
2355   /* restore deactivated drawing when quick-loading level tape recording */
2356   if (tape.playing && tape.deactivate_display)
2357     TapeDeactivateDisplayOn();
2358
2359   return result;
2360 }
2361
2362 unsigned int OpenDoor(unsigned int door_state)
2363 {
2364   if (door_state & DOOR_COPY_BACK)
2365   {
2366     if (door_state & DOOR_OPEN_1)
2367       BlitBitmap(bitmap_db_door, bitmap_db_door,
2368                  DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE,
2369                  DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2370
2371     if (door_state & DOOR_OPEN_2)
2372       BlitBitmap(bitmap_db_door, bitmap_db_door,
2373                  DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY2, VXSIZE, VYSIZE,
2374                  DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2375
2376     door_state &= ~DOOR_COPY_BACK;
2377   }
2378
2379   return MoveDoor(door_state);
2380 }
2381
2382 unsigned int CloseDoor(unsigned int door_state)
2383 {
2384   unsigned int old_door_state = GetDoorState();
2385
2386   if (!(door_state & DOOR_NO_COPY_BACK))
2387   {
2388     if (old_door_state & DOOR_OPEN_1)
2389       BlitBitmap(backbuffer, bitmap_db_door,
2390                  DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
2391
2392     if (old_door_state & DOOR_OPEN_2)
2393       BlitBitmap(backbuffer, bitmap_db_door,
2394                  VX, VY, VXSIZE, VYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2);
2395
2396     door_state &= ~DOOR_NO_COPY_BACK;
2397   }
2398
2399   return MoveDoor(door_state);
2400 }
2401
2402 unsigned int GetDoorState()
2403 {
2404   return MoveDoor(DOOR_GET_STATE);
2405 }
2406
2407 unsigned int SetDoorState(unsigned int door_state)
2408 {
2409   return MoveDoor(door_state | DOOR_SET_STATE);
2410 }
2411
2412 unsigned int MoveDoor(unsigned int door_state)
2413 {
2414   static int door1 = DOOR_OPEN_1;
2415   static int door2 = DOOR_CLOSE_2;
2416   unsigned long door_delay = 0;
2417   unsigned long door_delay_value;
2418   int stepsize = 1;
2419
2420   if (door_state == DOOR_GET_STATE)
2421     return(door1 | door2);
2422
2423   if (door_state & DOOR_SET_STATE)
2424   {
2425     if (door_state & DOOR_ACTION_1)
2426       door1 = door_state & DOOR_ACTION_1;
2427     if (door_state & DOOR_ACTION_2)
2428       door2 = door_state & DOOR_ACTION_2;
2429
2430     return(door1 | door2);
2431   }
2432
2433   if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
2434     door_state &= ~DOOR_OPEN_1;
2435   else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
2436     door_state &= ~DOOR_CLOSE_1;
2437   if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
2438     door_state &= ~DOOR_OPEN_2;
2439   else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
2440     door_state &= ~DOOR_CLOSE_2;
2441
2442   door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay :
2443                       door_2.step_delay);
2444
2445   if (setup.quick_doors)
2446   {
2447     stepsize = 20;              /* must be choosen to always draw last frame */
2448     door_delay_value = 0;
2449   }
2450
2451   if (global.autoplay_leveldir)
2452   {
2453     door_state |= DOOR_NO_DELAY;
2454     door_state &= ~DOOR_CLOSE_ALL;
2455   }
2456
2457   if (door_state & DOOR_ACTION)
2458   {
2459     boolean door_1_done = !(door_state & DOOR_ACTION_1);
2460     boolean door_2_done = !(door_state & DOOR_ACTION_2);
2461     int start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
2462     int end = (door_state & DOOR_ACTION_1 &&
2463                door_1.anim_mode == ANIM_VERTICAL ? DYSIZE : DXSIZE);
2464     int x;
2465
2466     if (!(door_state & DOOR_NO_DELAY) && !setup.quick_doors)
2467     {
2468       /* opening door sound has priority over simultaneously closing door */
2469       if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2))
2470         PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE);
2471       else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2))
2472         PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE);
2473     }
2474
2475     for (x = start; x <= end && !(door_1_done && door_2_done); x += stepsize)
2476     {
2477       Bitmap *bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2478       GC gc = bitmap->stored_clip_gc;
2479
2480       if (door_state & DOOR_ACTION_1)
2481       {
2482         int a = MIN(x * door_1.step_offset, end);
2483         int i = (door_state & DOOR_OPEN_1 ? end - a : a);
2484
2485         if (x <= a)
2486         {
2487           BlitBitmap(bitmap_db_door, drawto,
2488                      DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1 + i / 2,
2489                      DXSIZE, DYSIZE - i / 2, DX, DY);
2490
2491           ClearRectangle(drawto, DX, DY + DYSIZE - i / 2, DXSIZE, i / 2);
2492         }
2493
2494         if (door_1.anim_mode == ANIM_HORIZONTAL && x <= DXSIZE)
2495         {
2496           int src1_x = DXSIZE,          src1_y = DOOR_GFX_PAGEY1;
2497           int dst1_x = DX + DXSIZE - i, dst1_y = DY;
2498           int src2_x = DXSIZE - i,      src2_y = DOOR_GFX_PAGEY1;
2499           int dst2_x = DX,              dst2_y = DY;
2500           int width = i, height = DYSIZE;
2501
2502           SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2503           BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2504                            dst1_x, dst1_y);
2505
2506           SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2507           BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2508                            dst2_x, dst2_y);
2509         }
2510         else if (door_1.anim_mode == ANIM_VERTICAL && x <= DYSIZE)
2511         {
2512           int src1_x = DXSIZE,          src1_y = DOOR_GFX_PAGEY1;
2513           int dst1_x = DX,              dst1_y = DY + DYSIZE - i;
2514           int src2_x = 0,               src2_y = DOOR_GFX_PAGEY1 + DYSIZE - i;
2515           int dst2_x = DX,              dst2_y = DY;
2516           int width = DXSIZE, height = i;
2517
2518           SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2519           BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2520                            dst1_x, dst1_y);
2521
2522           SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2523           BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2524                            dst2_x, dst2_y);
2525         }
2526         else if (x <= DXSIZE)   /* ANIM_DEFAULT */
2527         {
2528           int j = (door_1.anim_mode == ANIM_DEFAULT ? (DXSIZE - i) / 3 : 0);
2529
2530           SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2531           BlitBitmapMasked(bitmap, drawto,
2532                            DXSIZE, DOOR_GFX_PAGEY1, i, 77,
2533                            DX + DXSIZE - i, DY + j);
2534           BlitBitmapMasked(bitmap, drawto,
2535                            DXSIZE, DOOR_GFX_PAGEY1 + 140, i, 63,
2536                            DX + DXSIZE - i, DY + 140 + j);
2537           SetClipOrigin(bitmap, gc, DX - DXSIZE + i,
2538                         DY - (DOOR_GFX_PAGEY1 + j));
2539           BlitBitmapMasked(bitmap, drawto,
2540                            DXSIZE - i, DOOR_GFX_PAGEY1 + j, i, 77 - j,
2541                            DX, DY);
2542           BlitBitmapMasked(bitmap, drawto,
2543                            DXSIZE-i, DOOR_GFX_PAGEY1 + 140, i, 63,
2544                            DX, DY + 140 - j);
2545
2546           BlitBitmapMasked(bitmap, drawto,
2547                            DXSIZE - i, DOOR_GFX_PAGEY1 + 77, i, 63,
2548                            DX, DY + 77 - j);
2549           BlitBitmapMasked(bitmap, drawto,
2550                            DXSIZE - i, DOOR_GFX_PAGEY1 + 203, i, 77,
2551                            DX, DY + 203 - j);
2552           SetClipOrigin(bitmap, gc, DX - i, (DY + j) - DOOR_GFX_PAGEY1);
2553           BlitBitmapMasked(bitmap, drawto,
2554                            DXSIZE, DOOR_GFX_PAGEY1 + 77, i, 63,
2555                            DX + DXSIZE - i, DY + 77 + j);
2556           BlitBitmapMasked(bitmap, drawto,
2557                            DXSIZE, DOOR_GFX_PAGEY1 + 203, i, 77 - j,
2558                            DX + DXSIZE - i, DY + 203 + j);
2559         }
2560
2561         redraw_mask |= REDRAW_DOOR_1;
2562         door_1_done = (a == end);
2563       }
2564
2565       if (door_state & DOOR_ACTION_2)
2566       {
2567         int a = MIN(x * door_2.step_offset, VXSIZE);
2568         int i = (door_state & DOOR_OPEN_2 ? VXSIZE - a : a);
2569
2570         if (x <= VYSIZE)
2571         {
2572           BlitBitmap(bitmap_db_door, drawto,
2573                      DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY2 + i / 2,
2574                      VXSIZE, VYSIZE - i / 2, VX, VY);
2575
2576           ClearRectangle(drawto, VX, VY + VYSIZE - i / 2, VXSIZE, i / 2);
2577         }
2578
2579         if (door_2.anim_mode == ANIM_HORIZONTAL && x <= VXSIZE)
2580         {
2581           int src1_x = VXSIZE,          src1_y = DOOR_GFX_PAGEY2;
2582           int dst1_x = VX + VXSIZE - i, dst1_y = VY;
2583           int src2_x = VXSIZE - i,      src2_y = DOOR_GFX_PAGEY2;
2584           int dst2_x = VX,              dst2_y = VY;
2585           int width = i, height = VYSIZE;
2586
2587           SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2588           BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2589                            dst1_x, dst1_y);
2590
2591           SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2592           BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2593                            dst2_x, dst2_y);
2594         }
2595         else if (door_2.anim_mode == ANIM_VERTICAL && x <= VYSIZE)
2596         {
2597           int src1_x = VXSIZE,          src1_y = DOOR_GFX_PAGEY2;
2598           int dst1_x = VX,              dst1_y = VY + VYSIZE - i;
2599           int src2_x = 0,               src2_y = DOOR_GFX_PAGEY2 + VYSIZE - i;
2600           int dst2_x = VX,              dst2_y = VY;
2601           int width = VXSIZE, height = i;
2602
2603           SetClipOrigin(bitmap, gc, dst1_x - src1_x, dst1_y - src1_y);
2604           BlitBitmapMasked(bitmap, drawto, src1_x, src1_y, width, height,
2605                            dst1_x, dst1_y);
2606
2607           SetClipOrigin(bitmap, gc, dst2_x - src2_x, dst2_y - src2_y);
2608           BlitBitmapMasked(bitmap, drawto, src2_x, src2_y, width, height,
2609                            dst2_x, dst2_y);
2610         }
2611         else if (x <= VXSIZE)   /* ANIM_DEFAULT */
2612         {
2613           int j = (door_2.anim_mode == ANIM_DEFAULT ? (VXSIZE - i) / 3 : 0);
2614
2615           SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2616           BlitBitmapMasked(bitmap, drawto,
2617                            VXSIZE, DOOR_GFX_PAGEY2, i, VYSIZE / 2,
2618                            VX + VXSIZE - i, VY + j);
2619           SetClipOrigin(bitmap, gc,
2620                         VX - VXSIZE + i, VY - (DOOR_GFX_PAGEY2 + j));
2621           BlitBitmapMasked(bitmap, drawto,
2622                            VXSIZE - i, DOOR_GFX_PAGEY2 + j, i, VYSIZE / 2 - j,
2623                            VX, VY);
2624
2625           BlitBitmapMasked(bitmap, drawto,
2626                            VXSIZE - i, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2627                            i, VYSIZE / 2, VX, VY + VYSIZE / 2 - j);
2628           SetClipOrigin(bitmap, gc, VX - i, (VY + j) - DOOR_GFX_PAGEY2);
2629           BlitBitmapMasked(bitmap, drawto,
2630                            VXSIZE, DOOR_GFX_PAGEY2 + VYSIZE / 2,
2631                            i, VYSIZE / 2 - j,
2632                            VX + VXSIZE - i, VY + VYSIZE / 2 + j);
2633         }
2634
2635         redraw_mask |= REDRAW_DOOR_2;
2636         door_2_done = (a == VXSIZE);
2637       }
2638
2639       BackToFront();
2640
2641       if (game_status == GAME_MODE_MAIN)
2642         DoAnimation();
2643
2644       if (!(door_state & DOOR_NO_DELAY))
2645         WaitUntilDelayReached(&door_delay, door_delay_value);
2646     }
2647   }
2648
2649   if (door_state & DOOR_ACTION_1)
2650     door1 = door_state & DOOR_ACTION_1;
2651   if (door_state & DOOR_ACTION_2)
2652     door2 = door_state & DOOR_ACTION_2;
2653
2654   return (door1 | door2);
2655 }
2656
2657 void DrawSpecialEditorDoor()
2658 {
2659   /* draw bigger toolbox window */
2660   BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
2661              DOOR_GFX_PAGEX7, 0, EXSIZE + 8, 8,
2662              EX - 4, EY - 12);
2663   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2664              EX - 4, VY - 4, EXSIZE + 8, EYSIZE - VYSIZE + 4,
2665              EX - 4, EY - 4);
2666
2667   redraw_mask |= REDRAW_ALL;
2668 }
2669
2670 void UndrawSpecialEditorDoor()
2671 {
2672   /* draw normal tape recorder window */
2673   BlitBitmap(graphic_info[IMG_GLOBAL_BORDER].bitmap, drawto,
2674              EX - 4, EY - 12, EXSIZE + 8, EYSIZE - VYSIZE + 12,
2675              EX - 4, EY - 12);
2676
2677   redraw_mask |= REDRAW_ALL;
2678 }
2679
2680
2681 /* ---------- new tool button stuff ---------------------------------------- */
2682
2683 /* graphic position values for tool buttons */
2684 #define TOOL_BUTTON_YES_XPOS            2
2685 #define TOOL_BUTTON_YES_YPOS            250
2686 #define TOOL_BUTTON_YES_GFX_YPOS        0
2687 #define TOOL_BUTTON_YES_XSIZE           46
2688 #define TOOL_BUTTON_YES_YSIZE           28
2689 #define TOOL_BUTTON_NO_XPOS             52
2690 #define TOOL_BUTTON_NO_YPOS             TOOL_BUTTON_YES_YPOS
2691 #define TOOL_BUTTON_NO_GFX_YPOS         TOOL_BUTTON_YES_GFX_YPOS
2692 #define TOOL_BUTTON_NO_XSIZE            TOOL_BUTTON_YES_XSIZE
2693 #define TOOL_BUTTON_NO_YSIZE            TOOL_BUTTON_YES_YSIZE
2694 #define TOOL_BUTTON_CONFIRM_XPOS        TOOL_BUTTON_YES_XPOS
2695 #define TOOL_BUTTON_CONFIRM_YPOS        TOOL_BUTTON_YES_YPOS
2696 #define TOOL_BUTTON_CONFIRM_GFX_YPOS    30
2697 #define TOOL_BUTTON_CONFIRM_XSIZE       96
2698 #define TOOL_BUTTON_CONFIRM_YSIZE       TOOL_BUTTON_YES_YSIZE
2699 #define TOOL_BUTTON_PLAYER_XSIZE        30
2700 #define TOOL_BUTTON_PLAYER_YSIZE        30
2701 #define TOOL_BUTTON_PLAYER_GFX_XPOS     5
2702 #define TOOL_BUTTON_PLAYER_GFX_YPOS     185
2703 #define TOOL_BUTTON_PLAYER_XPOS         (5 + TOOL_BUTTON_PLAYER_XSIZE / 2)
2704 #define TOOL_BUTTON_PLAYER_YPOS         (215 - TOOL_BUTTON_PLAYER_YSIZE / 2)
2705 #define TOOL_BUTTON_PLAYER1_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2706                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2707 #define TOOL_BUTTON_PLAYER2_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2708                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2709 #define TOOL_BUTTON_PLAYER3_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2710                                          + 0 * TOOL_BUTTON_PLAYER_XSIZE)
2711 #define TOOL_BUTTON_PLAYER4_XPOS        (TOOL_BUTTON_PLAYER_XPOS \
2712                                          + 1 * TOOL_BUTTON_PLAYER_XSIZE)
2713 #define TOOL_BUTTON_PLAYER1_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2714                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2715 #define TOOL_BUTTON_PLAYER2_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2716                                          + 0 * TOOL_BUTTON_PLAYER_YSIZE)
2717 #define TOOL_BUTTON_PLAYER3_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2718                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2719 #define TOOL_BUTTON_PLAYER4_YPOS        (TOOL_BUTTON_PLAYER_YPOS \
2720                                          + 1 * TOOL_BUTTON_PLAYER_YSIZE)
2721
2722 static struct
2723 {
2724   int xpos, ypos;
2725   int x, y;
2726   int width, height;
2727   int gadget_id;
2728   char *infotext;
2729 } toolbutton_info[NUM_TOOL_BUTTONS] =
2730 {
2731   {
2732     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_GFX_YPOS,
2733     TOOL_BUTTON_YES_XPOS,       TOOL_BUTTON_YES_YPOS,
2734     TOOL_BUTTON_YES_XSIZE,      TOOL_BUTTON_YES_YSIZE,
2735     TOOL_CTRL_ID_YES,
2736     "yes"
2737   },
2738   {
2739     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_GFX_YPOS,
2740     TOOL_BUTTON_NO_XPOS,        TOOL_BUTTON_NO_YPOS,
2741     TOOL_BUTTON_NO_XSIZE,       TOOL_BUTTON_NO_YSIZE,
2742     TOOL_CTRL_ID_NO,
2743     "no"
2744   },
2745   {
2746     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_GFX_YPOS,
2747     TOOL_BUTTON_CONFIRM_XPOS,   TOOL_BUTTON_CONFIRM_YPOS,
2748     TOOL_BUTTON_CONFIRM_XSIZE,  TOOL_BUTTON_CONFIRM_YSIZE,
2749     TOOL_CTRL_ID_CONFIRM,
2750     "confirm"
2751   },
2752   {
2753     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2754     TOOL_BUTTON_PLAYER1_XPOS,   TOOL_BUTTON_PLAYER1_YPOS,
2755     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2756     TOOL_CTRL_ID_PLAYER_1,
2757     "player 1"
2758   },
2759   {
2760     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2761     TOOL_BUTTON_PLAYER2_XPOS,   TOOL_BUTTON_PLAYER2_YPOS,
2762     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2763     TOOL_CTRL_ID_PLAYER_2,
2764     "player 2"
2765   },
2766   {
2767     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2768     TOOL_BUTTON_PLAYER3_XPOS,   TOOL_BUTTON_PLAYER3_YPOS,
2769     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2770     TOOL_CTRL_ID_PLAYER_3,
2771     "player 3"
2772   },
2773   {
2774     TOOL_BUTTON_PLAYER_GFX_XPOS,TOOL_BUTTON_PLAYER_GFX_YPOS,
2775     TOOL_BUTTON_PLAYER4_XPOS,   TOOL_BUTTON_PLAYER4_YPOS,
2776     TOOL_BUTTON_PLAYER_XSIZE,   TOOL_BUTTON_PLAYER_YSIZE,
2777     TOOL_CTRL_ID_PLAYER_4,
2778     "player 4"
2779   }
2780 };
2781
2782 void CreateToolButtons()
2783 {
2784   int i;
2785
2786   for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2787   {
2788     Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
2789     Bitmap *deco_bitmap = None;
2790     int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0;
2791     struct GadgetInfo *gi;
2792     unsigned long event_mask;
2793     int gd_xoffset, gd_yoffset;
2794     int gd_x1, gd_x2, gd_y;
2795     int id = i;
2796
2797     event_mask = GD_EVENT_RELEASED;
2798
2799     gd_xoffset = toolbutton_info[i].xpos;
2800     gd_yoffset = toolbutton_info[i].ypos;
2801     gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
2802     gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
2803     gd_y = DOOR_GFX_PAGEY1 + gd_yoffset;
2804
2805     if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4)
2806     {
2807       int player_nr = id - TOOL_CTRL_ID_PLAYER_1;
2808
2809       getMiniGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr),
2810                            &deco_bitmap, &deco_x, &deco_y);
2811       deco_xpos = (toolbutton_info[i].width - MINI_TILEX) / 2;
2812       deco_ypos = (toolbutton_info[i].height - MINI_TILEY) / 2;
2813     }
2814
2815     gi = CreateGadget(GDI_CUSTOM_ID, id,
2816                       GDI_INFO_TEXT, toolbutton_info[i].infotext,
2817                       GDI_X, DX + toolbutton_info[i].x,
2818                       GDI_Y, DY + toolbutton_info[i].y,
2819                       GDI_WIDTH, toolbutton_info[i].width,
2820                       GDI_HEIGHT, toolbutton_info[i].height,
2821                       GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
2822                       GDI_STATE, GD_BUTTON_UNPRESSED,
2823                       GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
2824                       GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
2825                       GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
2826                       GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
2827                       GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
2828                       GDI_DECORATION_SHIFTING, 1, 1,
2829                       GDI_EVENT_MASK, event_mask,
2830                       GDI_CALLBACK_ACTION, HandleToolButtons,
2831                       GDI_END);
2832
2833     if (gi == NULL)
2834       Error(ERR_EXIT, "cannot create gadget");
2835
2836     tool_gadget[id] = gi;
2837   }
2838 }
2839
2840 void FreeToolButtons()
2841 {
2842   int i;
2843
2844   for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2845     FreeGadget(tool_gadget[i]);
2846 }
2847
2848 static void UnmapToolButtons()
2849 {
2850   int i;
2851
2852   for (i = 0; i < NUM_TOOL_BUTTONS; i++)
2853     UnmapGadget(tool_gadget[i]);
2854 }
2855
2856 static void HandleToolButtons(struct GadgetInfo *gi)
2857 {
2858   request_gadget_id = gi->custom_id;
2859 }
2860
2861 static struct Mapping_EM_to_RND_object
2862 {
2863   int element_em;
2864   boolean is_rnd_to_em_mapping;         /* unique mapping EM <-> RND */
2865   boolean is_backside;                  /* backside of moving element */
2866
2867   int element_rnd;
2868   int action;
2869   int direction;
2870 }
2871 em_object_mapping_list[] =
2872 {
2873   {
2874     Xblank,                             TRUE,   FALSE,
2875     EL_EMPTY,                           -1, -1
2876   },
2877   {
2878     Yacid_splash_eB,                    FALSE,  FALSE,
2879     EL_ACID_SPLASH_RIGHT,               -1, -1
2880   },
2881   {
2882     Yacid_splash_wB,                    FALSE,  FALSE,
2883     EL_ACID_SPLASH_LEFT,                -1, -1
2884   },
2885
2886 #ifdef EM_ENGINE_BAD_ROLL
2887   {
2888     Xstone_force_e,                     FALSE,  FALSE,
2889     EL_ROCK,                            -1, MV_BIT_RIGHT
2890   },
2891   {
2892     Xstone_force_w,                     FALSE,  FALSE,
2893     EL_ROCK,                            -1, MV_BIT_LEFT
2894   },
2895   {
2896     Xnut_force_e,                       FALSE,  FALSE,
2897     EL_NUT,                             -1, MV_BIT_RIGHT
2898   },
2899   {
2900     Xnut_force_w,                       FALSE,  FALSE,
2901     EL_NUT,                             -1, MV_BIT_LEFT
2902   },
2903   {
2904     Xspring_force_e,                    FALSE,  FALSE,
2905     EL_SPRING,                          -1, MV_BIT_RIGHT
2906   },
2907   {
2908     Xspring_force_w,                    FALSE,  FALSE,
2909     EL_SPRING,                          -1, MV_BIT_LEFT
2910   },
2911   {
2912     Xemerald_force_e,                   FALSE,  FALSE,
2913     EL_EMERALD,                         -1, MV_BIT_RIGHT
2914   },
2915   {
2916     Xemerald_force_w,                   FALSE,  FALSE,
2917     EL_EMERALD,                         -1, MV_BIT_LEFT
2918   },
2919   {
2920     Xdiamond_force_e,                   FALSE,  FALSE,
2921     EL_DIAMOND,                         -1, MV_BIT_RIGHT
2922   },
2923   {
2924     Xdiamond_force_w,                   FALSE,  FALSE,
2925     EL_DIAMOND,                         -1, MV_BIT_LEFT
2926   },
2927   {
2928     Xbomb_force_e,                      FALSE,  FALSE,
2929     EL_BOMB,                            -1, MV_BIT_RIGHT
2930   },
2931   {
2932     Xbomb_force_w,                      FALSE,  FALSE,
2933     EL_BOMB,                            -1, MV_BIT_LEFT
2934   },
2935 #endif  /* EM_ENGINE_BAD_ROLL */
2936
2937   {
2938     Xstone,                             TRUE,   FALSE,
2939     EL_ROCK,                            -1, -1
2940   },
2941   {
2942     Xstone_pause,                       FALSE,  FALSE,
2943     EL_ROCK,                            -1, -1
2944   },
2945   {
2946     Xstone_fall,                        FALSE,  FALSE,
2947     EL_ROCK,                            -1, -1
2948   },
2949   {
2950     Ystone_s,                           FALSE,  FALSE,
2951     EL_ROCK,                            ACTION_FALLING, -1
2952   },
2953   {
2954     Ystone_sB,                          FALSE,  TRUE,
2955     EL_ROCK,                            ACTION_FALLING, -1
2956   },
2957   {
2958     Ystone_e,                           FALSE,  FALSE,
2959     EL_ROCK,                            ACTION_MOVING, MV_BIT_RIGHT
2960   },
2961   {
2962     Ystone_eB,                          FALSE,  TRUE,
2963     EL_ROCK,                            ACTION_MOVING, MV_BIT_RIGHT
2964   },
2965   {
2966     Ystone_w,                           FALSE,  FALSE,
2967     EL_ROCK,                            ACTION_MOVING, MV_BIT_LEFT
2968   },
2969   {
2970     Ystone_wB,                          FALSE,  TRUE,
2971     EL_ROCK,                            ACTION_MOVING, MV_BIT_LEFT
2972   },
2973   {
2974     Xnut,                               TRUE,   FALSE,
2975     EL_NUT,                             -1, -1
2976   },
2977   {
2978     Xnut_pause,                         FALSE,  FALSE,
2979     EL_NUT,                             -1, -1
2980   },
2981   {
2982     Xnut_fall,                          FALSE,  FALSE,
2983     EL_NUT,                             -1, -1
2984   },
2985   {
2986     Ynut_s,                             FALSE,  FALSE,
2987     EL_NUT,                             ACTION_FALLING, -1
2988   },
2989   {
2990     Ynut_sB,                            FALSE,  TRUE,
2991     EL_NUT,                             ACTION_FALLING, -1
2992   },
2993   {
2994     Ynut_e,                             FALSE,  FALSE,
2995     EL_NUT,                             ACTION_MOVING, MV_BIT_RIGHT
2996   },
2997   {
2998     Ynut_eB,                            FALSE,  TRUE,
2999     EL_NUT,                             ACTION_MOVING, MV_BIT_RIGHT
3000   },
3001   {
3002     Ynut_w,                             FALSE,  FALSE,
3003     EL_NUT,                             ACTION_MOVING, MV_BIT_LEFT
3004   },
3005   {
3006     Ynut_wB,                            FALSE,  TRUE,
3007     EL_NUT,                             ACTION_MOVING, MV_BIT_LEFT
3008   },
3009   {
3010     Xbug_n,                             TRUE,   FALSE,
3011     EL_BUG_UP,                          -1, -1
3012   },
3013   {
3014     Xbug_e,                             TRUE,   FALSE,
3015     EL_BUG_RIGHT,                       -1, -1
3016   },
3017   {
3018     Xbug_s,                             TRUE,   FALSE,
3019     EL_BUG_DOWN,                        -1, -1
3020   },
3021   {
3022     Xbug_w,                             TRUE,   FALSE,
3023     EL_BUG_LEFT,                        -1, -1
3024   },
3025   {
3026     Xbug_gon,                           FALSE,  FALSE,
3027     EL_BUG_UP,                          -1, -1
3028   },
3029   {
3030     Xbug_goe,                           FALSE,  FALSE,
3031     EL_BUG_RIGHT,                       -1, -1
3032   },
3033   {
3034     Xbug_gos,                           FALSE,  FALSE,
3035     EL_BUG_DOWN,                        -1, -1
3036   },
3037   {
3038     Xbug_gow,                           FALSE,  FALSE,
3039     EL_BUG_LEFT,                        -1, -1
3040   },
3041   {
3042     Ybug_n,                             FALSE,  FALSE,
3043     EL_BUG,                             ACTION_MOVING, MV_BIT_UP
3044   },
3045   {
3046     Ybug_nB,                            FALSE,  TRUE,
3047     EL_BUG,                             ACTION_MOVING, MV_BIT_UP
3048   },
3049   {
3050     Ybug_e,                             FALSE,  FALSE,
3051     EL_BUG,                             ACTION_MOVING, MV_BIT_RIGHT
3052   },
3053   {
3054     Ybug_eB,                            FALSE,  TRUE,
3055     EL_BUG,                             ACTION_MOVING, MV_BIT_RIGHT
3056   },
3057   {
3058     Ybug_s,                             FALSE,  FALSE,
3059     EL_BUG,                             ACTION_MOVING, MV_BIT_DOWN
3060   },
3061   {
3062     Ybug_sB,                            FALSE,  TRUE,
3063     EL_BUG,                             ACTION_MOVING, MV_BIT_DOWN
3064   },
3065   {
3066     Ybug_w,                             FALSE,  FALSE,
3067     EL_BUG,                             ACTION_MOVING, MV_BIT_LEFT
3068   },
3069   {
3070     Ybug_wB,                            FALSE,  TRUE,
3071     EL_BUG,                             ACTION_MOVING, MV_BIT_LEFT
3072   },
3073   {
3074     Ybug_w_n,                           FALSE,  FALSE,
3075     EL_BUG,                             ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3076   },
3077   {
3078     Ybug_n_e,                           FALSE,  FALSE,
3079     EL_BUG,                             ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3080   },
3081   {
3082     Ybug_e_s,                           FALSE,  FALSE,
3083     EL_BUG,                             ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3084   },
3085   {
3086     Ybug_s_w,                           FALSE,  FALSE,
3087     EL_BUG,                             ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3088   },
3089   {
3090     Ybug_e_n,                           FALSE,  FALSE,
3091     EL_BUG,                             ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3092   },
3093   {
3094     Ybug_s_e,                           FALSE,  FALSE,
3095     EL_BUG,                             ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3096   },
3097   {
3098     Ybug_w_s,                           FALSE,  FALSE,
3099     EL_BUG,                             ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3100   },
3101   {
3102     Ybug_n_w,                           FALSE,  FALSE,
3103     EL_BUG,                             ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3104   },
3105   {
3106     Ybug_stone,                         FALSE,  FALSE,
3107     EL_BUG,                             ACTION_SMASHED_BY_ROCK, -1
3108   },
3109   {
3110     Ybug_spring,                        FALSE,  FALSE,
3111     EL_BUG,                             ACTION_SMASHED_BY_SPRING, -1
3112   },
3113   {
3114     Xtank_n,                            TRUE,   FALSE,
3115     EL_SPACESHIP_UP,                    -1, -1
3116   },
3117   {
3118     Xtank_e,                            TRUE,   FALSE,
3119     EL_SPACESHIP_RIGHT,                 -1, -1
3120   },
3121   {
3122     Xtank_s,                            TRUE,   FALSE,
3123     EL_SPACESHIP_DOWN,                  -1, -1
3124   },
3125   {
3126     Xtank_w,                            TRUE,   FALSE,
3127     EL_SPACESHIP_LEFT,                  -1, -1
3128   },
3129   {
3130     Xtank_gon,                          FALSE,  FALSE,
3131     EL_SPACESHIP_UP,                    -1, -1
3132   },
3133   {
3134     Xtank_goe,                          FALSE,  FALSE,
3135     EL_SPACESHIP_RIGHT,                 -1, -1
3136   },
3137   {
3138     Xtank_gos,                          FALSE,  FALSE,
3139     EL_SPACESHIP_DOWN,                  -1, -1
3140   },
3141   {
3142     Xtank_gow,                          FALSE,  FALSE,
3143     EL_SPACESHIP_LEFT,                  -1, -1
3144   },
3145   {
3146     Ytank_n,                            FALSE,  FALSE,
3147     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_UP
3148   },
3149   {
3150     Ytank_nB,                           FALSE,  TRUE,
3151     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_UP
3152   },
3153   {
3154     Ytank_e,                            FALSE,  FALSE,
3155     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_RIGHT
3156   },
3157   {
3158     Ytank_eB,                           FALSE,  TRUE,
3159     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_RIGHT
3160   },
3161   {
3162     Ytank_s,                            FALSE,  FALSE,
3163     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_DOWN
3164   },
3165   {
3166     Ytank_sB,                           FALSE,  TRUE,
3167     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_DOWN
3168   },
3169   {
3170     Ytank_w,                            FALSE,  FALSE,
3171     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_LEFT
3172   },
3173   {
3174     Ytank_wB,                           FALSE,  TRUE,
3175     EL_SPACESHIP,                       ACTION_MOVING, MV_BIT_LEFT
3176   },
3177   {
3178     Ytank_w_n,                          FALSE,  FALSE,
3179     EL_SPACESHIP,                       ACTION_TURNING_FROM_LEFT, MV_BIT_UP
3180   },
3181   {
3182     Ytank_n_e,                          FALSE,  FALSE,
3183     EL_SPACESHIP,                       ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3184   },
3185   {
3186     Ytank_e_s,                          FALSE,  FALSE,
3187     EL_SPACESHIP,                       ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN
3188   },
3189   {
3190     Ytank_s_w,                          FALSE,  FALSE,
3191     EL_SPACESHIP,                       ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3192   },
3193   {
3194     Ytank_e_n,                          FALSE,  FALSE,
3195     EL_SPACESHIP,                       ACTION_TURNING_FROM_RIGHT, MV_BIT_UP
3196   },
3197   {
3198     Ytank_s_e,                          FALSE,  FALSE,
3199     EL_SPACESHIP,                       ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3200   },
3201   {
3202     Ytank_w_s,                          FALSE,  FALSE,
3203     EL_SPACESHIP,                       ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN
3204   },
3205   {
3206     Ytank_n_w,                          FALSE,  FALSE,
3207     EL_SPACESHIP,                       ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3208   },
3209   {
3210     Ytank_stone,                        FALSE,  FALSE,
3211     EL_SPACESHIP,                       ACTION_SMASHED_BY_ROCK, -1
3212   },
3213   {
3214     Ytank_spring,                       FALSE,  FALSE,
3215     EL_SPACESHIP,                       ACTION_SMASHED_BY_SPRING, -1
3216   },
3217   {
3218     Xandroid,                           TRUE,   FALSE,
3219     EL_EMC_ANDROID,                     ACTION_ACTIVE, -1
3220   },
3221   {
3222     Xandroid_1_n,                       FALSE,  FALSE,
3223     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_UP
3224   },
3225   {
3226     Xandroid_2_n,                       FALSE,  FALSE,
3227     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_UP
3228   },
3229   {
3230     Xandroid_1_e,                       FALSE,  FALSE,
3231     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_RIGHT
3232   },
3233   {
3234     Xandroid_2_e,                       FALSE,  FALSE,
3235     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_RIGHT
3236   },
3237   {
3238     Xandroid_1_w,                       FALSE,  FALSE,
3239     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_LEFT
3240   },
3241   {
3242     Xandroid_2_w,                       FALSE,  FALSE,
3243     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_LEFT
3244   },
3245   {
3246     Xandroid_1_s,                       FALSE,  FALSE,
3247     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_DOWN
3248   },
3249   {
3250     Xandroid_2_s,                       FALSE,  FALSE,
3251     EL_EMC_ANDROID,                     ACTION_ACTIVE, MV_BIT_DOWN
3252   },
3253   {
3254     Yandroid_n,                         FALSE,  FALSE,
3255     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_UP
3256   },
3257   {
3258     Yandroid_nB,                        FALSE,  TRUE,
3259     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_UP
3260   },
3261   {
3262     Yandroid_ne,                        FALSE,  FALSE,
3263     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3264   },
3265   {
3266     Yandroid_neB,                       FALSE,  TRUE,
3267     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_UP, MV_BIT_RIGHT
3268   },
3269   {
3270     Yandroid_e,                         FALSE,  FALSE,
3271     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_RIGHT
3272   },
3273   {
3274     Yandroid_eB,                        FALSE,  TRUE,
3275     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_RIGHT
3276   },
3277   {
3278     Yandroid_se,                        FALSE,  FALSE,
3279     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3280   },
3281   {
3282     Yandroid_seB,                       FALSE,  TRUE,
3283     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT
3284   },
3285   {
3286     Yandroid_s,                         FALSE,  FALSE,
3287     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_DOWN
3288   },
3289   {
3290     Yandroid_sB,                        FALSE,  TRUE,
3291     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_DOWN
3292   },
3293   {
3294     Yandroid_sw,                        FALSE,  FALSE,
3295     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3296   },
3297   {
3298     Yandroid_swB,                       FALSE,  TRUE,
3299     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT
3300   },
3301   {
3302     Yandroid_w,                         FALSE,  FALSE,
3303     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_LEFT
3304   },
3305   {
3306     Yandroid_wB,                        FALSE,  TRUE,
3307     EL_EMC_ANDROID,                     ACTION_MOVING, MV_BIT_LEFT
3308   },
3309   {
3310     Yandroid_nw,                        FALSE,  FALSE,
3311     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3312   },
3313   {
3314     Yandroid_nwB,                       FALSE,  TRUE,
3315     EL_EMC_ANDROID,                     ACTION_TURNING_FROM_UP, MV_BIT_LEFT
3316   },
3317   {
3318     Xspring,                            TRUE,   FALSE,
3319     EL_SPRING,                          -1, -1
3320   },
3321   {
3322     Xspring_pause,                      FALSE,  FALSE,
3323     EL_SPRING,                          -1, -1
3324   },
3325   {
3326     Xspring_e,                          FALSE,  FALSE,
3327     EL_SPRING,                          -1, -1
3328   },
3329   {
3330     Xspring_w,                          FALSE,  FALSE,
3331     EL_SPRING,                          -1, -1
3332   },
3333   {
3334     Xspring_fall,                       FALSE,  FALSE,
3335     EL_SPRING,                          -1, -1
3336   },
3337   {
3338     Yspring_s,                          FALSE,  FALSE,
3339     EL_SPRING,                          ACTION_FALLING, -1
3340   },
3341   {
3342     Yspring_sB,                         FALSE,  TRUE,
3343     EL_SPRING,                          ACTION_FALLING, -1
3344   },
3345   {
3346     Yspring_e,                          FALSE,  FALSE,
3347     EL_SPRING,                          ACTION_MOVING, MV_BIT_RIGHT
3348   },
3349   {
3350     Yspring_eB,                         FALSE,  TRUE,
3351     EL_SPRING,                          ACTION_MOVING, MV_BIT_RIGHT
3352   },
3353   {
3354     Yspring_w,                          FALSE,  FALSE,
3355     EL_SPRING,                          ACTION_MOVING, MV_BIT_LEFT
3356   },
3357   {
3358     Yspring_wB,                         FALSE,  TRUE,
3359     EL_SPRING,                          ACTION_MOVING, MV_BIT_LEFT
3360   },
3361   {
3362     Yspring_kill_e,                     FALSE,  FALSE,
3363     EL_ROBOT,                           ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3364   },
3365   {
3366     Yspring_kill_eB,                    FALSE,  TRUE,
3367     EL_ROBOT,                           ACTION_SLURPED_BY_SPRING, MV_BIT_RIGHT
3368   },
3369   {
3370     Yspring_kill_w,                     FALSE,  FALSE,
3371     EL_ROBOT,                           ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3372   },
3373   {
3374     Yspring_kill_wB,                    FALSE,  TRUE,
3375     EL_ROBOT,                           ACTION_SLURPED_BY_SPRING, MV_BIT_LEFT
3376   },
3377   {
3378     Xeater_n,                           TRUE,   FALSE,
3379     EL_YAMYAM,                          -1, -1
3380   },
3381   {
3382     Xeater_e,                           FALSE,  FALSE,
3383     EL_YAMYAM,                          -1, -1
3384   },
3385   {
3386     Xeater_w,                           FALSE,  FALSE,
3387     EL_YAMYAM,                          -1, -1
3388   },
3389   {
3390     Xeater_s,                           FALSE,  FALSE,
3391     EL_YAMYAM,                          -1, -1
3392   },
3393   {
3394     Yeater_n,                           FALSE,  FALSE,
3395     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_UP
3396   },
3397   {
3398     Yeater_nB,                          FALSE,  TRUE,
3399     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_UP
3400   },
3401   {
3402     Yeater_e,                           FALSE,  FALSE,
3403     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_RIGHT
3404   },
3405   {
3406     Yeater_eB,                          FALSE,  TRUE,
3407     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_RIGHT
3408   },
3409   {
3410     Yeater_s,                           FALSE,  FALSE,
3411     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_DOWN
3412   },
3413   {
3414     Yeater_sB,                          FALSE,  TRUE,
3415     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_DOWN
3416   },
3417   {
3418     Yeater_w,                           FALSE,  FALSE,
3419     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_LEFT
3420   },
3421   {
3422     Yeater_wB,                          FALSE,  TRUE,
3423     EL_YAMYAM,                          ACTION_MOVING, MV_BIT_LEFT
3424   },
3425   {
3426     Yeater_stone,                       FALSE,  FALSE,
3427     EL_YAMYAM,                          ACTION_SMASHED_BY_ROCK, -1
3428   },
3429   {
3430     Yeater_spring,                      FALSE,  FALSE,
3431     EL_YAMYAM,                          ACTION_SMASHED_BY_SPRING, -1
3432   },
3433   {
3434     Xalien,                             TRUE,   FALSE,
3435     EL_ROBOT,                           -1, -1
3436   },
3437   {
3438     Xalien_pause,                       FALSE,  FALSE,
3439     EL_ROBOT,                           -1, -1
3440   },
3441   {
3442     Yalien_n,                           FALSE,  FALSE,
3443     EL_ROBOT,                           ACTION_MOVING, MV_BIT_UP
3444   },
3445   {
3446     Yalien_nB,                          FALSE,  TRUE,
3447     EL_ROBOT,                           ACTION_MOVING, MV_BIT_UP
3448   },
3449   {
3450     Yalien_e,                           FALSE,  FALSE,
3451     EL_ROBOT,                           ACTION_MOVING, MV_BIT_RIGHT
3452   },
3453   {
3454     Yalien_eB,                          FALSE,  TRUE,
3455     EL_ROBOT,                           ACTION_MOVING, MV_BIT_RIGHT
3456   },
3457   {
3458     Yalien_s,                           FALSE,  FALSE,
3459     EL_ROBOT,                           ACTION_MOVING, MV_BIT_DOWN
3460   },
3461   {
3462     Yalien_sB,                          FALSE,  TRUE,
3463     EL_ROBOT,                           ACTION_MOVING, MV_BIT_DOWN
3464   },
3465   {
3466     Yalien_w,                           FALSE,  FALSE,
3467     EL_ROBOT,                           ACTION_MOVING, MV_BIT_LEFT
3468   },
3469   {
3470     Yalien_wB,                          FALSE,  TRUE,
3471     EL_ROBOT,                           ACTION_MOVING, MV_BIT_LEFT
3472   },
3473   {
3474     Yalien_stone,                       FALSE,  FALSE,
3475     EL_ROBOT,                           ACTION_SMASHED_BY_ROCK, -1
3476   },
3477   {
3478     Yalien_spring,                      FALSE,  FALSE,
3479     EL_ROBOT,                           ACTION_SMASHED_BY_SPRING, -1
3480   },
3481   {
3482     Xemerald,                           TRUE,   FALSE,
3483     EL_EMERALD,                         -1, -1
3484   },
3485   {
3486     Xemerald_pause,                     FALSE,  FALSE,
3487     EL_EMERALD,                         -1, -1
3488   },
3489   {
3490     Xemerald_fall,                      FALSE,  FALSE,
3491     EL_EMERALD,                         -1, -1
3492   },
3493   {
3494     Xemerald_shine,                     FALSE,  FALSE,
3495     EL_EMERALD,                         ACTION_TWINKLING, -1
3496   },
3497   {
3498     Yemerald_s,                         FALSE,  FALSE,
3499     EL_EMERALD,                         ACTION_FALLING, -1
3500   },
3501   {
3502     Yemerald_sB,                        FALSE,  TRUE,
3503     EL_EMERALD,                         ACTION_FALLING, -1
3504   },
3505   {
3506     Yemerald_e,                         FALSE,  FALSE,
3507     EL_EMERALD,                         ACTION_MOVING, MV_BIT_RIGHT
3508   },
3509   {
3510     Yemerald_eB,                        FALSE,  TRUE,
3511     EL_EMERALD,                         ACTION_MOVING, MV_BIT_RIGHT
3512   },
3513   {
3514     Yemerald_w,                         FALSE,  FALSE,
3515     EL_EMERALD,                         ACTION_MOVING, MV_BIT_LEFT
3516   },
3517   {
3518     Yemerald_wB,                        FALSE,  TRUE,
3519     EL_EMERALD,                         ACTION_MOVING, MV_BIT_LEFT
3520   },
3521   {
3522     Yemerald_eat,                       FALSE,  FALSE,
3523     EL_EMERALD,                         ACTION_COLLECTING, -1
3524   },
3525   {
3526     Yemerald_stone,                     FALSE,  FALSE,
3527     EL_NUT,                             ACTION_BREAKING, -1
3528   },
3529   {
3530     Xdiamond,                           TRUE,   FALSE,
3531     EL_DIAMOND,                         -1, -1
3532   },
3533   {
3534     Xdiamond_pause,                     FALSE,  FALSE,
3535     EL_DIAMOND,                         -1, -1
3536   },
3537   {
3538     Xdiamond_fall,                      FALSE,  FALSE,
3539     EL_DIAMOND,                         -1, -1
3540   },
3541   {
3542     Xdiamond_shine,                     FALSE,  FALSE,
3543     EL_DIAMOND,                         ACTION_TWINKLING, -1
3544   },
3545   {
3546     Ydiamond_s,                         FALSE,  FALSE,
3547     EL_DIAMOND,                         ACTION_FALLING, -1
3548   },
3549   {
3550     Ydiamond_sB,                        FALSE,  TRUE,
3551     EL_DIAMOND,                         ACTION_FALLING, -1
3552   },
3553   {
3554     Ydiamond_e,                         FALSE,  FALSE,
3555     EL_DIAMOND,                         ACTION_MOVING, MV_BIT_RIGHT
3556   },
3557   {
3558     Ydiamond_eB,                        FALSE,  TRUE,
3559     EL_DIAMOND,                         ACTION_MOVING, MV_BIT_RIGHT
3560   },
3561   {
3562     Ydiamond_w,                         FALSE,  FALSE,
3563     EL_DIAMOND,                         ACTION_MOVING, MV_BIT_LEFT
3564   },
3565   {
3566     Ydiamond_wB,                        FALSE,  TRUE,
3567     EL_DIAMOND,                         ACTION_MOVING, MV_BIT_LEFT
3568   },
3569   {
3570     Ydiamond_eat,                       FALSE,  FALSE,
3571     EL_DIAMOND,                         ACTION_COLLECTING, -1
3572   },
3573   {
3574     Ydiamond_stone,                     FALSE,  FALSE,
3575     EL_DIAMOND,                         ACTION_SMASHED_BY_ROCK, -1
3576   },
3577   {
3578     Xdrip_fall,                         TRUE,   FALSE,
3579     EL_AMOEBA_DROP,                     -1, -1
3580   },
3581   {
3582     Xdrip_stretch,                      FALSE,  FALSE,
3583     EL_AMOEBA_DROP,                     ACTION_FALLING, -1
3584   },
3585   {
3586     Xdrip_stretchB,                     FALSE,  TRUE,
3587     EL_AMOEBA_DROP,                     ACTION_FALLING, -1
3588   },
3589   {
3590     Xdrip_eat,                          FALSE,  FALSE,
3591     EL_AMOEBA_DROP,                     ACTION_GROWING, -1
3592   },
3593   {
3594     Ydrip_s1,                           FALSE,  FALSE,
3595     EL_AMOEBA_DROP,                     ACTION_FALLING, -1
3596   },
3597   {
3598     Ydrip_s1B,                          FALSE,  TRUE,
3599     EL_AMOEBA_DROP,                     ACTION_FALLING, -1
3600   },
3601   {
3602     Ydrip_s2,                           FALSE,  FALSE,
3603     EL_AMOEBA_DROP,                     ACTION_FALLING, -1
3604   },
3605   {
3606     Ydrip_s2B,                          FALSE,  TRUE,
3607     EL_AMOEBA_DROP,                     ACTION_FALLING, -1
3608   },
3609   {
3610     Xbomb,                              TRUE,   FALSE,
3611     EL_BOMB,                            -1, -1
3612   },
3613   {
3614     Xbomb_pause,                        FALSE,  FALSE,
3615     EL_BOMB,                            -1, -1
3616   },
3617   {
3618     Xbomb_fall,                         FALSE,  FALSE,
3619     EL_BOMB,                            -1, -1
3620   },
3621   {
3622     Ybomb_s,                            FALSE,  FALSE,
3623     EL_BOMB,                            ACTION_FALLING, -1
3624   },
3625   {
3626     Ybomb_sB,                           FALSE,  TRUE,
3627     EL_BOMB,                            ACTION_FALLING, -1
3628   },
3629   {
3630     Ybomb_e,                            FALSE,  FALSE,
3631     EL_BOMB,                            ACTION_MOVING, MV_BIT_RIGHT
3632   },
3633   {
3634     Ybomb_eB,                           FALSE,  TRUE,
3635     EL_BOMB,                            ACTION_MOVING, MV_BIT_RIGHT
3636   },
3637   {
3638     Ybomb_w,                            FALSE,  FALSE,
3639     EL_BOMB,                            ACTION_MOVING, MV_BIT_LEFT
3640   },
3641   {
3642     Ybomb_wB,                           FALSE,  TRUE,
3643     EL_BOMB,                            ACTION_MOVING, MV_BIT_LEFT
3644   },
3645   {
3646     Ybomb_eat,                          FALSE,  FALSE,
3647     EL_BOMB,                            ACTION_ACTIVATING, -1
3648   },
3649   {
3650     Xballoon,                           TRUE,   FALSE,
3651     EL_BALLOON,                         -1, -1
3652   },
3653   {
3654     Yballoon_n,                         FALSE,  FALSE,
3655     EL_BALLOON,                         ACTION_MOVING, MV_BIT_UP
3656   },
3657   {
3658     Yballoon_nB,                        FALSE,  TRUE,
3659     EL_BALLOON,                         ACTION_MOVING, MV_BIT_UP
3660   },
3661   {
3662     Yballoon_e,                         FALSE,  FALSE,
3663     EL_BALLOON,                         ACTION_MOVING, MV_BIT_RIGHT
3664   },
3665   {
3666     Yballoon_eB,                        FALSE,  TRUE,
3667     EL_BALLOON,                         ACTION_MOVING, MV_BIT_RIGHT
3668   },
3669   {
3670     Yballoon_s,                         FALSE,  FALSE,
3671     EL_BALLOON,                         ACTION_MOVING, MV_BIT_DOWN
3672   },
3673   {
3674     Yballoon_sB,                        FALSE,  TRUE,
3675     EL_BALLOON,                         ACTION_MOVING, MV_BIT_DOWN
3676   },
3677   {
3678     Yballoon_w,                         FALSE,  FALSE,
3679     EL_BALLOON,                         ACTION_MOVING, MV_BIT_LEFT
3680   },
3681   {
3682     Yballoon_wB,                        FALSE,  TRUE,
3683     EL_BALLOON,                         ACTION_MOVING, MV_BIT_LEFT
3684   },
3685   {
3686     Xgrass,                             TRUE,   FALSE,
3687     EL_EMC_GRASS,                       -1, -1
3688   },
3689   {
3690     Ygrass_nB,                          FALSE,  FALSE,
3691     EL_EMC_GRASS,                       ACTION_DIGGING, MV_BIT_UP
3692   },
3693   {
3694     Ygrass_eB,                          FALSE,  FALSE,
3695     EL_EMC_GRASS,                       ACTION_DIGGING, MV_BIT_RIGHT
3696   },
3697   {
3698     Ygrass_sB,                          FALSE,  FALSE,
3699     EL_EMC_GRASS,                       ACTION_DIGGING, MV_BIT_DOWN
3700   },
3701   {
3702     Ygrass_wB,                          FALSE,  FALSE,
3703     EL_EMC_GRASS,                       ACTION_DIGGING, MV_BIT_LEFT
3704   },
3705   {
3706     Xdirt,                              TRUE,   FALSE,
3707     EL_SAND,                            -1, -1
3708   },
3709   {
3710     Ydirt_nB,                           FALSE,  FALSE,
3711     EL_SAND,                            ACTION_DIGGING, MV_BIT_UP
3712   },
3713   {
3714     Ydirt_eB,                           FALSE,  FALSE,
3715     EL_SAND,                            ACTION_DIGGING, MV_BIT_RIGHT
3716   },
3717   {
3718     Ydirt_sB,                           FALSE,  FALSE,
3719     EL_SAND,                            ACTION_DIGGING, MV_BIT_DOWN
3720   },
3721   {
3722     Ydirt_wB,                           FALSE,  FALSE,
3723     EL_SAND,                            ACTION_DIGGING, MV_BIT_LEFT
3724   },
3725   {
3726     Xacid_ne,                           TRUE,   FALSE,
3727     EL_ACID_POOL_TOPRIGHT,              -1, -1
3728   },
3729   {
3730     Xacid_se,                           TRUE,   FALSE,
3731     EL_ACID_POOL_BOTTOMRIGHT,           -1, -1
3732   },
3733   {
3734     Xacid_s,                            TRUE,   FALSE,
3735     EL_ACID_POOL_BOTTOM,                -1, -1
3736   },
3737   {
3738     Xacid_sw,                           TRUE,   FALSE,
3739     EL_ACID_POOL_BOTTOMLEFT,            -1, -1
3740   },
3741   {
3742     Xacid_nw,                           TRUE,   FALSE,
3743     EL_ACID_POOL_TOPLEFT,               -1, -1
3744   },
3745   {
3746     Xacid_1,                            TRUE,   FALSE,
3747     EL_ACID,                            -1, -1
3748   },
3749   {
3750     Xacid_2,                            FALSE,  FALSE,
3751     EL_ACID,                            -1, -1
3752   },
3753   {
3754     Xacid_3,                            FALSE,  FALSE,
3755     EL_ACID,                            -1, -1
3756   },
3757   {
3758     Xacid_4,                            FALSE,  FALSE,
3759     EL_ACID,                            -1, -1
3760   },
3761   {
3762     Xacid_5,                            FALSE,  FALSE,
3763     EL_ACID,                            -1, -1
3764   },
3765   {
3766     Xacid_6,                            FALSE,  FALSE,
3767     EL_ACID,                            -1, -1
3768   },
3769   {
3770     Xacid_7,                            FALSE,  FALSE,
3771     EL_ACID,                            -1, -1
3772   },
3773   {
3774     Xacid_8,                            FALSE,  FALSE,
3775     EL_ACID,                            -1, -1
3776   },
3777   {
3778     Xball_1,                            TRUE,   FALSE,
3779     EL_EMC_MAGIC_BALL,                  -1, -1
3780   },
3781   {
3782     Xball_1B,                           FALSE,  FALSE,
3783     EL_EMC_MAGIC_BALL,                  ACTION_ACTIVE, -1
3784   },
3785   {
3786     Xball_2,                            FALSE,  FALSE,
3787     EL_EMC_MAGIC_BALL,                  ACTION_ACTIVE, -1
3788   },
3789   {
3790     Xball_2B,                           FALSE,  FALSE,
3791     EL_EMC_MAGIC_BALL,                  ACTION_ACTIVE, -1
3792   },
3793   {
3794     Yball_eat,                          FALSE,  FALSE,
3795     EL_EMC_MAGIC_BALL,                  ACTION_DROPPING, -1
3796   },
3797   {
3798     Ykey_1_eat,                         FALSE,  FALSE,
3799     EL_EM_KEY_1,                        ACTION_COLLECTING, -1
3800   },
3801   {
3802     Ykey_2_eat,                         FALSE,  FALSE,
3803     EL_EM_KEY_2,                        ACTION_COLLECTING, -1
3804   },
3805   {
3806     Ykey_3_eat,                         FALSE,  FALSE,
3807     EL_EM_KEY_3,                        ACTION_COLLECTING, -1
3808   },
3809   {
3810     Ykey_4_eat,                         FALSE,  FALSE,
3811     EL_EM_KEY_4,                        ACTION_COLLECTING, -1
3812   },
3813   {
3814     Ykey_5_eat,                         FALSE,  FALSE,
3815     EL_EMC_KEY_5,                       ACTION_COLLECTING, -1
3816   },
3817   {
3818     Ykey_6_eat,                         FALSE,  FALSE,
3819     EL_EMC_KEY_6,                       ACTION_COLLECTING, -1
3820   },
3821   {
3822     Ykey_7_eat,                         FALSE,  FALSE,
3823     EL_EMC_KEY_7,                       ACTION_COLLECTING, -1
3824   },
3825   {
3826     Ykey_8_eat,                         FALSE,  FALSE,
3827     EL_EMC_KEY_8,                       ACTION_COLLECTING, -1
3828   },
3829   {
3830     Ylenses_eat,                        FALSE,  FALSE,
3831     EL_EMC_LENSES,                      ACTION_COLLECTING, -1
3832   },
3833   {
3834     Ymagnify_eat,                       FALSE,  FALSE,
3835     EL_EMC_MAGNIFIER,                   ACTION_COLLECTING, -1
3836   },
3837   {
3838     Ygrass_eat,                         FALSE,  FALSE,
3839     EL_EMC_GRASS,                       ACTION_SNAPPING, -1
3840   },
3841   {
3842     Ydirt_eat,                          FALSE,  FALSE,
3843     EL_SAND,                            ACTION_SNAPPING, -1
3844   },
3845   {
3846     Xgrow_ns,                           TRUE,   FALSE,
3847     EL_EXPANDABLE_WALL_VERTICAL,        -1, -1
3848   },
3849   {
3850     Ygrow_ns_eat,                       FALSE,  FALSE,
3851     EL_EXPANDABLE_WALL_VERTICAL,        ACTION_GROWING, -1
3852   },
3853   {
3854     Xgrow_ew,                           TRUE,   FALSE,
3855     EL_EXPANDABLE_WALL_HORIZONTAL,      -1, -1
3856   },
3857   {
3858     Ygrow_ew_eat,                       FALSE,  FALSE,
3859     EL_EXPANDABLE_WALL_HORIZONTAL,      ACTION_GROWING, -1
3860   },
3861   {
3862     Xwonderwall,                        TRUE,   FALSE,
3863     EL_MAGIC_WALL,                      -1, -1
3864   },
3865   {
3866     XwonderwallB,                       FALSE,  FALSE,
3867     EL_MAGIC_WALL,                      ACTION_ACTIVE, -1
3868   },
3869   {
3870     Xamoeba_1,                          TRUE,   FALSE,
3871     EL_AMOEBA_DRY,                      ACTION_OTHER, -1
3872   },
3873   {
3874     Xamoeba_2,                          FALSE,  FALSE,
3875     EL_AMOEBA_DRY,                      ACTION_OTHER, -1
3876   },
3877   {
3878     Xamoeba_3,                          FALSE,  FALSE,
3879     EL_AMOEBA_DRY,                      ACTION_OTHER, -1
3880   },
3881   {
3882     Xamoeba_4,                          FALSE,  FALSE,
3883     EL_AMOEBA_DRY,                      ACTION_OTHER, -1
3884   },
3885   {
3886     Xamoeba_5,                          TRUE,   FALSE,
3887     EL_AMOEBA_WET,                      ACTION_OTHER, -1
3888   },
3889   {
3890     Xamoeba_6,                          FALSE,  FALSE,
3891     EL_AMOEBA_WET,                      ACTION_OTHER, -1
3892   },
3893   {
3894     Xamoeba_7,                          FALSE,  FALSE,
3895     EL_AMOEBA_WET,                      ACTION_OTHER, -1
3896   },
3897   {
3898     Xamoeba_8,                          FALSE,  FALSE,
3899     EL_AMOEBA_WET,                      ACTION_OTHER, -1
3900   },
3901   {
3902     Xdoor_1,                            TRUE,   FALSE,
3903     EL_EM_GATE_1,                       -1, -1
3904   },
3905   {
3906     Xdoor_2,                            TRUE,   FALSE,
3907     EL_EM_GATE_2,                       -1, -1
3908   },
3909   {
3910     Xdoor_3,                            TRUE,   FALSE,
3911     EL_EM_GATE_3,                       -1, -1
3912   },
3913   {
3914     Xdoor_4,                            TRUE,   FALSE,
3915     EL_EM_GATE_4,                       -1, -1
3916   },
3917   {
3918     Xdoor_5,                            TRUE,   FALSE,
3919     EL_EMC_GATE_5,                      -1, -1
3920   },
3921   {
3922     Xdoor_6,                            TRUE,   FALSE,
3923     EL_EMC_GATE_6,                      -1, -1
3924   },
3925   {
3926     Xdoor_7,                            TRUE,   FALSE,
3927     EL_EMC_GATE_7,                      -1, -1
3928   },
3929   {
3930     Xdoor_8,                            TRUE,   FALSE,
3931     EL_EMC_GATE_8,                      -1, -1
3932   },
3933   {
3934     Xkey_1,                             TRUE,   FALSE,
3935     EL_EM_KEY_1,                        -1, -1
3936   },
3937   {
3938     Xkey_2,                             TRUE,   FALSE,
3939     EL_EM_KEY_2,                        -1, -1
3940   },
3941   {
3942     Xkey_3,                             TRUE,   FALSE,
3943     EL_EM_KEY_3,                        -1, -1
3944   },
3945   {
3946     Xkey_4,                             TRUE,   FALSE,
3947     EL_EM_KEY_4,                        -1, -1
3948   },
3949   {
3950     Xkey_5,                             TRUE,   FALSE,
3951     EL_EMC_KEY_5,                       -1, -1
3952   },
3953   {
3954     Xkey_6,                             TRUE,   FALSE,
3955     EL_EMC_KEY_6,                       -1, -1
3956   },
3957   {
3958     Xkey_7,                             TRUE,   FALSE,
3959     EL_EMC_KEY_7,                       -1, -1
3960   },
3961   {
3962     Xkey_8,                             TRUE,   FALSE,
3963     EL_EMC_KEY_8,                       -1, -1
3964   },
3965   {
3966     Xwind_n,                            TRUE,   FALSE,
3967     EL_BALLOON_SWITCH_UP,               -1, -1
3968   },
3969   {
3970     Xwind_e,                            TRUE,   FALSE,
3971     EL_BALLOON_SWITCH_RIGHT,            -1, -1
3972   },
3973   {
3974     Xwind_s,                            TRUE,   FALSE,
3975     EL_BALLOON_SWITCH_DOWN,             -1, -1
3976   },
3977   {
3978     Xwind_w,                            TRUE,   FALSE,
3979     EL_BALLOON_SWITCH_LEFT,             -1, -1
3980   },
3981   {
3982     Xwind_nesw,                         TRUE,   FALSE,
3983     EL_BALLOON_SWITCH_ANY,              -1, -1
3984   },
3985   {
3986     Xwind_stop,                         TRUE,   FALSE,
3987     EL_BALLOON_SWITCH_NONE,             -1, -1
3988   },
3989   {
3990     Xexit,                              TRUE,   FALSE,
3991     EL_EXIT_CLOSED,                     -1, -1
3992   },
3993   {
3994     Xexit_1,                            TRUE,   FALSE,
3995     EL_EXIT_OPEN,                       -1, -1
3996   },
3997   {
3998     Xexit_2,                            FALSE,  FALSE,
3999     EL_EXIT_OPEN,                       -1, -1
4000   },
4001   {
4002     Xexit_3,                            FALSE,  FALSE,
4003     EL_EXIT_OPEN,                       -1, -1
4004   },
4005   {
4006     Xdynamite,                          TRUE,   FALSE,
4007     EL_DYNAMITE,                        -1, -1
4008   },
4009   {
4010     Ydynamite_eat,                      FALSE,  FALSE,
4011     EL_DYNAMITE,                        ACTION_COLLECTING, -1
4012   },
4013   {
4014     Xdynamite_1,                        TRUE,   FALSE,
4015     EL_DYNAMITE_ACTIVE,                 -1, -1
4016   },
4017   {
4018     Xdynamite_2,                        FALSE,  FALSE,
4019     EL_DYNAMITE_ACTIVE,                 -1, -1
4020   },
4021   {
4022     Xdynamite_3,                        FALSE,  FALSE,
4023     EL_DYNAMITE_ACTIVE,                 -1, -1
4024   },
4025   {
4026     Xdynamite_4,                        FALSE,  FALSE,
4027     EL_DYNAMITE_ACTIVE,                 -1, -1
4028   },
4029   {
4030     Xbumper,                            TRUE,   FALSE,
4031     EL_EMC_SPRING_BUMPER,               -1, -1
4032   },
4033   {
4034     XbumperB,                           FALSE,  FALSE,
4035     EL_EMC_SPRING_BUMPER,               ACTION_ACTIVE, -1
4036   },
4037   {
4038     Xwheel,                             TRUE,   FALSE,
4039     EL_ROBOT_WHEEL,                     -1, -1
4040   },
4041   {
4042     XwheelB,                            FALSE,  FALSE,
4043     EL_ROBOT_WHEEL,                     ACTION_ACTIVE, -1
4044   },
4045   {
4046     Xswitch,                            TRUE,   FALSE,
4047     EL_EMC_MAGIC_BALL_SWITCH,           -1, -1
4048   },
4049   {
4050     XswitchB,                           FALSE,  FALSE,
4051     EL_EMC_MAGIC_BALL_SWITCH,           ACTION_ACTIVE, -1
4052   },
4053   {
4054     Xsand,                              TRUE,   FALSE,
4055     EL_QUICKSAND_EMPTY,                 -1, -1
4056   },
4057   {
4058     Xsand_stone,                        TRUE,   FALSE,
4059     EL_QUICKSAND_FULL,                  -1, -1
4060   },
4061   {
4062     Xsand_stonein_1,                    FALSE,  FALSE,
4063     EL_ROCK,                            ACTION_FILLING, -1
4064   },
4065   {
4066     Xsand_stonein_2,                    FALSE,  FALSE,
4067     EL_ROCK,                            ACTION_FILLING, -1
4068   },
4069   {
4070     Xsand_stonein_3,                    FALSE,  FALSE,
4071     EL_ROCK,                            ACTION_FILLING, -1
4072   },
4073   {
4074     Xsand_stonein_4,                    FALSE,  FALSE,
4075     EL_ROCK,                            ACTION_FILLING, -1
4076   },
4077   {
4078     Xsand_stonesand_1,                  FALSE,  FALSE,
4079     EL_QUICKSAND_FULL,                  -1, -1
4080   },
4081   {
4082     Xsand_stonesand_2,                  FALSE,  FALSE,
4083     EL_QUICKSAND_FULL,                  -1, -1
4084   },
4085   {
4086     Xsand_stonesand_3,                  FALSE,  FALSE,
4087     EL_QUICKSAND_FULL,                  -1, -1
4088   },
4089   {
4090     Xsand_stonesand_4,                  FALSE,  FALSE,
4091     EL_QUICKSAND_FULL,                  -1, -1
4092   },
4093   {
4094     Xsand_stoneout_1,                   FALSE,  FALSE,
4095     EL_ROCK,                            ACTION_EMPTYING, -1
4096   },
4097   {
4098     Xsand_stoneout_2,                   FALSE,  FALSE,
4099     EL_ROCK,                            ACTION_EMPTYING, -1
4100   },
4101   {
4102     Xsand_sandstone_1,                  FALSE,  FALSE,
4103     EL_QUICKSAND_FULL,                  -1, -1
4104   },
4105   {
4106     Xsand_sandstone_2,                  FALSE,  FALSE,
4107     EL_QUICKSAND_FULL,                  -1, -1
4108   },
4109   {
4110     Xsand_sandstone_3,                  FALSE,  FALSE,
4111     EL_QUICKSAND_FULL,                  -1, -1
4112   },
4113   {
4114     Xsand_sandstone_4,                  FALSE,  FALSE,
4115     EL_QUICKSAND_FULL,                  -1, -1
4116   },
4117   {
4118     Xplant,                             TRUE,   FALSE,
4119     EL_EMC_PLANT,                       -1, -1
4120   },
4121   {
4122     Yplant,                             FALSE,  FALSE,
4123     EL_EMC_PLANT,                       -1, -1
4124   },
4125   {
4126     Xlenses,                            TRUE,   FALSE,
4127     EL_EMC_LENSES,                      -1, -1
4128   },
4129   {
4130     Xmagnify,                           TRUE,   FALSE,
4131     EL_EMC_MAGNIFIER,                   -1, -1
4132   },
4133   {
4134     Xdripper,                           TRUE,   FALSE,
4135     EL_EMC_DRIPPER,                     -1, -1
4136   },
4137   {
4138     XdripperB,                          FALSE,  FALSE,
4139     EL_EMC_DRIPPER,                     ACTION_ACTIVE, -1
4140   },
4141   {
4142     Xfake_blank,                        TRUE,   FALSE,
4143     EL_INVISIBLE_WALL,                  -1, -1
4144   },
4145   {
4146     Xfake_blankB,                       FALSE,  FALSE,
4147     EL_INVISIBLE_WALL,                  ACTION_ACTIVE, -1
4148   },
4149   {
4150     Xfake_grass,                        TRUE,   FALSE,
4151     EL_EMC_FAKE_GRASS,                  -1, -1
4152   },
4153   {
4154     Xfake_grassB,                       FALSE,  FALSE,
4155     EL_EMC_FAKE_GRASS,                  ACTION_ACTIVE, -1
4156   },
4157   {
4158     Xfake_door_1,                       TRUE,   FALSE,
4159     EL_EM_GATE_1_GRAY,                  -1, -1
4160   },
4161   {
4162     Xfake_door_2,                       TRUE,   FALSE,
4163     EL_EM_GATE_2_GRAY,                  -1, -1
4164   },
4165   {
4166     Xfake_door_3,                       TRUE,   FALSE,
4167     EL_EM_GATE_3_GRAY,                  -1, -1
4168   },
4169   {
4170     Xfake_door_4,                       TRUE,   FALSE,
4171     EL_EM_GATE_4_GRAY,                  -1, -1
4172   },
4173   {
4174     Xfake_door_5,                       TRUE,   FALSE,
4175     EL_EMC_GATE_5_GRAY,                 -1, -1
4176   },
4177   {
4178     Xfake_door_6,                       TRUE,   FALSE,
4179     EL_EMC_GATE_6_GRAY,                 -1, -1
4180   },
4181   {
4182     Xfake_door_7,                       TRUE,   FALSE,
4183     EL_EMC_GATE_7_GRAY,                 -1, -1
4184   },
4185   {
4186     Xfake_door_8,                       TRUE,   FALSE,
4187     EL_EMC_GATE_8_GRAY,                 -1, -1
4188   },
4189   {
4190     Xfake_acid_1,                       TRUE,   FALSE,
4191     EL_EMC_FAKE_ACID,                   -1, -1
4192   },
4193   {
4194     Xfake_acid_2,                       FALSE,  FALSE,
4195     EL_EMC_FAKE_ACID,                   -1, -1
4196   },
4197   {
4198     Xfake_acid_3,                       FALSE,  FALSE,
4199     EL_EMC_FAKE_ACID,                   -1, -1
4200   },
4201   {
4202     Xfake_acid_4,                       FALSE,  FALSE,
4203     EL_EMC_FAKE_ACID,                   -1, -1
4204   },
4205   {
4206     Xfake_acid_5,                       FALSE,  FALSE,
4207     EL_EMC_FAKE_ACID,                   -1, -1
4208   },
4209   {
4210     Xfake_acid_6,                       FALSE,  FALSE,
4211     EL_EMC_FAKE_ACID,                   -1, -1
4212   },
4213   {
4214     Xfake_acid_7,                       FALSE,  FALSE,
4215     EL_EMC_FAKE_ACID,                   -1, -1
4216   },
4217   {
4218     Xfake_acid_8,                       FALSE,  FALSE,
4219     EL_EMC_FAKE_ACID,                   -1, -1
4220   },
4221   {
4222     Xsteel_1,                           TRUE,   FALSE,
4223     EL_STEELWALL,                       -1, -1
4224   },
4225   {
4226     Xsteel_2,                           TRUE,   FALSE,
4227     EL_EMC_STEELWALL_2,                 -1, -1
4228   },
4229   {
4230     Xsteel_3,                           TRUE,   FALSE,
4231     EL_EMC_STEELWALL_3,                 -1, -1
4232   },
4233   {
4234     Xsteel_4,                           TRUE,   FALSE,
4235     EL_EMC_STEELWALL_4,                 -1, -1
4236   },
4237   {
4238     Xwall_1,                            TRUE,   FALSE,
4239     EL_WALL,                            -1, -1
4240   },
4241   {
4242     Xwall_2,                            TRUE,   FALSE,
4243     EL_EMC_WALL_14,                     -1, -1
4244   },
4245   {
4246     Xwall_3,                            TRUE,   FALSE,
4247     EL_EMC_WALL_15,                     -1, -1
4248   },
4249   {
4250     Xwall_4,                            TRUE,   FALSE,
4251     EL_EMC_WALL_16,                     -1, -1
4252   },
4253   {
4254     Xround_wall_1,                      TRUE,   FALSE,
4255     EL_WALL_SLIPPERY,                   -1, -1
4256   },
4257   {
4258     Xround_wall_2,                      TRUE,   FALSE,
4259     EL_EMC_WALL_SLIPPERY_2,             -1, -1
4260   },
4261   {
4262     Xround_wall_3,                      TRUE,   FALSE,
4263     EL_EMC_WALL_SLIPPERY_3,             -1, -1
4264   },
4265   {
4266     Xround_wall_4,                      TRUE,   FALSE,
4267     EL_EMC_WALL_SLIPPERY_4,             -1, -1
4268   },
4269   {
4270     Xdecor_1,                           TRUE,   FALSE,
4271     EL_EMC_WALL_8,                      -1, -1
4272   },
4273   {
4274     Xdecor_2,                           TRUE,   FALSE,
4275     EL_EMC_WALL_6,                      -1, -1
4276   },
4277   {
4278     Xdecor_3,                           TRUE,   FALSE,
4279     EL_EMC_WALL_4,                      -1, -1
4280   },
4281   {
4282     Xdecor_4,                           TRUE,   FALSE,
4283     EL_EMC_WALL_7,                      -1, -1
4284   },
4285   {
4286     Xdecor_5,                           TRUE,   FALSE,
4287     EL_EMC_WALL_5,                      -1, -1
4288   },
4289   {
4290     Xdecor_6,                           TRUE,   FALSE,
4291     EL_EMC_WALL_9,                      -1, -1
4292   },
4293   {
4294     Xdecor_7,                           TRUE,   FALSE,
4295     EL_EMC_WALL_10,                     -1, -1
4296   },
4297   {
4298     Xdecor_8,                           TRUE,   FALSE,
4299     EL_EMC_WALL_1,                      -1, -1
4300   },
4301   {
4302     Xdecor_9,                           TRUE,   FALSE,
4303     EL_EMC_WALL_2,                      -1, -1
4304   },
4305   {
4306     Xdecor_10,                          TRUE,   FALSE,
4307     EL_EMC_WALL_3,                      -1, -1
4308   },
4309   {
4310     Xdecor_11,                          TRUE,   FALSE,
4311     EL_EMC_WALL_11,                     -1, -1
4312   },
4313   {
4314     Xdecor_12,                          TRUE,   FALSE,
4315     EL_EMC_WALL_12,                     -1, -1
4316   },
4317   {
4318     Xalpha_0,                           TRUE,   FALSE,
4319     EL_CHAR('0'),                       -1, -1
4320   },
4321   {
4322     Xalpha_1,                           TRUE,   FALSE,
4323     EL_CHAR('1'),                       -1, -1
4324   },
4325   {
4326     Xalpha_2,                           TRUE,   FALSE,
4327     EL_CHAR('2'),                       -1, -1
4328   },
4329   {
4330     Xalpha_3,                           TRUE,   FALSE,
4331     EL_CHAR('3'),                       -1, -1
4332   },
4333   {
4334     Xalpha_4,                           TRUE,   FALSE,
4335     EL_CHAR('4'),                       -1, -1
4336   },
4337   {
4338     Xalpha_5,                           TRUE,   FALSE,
4339     EL_CHAR('5'),                       -1, -1
4340   },
4341   {
4342     Xalpha_6,                           TRUE,   FALSE,
4343     EL_CHAR('6'),                       -1, -1
4344   },
4345   {
4346     Xalpha_7,                           TRUE,   FALSE,
4347     EL_CHAR('7'),                       -1, -1
4348   },
4349   {
4350     Xalpha_8,                           TRUE,   FALSE,
4351     EL_CHAR('8'),                       -1, -1
4352   },
4353   {
4354     Xalpha_9,                           TRUE,   FALSE,
4355     EL_CHAR('9'),                       -1, -1
4356   },
4357   {
4358     Xalpha_excla,                       TRUE,   FALSE,
4359     EL_CHAR('!'),                       -1, -1
4360   },
4361   {
4362     Xalpha_quote,                       TRUE,   FALSE,
4363     EL_CHAR('"'),                       -1, -1
4364   },
4365   {
4366     Xalpha_comma,                       TRUE,   FALSE,
4367     EL_CHAR(','),                       -1, -1
4368   },
4369   {
4370     Xalpha_minus,                       TRUE,   FALSE,
4371     EL_CHAR('-'),                       -1, -1
4372   },
4373   {
4374     Xalpha_perio,                       TRUE,   FALSE,
4375     EL_CHAR('.'),                       -1, -1
4376   },
4377   {
4378     Xalpha_colon,                       TRUE,   FALSE,
4379     EL_CHAR(':'),                       -1, -1
4380   },
4381   {
4382     Xalpha_quest,                       TRUE,   FALSE,
4383     EL_CHAR('?'),                       -1, -1
4384   },
4385   {
4386     Xalpha_a,                           TRUE,   FALSE,
4387     EL_CHAR('A'),                       -1, -1
4388   },
4389   {
4390     Xalpha_b,                           TRUE,   FALSE,
4391     EL_CHAR('B'),                       -1, -1
4392   },
4393   {
4394     Xalpha_c,                           TRUE,   FALSE,
4395     EL_CHAR('C'),                       -1, -1
4396   },
4397   {
4398     Xalpha_d,                           TRUE,   FALSE,
4399     EL_CHAR('D'),                       -1, -1
4400   },
4401   {
4402     Xalpha_e,                           TRUE,   FALSE,
4403     EL_CHAR('E'),                       -1, -1
4404   },
4405   {
4406     Xalpha_f,                           TRUE,   FALSE,
4407     EL_CHAR('F'),                       -1, -1
4408   },
4409   {
4410     Xalpha_g,                           TRUE,   FALSE,
4411     EL_CHAR('G'),                       -1, -1
4412   },
4413   {
4414     Xalpha_h,                           TRUE,   FALSE,
4415     EL_CHAR('H'),                       -1, -1
4416   },
4417   {
4418     Xalpha_i,                           TRUE,   FALSE,
4419     EL_CHAR('I'),                       -1, -1
4420   },
4421   {
4422     Xalpha_j,                           TRUE,   FALSE,
4423     EL_CHAR('J'),                       -1, -1
4424   },
4425   {
4426     Xalpha_k,                           TRUE,   FALSE,
4427     EL_CHAR('K'),                       -1, -1
4428   },
4429   {
4430     Xalpha_l,                           TRUE,   FALSE,
4431     EL_CHAR('L'),                       -1, -1
4432   },
4433   {
4434     Xalpha_m,                           TRUE,   FALSE,
4435     EL_CHAR('M'),                       -1, -1
4436   },
4437   {
4438     Xalpha_n,                           TRUE,   FALSE,
4439     EL_CHAR('N'),                       -1, -1
4440   },
4441   {
4442     Xalpha_o,                           TRUE,   FALSE,
4443     EL_CHAR('O'),                       -1, -1
4444   },
4445   {
4446     Xalpha_p,                           TRUE,   FALSE,
4447     EL_CHAR('P'),                       -1, -1
4448   },
4449   {
4450     Xalpha_q,                           TRUE,   FALSE,
4451     EL_CHAR('Q'),                       -1, -1
4452   },
4453   {
4454     Xalpha_r,                           TRUE,   FALSE,
4455     EL_CHAR('R'),                       -1, -1
4456   },
4457   {
4458     Xalpha_s,                           TRUE,   FALSE,
4459     EL_CHAR('S'),                       -1, -1
4460   },
4461   {
4462     Xalpha_t,                           TRUE,   FALSE,
4463     EL_CHAR('T'),                       -1, -1
4464   },
4465   {
4466     Xalpha_u,                           TRUE,   FALSE,
4467     EL_CHAR('U'),                       -1, -1
4468   },
4469   {
4470     Xalpha_v,                           TRUE,   FALSE,
4471     EL_CHAR('V'),                       -1, -1
4472   },
4473   {
4474     Xalpha_w,                           TRUE,   FALSE,
4475     EL_CHAR('W'),                       -1, -1
4476   },
4477   {
4478     Xalpha_x,                           TRUE,   FALSE,
4479     EL_CHAR('X'),                       -1, -1
4480   },
4481   {
4482     Xalpha_y,                           TRUE,   FALSE,
4483     EL_CHAR('Y'),                       -1, -1
4484   },
4485   {
4486     Xalpha_z,                           TRUE,   FALSE,
4487     EL_CHAR('Z'),                       -1, -1
4488   },
4489   {
4490     Xalpha_arrow_e,                     TRUE,   FALSE,
4491     EL_CHAR('>'),                       -1, -1
4492   },
4493   {
4494     Xalpha_arrow_w,                     TRUE,   FALSE,
4495     EL_CHAR('<'),                       -1, -1
4496   },
4497   {
4498     Xalpha_copyr,                       TRUE,   FALSE,
4499     EL_CHAR('©'),                       -1, -1
4500   },
4501   {
4502     Xalpha_copyr,                       TRUE,   FALSE,
4503     EL_CHAR('©'),                       -1, -1
4504   },
4505
4506   {
4507     Xboom_bug,                          FALSE,  FALSE,
4508     EL_BUG,                             ACTION_EXPLODING, -1
4509   },
4510   {
4511     Xboom_bomb,                         FALSE,  FALSE,
4512     EL_BOMB,                            ACTION_EXPLODING, -1
4513   },
4514   {
4515     Xboom_android,                      FALSE,  FALSE,
4516     EL_EMC_ANDROID,                     ACTION_OTHER, -1
4517   },
4518   {
4519     Xboom_1,                            FALSE,  FALSE,
4520     EL_DEFAULT,                         ACTION_EXPLODING, -1
4521   },
4522   {
4523     Xboom_2,                            FALSE,  FALSE,
4524     EL_DEFAULT,                         ACTION_EXPLODING, -1
4525   },
4526   {
4527     Znormal,                            FALSE,  FALSE,
4528     EL_EMPTY,                           -1, -1
4529   },
4530   {
4531     Zdynamite,                          FALSE,  FALSE,
4532     EL_EMPTY,                           -1, -1
4533   },
4534   {
4535     Zplayer,                            FALSE,  FALSE,
4536     EL_EMPTY,                           -1, -1
4537   },
4538   {
4539     ZBORDER,                            FALSE,  FALSE,
4540     EL_EMPTY,                           -1, -1
4541   },
4542
4543   {
4544     -1,                                 FALSE,  FALSE,
4545     -1,                                 -1, -1
4546   }
4547 };
4548
4549 static struct Mapping_EM_to_RND_player
4550 {
4551   int action_em;
4552   int player_nr;
4553
4554   int element_rnd;
4555   int action;
4556   int direction;
4557 }
4558 em_player_mapping_list[] =
4559 {
4560   {
4561     SPR_walk + 0,                       0,
4562     EL_PLAYER_1,                        ACTION_MOVING, MV_BIT_UP,
4563   },
4564   {
4565     SPR_walk + 1,                       0,
4566     EL_PLAYER_1,                        ACTION_MOVING, MV_BIT_RIGHT,
4567   },
4568   {
4569     SPR_walk + 2,                       0,
4570     EL_PLAYER_1,                        ACTION_MOVING, MV_BIT_DOWN,
4571   },
4572   {
4573     SPR_walk + 3,                       0,
4574     EL_PLAYER_1,                        ACTION_MOVING, MV_BIT_LEFT,
4575   },
4576   {
4577     SPR_push + 0,                       0,
4578     EL_PLAYER_1,                        ACTION_PUSHING, MV_BIT_UP,
4579   },
4580   {
4581     SPR_push + 1,                       0,
4582     EL_PLAYER_1,                        ACTION_PUSHING, MV_BIT_RIGHT,
4583   },
4584   {
4585     SPR_push + 2,                       0,
4586     EL_PLAYER_1,                        ACTION_PUSHING, MV_BIT_DOWN,
4587   },
4588   {
4589     SPR_push + 3,                       0,
4590     EL_PLAYER_1,                        ACTION_PUSHING, MV_BIT_LEFT,
4591   },
4592   {
4593     SPR_spray + 0,                      0,
4594     EL_PLAYER_1,                        ACTION_SNAPPING, MV_BIT_UP,
4595   },
4596   {
4597     SPR_spray + 1,                      0,
4598     EL_PLAYER_1,                        ACTION_SNAPPING, MV_BIT_RIGHT,
4599   },
4600   {
4601     SPR_spray + 2,                      0,
4602     EL_PLAYER_1,                        ACTION_SNAPPING, MV_BIT_DOWN,
4603   },
4604   {
4605     SPR_spray + 3,                      0,
4606     EL_PLAYER_1,                        ACTION_SNAPPING, MV_BIT_LEFT,
4607   },
4608   {
4609     SPR_walk + 0,                       1,
4610     EL_PLAYER_2,                        ACTION_MOVING, MV_BIT_UP,
4611   },
4612   {
4613     SPR_walk + 1,                       1,
4614     EL_PLAYER_2,                        ACTION_MOVING, MV_BIT_RIGHT,
4615   },
4616   {
4617     SPR_walk + 2,                       1,
4618     EL_PLAYER_2,                        ACTION_MOVING, MV_BIT_DOWN,
4619   },
4620   {
4621     SPR_walk + 3,                       1,
4622     EL_PLAYER_2,                        ACTION_MOVING, MV_BIT_LEFT,
4623   },
4624   {
4625     SPR_push + 0,                       1,
4626     EL_PLAYER_2,                        ACTION_PUSHING, MV_BIT_UP,
4627   },
4628   {
4629     SPR_push + 1,                       1,
4630     EL_PLAYER_2,                        ACTION_PUSHING, MV_BIT_RIGHT,
4631   },
4632   {
4633     SPR_push + 2,                       1,
4634     EL_PLAYER_2,                        ACTION_PUSHING, MV_BIT_DOWN,
4635   },
4636   {
4637     SPR_push + 3,                       1,
4638     EL_PLAYER_2,                        ACTION_PUSHING, MV_BIT_LEFT,
4639   },
4640   {
4641     SPR_spray + 0,                      1,
4642     EL_PLAYER_2,                        ACTION_SNAPPING, MV_BIT_UP,
4643   },
4644   {
4645     SPR_spray + 1,                      1,
4646     EL_PLAYER_2,                        ACTION_SNAPPING, MV_BIT_RIGHT,
4647   },
4648   {
4649     SPR_spray + 2,                      1,
4650     EL_PLAYER_2,                        ACTION_SNAPPING, MV_BIT_DOWN,
4651   },
4652   {
4653     SPR_spray + 3,                      1,
4654     EL_PLAYER_2,                        ACTION_SNAPPING, MV_BIT_LEFT,
4655   },
4656   {
4657     SPR_still,                          0,
4658     EL_PLAYER_1,                        ACTION_DEFAULT, -1,
4659   },
4660   {
4661     SPR_still,                          1,
4662     EL_PLAYER_2,                        ACTION_DEFAULT, -1,
4663   },
4664
4665   {
4666     -1,                                 -1,
4667     -1,                                 -1, -1
4668   }
4669 };
4670
4671 int map_element_RND_to_EM(int element_rnd)
4672 {
4673   static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4674   static boolean mapping_initialized = FALSE;
4675
4676   if (!mapping_initialized)
4677   {
4678     int i;
4679
4680     /* return "Xalpha_quest" for all undefined elements in mapping array */
4681     for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4682       mapping_RND_to_EM[i] = Xalpha_quest;
4683
4684     for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4685       if (em_object_mapping_list[i].is_rnd_to_em_mapping)
4686         mapping_RND_to_EM[em_object_mapping_list[i].element_rnd] =
4687           em_object_mapping_list[i].element_em;
4688
4689     mapping_initialized = TRUE;
4690   }
4691
4692   if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4693     return mapping_RND_to_EM[element_rnd];
4694
4695   Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4696
4697   return EL_UNKNOWN;
4698 }
4699
4700 int map_element_EM_to_RND(int element_em)
4701 {
4702   static unsigned short mapping_EM_to_RND[TILE_MAX];
4703   static boolean mapping_initialized = FALSE;
4704
4705   if (!mapping_initialized)
4706   {
4707     int i;
4708
4709     /* return "EL_UNKNOWN" for all undefined elements in mapping array */
4710     for (i = 0; i < TILE_MAX; i++)
4711       mapping_EM_to_RND[i] = EL_UNKNOWN;
4712
4713     for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
4714       mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
4715         em_object_mapping_list[i].element_rnd;
4716
4717     mapping_initialized = TRUE;
4718   }
4719
4720   if (element_em >= 0 && element_em < TILE_MAX)
4721     return mapping_EM_to_RND[element_em];
4722
4723   Error(ERR_WARN, "invalid EM level element %d", element_em);
4724
4725   return EL_UNKNOWN;
4726 }
4727
4728 #if 0
4729
4730 int map_element_RND_to_EM(int element_rnd)
4731 {
4732   static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
4733   static boolean mapping_initialized = FALSE;
4734
4735   struct
4736   {
4737     int element_em;
4738     int element_rnd;
4739   }
4740   mapping_RND_to_EM_list[] =
4741   {
4742     { Xblank,                   EL_EMPTY                        },
4743     { Xstone,                   EL_ROCK                         },
4744     { Xnut,                     EL_NUT                          },
4745     { Xbug_n,                   EL_BUG_UP                       },
4746     { Xbug_e,                   EL_BUG_RIGHT                    },
4747     { Xbug_s,                   EL_BUG_DOWN                     },
4748     { Xbug_w,                   EL_BUG_LEFT                     },
4749     { Xtank_n,                  EL_SPACESHIP_UP                 },
4750     { Xtank_e,                  EL_SPACESHIP_RIGHT              },
4751     { Xtank_s,                  EL_SPACESHIP_DOWN               },
4752     { Xtank_w,                  EL_SPACESHIP_LEFT               },
4753     { Xandroid,                 EL_EMC_ANDROID                  },
4754     { Xandroid_1_n,             EL_EMC_ANDROID_UP               },
4755     { Xandroid_1_e,             EL_EMC_ANDROID_RIGHT            },
4756     { Xandroid_1_w,             EL_EMC_ANDROID_LEFT             },
4757     { Xandroid_1_s,             EL_EMC_ANDROID_DOWN             },
4758     { Xspring,                  EL_SPRING                       },
4759     { Xeater_n,                 EL_YAMYAM                       },
4760     { Xalien,                   EL_ROBOT                        },
4761     { Xemerald,                 EL_EMERALD                      },
4762     { Xdiamond,                 EL_DIAMOND                      },
4763     { Xdrip_fall,               EL_AMOEBA_DROP                  },
4764     { Xbomb,                    EL_BOMB                         },
4765     { Xballoon,                 EL_BALLOON                      },
4766     { Xgrass,                   EL_EMC_GRASS                    },
4767     { Xdirt,                    EL_SAND                         },
4768     { Xacid_ne,                 EL_ACID_POOL_TOPRIGHT           },
4769     { Xacid_se,                 EL_ACID_POOL_BOTTOMRIGHT        },
4770     { Xacid_s,                  EL_ACID_POOL_BOTTOM             },
4771     { Xacid_sw,                 EL_ACID_POOL_BOTTOMLEFT         },
4772     { Xacid_nw,                 EL_ACID_POOL_TOPLEFT            },
4773     { Xacid_1,                  EL_ACID                         },
4774     { Xball_1,                  EL_EMC_MAGIC_BALL               },
4775     { Xgrow_ns,                 EL_EMC_GROW                     },
4776     { Xwonderwall,              EL_MAGIC_WALL                   },
4777     { Xamoeba_1,                EL_AMOEBA_WET                   },
4778     { Xdoor_1,                  EL_EM_GATE_1                    },
4779     { Xdoor_2,                  EL_EM_GATE_2                    },
4780     { Xdoor_3,                  EL_EM_GATE_3                    },
4781     { Xdoor_4,                  EL_EM_GATE_4                    },
4782     { Xdoor_5,                  EL_EMC_GATE_5                   },
4783     { Xdoor_6,                  EL_EMC_GATE_6                   },
4784     { Xdoor_7,                  EL_EMC_GATE_7                   },
4785     { Xdoor_8,                  EL_EMC_GATE_8                   },
4786     { Xkey_1,                   EL_EM_KEY_1                     },
4787     { Xkey_2,                   EL_EM_KEY_2                     },
4788     { Xkey_3,                   EL_EM_KEY_3                     },
4789     { Xkey_4,                   EL_EM_KEY_4                     },
4790     { Xkey_5,                   EL_EMC_KEY_5                    },
4791     { Xkey_6,                   EL_EMC_KEY_6                    },
4792     { Xkey_7,                   EL_EMC_KEY_7                    },
4793     { Xkey_8,                   EL_EMC_KEY_8                    },
4794     { Xwind_n,                  EL_BALLOON_SWITCH_UP            },
4795     { Xwind_e,                  EL_BALLOON_SWITCH_RIGHT         },
4796     { Xwind_s,                  EL_BALLOON_SWITCH_DOWN          },
4797     { Xwind_w,                  EL_BALLOON_SWITCH_LEFT          },
4798     { Xwind_nesw,               EL_BALLOON_SWITCH_ANY           },
4799     { Xwind_stop,               EL_BALLOON_SWITCH_NONE          },
4800     { Xexit,                    EL_EXIT_CLOSED                  },
4801     { Xexit_1,                  EL_EXIT_OPEN                    },
4802     { Xdynamite,                EL_DYNAMITE                     },
4803     { Xdynamite_1,              EL_DYNAMITE_ACTIVE              },
4804     { Xbumper,                  EL_EMC_BUMPER                   },
4805     { Xwheel,                   EL_ROBOT_WHEEL                  },
4806     { Xswitch,                  EL_UNKNOWN                      },
4807     { Xsand,                    EL_QUICKSAND_EMPTY              },
4808     { Xsand_stone,              EL_QUICKSAND_FULL               },
4809     { Xplant,                   EL_EMC_PLANT                    },
4810     { Xlenses,                  EL_EMC_LENSES                   },
4811     { Xmagnify,                 EL_EMC_MAGNIFIER                },
4812     { Xdripper,                 EL_UNKNOWN                      },
4813     { Xfake_blank,              EL_INVISIBLE_WALL               },
4814     { Xfake_grass,              EL_INVISIBLE_SAND               },
4815     { Xfake_door_1,             EL_EM_GATE_1_GRAY               },
4816     { Xfake_door_2,             EL_EM_GATE_2_GRAY               },
4817     { Xfake_door_3,             EL_EM_GATE_3_GRAY               },
4818     { Xfake_door_4,             EL_EM_GATE_4_GRAY               },
4819     { Xfake_door_5,             EL_EMC_GATE_5_GRAY              },
4820     { Xfake_door_6,             EL_EMC_GATE_6_GRAY              },
4821     { Xfake_door_7,             EL_EMC_GATE_7_GRAY              },
4822     { Xfake_door_8,             EL_EMC_GATE_8_GRAY              },
4823     { Xsteel_1,                 EL_STEELWALL                    },
4824     { Xsteel_2,                 EL_UNKNOWN                      },
4825     { Xsteel_3,                 EL_EMC_STEELWALL_1              },
4826     { Xsteel_4,                 EL_UNKNOWN                      },
4827     { Xwall_1,                  EL_WALL                         },
4828     { Xwall_2,                  EL_UNKNOWN                      },
4829     { Xwall_3,                  EL_UNKNOWN                      },
4830     { Xwall_4,                  EL_UNKNOWN                      },
4831     { Xround_wall_1,            EL_WALL_SLIPPERY                },
4832     { Xround_wall_2,            EL_UNKNOWN                      },
4833     { Xround_wall_3,            EL_UNKNOWN                      },
4834     { Xround_wall_4,            EL_UNKNOWN                      },
4835     { Xdecor_1,                 EL_UNKNOWN                      },
4836     { Xdecor_2,                 EL_EMC_WALL_6                   },
4837     { Xdecor_3,                 EL_EMC_WALL_4                   },
4838     { Xdecor_4,                 EL_EMC_WALL_5                   },
4839     { Xdecor_5,                 EL_EMC_WALL_7                   },
4840     { Xdecor_6,                 EL_EMC_WALL_8                   },
4841     { Xdecor_7,                 EL_UNKNOWN                      },
4842     { Xdecor_8,                 EL_EMC_WALL_1                   },
4843     { Xdecor_9,                 EL_EMC_WALL_2                   },
4844     { Xdecor_10,                EL_EMC_WALL_3                   },
4845     { Xdecor_11,                EL_UNKNOWN                      },
4846     { Xdecor_12,                EL_UNKNOWN                      },
4847     { Xalpha_0,                 EL_CHAR('0')                    },
4848     { Xalpha_1,                 EL_CHAR('1')                    },
4849     { Xalpha_2,                 EL_CHAR('2')                    },
4850     { Xalpha_3,                 EL_CHAR('3')                    },
4851     { Xalpha_4,                 EL_CHAR('4')                    },
4852     { Xalpha_5,                 EL_CHAR('5')                    },
4853     { Xalpha_6,                 EL_CHAR('6')                    },
4854     { Xalpha_7,                 EL_CHAR('7')                    },
4855     { Xalpha_8,                 EL_CHAR('8')                    },
4856     { Xalpha_9,                 EL_CHAR('9')                    },
4857     { Xalpha_excla,             EL_CHAR('!')                    },
4858     { Xalpha_quote,             EL_CHAR('"')                    },
4859     { Xalpha_comma,             EL_CHAR(',')                    },
4860     { Xalpha_minus,             EL_CHAR('-')                    },
4861     { Xalpha_perio,             EL_CHAR('.')                    },
4862     { Xalpha_colon,             EL_CHAR(':')                    },
4863     { Xalpha_quest,             EL_CHAR('?')                    },
4864     { Xalpha_a,                 EL_CHAR('A')                    },
4865     { Xalpha_b,                 EL_CHAR('B')                    },
4866     { Xalpha_c,                 EL_CHAR('C')                    },
4867     { Xalpha_d,                 EL_CHAR('D')                    },
4868     { Xalpha_e,                 EL_CHAR('E')                    },
4869     { Xalpha_f,                 EL_CHAR('F')                    },
4870     { Xalpha_g,                 EL_CHAR('G')                    },
4871     { Xalpha_h,                 EL_CHAR('H')                    },
4872     { Xalpha_i,                 EL_CHAR('I')                    },
4873     { Xalpha_j,                 EL_CHAR('J')                    },
4874     { Xalpha_k,                 EL_CHAR('K')                    },
4875     { Xalpha_l,                 EL_CHAR('L')                    },
4876     { Xalpha_m,                 EL_CHAR('M')                    },
4877     { Xalpha_n,                 EL_CHAR('N')                    },
4878     { Xalpha_o,                 EL_CHAR('O')                    },
4879     { Xalpha_p,                 EL_CHAR('P')                    },
4880     { Xalpha_q,                 EL_CHAR('Q')                    },
4881     { Xalpha_r,                 EL_CHAR('R')                    },
4882     { Xalpha_s,                 EL_CHAR('S')                    },
4883     { Xalpha_t,                 EL_CHAR('T')                    },
4884     { Xalpha_u,                 EL_CHAR('U')                    },
4885     { Xalpha_v,                 EL_CHAR('V')                    },
4886     { Xalpha_w,                 EL_CHAR('W')                    },
4887     { Xalpha_x,                 EL_CHAR('X')                    },
4888     { Xalpha_y,                 EL_CHAR('Y')                    },
4889     { Xalpha_z,                 EL_CHAR('Z')                    },
4890     { Xalpha_arrow_e,           EL_CHAR('>')                    },
4891     { Xalpha_arrow_w,           EL_CHAR('<')                    },
4892     { Xalpha_copyr,             EL_CHAR('©')                    },
4893
4894     { Zplayer,                  EL_PLAYER_1                     },
4895     { Zplayer,                  EL_PLAYER_2                     },
4896     { Zplayer,                  EL_PLAYER_3                     },
4897     { Zplayer,                  EL_PLAYER_4                     },
4898
4899     { ZBORDER,                  EL_EMC_LEVEL_BORDER             },
4900
4901     { -1,                       -1                              }
4902   };
4903
4904   if (!mapping_initialized)
4905   {
4906     int i;
4907
4908     /* return "Xalpha_quest" for all undefined elements in mapping array */
4909     for (i = 0; i < NUM_FILE_ELEMENTS; i++)
4910       mapping_RND_to_EM[i] = Xalpha_quest;
4911
4912     for (i = 0; mapping_RND_to_EM_list[i].element_rnd != -1; i++)
4913       mapping_RND_to_EM[mapping_RND_to_EM_list[i].element_rnd] =
4914         mapping_RND_to_EM_list[i].element_em;
4915
4916     mapping_initialized = TRUE;
4917   }
4918
4919   if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
4920     return mapping_RND_to_EM[element_rnd];
4921
4922   Error(ERR_WARN, "invalid RND level element %d", element_rnd);
4923
4924   return EL_UNKNOWN;
4925 }
4926
4927 int map_element_EM_to_RND(int element_em)
4928 {
4929   static unsigned short mapping_EM_to_RND[TILE_MAX];
4930   static boolean mapping_initialized = FALSE;
4931
4932   struct
4933   {
4934     int element_em;
4935     int element_rnd;
4936   }
4937   em_object_mapping_list[] =
4938   {
4939     { Xblank,                   EL_EMPTY                        },
4940     { Yacid_splash_eB,          EL_EMPTY                        },
4941     { Yacid_splash_wB,          EL_EMPTY                        },
4942
4943 #ifdef EM_ENGINE_BAD_ROLL
4944     { Xstone_force_e,           EL_ROCK                         },
4945     { Xstone_force_w,           EL_ROCK                         },
4946     { Xnut_force_e,             EL_NUT                          },
4947     { Xnut_force_w,             EL_NUT                          },
4948     { Xspring_force_e,          EL_SPRING                       },
4949     { Xspring_force_w,          EL_SPRING                       },
4950     { Xemerald_force_e,         EL_EMERALD                      },
4951     { Xemerald_force_w,         EL_EMERALD                      },
4952     { Xdiamond_force_e,         EL_DIAMOND                      },
4953     { Xdiamond_force_w,         EL_DIAMOND                      },
4954     { Xbomb_force_e,            EL_BOMB                         },
4955     { Xbomb_force_w,            EL_BOMB                         },
4956 #endif
4957
4958     { Xstone,                   EL_ROCK                         },
4959     { Xstone_pause,             EL_ROCK                         },
4960     { Xstone_fall,              EL_ROCK                         },
4961     { Ystone_s,                 EL_ROCK                         },
4962     { Ystone_sB,                EL_ROCK                         },
4963     { Ystone_e,                 EL_ROCK                         },
4964     { Ystone_eB,                EL_ROCK                         },
4965     { Ystone_w,                 EL_ROCK                         },
4966     { Ystone_wB,                EL_ROCK                         },
4967     { Xnut,                     EL_NUT                          },
4968     { Xnut_pause,               EL_NUT                          },
4969     { Xnut_fall,                EL_NUT                          },
4970     { Ynut_s,                   EL_NUT                          },
4971     { Ynut_sB,                  EL_NUT                          },
4972     { Ynut_e,                   EL_NUT                          },
4973     { Ynut_eB,                  EL_NUT                          },
4974     { Ynut_w,                   EL_NUT                          },
4975     { Ynut_wB,                  EL_NUT                          },
4976     { Xbug_n,                   EL_BUG_UP                       },
4977     { Xbug_e,                   EL_BUG_RIGHT                    },
4978     { Xbug_s,                   EL_BUG_DOWN                     },
4979     { Xbug_w,                   EL_BUG_LEFT                     },
4980     { Xbug_gon,                 EL_BUG_UP                       },
4981     { Xbug_goe,                 EL_BUG_RIGHT                    },
4982     { Xbug_gos,                 EL_BUG_DOWN                     },
4983     { Xbug_gow,                 EL_BUG_LEFT                     },
4984     { Ybug_n,                   EL_BUG_UP                       },
4985     { Ybug_nB,                  EL_BUG_UP                       },
4986     { Ybug_e,                   EL_BUG_RIGHT                    },
4987     { Ybug_eB,                  EL_BUG_RIGHT                    },
4988     { Ybug_s,                   EL_BUG_DOWN                     },
4989     { Ybug_sB,                  EL_BUG_DOWN                     },
4990     { Ybug_w,                   EL_BUG_LEFT                     },
4991     { Ybug_wB,                  EL_BUG_LEFT                     },
4992     { Ybug_w_n,                 EL_BUG_UP                       },
4993     { Ybug_n_e,                 EL_BUG_RIGHT                    },
4994     { Ybug_e_s,                 EL_BUG_DOWN                     },
4995     { Ybug_s_w,                 EL_BUG_LEFT                     },
4996     { Ybug_e_n,                 EL_BUG_UP                       },
4997     { Ybug_s_e,                 EL_BUG_RIGHT                    },
4998     { Ybug_w_s,                 EL_BUG_DOWN                     },
4999     { Ybug_n_w,                 EL_BUG_LEFT                     },
5000     { Ybug_stone,               EL_ROCK                         },
5001     { Ybug_spring,              EL_SPRING                       },
5002     { Xtank_n,                  EL_SPACESHIP_UP                 },
5003     { Xtank_e,                  EL_SPACESHIP_RIGHT              },
5004     { Xtank_s,                  EL_SPACESHIP_DOWN               },
5005     { Xtank_w,                  EL_SPACESHIP_LEFT               },
5006     { Xtank_gon,                EL_SPACESHIP_UP                 },
5007     { Xtank_goe,                EL_SPACESHIP_RIGHT              },
5008     { Xtank_gos,                EL_SPACESHIP_DOWN               },
5009     { Xtank_gow,                EL_SPACESHIP_LEFT               },
5010     { Ytank_n,                  EL_SPACESHIP_UP                 },
5011     { Ytank_nB,                 EL_SPACESHIP_UP                 },
5012     { Ytank_e,                  EL_SPACESHIP_RIGHT              },
5013     { Ytank_eB,                 EL_SPACESHIP_RIGHT              },
5014     { Ytank_s,                  EL_SPACESHIP_DOWN               },
5015     { Ytank_sB,                 EL_SPACESHIP_DOWN               },
5016     { Ytank_w,                  EL_SPACESHIP_LEFT               },
5017     { Ytank_wB,                 EL_SPACESHIP_LEFT               },
5018     { Ytank_w_n,                EL_SPACESHIP_UP                 },
5019     { Ytank_n_e,                EL_SPACESHIP_RIGHT              },
5020     { Ytank_e_s,                EL_SPACESHIP_DOWN               },
5021     { Ytank_s_w,                EL_SPACESHIP_LEFT               },
5022     { Ytank_e_n,                EL_SPACESHIP_UP                 },
5023     { Ytank_s_e,                EL_SPACESHIP_RIGHT              },
5024     { Ytank_w_s,                EL_SPACESHIP_DOWN               },
5025     { Ytank_n_w,                EL_SPACESHIP_LEFT               },
5026     { Ytank_stone,              EL_ROCK                         },
5027     { Ytank_spring,             EL_SPRING                       },
5028     { Xandroid,                 EL_EMC_ANDROID                  },
5029     { Xandroid_1_n,             EL_EMC_ANDROID_UP               },
5030     { Xandroid_2_n,             EL_EMC_ANDROID_UP               },
5031     { Xandroid_1_e,             EL_EMC_ANDROID_RIGHT            },
5032     { Xandroid_2_e,             EL_EMC_ANDROID_RIGHT            },
5033     { Xandroid_1_w,             EL_EMC_ANDROID_LEFT             },
5034     { Xandroid_2_w,             EL_EMC_ANDROID_LEFT             },
5035     { Xandroid_1_s,             EL_EMC_ANDROID_DOWN             },
5036     { Xandroid_2_s,             EL_EMC_ANDROID_DOWN             },
5037     { Yandroid_n,               EL_EMC_ANDROID_UP               },
5038     { Yandroid_nB,              EL_EMC_ANDROID_UP               },
5039     { Yandroid_ne,              EL_EMC_ANDROID_RIGHT_UP         },
5040     { Yandroid_neB,             EL_EMC_ANDROID_RIGHT_UP         },
5041     { Yandroid_e,               EL_EMC_ANDROID_RIGHT            },
5042     { Yandroid_eB,              EL_EMC_ANDROID_RIGHT            },
5043     { Yandroid_se,              EL_EMC_ANDROID_RIGHT_DOWN       },
5044     { Yandroid_seB,             EL_EMC_ANDROID_RIGHT_DOWN       },
5045     { Yandroid_s,               EL_EMC_ANDROID_DOWN             },
5046     { Yandroid_sB,              EL_EMC_ANDROID_DOWN             },
5047     { Yandroid_sw,              EL_EMC_ANDROID_LEFT_DOWN        },
5048     { Yandroid_swB,             EL_EMC_ANDROID_LEFT_DOWN        },
5049     { Yandroid_w,               EL_EMC_ANDROID_LEFT             },
5050     { Yandroid_wB,              EL_EMC_ANDROID_LEFT             },
5051     { Yandroid_nw,              EL_EMC_ANDROID_LEFT_UP          },
5052     { Yandroid_nwB,             EL_EMC_ANDROID_LEFT_UP          },
5053     { Xspring,                  EL_SPRING                       },
5054     { Xspring_pause,            EL_SPRING                       },
5055     { Xspring_e,                EL_SPRING                       },
5056     { Xspring_w,                EL_SPRING                       },
5057     { Xspring_fall,             EL_SPRING                       },
5058     { Yspring_s,                EL_SPRING                       },
5059     { Yspring_sB,               EL_SPRING                       },
5060     { Yspring_e,                EL_SPRING                       },
5061     { Yspring_eB,               EL_SPRING                       },
5062     { Yspring_w,                EL_SPRING                       },
5063     { Yspring_wB,               EL_SPRING                       },
5064     { Yspring_kill_e,           EL_SPRING                       },
5065     { Yspring_kill_eB,          EL_SPRING                       },
5066     { Yspring_kill_w,           EL_SPRING                       },
5067     { Yspring_kill_wB,          EL_SPRING                       },
5068     { Xeater_n,                 EL_YAMYAM                       },
5069     { Xeater_e,                 EL_YAMYAM                       },
5070     { Xeater_w,                 EL_YAMYAM                       },
5071     { Xeater_s,                 EL_YAMYAM                       },
5072     { Yeater_n,                 EL_YAMYAM                       },
5073     { Yeater_nB,                EL_YAMYAM                       },
5074     { Yeater_e,                 EL_YAMYAM                       },
5075     { Yeater_eB,                EL_YAMYAM                       },
5076     { Yeater_s,                 EL_YAMYAM                       },
5077     { Yeater_sB,                EL_YAMYAM                       },
5078     { Yeater_w,                 EL_YAMYAM                       },
5079     { Yeater_wB,                EL_YAMYAM                       },
5080     { Yeater_stone,             EL_ROCK                         },
5081     { Yeater_spring,            EL_SPRING                       },
5082     { Xalien,                   EL_ROBOT                        },
5083     { Xalien_pause,             EL_ROBOT                        },
5084     { Yalien_n,                 EL_ROBOT                        },
5085     { Yalien_nB,                EL_ROBOT                        },
5086     { Yalien_e,                 EL_ROBOT                        },
5087     { Yalien_eB,                EL_ROBOT                        },
5088     { Yalien_s,                 EL_ROBOT                        },
5089     { Yalien_sB,                EL_ROBOT                        },
5090     { Yalien_w,                 EL_ROBOT                        },
5091     { Yalien_wB,                EL_ROBOT                        },
5092     { Yalien_stone,             EL_ROCK                         },
5093     { Yalien_spring,            EL_SPRING                       },
5094     { Xemerald,                 EL_EMERALD                      },
5095     { Xemerald_pause,           EL_EMERALD                      },
5096     { Xemerald_fall,            EL_EMERALD                      },
5097     { Xemerald_shine,           EL_EMERALD                      },
5098     { Yemerald_s,               EL_EMERALD                      },
5099     { Yemerald_sB,              EL_EMERALD                      },
5100     { Yemerald_e,               EL_EMERALD                      },
5101     { Yemerald_eB,              EL_EMERALD                      },
5102     { Yemerald_w,               EL_EMERALD                      },
5103     { Yemerald_wB,              EL_EMERALD                      },
5104     { Yemerald_eat,             EL_EMERALD                      },
5105     { Yemerald_stone,           EL_ROCK                         },
5106     { Xdiamond,                 EL_DIAMOND                      },
5107     { Xdiamond_pause,           EL_DIAMOND                      },
5108     { Xdiamond_fall,            EL_DIAMOND                      },
5109     { Xdiamond_shine,           EL_DIAMOND                      },
5110     { Ydiamond_s,               EL_DIAMOND                      },
5111     { Ydiamond_sB,              EL_DIAMOND                      },
5112     { Ydiamond_e,               EL_DIAMOND                      },
5113     { Ydiamond_eB,              EL_DIAMOND                      },
5114     { Ydiamond_w,               EL_DIAMOND                      },
5115     { Ydiamond_wB,              EL_DIAMOND                      },
5116     { Ydiamond_eat,             EL_DIAMOND                      },
5117     { Ydiamond_stone,           EL_ROCK                         },
5118     { Xdrip_fall,               EL_AMOEBA_DROP                  },
5119     { Xdrip_stretch,            EL_AMOEBA_DROP                  },
5120     { Xdrip_stretchB,           EL_AMOEBA_DROP                  },
5121     { Xdrip_eat,                EL_AMOEBA_DROP                  },
5122     { Ydrip_s1,                 EL_AMOEBA_DROP                  },
5123     { Ydrip_s1B,                EL_AMOEBA_DROP                  },
5124     { Ydrip_s2,                 EL_AMOEBA_DROP                  },
5125     { Ydrip_s2B,                EL_AMOEBA_DROP                  },
5126     { Xbomb,                    EL_BOMB                         },
5127     { Xbomb_pause,              EL_BOMB                         },
5128     { Xbomb_fall,               EL_BOMB                         },
5129     { Ybomb_s,                  EL_BOMB                         },
5130     { Ybomb_sB,                 EL_BOMB                         },
5131     { Ybomb_e,                  EL_BOMB                         },
5132     { Ybomb_eB,                 EL_BOMB                         },
5133     { Ybomb_w,                  EL_BOMB                         },
5134     { Ybomb_wB,                 EL_BOMB                         },
5135     { Ybomb_eat,                EL_BOMB                         },
5136     { Xballoon,                 EL_BALLOON                      },
5137     { Yballoon_n,               EL_BALLOON                      },
5138     { Yballoon_nB,              EL_BALLOON                      },
5139     { Yballoon_e,               EL_BALLOON                      },
5140     { Yballoon_eB,              EL_BALLOON                      },
5141     { Yballoon_s,               EL_BALLOON                      },
5142     { Yballoon_sB,              EL_BALLOON                      },
5143     { Yballoon_w,               EL_BALLOON                      },
5144     { Yballoon_wB,              EL_BALLOON                      },
5145     { Xgrass,                   EL_SAND                         },
5146     { Ygrass_nB,                EL_SAND                         },
5147     { Ygrass_eB,                EL_SAND                         },
5148     { Ygrass_sB,                EL_SAND                         },
5149     { Ygrass_wB,                EL_SAND                         },
5150     { Xdirt,                    EL_SAND                         },
5151     { Ydirt_nB,                 EL_SAND                         },
5152     { Ydirt_eB,                 EL_SAND                         },
5153     { Ydirt_sB,                 EL_SAND                         },
5154     { Ydirt_wB,                 EL_SAND                         },
5155     { Xacid_ne,                 EL_ACID_POOL_TOPRIGHT           },
5156     { Xacid_se,                 EL_ACID_POOL_BOTTOMRIGHT        },
5157     { Xacid_s,                  EL_ACID_POOL_BOTTOM             },
5158     { Xacid_sw,                 EL_ACID_POOL_BOTTOMLEFT         },
5159     { Xacid_nw,                 EL_ACID_POOL_TOPLEFT            },
5160     { Xacid_1,                  EL_ACID                         },
5161     { Xacid_2,                  EL_ACID                         },
5162     { Xacid_3,                  EL_ACID                         },
5163     { Xacid_4,                  EL_ACID                         },
5164     { Xacid_5,                  EL_ACID                         },
5165     { Xacid_6,                  EL_ACID                         },
5166     { Xacid_7,                  EL_ACID                         },
5167     { Xacid_8,                  EL_ACID                         },
5168     { Xball_1,                  EL_EMC_MAGIC_BALL               },
5169     { Xball_1B,                 EL_EMC_MAGIC_BALL               },
5170     { Xball_2,                  EL_EMC_MAGIC_BALL               },
5171     { Xball_2B,                 EL_EMC_MAGIC_BALL               },
5172     { Yball_eat,                EL_EMC_MAGIC_BALL               },
5173     { Xgrow_ns,                 EL_EMC_GROW                     },
5174     { Ygrow_ns_eat,             EL_EMC_GROW                     },
5175     { Xgrow_ew,                 EL_EMC_GROW                     },
5176     { Ygrow_ew_eat,             EL_EMC_GROW                     },
5177     { Xwonderwall,              EL_MAGIC_WALL                   },
5178     { XwonderwallB,             EL_MAGIC_WALL                   },
5179     { Xamoeba_1,                EL_AMOEBA_WET                   },
5180     { Xamoeba_2,                EL_AMOEBA_WET                   },
5181     { Xamoeba_3,                EL_AMOEBA_WET                   },
5182     { Xamoeba_4,                EL_AMOEBA_WET                   },
5183     { Xamoeba_5,                EL_AMOEBA_WET                   },
5184     { Xamoeba_6,                EL_AMOEBA_WET                   },
5185     { Xamoeba_7,                EL_AMOEBA_WET                   },
5186     { Xamoeba_8,                EL_AMOEBA_WET                   },
5187     { Xdoor_1,                  EL_EM_GATE_1                    },
5188     { Xdoor_2,                  EL_EM_GATE_2                    },
5189     { Xdoor_3,                  EL_EM_GATE_3                    },
5190     { Xdoor_4,                  EL_EM_GATE_4                    },
5191     { Xdoor_5,                  EL_EMC_GATE_5                   },
5192     { Xdoor_6,                  EL_EMC_GATE_6                   },
5193     { Xdoor_7,                  EL_EMC_GATE_7                   },
5194     { Xdoor_8,                  EL_EMC_GATE_8                   },
5195     { Xkey_1,                   EL_EM_KEY_1                     },
5196     { Xkey_2,                   EL_EM_KEY_2                     },
5197     { Xkey_3,                   EL_EM_KEY_3                     },
5198     { Xkey_4,                   EL_EM_KEY_4                     },
5199     { Xkey_5,                   EL_EMC_KEY_5                    },
5200     { Xkey_6,                   EL_EMC_KEY_6                    },
5201     { Xkey_7,                   EL_EMC_KEY_7                    },
5202     { Xkey_8,                   EL_EMC_KEY_8                    },
5203     { Xwind_n,                  EL_BALLOON_SWITCH_UP            },
5204     { Xwind_e,                  EL_BALLOON_SWITCH_RIGHT         },
5205     { Xwind_s,                  EL_BALLOON_SWITCH_DOWN          },
5206     { Xwind_w,                  EL_BALLOON_SWITCH_LEFT          },
5207     { Xwind_nesw,               EL_BALLOON_SWITCH_ANY           },
5208     { Xwind_stop,               EL_BALLOON_SWITCH_NONE          },
5209     { Xexit,                    EL_EXIT_CLOSED                  },
5210     { Xexit_1,                  EL_EXIT_OPEN                    },
5211     { Xexit_2,                  EL_EXIT_OPEN                    },
5212     { Xexit_3,                  EL_EXIT_OPEN                    },
5213     { Xdynamite,                EL_DYNAMITE                     },
5214     { Ydynamite_eat,            EL_DYNAMITE                     },
5215     { Xdynamite_1,              EL_DYNAMITE_ACTIVE              },
5216     { Xdynamite_2,              EL_DYNAMITE_ACTIVE              },
5217     { Xdynamite_3,              EL_DYNAMITE_ACTIVE              },
5218     { Xdynamite_4,              EL_DYNAMITE_ACTIVE              },
5219     { Xbumper,                  EL_EMC_BUMPER                   },
5220     { XbumperB,                 EL_EMC_BUMPER                   },
5221     { Xwheel,                   EL_ROBOT_WHEEL                  },
5222     { XwheelB,                  EL_ROBOT_WHEEL                  },
5223     { Xswitch,                  EL_UNKNOWN                      },
5224     { XswitchB,                 EL_UNKNOWN                      },
5225     { Xsand,                    EL_QUICKSAND_EMPTY              },
5226     { Xsand_stone,              EL_QUICKSAND_FULL               },
5227     { Xsand_stonein_1,          EL_QUICKSAND_FULL               },
5228     { Xsand_stonein_2,          EL_QUICKSAND_FULL               },
5229     { Xsand_stonein_3,          EL_QUICKSAND_FULL               },
5230     { Xsand_stonein_4,          EL_QUICKSAND_FULL               },
5231     { Xsand_stonesand_1,        EL_QUICKSAND_FULL               },
5232     { Xsand_stonesand_2,        EL_QUICKSAND_FULL               },
5233     { Xsand_stonesand_3,        EL_QUICKSAND_FULL               },
5234     { Xsand_stonesand_4,        EL_QUICKSAND_FULL               },
5235     { Xsand_stoneout_1,         EL_QUICKSAND_FULL               },
5236     { Xsand_stoneout_2,         EL_QUICKSAND_FULL               },
5237     { Xsand_sandstone_1,        EL_QUICKSAND_FULL               },
5238     { Xsand_sandstone_2,        EL_QUICKSAND_FULL               },
5239     { Xsand_sandstone_3,        EL_QUICKSAND_FULL               },
5240     { Xsand_sandstone_4,        EL_QUICKSAND_FULL               },
5241     { Xplant,                   EL_EMC_PLANT                    },
5242     { Yplant,                   EL_EMC_PLANT                    },
5243     { Xlenses,                  EL_EMC_LENSES                   },
5244     { Xmagnify,                 EL_EMC_MAGNIFIER                },
5245     { Xdripper,                 EL_UNKNOWN                      },
5246     { XdripperB,                EL_UNKNOWN                      },
5247     { Xfake_blank,              EL_INVISIBLE_WALL               },
5248     { Xfake_blankB,             EL_INVISIBLE_WALL               },
5249     { Xfake_grass,              EL_INVISIBLE_SAND               },
5250     { Xfake_grassB,             EL_INVISIBLE_SAND               },
5251     { Xfake_door_1,             EL_EM_GATE_1_GRAY               },
5252     { Xfake_door_2,             EL_EM_GATE_2_GRAY               },
5253     { Xfake_door_3,             EL_EM_GATE_3_GRAY               },
5254     { Xfake_door_4,             EL_EM_GATE_4_GRAY               },
5255     { Xfake_door_5,             EL_EMC_GATE_5_GRAY              },
5256     { Xfake_door_6,             EL_EMC_GATE_6_GRAY              },
5257     { Xfake_door_7,             EL_EMC_GATE_7_GRAY              },
5258     { Xfake_door_8,             EL_EMC_GATE_8_GRAY              },
5259     { Xsteel_1,                 EL_STEELWALL                    },
5260     { Xsteel_2,                 EL_UNKNOWN                      },
5261     { Xsteel_3,                 EL_EMC_STEELWALL_1              },
5262     { Xsteel_4,                 EL_UNKNOWN                      },
5263     { Xwall_1,                  EL_WALL                         },
5264     { Xwall_2,                  EL_UNKNOWN                      },
5265     { Xwall_3,                  EL_UNKNOWN                      },
5266     { Xwall_4,                  EL_UNKNOWN                      },
5267     { Xround_wall_1,            EL_WALL_SLIPPERY                },
5268     { Xround_wall_2,            EL_UNKNOWN                      },
5269     { Xround_wall_3,            EL_UNKNOWN                      },
5270     { Xround_wall_4,            EL_UNKNOWN                      },
5271     { Xdecor_1,                 EL_UNKNOWN                      },
5272     { Xdecor_2,                 EL_EMC_WALL_6                   },
5273     { Xdecor_3,                 EL_EMC_WALL_4                   },
5274     { Xdecor_4,                 EL_EMC_WALL_5                   },
5275     { Xdecor_5,                 EL_EMC_WALL_7                   },
5276     { Xdecor_6,                 EL_EMC_WALL_8                   },
5277     { Xdecor_7,                 EL_UNKNOWN                      },
5278     { Xdecor_8,                 EL_EMC_WALL_1                   },
5279     { Xdecor_9,                 EL_EMC_WALL_2                   },
5280     { Xdecor_10,                EL_EMC_WALL_3                   },
5281     { Xdecor_11,                EL_UNKNOWN                      },
5282     { Xdecor_12,                EL_UNKNOWN                      },
5283     { Xalpha_0,                 EL_CHAR('0')                    },
5284     { Xalpha_1,                 EL_CHAR('1')                    },
5285     { Xalpha_2,                 EL_CHAR('2')                    },
5286     { Xalpha_3,                 EL_CHAR('3')                    },
5287     { Xalpha_4,                 EL_CHAR('4')                    },
5288     { Xalpha_5,                 EL_CHAR('5')                    },
5289     { Xalpha_6,                 EL_CHAR('6')                    },
5290     { Xalpha_7,                 EL_CHAR('7')                    },
5291     { Xalpha_8,                 EL_CHAR('8')                    },
5292     { Xalpha_9,                 EL_CHAR('9')                    },
5293     { Xalpha_excla,             EL_CHAR('!')                    },
5294     { Xalpha_quote,             EL_CHAR('"')                    },
5295     { Xalpha_comma,             EL_CHAR(',')                    },
5296     { Xalpha_minus,             EL_CHAR('-')                    },
5297     { Xalpha_perio,             EL_CHAR('.')                    },
5298     { Xalpha_colon,             EL_CHAR(':')                    },
5299     { Xalpha_quest,             EL_CHAR('?')                    },
5300     { Xalpha_a,                 EL_CHAR('A')                    },
5301     { Xalpha_b,                 EL_CHAR('B')                    },
5302     { Xalpha_c,                 EL_CHAR('C')                    },
5303     { Xalpha_d,                 EL_CHAR('D')                    },
5304     { Xalpha_e,                 EL_CHAR('E')                    },
5305     { Xalpha_f,                 EL_CHAR('F')                    },
5306     { Xalpha_g,                 EL_CHAR('G')                    },
5307     { Xalpha_h,                 EL_CHAR('H')                    },
5308     { Xalpha_i,                 EL_CHAR('I')                    },
5309     { Xalpha_j,                 EL_CHAR('J')                    },
5310     { Xalpha_k,                 EL_CHAR('K')                    },
5311     { Xalpha_l,                 EL_CHAR('L')                    },
5312     { Xalpha_m,                 EL_CHAR('M')                    },
5313     { Xalpha_n,                 EL_CHAR('N')                    },
5314     { Xalpha_o,                 EL_CHAR('O')                    },
5315     { Xalpha_p,                 EL_CHAR('P')                    },
5316     { Xalpha_q,                 EL_CHAR('Q')                    },
5317     { Xalpha_r,                 EL_CHAR('R')                    },
5318     { Xalpha_s,                 EL_CHAR('S')                    },
5319     { Xalpha_t,                 EL_CHAR('T')                    },
5320     { Xalpha_u,                 EL_CHAR('U')                    },
5321     { Xalpha_v,                 EL_CHAR('V')                    },
5322     { Xalpha_w,                 EL_CHAR('W')                    },
5323     { Xalpha_x,                 EL_CHAR('X')                    },
5324     { Xalpha_y,                 EL_CHAR('Y')                    },
5325     { Xalpha_z,                 EL_CHAR('Z')                    },
5326     { Xalpha_arrow_e,           EL_CHAR('>')                    },
5327     { Xalpha_arrow_w,           EL_CHAR('<')                    },
5328     { Xalpha_copyr,             EL_CHAR('©')                    },
5329
5330     { Zplayer,                  EL_PLAYER_1                     },
5331
5332     { ZBORDER,                  EL_EMC_LEVEL_BORDER             },
5333
5334     { -1,                       -1                              }
5335   };
5336
5337   if (!mapping_initialized)
5338   {
5339     int i;
5340
5341     /* return "EL_UNKNOWN" for all undefined elements in mapping array */
5342     for (i = 0; i < TILE_MAX; i++)
5343       mapping_EM_to_RND[i] = EL_UNKNOWN;
5344
5345     for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5346       mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
5347         em_object_mapping_list[i].element_rnd;
5348
5349     mapping_initialized = TRUE;
5350   }
5351
5352   if (element_em >= 0 && element_em < TILE_MAX)
5353     return mapping_EM_to_RND[element_em];
5354
5355   Error(ERR_WARN, "invalid EM level element %d", element_em);
5356
5357   return EL_UNKNOWN;
5358 }
5359
5360 #endif
5361
5362 int get_next_element(int element)
5363 {
5364   switch(element)
5365   {
5366     case EL_QUICKSAND_FILLING:          return EL_QUICKSAND_FULL;
5367     case EL_QUICKSAND_EMPTYING:         return EL_QUICKSAND_EMPTY;
5368     case EL_MAGIC_WALL_FILLING:         return EL_MAGIC_WALL_FULL;
5369     case EL_MAGIC_WALL_EMPTYING:        return EL_MAGIC_WALL_ACTIVE;
5370     case EL_BD_MAGIC_WALL_FILLING:      return EL_BD_MAGIC_WALL_FULL;
5371     case EL_BD_MAGIC_WALL_EMPTYING:     return EL_BD_MAGIC_WALL_ACTIVE;
5372     case EL_AMOEBA_DROPPING:            return EL_AMOEBA_WET;
5373
5374     default:                            return element;
5375   }
5376 }
5377
5378 #if 0
5379 int el_act_dir2img(int element, int action, int direction)
5380 {
5381   element = GFX_ELEMENT(element);
5382
5383   if (direction == MV_NO_MOVING)
5384     return element_info[element].graphic[action];
5385
5386   direction = MV_DIR_BIT(direction);
5387
5388   return element_info[element].direction_graphic[action][direction];
5389 }
5390 #else
5391 int el_act_dir2img(int element, int action, int direction)
5392 {
5393   element = GFX_ELEMENT(element);
5394   direction = MV_DIR_BIT(direction);    /* default: MV_NO_MOVING => MV_DOWN */
5395
5396   /* direction_graphic[][] == graphic[] for undefined direction graphics */
5397   return element_info[element].direction_graphic[action][direction];
5398 }
5399 #endif
5400
5401 #if 0
5402 static int el_act_dir2crm(int element, int action, int direction)
5403 {
5404   element = GFX_ELEMENT(element);
5405
5406   if (direction == MV_NO_MOVING)
5407     return element_info[element].crumbled[action];
5408
5409   direction = MV_DIR_BIT(direction);
5410
5411   return element_info[element].direction_crumbled[action][direction];
5412 }
5413 #else
5414 static int el_act_dir2crm(int element, int action, int direction)
5415 {
5416   element = GFX_ELEMENT(element);
5417   direction = MV_DIR_BIT(direction);    /* default: MV_NO_MOVING => MV_DOWN */
5418
5419   /* direction_graphic[][] == graphic[] for undefined direction graphics */
5420   return element_info[element].direction_crumbled[action][direction];
5421 }
5422 #endif
5423
5424 int el_act2img(int element, int action)
5425 {
5426   element = GFX_ELEMENT(element);
5427
5428   return element_info[element].graphic[action];
5429 }
5430
5431 int el_act2crm(int element, int action)
5432 {
5433   element = GFX_ELEMENT(element);
5434
5435   return element_info[element].crumbled[action];
5436 }
5437
5438 int el_dir2img(int element, int direction)
5439 {
5440   element = GFX_ELEMENT(element);
5441
5442   return el_act_dir2img(element, ACTION_DEFAULT, direction);
5443 }
5444
5445 int el2baseimg(int element)
5446 {
5447   return element_info[element].graphic[ACTION_DEFAULT];
5448 }
5449
5450 int el2img(int element)
5451 {
5452   element = GFX_ELEMENT(element);
5453
5454   return element_info[element].graphic[ACTION_DEFAULT];
5455 }
5456
5457 int el2edimg(int element)
5458 {
5459   element = GFX_ELEMENT(element);
5460
5461   return element_info[element].special_graphic[GFX_SPECIAL_ARG_EDITOR];
5462 }
5463
5464 int el2preimg(int element)
5465 {
5466   element = GFX_ELEMENT(element);
5467
5468   return element_info[element].special_graphic[GFX_SPECIAL_ARG_PREVIEW];
5469 }
5470
5471 int getGameFrameDelay_EM(int native_em_game_frame_delay)
5472 {
5473   int game_frame_delay_value;
5474
5475   game_frame_delay_value =
5476     (tape.playing && tape.fast_forward ? FfwdFrameDelay :
5477      GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
5478      GameFrameDelay);
5479
5480   if (tape.playing && tape.warp_forward && !tape.pausing)
5481     game_frame_delay_value = 0;
5482
5483   return game_frame_delay_value;
5484 }
5485
5486 unsigned int InitRND(long seed)
5487 {
5488   if (level.game_engine_type == GAME_ENGINE_TYPE_EM)
5489     return InitEngineRND_EM(seed);
5490   else
5491     return InitEngineRND(seed);
5492 }
5493
5494 #define DEBUG_EM_GFX    0
5495
5496 void InitGraphicInfo_EM(void)
5497 {
5498   struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
5499   struct Mapping_EM_to_RND_player player_mapping[2][SPR_MAX];
5500   int i, j, p;
5501
5502 #if DEBUG_EM_GFX
5503   if (graphic_info_em_object[0][0].bitmap == NULL)
5504   {
5505     /* EM graphics not yet initialized in em_open_all() */
5506
5507     return;
5508   }
5509 #endif
5510
5511   /* always start with reliable default values */
5512   for (i = 0; i < TILE_MAX; i++)
5513   {
5514     object_mapping[i].element_rnd = EL_UNKNOWN;
5515     object_mapping[i].is_backside = FALSE;
5516     object_mapping[i].action = ACTION_DEFAULT;
5517     object_mapping[i].direction = MV_NO_MOVING;
5518   }
5519
5520   /* always start with reliable default values */
5521   for (p = 0; p < 2; p++)
5522   {
5523     for (i = 0; i < SPR_MAX; i++)
5524     {
5525       player_mapping[p][i].element_rnd = EL_UNKNOWN;
5526       player_mapping[p][i].action = ACTION_DEFAULT;
5527       player_mapping[p][i].direction = MV_NO_MOVING;
5528     }
5529   }
5530
5531   for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
5532   {
5533     int e = em_object_mapping_list[i].element_em;
5534
5535     object_mapping[e].element_rnd = em_object_mapping_list[i].element_rnd;
5536     object_mapping[e].is_backside = em_object_mapping_list[i].is_backside;
5537
5538     if (em_object_mapping_list[i].action != -1)
5539       object_mapping[e].action = em_object_mapping_list[i].action;
5540
5541     if (em_object_mapping_list[i].direction != -1)
5542       object_mapping[e].direction = (1 << em_object_mapping_list[i].direction);
5543   }
5544
5545   for (i = 0; em_player_mapping_list[i].action_em != -1; i++)
5546   {
5547     int a = em_player_mapping_list[i].action_em;
5548     int p = em_player_mapping_list[i].player_nr;
5549
5550     player_mapping[p][a].element_rnd = em_player_mapping_list[i].element_rnd;
5551
5552     if (em_player_mapping_list[i].action != -1)
5553       player_mapping[p][a].action = em_player_mapping_list[i].action;
5554
5555     if (em_player_mapping_list[i].direction != -1)
5556       player_mapping[p][a].direction =
5557         (1 << em_player_mapping_list[i].direction);
5558   }
5559
5560   for (i = 0; i < TILE_MAX; i++)
5561   {
5562     int element = object_mapping[i].element_rnd;
5563     int action = object_mapping[i].action;
5564     int direction = object_mapping[i].direction;
5565     boolean is_backside = object_mapping[i].is_backside;
5566     boolean action_removing = (action == ACTION_DIGGING ||
5567                                action == ACTION_SNAPPING ||
5568                                action == ACTION_COLLECTING);
5569     boolean action_exploding = ((action == ACTION_EXPLODING ||
5570                                  action == ACTION_SMASHED_BY_ROCK ||
5571                                  action == ACTION_SMASHED_BY_SPRING) &&
5572                                 element != EL_DIAMOND);
5573     boolean action_active = (action == ACTION_ACTIVE);
5574     boolean action_other = (action == ACTION_OTHER);
5575
5576     for (j = 0; j < 8; j++)
5577     {
5578       int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY :
5579                                j > 5 && i == Yacid_splash_wB ? EL_EMPTY :
5580                                j < 7 ? element :
5581                                i == Xdrip_stretch ? element :
5582                                i == Xdrip_stretchB ? element :
5583                                i == Ydrip_s1 ? element :
5584                                i == Ydrip_s1B ? element :
5585                                i == Xball_1B ? element :
5586                                i == Xball_2 ? element :
5587                                i == Xball_2B ? element :
5588                                i == Yball_eat ? element :
5589                                i == Ykey_1_eat ? element :
5590                                i == Ykey_2_eat ? element :
5591                                i == Ykey_3_eat ? element :
5592                                i == Ykey_4_eat ? element :
5593                                i == Ykey_5_eat ? element :
5594                                i == Ykey_6_eat ? element :
5595                                i == Ykey_7_eat ? element :
5596                                i == Ykey_8_eat ? element :
5597                                i == Ylenses_eat ? element :
5598                                i == Ymagnify_eat ? element :
5599                                i == Ygrass_eat ? element :
5600                                i == Ydirt_eat ? element :
5601                                i == Yspring_kill_e ? EL_SPRING :
5602                                i == Yspring_kill_w ? EL_SPRING :
5603                                i == Yemerald_stone ? EL_EMERALD :
5604                                i == Ydiamond_stone ? EL_ROCK :
5605                                i == Xsand_stonein_4 ? EL_EMPTY :
5606                                i == Xsand_stoneout_2 ? EL_ROCK :
5607                                is_backside ? EL_EMPTY :
5608                                action_removing ? EL_EMPTY :
5609                                element);
5610       int effective_action = (j < 7 ? action :
5611                               i == Xdrip_stretch ? action :
5612                               i == Xdrip_stretchB ? action :
5613                               i == Ydrip_s1 ? action :
5614                               i == Ydrip_s1B ? action :
5615                               i == Xball_1B ? action :
5616                               i == Xball_2 ? action :
5617                               i == Xball_2B ? action :
5618                               i == Yball_eat ? action :
5619                               i == Ykey_1_eat ? action :
5620                               i == Ykey_2_eat ? action :
5621                               i == Ykey_3_eat ? action :
5622                               i == Ykey_4_eat ? action :
5623                               i == Ykey_5_eat ? action :
5624                               i == Ykey_6_eat ? action :
5625                               i == Ykey_7_eat ? action :
5626                               i == Ykey_8_eat ? action :
5627                               i == Ylenses_eat ? action :
5628                               i == Ymagnify_eat ? action :
5629                               i == Ygrass_eat ? action :
5630                               i == Ydirt_eat ? action :
5631                               i == Xsand_stonein_1 ? action :
5632                               i == Xsand_stonein_2 ? action :
5633                               i == Xsand_stonein_3 ? action :
5634                               i == Xsand_stonein_4 ? action :
5635                               i == Xsand_stoneout_1 ? action :
5636                               i == Xsand_stoneout_2 ? action :
5637                               i == Xboom_android ? ACTION_EXPLODING :
5638                               action_exploding ? ACTION_EXPLODING :
5639                               action_active ? action :
5640                               action_other ? action :
5641                               ACTION_DEFAULT);
5642       int graphic = (el_act_dir2img(effective_element, effective_action,
5643                                     direction));
5644       int crumbled = (el_act_dir2crm(effective_element, effective_action,
5645                                      direction));
5646       int base_graphic = el_act2img(effective_element, ACTION_DEFAULT);
5647       int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT);
5648       boolean has_crumbled_graphics = (base_crumbled != base_graphic);
5649       struct GraphicInfo *g = &graphic_info[graphic];
5650       struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
5651       Bitmap *src_bitmap;
5652       int src_x, src_y;
5653       /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */
5654       boolean special_animation = (action != ACTION_DEFAULT &&
5655                                    g->anim_frames == 3 &&
5656                                    g->anim_delay == 2 &&
5657                                    g->anim_mode & ANIM_LINEAR);
5658       int sync_frame = (i == Xdrip_stretch ? 7 :
5659                         i == Xdrip_stretchB ? 7 :
5660                         i == Ydrip_s2 ? j + 8 :
5661                         i == Ydrip_s2B ? j + 8 :
5662                         i == Xacid_1 ? 0 :
5663                         i == Xacid_2 ? 10 :
5664                         i == Xacid_3 ? 20 :
5665                         i == Xacid_4 ? 30 :
5666                         i == Xacid_5 ? 40 :
5667                         i == Xacid_6 ? 50 :
5668                         i == Xacid_7 ? 60 :
5669                         i == Xacid_8 ? 70 :
5670                         i == Xfake_acid_1 ? 0 :
5671                         i == Xfake_acid_2 ? 10 :
5672                         i == Xfake_acid_3 ? 20 :
5673                         i == Xfake_acid_4 ? 30 :
5674                         i == Xfake_acid_5 ? 40 :
5675                         i == Xfake_acid_6 ? 50 :
5676                         i == Xfake_acid_7 ? 60 :
5677                         i == Xfake_acid_8 ? 70 :
5678                         i == Xball_2 ? 7 :
5679                         i == Xball_2B ? j + 8 :
5680                         i == Yball_eat ? j + 1 :
5681                         i == Ykey_1_eat ? j + 1 :
5682                         i == Ykey_2_eat ? j + 1 :
5683                         i == Ykey_3_eat ? j + 1 :
5684                         i == Ykey_4_eat ? j + 1 :
5685                         i == Ykey_5_eat ? j + 1 :
5686                         i == Ykey_6_eat ? j + 1 :
5687                         i == Ykey_7_eat ? j + 1 :
5688                         i == Ykey_8_eat ? j + 1 :
5689                         i == Ylenses_eat ? j + 1 :
5690                         i == Ymagnify_eat ? j + 1 :
5691                         i == Ygrass_eat ? j + 1 :
5692                         i == Ydirt_eat ? j + 1 :
5693                         i == Xamoeba_1 ? 0 :
5694                         i == Xamoeba_2 ? 1 :
5695                         i == Xamoeba_3 ? 2 :
5696                         i == Xamoeba_4 ? 3 :
5697                         i == Xamoeba_5 ? 0 :
5698                         i == Xamoeba_6 ? 1 :
5699                         i == Xamoeba_7 ? 2 :
5700                         i == Xamoeba_8 ? 3 :
5701                         i == Xexit_2 ? j + 8 :
5702                         i == Xexit_3 ? j + 16 :
5703                         i == Xdynamite_1 ? 0 :
5704                         i == Xdynamite_2 ? 20 :
5705                         i == Xdynamite_3 ? 40 :
5706                         i == Xdynamite_4 ? 60 :
5707                         i == Xsand_stonein_1 ? j + 1 :
5708                         i == Xsand_stonein_2 ? j + 9 :
5709                         i == Xsand_stonein_3 ? j + 17 :
5710                         i == Xsand_stonein_4 ? j + 25 :
5711                         i == Xsand_stoneout_1 && j == 0 ? 0 :
5712                         i == Xsand_stoneout_1 && j == 1 ? 0 :
5713                         i == Xsand_stoneout_1 && j == 2 ? 1 :
5714                         i == Xsand_stoneout_1 && j == 3 ? 2 :
5715                         i == Xsand_stoneout_1 && j == 4 ? 2 :
5716                         i == Xsand_stoneout_1 && j == 5 ? 3 :
5717                         i == Xsand_stoneout_1 && j == 6 ? 4 :
5718                         i == Xsand_stoneout_1 && j == 7 ? 4 :
5719                         i == Xsand_stoneout_2 && j == 0 ? 5 :
5720                         i == Xsand_stoneout_2 && j == 1 ? 6 :
5721                         i == Xsand_stoneout_2 && j == 2 ? 7 :
5722                         i == Xsand_stoneout_2 && j == 3 ? 8 :
5723                         i == Xsand_stoneout_2 && j == 4 ? 9 :
5724                         i == Xsand_stoneout_2 && j == 5 ? 11 :
5725                         i == Xsand_stoneout_2 && j == 6 ? 13 :
5726                         i == Xsand_stoneout_2 && j == 7 ? 15 :
5727                         i == Xboom_bug && j == 1 ? 2 :
5728                         i == Xboom_bug && j == 2 ? 2 :
5729                         i == Xboom_bug && j == 3 ? 4 :
5730                         i == Xboom_bug && j == 4 ? 4 :
5731                         i == Xboom_bug && j == 5 ? 2 :
5732                         i == Xboom_bug && j == 6 ? 2 :
5733                         i == Xboom_bug && j == 7 ? 0 :
5734                         i == Xboom_bomb && j == 1 ? 2 :
5735                         i == Xboom_bomb && j == 2 ? 2 :
5736                         i == Xboom_bomb && j == 3 ? 4 :
5737                         i == Xboom_bomb && j == 4 ? 4 :
5738                         i == Xboom_bomb && j == 5 ? 2 :
5739                         i == Xboom_bomb && j == 6 ? 2 :
5740                         i == Xboom_bomb && j == 7 ? 0 :
5741                         i == Xboom_android && j == 7 ? 6 :
5742                         i == Xboom_1 && j == 1 ? 2 :
5743                         i == Xboom_1 && j == 2 ? 2 :
5744                         i == Xboom_1 && j == 3 ? 4 :
5745                         i == Xboom_1 && j == 4 ? 4 :
5746                         i == Xboom_1 && j == 5 ? 6 :
5747                         i == Xboom_1 && j == 6 ? 6 :
5748                         i == Xboom_1 && j == 7 ? 8 :
5749                         i == Xboom_2 && j == 0 ? 8 :
5750                         i == Xboom_2 && j == 1 ? 8 :
5751                         i == Xboom_2 && j == 2 ? 10 :
5752                         i == Xboom_2 && j == 3 ? 10 :
5753                         i == Xboom_2 && j == 4 ? 10 :
5754                         i == Xboom_2 && j == 5 ? 12 :
5755                         i == Xboom_2 && j == 6 ? 12 :
5756                         i == Xboom_2 && j == 7 ? 12 :
5757                         special_animation && j == 4 ? 3 :
5758                         effective_action != action ? 0 :
5759                         j);
5760
5761 #if DEBUG_EM_GFX
5762       Bitmap *debug_bitmap = g_em->bitmap;
5763       int debug_src_x = g_em->src_x;
5764       int debug_src_y = g_em->src_y;
5765 #endif
5766
5767       int frame = getAnimationFrame(g->anim_frames,
5768                                     g->anim_delay,
5769                                     g->anim_mode,
5770                                     g->anim_start_frame,
5771                                     sync_frame);
5772
5773       getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y,
5774                           g->double_movement && is_backside);
5775
5776       g_em->bitmap = src_bitmap;
5777       g_em->src_x = src_x;
5778       g_em->src_y = src_y;
5779       g_em->src_offset_x = 0;
5780       g_em->src_offset_y = 0;
5781       g_em->dst_offset_x = 0;
5782       g_em->dst_offset_y = 0;
5783       g_em->width  = TILEX;
5784       g_em->height = TILEY;
5785
5786       g_em->crumbled_bitmap = NULL;
5787       g_em->crumbled_src_x = 0;
5788       g_em->crumbled_src_y = 0;
5789       g_em->crumbled_border_size = 0;
5790
5791       g_em->has_crumbled_graphics = FALSE;
5792       g_em->preserve_background = FALSE;
5793
5794 #if 0
5795       if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE)
5796         printf("::: empty crumbled: %d [%s], %d, %d\n",
5797                effective_element, element_info[effective_element].token_name,
5798                effective_action, direction);
5799 #endif
5800
5801       /* if element can be crumbled, but certain action graphics are just empty
5802          space (like snapping sand with the original R'n'D graphics), do not
5803          treat these empty space graphics as crumbled graphics in EMC engine */
5804       if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE)
5805       {
5806         getGraphicSource(crumbled, frame, &src_bitmap, &src_x, &src_y);
5807
5808         g_em->has_crumbled_graphics = TRUE;
5809         g_em->crumbled_bitmap = src_bitmap;
5810         g_em->crumbled_src_x = src_x;
5811         g_em->crumbled_src_y = src_y;
5812         g_em->crumbled_border_size = graphic_info[crumbled].border_size;
5813       }
5814
5815       if (!g->double_movement && (effective_action == ACTION_FALLING ||
5816                                   effective_action == ACTION_MOVING ||
5817                                   effective_action == ACTION_PUSHING))
5818       {
5819         int move_dir =
5820           (effective_action == ACTION_FALLING ? MV_DOWN : direction);
5821         int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0);
5822         int dy = (move_dir == MV_UP   ? -1 : move_dir == MV_DOWN  ? 1 : 0);
5823         int num_steps = (i == Ydrip_s1 ||
5824                          i == Ydrip_s1B ||
5825                          i == Ydrip_s2 ||
5826                          i == Ydrip_s2B ? 16 : 8);
5827         int cx = ABS(dx) * (TILEX / num_steps);
5828         int cy = ABS(dy) * (TILEY / num_steps);
5829         int step_frame = (i == Ydrip_s2 ||
5830                           i == Ydrip_s2B ? j + 8 : j) + 1;
5831         int step = (is_backside ? step_frame : num_steps - step_frame);
5832
5833         if (is_backside)        /* tile where movement starts */
5834         {
5835           if (dx < 0 || dy < 0)
5836           {
5837             g_em->src_offset_x = cx * step;
5838             g_em->src_offset_y = cy * step;
5839           }
5840           else
5841           {
5842             g_em->dst_offset_x = cx * step;
5843             g_em->dst_offset_y = cy * step;
5844           }
5845         }
5846         else                    /* tile where movement ends */
5847         {
5848           if (dx < 0 || dy < 0)
5849           {
5850             g_em->dst_offset_x = cx * step;
5851             g_em->dst_offset_y = cy * step;
5852           }
5853           else
5854           {
5855             g_em->src_offset_x = cx * step;
5856             g_em->src_offset_y = cy * step;
5857           }
5858         }
5859
5860         g_em->width  = TILEX - cx * step;
5861         g_em->height = TILEY - cy * step;
5862       }
5863
5864       /* create unique graphic identifier to decide if tile must be redrawn */
5865       /* bit 31 - 16 (16 bit): EM style element
5866          bit 15 - 12 ( 4 bit): EM style frame
5867          bit 11 -  6 ( 6 bit): graphic width
5868          bit  5 -  0 ( 6 bit): graphic height */
5869       g_em->unique_identifier =
5870         (i << 16) | (j << 12) | (g_em->width << 6) | g_em->height;
5871
5872 #if DEBUG_EM_GFX
5873       if (g_em->bitmap != debug_bitmap ||
5874           g_em->src_x != debug_src_x ||
5875           g_em->src_y != debug_src_y ||
5876           g_em->src_offset_x != 0 ||
5877           g_em->src_offset_y != 0 ||
5878           g_em->dst_offset_x != 0 ||
5879           g_em->dst_offset_y != 0 ||
5880           g_em->width != TILEX ||
5881           g_em->height != TILEY)
5882       {
5883         static int last_i = -1;
5884
5885         if (i != last_i)
5886         {
5887           printf("\n");
5888           last_i = i;
5889         }
5890
5891         printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
5892                i, element, element_info[element].token_name,
5893                element_action_info[effective_action].suffix, direction);
5894
5895         if (element != effective_element)
5896           printf(" [%d ('%s')]",
5897                  effective_element,
5898                  element_info[effective_element].token_name);
5899
5900         printf("\n");
5901
5902         if (g_em->bitmap != debug_bitmap)
5903           printf("    %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
5904                  j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
5905
5906         if (g_em->src_x != debug_src_x ||
5907             g_em->src_y != debug_src_y)
5908           printf("    frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
5909                  j, (is_backside ? 'B' : 'F'),
5910                  g_em->src_x, g_em->src_y,
5911                  g_em->src_x / 32, g_em->src_y / 32,
5912                  debug_src_x, debug_src_y,
5913                  debug_src_x / 32, debug_src_y / 32);
5914
5915         if (g_em->src_offset_x != 0 ||
5916             g_em->src_offset_y != 0 ||
5917             g_em->dst_offset_x != 0 ||
5918             g_em->dst_offset_y != 0)
5919           printf("    %d (%d): offsets %d,%d and %d,%d should be all 0\n",
5920                  j, is_backside,
5921                  g_em->src_offset_x, g_em->src_offset_y,
5922                  g_em->dst_offset_x, g_em->dst_offset_y);
5923
5924         if (g_em->width != TILEX ||
5925             g_em->height != TILEY)
5926           printf("    %d (%d): size %d,%d should be %d,%d\n",
5927                  j, is_backside,
5928                  g_em->width, g_em->height, TILEX, TILEY);
5929       }
5930 #endif
5931
5932     }
5933   }
5934
5935   for (i = 0; i < TILE_MAX; i++)
5936   {
5937     for (j = 0; j < 8; j++)
5938     {
5939       int element = object_mapping[i].element_rnd;
5940       int action = object_mapping[i].action;
5941
5942       if (action == ACTION_SMASHED_BY_ROCK &&
5943           element_info[element].graphic[action] ==
5944           element_info[element].graphic[ACTION_DEFAULT])
5945       {
5946         /* no separate animation for "smashed by rock" -- use rock instead */
5947         struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
5948         struct GraphicInfo_EM *g_xx = &graphic_info_em_object[Ystone_s][7 - j];
5949
5950         g_em->bitmap            = g_xx->bitmap;
5951         g_em->src_x             = g_xx->src_x;
5952         g_em->src_y             = g_xx->src_y;
5953         g_em->src_offset_x      = g_xx->src_offset_x;
5954         g_em->src_offset_y      = g_xx->src_offset_y;
5955         g_em->dst_offset_x      = g_xx->dst_offset_x;
5956         g_em->dst_offset_y      = g_xx->dst_offset_y;
5957         g_em->width             = g_xx->width;
5958         g_em->height            = g_xx->height;
5959
5960         g_em->preserve_background = TRUE;
5961       }
5962     }
5963   }
5964
5965   for (p = 0; p < 2; p++)
5966   {
5967     for (i = 0; i < SPR_MAX; i++)
5968     {
5969       int element = player_mapping[p][i].element_rnd;
5970       int action = player_mapping[p][i].action;
5971       int direction = player_mapping[p][i].direction;
5972
5973       for (j = 0; j < 8; j++)
5974       {
5975         int effective_element = element;
5976         int effective_action = action;
5977         int graphic = (direction == MV_NO_MOVING ?
5978                        el_act2img(effective_element, effective_action) :
5979                        el_act_dir2img(effective_element, effective_action,
5980                                       direction));
5981         struct GraphicInfo *g = &graphic_info[graphic];
5982         struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
5983         Bitmap *src_bitmap;
5984         int src_x, src_y;
5985         int sync_frame = j;
5986
5987 #if DEBUG_EM_GFX
5988         Bitmap *debug_bitmap = g_em->bitmap;
5989         int debug_src_x = g_em->src_x;
5990         int debug_src_y = g_em->src_y;
5991 #endif
5992
5993         int frame = getAnimationFrame(g->anim_frames,
5994                                       g->anim_delay,
5995                                       g->anim_mode,
5996                                       g->anim_start_frame,
5997                                       sync_frame);
5998
5999         getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x,&src_y, FALSE);
6000
6001         g_em->bitmap = src_bitmap;
6002         g_em->src_x = src_x;
6003         g_em->src_y = src_y;
6004         g_em->src_offset_x = 0;
6005         g_em->src_offset_y = 0;
6006         g_em->dst_offset_x = 0;
6007         g_em->dst_offset_y = 0;
6008         g_em->width  = TILEX;
6009         g_em->height = TILEY;
6010
6011 #if DEBUG_EM_GFX
6012         if (g_em->bitmap != debug_bitmap ||
6013             g_em->src_x != debug_src_x ||
6014             g_em->src_y != debug_src_y)
6015         {
6016           static int last_i = -1;
6017
6018           if (i != last_i)
6019           {
6020             printf("\n");
6021             last_i = i;
6022           }
6023
6024           printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
6025                  p, i, element, element_info[element].token_name,
6026                  element_action_info[effective_action].suffix, direction);
6027
6028           if (element != effective_element)
6029             printf(" [%d ('%s')]",
6030                    effective_element,
6031                    element_info[effective_element].token_name);
6032
6033           printf("\n");
6034
6035           if (g_em->bitmap != debug_bitmap)
6036             printf("    %d: different bitmap! (0x%08x != 0x%08x)\n",
6037                    j, (int)(g_em->bitmap), (int)(debug_bitmap));
6038
6039           if (g_em->src_x != debug_src_x ||
6040               g_em->src_y != debug_src_y)
6041             printf("    frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
6042                    j,
6043                    g_em->src_x, g_em->src_y,
6044                    g_em->src_x / 32, g_em->src_y / 32,
6045                    debug_src_x, debug_src_y,
6046                    debug_src_x / 32, debug_src_y / 32);
6047         }
6048 #endif
6049
6050       }
6051     }
6052   }
6053
6054 #if DEBUG_EM_GFX
6055   exit(0);
6056 #endif
6057 }