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