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