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