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