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