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