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