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